Commit 7319b10d authored by Jasper St. Pierre's avatar Jasper St. Pierre

MetaShapedTexture: Remove visible_pixels_region

When we were shaping the window with a cairo region, there was an easy
optimization to restrict painting only to the pixels we were going to
actually draw. With rounded corners, the amount of work we have to do
figure out what pixels isn't worth the small savings of not drawing the
completely transparent parts of the corners, so remove this optimization,
and the supporting meta_shaped_texture_get_visible_pixels_region()

https://bugzilla.gnome.org/show_bug.cgi?id=657639
parent 1265efcf
......@@ -76,8 +76,6 @@ struct _MetaShapedTexturePrivate
cairo_region_t *overlay_region;
cairo_path_t *overlay_path;
cairo_region_t *visible_pixels_region;
guint tex_width, tex_height;
guint mask_width, mask_height;
......@@ -110,7 +108,6 @@ meta_shaped_texture_init (MetaShapedTexture *self)
priv->shape_region = NULL;
priv->overlay_path = NULL;
priv->overlay_region = NULL;
priv->visible_pixels_region = NULL;
priv->paint_tower = meta_texture_tower_new ();
priv->texture = COGL_INVALID_HANDLE;
priv->mask_texture = COGL_INVALID_HANDLE;
......@@ -157,84 +154,14 @@ meta_shaped_texture_dirty_mask (MetaShapedTexture *stex)
{
MetaShapedTexturePrivate *priv = stex->priv;
if (priv->visible_pixels_region != NULL)
if (priv->mask_texture != COGL_INVALID_HANDLE)
{
cairo_region_destroy (priv->visible_pixels_region);
priv->visible_pixels_region = NULL;
if (priv->mask_texture != COGL_INVALID_HANDLE)
{
cogl_handle_unref (priv->mask_texture);
priv->mask_texture = COGL_INVALID_HANDLE;
}
if (priv->material != COGL_INVALID_HANDLE)
cogl_material_set_layer (priv->material, 1, COGL_INVALID_HANDLE);
cogl_handle_unref (priv->mask_texture);
priv->mask_texture = COGL_INVALID_HANDLE;
}
}
static void
scan_visible_region (MetaShapedTexture *stex,
guchar *mask_data,
int stride)
{
MetaShapedTexturePrivate *priv = stex->priv;
cairo_region_t *visible_pixels_region;
cairo_region_t *overlay_region;
int i, n_rects;
/* The visible pixels region contains all pixel values above 0.
* This is somewhat complicated when there's an overlay: we
* need to scan all regions potentially modified by it.
*/
if (priv->visible_pixels_region)
cairo_region_destroy (priv->visible_pixels_region);
priv->visible_pixels_region = cairo_region_copy (priv->shape_region);
visible_pixels_region = priv->visible_pixels_region;
overlay_region = priv->overlay_region;
/* With no overlay region, the visible region is defined
* by the mask region, so we don't need to scan anything. */
if (overlay_region == NULL)
return;
/* Subtract all the rectangles in the overlay region so that we can
* scan all the pixels potentially added by the overlay path. */
cairo_region_subtract (visible_pixels_region, overlay_region);
n_rects = cairo_region_num_rectangles (overlay_region);
for (i = 0; i < n_rects; i++)
{
int x, y;
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (overlay_region, i, &rect);
for (y = rect.y; y < (rect.y + rect.height); y++)
{
for (x = rect.x; x < (rect.x + rect.width); x++)
{
int w = x;
while (mask_data[y * stride + w] > 0 && w < (rect.x + rect.width))
w++;
if (w > 0)
{
cairo_rectangle_int_t tmp;
tmp.x = x;
tmp.y = y;
tmp.width = w - x;
tmp.height = 1;
cairo_region_union_rectangle (visible_pixels_region, &tmp);
x = w;
}
}
}
}
if (priv->material != COGL_INVALID_HANDLE)
cogl_material_set_layer (priv->material, 1, COGL_INVALID_HANDLE);
}
static void
......@@ -312,7 +239,7 @@ meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
meta_shaped_texture_dirty_mask (stex);
/* If we don't have a mask texture yet then create one */
if (priv->visible_pixels_region == NULL)
if (priv->mask_texture == COGL_INVALID_HANDLE)
{
guchar *mask_data;
int i;
......@@ -326,10 +253,6 @@ meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
(priv->overlay_region == NULL ||
cairo_region_num_rectangles (priv->overlay_region) == 0))
{
/* With no mask, the visible region is just
* {0, 0, tex_width, tex_height}. */
cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
priv->visible_pixels_region = cairo_region_create_rectangle (&rect);
return;
}
......@@ -364,7 +287,6 @@ meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
}
install_overlay_path (stex, mask_data, tex_width, tex_height, stride);
scan_visible_region (stex, mask_data, stride);
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
......@@ -499,6 +421,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
{
int n_rects;
int i;
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
/* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */
......@@ -516,6 +439,9 @@ meta_shaped_texture_paint (ClutterActor *actor)
cairo_region_get_rectangle (priv->clip_region, i, &rect);
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
continue;
x1 = rect.x;
y1 = rect.y;
x2 = rect.x + rect.width;
......@@ -751,24 +677,6 @@ set_cogl_texture (MetaShapedTexture *stex,
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
/**
* meta_shaped_texture_get_visible_pixels_region:
* @stex: a #MetaShapedTexture
*
* Return a region enclosing only visible pixels: those with
* alpha values above 0.
*
* Returns: a #cairo_region_t
*/
cairo_region_t *
meta_shaped_texture_get_visible_pixels_region (MetaShapedTexture *stex)
{
g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL);
meta_shaped_texture_ensure_mask (stex);
return stex->priv->visible_pixels_region;
}
/**
* meta_shaped_texture_set_pixmap:
* @stex: The #MetaShapedTexture
......@@ -857,8 +765,7 @@ meta_shaped_texture_set_overlay_path (MetaShapedTexture *stex,
* meta_shaped_texture_set_clip_region:
* @stex: a #MetaShapedTexture
* @clip_region: (transfer full): the region of the texture that
* is visible and should be painted. OWNERSHIP IS ASSUMED BY
* THE FUNCTION (for efficiency to avoid a copy.)
* is visible and should be painted.
*
* Provides a hint to the texture about what areas of the texture
* are not completely obscured and thus need to be painted. This
......@@ -884,7 +791,10 @@ meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
priv->clip_region = NULL;
}
priv->clip_region = clip_region;
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
else
priv->clip_region = NULL;
}
/**
......
......@@ -1749,22 +1749,9 @@ meta_window_actor_set_visible_region (MetaWindowActor *self,
cairo_region_t *visible_region)
{
MetaWindowActorPrivate *priv = self->priv;
cairo_region_t *texture_clip_region = NULL;
/* Get the area of the window texture that would be drawn if
* we weren't obscured at all
*/
texture_clip_region = meta_shaped_texture_get_visible_pixels_region (META_SHAPED_TEXTURE (priv->actor));
texture_clip_region = cairo_region_copy (texture_clip_region);
/* Then intersect that with the visible region to get the region
* that we actually need to redraw.
*/
cairo_region_intersect (texture_clip_region, visible_region);
/* Assumes ownership */
meta_shaped_texture_set_clip_region (META_SHAPED_TEXTURE (priv->actor),
texture_clip_region);
visible_region);
}
/**
......
......@@ -75,8 +75,6 @@ CoglHandle meta_shaped_texture_get_texture (MetaShapedTexture *stex);
void meta_shaped_texture_set_shape_region (MetaShapedTexture *stex,
cairo_region_t *region);
cairo_region_t *meta_shaped_texture_get_visible_pixels_region (MetaShapedTexture *stex);
void meta_shaped_texture_set_overlay_path (MetaShapedTexture *stex,
cairo_region_t *overlay_region,
cairo_path_t *overlay_path);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment