diff --git a/client/displayservers/Wayland/wayland.c b/client/displayservers/Wayland/wayland.c index f7d95769..2c6b6e85 100644 --- a/client/displayservers/Wayland/wayland.c +++ b/client/displayservers/Wayland/wayland.c @@ -172,7 +172,7 @@ struct LG_DisplayServerOps LGDS_Wayland = .glSetSwapInterval = waylandGLSetSwapInterval, .glSwapBuffers = waylandGLSwapBuffers, #endif - .signalNextFrame = waylandSignalNextFrame, + .waitFrame = waylandWaitFrame, .guestPointerUpdated = waylandGuestPointerUpdated, .setPointer = waylandSetPointer, .grabPointer = waylandGrabPointer, diff --git a/client/displayservers/Wayland/wayland.h b/client/displayservers/Wayland/wayland.h index 56c72abb..e4ff9e4c 100644 --- a/client/displayservers/Wayland/wayland.h +++ b/client/displayservers/Wayland/wayland.h @@ -176,6 +176,8 @@ struct WaylandDSState struct wl_list surfaceOutputs; // SurfaceOutput::link bool useFractionalScale; + LGEvent * frameEvent; + struct wl_list poll; // WaylandPoll::link struct wl_list pollFree; // WaylandPoll::link LG_Lock pollLock; @@ -304,4 +306,4 @@ void waylandWindowFree(void); void waylandWindowUpdateScale(void); void waylandSetWindowSize(int x, int y); bool waylandIsValidPointerPos(int x, int y); -void waylandSignalNextFrame(LGEvent * event); +void waylandWaitFrame(void); diff --git a/client/displayservers/Wayland/window.c b/client/displayservers/Wayland/window.c index a0e26789..2ef0ece1 100644 --- a/client/displayservers/Wayland/window.c +++ b/client/displayservers/Wayland/window.c @@ -80,6 +80,14 @@ bool waylandWindowInit(const char * title, bool fullscreen, bool maximize, bool { wlWm.scale = wl_fixed_from_int(1); + wlWm.frameEvent = lgCreateEvent(true, 0); + if (!wlWm.frameEvent) + { + DEBUG_ERROR("Failed to initialize event for waitFrame"); + return false; + } + lgSignalEvent(wlWm.frameEvent); + if (!wlWm.compositor) { DEBUG_ERROR("Compositor missing wl_compositor (version 3+), will not proceed"); @@ -105,6 +113,7 @@ bool waylandWindowInit(const char * title, bool fullscreen, bool maximize, bool void waylandWindowFree(void) { wl_surface_destroy(wlWm.surface); + lgFreeEvent(wlWm.frameEvent); } void waylandSetWindowSize(int x, int y) @@ -119,8 +128,7 @@ bool waylandIsValidPointerPos(int x, int y) static void frameHandler(void * opaque, struct wl_callback * callback, unsigned int data) { - LGEvent * event = opaque; - lgSignalEvent(event); + lgSignalEvent(wlWm.frameEvent); wl_callback_destroy(callback); } @@ -128,9 +136,11 @@ static const struct wl_callback_listener frame_listener = { .done = frameHandler, }; -void waylandSignalNextFrame(LGEvent * event) +void waylandWaitFrame(void) { + lgWaitEvent(wlWm.frameEvent, TIMEOUT_INFINITE); + struct wl_callback * callback = wl_surface_frame(wlWm.surface); if (callback) - wl_callback_add_listener(callback, &frame_listener, event); + wl_callback_add_listener(callback, &frame_listener, NULL); } diff --git a/client/include/interface/displayserver.h b/client/include/interface/displayserver.h index 8af237c1..7645a5b8 100644 --- a/client/include/interface/displayserver.h +++ b/client/include/interface/displayserver.h @@ -149,11 +149,10 @@ struct LG_DisplayServerOps void (*glSwapBuffers)(void); #endif - /* Signals event when the next frame should be rendered in time for the next vblank. - * This must be invoked on the render thread before swapping buffers. - * If used, the render thread MUST wait for event before rendering the next frame. + /* Waits for a good time to render the next frame in time for the next vblank. + * Once this returns, a frame must be rendered. * This is optional and a display server may choose to not implement it. */ - void (*signalNextFrame)(LGEvent * event); + void (*waitFrame)(void); /* dm specific cursor implementations */ void (*guestPointerUpdated)(double x, double y, double localX, double localY); diff --git a/client/src/main.c b/client/src/main.c index 785e8078..57c17249 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -167,8 +167,8 @@ static int renderThread(void * unused) while(g_state.state != APP_STATE_SHUTDOWN) { - if (g_state.jitRender) - lgWaitEvent(g_state.jitEvent, TIMEOUT_INFINITE); + if (g_state.jitRender || (g_state.ds->waitFrame && g_state.overlayInput)) + g_state.ds->waitFrame(); else if (g_params.fpsMin != 0) { float ups = atomic_load_explicit(&g_state.ups, memory_order_relaxed); @@ -182,12 +182,6 @@ static int renderThread(void * unused) } } - if (!g_params.jitRender && g_state.ds->signalNextFrame) - g_state.jitRender = g_state.overlayInput; - - if (g_state.jitRender) - g_state.ds->signalNextFrame(g_state.jitEvent); - int resize = atomic_load(&g_state.lgrResize); if (resize) { @@ -828,7 +822,7 @@ static int lg_run(void) if (g_params.jitRender) { - if (g_state.ds->signalNextFrame) + if (g_state.ds->waitFrame) g_state.jitRender = true; else DEBUG_WARN("JIT render not supported on display server backend, disabled");