internal/ui: refactoring: integrate the render thread usages into internal/graphicscommand

Updates #2664
This commit is contained in:
Hajime Hoshi 2023-07-30 02:25:10 +09:00
parent 246bd41695
commit 3869e2e4f6
11 changed files with 37 additions and 34 deletions

View File

@ -788,10 +788,10 @@ func (i *Image) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, path stri
return i.backend.restorable.Dump(graphicsDriver, path, blackbg, image.Rect(0, 0, i.width, i.height)) return i.backend.restorable.Dump(graphicsDriver, path, blackbg, image.Rect(0, 0, i.width, i.height))
} }
func EndFrame(graphicsDriver graphicsdriver.Graphics) error { func EndFrame(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) error {
backendsM.Lock() backendsM.Lock()
if err := restorable.EndFrame(graphicsDriver); err != nil { if err := restorable.EndFrame(graphicsDriver, swapBuffersForGL); err != nil {
return err return err
} }

View File

@ -42,8 +42,8 @@ func BeginFrame(graphicsDriver graphicsdriver.Graphics) error {
return nil return nil
} }
func EndFrame(graphicsDriver graphicsdriver.Graphics) error { func EndFrame(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) error {
return atlas.EndFrame(graphicsDriver) return atlas.EndFrame(graphicsDriver, swapBuffersForGL)
} }
func NewImage(width, height int, imageType atlas.ImageType) *Image { func NewImage(width, height int, imageType atlas.ImageType) *Image {

View File

@ -164,9 +164,16 @@ func (q *commandQueue) Enqueue(command command) {
} }
// Flush flushes the command queue. // Flush flushes the command queue.
func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bool) (err error) { func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bool, swapBuffersForGL func()) (err error) {
runOnRenderThread(func() { runOnRenderThread(func() {
err = q.flush(graphicsDriver, endFrame) err = q.flush(graphicsDriver, endFrame)
if err != nil {
return
}
if endFrame && swapBuffersForGL != nil {
swapBuffersForGL()
}
}) })
if endFrame { if endFrame {
q.uint32sBuffer.reset() q.uint32sBuffer.reset()
@ -253,9 +260,9 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
// FlushCommands flushes the command queue and present the screen if needed. // FlushCommands flushes the command queue and present the screen if needed.
// If endFrame is true, the current screen might be used to present. // If endFrame is true, the current screen might be used to present.
func FlushCommands(graphicsDriver graphicsdriver.Graphics, endFrame bool) error { func FlushCommands(graphicsDriver graphicsdriver.Graphics, endFrame bool, swapBuffersForGL func()) error {
flushImageBuffers() flushImageBuffers()
return theCommandQueue.Flush(graphicsDriver, endFrame) return theCommandQueue.Flush(graphicsDriver, endFrame, swapBuffersForGL)
} }
// drawTrianglesCommand represents a drawing command to draw an image on another image. // drawTrianglesCommand represents a drawing command to draw an image on another image.

View File

@ -171,7 +171,7 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, buf []byte, r
result: buf, result: buf,
} }
theCommandQueue.Enqueue(c) theCommandQueue.Enqueue(c)
if err := theCommandQueue.Flush(graphicsDriver, false); err != nil { if err := theCommandQueue.Flush(graphicsDriver, false, nil); err != nil {
return err return err
} }
return nil return nil
@ -201,7 +201,7 @@ func (i *Image) IsInvalidated(graphicsDriver graphicsdriver.Graphics) (bool, err
image: i, image: i,
} }
theCommandQueue.Enqueue(c) theCommandQueue.Enqueue(c)
if err := theCommandQueue.Flush(graphicsDriver, false); err != nil { if err := theCommandQueue.Flush(graphicsDriver, false, nil); err != nil {
return false, err return false, err
} }
return c.result, nil return c.result, nil

View File

@ -21,7 +21,7 @@ import (
) )
func ResolveStaleImages(graphicsDriver graphicsdriver.Graphics) error { func ResolveStaleImages(graphicsDriver graphicsdriver.Graphics) error {
return resolveStaleImages(graphicsDriver, false) return resolveStaleImages(graphicsDriver, false, nil)
} }
func AppendRegionRemovingDuplicates(regions *[]image.Rectangle, region image.Rectangle) { func AppendRegionRemovingDuplicates(regions *[]image.Rectangle, region image.Rectangle) {

View File

@ -56,7 +56,7 @@ var theImages = &images{
shaders: map[*Shader]struct{}{}, shaders: map[*Shader]struct{}{},
} }
func EndFrame(graphicsDriver graphicsdriver.Graphics) error { func EndFrame(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) 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))
@ -65,13 +65,13 @@ func EndFrame(graphicsDriver graphicsdriver.Graphics) error {
} }
graphicscommand.LogImagesInfo(imgs) graphicscommand.LogImagesInfo(imgs)
} }
return resolveStaleImages(graphicsDriver, true) return resolveStaleImages(graphicsDriver, true, swapBuffersForGL)
} }
// resolveStaleImages flushes the queued draw commands and resolves all stale images. // 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. // If endFrame is true, the current screen might be used to present when flushing the commands.
func resolveStaleImages(graphicsDriver graphicsdriver.Graphics, endFrame bool) error { func resolveStaleImages(graphicsDriver graphicsdriver.Graphics, endFrame bool, swapBuffersForGL func()) error {
if err := graphicscommand.FlushCommands(graphicsDriver, endFrame); err != nil { if err := graphicscommand.FlushCommands(graphicsDriver, endFrame, swapBuffersForGL); err != nil {
return err return err
} }
if !needsRestoring() { if !needsRestoring() {

View File

@ -68,12 +68,12 @@ func newContext(game Game) *context {
} }
} }
func (c *context) updateFrame(graphicsDriver graphicsdriver.Graphics, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *userInterfaceImpl) error { func (c *context) updateFrame(graphicsDriver graphicsdriver.Graphics, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *userInterfaceImpl, swapBuffersForGL func()) error {
// TODO: If updateCount is 0 and vsync is disabled, swapping buffers can be skipped. // TODO: If updateCount is 0 and vsync is disabled, swapping buffers can be skipped.
return c.updateFrameImpl(graphicsDriver, clock.UpdateFrame(), outsideWidth, outsideHeight, deviceScaleFactor, ui, false) return c.updateFrameImpl(graphicsDriver, clock.UpdateFrame(), outsideWidth, outsideHeight, deviceScaleFactor, ui, false, swapBuffersForGL)
} }
func (c *context) forceUpdateFrame(graphicsDriver graphicsdriver.Graphics, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *userInterfaceImpl) error { func (c *context) forceUpdateFrame(graphicsDriver graphicsdriver.Graphics, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *userInterfaceImpl, swapBuffersForGL func()) error {
n := 1 n := 1
if graphicsDriver.IsDirectX() { if graphicsDriver.IsDirectX() {
// On DirectX, both framebuffers in the swap chain should be updated. // On DirectX, both framebuffers in the swap chain should be updated.
@ -81,14 +81,14 @@ func (c *context) forceUpdateFrame(graphicsDriver graphicsdriver.Graphics, outsi
n = 2 n = 2
} }
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
if err := c.updateFrameImpl(graphicsDriver, 1, outsideWidth, outsideHeight, deviceScaleFactor, ui, true); err != nil { if err := c.updateFrameImpl(graphicsDriver, 1, outsideWidth, outsideHeight, deviceScaleFactor, ui, true, swapBuffersForGL); err != nil {
return err return err
} }
} }
return nil return nil
} }
func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, updateCount int, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *userInterfaceImpl, forceDraw bool) (err error) { func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, updateCount int, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *userInterfaceImpl, forceDraw bool, swapBuffersForGL func()) (err error) {
if err := theGlobalState.error(); err != nil { if err := theGlobalState.error(); err != nil {
return err return err
} }
@ -108,7 +108,7 @@ func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, update
return err return err
} }
defer func() { defer func() {
if err1 := buffered.EndFrame(graphicsDriver); err == nil && err1 != nil { if err1 := buffered.EndFrame(graphicsDriver, swapBuffersForGL); err == nil && err1 != nil {
err = err1 err = err1
} }
}() }()

