mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-13 22:47:26 +01:00
restorable: Merge Clear to ReplacePixels
This can avoid unnecessary stale images that requires loading pixels from GPU.
This commit is contained in:
parent
4900d74a4d
commit
fb641d88cd
@ -89,18 +89,10 @@ func newImageWithoutInit(width, height int, volatile bool) *Image {
|
|||||||
// The returned image is cleared.
|
// The returned image is cleared.
|
||||||
func NewImage(width, height int, volatile bool) *Image {
|
func NewImage(width, height int, volatile bool) *Image {
|
||||||
i := newImageWithoutInit(width, height, volatile)
|
i := newImageWithoutInit(width, height, volatile)
|
||||||
i.Clear(0, 0, width, height)
|
i.ReplacePixels(nil, 0, 0, width, height)
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) Clear(x, y, width, height int) {
|
|
||||||
w, h := dummyImage.Size()
|
|
||||||
geom := (*affine.GeoM)(nil).Scale(float64(width)/float64(w), float64(height)/float64(h))
|
|
||||||
geom = geom.Translate(float64(x), float64(y))
|
|
||||||
colorm := (*affine.ColorM)(nil).Scale(0, 0, 0, 0)
|
|
||||||
i.DrawImage(dummyImage, 0, 0, w, h, geom, colorm, opengl.CompositeModeCopy, graphics.FilterNearest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewScreenFramebufferImage creates a special image that framebuffer is one for the screen.
|
// NewScreenFramebufferImage creates a special image that framebuffer is one for the screen.
|
||||||
//
|
//
|
||||||
// The returned image is cleared.
|
// The returned image is cleared.
|
||||||
@ -112,7 +104,7 @@ func NewScreenFramebufferImage(width, height int) *Image {
|
|||||||
}
|
}
|
||||||
theImages.add(i)
|
theImages.add(i)
|
||||||
runtime.SetFinalizer(i, (*Image).Dispose)
|
runtime.SetFinalizer(i, (*Image).Dispose)
|
||||||
i.Clear(0, 0, width, height)
|
i.ReplacePixels(nil, 0, 0, width, height)
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +131,8 @@ func (i *Image) makeStale() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReplacePixels replaces the image pixels with the given pixels slice.
|
// ReplacePixels replaces the image pixels with the given pixels slice.
|
||||||
|
//
|
||||||
|
// If pixels is nil, ReplacePixels clears the specified reagion.
|
||||||
func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
||||||
w, h := i.image.Size()
|
w, h := i.image.Size()
|
||||||
if width <= 0 || height <= 0 {
|
if width <= 0 || height <= 0 {
|
||||||
@ -152,7 +146,16 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
// For this purpuse, images should remember which part of that is used for DrawImage.
|
// For this purpuse, images should remember which part of that is used for DrawImage.
|
||||||
theImages.makeStaleIfDependingOn(i)
|
theImages.makeStaleIfDependingOn(i)
|
||||||
|
|
||||||
|
if pixels != nil {
|
||||||
i.image.ReplacePixels(pixels, x, y, width, height)
|
i.image.ReplacePixels(pixels, x, y, width, height)
|
||||||
|
} else {
|
||||||
|
w, h := dummyImage.Size()
|
||||||
|
geom := (*affine.GeoM)(nil).Scale(float64(width)/float64(w), float64(height)/float64(h))
|
||||||
|
geom = geom.Translate(float64(x), float64(y))
|
||||||
|
colorm := (*affine.ColorM)(nil).Scale(0, 0, 0, 0)
|
||||||
|
vs := vertices(w, h, 0, 0, w, h, geom)
|
||||||
|
i.image.DrawImage(dummyImage.image, vs, colorm, opengl.CompositeModeCopy, graphics.FilterNearest)
|
||||||
|
}
|
||||||
|
|
||||||
if x == 0 && y == 0 && width == w && height == h {
|
if x == 0 && y == 0 && width == w && height == h {
|
||||||
if i.basePixels == nil {
|
if i.basePixels == nil {
|
||||||
@ -172,10 +175,18 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
idx := 4 * (y*w + x)
|
idx := 4 * (y*w + x)
|
||||||
|
if pixels != nil {
|
||||||
for j := 0; j < height; j++ {
|
for j := 0; j < height; j++ {
|
||||||
copy(i.basePixels[idx:idx+4*width], pixels[4*j*width:4*(j+1)*width])
|
copy(i.basePixels[idx:idx+4*width], pixels[4*j*width:4*(j+1)*width])
|
||||||
idx += 4 * w
|
idx += 4 * w
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
zeros := make([]byte, 4*width)
|
||||||
|
for j := 0; j < height; j++ {
|
||||||
|
copy(i.basePixels[idx:idx+4*width], zeros)
|
||||||
|
idx += 4 * w
|
||||||
|
}
|
||||||
|
}
|
||||||
i.stale = false
|
i.stale = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,4 +569,69 @@ func TestDoubleResolve(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClear(t *testing.T) {
|
||||||
|
pix := make([]uint8, 4*4*4)
|
||||||
|
for i := range pix {
|
||||||
|
pix[i] = 0xff
|
||||||
|
}
|
||||||
|
|
||||||
|
img := NewImage(4, 4, false)
|
||||||
|
img.ReplacePixels(pix, 0, 0, 4, 4)
|
||||||
|
// This doesn't make the image stale. Its base pixels are available.
|
||||||
|
img.ReplacePixels(nil, 1, 1, 2, 2)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
Index int
|
||||||
|
Want color.RGBA
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 3,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 4,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 5,
|
||||||
|
Want: color.RGBA{0, 0, 0, 0},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 7,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 8,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 10,
|
||||||
|
Want: color.RGBA{0, 0, 0, 0},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 11,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 12,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 15,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
got := byteSliceToColor(img.BasePixelsForTesting(), c.Index)
|
||||||
|
want := c.Want
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("base pixel [%d]: got %v, want %v", c.Index, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: How about volatile/screen images?
|
// TODO: How about volatile/screen images?
|
||||||
|
@ -189,7 +189,8 @@ func (i *Image) dispose() {
|
|||||||
i.backend.page.Free(i.node)
|
i.backend.page.Free(i.node)
|
||||||
if !i.backend.page.IsEmpty() {
|
if !i.backend.page.IsEmpty() {
|
||||||
// As this part can be reused, this should be cleared explicitly.
|
// As this part can be reused, this should be cleared explicitly.
|
||||||
i.backend.restorable.Clear(i.region())
|
x0, y0, x1, y1 := i.region()
|
||||||
|
i.backend.restorable.ReplacePixels(nil, x0, y0, x1, y1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user