From 2503323557f2e4b65b991c73f3bf0c72292447ef Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Thu, 22 Jul 2021 23:55:26 +0900 Subject: [PATCH] internal/driver: Add FPSMode Updates #1556 --- internal/driver/ui.go | 11 ++++++-- internal/uidriver/glfw/ui.go | 46 +++++++++++++++++----------------- internal/uidriver/js/ui_js.go | 13 +++++----- internal/uidriver/mobile/ui.go | 6 ++--- run.go | 8 ++++-- 5 files changed, 47 insertions(+), 37 deletions(-) diff --git a/internal/driver/ui.go b/internal/driver/ui.go index 3f6a205eb..7c9ef06fb 100644 --- a/internal/driver/ui.go +++ b/internal/driver/ui.go @@ -54,8 +54,8 @@ type UI interface { IsRunnableOnUnfocused() bool SetRunnableOnUnfocused(runnableOnUnfocused bool) - IsVsyncEnabled() bool - SetVsyncEnabled(enabled bool) + FPSMode() FPSMode + SetFPSMode(mode FPSMode) IsScreenTransparent() bool SetScreenTransparent(transparent bool) @@ -98,3 +98,10 @@ type Window interface { SetClosingHandled(handled bool) IsClosingHandled() bool } + +type FPSMode int + +const ( + FPSModeVsyncOn FPSMode = iota + FPSModeVsyncOffMaximum +) diff --git a/internal/uidriver/glfw/ui.go b/internal/uidriver/glfw/ui.go index b6d0f75a2..5d73f3b8e 100644 --- a/internal/uidriver/glfw/ui.go +++ b/internal/uidriver/glfw/ui.go @@ -69,7 +69,7 @@ type UserInterface struct { origPosX int origPosY int runnableOnUnfocused bool - vsync bool + fpsMode driver.FPSMode iconImages []image.Image cursorShape driver.CursorShape windowClosingHandled bool @@ -90,7 +90,7 @@ type UserInterface struct { initFullscreenHeightInDP int initTitle string - initVsync bool + initFPSMode driver.FPSMode initFullscreen bool initCursorMode driver.CursorMode initWindowDecorated bool @@ -104,7 +104,7 @@ type UserInterface struct { initScreenTransparent bool initFocused bool - vsyncInited bool + fpsModeInited bool input Input iwindow window @@ -133,7 +133,7 @@ var ( maxWindowHeightInDP: glfw.DontCare, origPosX: invalidPos, origPosY: invalidPos, - initVsync: true, + initFPSMode: driver.FPSModeVsyncOn, initCursorMode: driver.CursorModeVisible, initWindowDecorated: true, initWindowPositionXInDP: invalidPos, @@ -141,7 +141,7 @@ var ( initWindowWidthInDP: 640, initWindowHeightInDP: 480, initFocused: true, - vsync: true, + fpsMode: driver.FPSModeVsyncOn, } ) @@ -314,9 +314,9 @@ func (u *UserInterface) setInitTitle(title string) { u.m.RUnlock() } -func (u *UserInterface) isInitVsyncEnabled() bool { +func (u *UserInterface) getInitFPSMode() driver.FPSMode { u.m.RLock() - v := u.initVsync + v := u.initFPSMode u.m.RUnlock() return v } @@ -599,41 +599,41 @@ func (u *UserInterface) IsRunnableOnUnfocused() bool { return u.isRunnableOnUnfocused() } -func (u *UserInterface) SetVsyncEnabled(enabled bool) { +func (u *UserInterface) SetFPSMode(mode driver.FPSMode) { if !u.isRunning() { // In general, m is used for locking init* values. // m is not used for updating vsync in setWindowSize so far, but // it should be OK since any goroutines can't reach here when // the game already starts and setWindowSize can be called. u.m.Lock() - u.initVsync = enabled + u.initFPSMode = mode u.m.Unlock() return } _ = u.t.Call(func() error { - if !u.vsyncInited { + if !u.fpsModeInited { u.m.Lock() - u.initVsync = enabled + u.initFPSMode = mode u.m.Unlock() return nil } - u.vsync = enabled + u.fpsMode = mode u.updateVsync() return nil }) } -func (u *UserInterface) IsVsyncEnabled() bool { +func (u *UserInterface) FPSMode() driver.FPSMode { if !u.isRunning() { - return u.isInitVsyncEnabled() + return u.getInitFPSMode() } - var v bool + var v driver.FPSMode _ = u.t.Call(func() error { - if !u.vsyncInited { - v = u.isInitVsyncEnabled() + if !u.fpsModeInited { + v = u.getInitFPSMode() return nil } - v = u.vsync + v = u.fpsMode return nil }) return v @@ -956,10 +956,10 @@ func (u *UserInterface) update() (float64, float64, bool, error) { // Initialize vsync after SetMonitor is called. See the comment in updateVsync. // Calling this inside setWindowSize didn't work (#1363). - if !u.vsyncInited { - u.vsync = u.isInitVsyncEnabled() + if !u.fpsModeInited { + u.fpsMode = u.getInitFPSMode() u.updateVsync() - u.vsyncInited = true + u.fpsModeInited = true } outsideWidth, outsideHeight, outsideSizeChanged := u.updateSize() @@ -1326,13 +1326,13 @@ func (u *UserInterface) updateVsync() { // TODO: (#405) If triple buffering is needed, SwapInterval(0) should be called, // but is this correct? If glfw.SwapInterval(0) and the driver doesn't support triple // buffering, what will happen? - if u.vsync { + if u.fpsMode == driver.FPSModeVsyncOn { glfw.SwapInterval(1) } else { glfw.SwapInterval(0) } } - u.Graphics().SetVsyncEnabled(u.vsync) + u.Graphics().SetVsyncEnabled(u.fpsMode == driver.FPSModeVsyncOn) } // currentMonitor returns the current active monitor. diff --git a/internal/uidriver/js/ui_js.go b/internal/uidriver/js/ui_js.go index f49828ffd..9afb412a7 100644 --- a/internal/uidriver/js/ui_js.go +++ b/internal/uidriver/js/ui_js.go @@ -49,7 +49,7 @@ func driverCursorShapeToCSSCursor(cursor driver.CursorShape) string { type UserInterface struct { runnableOnUnfocused bool - vsync bool + fpsMode driver.FPSMode running bool initFocused bool cursorMode driver.CursorMode @@ -67,7 +67,6 @@ type UserInterface struct { var theUI = &UserInterface{ runnableOnUnfocused: true, sizeChanged: true, - vsync: true, initFocused: true, } @@ -136,12 +135,12 @@ func (u *UserInterface) IsRunnableOnUnfocused() bool { return u.runnableOnUnfocused } -func (u *UserInterface) SetVsyncEnabled(enabled bool) { - u.vsync = enabled +func (u *UserInterface) SetFPSMode(mode driver.FPSMode) { + u.fpsMode = mode } -func (u *UserInterface) IsVsyncEnabled() bool { - return u.vsync +func (u *UserInterface) FPSMode() driver.FPSMode { + return u.fpsMode } func (u *UserInterface) CursorMode() driver.CursorMode { @@ -295,7 +294,7 @@ func (u *UserInterface) loop(context driver.UIContext) <-chan error { errCh <- err return } - if u.vsync { + if u.fpsMode == driver.FPSModeVsyncOn { requestAnimationFrame.Invoke(cf) } else { setTimeout.Invoke(cf, 0) diff --git a/internal/uidriver/mobile/ui.go b/internal/uidriver/mobile/ui.go index e391dd19a..f95a4e20e 100644 --- a/internal/uidriver/mobile/ui.go +++ b/internal/uidriver/mobile/ui.go @@ -404,11 +404,11 @@ func (u *UserInterface) SetRunnableOnUnfocused(runnableOnUnfocused bool) { // Do nothing } -func (u *UserInterface) IsVsyncEnabled() bool { - return true +func (u *UserInterface) FPSMode() driver.FPSMode { + return driver.FPSModeVsyncOn } -func (u *UserInterface) SetVsyncEnabled(enabled bool) { +func (u *UserInterface) SetFPSMode(mode driver.FPSMode) { // Do nothing } diff --git a/run.go b/run.go index ddb33f33e..ef36584d9 100644 --- a/run.go +++ b/run.go @@ -328,7 +328,7 @@ func DeviceScaleFactor() float64 { // // IsVsyncEnabled is concurrent-safe. func IsVsyncEnabled() bool { - return uiDriver().IsVsyncEnabled() + return uiDriver().FPSMode() == driver.FPSModeVsyncOn } // SetVsyncEnabled sets a boolean value indicating whether @@ -346,7 +346,11 @@ func IsVsyncEnabled() bool { // // SetVsyncEnabled is concurrent-safe. func SetVsyncEnabled(enabled bool) { - uiDriver().SetVsyncEnabled(enabled) + if enabled { + uiDriver().SetFPSMode(driver.FPSModeVsyncOn) + } else { + uiDriver().SetFPSMode(driver.FPSModeVsyncOffMaximum) + } } // MaxTPS returns the current maximum TPS.