mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 00:31:31 +00:00
[client] scheduler: qualify presentation feedback
Track cadence, interruption, and calibration wake reasons independently across X11 and Wayland. Feed phase correction back only when a pure cadence wake renders the exact frame that was queued at that wake. Propagate EGL swap results through the display-server boundary. Reject failed presentations and keep pending Wayland HDR descriptions inactive until the preceding surface commit succeeds.
This commit is contained in:
@@ -228,8 +228,11 @@ static const struct wp_image_description_v1_listener hdrImageDescListener =
|
||||
.ready2 = hdrImageDescReadyV2,
|
||||
};
|
||||
|
||||
void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct Rect * damage, int count)
|
||||
bool waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface,
|
||||
const struct Rect * damage, int count)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// EGL presentation sends a batch of Wayland requests ending in a surface
|
||||
// commit. A concurrent commit would apply a partial batch and, when explicit
|
||||
// sync is active, omit one of the required acquire/release timeline points.
|
||||
@@ -248,8 +251,10 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct
|
||||
|
||||
waylandPresentationFrame();
|
||||
applyHDRPending();
|
||||
swapWithDamage(&wlWm.swapWithDamage, display, surface, damage, count);
|
||||
activateReadyHDRImageDesc();
|
||||
result = swapWithDamage(
|
||||
&wlWm.swapWithDamage, display, surface, damage, count);
|
||||
if (result)
|
||||
activateReadyHDRImageDesc();
|
||||
});
|
||||
|
||||
if (wlWm.needsResize)
|
||||
@@ -305,6 +310,7 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct
|
||||
}
|
||||
|
||||
wlWm.desktop->shellAckConfigureIfNeeded();
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -750,6 +756,6 @@ void waylandGLSetSwapInterval(int interval)
|
||||
|
||||
void waylandGLSwapBuffers(void)
|
||||
{
|
||||
waylandEGLSwapBuffers(wlWm.glDisplay, wlWm.glSurface, NULL, 0);
|
||||
(void)waylandEGLSwapBuffers(wlWm.glDisplay, wlWm.glSurface, NULL, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -267,7 +267,8 @@ struct WaylandDSState
|
||||
enum WaylandHDRPendingAction pendingHDRAction;
|
||||
struct WaylandHDRParameters pendingHDR;
|
||||
|
||||
LGEvent * frameEvent;
|
||||
_Atomic(unsigned) frameEventFlags;
|
||||
LGEvent * frameEvent;
|
||||
|
||||
struct wl_list poll; // WaylandPoll::link
|
||||
struct wl_list pollFree; // WaylandPoll::link
|
||||
@@ -333,7 +334,8 @@ void waylandCursorScaleChange(void);
|
||||
#if defined(ENABLE_EGL) || defined(ENABLE_OPENGL)
|
||||
bool waylandEGLInit(int w, int h);
|
||||
EGLDisplay waylandGetEGLDisplay(void);
|
||||
void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct Rect * damage, int count);
|
||||
bool waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface,
|
||||
const struct Rect * damage, int count);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_EGL
|
||||
@@ -421,7 +423,7 @@ void waylandWindowFree(void);
|
||||
void waylandWindowUpdateScale(void);
|
||||
void waylandSetWindowSize(int x, int y);
|
||||
bool waylandIsValidPointerPos(int x, int y);
|
||||
bool waylandWaitFrame(void);
|
||||
LG_DSWaitFrameResult waylandWaitFrame(void);
|
||||
void waylandSkipFrame(void);
|
||||
void waylandStopWaitFrame(void);
|
||||
void waylandNeedsResize(void);
|
||||
|
||||
@@ -113,6 +113,13 @@ static const struct wl_surface_listener wlSurfaceListener = {
|
||||
.leave = wlSurfaceLeaveHandler,
|
||||
};
|
||||
|
||||
static void waylandSignalFrame(LG_DSWaitFrameResult result)
|
||||
{
|
||||
atomic_fetch_or_explicit(
|
||||
&wlWm.frameEventFlags, result, memory_order_release);
|
||||
lgSignalEvent(wlWm.frameEvent);
|
||||
}
|
||||
|
||||
static void fractionalScalePreferredScale(void * data,
|
||||
struct wp_fractional_scale_v1 * fractionalScale, uint32_t scale)
|
||||
{
|
||||
@@ -133,7 +140,7 @@ bool waylandWindowInit(const char * title, const char * appId, bool fullscreen,
|
||||
DEBUG_ERROR("Failed to initialize event for waitFrame");
|
||||
return false;
|
||||
}
|
||||
lgSignalEvent(wlWm.frameEvent);
|
||||
waylandSignalFrame(LG_DS_WAIT_FRAME_INTERRUPTED);
|
||||
|
||||
if (!wlWm.compositor)
|
||||
{
|
||||
@@ -220,7 +227,7 @@ bool waylandIsValidPointerPos(int x, int y)
|
||||
|
||||
static void frameHandler(void * opaque, struct wl_callback * callback, unsigned int data)
|
||||
{
|
||||
lgSignalEvent(wlWm.frameEvent);
|
||||
waylandSignalFrame(LG_DS_WAIT_FRAME_CADENCE);
|
||||
wl_callback_destroy(callback);
|
||||
}
|
||||
|
||||
@@ -228,9 +235,11 @@ static const struct wl_callback_listener frame_listener = {
|
||||
.done = frameHandler,
|
||||
};
|
||||
|
||||
bool waylandWaitFrame(void)
|
||||
LG_DSWaitFrameResult waylandWaitFrame(void)
|
||||
{
|
||||
lgWaitEvent(wlWm.frameEvent, TIMEOUT_INFINITE);
|
||||
const LG_DSWaitFrameResult result = atomic_exchange_explicit(
|
||||
&wlWm.frameEventFlags, LG_DS_WAIT_FRAME_NONE, memory_order_acquire);
|
||||
|
||||
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||
{
|
||||
@@ -239,7 +248,7 @@ bool waylandWaitFrame(void)
|
||||
wl_callback_add_listener(callback, &frame_listener, NULL);
|
||||
});
|
||||
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
void waylandSkipFrame(void)
|
||||
@@ -253,5 +262,5 @@ void waylandSkipFrame(void)
|
||||
|
||||
void waylandStopWaitFrame(void)
|
||||
{
|
||||
lgSignalEvent(wlWm.frameEvent);
|
||||
waylandSignalFrame(LG_DS_WAIT_FRAME_INTERRUPTED);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user