shaped-texture: Move MetaCullable helpers to MetaSurfaceActor

Now that MetaShapedTexture is not a ClutterActor anymore, it does
not make sense to make it a MetaCullable semi-implementation. This
is, naturally, a responsibility of MetaSurfaceActor, since now
MetaShapedTexture is a ClutterContent and as such, it only cares
about what to draw.

Move the MetaCullable implementation of MetaShapedTexture to
MetaSurfaceActor.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/409
This commit is contained in:
Georges Basile Stavracas Neto 2019-01-29 19:53:50 -02:00 committed by Jonas Ådahl
parent 425e65049b
commit 4c1fde9deb
4 changed files with 171 additions and 173 deletions

View File

@ -40,7 +40,6 @@ void meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex, void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
int fallback_width, int fallback_width,
int fallback_height); int fallback_height);
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
cairo_region_t * meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex); cairo_region_t * meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex);
void meta_shaped_texture_set_transform (MetaShapedTexture *stex, void meta_shaped_texture_set_transform (MetaShapedTexture *stex,
MetaMonitorTransform transform); MetaMonitorTransform transform);
@ -51,11 +50,6 @@ void meta_shaped_texture_set_viewport_dst_size (MetaShapedTexture *stex,
int dst_width, int dst_width,
int dst_height); int dst_height);
void meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex); void meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex);
void meta_shaped_texture_cull_out (MetaShapedTexture *stex,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region,
uint8_t opacity);
void meta_shaped_texture_reset_culling (MetaShapedTexture *stex);
void meta_shaped_texture_set_buffer_scale (MetaShapedTexture *stex, void meta_shaped_texture_set_buffer_scale (MetaShapedTexture *stex,
int buffer_scale); int buffer_scale);
int meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex); int meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex);

View File

