uidriver/glfw: Bug fix: SetVsyncEnabled(false) did not work before the main loop

Fixes #1197
This commit is contained in:
Hajime Hoshi 2020-06-14 11:50:58 +09:00
parent be54f1d33c
commit 7873563667
3 changed files with 67 additions and 32 deletions

View File

@ -61,6 +61,7 @@ var (
flagAutoAdjusting = flag.Bool("autoadjusting", false, "make the game screen auto-adjusting")
flagFloating = flag.Bool("floating", false, "make the window floating")
flagMaximize = flag.Bool("maximize", false, "maximize the window")
flagVsync = flag.Bool("vsync", true, "enable vsync")
)
func init() {
@ -409,6 +410,7 @@ func main() {
ebiten.SetWindowResizable(true)
ebiten.MaximizeWindow()
}
ebiten.SetVsyncEnabled(*flagVsync)
if *flagAutoAdjusting {
if *flagLegacy {
log.Println("-autoadjusting flag cannot work with -legacy flag")

View File

@ -56,6 +56,7 @@ type UserInterface struct {
initMonitor *glfw.Monitor
initTitle string
initVsync bool
initFullscreenWidthInDP int
initFullscreenHeightInDP int
initFullscreen bool
@ -71,6 +72,8 @@ type UserInterface struct {
initScreenTransparent bool
initIconImages []image.Image
vsyncInited bool
reqWidth int
reqHeight int
@ -91,13 +94,13 @@ var (
theUI = &UserInterface{
origPosX: invalidPos,
origPosY: invalidPos,
initVsync: true,
initCursorMode: driver.CursorModeVisible,
initWindowDecorated: true,
initWindowPositionXInDP: invalidPos,
initWindowPositionYInDP: invalidPos,
initWindowWidthInDP: 640,
initWindowHeightInDP: 480,
vsync: true,
}
)
@ -215,6 +218,13 @@ func (u *UserInterface) setInitTitle(title string) {
u.m.RUnlock()
}
func (u *UserInterface) isInitVsyncEnabled() bool {
u.m.RLock()
v := u.initVsync
u.m.RUnlock()
return v
}
func (u *UserInterface) isInitFullscreen() bool {
u.m.RLock()
v := u.initFullscreen
@ -427,7 +437,7 @@ func (u *UserInterface) SetFullscreen(fullscreen bool) {
w, h = u.windowWidth, u.windowHeight
return nil
})
u.setWindowSize(w, h, fullscreen, u.vsync)
u.setWindowSize(w, h, fullscreen)
}
func (u *UserInterface) IsFocused() bool {
@ -458,23 +468,37 @@ func (u *UserInterface) SetVsyncEnabled(enabled bool) {
// 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.vsync = enabled
u.initVsync = enabled
u.m.Unlock()
return
}
var w, h int
_ = u.t.Call(func() error {
w, h = u.windowWidth, u.windowHeight
if !u.vsyncInited {
u.m.Lock()
u.initVsync = enabled
u.m.Unlock()
return nil
}
u.vsync = enabled
u.updateVsync()
return nil
})
u.setWindowSize(w, h, u.isFullscreen(), enabled)
}
func (u *UserInterface) IsVsyncEnabled() bool {
u.m.RLock()
r := u.vsync
u.m.RUnlock()
return r
if !u.isRunning() {
return u.isInitVsyncEnabled()
}
var v bool
_ = u.t.Call(func() error {
if !u.vsyncInited {
v = u.isInitVsyncEnabled()
return nil
}
v = u.vsync
return nil
})
return v
}
func (u *UserInterface) CursorMode() driver.CursorMode {
@ -688,7 +712,7 @@ func (u *UserInterface) run(context driver.UIContext) error {
ww, wh := u.getInitWindowSize()
ww = int(u.toDeviceDependentPixel(float64(ww)))
wh = int(u.toDeviceDependentPixel(float64(wh)))
u.setWindowSize(ww, wh, u.isFullscreen(), u.vsync)
u.setWindowSize(ww, wh, u.isFullscreen())
}
// Set the window size and the window position in this order on Linux or other UNIX using X (#1118),
@ -734,7 +758,7 @@ func (u *UserInterface) updateSize(context driver.UIContext) {
w, h = u.windowWidth, u.windowHeight
return nil
})
u.setWindowSize(w, h, u.isFullscreen(), u.vsync)
u.setWindowSize(w, h, u.isFullscreen())
sizeChanged := false
_ = u.t.Call(func() error {
@ -781,7 +805,7 @@ func (u *UserInterface) update(context driver.UIContext) error {
w, h = u.window.GetSize()
return nil
})
u.setWindowSize(w, h, true, u.vsync)
u.setWindowSize(w, h, true)
u.setInitFullscreen(false)
}
@ -821,7 +845,7 @@ func (u *UserInterface) update(context driver.UIContext) error {
return nil
})
if w != 0 || h != 0 {
u.setWindowSize(w, h, u.isFullscreen(), u.vsync)
u.setWindowSize(w, h, u.isFullscreen())
}
_ = u.t.Call(func() error {
u.reqWidth = 0
@ -884,11 +908,11 @@ func (u *UserInterface) swapBuffers() {
}
}
func (u *UserInterface) setWindowSize(width, height int, fullscreen bool, vsync bool) {
func (u *UserInterface) setWindowSize(width, height int, fullscreen bool) {
windowRecreated := false
_ = u.t.Call(func() error {
if u.windowWidth == width && u.windowHeight == height && u.isFullscreen() == fullscreen && u.vsync == vsync && u.lastDeviceScaleFactor == u.deviceScaleFactor() {
if u.windowWidth == width && u.windowHeight == height && u.isFullscreen() == fullscreen && u.lastDeviceScaleFactor == u.deviceScaleFactor() {
return nil
}
@ -899,7 +923,6 @@ func (u *UserInterface) setWindowSize(width, height int, fullscreen bool, vsync
height = 1
}
u.vsync = vsync
u.lastDeviceScaleFactor = u.deviceScaleFactor()
// To make sure the current existing framebuffers are rendered,
@ -1001,21 +1024,12 @@ func (u *UserInterface) setWindowSize(width, height int, fullscreen bool, vsync
u.windowWidth = width
u.windowHeight = height
if u.Graphics().IsGL() {
// SwapInterval is affected by the current monitor of the window.
// This needs to be called at least after SetMonitor.
// Without SwapInterval after SetMonitor, vsynch doesn't work (#375).
//
// 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 {
glfw.SwapInterval(1)
} else {
glfw.SwapInterval(0)
}
if !u.vsyncInited {
// Initialize vsync after SetMonitor is called. See the comment in updateVsync.
u.vsync = u.isInitVsyncEnabled()
u.updateVsync()
u.vsyncInited = true
}
u.Graphics().SetVsyncEnabled(vsync)
u.toChangeSize = true
return nil
@ -1028,6 +1042,25 @@ func (u *UserInterface) setWindowSize(width, height int, fullscreen bool, vsync
}
}
// updateVsync must be called on the main thread.
func (u *UserInterface) updateVsync() {
if u.Graphics().IsGL() {
// SwapInterval is affected by the current monitor of the window.
// This needs to be called at least after SetMonitor.
// Without SwapInterval after SetMonitor, vsynch doesn't work (#375).
//
// 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 {
glfw.SwapInterval(1)
} else {
glfw.SwapInterval(0)
}
}
u.Graphics().SetVsyncEnabled(u.vsync)
}
// currentMonitor returns the monitor most suitable with the current window.
//
// currentMonitor must be called on the main thread.

View File

@ -238,7 +238,7 @@ func (w *window) SetSize(width, height int) {
}
ww := int(w.ui.toDeviceDependentPixel(float64(width)))
wh := int(w.ui.toDeviceDependentPixel(float64(height)))
w.ui.setWindowSize(ww, wh, w.ui.isFullscreen(), w.ui.vsync)
w.ui.setWindowSize(ww, wh, w.ui.isFullscreen())
}
func (w *window) SetIcon(iconImages []image.Image) {