internal/restorable: reland: use a smaller size rectangle for staleRegion

This commit is contained in:
Hajime Hoshi 2023-02-24 18:37:41 +09:00
parent f58d7e1ab5
commit e36007a3a3

View File

@ -17,6 +17,7 @@ package restorable
import ( import (
"fmt" "fmt"
"image" "image"
"math"
"github.com/hajimehoshi/ebiten/v2/internal/graphics" "github.com/hajimehoshi/ebiten/v2/internal/graphics"
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand" "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
@ -269,7 +270,14 @@ func (i *Image) BasePixelsForTesting() *Pixels {
// makeStale makes the image stale. // makeStale makes the image stale.
func (i *Image) makeStale(rect image.Rectangle) { func (i *Image) makeStale(rect image.Rectangle) {
i.stale = true i.stale = true
i.staleRegion = i.staleRegion.Union(i.basePixels.Region()).Union(rect)
r := i.staleRegion
r = r.Union(i.basePixels.Region())
for _, d := range i.drawTrianglesHistory {
r = r.Union(regionToRectangle(d.dstRegion))
}
r = r.Union(rect)
i.staleRegion = r
i.basePixels = Pixels{} i.basePixels = Pixels{}
i.clearDrawTrianglesHistory() i.clearDrawTrianglesHistory()
@ -338,7 +346,7 @@ func (i *Image) WritePixels(pixels []byte, x, y, width, height int) {
// Records for DrawTriangles cannot come before records for WritePixels. // Records for DrawTriangles cannot come before records for WritePixels.
if len(i.drawTrianglesHistory) > 0 { if len(i.drawTrianglesHistory) > 0 {
i.makeStale(image.Rect(0, 0, i.width, i.height)) i.makeStale(image.Rect(x, y, x+width, y+height))
return return
} }
@ -386,8 +394,9 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [g
} }
} }
if srcstale || !needsRestoring() || !i.needsRestoring() { // Even if the image is already stale, call makeStale to extend the stale region.
i.makeStale(image.Rect(0, 0, i.width, i.height)) if srcstale || !needsRestoring() || !i.needsRestoring() || i.stale {
i.makeStale(regionToRectangle(dstRegion))
} else { } else {
i.appendDrawTrianglesHistory(srcs, offsets, vertices, indices, blend, dstRegion, srcRegion, shader, uniforms, evenOdd) i.appendDrawTrianglesHistory(srcs, offsets, vertices, indices, blend, dstRegion, srcRegion, shader, uniforms, evenOdd)
} }
@ -405,13 +414,13 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [g
// appendDrawTrianglesHistory appends a draw-image history item to the image. // appendDrawTrianglesHistory appends a draw-image history item to the image.
func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms []uint32, evenOdd bool) { func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms []uint32, evenOdd bool) {
if i.stale || !i.needsRestoring() { if i.stale || !i.needsRestoring() {
return panic("restorable: an image must not be stale or need restoring at appendDrawTrianglesHistory")
} }
// TODO: Would it be possible to merge draw image history items? // TODO: Would it be possible to merge draw image history items?
const maxDrawTrianglesHistoryCount = 1024 const maxDrawTrianglesHistoryCount = 1024
if len(i.drawTrianglesHistory)+1 > maxDrawTrianglesHistoryCount { if len(i.drawTrianglesHistory)+1 > maxDrawTrianglesHistoryCount {
i.makeStale(image.Rect(0, 0, i.width, i.height)) i.makeStale(regionToRectangle(dstRegion))
return return
} }
// All images must be resolved and not stale each after frame. // All images must be resolved and not stale each after frame.
@ -467,7 +476,8 @@ func (i *Image) makeStaleIfDependingOn(target *Image) {
return return
} }
if i.dependsOn(target) { if i.dependsOn(target) {
i.makeStale(image.Rect(0, 0, i.width, i.height)) // There is no new region to make stale.
i.makeStale(image.Rectangle{})
} }
} }
@ -477,16 +487,21 @@ func (i *Image) makeStaleIfDependingOnShader(shader *Shader) {
return return
} }
if i.dependsOnShader(shader) { if i.dependsOnShader(shader) {
i.makeStale(image.Rect(0, 0, i.width, i.height)) // There is no new region to make stale.
i.makeStale(image.Rectangle{})
} }
} }
// readPixelsFromGPU reads the pixels from GPU and resolves the image's 'stale' state. // readPixelsFromGPU reads the pixels from GPU and resolves the image's 'stale' state.
func (i *Image) readPixelsFromGPU(graphicsDriver graphicsdriver.Graphics) error { func (i *Image) readPixelsFromGPU(graphicsDriver graphicsdriver.Graphics) error {
i.basePixels = Pixels{} i.basePixels = Pixels{}
r := i.staleRegion var r image.Rectangle
if len(i.drawTrianglesHistory) > 0 { if i.stale {
r = image.Rect(0, 0, i.width, i.height) r = i.staleRegion
} else {
for _, d := range i.drawTrianglesHistory {
r = r.Union(regionToRectangle(d.dstRegion))
}
} }
if !r.Empty() { if !r.Empty() {
var pix []byte var pix []byte
@ -678,3 +693,11 @@ func (i *Image) clearDrawTrianglesHistory() {
func (i *Image) InternalSize() (int, int) { func (i *Image) InternalSize() (int, int) {
return i.image.InternalSize() return i.image.InternalSize()
} }
func regionToRectangle(region graphicsdriver.Region) image.Rectangle {
return image.Rect(
int(math.Floor(float64(region.X))),
int(math.Floor(float64(region.Y))),
int(math.Ceil(float64(region.X+region.Width))),
int(math.Ceil(float64(region.Y+region.Height))))
}