From 4824cbc755960d9ebbd27238601947d57ce18d84 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Tue, 13 Sep 2022 12:15:14 +0900 Subject: [PATCH] internal/graphicscommand: bug fix: IsInvalidated was not concurrent-safe This function was not called actually, so this is not a real problem. However, this could be a potential problem for a future GLES driver (#292). Updates #292 Closes #2321 --- internal/graphicscommand/command.go | 14 ++++++++++++++ internal/graphicscommand/image.go | 16 ++++++++++++---- internal/restorable/image.go | 7 ++----- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/internal/graphicscommand/command.go b/internal/graphicscommand/command.go index 065594a0e..a1d3701bf 100644 --- a/internal/graphicscommand/command.go +++ b/internal/graphicscommand/command.go @@ -625,6 +625,20 @@ func (c *newShaderCommand) Exec(graphicsDriver graphicsdriver.Graphics, indexOff return nil } +type isInvalidatedCommand struct { + result bool + image *Image +} + +func (c *isInvalidatedCommand) String() string { + return fmt.Sprintf("is-invalidated: image: %d", c.image.id) +} + +func (c *isInvalidatedCommand) Exec(graphicsDriver graphicsdriver.Graphics, indexOffset int) error { + c.result = c.image.image.IsInvalidated() + return nil +} + // InitializeGraphicsDriverState initialize the current graphics driver state. func InitializeGraphicsDriverState(graphicsDriver graphicsdriver.Graphics) (err error) { runOnRenderingThread(func() { diff --git a/internal/graphicscommand/image.go b/internal/graphicscommand/image.go index e2ab59a35..d22a5e770 100644 --- a/internal/graphicscommand/image.go +++ b/internal/graphicscommand/image.go @@ -181,18 +181,26 @@ func (i *Image) WritePixels(pixels []byte, x, y, width, height int) { }) } -func (i *Image) IsInvalidated() bool { +func (i *Image) IsInvalidated(graphicsDriver graphicsdriver.Graphics) (bool, error) { if i.screen { // The screen image might not have a texture, and in this case it is impossible to detect whether // the image is invalidated or not. - panic("graphicscommand: IsInvalidated cannot be called on the screen image") + return false, fmt.Errorf("graphicscommand: IsInvalidated cannot be called on the screen image") } // i.image can be nil before initializing. if i.image == nil { - return false + return false, nil } - return i.image.IsInvalidated() + + c := &isInvalidatedCommand{ + image: i, + } + theCommandQueue.Enqueue(c) + if err := theCommandQueue.Flush(graphicsDriver); err != nil { + return false, err + } + return c.result, nil } func (i *Image) dumpName(path string) string { diff --git a/internal/restorable/image.go b/internal/restorable/image.go index 572547638..72b62ea80 100644 --- a/internal/restorable/image.go +++ b/internal/restorable/image.go @@ -661,11 +661,8 @@ func (i *Image) Dispose() { // // If an image is invalidated, GL context is lost and all the images should be restored asap. func (i *Image) isInvalidated(graphicsDriver graphicsdriver.Graphics) (bool, error) { - // FlushCommands is required because c.offscreen.impl might not have an actual texture. - if err := graphicscommand.FlushCommands(graphicsDriver); err != nil { - return false, err - } - return i.image.IsInvalidated(), nil + // IsInvalidated flushes the commands internally. + return i.image.IsInvalidated(graphicsDriver) } func (i *Image) Dump(graphicsDriver graphicsdriver.Graphics, path string, blackbg bool, rect image.Rectangle) (string, error) {