mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
shareable: Add Shader
This commit is contained in:
parent
1c980a16f5
commit
9c637c65be
@ -150,7 +150,7 @@ func (m *Mipmap) DrawImage(src *Mipmap, bounds image.Rectangle, geom GeoM, color
|
|||||||
if level == 0 {
|
if level == 0 {
|
||||||
vs := quadVertices(bounds.Min.X, bounds.Min.Y, bounds.Max.X, bounds.Max.Y, a, b, c, d, tx, ty, cr, cg, cb, ca, screen)
|
vs := quadVertices(bounds.Min.X, bounds.Min.Y, bounds.Max.X, bounds.Max.Y, a, b, c, d, tx, ty, cr, cg, cb, ca, screen)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
m.orig.DrawTriangles(src.orig, vs, is, colorm, mode, filter, driver.AddressClampToZero)
|
m.orig.DrawTriangles(src.orig, vs, is, colorm, mode, filter, driver.AddressClampToZero, nil, nil)
|
||||||
} else if buf := src.level(bounds, level); buf != nil {
|
} else if buf := src.level(bounds, level); buf != nil {
|
||||||
w, h := sizeForLevel(bounds.Dx(), bounds.Dy(), level)
|
w, h := sizeForLevel(bounds.Dx(), bounds.Dy(), level)
|
||||||
s := pow2(level)
|
s := pow2(level)
|
||||||
@ -160,7 +160,7 @@ func (m *Mipmap) DrawImage(src *Mipmap, bounds image.Rectangle, geom GeoM, color
|
|||||||
d *= s
|
d *= s
|
||||||
vs := quadVertices(0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca, false)
|
vs := quadVertices(0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca, false)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
m.orig.DrawTriangles(buf, vs, is, colorm, mode, filter, driver.AddressClampToZero)
|
m.orig.DrawTriangles(buf, vs, is, colorm, mode, filter, driver.AddressClampToZero, nil, nil)
|
||||||
}
|
}
|
||||||
m.disposeMipmaps()
|
m.disposeMipmaps()
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ func (m *Mipmap) DrawTriangles(src *Mipmap, vertices []float32, indices []uint16
|
|||||||
vertices[i*n+11] *= ca
|
vertices[i*n+11] *= ca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.orig.DrawTriangles(src.orig, vertices, indices, colorm, mode, filter, address)
|
m.orig.DrawTriangles(src.orig, vertices, indices, colorm, mode, filter, address, nil, nil)
|
||||||
m.disposeMipmaps()
|
m.disposeMipmaps()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ func (m *Mipmap) level(r image.Rectangle, level int) *shareable.Image {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
s := shareable.NewImage(w2, h2, m.volatile)
|
s := shareable.NewImage(w2, h2, m.volatile)
|
||||||
s.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, filter, driver.AddressClampToZero)
|
s.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, filter, driver.AddressClampToZero, nil, nil)
|
||||||
imgs[level] = s
|
imgs[level] = s
|
||||||
|
|
||||||
return imgs[level]
|
return imgs[level]
|
||||||
|
@ -282,7 +282,7 @@ func (i *Image) region() (x, y, width, height int) {
|
|||||||
// 9: Color G
|
// 9: Color G
|
||||||
// 10: Color B
|
// 10: Color B
|
||||||
// 11: Color Y
|
// 11: Color Y
|
||||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address) {
|
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, shader *Shader, uniforms []interface{}) {
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
// Do not use defer for performance.
|
// Do not use defer for performance.
|
||||||
|
|
||||||
@ -316,7 +316,36 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
|||||||
vertices[i*graphics.VertexFloatNum+7] += oyf
|
vertices[i*graphics.VertexFloatNum+7] += oyf
|
||||||
}
|
}
|
||||||
|
|
||||||
i.backend.restorable.DrawTriangles(img.backend.restorable, vertices, indices, colorm, mode, filter, address, nil, nil)
|
var s *restorable.Shader
|
||||||
|
if shader != nil {
|
||||||
|
s = shader.shader
|
||||||
|
}
|
||||||
|
|
||||||
|
firstImage := true
|
||||||
|
us := make([]interface{}, len(uniforms))
|
||||||
|
for i := 0; i < len(uniforms); i++ {
|
||||||
|
switch v := us[i].(type) {
|
||||||
|
case *Image:
|
||||||
|
us[i] = v.backend.restorable
|
||||||
|
if !firstImage {
|
||||||
|
i++
|
||||||
|
pos := us[i].([]float32)
|
||||||
|
pos[0] += oxf
|
||||||
|
pos[1] += oyf
|
||||||
|
i++
|
||||||
|
region := us[i].([]float32)
|
||||||
|
region[0] += oxf
|
||||||
|
region[1] += oyf
|
||||||
|
region[2] += oxf
|
||||||
|
region[3] += oyf
|
||||||
|
}
|
||||||
|
firstImage = false
|
||||||
|
default:
|
||||||
|
us[i] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i.backend.restorable.DrawTriangles(img.backend.restorable, vertices, indices, colorm, mode, filter, address, s, us)
|
||||||
|
|
||||||
i.nonUpdatedCount = 0
|
i.nonUpdatedCount = 0
|
||||||
delete(imagesToMakeShared, i)
|
delete(imagesToMakeShared, i)
|
||||||
|
@ -89,7 +89,7 @@ func TestEnsureNotShared(t *testing.T) {
|
|||||||
// img4.ensureNotShared() should be called.
|
// img4.ensureNotShared() should be called.
|
||||||
vs := quadVertices(size/2, size/2, size/4, size/4, 1)
|
vs := quadVertices(size/2, size/2, size/4, size/4, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, nil, nil)
|
||||||
want := false
|
want := false
|
||||||
if got := img4.IsSharedForTesting(); got != want {
|
if got := img4.IsSharedForTesting(); got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
@ -119,7 +119,7 @@ func TestEnsureNotShared(t *testing.T) {
|
|||||||
|
|
||||||
// Check further drawing doesn't cause panic.
|
// Check further drawing doesn't cause panic.
|
||||||
// This bug was fixed by 03dcd948.
|
// This bug was fixed by 03dcd948.
|
||||||
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReshared(t *testing.T) {
|
func TestReshared(t *testing.T) {
|
||||||
@ -159,7 +159,7 @@ func TestReshared(t *testing.T) {
|
|||||||
// Use img1 as a render target.
|
// Use img1 as a render target.
|
||||||
vs := quadVertices(size, size, 0, 0, 1)
|
vs := quadVertices(size, size, 0, 0, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img1.DrawTriangles(img2, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
img1.DrawTriangles(img2, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, nil, nil)
|
||||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -169,7 +169,7 @@ func TestReshared(t *testing.T) {
|
|||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, nil, nil)
|
||||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ func TestReshared(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, nil, nil)
|
||||||
if got, want := img1.IsSharedForTesting(), true; got != want {
|
if got, want := img1.IsSharedForTesting(), true; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -224,7 +224,7 @@ func TestReshared(t *testing.T) {
|
|||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img0.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
img0.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, nil, nil)
|
||||||
if got, want := img3.IsSharedForTesting(), false; got != want {
|
if got, want := img3.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -319,7 +319,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w, h, 0, 0, 1)
|
vs := quadVertices(w, h, 0, 0, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, nil, nil)
|
||||||
dst.ReplacePixels(pix)
|
dst.ReplacePixels(pix)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, w, h)
|
pix, err := dst.Pixels(0, 0, w, h)
|
||||||
@ -361,7 +361,7 @@ func TestSmallImages(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w, h, 0, 0, 1)
|
vs := quadVertices(w, h, 0, 0, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressClampToZero)
|
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressClampToZero, nil, nil)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, w, h)
|
pix, err := dst.Pixels(0, 0, w, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -403,7 +403,7 @@ func TestLongImages(t *testing.T) {
|
|||||||
const scale = 120
|
const scale = 120
|
||||||
vs := quadVertices(w, h, 0, 0, scale)
|
vs := quadVertices(w, h, 0, 0, scale)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressClampToZero)
|
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressClampToZero, nil, nil)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, dstW, dstH)
|
pix, err := dst.Pixels(0, 0, dstW, dstH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
52
internal/shareable/shader.go
Normal file
52
internal/shareable/shader.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright 2020 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package shareable
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/restorable"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/shaderir"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Shader struct {
|
||||||
|
shader *restorable.Shader
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShader(program *shaderir.Program) *Shader {
|
||||||
|
s := &Shader{
|
||||||
|
shader: restorable.NewShader(program),
|
||||||
|
}
|
||||||
|
runtime.SetFinalizer(s, (*Shader).MarkDisposed)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkDisposed marks the shader as disposed. The actual operation is deferred.
|
||||||
|
// MarkDisposed can be called from finalizers.
|
||||||
|
//
|
||||||
|
// A function from finalizer must not be blocked, but disposing operation can be blocked.
|
||||||
|
// Defer this operation until it becomes safe. (#913)
|
||||||
|
func (s *Shader) MarkDisposed() {
|
||||||
|
deferredM.Lock()
|
||||||
|
deferred = append(deferred, func() {
|
||||||
|
s.dispose()
|
||||||
|
})
|
||||||
|
deferredM.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Shader) dispose() {
|
||||||
|
s.shader.Dispose()
|
||||||
|
s.shader = nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user