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:
parent
a4223007e2
commit
6bbb216f07
@ -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));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user