[client] ds: waitFrame now returns a bool to force rendering if needed

X11 needs to calibrate to get the best possible latency, as such it
needs the scene to render so that the render time of the scene can be
accounted for in the delay calculation.
This commit is contained in:
Geoffrey McRae 2021-08-04 06:49:35 +10:00
parent 0f7fa32d12
commit c15d0dc672
4 changed files with 21 additions and 6 deletions

View File

@ -138,13 +138,15 @@ static const struct wl_callback_listener frame_listener = {
.done = frameHandler, .done = frameHandler,
}; };
void waylandWaitFrame(void) bool waylandWaitFrame(void)
{ {
lgWaitEvent(wlWm.frameEvent, TIMEOUT_INFINITE); lgWaitEvent(wlWm.frameEvent, TIMEOUT_INFINITE);
struct wl_callback * callback = wl_surface_frame(wlWm.surface); struct wl_callback * callback = wl_surface_frame(wlWm.surface);
if (callback) if (callback)
wl_callback_add_listener(callback, &frame_listener, NULL); wl_callback_add_listener(callback, &frame_listener, NULL);
return false;
} }
void waylandSkipFrame(void) void waylandSkipFrame(void)

View File

@ -1128,7 +1128,7 @@ static void x11GLSwapBuffers(void)
} }
#endif #endif
static void x11WaitFrame(void) static bool x11WaitFrame(void)
{ {
/* wait until we are woken up by the present event */ /* wait until we are woken up by the present event */
lgWaitEvent(x11.frameEvent, TIMEOUT_INFINITE); lgWaitEvent(x11.frameEvent, TIMEOUT_INFINITE);
@ -1196,6 +1196,13 @@ static void x11WaitFrame(void)
struct timespec ts = { .tv_nsec = delay * 1000 }; struct timespec ts = { .tv_nsec = delay * 1000 };
while(nanosleep(&ts, &ts)) {}; while(nanosleep(&ts, &ts)) {};
/* force rendering until we have finished calibration so we can take into
* account how long it takes for the scene to render */
if (calibrate < CALIBRATION_COUNT)
return true;
return false;
} }
static void x11StopWaitFrame(void) static void x11StopWaitFrame(void)

View File

@ -154,8 +154,11 @@ struct LG_DisplayServerOps
#endif #endif
/* Waits for a good time to render the next frame in time for the next vblank. /* Waits for a good time to render the next frame in time for the next vblank.
* This is optional and a display server may choose to not implement it. */ * This is optional and a display server may choose to not implement it.
void (*waitFrame)(void); *
* return true to force the frame to be rendered, this is used by X11 for
* calibration */
bool (*waitFrame)(void);
/* This must be called when waitFrame returns, but no frame is actually rendered. */ /* This must be called when waitFrame returns, but no frame is actually rendered. */
void (*skipFrame)(void); void (*skipFrame)(void);

View File

@ -171,14 +171,17 @@ static int renderThread(void * unused)
while(g_state.state != APP_STATE_SHUTDOWN) while(g_state.state != APP_STATE_SHUTDOWN)
{ {
bool forceRender = false;
if (g_state.jitRender)
forceRender = g_state.ds->waitFrame();
app_handleRenderEvent(microtime()); app_handleRenderEvent(microtime());
if (g_state.jitRender) if (g_state.jitRender)
{ {
g_state.ds->waitFrame();
const uint64_t pending = const uint64_t pending =
atomic_load_explicit(&g_state.pendingCount, memory_order_acquire); atomic_load_explicit(&g_state.pendingCount, memory_order_acquire);
if (!lgResetEvent(g_state.frameEvent) if (!lgResetEvent(g_state.frameEvent)
&& !forceRender
&& !pending && !pending
&& !app_overlayNeedsRender() && !app_overlayNeedsRender()
&& !g_state.lgr->needs_render(g_state.lgrData)) && !g_state.lgr->needs_render(g_state.lgrData))