@ -88,10 +88,6 @@ struct _MetaShapedTexture
/* The region containing only fully opaque pixels */ /* The region containing only fully opaque pixels */
cairo_region_t *opaque_region; cairo_region_t *opaque_region;
/* MetaCullable regions, see that documentation for more details */
cairo_region_t *clip_region;
cairo_region_t *unobscured_region;
gboolean size_invalid; gboolean size_invalid;
MetaMonitorTransform transform; MetaMonitorTransform transform;
gboolean has_viewport_src_rect; gboolean has_viewport_src_rect;
@ -219,34 +215,6 @@ ensure_size_valid (MetaShapedTexture *stex)
update_size (stex); update_size (stex);
} }
static void
set_unobscured_region (MetaShapedTexture *stex,
cairo_region_t *unobscured_region)
{
g_clear_pointer (&stex->unobscured_region, cairo_region_destroy);
if (unobscured_region)
{
int width, height;
ensure_size_valid (stex);
width = stex->dst_width;
height = stex->dst_height;
cairo_rectangle_int_t bounds = { 0, 0, width, height };
stex->unobscured_region = cairo_region_copy (unobscured_region);
cairo_region_intersect_rectangle (stex->unobscured_region, &bounds);
}
}
static void
set_clip_region (MetaShapedTexture *stex,
cairo_region_t *clip_region)
{
g_clear_pointer (&stex->clip_region, cairo_region_destroy);
if (clip_region)
stex->clip_region = cairo_region_copy (clip_region);
}
static void static void
meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex) meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
{ {
@ -271,12 +239,8 @@ meta_shaped_texture_dispose (GObject *object)
stex->paint_tower = NULL; stex->paint_tower = NULL;
g_clear_pointer (&stex->texture, cogl_object_unref); g_clear_pointer (&stex->texture, cogl_object_unref);
g_clear_pointer (&stex->opaque_region, cairo_region_destroy);
meta_shaped_texture_set_mask_texture (stex, NULL); meta_shaped_texture_set_mask_texture (stex, NULL);
set_unobscured_region (stex, NULL);
set_clip_region (stex, NULL);
meta_shaped_texture_reset_pipelines (stex); meta_shaped_texture_reset_pipelines (stex);
g_clear_pointer (&stex->snippet, cogl_object_unref); g_clear_pointer (&stex->snippet, cogl_object_unref);
@ -546,12 +510,6 @@ texture_is_idle_and_not_mipmapped (gpointer user_data)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static cairo_region_t *
effective_unobscured_region (MetaShapedTexture *stex)
{
return stex->unobscured_region;
}
static void static void
do_paint_content (MetaShapedTexture *stex, do_paint_content (MetaShapedTexture *stex,
ClutterPaintNode *root_node, ClutterPaintNode *root_node,
@ -599,19 +557,12 @@ do_paint_content (MetaShapedTexture *stex,
if (use_opaque_region) if (use_opaque_region)
{ {
if (stex->clip_region) blended_tex_region = cairo_region_create_rectangle (&content_rect);
blended_tex_region = cairo_region_copy (stex->clip_region);
else
blended_tex_region = cairo_region_create_rectangle (&content_rect);
cairo_region_subtract (blended_tex_region, stex->opaque_region); cairo_region_subtract (blended_tex_region, stex->opaque_region);
} }
else else
{ {
if (stex->clip_region) blended_tex_region = NULL;
blended_tex_region = cairo_region_reference (stex->clip_region);
else
blended_tex_region = NULL;
} }
/* Limit to how many separate rectangles we'll draw; beyond this just /* Limit to how many separate rectangles we'll draw; beyond this just
@ -633,21 +584,10 @@ do_paint_content (MetaShapedTexture *stex,
/* First, paint the unblended parts, which are part of the opaque region. */ /* First, paint the unblended parts, which are part of the opaque region. */
if (use_opaque_region) if (use_opaque_region)
{ {
cairo_region_t *region;
int n_rects; int n_rects;
int i; int i;
if (stex->clip_region) if (!cairo_region_is_empty (stex->opaque_region))
{
region = cairo_region_copy (stex->clip_region);
cairo_region_intersect (region, stex->opaque_region);
}
else
{
region = cairo_region_reference (stex->opaque_region);
}
if (!cairo_region_is_empty (region))
{ {
CoglPipeline *opaque_pipeline; CoglPipeline *opaque_pipeline;
@ -655,18 +595,16 @@ do_paint_content (MetaShapedTexture *stex,
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter); cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
n_rects = cairo_region_num_rectangles (region); n_rects = cairo_region_num_rectangles (stex->opaque_region);
for (i = 0; i < n_rects; i++) for (i = 0; i < n_rects; i++)
{ {
cairo_rectangle_int_t rect; cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect); cairo_region_get_rectangle (stex->opaque_region, i, &rect);
paint_clipped_rectangle_node (stex, root_node, paint_clipped_rectangle_node (stex, root_node,
opaque_pipeline, opaque_pipeline,
&rect, alloc); &rect, alloc);
} }
} }
cairo_region_destroy (region);
} }
/* Now, go ahead and paint the blended parts. */ /* Now, go ahead and paint the blended parts. */
@ -786,9 +724,6 @@ meta_shaped_texture_paint_content (ClutterContent *content,
CoglTexture *paint_tex = NULL; CoglTexture *paint_tex = NULL;
uint8_t opacity; uint8_t opacity;
if (stex->clip_region && cairo_region_is_empty (stex->clip_region))
return;
/* The GL EXT_texture_from_pixmap extension does allow for it to be /* The GL EXT_texture_from_pixmap extension does allow for it to be
* used together with SGIS_generate_mipmap, however this is very * used together with SGIS_generate_mipmap, however this is very
* rarely supported. Also, even when it is supported there * rarely supported. Also, even when it is supported there
@ -873,17 +808,6 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
clutter_content_invalidate (CLUTTER_CONTENT (stex)); clutter_content_invalidate (CLUTTER_CONTENT (stex));
} }
gboolean
meta_shaped_texture_is_obscured (MetaShapedTexture *stex)
{
cairo_region_t *unobscured_region = effective_unobscured_region (stex);
if (unobscured_region)
return cairo_region_is_empty (unobscured_region);
else
return FALSE;
}
/** /**
* meta_shaped_texture_update_area: * meta_shaped_texture_update_area:
* @stex: #MetaShapedTexture * @stex: #MetaShapedTexture
@ -891,6 +815,7 @@ meta_shaped_texture_is_obscured (MetaShapedTexture *stex)
* @y: the y coordinate of the damaged area * @y: the y coordinate of the damaged area
* @width: the width of the damaged area * @width: the width of the damaged area
* @height: the height of the damaged area * @height: the height of the damaged area
* @clip: (out): the resulting clip region
* *
* Repairs the damaged area indicated by @x, @y, @width and @height * Repairs the damaged area indicated by @x, @y, @width and @height
* and potentially queues a redraw. * and potentially queues a redraw.
@ -898,33 +823,37 @@ meta_shaped_texture_is_obscured (MetaShapedTexture *stex)
* Return value: Whether a redraw have been queued or not * Return value: Whether a redraw have been queued or not
*/ */
gboolean gboolean
meta_shaped_texture_update_area (MetaShapedTexture *stex, meta_shaped_texture_update_area (MetaShapedTexture *stex,
int x, int x,
int y, int y,
int width, int width,
int height) int height,
cairo_rectangle_int_t *clip)
{ {
cairo_region_t *unobscured_region;
cairo_rectangle_int_t clip;
MetaMonitorTransform inverted_transform; MetaMonitorTransform inverted_transform;
if (stex->texture == NULL) if (stex->texture == NULL)
return FALSE; return FALSE;
clip = (cairo_rectangle_int_t) { *clip = (cairo_rectangle_int_t) {
.x = x, .x = x,
.y = y, .y = y,
.width = width, .width = width,
.height = height .height = height
}; };
meta_rectangle_scale_double (clip,
1.0 / stex->buffer_scale,
META_ROUNDING_STRATEGY_SHRINK,
clip);
inverted_transform = meta_monitor_transform_invert (stex->transform); inverted_transform = meta_monitor_transform_invert (stex->transform);
ensure_size_valid (stex); ensure_size_valid (stex);
meta_rectangle_transform (&clip, meta_rectangle_transform (clip,
inverted_transform, inverted_transform,
stex->dst_width, stex->dst_width,
stex->dst_height, stex->dst_height,
&clip); clip);
if (stex->has_viewport_src_rect || stex->has_viewport_dst_size) if (stex->has_viewport_src_rect || stex->has_viewport_dst_size)
{ {
@ -969,11 +898,11 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
inverted_dst_width = ceilf (viewport.size.width); inverted_dst_width = ceilf (viewport.size.width);
inverted_dst_height = ceilf (viewport.size.height); inverted_dst_height = ceilf (viewport.size.height);
meta_rectangle_crop_and_scale (&clip, meta_rectangle_crop_and_scale (clip,
&inverted_viewport, &inverted_viewport,
inverted_dst_width, inverted_dst_width,
inverted_dst_height, inverted_dst_height,
&clip); clip);
} }
meta_texture_tower_update_area (stex->paint_tower, meta_texture_tower_update_area (stex->paint_tower,
@ -996,36 +925,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
stex->fast_updates++; stex->fast_updates++;
} }
unobscured_region = effective_unobscured_region (stex); return TRUE;
if (unobscured_region)
{
cairo_rectangle_int_t extents;
cairo_region_t *scaled_unobscured_region;
cairo_region_t *intersection;
if (cairo_region_is_empty (unobscured_region))
return FALSE;
intersection = cairo_region_copy (unobscured_region);
cairo_region_intersect_rectangle (intersection, &clip);
if (!cairo_region_is_empty (intersection))
{
cairo_rectangle_int_t damage_rect;
cairo_region_get_extents (intersection, &damage_rect);
clutter_content_invalidate (CLUTTER_CONTENT (stex));
cairo_region_destroy (intersection);
return TRUE;
}
cairo_region_destroy (intersection);
return FALSE;
}
else
{
clutter_content_invalidate (CLUTTER_CONTENT (stex));
return TRUE;
}
} }
/** /**
@ -1455,34 +1355,3 @@ meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex)
return stex->buffer_scale; return stex->buffer_scale;
} }
void
meta_shaped_texture_cull_out (MetaShapedTexture *stex,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region,
uint8_t opacity)
{
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
set_unobscured_region (stex, unobscured_region);
set_clip_region (stex, clip_region);
if (opacity == 0xff)
{
if (stex->opaque_region)
{
if (unobscured_region)
cairo_region_subtract (unobscured_region, stex->opaque_region);
if (clip_region)
cairo_region_subtract (clip_region, stex->opaque_region);
}
}
}
void
meta_shaped_texture_reset_culling (MetaShapedTexture *stex)
{
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
set_clip_region (stex, NULL);
}

View File

@ -30,6 +30,10 @@ typedef struct _MetaSurfaceActorPrivate
cairo_region_t *input_region; cairo_region_t *input_region;
/* MetaCullable regions, see that documentation for more details */
cairo_region_t *clip_region;
cairo_region_t *unobscured_region;
/* Freeze/thaw accounting */ /* Freeze/thaw accounting */
cairo_region_t *pending_damage; cairo_region_t *pending_damage;
guint frozen : 1; guint frozen : 1;
@ -51,6 +55,78 @@ enum
static guint signals[LAST_SIGNAL]; static guint signals[LAST_SIGNAL];
static cairo_region_t *
effective_unobscured_region (MetaSurfaceActor *surface_actor)
{
MetaSurfaceActorPrivate *priv =
meta_surface_actor_get_instance_private (surface_actor);
ClutterActor *actor;
/* Fail if we have any mapped clones. */
actor = CLUTTER_ACTOR (surface_actor);
do
{
if (clutter_actor_has_mapped_clones (actor))
return NULL;
actor = clutter_actor_get_parent (actor);
}
while (actor != NULL);
return priv->unobscured_region;
}
static void
set_unobscured_region (MetaSurfaceActor *surface_actor,
cairo_region_t *unobscured_region)
{
MetaSurfaceActorPrivate *priv =
meta_surface_actor_get_instance_private (surface_actor);
g_clear_pointer (&priv->unobscured_region, cairo_region_destroy);
if (unobscured_region)
{
cairo_rectangle_int_t bounds = { 0, };
float width, height;
clutter_content_get_preferred_size (CLUTTER_CONTENT (priv->texture),
&width,
&height);
bounds = (cairo_rectangle_int_t) {
.width = width,
.height = height,
};
priv->unobscured_region = cairo_region_copy (unobscured_region);
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
}
}
static void
set_clip_region (MetaSurfaceActor *surface_actor,
cairo_region_t *clip_region)
{
MetaSurfaceActorPrivate *priv =
meta_surface_actor_get_instance_private (surface_actor);
g_clear_pointer (&priv->clip_region, cairo_region_destroy);
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
}
static void
meta_surface_actor_paint (ClutterActor *actor)
{
MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (actor);
MetaSurfaceActorPrivate *priv =
meta_surface_actor_get_instance_private (surface_actor);
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
return;
CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->paint (actor);
}
static void static void
meta_surface_actor_pick (ClutterActor *actor, meta_surface_actor_pick (ClutterActor *actor,
const ClutterColor *color) const ClutterColor *color)
@ -126,6 +202,9 @@ meta_surface_actor_dispose (GObject *object)
g_clear_pointer (&priv->input_region, cairo_region_destroy); g_clear_pointer (&priv->input_region, cairo_region_destroy);
set_unobscured_region (self, NULL);
set_clip_region (self, NULL);
G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object); G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
} }
@ -136,6 +215,7 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
object_class->dispose = meta_surface_actor_dispose; object_class->dispose = meta_surface_actor_dispose;
actor_class->paint = meta_surface_actor_paint;
actor_class->pick = meta_surface_actor_pick; actor_class->pick = meta_surface_actor_pick;
actor_class->get_paint_volume = meta_surface_actor_get_paint_volume; actor_class->get_paint_volume = meta_surface_actor_get_paint_volume;
@ -164,17 +244,31 @@ meta_surface_actor_cull_out (MetaCullable *cullable,
meta_surface_actor_get_instance_private (surface_actor); meta_surface_actor_get_instance_private (surface_actor);
uint8_t opacity = clutter_actor_get_opacity (CLUTTER_ACTOR (cullable)); uint8_t opacity = clutter_actor_get_opacity (CLUTTER_ACTOR (cullable));
meta_shaped_texture_cull_out (priv->texture, unobscured_region, clip_region, opacity); set_unobscured_region (surface_actor, unobscured_region);
set_clip_region (surface_actor, clip_region);
if (opacity == 0xff)
{
cairo_region_t *opaque_region;
opaque_region = meta_shaped_texture_get_opaque_region (priv->texture);
if (opaque_region)
{
if (unobscured_region)
cairo_region_subtract (unobscured_region, opaque_region);
if (clip_region)
cairo_region_subtract (clip_region, opaque_region);
}
}
} }
static void static void
meta_surface_actor_reset_culling (MetaCullable *cullable) meta_surface_actor_reset_culling (MetaCullable *cullable)
{ {
MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable); MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable);
MetaSurfaceActorPrivate *priv =
meta_surface_actor_get_instance_private (surface_actor);
meta_shaped_texture_reset_culling (priv->texture); set_clip_region (surface_actor, NULL);
} }
static void static void
@ -232,18 +326,58 @@ meta_surface_actor_update_area (MetaSurfaceActor *self,
{ {
MetaSurfaceActorPrivate *priv = MetaSurfaceActorPrivate *priv =
meta_surface_actor_get_instance_private (self); meta_surface_actor_get_instance_private (self);
gboolean repaint_scheduled = FALSE;
cairo_rectangle_int_t clip;
if (meta_shaped_texture_update_area (priv->texture, x, y, width, height)) if (meta_shaped_texture_update_area (priv->texture, x, y, width, height, &clip))
{
cairo_region_t *unobscured_region;
unobscured_region = effective_unobscured_region (self);
if (unobscured_region)
{
cairo_region_t *intersection;
if (cairo_region_is_empty (unobscured_region))
return;
intersection = cairo_region_copy (unobscured_region);
cairo_region_intersect_rectangle (intersection, &clip);
if (!cairo_region_is_empty (intersection))
{
cairo_rectangle_int_t damage_rect;
cairo_region_get_extents (intersection, &damage_rect);
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (self), &damage_rect);
repaint_scheduled = TRUE;
}
cairo_region_destroy (intersection);
}
else
{
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (self), &clip);
repaint_scheduled = TRUE;
}
}
if (repaint_scheduled)
g_signal_emit (self, signals[REPAINT_SCHEDULED], 0); g_signal_emit (self, signals[REPAINT_SCHEDULED], 0);
} }
gboolean gboolean
meta_surface_actor_is_obscured (MetaSurfaceActor *self) meta_surface_actor_is_obscured (MetaSurfaceActor *self)
{ {
MetaSurfaceActorPrivate *priv = cairo_region_t *unobscured_region;
meta_surface_actor_get_instance_private (self);
return meta_shaped_texture_is_obscured (priv->texture); unobscured_region = effective_unobscured_region (self);
if (unobscured_region)
return cairo_region_is_empty (unobscured_region);
else
return FALSE;
} }
void void

View File

@ -45,11 +45,12 @@ void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
gboolean create_mipmaps); gboolean create_mipmaps);
META_EXPORT META_EXPORT
gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex, gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex,
int x, int x,
int y, int y,
int width, int width,
int height); int height,
cairo_rectangle_int_t *clip);
META_EXPORT META_EXPORT
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex); CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);