mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
restorable: Reland: Refactoring
This commit is contained in:
parent
3ab56778e7
commit
b41a333230
@ -301,7 +301,7 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
}
|
}
|
||||||
i.image.ReplacePixels(pixels, x, y, width, height)
|
i.image.ReplacePixels(pixels, x, y, width, height)
|
||||||
|
|
||||||
if !NeedsRestoring() {
|
if !needsRestoring() {
|
||||||
i.makeStale()
|
i.makeStale()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -362,7 +362,7 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
|||||||
}
|
}
|
||||||
theImages.makeStaleIfDependingOn(i)
|
theImages.makeStaleIfDependingOn(i)
|
||||||
|
|
||||||
if img.stale || img.volatile || i.screen || !NeedsRestoring() || i.volatile {
|
if img.stale || img.volatile || i.screen || !needsRestoring() || i.volatile {
|
||||||
i.makeStale()
|
i.makeStale()
|
||||||
} else {
|
} else {
|
||||||
i.appendDrawTrianglesHistory(img, vertices, indices, colorm, mode, filter, address)
|
i.appendDrawTrianglesHistory(img, vertices, indices, colorm, mode, filter, address)
|
||||||
@ -447,7 +447,7 @@ func (i *Image) readPixelsFromGPU() {
|
|||||||
|
|
||||||
// resolveStale resolves the image's 'stale' state.
|
// resolveStale resolves the image's 'stale' state.
|
||||||
func (i *Image) resolveStale() {
|
func (i *Image) resolveStale() {
|
||||||
if !NeedsRestoring() {
|
if !needsRestoring() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,15 +551,11 @@ func (i *Image) Dispose() {
|
|||||||
i.stale = false
|
i.stale = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsInvalidated returns a boolean value indicating whether the image is invalidated.
|
// isInvalidated returns a boolean value indicating whether the image is invalidated.
|
||||||
//
|
//
|
||||||
// If an image is invalidated, GL context is lost and all the images should be restored asap.
|
// If an image is invalidated, GL context is lost and all the images should be restored asap.
|
||||||
func (i *Image) IsInvalidated() (bool, error) {
|
func (i *Image) isInvalidated() bool {
|
||||||
// FlushCommands is required because c.offscreen.impl might not have an actual texture.
|
// FlushCommands is required because c.offscreen.impl might not have an actual texture.
|
||||||
graphicscommand.FlushCommands()
|
graphicscommand.FlushCommands()
|
||||||
if !NeedsRestoring() {
|
return i.image.IsInvalidated()
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return i.image.IsInvalidated(), nil
|
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,8 @@ import (
|
|||||||
// forceRestoring reports whether restoring forcely happens or not.
|
// forceRestoring reports whether restoring forcely happens or not.
|
||||||
var forceRestoring = false
|
var forceRestoring = false
|
||||||
|
|
||||||
// NeedsRestoring reports whether restoring process works or not.
|
// needsRestoring reports whether restoring process works or not.
|
||||||
func NeedsRestoring() bool {
|
func needsRestoring() bool {
|
||||||
if forceRestoring {
|
if forceRestoring {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -53,16 +53,33 @@ var theImages = &images{
|
|||||||
// ResolveStaleImages is intended to be called at the end of a frame.
|
// ResolveStaleImages is intended to be called at the end of a frame.
|
||||||
func ResolveStaleImages() {
|
func ResolveStaleImages() {
|
||||||
graphicscommand.FlushCommands()
|
graphicscommand.FlushCommands()
|
||||||
if !NeedsRestoring() {
|
if !needsRestoring() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
theImages.resolveStaleImages()
|
theImages.resolveStaleImages()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore restores the images.
|
// RestoreIfNeeded restores the images.
|
||||||
//
|
//
|
||||||
// Restoring means to make all *graphicscommand.Image objects have their textures and framebuffers.
|
// Restoring means to make all *graphicscommand.Image objects have their textures and framebuffers.
|
||||||
func Restore() error {
|
func RestoreIfNeeded() error {
|
||||||
|
if !needsRestoring() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !forceRestoring {
|
||||||
|
r := false
|
||||||
|
// As isInvalidated() is expensive, call this only for one image.
|
||||||
|
// This assumes that if there is one image that is invalidated, all images are invalidated.
|
||||||
|
for img := range theImages.images {
|
||||||
|
r = img.isInvalidated()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if !r {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := graphicscommand.ResetGraphicsDriverState(); err != nil {
|
if err := graphicscommand.ResetGraphicsDriverState(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -144,7 +161,7 @@ func (i *images) makeStaleIfDependingOnImpl(target *Image) {
|
|||||||
//
|
//
|
||||||
// Restoring means to make all *graphicscommand.Image objects have their textures and framebuffers.
|
// Restoring means to make all *graphicscommand.Image objects have their textures and framebuffers.
|
||||||
func (i *images) restore() error {
|
func (i *images) restore() error {
|
||||||
if !NeedsRestoring() {
|
if !needsRestoring() {
|
||||||
panic("restorable: restore cannot be called when restoring is disabled")
|
panic("restorable: restore cannot be called when restoring is disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ func TestRestore(t *testing.T) {
|
|||||||
clr0 := color.RGBA{0x00, 0x00, 0x00, 0xff}
|
clr0 := color.RGBA{0x00, 0x00, 0x00, 0xff}
|
||||||
img0.Fill(clr0.R, clr0.G, clr0.B, clr0.A)
|
img0.Fill(clr0.R, clr0.G, clr0.B, clr0.A)
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
want := clr0
|
want := clr0
|
||||||
@ -92,7 +92,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.
|
||||||
|
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ func TestRestoreChain(t *testing.T) {
|
|||||||
imgs[i+1].DrawTriangles(imgs[i], vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)
|
imgs[i+1].DrawTriangles(imgs[i], vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||||
}
|
}
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
want := clr
|
want := clr
|
||||||
@ -175,7 +175,7 @@ func TestRestoreChain2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
for i, img := range imgs {
|
for i, img := range imgs {
|
||||||
@ -214,7 +214,7 @@ func TestRestoreOverrideSource(t *testing.T) {
|
|||||||
img0.Fill(clr1.R, clr1.G, clr1.B, clr1.A)
|
img0.Fill(clr1.R, clr1.G, clr1.B, clr1.A)
|
||||||
img1.DrawTriangles(img0, quadVertices(img0, w, h, 0, 0), is, nil, graphics.CompositeModeSourceOver, graphics.FilterNearest, graphics.AddressClampToZero)
|
img1.DrawTriangles(img0, quadVertices(img0, w, h, 0, 0), is, nil, graphics.CompositeModeSourceOver, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
@ -307,7 +307,7 @@ func TestRestoreComplexGraph(t *testing.T) {
|
|||||||
vs = quadVertices(img3, w, h, 2, 0)
|
vs = quadVertices(img3, w, h, 2, 0)
|
||||||
img7.DrawTriangles(img3, vs, is, nil, graphics.CompositeModeSourceOver, graphics.FilterNearest, graphics.AddressClampToZero)
|
img7.DrawTriangles(img3, vs, is, nil, graphics.CompositeModeSourceOver, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
@ -398,7 +398,7 @@ func TestRestoreRecursive(t *testing.T) {
|
|||||||
img1.DrawTriangles(img0, quadVertices(img0, w, h, 1, 0), is, nil, graphics.CompositeModeSourceOver, graphics.FilterNearest, graphics.AddressClampToZero)
|
img1.DrawTriangles(img0, quadVertices(img0, w, h, 1, 0), is, nil, graphics.CompositeModeSourceOver, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||||
img0.DrawTriangles(img1, quadVertices(img1, w, h, 1, 0), is, nil, graphics.CompositeModeSourceOver, graphics.FilterNearest, graphics.AddressClampToZero)
|
img0.DrawTriangles(img1, quadVertices(img1, w, h, 1, 0), is, nil, graphics.CompositeModeSourceOver, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
@ -452,7 +452,7 @@ func TestReplacePixels(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
for j := 7; j < 11; j++ {
|
for j := 7; j < 11; j++ {
|
||||||
@ -484,7 +484,7 @@ func TestDrawTrianglesAndReplacePixels(t *testing.T) {
|
|||||||
img1.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
img1.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
||||||
|
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
r, g, b, a := img1.At(0, 0)
|
r, g, b, a := img1.At(0, 0)
|
||||||
@ -517,7 +517,7 @@ func TestDispose(t *testing.T) {
|
|||||||
img1.Dispose()
|
img1.Dispose()
|
||||||
|
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
r, g, b, a := img0.At(0, 0)
|
r, g, b, a := img0.At(0, 0)
|
||||||
@ -625,7 +625,7 @@ func TestReplacePixelsOnly(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResolveStaleImages()
|
ResolveStaleImages()
|
||||||
if err := Restore(); err != nil {
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
want := color.RGBA{1, 2, 3, 4}
|
want := color.RGBA{1, 2, 3, 4}
|
||||||
|
@ -404,13 +404,6 @@ func (i *Image) IsVolatile() bool {
|
|||||||
return i.backend.restorable.IsVolatile()
|
return i.backend.restorable.IsVolatile()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) IsInvalidated() (bool, error) {
|
|
||||||
backendsM.Lock()
|
|
||||||
defer backendsM.Unlock()
|
|
||||||
v, err := i.backend.restorable.IsInvalidated()
|
|
||||||
return v, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewImage(width, height int) *Image {
|
func NewImage(width, height int) *Image {
|
||||||
// Actual allocation is done lazily.
|
// Actual allocation is done lazily.
|
||||||
return &Image{
|
return &Image{
|
||||||
@ -508,15 +501,10 @@ func ResolveStaleImages() {
|
|||||||
restorable.ResolveStaleImages()
|
restorable.ResolveStaleImages()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NeedsRestoring() bool {
|
func RestoreIfNeeded() error {
|
||||||
// As NeedsRestoring is an immutable state, no need to lock here.
|
|
||||||
return restorable.NeedsRestoring()
|
|
||||||
}
|
|
||||||
|
|
||||||
func Restore() error {
|
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
defer backendsM.Unlock()
|
defer backendsM.Unlock()
|
||||||
return restorable.Restore()
|
return restorable.RestoreIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Images() []image.Image {
|
func Images() []image.Image {
|
||||||
|
16
uicontext.go
16
uicontext.go
@ -146,22 +146,8 @@ func (c *uiContext) Update(afterFrameUpdate func()) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *uiContext) needsRestoring() (bool, error) {
|
|
||||||
return c.offscreen.mipmap.original().IsInvalidated()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *uiContext) restoreIfNeeded() error {
|
func (c *uiContext) restoreIfNeeded() error {
|
||||||
if !shareable.NeedsRestoring() {
|
if err := shareable.RestoreIfNeeded(); err != nil {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
r, err := c.needsRestoring()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !r {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := shareable.Restore(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user