screen-cast/monitor-stream: Immediately record scanout frames

When the before-paint function is executed, it's only purpose
is to check if there's any scanout queue, and immediately
record it if any.

However, since [1], we regressed in this specific case with the
introduction of an idle callback in the before-paint function.
The regression only happens when the PipeWire stream is using
DMA-BUF buffers, and it would operate as follows:

 1. In before-paint, when there's a scanout available, we queue
    an idle callback to capture the monitor. The idle callback
    (almost always) executes after the scanout is pulled from
    the stage view

 2. meta_screen_cast_stream_src_maybe_record_frame() is called
    by the idle callback. In the DMA-BUF case, it then runs
    meta_screen_cast_monitor_stream_src_record_to_framebuffer()

 3. In meta_screen_cast_monitor_stream_src_record_to_framebuffer(),
    because the stage view doesn't have a scanout anymore, it
    ends up calling cogl_blit_framebuffer() with the stage view
    framebuffer. This is the regression bug.

This regression presents itself in the form of the screencast
stream showing the desktop when there's an unredirected fullscreen
application window running.

Revert before-paint - and only that - back to immediately capturing
any available scanout. Only record these frames when the target
buffer is a DMA-BUF handle. Nothing is captured on before-paint if
the stream is not using DMA-BUF, since the regular paint routine
will handle these frames regularly post-paint.

[1] https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1914

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2186>
This commit is contained in:
Georges Basile Stavracas Neto 2021-12-27 15:32:27 -03:00 committed by Marge Bot
parent 8fe45d7750
commit 77d5c8c928

View File

@ -162,6 +162,7 @@ before_stage_painted (MetaStage *stage,
MetaScreenCastMonitorStreamSrc *monitor_src = MetaScreenCastMonitorStreamSrc *monitor_src =
META_SCREEN_CAST_MONITOR_STREAM_SRC (user_data); META_SCREEN_CAST_MONITOR_STREAM_SRC (user_data);
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src); MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
MetaScreenCastRecordFlag flags;
if (monitor_src->maybe_record_idle_id) if (monitor_src->maybe_record_idle_id)
return; return;
@ -169,10 +170,8 @@ before_stage_painted (MetaStage *stage,
if (!clutter_stage_view_peek_scanout (view)) if (!clutter_stage_view_peek_scanout (view))
return; return;
monitor_src->maybe_record_idle_id = g_idle_add (maybe_record_frame_on_idle, flags = META_SCREEN_CAST_RECORD_FLAG_DMABUF_ONLY;
src); meta_screen_cast_stream_src_maybe_record_frame (src, flags);
g_source_set_name_by_id (monitor_src->maybe_record_idle_id,
"[mutter] maybe_record_frame_on_idle [monitor-src]");
} }
static MetaBackend * static MetaBackend *