# When responses to window refresh take too long

**URL:** <https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899>\
**Category:** support\
**Created:** [July 29, 2021, 7:12pm UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899 "2021-07-29T19:12:15Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![H8J4K2](https://avatars.discourse-cdn.com/v4/letter/h/f05b48/32.png) [@H8J4K2](https://discourse.glfw.org/u/H8J4K2)\
**Post date:** [July 29, 2021, 7:12pm UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/1 "2021-07-29T19:12:15Z")

</div>

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 ?

---

<div class="post-metadata">

**Author:** ![dougbinks](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/dougbinks/32/39_2.png) [@dougbinks](https://discourse.glfw.org/u/dougbinks)\
**Post date:** [July 29, 2021, 9:00pm UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/2 "2021-07-29T21:00:19Z")

</div>

Hi & welcome to the GLFW forums!

Please take a look at the [example code in the documentation](https://www.glfw.org/documentation.html), along with the [GLFW examples](https://github.com/glfw/glfw/tree/master/examples) the [GLFW CMake Starter](https://github.com/juliettef/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.

---

<div class="post-metadata">

**Author:** ![H8J4K2](https://avatars.discourse-cdn.com/v4/letter/h/f05b48/32.png) [@H8J4K2](https://discourse.glfw.org/u/H8J4K2)\
**Post date:** [July 31, 2021, 9:13pm UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/3 "2021-07-31T21:13:34Z")

</div>

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.

```auto
       /* 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.

---

<div class="post-metadata">

**Author:** ![dougbinks](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/dougbinks/32/39_2.png) [@dougbinks](https://discourse.glfw.org/u/dougbinks)\
**Post date:** [August 1, 2021, 11:29am UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/4 "2021-08-01T11:29:50Z")

</div>

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:

> <https://github.com/glfw/glfw/pull/1426>
>
> This change provides workaround for Windows modal event loop while window is bei…ng resized/moved.
> User can continue using their standard "while" event loop in main thread to do updates in their application.
> 
> Change includes two parts:
> 
> \* Move message dispatching in separate fiber. This allows to "break out" the modal event loop. This is done by using timer which fires after 1msec on window resize/move event. After timer fires, the control returns to main code. There is pretty much no performance overhead for switching fibers in this situation.
> 
> \* Handle non-client left mouse click on title bar. Otherwise Windows does not return in DefWindowProc. Easy way to do this is to defer calling DefWindowProc on WM\_NCLBUTTONDOWN message. Wait until user moves mouse (WMNC\_MOUSEMOVE or WM\_MOUSEMOVE) and then deliver original message. For example, exact same thing is done in \[Google Chromium\](https://chromium.googlesource.com/chromium/src/+/master/ui/views/win/hwnd\_message\_handler.cc#3187) source code.
> 
> This fixes issues like #1231, #561, #185.
> 
> To check how this new behavior works - open any example that does some kind of animation in their main loop. For example, \`particles\`. Then try resizing or dragging window. Notice how all animation stops without this change. But with this pull request the animation will smoothly continue updating.

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

---

<div class="post-metadata">

**Author:** ![H8J4K2](https://avatars.discourse-cdn.com/v4/letter/h/f05b48/32.png) [@H8J4K2](https://discourse.glfw.org/u/H8J4K2)\
**Post date:** [August 1, 2021, 11:04pm UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/5 "2021-08-01T23:04:36Z")

</div>

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 ?!

---

<div class="post-metadata">

**Author:** ![dougbinks](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/dougbinks/32/39_2.png) [@dougbinks](https://discourse.glfw.org/u/dougbinks)\
**Post date:** [August 2, 2021, 10:11am UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/6 "2021-08-02T10:11:34Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![michaeljclark](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/michaeljclark/32/590_2.png) [@michaeljclark](https://discourse.glfw.org/u/michaeljclark)\
**Post date:** [January 1, 2022, 11:43pm UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/7 "2022-01-01T23:43:27Z")

</div>

I spent a little bit of time looking into tears during window resizing when using GLFW on Linux with the Intel Mesa driver. I started exploring the extended frame synchronization protocols that have been designed to solve this. I have written a small sample along with documentation that may make it easier to implement GLX XSync extended frame synchronization when using the GLX-based Window system in GLFW. It has so far had testing with NVIDIA on Xorg and Intel on XWayland:

- [GitHub - michaeljclark/glxsync: An example X Windows OpenGL application using GLX and XSync extended frame synchronization](https://github.com/michaeljclark/glxsync)

This email to the Mesa Developers mailing list goes into the background behind the sample:

- [glxsync - explicit frame synchronization sample implementation](https://lists.freedesktop.org/archives/mesa-dev/2021-December/225614.html)

I would consider making patches for GLFW but would like to know if the approach is reasonable first. The reason to make something freestanding and isolated was so that it was easier to debug as it seem easy to get flickers with the Intel Mesa driver if the timing is not just right. I think once the approach is workable it should not be too hard to integrate with GLFW. I am not sure if there is a bug in the issue tracker where one could add these notes or it is appropriate to discuss here.

---

<div class="post-metadata">

**Author:** ![dougbinks](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/dougbinks/32/39_2.png) [@dougbinks](https://discourse.glfw.org/u/dougbinks)\
**Post date:** [January 2, 2022, 1:32pm UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/8 "2022-01-02T13:32:15Z")

</div>

Thanks for this sample work & information!

In future I would recommend starting a new thread (with a link to this one) or a new Github issue for feedback of this type.

I know @mmozeiko has been working on [an improved Win32 resize event handling PR](https://github.com/glfw/glfw/pull/1426), and the design of that may have some bearing on your proposal.

From reading your sample and notes I am personally unable to tell exactly how the PR would work within `GLFW`'s current design without a good deal more time to read it through. The main issue I see is that your event loop directly handles frame rendering via the `submit_frame` function, whereas `GLFW` has no such render callback - client code handles when and how to render and rendering can be on a secondary thread. I am also concerned about potential performance and latency related issues for applications which care less about resizing causing flickering than they do about performance when the window size is fixed (for example games).

One consideration is how much of the sample requires exposure in GLFW code, and how much can be exposed for client code to decide how to use the information. For example, an API which allows the application to synchronize during window resizing along with example code would in my view a better approach than ‘builtin’ `GLFW` synchronization, although making this workable in a cross platform way needs consideration.

---

<div class="post-metadata">

**Author:** ![michaeljclark](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/michaeljclark/32/590_2.png) [@michaeljclark](https://discourse.glfw.org/u/michaeljclark)\
**Post date:** [January 2, 2022, 10:09pm UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/9 "2022-01-02T22:09:16Z")

</div>

Thanks for getting back to me. I will take a look at the resize handling PR.

I think the event loop and `submit_frame` in the example should be able to be abstracted to use [glfwWaitEventsTimeout](https://www.glfw.org/docs/3.3/group__window.html#ga605a178db92f1a7f1a925563ef3ea2cf) and regular draw calls. As long as we can poll with a timeout I think it should work. We have control over the event loop. The _glxsync_ sample is quite deliberately hardcoded because the intention was to isolate the concern so there were no function pointer indirections to reason about while testing as it took quite a bit of iteration to figure out exactly which events were needed and how they should be handled.

The compositor resize sync events need some consideration as to how they would be exposed (or not exposed). It could be via calls to refresh where the frame sync locking magic is done behind the scenes. It actually amounts to locking around swap buffers and some serial numbers from the window manager events. It could suffice to allow a user to hook swap buffers with a before and after callback but ideally, one could hide frame sync from the user altogether and expose it simply as a Hint to enable it (off by default) and the frame sync locking added around `refresh` callbacks and `swap_buffers` if it is enabled.

See this patch where I made a small change after reasoning about the frame sync locking as I added some docs describing the events and locking at each stage, subject to verification of course:

> <https://github.com/michaeljclark/glxsync/commit/1fa5b9cbe38d9095164078ef89de33f57f218fd5>
>
> we can actually move the start of the lock after draw\_frame but before
> swap\_buff…ers because this is when the framebuffer can't be sampled.
> draw\_frame is labeled by the paced XFlush finishing the prior frame.

---

<div class="post-metadata">

**Author:** ![dougbinks](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/dougbinks/32/39_2.png) [@dougbinks](https://discourse.glfw.org/u/dougbinks)\
**Post date:** [January 3, 2022, 3:30pm UTC](https://discourse.glfw.org/t/when-responses-to-window-refresh-take-too-long/1899/10 "2022-01-03T15:30:20Z")

</div>

Note that most applications will likely be using `glfwPollEvents` which does not wait. Applications could combine this with `glfwWaitEventsTimeout` when the window is resizing, but currently `GLFW` only has an API for window resize events which indicate a size has changed, not that it has started/stopped changing so managing this is complex.

Frame sync locking via a hint sounds a valid solution, especially if it only applies during resizing. This could be done within `glfwSwapBuffers` so the only API to expose would be the hint, and as a hint it’s reasonable that some OS’s either wouldn’t need or be able to honour it.
