Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Cannot enable vsync in a non-fullscreen window covering the entire screen #1267
First, a clarification of terms:
GLFW's definition of windowed fullscreen mode, as per documentation, involves selecting the current video mode for window creation and passing a monitor parameter to glfwCreateWindow. This creates an actual fullscreen window that is faster to switch to since it doesn't involve a display mode change. However, this does not conform to the typical definition of "windowed fullscreen mode," which is a non-fullscreen borderless window covering the entire screen. The behavior of this type of window is different (at least under Windows), since it does not produce any black flickering, allows other windows to be displayed on top, and allows alt-tabbing more quickly. The primary distinction seems to occur based on whether glfwCreateWindow was passed a "monitor" parameter or not: passing the monitor parameter results in a fullscreen display, and omitting results in a windowed display.
Now that I have made this distinction, I can report that under Windows 7 (possibly Windows 8+ as well, I can't test it), it seems to be impossible to activate vsync with a non-fullscreen window covering the entire screen. In this code, GLFW seems to ignore the vsync setting if a monitor parameter has been provided and Windows compositing is enabled. This is under the assumption that Windows DWM will be forcing vsync anyway. However, if the window covers the entire screen, Windows 7 (and possibly Windows 8+) do not actually composite the window with the DWM. Therefore the vsync setting is being ignored by GLFW and not provided by Windows, making it impossible to activate.
This can be worked around by making sure the window's size does not quite match the display mode (i.e. adding a 1px tall gap at the bottom of the window). This forces the DWM to composite and provides vsync. However, that is a rather ugly solution. This is an unfortunate problem overall, since the preferred display mode for my game would be a non-fullscreen window covering the entire screen, but I also need vsync to work.
As further clarification: I am aware that GLFW intentionally disables vsync under Windows while using windowed mode because of interference/stuttering introduced by using vsync and DWM at the same time. My issue boils down to the idea that DWM is not necessarily in use for all windowed displays. Windows 7 does not seem to composite and provide vsync if the window covers the entire screen. This leaves no way to enable vsync with what should be a popular and useful display mode.
I would propose detecting whether the window is covering the entire screen, and if so, do not discard the vsync setting. If this would prove unreliable somehow, an override which allows forced vsync would be acceptable.
I do apologise, I didn't notice the link.
Do I understand correctly, that if you set vsync prior to going
To be honest, this does sound like a bug to me. I also wonder why there is a
I had not thought of that before, but you're right.
If I enable vsync before creating the window, it works, even without being in fullscreen mode. I don't understand quite why this works, but it does. This is the only way I can get vsync enabled without also using fullscreen display. Interestingly, if I combine this with the 1-pixel-gap workaround, this presumably means I would be using vsync together with DWM, but I do not get any stuttering on my setup.
If I attempt to re-enable vsync after window creation, the setting will be ignored.
So, the "no vsync if composition is enabled" hack can be bypassed by setting vsync before window creation. This should probably also be considered a bug, but at the moment, it's a preferable workaround compared to the 1px gap method.
EDIT: After further testing, it seems to hinge on whether vsync is set before or after calling glfwMakeContextCurrent. For non-fullscreen windows, enabling vsync just before it works, and enabling vsync just after it fails. Perhaps glfw is unable to detect whether desktop composition is enabled before the context is made current?