When responses to window refresh take too long

I would like to check if my understanding is right.

When I run GLFW with OpenGL on Linux, I have to respond to “refresh” (or “move” /"resize) callbacks to repaint the window. If I don’t do this in a timely manner, I get flicker or corrupt looking contents. If I am running a single threaded app and my response takes too long, maybe the drawing is too slow and exceeds the screen refresh rate, then flicker is unavoidable. This seems basic, but I could be overlooking something. But if this is true, this would mean, that for slow redraws I must be using some multi-threaded setup. Is this true ?

Hi & welcome to the GLFW forums!

Please take a look at the example code in the documentation, along with the GLFW examples the GLFW CMake Starter. This shows the basics of a GLFW application.

From these you’ll notice that you don’t need to respond to “refresh” or “resize” callbacks - the application should run a render loop calling either glfwPollEvents if you want to animate/redraw without waiting for input or glfwWaitEvents if you want to wait for input before re-drawing.

You shouldn’t get flickering if your render time is longer than the refresh time, because OpenGL draws to a backbuffer whilst the front buffer is being displayed, then swaps these when glfwSwapBuffers is called.

Very well, lets use the “boing.c” demo as an example. When I put in a delay before the glfwSwapBuffers(window); and resize the window, I get a lot of flicker.

       /* Swap buffers */
       {
          struct timespec  delay = { 0, 1 / 60.0 * 1000L * 1000 * 1000 };
          nanosleep( &delay, NULL);
       }
       glfwSwapBuffers(window);

To me that’s not unexpected as I wrote in the initial question.

The resize is done by the window manager on linux (a separate process) My understanding is that it’s up to the app to provide the window contents in a timely manner (what timely is exactly I don’t know). The framebuffer size is different due to the resize, so a new framebuffer must be filled with contents. As I see black in the flicker, I assume the old framebuffer has been invalidated and cleared already.

During resizing the exact behaviour of the backbuffer is presented depends on the OS/Window Manager/Driver and this isn’t something developers have explicit control over, so if you are unable to render during resizing there could indeed be some issues. Note that on Win32 there is currently an open issue with being able to process messages during a resize, as Windows blocks the message queue during this operation:

If your rendering is too slow, multithreading won’t help alleviate any of these issues.

So we agree, that flicker is unavoidable during resize in a single threaded scenario, if the drawing code takes too long. We disagree on whether that’s fixable with threads, but that’s OK!

What would be interesting to know, if it’s possible to determine the amount of time available for the redraw. For example one might assume, that glfwSwapInterval(1); guarantees one frame worth of time.

But if the resize message from the OS could arrive towards the end of the frame, it would reduce the available render time. I would like to learn about real life experiences and solutions. Other OpenGL programmer must have run into this ?!

When I originally stated You shouldn’t get flickering if your render time is longer than the refresh time I should have clarified this was if your window size was constant.

Flickering is not quite ‘unavoidable’ since the OS/Window Manager/Driver may not exhibit this (it could for example rescale the content). Additionally I would not describe what I’ve seen as flickering, but this is somewhat subjective.

glfwSwapInterval(1) does not guarantee that the rendering will take one frame - it requests that the buffer swap does not occur immediately on render completion but when the next display refresh occurs. So with 60Hz refresh if your rendering takes longer than 1/60s (~16ms) then you get the buffer swapping at the next refresh time of 2/60s or 30Hz. However, when running in a window some OS/Window Manager/Driver combinations do not honor refresh rate requests.

If your rendering is slower than your refresh rate then you will have frames during resizing where the window size is not equal to the last rendered framebuffer size, which will potentially produce visual issues. To resolve these you need your rendering to be faster than the refresh rate to start with, at which point multithreading the rendering and event loop may help reduce the residual issues which remain due to input timing.

In my case I simply ignore this issue - if the user is resizing or moving the window they are not interacting with the content so I don’t worry about it. For fullscreen OpenGL apps this obviously also isn’t an issue.