New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot enable vsync in a non-fullscreen window covering the entire screen #1267

Open
Grimmov opened this Issue May 14, 2018 · 4 comments

Comments

Projects
None yet
3 participants
@Grimmov
Copy link

Grimmov commented May 14, 2018

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.

@Grimmov Grimmov changed the title Issue enabling vsync in non-fullscreen windows covering the entire screen Cannot enable vsync in a non-fullscreen window covering the entire screen May 14, 2018

@ghuser404

This comment has been minimized.

Copy link

ghuser404 commented May 14, 2018

Did you check GLFW code? As far as I remember, it wasn't doing anything special to forbid this. I believe, this is related to how your OpenGL driver works on Windows.

@Grimmov

This comment has been minimized.

Copy link

Grimmov commented May 14, 2018

I believe it is caused by this code, which I linked in my post, which prevents vsync on Windows if using a windowed display and desktop compositing is enabled.

@ghuser404

This comment has been minimized.

Copy link

ghuser404 commented May 14, 2018

I do apologise, I didn't notice the link.

Do I understand correctly, that if you set vsync prior to going non-fullscreen window covering the entire screen, it will persist to when you set it to that?

To be honest, this does sound like a bug to me. I also wonder why there is a // HACK comment.

@Grimmov

This comment has been minimized.

Copy link

Grimmov commented May 14, 2018

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?

@elmindreda elmindreda added the Windows label May 16, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment