Commit 01a47c7d authored by Jasper St. Pierre's avatar Jasper St. Pierre

shaped-texture: If we have too many rectangles, don't paint the opaque

region first

If we're going to render the entire texture blended, then don't bother
painting the unblended stuff, since we're just going to draw on top
anyway.
parent 3ee09c62
......@@ -298,10 +298,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
guchar opacity;
CoglContext *ctx;
CoglFramebuffer *fb;
CoglPipeline *pipeline = NULL;
CoglTexture *paint_tex;
ClutterActorBox alloc;
cairo_region_t *blended_region = NULL;
CoglPipelineFilter filter;
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
......@@ -339,6 +337,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
/* Use nearest-pixel interpolation if the texture is unscaled. This
* improves performance, especially with software rendering.
*/
......@@ -354,7 +354,45 @@ meta_shaped_texture_paint (ClutterActor *actor)
opacity = clutter_actor_get_paint_opacity (actor);
clutter_actor_get_allocation_box (actor, &alloc);
if (priv->opaque_region != NULL && opacity == 255)
cairo_region_t *blended_region;
gboolean use_opaque_region = (priv->opaque_region != NULL && opacity == 255);
if (use_opaque_region)
{
if (priv->clip_region != NULL)
blended_region = cairo_region_copy (priv->clip_region);
else
blended_region = cairo_region_create_rectangle (&tex_rect);
cairo_region_subtract (blended_region, priv->opaque_region);
}
else
{
if (priv->clip_region != NULL)
blended_region = cairo_region_reference (priv->clip_region);
else
blended_region = NULL;
}
/* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */
#define MAX_RECTS 16
if (blended_region != NULL)
{
int n_rects = cairo_region_num_rectangles (blended_region);
if (n_rects > MAX_RECTS)
{
/* Fall back to taking the fully blended path. */
use_opaque_region = FALSE;
cairo_region_destroy (blended_region);
blended_region = NULL;
}
}
/* First, paint the unblended parts, which are part of the opaque region. */
if (use_opaque_region)
{
CoglPipeline *opaque_pipeline;
cairo_region_t *region;
......@@ -371,9 +409,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
region = cairo_region_reference (priv->opaque_region);
}
if (cairo_region_is_empty (region))
goto paint_blended;
if (!cairo_region_is_empty (region))
{
opaque_pipeline = get_unblended_pipeline (ctx);
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
......@@ -387,87 +424,60 @@ meta_shaped_texture_paint (ClutterActor *actor)
}
cogl_object_unref (opaque_pipeline);
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:
cairo_region_destroy (region);
}
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;
/* Now, go ahead and paint the blended parts. */
{
CoglPipeline *blended_pipeline;
if (priv->mask_texture == NULL)
{
pipeline = get_unmasked_pipeline (ctx);
blended_pipeline = get_unmasked_pipeline (ctx);
}
else
{
pipeline = get_masked_pipeline (ctx);
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
cogl_pipeline_set_layer_filters (pipeline, 1, filter, filter);
blended_pipeline = get_masked_pipeline (ctx);
cogl_pipeline_set_layer_texture (blended_pipeline, 1, priv->mask_texture);
cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
}
cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter);
cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter);
{
CoglColor color;
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_pipeline_set_color (pipeline, &color);
}
if (blended_region != NULL)
{
int n_rects;
/* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */
# define MAX_RECTS 16
cogl_pipeline_set_color (blended_pipeline, &color);
n_rects = cairo_region_num_rectangles (blended_region);
if (n_rects <= MAX_RECTS)
if (blended_region != NULL && !cairo_region_is_empty (blended_region))
{
int i;
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
int n_rects = cairo_region_num_rectangles (blended_region);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (blended_region, i, &rect);
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
continue;
paint_clipped_rectangle (fb, pipeline, &rect, &alloc);
paint_clipped_rectangle (fb, blended_pipeline, &rect, &alloc);
}
goto out;
}
}
cogl_framebuffer_draw_rectangle (fb, pipeline,
else
{
cogl_framebuffer_draw_rectangle (fb, blended_pipeline,
0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
}
cogl_object_unref (blended_pipeline);
}
out:
if (pipeline != NULL)
cogl_object_unref (pipeline);
if (blended_region != NULL)
cairo_region_destroy (blended_region);
}
......
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