vo: allow VOs to request waiting before advancing frames
This is essentially for vo_dmabuf_wayland, but there is a race condition during initialization where we should wait on an event from the compositor to set the appropriate description for the image (namely for color management) before flipping the page. Previously, there was an off-by-one frame difference which resulted in the initial frame not being appropriately color managed. Fix this by telling the core render loop that it is not ready for the next frame. This keeps the frame queue from advancing and allows the backend to process events appropriately until it signals that it is ready.
This commit is contained in:
1 parent
1af136bceb
commit
468d34c9bd
5 files changed
+27
-4
No files matched your search
+10
-1
@@ -138,6 +138,7 @@ struct vo_internal {
|
||||
bool send_reset; // send VOCTRL_RESET
|
||||
bool paused;
|
||||
bool visible;
|
||||
bool wait_on_vo;
|
||||
bool wakeup_on_done;
|
||||
int queued_events; // event mask for the user
|
||||
int internal_events; // event mask for us
|
||||
@@ -836,7 +837,7 @@ bool vo_is_ready_for_frame(struct vo *vo, int64_t next_pts)
|
||||
{
|
||||
struct vo_internal *in = vo->in;
|
||||
mp_mutex_lock(&in->lock);
|
||||
bool r = vo->config_ok && !in->frame_queued &&
|
||||
bool r = vo->config_ok && !in->wait_on_vo && !in->frame_queued &&
|
||||
(!in->current_frame || in->current_frame->num_vsyncs < 1);
|
||||
if (r && next_pts >= 0) {
|
||||
// Don't show the frame too early - it would basically freeze the
|
||||
@@ -898,6 +899,14 @@ void vo_wait_frame(struct vo *vo)
|
||||
mp_mutex_unlock(&in->lock);
|
||||
}
|
||||
|
||||
void vo_wait_on_vo(struct vo *vo, bool wait)
|
||||
{
|
||||
struct vo_internal *in = vo->in;
|
||||
mp_mutex_lock(&in->lock);
|
||||
in->wait_on_vo = wait;
|
||||
mp_mutex_unlock(&in->lock);
|
||||
}
|
||||
|
||||
// Wait until realtime is >= ts
|
||||
// called without lock
|
||||
static void wait_until(struct vo *vo, int64_t target)
|
||||
|
||||
@@ -533,6 +533,7 @@ bool vo_is_ready_for_frame(struct vo *vo, int64_t next_pts);
|
||||
bool vo_is_visible(struct vo *vo);
|
||||
void vo_queue_frame(struct vo *vo, struct vo_frame *frame);
|
||||
void vo_wait_frame(struct vo *vo);
|
||||
void vo_wait_on_vo(struct vo *vo, bool wait);
|
||||
bool vo_still_displaying(struct vo *vo);
|
||||
void vo_request_wakeup_on_done(struct vo *vo);
|
||||
bool vo_has_frame(struct vo *vo);
|
||||
|
||||
@@ -103,6 +103,7 @@ struct priv {
|
||||
|
||||
bool destroy_buffers;
|
||||
bool force_window;
|
||||
bool vo_is_waiting;
|
||||
enum hwdec_type hwdec_type;
|
||||
|
||||
struct mp_image_params target_params;
|
||||
@@ -626,6 +627,11 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
wl_surface_damage_buffer(wl->video_surface, 0, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (wl->color_surface && (!wl->image_description_processed || p->vo_is_waiting)) {
|
||||
vo_wait_on_vo(vo, !wl->image_description_processed);
|
||||
p->vo_is_waiting = !wl->image_description_processed;
|
||||
}
|
||||
|
||||
pts = frame->current ? frame->current->pts : 0;
|
||||
if (frame->current) {
|
||||
buf = buffer_get(vo, frame);
|
||||
@@ -660,10 +666,13 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static void flip_page(struct vo *vo)
|
||||
{
|
||||
struct vo_wayland_state *wl = vo->wl;
|
||||
struct priv *p = vo->priv;
|
||||
|
||||
wl_surface_commit(wl->osd_surface);
|
||||
wl_surface_commit(wl->video_surface);
|
||||
wl_surface_commit(wl->surface);
|
||||
if (!p->vo_is_waiting) {
|
||||
wl_surface_commit(wl->osd_surface);
|
||||
wl_surface_commit(wl->video_surface);
|
||||
wl_surface_commit(wl->surface);
|
||||
}
|
||||
|
||||
if (wl->opts->wl_internal_vsync)
|
||||
vo_wayland_wait_frame(wl);
|
||||
|
||||
@@ -2108,6 +2108,7 @@ static void image_description_failed(void *data, struct wp_image_description_v1
|
||||
MP_VERBOSE(wl, "Image description failed: %d, %s\n", cause, msg);
|
||||
wp_color_management_surface_v1_unset_image_description(wl->color_surface);
|
||||
wp_image_description_v1_destroy(image_description);
|
||||
wl->image_description_processed = true;
|
||||
}
|
||||
|
||||
static void image_description_ready2(void *data, struct wp_image_description_v1 *image_description,
|
||||
@@ -2118,6 +2119,7 @@ static void image_description_ready2(void *data, struct wp_image_description_v1
|
||||
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
|
||||
MP_TRACE(wl, "Image description set on color surface.\n");
|
||||
wp_image_description_v1_destroy(image_description);
|
||||
wl->image_description_processed = true;
|
||||
}
|
||||
|
||||
static void image_description_ready(void *data, struct wp_image_description_v1 *image_description,
|
||||
@@ -3538,6 +3540,7 @@ static void set_color_management(struct vo_wayland_state *wl)
|
||||
wp_image_description_creator_params_v1_set_max_fall(image_creator_params, lrintf(hdr.max_fall));
|
||||
}
|
||||
struct wp_image_description_v1 *image_description = wp_image_description_creator_params_v1_create(image_creator_params);
|
||||
wl->image_description_processed = false;
|
||||
wp_image_description_v1_add_listener(image_description, &image_description_listener, wl);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ struct vo_wayland_state {
|
||||
struct wp_color_management_surface_feedback_v1 *color_surface_feedback;
|
||||
struct wp_image_description_creator_icc_v1 *icc_creator;
|
||||
struct mp_image_params target_params;
|
||||
bool image_description_processed;
|
||||
bool supports_parametric;
|
||||
bool supports_display_primaries;
|
||||
int primaries_map[PL_COLOR_PRIM_COUNT];
|
||||
|
||||
Reference in new issue
Block a user