mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 11:18:54 +01:00
parent
b03c02dd28
commit
bc4e35a6c5
@ -22,10 +22,40 @@ import (
|
||||
|
||||
"github.com/hajimehoshi/ebiten/internal/affine"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/internal/hooks"
|
||||
"github.com/hajimehoshi/ebiten/internal/packing"
|
||||
"github.com/hajimehoshi/ebiten/internal/restorable"
|
||||
)
|
||||
|
||||
func init() {
|
||||
hooks.AppendHookOnBeforeUpdate(func() error {
|
||||
makeImagesShared()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// MaxCountForShare represents the time duration when the image can become shared.
|
||||
//
|
||||
// This value is expoted for testing.
|
||||
const MaxCountForShare = 10
|
||||
|
||||
func makeImagesShared() {
|
||||
backendsM.Lock()
|
||||
defer backendsM.Unlock()
|
||||
|
||||
for i := range imagesToMakeShared {
|
||||
i.nonUpdatedCount++
|
||||
if i.nonUpdatedCount >= MaxCountForShare {
|
||||
i.makeShared()
|
||||
}
|
||||
delete(imagesToMakeShared, i)
|
||||
}
|
||||
}
|
||||
|
||||
func MakeImagesSharedForTesting() {
|
||||
makeImagesShared()
|
||||
}
|
||||
|
||||
const (
|
||||
initSize = 1024
|
||||
maxSize = 4096
|
||||
@ -84,6 +114,8 @@ var (
|
||||
|
||||
// theBackends is a set of actually shared images.
|
||||
theBackends = []*backend{}
|
||||
|
||||
imagesToMakeShared = map[*Image]struct{}{}
|
||||
)
|
||||
|
||||
type Image struct {
|
||||
@ -93,8 +125,17 @@ type Image struct {
|
||||
|
||||
backend *backend
|
||||
|
||||
node *packing.Node
|
||||
countForShare int
|
||||
node *packing.Node
|
||||
|
||||
// nonUpdatedCount represents how long the image is kept not modified with DrawTriangles.
|
||||
// In the current implementation, if an image is being modified by DrawTriangles, the image is separated from
|
||||
// a shared (restorable) image by ensureNotShared.
|
||||
//
|
||||
// nonUpdatedCount is increased every frame if the image is not modified, or set to 0 if the image id
|
||||
// modified.
|
||||
//
|
||||
// ReplacePixels doesn't affect this value since ReplacePixels can be done on shared images.
|
||||
nonUpdatedCount int
|
||||
|
||||
neverShared bool
|
||||
}
|
||||
@ -140,7 +181,7 @@ func (i *Image) ensureNotShared() {
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Image) forceShared() {
|
||||
func (i *Image) makeShared() {
|
||||
if i.backend == nil {
|
||||
i.allocate(true)
|
||||
return
|
||||
@ -151,7 +192,7 @@ func (i *Image) forceShared() {
|
||||
}
|
||||
|
||||
if !i.shareable() {
|
||||
panic("shareable: forceShared cannot be called on a non-shareable image")
|
||||
panic("shareable: makeShared cannot be called on a non-shareable image")
|
||||
}
|
||||
|
||||
newI := NewImage(i.width, i.height)
|
||||
@ -167,7 +208,7 @@ func (i *Image) forceShared() {
|
||||
}
|
||||
newI.replacePixels(pixels)
|
||||
newI.moveTo(i)
|
||||
i.countForShare = 0
|
||||
i.nonUpdatedCount = 0
|
||||
}
|
||||
|
||||
func (i *Image) region() (x, y, width, height int) {
|
||||
@ -207,8 +248,6 @@ func (i *Image) PutVertex(dest []float32, dx, dy, sx, sy float32, bx0, by0, bx1,
|
||||
i.backend.restorable.PutVertex(dest, dx, dy, sx+oxf, sy+oyf, bx0+oxf, by0+oyf, bx1+oxf, by1+oyf, cr, cg, cb, ca)
|
||||
}
|
||||
|
||||
const MaxCountForShare = 10
|
||||
|
||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode graphics.CompositeMode, filter graphics.Filter, address graphics.Address) {
|
||||
backendsM.Lock()
|
||||
defer backendsM.Unlock()
|
||||
@ -233,17 +272,12 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
||||
|
||||
i.backend.restorable.DrawTriangles(img.backend.restorable, vertices, indices, colorm, mode, filter, address)
|
||||
|
||||
i.countForShare = 0
|
||||
i.nonUpdatedCount = 0
|
||||
delete(imagesToMakeShared, i)
|
||||
|
||||
// TODO: Reusing shared images is temporarily suspended for performance. See #661.
|
||||
//
|
||||
// if !img.isShared() && img.shareable() {
|
||||
// img.countForShare++
|
||||
// if img.countForShare >= MaxCountForShare {
|
||||
// img.forceShared()
|
||||
// img.countForShare = 0
|
||||
// }
|
||||
// }
|
||||
if !img.isShared() && img.shareable() {
|
||||
imagesToMakeShared[img] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill fills the image with a color. This affects not only the (0, 0)-(width, height) region but also the whole
|
||||
|
@ -112,7 +112,7 @@ func TestEnsureNotShared(t *testing.T) {
|
||||
img4.DrawTriangles(img3, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||
}
|
||||
|
||||
func Disabled_TestReshared(t *testing.T) {
|
||||
func TestReshared(t *testing.T) {
|
||||
const size = 16
|
||||
|
||||
img0 := NewImage(size, size)
|
||||
@ -122,8 +122,7 @@ func Disabled_TestReshared(t *testing.T) {
|
||||
img1 := NewImage(size, size)
|
||||
defer img1.Dispose()
|
||||
img1.ReplacePixels(make([]byte, 4*size*size))
|
||||
want := true
|
||||
if got := img1.IsSharedForTesting(); got != want {
|
||||
if got, want := img1.IsSharedForTesting(), true; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
@ -144,8 +143,7 @@ func Disabled_TestReshared(t *testing.T) {
|
||||
img3.MakeVolatile()
|
||||
defer img3.Dispose()
|
||||
img1.ReplacePixels(make([]byte, 4*size*size))
|
||||
want = false
|
||||
if got := img3.IsSharedForTesting(); got != want {
|
||||
if got, want := img3.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
@ -153,19 +151,19 @@ func Disabled_TestReshared(t *testing.T) {
|
||||
vs := img2.QuadVertices(0, 0, size, size, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles(img2, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||
want = false
|
||||
if got := img1.IsSharedForTesting(); got != want {
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
// Use img1 as a render source.
|
||||
for i := 0; i < MaxCountForShare-1; i++ {
|
||||
for i := 0; i < MaxCountForShare; i++ {
|
||||
MakeImagesSharedForTesting()
|
||||
img0.DrawTriangles(img1, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||
want := false
|
||||
if got := img1.IsSharedForTesting(); got != want {
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
MakeImagesSharedForTesting()
|
||||
|
||||
for j := 0; j < size; j++ {
|
||||
for i := 0; i < size; i++ {
|
||||
@ -179,8 +177,7 @@ func Disabled_TestReshared(t *testing.T) {
|
||||
}
|
||||
|
||||
img0.DrawTriangles(img1, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||
want = true
|
||||
if got := img1.IsSharedForTesting(); got != want {
|
||||
if got, want := img1.IsSharedForTesting(), true; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
@ -197,9 +194,9 @@ func Disabled_TestReshared(t *testing.T) {
|
||||
|
||||
// Use img3 as a render source. img3 never uses a shared texture.
|
||||
for i := 0; i < MaxCountForShare*2; i++ {
|
||||
MakeImagesSharedForTesting()
|
||||
img0.DrawTriangles(img3, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||
want := false
|
||||
if got := img3.IsSharedForTesting(); got != want {
|
||||
if got, want := img3.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user