From 86168b945ce0b159a011b2b018a62faca315b682 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Fri, 28 Feb 2020 12:23:15 -0300 Subject: [PATCH] window-stream-source: Draw into DMA buffer image Much like monitor streaming, implement window streaming by making the window actor draw itself with a paint context that used the passed framebuffer. Now that all MetaScreenCastStreamSrc subclasses implement blit_to_framebuffer, remove the conditional check from meta_screen_cast_stream_src_blit_to_framebuffer(). https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086 --- src/backends/meta-screen-cast-stream-src.c | 5 +- .../meta-screen-cast-window-stream-src.c | 21 ++++++ src/backends/meta-screen-cast-window.c | 11 ++++ src/backends/meta-screen-cast-window.h | 8 +++ src/compositor/meta-window-actor.c | 64 +++++++++++++++++++ 5 files changed, 105 insertions(+), 4 deletions(-) diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c index 0eb9f4d8c..6f7551ad4 100644 --- a/src/backends/meta-screen-cast-stream-src.c +++ b/src/backends/meta-screen-cast-stream-src.c @@ -149,10 +149,7 @@ meta_screen_cast_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src, MetaScreenCastStreamSrcClass *klass = META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - if (klass->blit_to_framebuffer) - return klass->blit_to_framebuffer (src, framebuffer); - - return FALSE; + return klass->blit_to_framebuffer (src, framebuffer); } static void diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c index 63ac5eb38..1159ddb69 100644 --- a/src/backends/meta-screen-cast-window-stream-src.c +++ b/src/backends/meta-screen-cast-window-stream-src.c @@ -401,6 +401,25 @@ meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src, return TRUE; } +static gboolean +meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src, + CoglFramebuffer *framebuffer) +{ + MetaScreenCastWindowStreamSrc *window_src = + META_SCREEN_CAST_WINDOW_STREAM_SRC (src); + MetaRectangle stream_rect; + + stream_rect.x = 0; + stream_rect.y = 0; + stream_rect.width = get_stream_width (window_src); + stream_rect.height = get_stream_height (window_src); + + return + meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window, + &stream_rect, + framebuffer); +} + static void meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, struct spa_meta_cursor *spa_meta_cursor) @@ -485,6 +504,8 @@ meta_screen_cast_window_stream_src_class_init (MetaScreenCastWindowStreamSrcClas src_class->enable = meta_screen_cast_window_stream_src_enable; src_class->disable = meta_screen_cast_window_stream_src_disable; src_class->record_frame = meta_screen_cast_window_stream_src_record_frame; + src_class->blit_to_framebuffer = + meta_screen_cast_window_stream_src_blit_to_framebuffer; src_class->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop; src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata; } diff --git a/src/backends/meta-screen-cast-window.c b/src/backends/meta-screen-cast-window.c index bc6249a47..ab3e4ebe3 100644 --- a/src/backends/meta-screen-cast-window.c +++ b/src/backends/meta-screen-cast-window.c @@ -78,6 +78,17 @@ meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_window, data); } +gboolean +meta_screen_cast_window_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window, + MetaRectangle *bounds, + CoglFramebuffer *framebuffer) +{ + MetaScreenCastWindowInterface *iface = + META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window); + + return iface->blit_to_framebuffer (screen_cast_window, bounds, framebuffer); +} + gboolean meta_screen_cast_window_has_damage (MetaScreenCastWindow *screen_cast_window) { diff --git a/src/backends/meta-screen-cast-window.h b/src/backends/meta-screen-cast-window.h index 28734d8fb..e149646ed 100644 --- a/src/backends/meta-screen-cast-window.h +++ b/src/backends/meta-screen-cast-window.h @@ -56,6 +56,10 @@ struct _MetaScreenCastWindowInterface MetaRectangle *bounds, uint8_t *data); + gboolean (*blit_to_framebuffer) (MetaScreenCastWindow *screen_cast_window, + MetaRectangle *bounds, + CoglFramebuffer *framebuffer); + gboolean (*has_damage) (MetaScreenCastWindow *screen_cast_window); }; @@ -78,6 +82,10 @@ void meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_win MetaRectangle *bounds, uint8_t *data); +gboolean meta_screen_cast_window_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window, + MetaRectangle *bounds, + CoglFramebuffer *framebuffer); + gboolean meta_screen_cast_window_has_damage (MetaScreenCastWindow *screen_cast_window); G_END_DECLS diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index c4781d3b2..c5ad8e1b0 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1256,6 +1256,69 @@ meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window, cairo_surface_destroy (image); } +static gboolean +meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window, + MetaRectangle *bounds, + CoglFramebuffer *framebuffer) +{ + MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window); + ClutterActor *actor = CLUTTER_ACTOR (window_actor); + ClutterPaintContext *paint_context; + MetaRectangle scaled_clip; + CoglColor clear_color; + float resource_scale; + float width, height; + float x, y; + + if (meta_window_actor_is_destroyed (window_actor)) + return FALSE; + + clutter_actor_get_size (actor, &width, &height); + + if (width == 0 || height == 0) + return FALSE; + + if (!clutter_actor_get_resource_scale (actor, &resource_scale)) + return FALSE; + + width = ceilf (width * resource_scale); + height = ceilf (height * resource_scale); + + cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); + clutter_actor_get_position (actor, &x, &y); + + cogl_framebuffer_push_matrix (framebuffer); + + cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color); + cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0); + cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1); + cogl_framebuffer_translate (framebuffer, -x, -y, 0); + + meta_rectangle_scale_double (bounds, resource_scale, + META_ROUNDING_STRATEGY_GROW, + &scaled_clip); + meta_rectangle_intersect (&scaled_clip, + &(MetaRectangle) { + .width = width, + .height = height, + }, + &scaled_clip); + + cogl_framebuffer_push_rectangle_clip (framebuffer, + scaled_clip.x, scaled_clip.y, + scaled_clip.x + scaled_clip.width, + scaled_clip.y + scaled_clip.height); + + paint_context = clutter_paint_context_new_for_framebuffer (framebuffer); + clutter_actor_paint (actor, paint_context); + clutter_paint_context_destroy (paint_context); + + cogl_framebuffer_pop_clip (framebuffer); + cogl_framebuffer_pop_matrix (framebuffer); + + return TRUE; +} + static gboolean meta_window_actor_has_damage (MetaScreenCastWindow *screen_cast_window) { @@ -1269,6 +1332,7 @@ screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface) iface->transform_relative_position = meta_window_actor_transform_relative_position; iface->transform_cursor_position = meta_window_actor_transform_cursor_position; iface->capture_into = meta_window_actor_capture_into; + iface->blit_to_framebuffer = meta_window_actor_blit_to_framebuffer; iface->has_damage = meta_window_actor_has_damage; }