Dumping what I debugged so far: When the window is maximized or restored, Qt renders everything twice: * As reaction to the Expose event, followed by glXSwapBuffers. * As reaction to some QTimer event, NOT followed by glXSwapBuffers! When using DRI2, Mesa reacts to the DRI2_InvalidateBuffers X11 event as soon as it is received and resizes the framebuffer at the beginning of next OpenGL call. When using DRI3, Mesa waits for first OpenGL call after glXSwapBuffers, then it retrieves events and if there was PresentConfigureNotify, it resizes the framebuffer. So the difference is that DRI2 is willing to resize the framebuffer at any point, DRI3 waits for the buffer swap. I have searched whether it is intentional and so far I have the impression that it is, although I did not find it anywhere explicitly stated. So this is what happens when maximizing and restoring the qmlscene window: * Start: window is small, framebuffer is small * Maximize clicked * PresentConfigureNotify delivered (queued in xcb) * Expose delivered - Qt will redraw, Mesa retrieves the event during the first OpenGL call and resizes the framebuffer -> Qt draws properly into the big framebuffer * Qt calls glXSwapBuffers -> the big framebuffer is delivered to the big window * QTimer event - Qt will draw again, but does not call glXSwapBuffers! -> nothing is delivered to the window * Restore clicked * PresentConfigureNotify delivered (queued in xcb) * Expose delivered - Qt will redraw, since there was no glXSwapBuffers, it is still drawing the "same" frame and the framebuffer is not resized. -> Qt draws small red rectangle into big framebuffer. * Qt calls glXSwapBuffers -> the big framebuffer is delivered to the small window, we see the wrong part of it which was cleared white * QTimer event -> Qt will draw again. This is the first OpenGL call after a swap, so the framebuffer is resized to the small size. -> Qt draws properly into the small framebuffer * No glXSwapBuffers is called! -> nothing is delivered to the window If you maximize & restore repeatedly the issue continues because the missing swap keeps the framebuffer resize delayed. If any other update repaints the window, it gets fixed until the next maximize & restore (or restore & maximize). I have not yet investigated why Qt repaints twice and why it does not call glXSwapBuffers the second time.