screen-cast/monitor: Always use clutter_stage_paint_to_framebuffer()

'screen-cast/monitor-src: Use clutter_stage_paint_to_buffer'
(6c818cd8d5) made the non-dma-buf path use
clutter_stage_paint_to_buffer() to avoid running into direct scanout
issues. At a glance, the dma-buf paths didn't have the same issue since
it explicitly handled dma-bufs by blitting them.

What it also did was move the recording to an idle callback, to avoid
paint reentry issues. A side effect of this, however, is that it also
broke the dma-buf paths, as they rely on the back buffer existing, and
the stage view direct scanout already being setup, which it isn't in an
idle callback.

Fix this by using the dma-buf variant of
clutter_stage_paint_to_buffer(): clutter_stage_paint_to_framebuffer().
This has some negative performance impact, but we can't use
cogl_blit_framebuffer() when using an idle callback for recording.

Potential performance improvements to make things work more as they did
before is to enhance 'cogl_blit_framebuffer()' a bit, making it a vfunc
that could be implemented by MetaOnscreenNative. A flag to say whether
to look at the back or front buffer would let MetaOnscreenNative know
whether to use the already committed-to-KMS buffer, or the current back
buffer.

Fixes: 6c818cd8d5
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2282
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2462>
This commit is contained in:
Jonas Ådahl 2022-06-13 18:41:17 +02:00 committed by Marge Bot
parent 4af54225de
commit 53b52e26f5

View File

@ -552,13 +552,13 @@ meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamS
{ {
MetaScreenCastMonitorStreamSrc *monitor_src = MetaScreenCastMonitorStreamSrc *monitor_src =
META_SCREEN_CAST_MONITOR_STREAM_SRC (src); META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
MetaBackend *backend = get_backend (monitor_src); MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
MetaRenderer *renderer = meta_backend_get_renderer (backend); ClutterStage *stage = get_stage (monitor_src);
MetaMonitor *monitor; MetaMonitor *monitor;
MetaLogicalMonitor *logical_monitor; MetaLogicalMonitor *logical_monitor;
MetaRectangle logical_monitor_layout; MetaRectangle logical_monitor_layout;
GList *l;
float view_scale; float view_scale;
ClutterPaintFlag paint_flags = CLUTTER_PAINT_FLAG_CLEAR;
monitor = get_monitor (monitor_src); monitor = get_monitor (monitor_src);
logical_monitor = meta_monitor_get_logical_monitor (monitor); logical_monitor = meta_monitor_get_logical_monitor (monitor);
@ -569,44 +569,22 @@ meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamS
else else
view_scale = 1.0; view_scale = 1.0;
for (l = meta_renderer_get_views (renderer); l; l = l->next) switch (meta_screen_cast_stream_get_cursor_mode (stream))
{ {
ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data); case META_SCREEN_CAST_CURSOR_MODE_METADATA:
CoglFramebuffer *view_framebuffer; case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
CoglScanout *scanout; paint_flags |= CLUTTER_PAINT_FLAG_NO_CURSORS;
MetaRectangle view_layout; break;
int x, y; case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
paint_flags |= CLUTTER_PAINT_FLAG_FORCE_CURSORS;
break;
}
clutter_stage_view_get_layout (view, &view_layout); clutter_stage_paint_to_framebuffer (stage,
if (!meta_rectangle_overlap (&logical_monitor_layout, &view_layout))
continue;
x = (int) roundf ((view_layout.x - logical_monitor_layout.x) * view_scale);
y = (int) roundf ((view_layout.y - logical_monitor_layout.y) * view_scale);
scanout = clutter_stage_view_peek_scanout (view);
if (scanout)
{
if (!cogl_scanout_blit_to_framebuffer (scanout,
framebuffer, framebuffer,
x, y, &logical_monitor_layout,
error)) view_scale,
return FALSE; paint_flags);
}
else
{
view_framebuffer = clutter_stage_view_get_framebuffer (view);
if (!cogl_blit_framebuffer (view_framebuffer,
framebuffer,
0, 0,
x, y,
cogl_framebuffer_get_width (view_framebuffer),
cogl_framebuffer_get_height (view_framebuffer),
error))
return FALSE;
}
}
cogl_framebuffer_flush (framebuffer); cogl_framebuffer_flush (framebuffer);