window-actor: Factor out framebuffer creation of get_image()

So we can reuse the code in the following commit.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1893>
This commit is contained in:
Robert Mader 2021-06-06 14:28:48 +02:00 committed by Marge Bot
parent a4223007e2
commit 6bbb216f07

View File

@ -1411,6 +1411,60 @@ meta_window_actor_notify_damaged (MetaWindowActor *window_actor)
g_signal_emit (window_actor, signals[DAMAGED], 0); g_signal_emit (window_actor, signals[DAMAGED], 0);
} }
static CoglFramebuffer *
create_framebuffer_from_window_actor (MetaWindowActor *self,
MetaRectangle *clip,
GError **error)
{
ClutterActor *actor = CLUTTER_ACTOR (self);
MetaBackend *backend = meta_get_backend ();
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
CoglTexture2D *texture;
CoglOffscreen *offscreen;
CoglFramebuffer *framebuffer;
CoglColor clear_color;
ClutterPaintContext *paint_context;
float resource_scale;
resource_scale = clutter_actor_get_resource_scale (actor);
texture = cogl_texture_2d_new_with_size (cogl_context,
clip->width * resource_scale,
clip->height * resource_scale);
if (!texture)
return NULL;
cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (texture),
FALSE);
offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
framebuffer = COGL_FRAMEBUFFER (offscreen);
cogl_object_unref (texture);
if (!cogl_framebuffer_allocate (framebuffer, error))
{
g_object_unref (framebuffer);
return NULL;
}
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color);
cogl_framebuffer_orthographic (framebuffer, 0, 0, clip->width, clip->height,
0, 1.0);
cogl_framebuffer_translate (framebuffer, -clip->x, -clip->y, 0);
paint_context =
clutter_paint_context_new_for_framebuffer (framebuffer, NULL,
CLUTTER_PAINT_FLAG_NONE);
clutter_actor_paint (actor, paint_context);
clutter_paint_context_destroy (paint_context);
return framebuffer;
}
/** /**
* meta_window_actor_get_image: * meta_window_actor_get_image:
* @self: A #MetaWindowActor * @self: A #MetaWindowActor
@ -1430,21 +1484,11 @@ meta_window_actor_get_image (MetaWindowActor *self,
{ {
MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self); MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self);
ClutterActor *actor = CLUTTER_ACTOR (self); ClutterActor *actor = CLUTTER_ACTOR (self);
MetaBackend *backend = meta_get_backend ();
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
float resource_scale;
float width, height;
CoglTexture2D *texture;
g_autoptr (GError) error = NULL;
CoglOffscreen *offscreen;
CoglFramebuffer *framebuffer;
CoglColor clear_color;
float x, y;
MetaRectangle scaled_clip;
ClutterPaintContext *paint_context;
cairo_surface_t *surface = NULL; cairo_surface_t *surface = NULL;
CoglFramebuffer *framebuffer;
MetaRectangle framebuffer_clip;
float resource_scale;
float x, y, width, height;
if (!priv->surface) if (!priv->surface)
return NULL; return NULL;
@ -1458,7 +1502,6 @@ meta_window_actor_get_image (MetaWindowActor *self,
if (clip) if (clip)
{ {
int geometry_scale; int geometry_scale;
geometry_scale = geometry_scale =
@ -1476,76 +1519,51 @@ meta_window_actor_get_image (MetaWindowActor *self,
goto out; goto out;
} }
clutter_actor_get_position (actor, &x, &y);
clutter_actor_get_size (actor, &width, &height); clutter_actor_get_size (actor, &width, &height);
if (width == 0 || height == 0) if (width == 0 || height == 0)
goto out; goto out;
resource_scale = clutter_actor_get_resource_scale (actor); framebuffer_clip = (MetaRectangle) {
.x = floorf (x),
width = ceilf (width * resource_scale); .y = floorf (y),
height = ceilf (height * resource_scale); .width = ceilf (width),
.height = ceilf (height),
texture = cogl_texture_2d_new_with_size (cogl_context, width, height); };
if (!texture)
goto out;
cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (texture),
FALSE);
offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
framebuffer = COGL_FRAMEBUFFER (offscreen);
cogl_object_unref (texture);
if (!cogl_framebuffer_allocate (framebuffer, &error))
{
g_warning ("Failed to allocate framebuffer for screenshot: %s",
error->message);
g_object_unref (framebuffer);
cogl_object_unref (texture);
goto out;
}
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
clutter_actor_get_position (actor, &x, &y);
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);
paint_context =
clutter_paint_context_new_for_framebuffer (framebuffer, NULL,
CLUTTER_PAINT_FLAG_NONE);
clutter_actor_paint (actor, paint_context);
clutter_paint_context_destroy (paint_context);
if (clip) if (clip)
{ {
meta_rectangle_scale_double (clip, resource_scale, MetaRectangle tmp_clip;
META_ROUNDING_STRATEGY_GROW, MetaRectangle intersected_clip;
&scaled_clip);
meta_rectangle_intersect (&scaled_clip, tmp_clip = *clip;
&(MetaRectangle) { tmp_clip.x += floorf (x);
.width = width, tmp_clip.y += floorf (y);
.height = height, if (!meta_rectangle_intersect (&framebuffer_clip,
}, &tmp_clip,
&scaled_clip); &intersected_clip))
} goto out;
else
{ framebuffer_clip = intersected_clip;
scaled_clip = (MetaRectangle) {
.width = width,
.height = height,
};
} }
framebuffer = create_framebuffer_from_window_actor (self,
&framebuffer_clip,
NULL);
if (!framebuffer)
goto out;
resource_scale = clutter_actor_get_resource_scale (actor);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
scaled_clip.width, scaled_clip.height); framebuffer_clip.width *
resource_scale,
framebuffer_clip.height *
resource_scale);
cogl_framebuffer_read_pixels (framebuffer, cogl_framebuffer_read_pixels (framebuffer,
scaled_clip.x, scaled_clip.y, 0, 0,
scaled_clip.width, scaled_clip.height, framebuffer_clip.width * resource_scale,
framebuffer_clip.height * resource_scale,
CLUTTER_CAIRO_FORMAT_ARGB32, CLUTTER_CAIRO_FORMAT_ARGB32,
cairo_image_surface_get_data (surface)); cairo_image_surface_get_data (surface));