Skip to content

Commit

Permalink
uidriver/glfw: Bug fix: SetVsyncEnabled(false) did not work before th…
Browse files Browse the repository at this point in the history
…e main loop

Fixes #1197
  • Loading branch information
hajimehoshi committed Jun 14, 2020
1 parent be54f1d commit 7873563
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 32 deletions.
2 changes: 2 additions & 0 deletions examples/windowsize/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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")
Expand Down
95 changes: 64 additions & 31 deletions internal/uidriver/glfw/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type UserInterface struct {

initMonitor *glfw.Monitor
initTitle string
initVsync bool
initFullscreenWidthInDP int
initFullscreenHeightInDP int
initFullscreen bool
Expand All @@ -71,6 +72,8 @@ type UserInterface struct {
initScreenTransparent bool
initIconImages []image.Image

vsyncInited bool

reqWidth int
reqHeight int

Expand All @@ -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,
}
)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion internal/uidriver/glfw/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 7873563

Please sign in to comment.