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))
}
func EndFrame(graphicsDriver graphicsdriver.Graphics) error {
func EndFrame(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) error {
backendsM.Lock()
if err := restorable.EndFrame(graphicsDriver); err != nil {
if err := restorable.EndFrame(graphicsDriver, swapBuffersForGL); err != nil {
return err
}

View File

@ -42,8 +42,8 @@ func BeginFrame(graphicsDriver graphicsdriver.Graphics) error {
return nil
}
func EndFrame(graphicsDriver graphicsdriver.Graphics) error {
return atlas.EndFrame(graphicsDriver)
func EndFrame(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) error {
return atlas.EndFrame(graphicsDriver, swapBuffersForGL)
}
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.
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() {
err = q.flush(graphicsDriver, endFrame)
if err != nil {
return
}
if endFrame && swapBuffersForGL != nil {
swapBuffersForGL()
}
})
if endFrame {
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.
// 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()
return theCommandQueue.Flush(graphicsDriver, endFrame)
return theCommandQueue.Flush(graphicsDriver, endFrame, swapBuffersForGL)
}
// 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,
}
theCommandQueue.Enqueue(c)
if err := theCommandQueue.Flush(graphicsDriver, false); err != nil {
if err := theCommandQueue.Flush(graphicsDriver, false, nil); err != nil {
return err
}
return nil
@ -201,7 +201,7 @@ func (i *Image) IsInvalidated(graphicsDriver graphicsdriver.Graphics) (bool, err
image: i,
}
theCommandQueue.Enqueue(c)
if err := theCommandQueue.Flush(graphicsDriver, false); err != nil {
if err := theCommandQueue.Flush(graphicsDriver, false, nil); err != nil {
return false, err
}
return c.result, nil

View File

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

View File

@ -56,7 +56,7 @@ var theImages = &images{
shaders: map[*Shader]struct{}{},
}
func EndFrame(graphicsDriver graphicsdriver.Graphics) error {
func EndFrame(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) error {
if debug.IsDebug {
debug.Logf("Internal image sizes:\n")
imgs := make([]*graphicscommand.Image, 0, len(theImages.images))
@ -65,13 +65,13 @@ func EndFrame(graphicsDriver graphicsdriver.Graphics) error {
}
graphicscommand.LogImagesInfo(imgs)
}
return resolveStaleImages(graphicsDriver, true)
return resolveStaleImages(graphicsDriver, true, swapBuffersForGL)
}
// 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 {
func resolveStaleImages(graphicsDriver graphicsdriver.Graphics, endFrame bool, swapBuffersForGL func()) error {
if err := graphicscommand.FlushCommands(graphicsDriver, endFrame, swapBuffersForGL); err != nil {
return err
}
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.
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
if graphicsDriver.IsDirectX() {
// 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
}
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 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 {
return err
}
@ -108,7 +108,7 @@ func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, update
return err
}
defer func() {
if err1 := buffered.EndFrame(graphicsDriver); err == nil && err1 != nil {
if err1 := buffered.EndFrame(graphicsDriver, swapBuffersForGL); err == nil && err1 != nil {
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 {
return err
}
u.renderThread.Call(func() {
if err := u.context.updateFrame(u.graphicsDriver, outsideWidth, outsideHeight, deviceScaleFactor, u, func() {
// Call updateVsync even though fpsMode is not updated.
// When toggling to fullscreen, vsync state might be reset unexpectedly (#1787).
u.updateVsyncOnRenderThread()
// This works only for OpenGL.
u.swapBuffersOnRenderThread()
})
}); err != nil {
return err
}
u.bufferOnceSwappedOnce.Do(func() {
u.mainThread.Call(func() {

View File

@ -343,11 +343,11 @@ func (u *userInterfaceImpl) updateImpl(force bool) error {
w, h := u.outsideSize()
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
}
} 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
}
}

View File

@ -331,7 +331,7 @@ func (u *userInterfaceImpl) update() error {
}()
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 nil

View File

@ -121,13 +121,11 @@ func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error {
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
}
u.renderThread.Call(func() {
u.egl.swapBuffers()
})
}
})