I confess I did not understand much about the problem. Is it about variable refresh rates? If I think a message _VARIABLE_REFRESH is received on the Notify event.
Or https://docs.gtk.org/gdk3/class.FrameClock.html I also did an EGL version in place of GLX: https://github.com/openjdk/jfx/pull/1381 -- Thiago Em qui., 2 de out. de 2025 às 06:59, Michael Zucchi <[email protected]> escreveu: > > All, > > Unfortunately I'm still unable to login to oracle.com to sign any OCA, > so the attached patch is just FYI. It seemed to create my account ok but > afterward confirming my email it redirected me to a page without being > logged in, and then any attempt to login fails. Firefox 140.x ESR using > a default profile of I reserve for finicky sites. Any suggestions? > > Regardless, I spent a few days poking around including installing > ubuntu 24 lts, and building javafx on windows 10 (in a vm) to see what > was supposed to be happening. > > Unlike D3D's SwapChain.Present(flags=0), glXSwapBuffers() is a not a > synchronous call[1]. It only inserts a synchronisation point into the > command queue which will block any calls that try to render to the back > buffer before it is swapped from the front - which means it > 'effectively' blocks if there's a backlog, but only at some unknown > point in the future (depending on how many buffers the driver sets up). > > As per [1] and the specification calling glFinish() immediately after > glXSwapBuffers() will synchronise to the display and make it behave > similarly to D3D's SwapChain.Present(0), but with GLX this only works > for a single window. Each additional window adds another whole frame so > they all run at 1/N the target rate. > > I tried a number of approaches, some of them follow. I was focusing on > making it work on both a single and multiple window application, and > with consistent pulse rates. > > "vsync" timers > -------------- > > One solution is to change the GtkGlass backend to export a non-zero > staticScreen_getVideoRefreshPeriod() which will cause Quantum to > assume the clock is accurate to vsync. And then implement something > that is either accurate or close-enough. > > I've tried a few different variations: > > 0. Use gdk_timeout but use a dynamic timeout each frame based on the > reported frame-rate, and using logic to maintain long-term > accuracy. > > Pros: No new mechanisms or races or build changes. > Fairly accurate over the lont term. > Can adapt if the monitor refresh rate changes at runtime. > Avoids vsyncHint() logic. > Cons: Jittery due to only millisecond precision and g_mainloop. > gdk_monitor_get_refresh_rate() must be correct (and exist) > > 1. As with the Mac backend, Gtk GlassTimer starts a thread that runs > it's own vblank timing. Use a hidden double-buffered Window and > call glXSwapBuffer() then glFinish() on a local context before the > callback. > > This works very well for X11 but breaks on XWayland due to [2] where > it runs at 'jittery 60Hz' regardless of the actual frame-rate because > wayland and by extension Xwayland doesn't think hidden windows should > know about vsync. > > Pros: For X11 Correct and accurate, should be well supported. > Avoids vsyncHint() logic. > Cons: Requires linking to libGL in gtk3glass. > Complicates errors/fallback a bit. > gdk_monitor_get_refresh_rate() must be correct (and exist) > XWayland is broken. > It is unclear whether the timer callback needs to run on the > g_mainloop, it doesn't seem to matter. > > 2. As with the Mac backend, Gtk GlassTimer starts a thread that runs > it's own timing. This time using clock_gettime() and usleep() and > some logic to avoid drift, handle suspend, and keep consistent > frame timing. > > This works quite well as long as GdkMonitor returns an accurate frame > rate. > > Pros: Simple, not perfect timing but fairly accurate in practice. > Avoids syncHint() logic. > Could just be implemented in Java if > GlassApplication.staticScreen_getVideoRefreshPeriod() is > accurate, although a frame-rate might be more useful. > Cons: Complicates errors/fallback a bit (if in native) > gdk_monitor_get_refresh_rate() must be correct (and exist) > It is unclear whether the timer callback needs to run on the > g_mainloop, it doesn't seem to matter. > > glFinish at a different spot > ---------------------------- > > After trying all of the above and reading some more internet forums and > articles I tried another approach: run a glFinish() once, after all > GlassScene's have been rendered. > > Pros: Seems to work reliably and accurately. > Pretty simple patch that doesn't touch much. > Cons: Better Gtk GlassTimer would be nice. > > Comments > -------- > > A better timer interface and for the animation.pulse value would be > nice, perhaps internally fps in decimal fixed-point like GdkMonitor > uses. A better Gtk GlassTimer using that, plus GLX syncing after > PaintCollector.renderAll(). > > Just for interest's sake I've attached a WIP patch of the last > suggestion. I thought they might provide more insight but I've attached > some frame-time plots from the various alternatives anyway. Note that > Wayland is on a machine with a frame-rate of 143.88, and the others 59.95. > > Regards, > !Z > > > [1] > > https://community.khronos.org/t/understanding-the-opengl-main-loop-swapbuffers/75593/12 > [2] https://gitlab.freedesktop.org/xorg/xserver/-/issues/631 >