View File

@ -1087,18 +1087,16 @@ func (u *userInterfaceImpl) updateGame() error {
}) })
}) })
if err := u.context.updateFrame(u.graphicsDriver, outsideWidth, outsideHeight, deviceScaleFactor, u); err != nil { if err := u.context.updateFrame(u.graphicsDriver, outsideWidth, outsideHeight, deviceScaleFactor, u, func() {
return err
}
u.renderThread.Call(func() {
// Call updateVsync even though fpsMode is not updated. // Call updateVsync even though fpsMode is not updated.
// When toggling to fullscreen, vsync state might be reset unexpectedly (#1787). // When toggling to fullscreen, vsync state might be reset unexpectedly (#1787).
u.updateVsyncOnRenderThread() u.updateVsyncOnRenderThread()
// This works only for OpenGL. // This works only for OpenGL.
u.swapBuffersOnRenderThread() u.swapBuffersOnRenderThread()
}) }); err != nil {
return err
}
u.bufferOnceSwappedOnce.Do(func() { u.bufferOnceSwappedOnce.Do(func() {
u.mainThread.Call(func() { u.mainThread.Call(func() {

View File

@ -343,11 +343,11 @@ func (u *userInterfaceImpl) updateImpl(force bool) error {
w, h := u.outsideSize() w, h := u.outsideSize()
if force { if force {
if err := u.context.forceUpdateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u); err != nil { if err := u.context.forceUpdateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u, nil); err != nil {
return err return err
} }
} else { } else {
if err := u.context.updateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u); err != nil { if err := u.context.updateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u, nil); err != nil {
return err return err
} }
} }

View File

@ -331,7 +331,7 @@ func (u *userInterfaceImpl) update() error {
}() }()
w, h := u.outsideSize() w, h := u.outsideSize()
if err := u.context.updateFrame(u.graphicsDriver, w, h, deviceScale(), u); err != nil { if err := u.context.updateFrame(u.graphicsDriver, w, h, deviceScale(), u, nil); err != nil {
return err return err
} }
return nil return nil

View File

@ -121,13 +121,11 @@ func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error {
u.updateInputState() u.updateInputState()
}) })
if err := u.context.updateFrame(u.graphicsDriver, float64(C.kScreenWidth), float64(C.kScreenHeight), deviceScaleFactor, u); err != nil { if err := u.context.updateFrame(u.graphicsDriver, float64(C.kScreenWidth), float64(C.kScreenHeight), deviceScaleFactor, u, func() {
u.egl.swapBuffers()
}); err != nil {
return err return err
} }
u.renderThread.Call(func() {
u.egl.swapBuffers()
})
} }
}) })