Commit dad36b91 authored by Daniel van Vugt's avatar Daniel van Vugt
Browse files

onscreen/native: Queue listeners at post time, not swap time

With triple buffering we might sometimes schedule two swaps and hence
two listeners between consecutive presentation notifications:

 0---------------------------1-----------------------------2----------
  \                             \
   notify0  swap1  post1  swap2  notify1  notify2  post2  ............
                                          ^^^^^^^^^^^^^^

So notify2 happens before it was even posted, with duplicate frame data
from notify1 because they're both fired by the same DRM event. This
mostly seems to happen with multi-monitors, probably because the event
loop is busier and notifications may arrive later. But it could also
happen with a single monitor in theory.

To avoid the problem we move queuing of listeners from swap time to post
time so now everything happens in the right order:

 0---------------------------1-----------------------------2----------
  \                             \                             \
   notify0  swap1  post1  swap2  notify1  post2  ............  notify2
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
parent a38377f3
This commit is part of merge request !1441. Comments created here will be created in the context of that merge request.
......@@ -444,7 +444,6 @@ static void
meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
MetaRendererView *view,
MetaCrtc *crtc,
MetaKmsPageFlipListenerFlag flags,
const int *rectangles,
int n_rectangles)
{
......@@ -452,7 +451,6 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
MetaRendererNativeGpuData *renderer_gpu_data;
MetaGpuKms *gpu_kms;
MetaKmsDevice *kms_device;
......@@ -508,6 +506,23 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
break;
#endif
}
}
static gboolean
add_page_flip_listener (CoglOnscreen *onscreen,
MetaKmsPageFlipListenerFlag flags)
{
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
MetaKms *kms = meta_kms_device_get_kms (kms_device);
MetaRendererView *view = onscreen_native->view;
MetaKmsUpdate *kms_update;
kms_update = meta_kms_get_pending_update (kms, kms_device);
if (!kms_update)
return FALSE;
meta_kms_update_add_page_flip_listener (kms_update,
kms_crtc,
......@@ -515,6 +530,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
flags,
g_object_ref (view),
g_object_unref);
return TRUE;
}
static void
......@@ -1114,7 +1131,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
meta_onscreen_native_flip_crtc (onscreen,
onscreen_native->view,
onscreen_native->crtc,
META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE,
rectangles,
n_rectangles);
}
......@@ -1144,8 +1160,10 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
meta_kms_device_get_path (kms_device));
promote_drm_next_to_posted (onscreen);
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
if (add_page_flip_listener (onscreen,
META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE))
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
return;
}
else if (meta_renderer_native_has_pending_mode_set (renderer_native))
......@@ -1154,10 +1172,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
meta_kms_device_get_path (kms_device));
promote_drm_next_to_posted (onscreen);
if (add_page_flip_listener (onscreen,
META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE))
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
meta_renderer_native_notify_mode_sets_reset (renderer_native);
meta_renderer_native_post_mode_set_updates (renderer_native);
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
return;
}
break;
......@@ -1168,10 +1189,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
if (meta_renderer_native_has_pending_mode_set (renderer_native))
{
if (add_page_flip_listener (onscreen,
META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE))
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
meta_renderer_native_notify_mode_sets_reset (renderer_native);
meta_renderer_native_post_mode_set_updates (renderer_native);
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
return;
}
break;
......@@ -1211,6 +1235,9 @@ post_latest_swap (CoglOnscreen *onscreen)
meta_kms_crtc_get_id (kms_crtc),
meta_kms_device_get_path (kms_device));
if (!add_page_flip_listener (onscreen, META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE))
return;
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
g_return_if_fail (kms_feedback != NULL);
......@@ -1363,10 +1390,13 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
meta_onscreen_native_flip_crtc (onscreen,
onscreen_native->view,
onscreen_native->crtc,
META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR,
NULL,
0);
if (!add_page_flip_listener (onscreen,
META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR))
return FALSE;
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
kms_device = meta_kms_crtc_get_device (kms_crtc);
......@@ -1423,27 +1453,18 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);;
MetaKms *kms = meta_kms_device_get_kms (kms_device);
MetaKmsUpdateFlag flags;
MetaKmsUpdate *kms_update;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
const GError *error;
if (onscreen_native->gbm.posted_fb) /* Post already pending. Avoid EBUSY */
return;
kms_update = meta_kms_get_pending_update (kms, kms_device);
if (!kms_update)
if (!add_page_flip_listener (onscreen, META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE))
{
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
return;
}
meta_kms_update_add_page_flip_listener (kms_update,
kms_crtc,
&page_flip_listener_vtable,
META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE,
g_object_ref (onscreen_native->view),
g_object_unref);
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms,
kms_device,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment