internal/restorable: reuse empty byte slices for ClearPixels

This is an improvement for https://github.com/hajimehoshi/ebiten/issues/2676#issuecomment-1650325027

Updates #2676
This commit is contained in:
Hajime Hoshi 2023-08-31 23:02:36 +09:00
parent 7ed2d73406
commit e082ea73dc
2 changed files with 39 additions and 2 deletions

View File

@ -102,6 +102,37 @@ const (
ImageTypeVolatile
)
// emptyPixels holds a byte slice used for ClearPixels.
// All the elements of the slice must be 0 and must not be modified.
//
// emptyPixels resets its slice if this is not used for a while.
type emptyPixels struct {
s []byte
last int
count int
}
var theEmptyPixels emptyPixels
func (e *emptyPixels) alloc(size int) []byte {
if cap(e.s) < size {
n := 16
for n < size {
n <<= 1
}
e.s = make([]byte, n)
}
e.last = e.count
return e.s[:size]
}
func (e *emptyPixels) endFrame() {
e.count++
if e.count-e.last >= 60 {
e.s = nil
}
}
// Image represents an image that can be restored when GL context is lost.
type Image struct {
image *graphicscommand.Image
@ -281,7 +312,7 @@ func (i *Image) WritePixels(pixels []byte, region image.Rectangle) {
// TODO: When pixels == nil, we don't have to care the pixel state there. In such cases, the image
// accepts only WritePixels and not Fill or DrawTriangles.
// TODO: Separate Image struct into two: images for WritePixels-only, and the others.
i.image.WritePixels(make([]byte, 4*region.Dx()*region.Dy()), region)
i.image.WritePixels(theEmptyPixels.alloc(4*region.Dx()*region.Dy()), region)
}
// Even if the image is already stale, call makeStale to extend the stale region.

View File

@ -65,7 +65,13 @@ func EndFrame(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) e
}
graphicscommand.LogImagesInfo(imgs)
}
return resolveStaleImages(graphicsDriver, true, swapBuffersForGL)
if err := resolveStaleImages(graphicsDriver, true, swapBuffersForGL); err != nil {
return err
}
theEmptyPixels.endFrame()
return nil
}
// resolveStaleImages flushes the queued draw commands and resolves all stale images.