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:
parent
425e65049b
commit
4c1fde9deb
@ -40,7 +40,6 @@ void meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
|
||||
void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
|
||||
int fallback_width,
|
||||
int fallback_height);
|
||||
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
|
||||
cairo_region_t * meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex);
|
||||
void meta_shaped_texture_set_transform (MetaShapedTexture *stex,
|
||||
MetaMonitorTransform transform);
|
||||
@ -51,11 +50,6 @@ void meta_shaped_texture_set_viewport_dst_size (MetaShapedTexture *stex,
|
||||
int dst_width,
|
||||
int dst_height);
|
||||
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,
|
||||
int buffer_scale);
|
||||
int meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex);
|
||||
|
@ -88,10 +88,6 @@ struct _MetaShapedTexture
|
||||
/* The region containing only fully opaque pixels */
|
||||
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;
|
||||
MetaMonitorTransform transform;
|
||||
gboolean has_viewport_src_rect;
|
||||
@ -219,34 +215,6 @@ ensure_size_valid (MetaShapedTexture *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
|
||||
meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
|
||||
{
|
||||
@ -271,12 +239,8 @@ meta_shaped_texture_dispose (GObject *object)
|
||||
stex->paint_tower = NULL;
|
||||
|
||||
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);
|
||||
set_unobscured_region (stex, NULL);
|
||||
set_clip_region (stex, NULL);
|
||||
|
||||
meta_shaped_texture_reset_pipelines (stex);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
effective_unobscured_region (MetaShapedTexture *stex)
|
||||
{
|
||||
return stex->unobscured_region;
|
||||
}
|
||||
|
||||
static void
|
||||
do_paint_content (MetaShapedTexture *stex,
|
||||
ClutterPaintNode *root_node,
|
||||
@ -599,19 +557,12 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
|
||||
if (use_opaque_region)
|
||||
{
|
||||
if (stex->clip_region)
|
||||
blended_tex_region = cairo_region_copy (stex->clip_region);
|
||||
else
|
||||
blended_tex_region = cairo_region_create_rectangle (&content_rect);
|
||||
|
||||
blended_tex_region = cairo_region_create_rectangle (&content_rect);
|
||||
cairo_region_subtract (blended_tex_region, stex->opaque_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stex->clip_region)
|
||||
blended_tex_region = cairo_region_reference (stex->clip_region);
|
||||
else
|
||||
blended_tex_region = NULL;
|
||||
blended_tex_region = NULL;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
if (use_opaque_region)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
int n_rects;
|
||||
int i;
|
||||
|
||||
if (stex->clip_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))
|
||||
if (!cairo_region_is_empty (stex->opaque_region))
|
||||
{
|
||||
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_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++)
|
||||
{
|
||||
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,
|
||||
opaque_pipeline,
|
||||
&rect, alloc);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
/* Now, go ahead and paint the blended parts. */
|
||||
@ -786,9 +724,6 @@ meta_shaped_texture_paint_content (ClutterContent *content,
|
||||
CoglTexture *paint_tex = NULL;
|
||||
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
|
||||
* used together with SGIS_generate_mipmap, however this is very
|
||||
* 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));
|
||||
}
|
||||
|
||||
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:
|
||||
* @stex: #MetaShapedTexture
|
||||
@ -891,6 +815,7 @@ meta_shaped_texture_is_obscured (MetaShapedTexture *stex)
|
||||
* @y: the y coordinate of the damaged area
|
||||
* @width: the width 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
|
||||
* 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
|
||||
*/
|
||||
gboolean
|
||||
meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_rectangle_int_t *clip)
|
||||
{
|
||||
cairo_region_t *unobscured_region;
|
||||
cairo_rectangle_int_t clip;
|
||||
MetaMonitorTransform inverted_transform;
|
||||
|
||||
if (stex->texture == NULL)
|
||||
return FALSE;
|
||||
|
||||
clip = (cairo_rectangle_int_t) {
|
||||
*clip = (cairo_rectangle_int_t) {
|
||||
.x = x,
|
||||
.y = y,
|
||||
.width = width,
|
||||
.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);
|
||||
ensure_size_valid (stex);
|
||||
meta_rectangle_transform (&clip,
|
||||
meta_rectangle_transform (clip,
|
||||
inverted_transform,
|
||||
stex->dst_width,
|
||||
stex->dst_height,
|
||||
&clip);
|
||||
clip);
|
||||
|
||||
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_height = ceilf (viewport.size.height);
|
||||
|
||||
meta_rectangle_crop_and_scale (&clip,
|
||||
meta_rectangle_crop_and_scale (clip,
|
||||
&inverted_viewport,
|
||||
inverted_dst_width,
|
||||
inverted_dst_height,
|
||||
&clip);
|
||||
clip);
|
||||
}
|
||||
|
||||
meta_texture_tower_update_area (stex->paint_tower,
|
||||
@ -996,36 +925,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
stex->fast_updates++;
|
||||
}
|
||||
|
||||
unobscured_region = effective_unobscured_region (stex);
|
||||
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;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1455,34 +1355,3 @@ meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex)
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -30,6 +30,10 @@ typedef struct _MetaSurfaceActorPrivate
|
||||
|
||||
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 */
|
||||
cairo_region_t *pending_damage;
|
||||
guint frozen : 1;
|
||||
@ -51,6 +55,78 @@ enum
|
||||
|
||||
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
|
||||
meta_surface_actor_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
@ -126,6 +202,9 @@ meta_surface_actor_dispose (GObject *object)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -136,6 +215,7 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_surface_actor_dispose;
|
||||
actor_class->paint = meta_surface_actor_paint;
|
||||
actor_class->pick = meta_surface_actor_pick;
|
||||
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);
|
||||
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
|
||||
meta_surface_actor_reset_culling (MetaCullable *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
|
||||
@ -232,18 +326,58 @@ meta_surface_actor_update_area (MetaSurfaceActor *self,
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv =
|
||||
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);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_obscured (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv =
|
||||
meta_surface_actor_get_instance_private (self);
|
||||
cairo_region_t *unobscured_region;
|
||||
|
||||
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
|
||||
|
@ -45,11 +45,12 @@ void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
gboolean create_mipmaps);
|
||||
|
||||
META_EXPORT
|
||||
gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_rectangle_int_t *clip);
|
||||
|
||||
META_EXPORT
|
||||
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
|
||||
|
Loading…
Reference in New Issue
Block a user