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
This commit is contained in:
Georges Basile Stavracas Neto 2020-02-28 12:23:15 -03:00
parent 680a54aff6
commit 86168b945c
5 changed files with 105 additions and 4 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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

View File

@ -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;
}