From 85e9784a22df401dfb0350fe550f33be0e51b434 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 4 Oct 2018 13:53:17 +0300 Subject: [PATCH] renderer/native: fix next_fb_id race on CPU copy path There was a race in setting next_fb_id when a secondary GPU was using the CPU copy path. Losing this race caused the attempt to drmModePageFlip () to FB ID 0 which is invalid and always fails. Failing to flip causes Mutter to fall back to drmModeSetCrtc () permanently. In meta_onscreen_native_swap_buffers_with_damage (): - update_secondary_gpu_state_pre_swap_buffers () - copy_shared_framebuffer_cpu () but only on the CPU copy path - secondary_gpu_state->gbm.next_fb_id is set - wait_for_pending_flips () - Waits for any remaining page flip events and executes and destroys the related page flip closures. - on_crtc_flipped () - meta_onscreen_native_swap_drm_fb () - swap_secondary_drm_fb () - secondary_gpu_state->gbm.next_fb_id = 0; - meta_onscreen_native_flip_crtcs () - meta_onscreen_native_flip_crtc () - meta_gpu_kms_flip_crtc () gets called with fb_id = 0 This race was observed lost when running 'mutter --wayland' on a machine with two outputs on Intel and one output on DisplayLink USB dock, and wiggling around a weston-terminal window between the Intel and DisplayLink outputs. It took from a second to a minute to trigger. For testing with DisplayLink outputs Mutter also needed a patch to take the DisplayLink output into use, as it would have otherwise been ignored being a platform device rather than a PCI device. Fix this race by first waiting for pending flips and only then proceeding with the swap operations. This should be safe, because the pending flips could have completed already before entering meta_onscreen_native_swap_buffers_with_damage (). --- src/backends/native/meta-renderer-native.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index f58e6b3e0..96414f678 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -1900,6 +1900,12 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, CoglFrameInfo *frame_info; gboolean egl_context_changed = FALSE; + /* + * Wait for the flip callback before continuing, as we might have started the + * animation earlier due to the animation being driven by some other monitor. + */ + wait_for_pending_flips (onscreen); + frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos); frame_info->global_frame_counter = renderer_native->frame_counter; @@ -1909,12 +1915,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, rectangles, n_rectangles); - /* - * Wait for the flip callback before continuing, as we might have started the - * animation earlier due to the animation being driven by some other monitor. - */ - wait_for_pending_flips (onscreen); - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, render_gpu); switch (renderer_gpu_data->mode)