diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 4f8bff0df..c60855805 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -59,6 +59,8 @@ enum wlr_output_state_field { WLR_OUTPUT_STATE_GAMMA_LUT = 1 << 7, WLR_OUTPUT_STATE_RENDER_FORMAT = 1 << 8, WLR_OUTPUT_STATE_SUBPIXEL = 1 << 9, + WLR_OUTPUT_STATE_WAIT_TIMELINE = 1 << 10, + WLR_OUTPUT_STATE_SIGNAL_TIMELINE = 1 << 11, }; enum wlr_output_state_mode_type { @@ -93,6 +95,13 @@ struct wlr_output_state { // only valid if WLR_OUTPUT_STATE_GAMMA_LUT uint16_t *gamma_lut; size_t gamma_lut_size; + + // only valid if WLR_OUTPUT_STATE_WAIT_TIMELINE + struct wlr_render_timeline *wait_timeline; + uint64_t wait_point; + // only valid if WLR_OUTPUT_STATE_SIGNAL_TIMELINE + struct wlr_render_timeline *signal_timeline; + uint64_t signal_point; }; struct wlr_output_impl; @@ -402,6 +411,31 @@ uint32_t wlr_output_preferred_read_format(struct wlr_output *output); */ void wlr_output_set_damage(struct wlr_output *output, pixman_region32_t *damage); +/** + * Set a timeline point to wait on before displaying the next frame. + * + * The timeline must continue to remain valid until the next call to + * wlr_output_commit() or wlr_output_rollback(). Committing a wait timeline + * point without a buffer is invalid. + * + * There is only a single wait timeline point, waiting for multiple timeline + * points is unsupported. + */ +void wlr_output_set_wait_timeline(struct wlr_output *output, + struct wlr_render_timeline *timeline, uint64_t src_point); +/** + * Set a timeline point to be signalled when the frame is no longer being used + * by the backend. + * + * The timeline must continue to remain valid until the next call to + * wlr_output_commit() or wlr_output_rollback(). Committing a signal timeline + * point without a buffer is invalid. + * + * There is only a single signal timeline point, signalling multiple timeline + * points is unsupported. + */ +void wlr_output_set_signal_timeline(struct wlr_output *output, + struct wlr_render_timeline *timeline, uint64_t dst_point); /** * Test whether the pending output state would be accepted by the backend. If * this function returns true, wlr_output_commit() can only fail due to a diff --git a/types/output/output.c b/types/output/output.c index ae18ea8de..07d2ef948 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -479,6 +479,20 @@ void wlr_output_set_damage(struct wlr_output *output, output->pending.committed |= WLR_OUTPUT_STATE_DAMAGE; } +void wlr_output_set_wait_timeline(struct wlr_output *output, + struct wlr_render_timeline *timeline, uint64_t src_point) { + output->pending.committed |= WLR_OUTPUT_STATE_WAIT_TIMELINE; + output->pending.wait_timeline = timeline; + output->pending.wait_point = src_point; +} + +void wlr_output_set_signal_timeline(struct wlr_output *output, + struct wlr_render_timeline *timeline, uint64_t dst_point) { + output->pending.committed |= WLR_OUTPUT_STATE_SIGNAL_TIMELINE; + output->pending.signal_timeline = timeline; + output->pending.signal_point = dst_point; +} + static void output_state_clear_gamma_lut(struct wlr_output_state *state) { free(state->gamma_lut); state->gamma_lut = NULL; @@ -606,6 +620,15 @@ static bool output_basic_test(struct wlr_output *output, return false; } } + } else { + if (output->pending.committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) { + wlr_log(WLR_DEBUG, "Tried to set wait timeline without a buffer"); + return false; + } + if (output->pending.committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) { + wlr_log(WLR_DEBUG, "Tried to set signal timeline without a buffer"); + return false; + } } if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) {