[mutter/wip/shape: 6/6] shaped-texture: Turn blending off when drawing entirely opaque regions
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/shape: 6/6] shaped-texture: Turn blending off when drawing entirely opaque regions
- Date: Tue, 27 Aug 2013 20:48:25 +0000 (UTC)
commit 55295d0fc3c33ce079982ca53422d8e8f6178905
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Tue Aug 27 16:17:34 2013 -0400
shaped-texture: Turn blending off when drawing entirely opaque regions
src/compositor/meta-shaped-texture.c | 171 ++++++++++++++++++++++++++++------
src/compositor/meta-window-actor.c | 3 +
src/meta/meta-shaped-texture.h | 3 +
3 files changed, 150 insertions(+), 27 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index acb0d55..abb7691 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -70,6 +70,7 @@ struct _MetaShapedTexturePrivate
CoglTexture *mask_texture;
cairo_region_t *clip_region;
+ cairo_region_t *opaque_region;
guint tex_width, tex_height;
@@ -145,6 +146,55 @@ get_masked_pipeline (CoglContext *ctx)
return cogl_pipeline_copy (template);
}
+static CoglPipeline *
+get_unblended_pipeline (CoglContext *ctx)
+{
+ static CoglPipeline *template = NULL;
+ if (G_UNLIKELY (template == NULL))
+ {
+ CoglColor color;
+ template = cogl_pipeline_new (ctx);
+ cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
+ cogl_pipeline_set_blend (template,
+ "RGBA = ADD (SRC_COLOR, 0)",
+ NULL);
+ cogl_pipeline_set_color (template, &color);
+ }
+
+ return cogl_pipeline_copy (template);
+}
+
+static void
+paint_clipped_rectangle (CoglFramebuffer *fb,
+ CoglPipeline *pipeline,
+ cairo_rectangle_int_t *rect,
+ ClutterActorBox *alloc)
+{
+ float coords[8];
+ float x1, y1, x2, y2;
+
+ x1 = rect->x;
+ y1 = rect->y;
+ x2 = rect->x + rect->width;
+ y2 = rect->y + rect->height;
+
+ coords[0] = rect->x / (alloc->x2 - alloc->x1);
+ coords[1] = rect->y / (alloc->y2 - alloc->y1);
+ coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1);
+ coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1);
+
+ coords[4] = coords[0];
+ coords[5] = coords[1];
+ coords[6] = coords[2];
+ coords[7] = coords[3];
+
+ cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline,
+ x1, y1, x2, y2,
+ &coords[0], 8);
+
+}
+
+
static void
meta_shaped_texture_paint (ClutterActor *actor)
{
@@ -156,6 +206,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
CoglContext *ctx;
CoglPipeline *pipeline;
CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
+ guchar opacity;
+ cairo_region_t *blended_region = NULL;
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
return;
@@ -194,6 +246,56 @@ meta_shaped_texture_paint (ClutterActor *actor)
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+ opacity = clutter_actor_get_paint_opacity (actor);
+
+ clutter_actor_get_allocation_box (actor, &alloc);
+
+ if (priv->opaque_region != NULL && opacity >= 1.0)
+ {
+ cairo_region_t *region;
+ int n_rects;
+ int i;
+
+ pipeline = get_unblended_pipeline (ctx);
+ cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
+
+ region = cairo_region_copy (priv->clip_region);
+ cairo_region_intersect (region, priv->opaque_region);
+
+ if (cairo_region_is_empty (region))
+ goto paint_blended;
+
+ n_rects = cairo_region_num_rectangles (region);
+ for (i = 0; i < n_rects; i++)
+ {
+ cairo_rectangle_int_t rect;
+ cairo_region_get_rectangle (region, i, &rect);
+ paint_clipped_rectangle (fb, pipeline, &rect, &alloc);
+ }
+
+ cairo_region_destroy (region);
+
+ if (priv->clip_region != NULL)
+ {
+ blended_region = cairo_region_copy (priv->clip_region);
+ }
+ else
+ {
+ cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
+ blended_region = cairo_region_create_rectangle (&rect);
+ }
+
+ cairo_region_subtract (blended_region, priv->opaque_region);
+ }
+
+ paint_blended:
+
+ if (blended_region == NULL && priv->clip_region != NULL)
+ blended_region = cairo_region_reference (priv->clip_region);
+
+ if (blended_region != NULL && cairo_region_is_empty (blended_region))
+ goto out;
+
if (priv->mask_texture == NULL)
{
pipeline = get_unmasked_pipeline (ctx);
@@ -208,18 +310,13 @@ meta_shaped_texture_paint (ClutterActor *actor)
{
CoglColor color;
- guchar opacity = clutter_actor_get_paint_opacity (actor);
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_pipeline_set_color (pipeline, &color);
}
- clutter_actor_get_allocation_box (actor, &alloc);
-
- if (priv->clip_region)
+ if (blended_region != NULL)
{
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 */
@@ -228,8 +325,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
n_rects = cairo_region_num_rectangles (priv->clip_region);
if (n_rects <= MAX_RECTS)
{
- float coords[8];
- float x1, y1, x2, y2;
+ int i;
+ cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
for (i = 0; i < n_rects; i++)
{
@@ -240,27 +337,10 @@ meta_shaped_texture_paint (ClutterActor *actor)
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
continue;
- x1 = rect.x;
- y1 = rect.y;
- x2 = rect.x + rect.width;
- y2 = rect.y + rect.height;
-
- coords[0] = rect.x / (alloc.x2 - alloc.x1);
- coords[1] = rect.y / (alloc.y2 - alloc.y1);
- coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1);
- coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1);
-
- coords[4] = coords[0];
- coords[5] = coords[1];
- coords[6] = coords[2];
- coords[7] = coords[3];
-
- cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline,
- x1, y1, x2, y2,
- &coords[0], 8);
+ paint_clipped_rectangle (fb, pipeline, &rect, &alloc);
}
- return;
+ goto out;
}
}
@@ -268,6 +348,10 @@ meta_shaped_texture_paint (ClutterActor *actor)
0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
+
+ out:
+ if (blended_region != NULL)
+ cairo_region_destroy (blended_region);
}
static void
@@ -610,6 +694,39 @@ meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
}
/**
+ * meta_shaped_texture_set_opaque_region:
+ * @stex: a #MetaShapedTexture
+ * @opaque_region: (transfer full): the region of the texture that
+ * can have blending turned off.
+ *
+ * As most windows have a large portion that does not require blending,
+ * we can easily turn off blending if we know the areas that do not
+ * require blending. This sets the region where we will not blend for
+ * optimization purposes.
+ */
+void
+meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
+ cairo_region_t *opaque_region)
+{
+ MetaShapedTexturePrivate *priv;
+
+ g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
+
+ priv = stex->priv;
+
+ if (priv->opaque_region)
+ {
+ cairo_region_destroy (priv->opaque_region);
+ priv->opaque_region = NULL;
+ }
+
+ if (opaque_region)
+ priv->opaque_region = cairo_region_reference (opaque_region);
+ else
+ priv->opaque_region = NULL;
+}
+
+/**
* meta_shaped_texture_get_image:
* @stex: A #MetaShapedTexture
* @clip: A clipping rectangle, to help prevent extra processing.
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index a32afed..4a28d10 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -2289,6 +2289,9 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
priv->opaque_region = NULL;
else
priv->opaque_region = cairo_region_reference (priv->shape_region);
+
+ meta_shaped_texture_set_opaque_region (META_SHAPED_TEXTURE (priv->actor),
+ priv->opaque_region);
}
static void
diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h
index 06b119b..9300cd3 100644
--- a/src/meta/meta-shaped-texture.h
+++ b/src/meta/meta-shaped-texture.h
@@ -87,6 +87,9 @@ void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
cairo_region_t *clip_region);
+void meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
+ cairo_region_t *opaque_region);
+
cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture *stex,
cairo_rectangle_int_t *clip);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]