From eb5ab57cdc3de00455362a13025c9ced854c28ae Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Mon, 12 Aug 2019 19:37:20 +0900 Subject: [PATCH] shareable: Bug fix: Defer Dispose so that ClearPixels doesn't affect other images later Updates #913 --- internal/shareable/shareable.go | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/internal/shareable/shareable.go b/internal/shareable/shareable.go index cd4658519..2d92c8479 100644 --- a/internal/shareable/shareable.go +++ b/internal/shareable/shareable.go @@ -50,6 +50,7 @@ func init() { hooks.AppendHookOnBeforeUpdate(func() error { backendsM.Lock() defer backendsM.Unlock() + once.Do(func() { if len(theBackends) != 0 { panic("shareable: all the images must be not-shared before the game starts") @@ -64,11 +65,23 @@ func init() { maxSize = 512 } }) + + resolveDeferred() makeImagesShared() return nil }) } +func resolveDeferred() { + deferredM.Lock() + defer deferredM.Unlock() + + for _, f := range deferred { + f() + } + deferred = nil +} + // MaxCountForShare represents the time duration when the image can become shared. // // This value is expoted for testing. @@ -137,6 +150,9 @@ var ( theBackends = []*backend{} imagesToMakeShared = map[*Image]struct{}{} + + deferred []func() + deferredM sync.Mutex ) // isShareable reports whether the new allocation can use the shareable backends. @@ -367,9 +383,17 @@ func (i *Image) at(x, y int) (byte, byte, byte, byte) { } func (i *Image) Dispose() { - backendsM.Lock() - defer backendsM.Unlock() - i.dispose(true) + deferredM.Lock() + defer deferredM.Unlock() + + // Defer actual disposing until disposing can finish completely. + // Otherwise, ClearPixels can be deferred in between frames, and delayed ClearPixels can affect other images. + // (#913) + // + // TODO: Other operations should be deferred too? + deferred = append(deferred, func() { + i.dispose(true) + }) } func (i *Image) dispose(markDisposed bool) {