mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
internal/graphicscommand: bug fix: buffered write pixel args might never be released
Closes #3036
This commit is contained in:
parent
46d171c3c5
commit
7b46df44ee
@ -59,6 +59,15 @@ func (m *ManagedBytes) GetAndRelease() ([]byte, func()) {
|
||||
}
|
||||
}
|
||||
|
||||
// Release releases the underlying byte slice.
|
||||
//
|
||||
// After Release is called, the underlying byte slice is no longer available.
|
||||
func (m *ManagedBytes) Release() {
|
||||
m.pool.put(m.bytes)
|
||||
m.bytes = nil
|
||||
runtime.SetFinalizer(m, nil)
|
||||
}
|
||||
|
||||
// NewManagedBytes returns a managed byte slice initialized by the given constructor f.
|
||||
//
|
||||
// The byte slice is not zero-cleared at the constructor.
|
||||
|
@ -161,7 +161,23 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, args []graphi
|
||||
}
|
||||
|
||||
func (i *Image) WritePixels(pixels *graphics.ManagedBytes, region image.Rectangle) {
|
||||
i.bufferedWritePixelsArgs = append(i.bufferedWritePixelsArgs, writePixelsCommandArgs{
|
||||
// Release the previous pixels if the region is included by the new region.
|
||||
// Successive WritePixels calls might accumulate the pixels and never release,
|
||||
// especially when the image is unmanaged (#3036).
|
||||
var cur int
|
||||
for idx := 0; idx < len(i.bufferedWritePixelsArgs); idx++ {
|
||||
arg := i.bufferedWritePixelsArgs[idx]
|
||||
if arg.region.In(region) {
|
||||
arg.pixels.Release()
|
||||
continue
|
||||
}
|
||||
i.bufferedWritePixelsArgs[cur] = arg
|
||||
cur++
|
||||
}
|
||||
for idx := cur; idx < len(i.bufferedWritePixelsArgs); idx++ {
|
||||
i.bufferedWritePixelsArgs[idx] = writePixelsCommandArgs{}
|
||||
}
|
||||
i.bufferedWritePixelsArgs = append(i.bufferedWritePixelsArgs[:cur], writePixelsCommandArgs{
|
||||
pixels: pixels,
|
||||
region: region,
|
||||
})
|
||||
|
@ -135,3 +135,54 @@ func TestShader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Issue #3036
|
||||
func TestSuccessiveWritePixels(t *testing.T) {
|
||||
const w, h = 32, 32
|
||||
dst := graphicscommand.NewImage(w, h, false)
|
||||
|
||||
dst.WritePixels(graphics.NewManagedBytes(4, func(bs []byte) {
|
||||
for i := range bs {
|
||||
bs[i] = 0
|
||||
}
|
||||
}), image.Rect(0, 0, 1, 1))
|
||||
if got, want := len(dst.BufferedWritePixelsArgsForTesting()), 1; got != want {
|
||||
t.Errorf("len(dst.BufferedWritePixelsArgsForTesting()): got %d, want: %d", got, want)
|
||||
}
|
||||
|
||||
dst.WritePixels(graphics.NewManagedBytes(4, func(bs []byte) {
|
||||
for i := range bs {
|
||||
bs[i] = 0
|
||||
}
|
||||
}), image.Rect(1, 1, 2, 2))
|
||||
if got, want := len(dst.BufferedWritePixelsArgsForTesting()), 2; got != want {
|
||||
t.Errorf("len(dst.BufferedWritePixelsArgsForTesting()): got %d, want: %d", got, want)
|
||||
}
|
||||
|
||||
dst.WritePixels(graphics.NewManagedBytes(4, func(bs []byte) {
|
||||
for i := range bs {
|
||||
bs[i] = 0
|
||||
}
|
||||
}), image.Rect(0, 0, 1, 1))
|
||||
if got, want := len(dst.BufferedWritePixelsArgsForTesting()), 2; got != want {
|
||||
t.Errorf("len(dst.BufferedWritePixelsArgsForTesting()): got %d, want: %d", got, want)
|
||||
}
|
||||
|
||||
dst.WritePixels(graphics.NewManagedBytes(4, func(bs []byte) {
|
||||
for i := range bs {
|
||||
bs[i] = 0
|
||||
}
|
||||
}), image.Rect(0, 0, 1, 1))
|
||||
if got, want := len(dst.BufferedWritePixelsArgsForTesting()), 2; got != want {
|
||||
t.Errorf("len(dst.BufferedWritePixelsArgsForTesting()): got %d, want: %d", got, want)
|
||||
}
|
||||
|
||||
dst.WritePixels(graphics.NewManagedBytes(4, func(bs []byte) {
|
||||
for i := range bs {
|
||||
bs[i] = 0
|
||||
}
|
||||
}), image.Rect(0, 0, 2, 2))
|
||||
if got, want := len(dst.BufferedWritePixelsArgsForTesting()), 1; got != want {
|
||||
t.Errorf("len(dst.BufferedWritePixelsArgsForTesting()): got %d, want: %d", got, want)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user