internal/atlas: add a new parameter specifying a mask for ReplacePixels

This commit is contained in:
Hajime Hoshi 2022-03-21 03:56:04 +09:00
parent 5c79b86412
commit b3f4d6c522
4 changed files with 28 additions and 29 deletions

View File

@ -337,7 +337,7 @@ func (i *Image) putOnAtlas(graphicsDriver graphicsdriver.Graphics) error {
pixels[4*(i.width*y+x)+3] = a pixels[4*(i.width*y+x)+3] = a
} }
} }
newI.replacePixels(pixels) newI.replacePixels(pixels, nil)
} else { } else {
// If the underlying graphics driver doesn't require restoring from the context lost, just a regular // If the underlying graphics driver doesn't require restoring from the context lost, just a regular
// rendering works. // rendering works.
@ -541,13 +541,13 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
// ReplacePixels replaces the pixels on the image. // ReplacePixels replaces the pixels on the image.
// ReplacePixels cannot take a region due to the current implementation. // ReplacePixels cannot take a region due to the current implementation.
// internal/restorable.Image has to record the areas of replaced pixels, and the areas must not be overlapped so far. // internal/restorable.Image has to record the areas of replaced pixels, and the areas must not be overlapped so far.
func (i *Image) ReplacePixels(pix []byte) { func (i *Image) ReplacePixels(pix []byte, mask []byte) {
backendsM.Lock() backendsM.Lock()
defer backendsM.Unlock() defer backendsM.Unlock()
i.replacePixels(pix) i.replacePixels(pix, mask)
} }
func (i *Image) replacePixels(pix []byte) { func (i *Image) replacePixels(pix []byte, mask []byte) {
if i.disposed { if i.disposed {
panic("atlas: the image must not be disposed at replacePixels") panic("atlas: the image must not be disposed at replacePixels")
} }
@ -598,8 +598,7 @@ func (i *Image) replacePixels(pix []byte) {
copy(pixb[4*((j+paddingSize)*pw+paddingSize):], pix[4*j*ow:4*(j+1)*ow]) copy(pixb[4*((j+paddingSize)*pw+paddingSize):], pix[4*j*ow:4*(j+1)*ow])
} }
// TODO: Specify a mask if needed. i.backend.restorable.ReplacePixels(pixb, mask, px, py, pw, ph)
i.backend.restorable.ReplacePixels(pixb, nil, px, py, pw, ph)
} }
func (img *Image) Pixels(graphicsDriver graphicsdriver.Graphics) ([]byte, error) { func (img *Image) Pixels(graphicsDriver graphicsdriver.Graphics) ([]byte, error) {

View File

@ -63,17 +63,17 @@ func TestEnsureIsolated(t *testing.T) {
img1 := atlas.NewImage(bigSize, 100) img1 := atlas.NewImage(bigSize, 100)
defer img1.MarkDisposed() defer img1.MarkDisposed()
// Ensure img1's region is allocated. // Ensure img1's region is allocated.
img1.ReplacePixels(make([]byte, 4*bigSize*100)) img1.ReplacePixels(make([]byte, 4*bigSize*100), nil)
img2 := atlas.NewImage(100, bigSize) img2 := atlas.NewImage(100, bigSize)
defer img2.MarkDisposed() defer img2.MarkDisposed()
img2.ReplacePixels(make([]byte, 4*100*bigSize)) img2.ReplacePixels(make([]byte, 4*100*bigSize), nil)
const size = 32 const size = 32
img3 := atlas.NewImage(size/2, size/2) img3 := atlas.NewImage(size/2, size/2)
defer img3.MarkDisposed() defer img3.MarkDisposed()
img3.ReplacePixels(make([]byte, (size/2)*(size/2)*4)) img3.ReplacePixels(make([]byte, (size/2)*(size/2)*4), nil)
img4 := atlas.NewImage(size, size) img4 := atlas.NewImage(size, size)
defer img4.MarkDisposed() defer img4.MarkDisposed()
@ -87,7 +87,7 @@ func TestEnsureIsolated(t *testing.T) {
pix[4*(i+j*size)+3] = byte(i + j) pix[4*(i+j*size)+3] = byte(i + j)
} }
} }
img4.ReplacePixels(pix) img4.ReplacePixels(pix, nil)
const ( const (
dx0 = size / 4 dx0 = size / 4
@ -142,11 +142,11 @@ func TestReputOnAtlas(t *testing.T) {
img0 := atlas.NewImage(size, size) img0 := atlas.NewImage(size, size)
defer img0.MarkDisposed() defer img0.MarkDisposed()
img0.ReplacePixels(make([]byte, 4*size*size)) img0.ReplacePixels(make([]byte, 4*size*size), nil)
img1 := atlas.NewImage(size, size) img1 := atlas.NewImage(size, size)
defer img1.MarkDisposed() defer img1.MarkDisposed()
img1.ReplacePixels(make([]byte, 4*size*size)) img1.ReplacePixels(make([]byte, 4*size*size), nil)
if got, want := img1.IsOnAtlasForTesting(), true; got != want { if got, want := img1.IsOnAtlasForTesting(), true; got != want {
t.Errorf("got: %v, want: %v", got, want) t.Errorf("got: %v, want: %v", got, want)
} }
@ -162,12 +162,12 @@ func TestReputOnAtlas(t *testing.T) {
pix[4*(i+j*size)+3] = byte(i + j) pix[4*(i+j*size)+3] = byte(i + j)
} }
} }
img2.ReplacePixels(pix) img2.ReplacePixels(pix, nil)
img3 := atlas.NewImage(size, size) img3 := atlas.NewImage(size, size)
img3.SetVolatile(true) img3.SetVolatile(true)
defer img3.MarkDisposed() defer img3.MarkDisposed()
img1.ReplacePixels(make([]byte, 4*size*size)) img1.ReplacePixels(make([]byte, 4*size*size), nil)
if got, want := img3.IsOnAtlasForTesting(), false; got != want { if got, want := img3.IsOnAtlasForTesting(), false; got != want {
t.Errorf("got: %v, want: %v", got, want) t.Errorf("got: %v, want: %v", got, want)
} }
@ -256,7 +256,7 @@ func TestReputOnAtlas(t *testing.T) {
if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil { if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
img1.ReplacePixels(make([]byte, 4*size*size)) img1.ReplacePixels(make([]byte, 4*size*size), nil)
img0.DrawTriangles([graphics.ShaderImageNum]*atlas.Image{img1}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false) img0.DrawTriangles([graphics.ShaderImageNum]*atlas.Image{img1}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
if got, want := img1.IsOnAtlasForTesting(), false; got != want { if got, want := img1.IsOnAtlasForTesting(), false; got != want {
t.Errorf("got: %v, want: %v", got, want) t.Errorf("got: %v, want: %v", got, want)
@ -298,7 +298,7 @@ func TestExtend(t *testing.T) {
p0[4*i+2] = byte(i) p0[4*i+2] = byte(i)
p0[4*i+3] = byte(i) p0[4*i+3] = byte(i)
} }
img0.ReplacePixels(p0) img0.ReplacePixels(p0, nil)
const w1, h1 = minImageSizeForTesting + 1, 100 const w1, h1 = minImageSizeForTesting + 1, 100
img1 := atlas.NewImage(w1, h1) img1 := atlas.NewImage(w1, h1)
@ -312,7 +312,7 @@ func TestExtend(t *testing.T) {
p1[4*i+3] = byte(i) p1[4*i+3] = byte(i)
} }
// Ensure to allocate // Ensure to allocate
img1.ReplacePixels(p1) img1.ReplacePixels(p1, nil)
pix0, err := img0.Pixels(ui.GraphicsDriverForTesting()) pix0, err := img0.Pixels(ui.GraphicsDriverForTesting())
if err != nil { if err != nil {
@ -367,7 +367,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
pix[4*i+2] = byte(i) pix[4*i+2] = byte(i)
pix[4*i+3] = byte(i) pix[4*i+3] = byte(i)
} }
src.ReplacePixels(pix) src.ReplacePixels(pix, nil)
vs := quadVertices(w, h, 0, 0, 1) vs := quadVertices(w, h, 0, 0, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
@ -378,7 +378,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
Height: h, Height: h,
} }
dst.DrawTriangles([graphics.ShaderImageNum]*atlas.Image{src}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false) dst.DrawTriangles([graphics.ShaderImageNum]*atlas.Image{src}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
dst.ReplacePixels(pix) dst.ReplacePixels(pix, nil)
pix, err := dst.Pixels(ui.GraphicsDriverForTesting()) pix, err := dst.Pixels(ui.GraphicsDriverForTesting())
if err != nil { if err != nil {
@ -415,7 +415,7 @@ func TestSmallImages(t *testing.T) {
pix[4*i+2] = 0xff pix[4*i+2] = 0xff
pix[4*i+3] = 0xff pix[4*i+3] = 0xff
} }
src.ReplacePixels(pix) src.ReplacePixels(pix, nil)
vs := quadVertices(w, h, 0, 0, 1) vs := quadVertices(w, h, 0, 0, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
@ -462,7 +462,7 @@ func TestLongImages(t *testing.T) {
pix[4*i+2] = 0xff pix[4*i+2] = 0xff
pix[4*i+3] = 0xff pix[4*i+3] = 0xff
} }
src.ReplacePixels(pix) src.ReplacePixels(pix, nil)
const scale = 120 const scale = 120
vs := quadVertices(w, h, 0, 0, scale) vs := quadVertices(w, h, 0, 0, scale)
@ -512,12 +512,12 @@ func TestExtendWithBigImage(t *testing.T) {
img0 := atlas.NewImage(1, 1) img0 := atlas.NewImage(1, 1)
defer img0.MarkDisposed() defer img0.MarkDisposed()
img0.ReplacePixels(make([]byte, 4*1*1)) img0.ReplacePixels(make([]byte, 4*1*1), nil)
img1 := atlas.NewImage(minImageSizeForTesting+1, minImageSizeForTesting+1) img1 := atlas.NewImage(minImageSizeForTesting+1, minImageSizeForTesting+1)
defer img1.MarkDisposed() defer img1.MarkDisposed()
img1.ReplacePixels(make([]byte, 4*(minImageSizeForTesting+1)*(minImageSizeForTesting+1))) img1.ReplacePixels(make([]byte, 4*(minImageSizeForTesting+1)*(minImageSizeForTesting+1)), nil)
} }
// Issue #1217 // Issue #1217
@ -526,7 +526,7 @@ func TestMaxImageSize(t *testing.T) {
s := maxImageSizeForTesting - 2*atlas.PaddingSize s := maxImageSizeForTesting - 2*atlas.PaddingSize
img := atlas.NewImage(s, s) img := atlas.NewImage(s, s)
defer img.MarkDisposed() defer img.MarkDisposed()
img.ReplacePixels(make([]byte, 4*s*s)) img.ReplacePixels(make([]byte, 4*s*s), nil)
} }
// Issue #1217 (disabled) // Issue #1217 (disabled)
@ -539,7 +539,7 @@ func Disable_TestMinImageSize(t *testing.T) {
s := minImageSizeForTesting s := minImageSizeForTesting
img := atlas.NewImage(s, s) img := atlas.NewImage(s, s)
defer img.MarkDisposed() defer img.MarkDisposed()
img.ReplacePixels(make([]byte, 4*s*s)) img.ReplacePixels(make([]byte, 4*s*s), nil)
} }
// Issue #1421 // Issue #1421

View File

@ -65,9 +65,9 @@ func TestImageDrawTwice(t *testing.T) {
dst := atlas.NewImage(w, h) dst := atlas.NewImage(w, h)
src0 := atlas.NewImage(w, h) src0 := atlas.NewImage(w, h)
src0.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff}) src0.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff}, nil)
src1 := atlas.NewImage(w, h) src1 := atlas.NewImage(w, h)
src1.ReplacePixels([]byte{0x80, 0x80, 0x80, 0xff}) src1.ReplacePixels([]byte{0x80, 0x80, 0x80, 0xff}, nil)
vs := quadVertices(w, h, 0, 0, 1) vs := quadVertices(w, h, 0, 0, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()

View File

@ -117,7 +117,7 @@ func (i *Image) invalidatePendingPixels() {
func (i *Image) resolvePendingPixels(keepPendingPixels bool) { func (i *Image) resolvePendingPixels(keepPendingPixels bool) {
if i.needsToResolvePixels { if i.needsToResolvePixels {
i.img.ReplacePixels(i.pixels) i.img.ReplacePixels(i.pixels, nil)
if !keepPendingPixels { if !keepPendingPixels {
i.pixels = nil i.pixels = nil
} }
@ -187,7 +187,7 @@ func (i *Image) ReplacePixels(pix []byte) {
i.invalidatePendingPixels() i.invalidatePendingPixels()
i.img.ReplacePixels(pix) i.img.ReplacePixels(pix, nil)
} }
// ReplacePartial replaces the pixel at the specified partial region. // ReplacePartial replaces the pixel at the specified partial region.