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 ().
This commit is contained in:
Pekka Paalanen 2018-10-04 13:53:17 +03:00 committed by Ray Strode
parent 49fea735aa
commit 85e9784a22

View File

@ -1900,6 +1900,12 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
CoglFrameInfo *frame_info; CoglFrameInfo *frame_info;
gboolean egl_context_changed = FALSE; 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 = g_queue_peek_tail (&onscreen->pending_frame_infos);
frame_info->global_frame_counter = renderer_native->frame_counter; frame_info->global_frame_counter = renderer_native->frame_counter;
@ -1909,12 +1915,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
rectangles, rectangles,
n_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, renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
render_gpu); render_gpu);
switch (renderer_gpu_data->mode) switch (renderer_gpu_data->mode)