restorable: Pixels() should return immediately when it doesn't have to access GPU

Fixes #763
This commit is contained in:
Hajime Hoshi 2018-12-26 20:10:12 +09:00
parent 454a7d8ef9
commit fbf7007056
3 changed files with 36 additions and 5 deletions

View File

@ -106,6 +106,10 @@ func (i *Image) BasePixelsForTesting() []byte {
return i.basePixels
}
// Pixels returns the image's pixel bytes.
//
// Pixels tries to read pixels from GPU if needed.
// It is assured that GPU is not accessed if only the image's ReplacePixels is called.
func (i *Image) Pixels() []byte {
i.readPixelsFromGPUIfNeeded()
return i.basePixels
@ -189,14 +193,16 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
i.stale = false
return
}
if i.basePixels == nil {
i.makeStale()
return
}
if len(i.drawImageHistory) > 0 {
i.makeStale()
return
}
if i.stale {
return
}
if i.basePixels == nil {
i.basePixels = make([]byte, 4*w*h)
}
idx := 4 * (y*w + x)
if pixels != nil {
for j := 0; j < height; j++ {

View File

@ -657,4 +657,26 @@ func TestClear(t *testing.T) {
}
}
func TestReplacePixelsOnly(t *testing.T) {
const w, h = 128, 128
img := NewImage(w, h, false)
defer img.Dispose()
for i := 0; i < w*h; i += 5 {
img.ReplacePixels([]byte{1, 2, 3, 4}, i%w, i/w, 1, 1)
}
// BasePixelsForTesting is available without GPU accessing.
for i := 0; i < w*h; i++ {
var want color.RGBA
if i%5 == 0 {
want = color.RGBA{1, 2, 3, 4}
}
got := byteSliceToColor(img.BasePixelsForTesting(), i)
if !sameColors(got, want, 0) {
t.Errorf("got %v, want %v", got, want)
}
}
}
// TODO: How about volatile/screen images?

View File

@ -69,7 +69,10 @@ func (b *backend) TryAlloc(width, height int) (*packing.Node, bool) {
// ReplacePixels on a part of image deletes other region that are rendered by DrawImage (#593, 758).
// TODO: Add validations to ensure that an image cannot accept DrawImage after ReplacePixels on a part of
// it.
newImg.ReplacePixels(oldImg.Pixels(), 0, 0, w, h)
//
// Pixels() returns immediately as long as only oldImg.ReplacePixels is called.
pix := oldImg.Pixels()
newImg.ReplacePixels(pix, 0, 0, w, h)
oldImg.Dispose()
b.restorable = newImg