Correct order for making fullscreen with poll events and window refresh, etc


#1

My project has an option to toggle between fullscreen and windowed mode through the user interface. The main problem is when I go into fullscreen mode, I momentarily see the window mid-transition to fullscreen (I can briefly see a windows 7 style title bar, random glitches, etc). This is not a major issue, but solving it will help me understand the interaction between GLFW and my own code better. I’m on Windows 10 and Nvidia (latest for both). There are no GL or GLFW errors. The application is single-threaded. I have windowWidth, windowHeight, and goToFullscreen global variables.

My loop looks like:

Update

  • updates core code and UI with windowWidth and windowHeight. sets goToFullscreen to either true or false.

Render

  • sets viewport to windowWidth and windowHeight and renders the scene

glfwSwapBuffers

glfwPollEvents

  • can trigger GLFWwindowrefreshfun (inside which calls Render and glfwSwapBuffers again, useful for any type of window resize, not just fullscreen)

MakeFullscreen

  • if goToFullscreen is true, calls glfwSetWindowMonitor(glfwWindow, monitor, 0, 0, videoMode->width, videoMode->height, videoMode->refreshRate);
  • automatically triggers GLFWframebuffersizefun, which updates windowWidth and windowHeight

RendererResize

  • called whenever windowWidth or windowHeight changes from previous frame, including when resizing window manually, or when graphics quality changes (doesn’t affect UI):
  • glFinish(probably unnecessary)
  • internal GL FBO/texture resize

Here’s a printout during a fullscreen (starting and ending with random normal frames):

– frame count 677 –
Update at 1280 720
Render at 1280 720
glfwSwapBuffers
glfwPollEvents
– frame count 678 –
Update at 1280 720
Render at 1280 720
glfwSwapBuffers
glfwPollEvents
MakeFullscreen
GLFWframebuffersizefun at 1296 759
GLFWframebuffersizefun at 1920 1080
RenderResize at 1920 1080
– frame count 679 –
Update at 1920 1080
Render at 1920 1080
glfwSwapBuffers
glfwPollEvents
GLFWwindowrefreshfun at 1920 1080 (*1)
Render at 1920 1080
glfwSwapBuffers
– frame count 680 –
Update at 1920 1080
Render at 1920 1080
glfwSwapBuffers
glfwPollEvents

When I move the MakeFullscreen and RenderResize checks BEFORE the glfwPollEvents, I get:

– frame count 363 –
Update at 1280 720
Render at 1280 720
glfwSwapBuffers
glfwPollEvents
– frame count 364 –
Update at 1280 720
Render at 1280 720
glfwSwapBuffers
MakeFullscreen
GLFWframebuffersizefun at 1296 759
GLFWframebuffersizefun at 1920 1080
RenderResize at 1920 1080
glfwPollEvents
GLFWwindowrefreshfun at 1920 1080
Render at 1920 1080 (*2)
glfwSwapBuffers
– frame count 365 –
Update at 1920 1080
Render at 1920 1080
glfwSwapBuffers
glfwPollEvents

Both versions I can see the glitchy mid-transition state of the window for an instant. The first version effectively ignores the refresh callback (*1) because the glfwPollEvents that triggers it happens on the next frame. I’m using this version because Update and Render are always in sync with window size. The second version is cleaner but has an intermediate Render that uses out-of-date values from Update (*2), causing my UI and other things to pop for a frame. The closer refresh seems to make no difference. The glitchy effect is more pronounced in Debug mode where CPU loads are heavier, which might be why I don’t see the problem with GLFW examples.

Overall, I think I have some misconceptions about fullscreen/windowed, framebuffer size and refresh callbacks, swapbuffers, and polling. Or maybe it’s a problem outside of my code or GLFW?

Side questions:

  1. Why is there a 1296x759 resize?
  2. Why does GLFW recommend calling glfwPollEvents after glfwSwapbuffers? A loop of: {PollEvents, Update, Render, SwapBuffers, CheckClose} doesn’t seem functionally different than {Update, Render, SwapBuffers, PollEvents, CheckClose} except for the first and last frame. The documentation says:

GLFW needs to communicate regularly with the window system both in order to receive events and to show that the application hasn’t locked up. Event processing must be done regularly while you have visible windows and is normally done each frame after buffer swapping.


#2

Some answers:

  1. I don’t know why you’re seeing a 1296x759 resize. I don’t on the systems I’ve tested on, though I don’t have a Windows 10 machine with NVIDIA GPU installed at the moment.
  2. The glfwPollEvents function can stall on some systems as per documentation: “On some platforms, a window move, resize or menu operation will cause event processing to block.” So it’s a good idea to call it after having swapped the last thing you rendered to the screen. You can also put rendering on a separate thread, though this is obviously more complicated. Putting it first is as you say logically similar, and it’s OK to do this.

I don’t have an answer as to how to achieve a clean fullscreen resize with GLFW or OpenGL. On my AMD GPU with Windows 10 I always get a black screen flicker during transition, and neither GLFW or my app is doing a clear to black so I suspect this is an OpenGL driver issue.


#3

Because currently removal of window decorations and resizing to fit the monitor are done separately. It can be done in a single operation but it’ll take some internal restructuring.


#4

Quick note:

Using the github master code for GLFW 3.3 and the glfwSetWindowAttrib I could set the decorated style to false when going fullscreen and reverting on going windowed, and this made window switching slightly nicer.

This could provide a workaround without changing GLFW code if you need improved transitions.


#5

Doug, interesting tip but it doesn’t work all the time.

I got master. I did glfwSetWindowAttrib(glfwWindow, GLFW_DECORATED, GLFW_FALSE) before glfwSetWindowMonitor for fullscreen and after for windowed. I can still see the blue windows 7 style title bar occasionally, hard to say if more or less frequently than before. When I manually step through the code the windows 10 title bar goes away after the attrib call, but it’s difficult to see what’s going on with the actual fullscreen action when the debugger is active.


#6

I can briefly see a windows 7 style title bar

I have definitely seen this happen. I think I even debugged it and it had something to do with use of styles, but don’t quote me on that. Sadly, I can’t remember why I didn’t report this issue.


#7

@IanLilleyT Can I ask you if your Windows is up-to-date? I tried reproducing the windows-7-style-title-bar thing, but couldn’t. This thing could definitely be affected by Windows update, because recently they seem to have broken the window icon - I have raised an issue in GLFW repo for this: 1163


#8

I’m on Windows 10, version 1709. I actually did a windows update in the middle of investigating this problem, but it made no difference. What do you mean by use of styles?


#9

I mean Windows API styles, for example WS_POPUP.


#10

The Windows 7 style menu bar only popped into existante during full screen
switch when I used latest GLFW. Released versions did not do this for me.


#11

@dougbinks Do you know how to exactly reproduce it?


#12

Yes, get latest from git hub and switch from wondowed to fullscreen.

I may have time to investigate why this happens later buy am busy for the
next few days.


#13

Well, I’ve done this but it is not happening.


#14

The fix for the double resize event has been merged.