diff --git a/client/displayservers/Wayland/output.c b/client/displayservers/Wayland/output.c index 3ff91559..43e4eb71 100644 --- a/client/displayservers/Wayland/output.c +++ b/client/displayservers/Wayland/output.c @@ -316,8 +316,9 @@ static void outputModeHandler(void * opaque, struct wl_output * wl_output, uint3 return; struct WaylandOutput * node = opaque; - node->modeWidth = width; - node->modeHeight = height; + node->modeWidth = width; + node->modeHeight = height; + node->modeRefresh = refresh; } static void outputDoneHandler(void * opaque, struct wl_output * output) @@ -483,3 +484,27 @@ struct WaylandScale waylandOutputGetScale(struct wl_output * output) return node->scale; return waylandScaleFromInt(0); } + +bool waylandOutputGetFramePeriod(uint64_t * period) +{ + uint64_t fastest = 0; + struct SurfaceOutput * surfaceOutput; + wl_list_for_each(surfaceOutput, &wlWm.surfaceOutputs, link) + { + const struct WaylandOutput * output = + outputFind(surfaceOutput->output); + if (!output || output->modeRefresh <= 0) + continue; + + const uint64_t candidate = + 1000000000000ULL / (uint64_t)output->modeRefresh; + if (!fastest || candidate < fastest) + fastest = candidate; + } + + if (!fastest) + return false; + + *period = fastest; + return true; +} diff --git a/client/displayservers/Wayland/presentation.c b/client/displayservers/Wayland/presentation.c index 44bd56a3..74a594fb 100644 --- a/client/displayservers/Wayland/presentation.c +++ b/client/displayservers/Wayland/presentation.c @@ -73,6 +73,12 @@ static void presentationFeedbackPresented(void * opaque, bool waylandGetFramePeriod(uint64_t * period) { + /* Frame demand must use the output's nominal rate. Basing demand on the + * observed presentation interval can lock a VRR session at its current, + * slower cadence. */ + if (waylandOutputGetFramePeriod(period)) + return true; + const uint64_t value = atomic_load(&wlWm.presentationPeriod); if (!value) return false; diff --git a/client/displayservers/Wayland/wayland.h b/client/displayservers/Wayland/wayland.h index 88ae6906..6b52ceb9 100644 --- a/client/displayservers/Wayland/wayland.h +++ b/client/displayservers/Wayland/wayland.h @@ -78,6 +78,7 @@ struct WaylandOutput int32_t logicalHeight; int32_t modeWidth; int32_t modeHeight; + int32_t modeRefresh; bool modeRotate; struct wl_output * output; struct zxdg_output_v1 * xdgOutput; @@ -386,6 +387,7 @@ void waylandOutputFree(void); void waylandOutputBind(uint32_t name, uint32_t version); void waylandOutputTryUnbind(uint32_t name); struct WaylandScale waylandOutputGetScale(struct wl_output * output); +bool waylandOutputGetFramePeriod(uint64_t * period); void waylandOutputColorMgmtInit(struct WaylandOutput * output); void waylandOutputColorMgmtInitAll(void); void waylandOutputUpdateHDRWhiteLevel(void);