internal/restorable: refactoring: add EndFrame

This commit is contained in:
Hajime Hoshi 2023-05-08 01:06:14 +09:00
parent befe990562
commit 20edb04e5e
5 changed files with 32 additions and 25 deletions

View File

@ -791,7 +791,7 @@ func (i *Image) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, path stri
func EndFrame(graphicsDriver graphicsdriver.Graphics) error { func EndFrame(graphicsDriver graphicsdriver.Graphics) error {
backendsM.Lock() backendsM.Lock()
if err := restorable.ResolveStaleImages(graphicsDriver, true); err != nil { if err := restorable.EndFrame(graphicsDriver); err != nil {
return err return err
} }

View File

@ -16,8 +16,14 @@ package restorable
import ( import (
"image" "image"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
) )
func ResolveStaleImages(graphicsDriver graphicsdriver.Graphics) error {
return resolveStaleImages(graphicsDriver, false)
}
func AppendRegionRemovingDuplicates(regions *[]image.Rectangle, region image.Rectangle) { func AppendRegionRemovingDuplicates(regions *[]image.Rectangle, region image.Rectangle) {
appendRegionRemovingDuplicates(regions, region) appendRegionRemovingDuplicates(regions, region)
} }

View File

@ -56,11 +56,7 @@ var theImages = &images{
shaders: map[*Shader]struct{}{}, shaders: map[*Shader]struct{}{},
} }
// ResolveStaleImages flushes the queued draw commands and resolves all stale images. func EndFrame(graphicsDriver graphicsdriver.Graphics) error {
// If endFrame is true, the current screen might be used to present when flushing the commands.
//
// ResolveStaleImages is intended to be called at the end of a frame.
func ResolveStaleImages(graphicsDriver graphicsdriver.Graphics, endFrame bool) error {
if debug.IsDebug { if debug.IsDebug {
debug.Logf("Internal image sizes:\n") debug.Logf("Internal image sizes:\n")
imgs := make([]*graphicscommand.Image, 0, len(theImages.images)) imgs := make([]*graphicscommand.Image, 0, len(theImages.images))
@ -69,7 +65,12 @@ func ResolveStaleImages(graphicsDriver graphicsdriver.Graphics, endFrame bool) e
} }
graphicscommand.LogImagesInfo(imgs) graphicscommand.LogImagesInfo(imgs)
} }
return resolveStaleImages(graphicsDriver, true)
}
// resolveStaleImages flushes the queued draw commands and resolves all stale images.
// If endFrame is true, the current screen might be used to present when flushing the commands.
func resolveStaleImages(graphicsDriver graphicsdriver.Graphics, endFrame bool) error {
if err := graphicscommand.FlushCommands(graphicsDriver, endFrame); err != nil { if err := graphicscommand.FlushCommands(graphicsDriver, endFrame); err != nil {
return err return err
} }

View File

@ -62,7 +62,7 @@ func TestRestore(t *testing.T) {
clr0 := color.RGBA{A: 0xff} clr0 := color.RGBA{A: 0xff}
img0.WritePixels([]byte{clr0.R, clr0.G, clr0.B, clr0.A}, image.Rect(0, 0, 1, 1)) img0.WritePixels([]byte{clr0.R, clr0.G, clr0.B, clr0.A}, image.Rect(0, 0, 1, 1))
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -81,7 +81,7 @@ func TestRestoreWithoutDraw(t *testing.T) {
// If there is no drawing command on img0, img0 is cleared when restored. // If there is no drawing command on img0, img0 is cleared when restored.
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -141,7 +141,7 @@ func TestRestoreChain(t *testing.T) {
} }
imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
} }
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -193,7 +193,7 @@ func TestRestoreChain2(t *testing.T) {
imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 0, 0), is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 0, 0), is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
} }
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -240,7 +240,7 @@ func TestRestoreOverrideSource(t *testing.T) {
img3.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 0, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) img3.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 0, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
img0.WritePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, image.Rect(0, 0, w, h)) img0.WritePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, image.Rect(0, 0, w, h))
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 0, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 0, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -342,7 +342,7 @@ func TestRestoreComplexGraph(t *testing.T) {
img7.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) img7.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
vs = quadVertices(w, h, 2, 0) vs = quadVertices(w, h, 2, 0)
img7.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img3}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) img7.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img3}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -441,7 +441,7 @@ func TestRestoreRecursive(t *testing.T) {
} }
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 1, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 1, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
img0.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 1, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) img0.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(w, h, 1, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -503,7 +503,7 @@ func TestWritePixels(t *testing.T) {
} }
} }
} }
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -546,7 +546,7 @@ func TestDrawTrianglesAndWritePixels(t *testing.T) {
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
img1.WritePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, image.Rect(0, 0, 2, 1)) img1.WritePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, image.Rect(0, 0, 2, 1))
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -590,7 +590,7 @@ func TestDispose(t *testing.T) {
img0.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false) img0.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
img1.Dispose() img1.Dispose()
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -722,7 +722,7 @@ func TestWritePixelsOnly(t *testing.T) {
} }
} }
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -817,7 +817,7 @@ func TestAllowWritePixelsForPartAfterDrawTriangles(t *testing.T) {
dst.WritePixels(make([]byte, 4*2*2), image.Rect(0, 0, 2, 2)) dst.WritePixels(make([]byte, 4*2*2), image.Rect(0, 0, 2, 2))
// WritePixels for a part of image doesn't panic. // WritePixels for a part of image doesn't panic.
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -974,7 +974,7 @@ func TestMutateSlices(t *testing.T) {
for i := range is { for i := range is {
is[i] = 0 is[i] = 0
} }
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -1126,7 +1126,7 @@ func TestOverlappedPixels(t *testing.T) {
} }
} }
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {

View File

@ -67,7 +67,7 @@ func TestShader(t *testing.T) {
} }
img.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, s, nil, false) img.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, s, nil, false)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -103,7 +103,7 @@ func TestShaderChain(t *testing.T) {
imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, s, nil, false) imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, s, nil, false)
} }
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -143,7 +143,7 @@ func TestShaderMultipleSources(t *testing.T) {
// Clear one of the sources after DrawTriangles. dst should not be affected. // Clear one of the sources after DrawTriangles. dst should not be affected.
clearImage(srcs[0], 1, 1) clearImage(srcs[0], 1, 1)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -184,7 +184,7 @@ func TestShaderMultipleSourcesOnOneTexture(t *testing.T) {
// Clear one of the sources after DrawTriangles. dst should not be affected. // Clear one of the sources after DrawTriangles. dst should not be affected.
clearImage(srcs[0], 3, 1) clearImage(srcs[0], 3, 1)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {
@ -215,7 +215,7 @@ func TestShaderDispose(t *testing.T) {
// stale. // stale.
s.Dispose() s.Dispose()
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.RestoreIfNeeded(ui.GraphicsDriverForTesting()); err != nil {