diff options
author | Zhigang Gong <zhigang.gong@linux.intel.com> | 2012-06-25 16:37:22 +0800 |
---|---|---|
committer | Zhigang Gong <zhigang.gong@linux.intel.com> | 2012-07-03 15:40:34 +0800 |
commit | 63fb516af37d07f11b4e8d52338354de98885425 (patch) | |
tree | 7d057d2abcea740bd886201d614055f2cf6f111c | |
parent | 07177a4842851a5ee611bdff6693bdd81c9828c1 (diff) |
glamor_composite_glyph: Optimize glyphs with non-solid pattern.
Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
-rw-r--r-- | src/glamor_render.c | 88 |
1 files changed, 78 insertions, 10 deletions
diff --git a/src/glamor_render.c b/src/glamor_render.c index b33d969..e2be4d7 100644 --- a/src/glamor_render.c +++ b/src/glamor_render.c @@ -1916,12 +1916,48 @@ glamor_composite_nf(CARD8 op, FALSE); } +static void +glamor_get_src_rect_extent(int nrect, + glamor_composite_rect_t *rects, + BoxPtr extent) +{ + extent->x1 = MAXSHORT; + extent->y1 = MAXSHORT; + extent->x2 = MINSHORT; + extent->y2 = MINSHORT; + + while(nrect--) { + if (extent->x1 > rects->x_src) + extent->x1 = rects->x_src; + if (extent->y1 > rects->y_src) + extent->y1 = rects->y_src; + if (extent->x2 < rects->x_src + rects->width) + extent->x2 = rects->x_src + rects->width; + if (extent->y2 < rects->y_src + rects->height) + extent->y2 = rects->y_src + rects->height; + rects++; + } +} + +static void +glamor_composite_src_rect_translate(int nrect, + glamor_composite_rect_t *rects, + int x, int y) +{ + while(nrect--) { + rects->x_src += x; + rects->y_src += y; + rects++; + } +} + void glamor_composite_glyph_rects(CARD8 op, PicturePtr src, PicturePtr mask, PicturePtr dst, int nrect, glamor_composite_rect_t * rects) { int n; + PicturePtr temp_src = NULL; glamor_composite_rect_t *r; Bool ok; @@ -1933,41 +1969,69 @@ glamor_composite_glyph_rects(CARD8 op, glamor_pixmap_private *src_pixmap_priv = NULL; glamor_pixmap_private *mask_pixmap_priv = NULL; glamor_pixmap_private *dst_pixmap_priv; + glamor_pixmap_private *temp_src_priv = NULL; + BoxRec src_extent; + + dst_pixmap_priv = glamor_get_pixmap_private + (glamor_get_drawable_pixmap(dst->pDrawable)); - dst_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(dst->pDrawable)); if (mask && mask->pDrawable) - mask_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(mask->pDrawable)); + mask_pixmap_priv = glamor_get_pixmap_private + (glamor_get_drawable_pixmap(mask->pDrawable)); if (src->pDrawable) - src_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(src->pDrawable)); + src_pixmap_priv = glamor_get_pixmap_private + (glamor_get_drawable_pixmap(src->pDrawable)); + + if (!src->pDrawable + && (src->pSourcePict->type != SourcePictTypeSolidFill)) { + glamor_get_src_rect_extent(nrect, rects, &src_extent); + temp_src = glamor_convert_gradient_picture(dst->pDrawable->pScreen, + src, + src_extent.x1, src_extent.y1, + src_extent.x2 - src_extent.x1, + src_extent.y2 - src_extent.y1); + if (!temp_src) + goto fallback; + + temp_src_priv = glamor_get_pixmap_private + ((PixmapPtr)(temp_src->pDrawable)); + glamor_composite_src_rect_translate(nrect, rects, + -src_extent.x1, -src_extent.y1); + } else { + temp_src = src; + temp_src_priv = src_pixmap_priv; + } if (mask && mask->componentAlpha) { if (op == PictOpOver) { ok = glamor_composite_with_shader(PictOpOutReverse, - src, mask, dst, src_pixmap_priv, + temp_src, mask, dst, temp_src_priv, mask_pixmap_priv, dst_pixmap_priv, nrect, rects); - if (!ok) + if (!ok) { goto fallback; + } ok |= glamor_composite_with_shader(PictOpAdd, - src, mask, dst, src_pixmap_priv, + temp_src, mask, dst, temp_src_priv, mask_pixmap_priv, dst_pixmap_priv, nrect, rects); if (ok) - return; + goto done; assert(0); } } else { - if (glamor_composite_with_shader(op, src, mask, dst, src_pixmap_priv, + if (glamor_composite_with_shader(op, temp_src, mask, dst, temp_src_priv, mask_pixmap_priv, dst_pixmap_priv, nrect, rects)) - return; + goto done; } } + fallback: n = nrect; r = rects; while (n--) { CompositePicture(op, - src, + temp_src ? temp_src : src, mask, dst, r->x_src, r->y_src, @@ -1975,6 +2039,10 @@ fallback: r->x_dst, r->y_dst, r->width, r->height); r++; } + +done: + if (temp_src && temp_src != src) + FreePicture(temp_src, 0); } static Bool |