From 733c1b649a0f037c94f2c59b2b7ed064276e682a Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 16 Feb 2020 20:15:45 +0900 Subject: [PATCH] buffered: Bug fix: Copying pixels failed for the delayed commands Fixes #1082 --- internal/buffered/image.go | 8 +++++-- internal/buffered/image_test.go | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/internal/buffered/image.go b/internal/buffered/image.go index 2fdaceb1e..38fed6672 100644 --- a/internal/buffered/image.go +++ b/internal/buffered/image.go @@ -199,9 +199,9 @@ func (i *Image) ReplacePixels(pix []byte) { defer delayedCommandsM.Unlock() if needsToDelayCommands { + copied := make([]byte, len(pix)) + copy(copied, pix) delayedCommands = append(delayedCommands, func() error { - copied := make([]byte, len(pix)) - copy(copied, pix) i.ReplacePixels(copied) return nil }) @@ -246,6 +246,9 @@ func (i *Image) drawImage(src *Image, bounds image.Rectangle, g *mipmap.GeoM, co i.img.DrawImage(src.img, bounds, g, colorm, mode, filter) } +// DrawTriangles draws the src image with the given vertices. +// +// Copying vertices and indices is the caller's responsibility. func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address) { if i == src { panic("buffered: Image.DrawTriangles: src must be different from the receiver") @@ -256,6 +259,7 @@ func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, if needsToDelayCommands { delayedCommands = append(delayedCommands, func() error { + // Arguments are not copied. Copying is the caller's responsibility. i.DrawTriangles(src, vertices, indices, colorm, mode, filter, address) return nil }) diff --git a/internal/buffered/image_test.go b/internal/buffered/image_test.go index 0443e618f..37f0fcb3b 100644 --- a/internal/buffered/image_test.go +++ b/internal/buffered/image_test.go @@ -246,3 +246,43 @@ func TestSetAndReplacePixelsBeforeMain(t *testing.T) { t.Errorf("got: %v, want: %v", got, want) } } + +var testReplacePixelsAndModifyBeforeMainResult = func() testResult { + img, _ := ebiten.NewImage(16, 16, ebiten.FilterDefault) + pix := make([]byte, 4*16*16) + for i := 0; i < len(pix)/4; i++ { + pix[4*i] = 1 + pix[4*i+1] = 2 + pix[4*i+2] = 3 + pix[4*i+3] = 4 + } + img.ReplacePixels(pix) + // After calling ReplacePixels, modifying pix must not affect the result. + for i := 0; i < len(pix)/4; i++ { + pix[4*i] = 5 + pix[4*i+1] = 6 + pix[4*i+2] = 7 + pix[4*i+3] = 8 + } + + ch := make(chan color.RGBA, 1) + go func() { + runOnMainThread(func() { + ch <- img.At(0, 0).(color.RGBA) + }) + }() + + return testResult{ + want: color.RGBA{1, 2, 3, 4}, + got: ch, + } +}() + +func TestReplacePixelsAndModifyBeforeMain(t *testing.T) { + got := <-testReplacePixelsAndModifyBeforeMainResult.got + want := testReplacePixelsAndModifyBeforeMainResult.want + + if got != want { + t.Errorf("got: %v, want: %v", got, want) + } +}