[Glamor] [PATCH 1/8] glamor_glyphs: Use glyph_to_dst as much as possible.

zhigang.gong at linux.intel.com zhigang.gong at linux.intel.com
Tue Jun 26 03:01:55 PDT 2012


From: Zhigang Gong <zhigang.gong at linux.intel.com>

To split a glyph's extent region to three sub-boxes
as below.

left box   2 x h
center box (w-4) x h
right box  2 x h

Take a simple glyph A as an example:
     *
  __* *__
   *****
  *     *
  ~~   ~~

The left box and right boxes are both 2 x 2. The center box
is 2 x 4.

And then we can check the inked area in left and right boxes.
And then latter, when detect overlapping, we can use these
three boxes to do the intersect cheking rather than a whole
large box. And in practice, this way, we can avoid most of
those faked overlapping case. And thus we can get much performance
benefit by this patch. The aa10text boost fom 1660000 to 320000.
Almost double the performance!

I will try to apply this method to cairo's gl backend
latter.

Signed-off-by: Zhigang Gong <zhigang.gong at linux.intel.com>
---
 src/glamor_glyphs.c |  347 ++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 287 insertions(+), 60 deletions(-)

diff --git a/src/glamor_glyphs.c b/src/glamor_glyphs.c
index 362e46f..476b485 100644
--- a/src/glamor_glyphs.c
+++ b/src/glamor_glyphs.c
@@ -16,7 +16,7 @@
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -33,7 +33,7 @@
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * Author: Owen Taylor <otaylor at fishsoup.net>
@@ -69,14 +69,20 @@
 
 typedef struct {
 	PicturePtr source;
-	glamor_composite_rect_t rects[GLYPH_BUFFER_SIZE];
+	glamor_composite_rect_t rects[GLYPH_BUFFER_SIZE + 4];
 	int count;
 } glamor_glyph_buffer_t;
 
+#define LEFT_SIDE 1
+#define RIGHT_SIDE 2
+
 struct glamor_glyph {
 	glamor_glyph_cache_t *cache;
 	uint16_t x, y;
 	uint16_t size, pos;
+	int y1,y2,y3,y4;  /* Use to check real intersect or not. */
+	Bool has_edge_y;
+	Bool cached;
 };
 
 typedef enum {
@@ -253,8 +259,8 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen,
 					  PictureMatchFormat
 					  (screen,
 					   pCachePixmap->
-				   drawable.depth,
-				   cache->picture->format),
+					   drawable.depth,
+					   cache->picture->format),
 					  0, NULL, serverClient,
 				  &error);
 			if (picture) {
@@ -264,7 +270,7 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen,
 					      NULL, picture,
 					      0, 0, 0, 0, 0,
 					      0,
-				      glyph->info.width,
+					      glyph->info.width,
 					      glyph->info.height);
 				FreePicture(picture, 0);
 			}
@@ -299,7 +305,8 @@ glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph)
 	if (priv == NULL)
 		return;
 
-	priv->cache->glyphs[priv->pos] = NULL;
+	if (priv->cached)
+		priv->cache->glyphs[priv->pos] = NULL;
 
 	glamor_glyph_set_private(glyph, NULL);
 	free(priv);
@@ -355,13 +362,16 @@ glamor_glyph_extents(int nlist,
  * bounding box, which appears to be good enough to catch most cases at least.
  */
 static Bool
-glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
+glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs,
+			PictFormatShort mask_format,
+			ScreenPtr screen, Bool check_fake_overlap)
 {
 	int x1, x2, y1, y2;
 	int n;
 	int x, y;
 	BoxRec extents;
 	Bool first = TRUE;
+	struct glamor_glyph *priv;
 
 	x = 0;
 	y = 0;
@@ -376,6 +386,7 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
 		list++;
 		while (n--) {
 			GlyphPtr glyph = *glyphs++;
+			BoxRec left_box, right_box;
 
 			if (glyph->info.width == 0
 			    || glyph->info.height == 0) {
@@ -383,17 +394,22 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
 				y += glyph->info.yOff;
 				continue;
 			}
-
+			if (mask_format
+			    && mask_format != GlyphPicture(glyph)[screen->myNum]->format)
+				return TRUE;
 			x1 = x - glyph->info.x;
 			if (x1 < MINSHORT)
 				x1 = MINSHORT;
 			y1 = y - glyph->info.y;
 			if (y1 < MINSHORT)
 				y1 = MINSHORT;
+			if (check_fake_overlap)
+				priv = glamor_glyph_get_private(glyph);
 			x2 = x1 + glyph->info.width;
+			y2 = y1 + glyph->info.height;
+
 			if (x2 > MAXSHORT)
 				x2 = MAXSHORT;
-			y2 = y1 + glyph->info.height;
 			if (y2 > MAXSHORT)
 				y2 = MAXSHORT;
 
@@ -402,18 +418,64 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
 				extents.y1 = y1;
 				extents.x2 = x2;
 				extents.y2 = y2;
+
+				if (check_fake_overlap && priv
+				    && priv->has_edge_y && glyph->info.yOff == 0) {
+					left_box.x1 = x1;
+					left_box.x2 = x1 + 2;
+					left_box.y1 = priv->y1;
+					left_box.y2 = priv->y2;
+
+					right_box.x1 = x2 - 2;
+					right_box.x2 = x2;
+					right_box.y1 = priv->y3;
+					right_box.y2 = priv->y4;
+				}
+
 				first = FALSE;
 			} else {
+
 				if (x1 < extents.x2 && x2 > extents.x1
 				    && y1 < extents.y2
 				    && y2 > extents.y1) {
-					return TRUE;
+					if (check_fake_overlap && priv
+					    && priv->has_edge_y && glyph->info.yOff == 0) {
+
+						if (x1 < left_box.x2 && x1 + 2 > left_box.x1
+						    && priv->y1 < left_box.y2 && priv->y2 > left_box.y1)
+							return TRUE;
+
+						if (x2 - 2 < right_box.x2 && x2 > right_box.x1
+						    && priv->y1 < right_box.y2 && priv->y2 > right_box.y1)
+							return TRUE;
+
+						if (x1 + 2 < extents.x2 && x2 - 2 > extents.x1)
+							return TRUE;
+					} else
+						return TRUE;
 				}
 
-				if (x1 < extents.x1)
+				if (x1 < extents.x1) {
 					extents.x1 = x1;
-				if (x2 > extents.x2)
+					if (check_fake_overlap && priv
+					    && priv->has_edge_y && glyph->info.yOff == 0) {
+						left_box.x1 = x1;
+						left_box.x2 = x1 + 2;
+						left_box.y1 = priv->y1;
+						left_box.y2 = priv->y2;
+					}
+				}
+				if (x2 > extents.x2) {
 					extents.x2 = x2;
+
+					if (check_fake_overlap && priv
+					    && priv->has_edge_y && glyph->info.yOff == 0) {
+						right_box.x1 = x2 - 2;
+						right_box.x2 = x2;
+						right_box.y1 = priv->y3;
+						right_box.y2 = priv->y4;
+					}
+				}
 				if (y1 < extents.y1)
 					extents.y1 = y1;
 				if (y2 > extents.y2)
@@ -448,6 +510,92 @@ glamor_glyph_size_to_mask(int size)
 	    glamor_glyph_count_to_mask(glamor_glyph_size_to_count(size));
 }
 
+static void
+glamor_glyph_priv_get_edge_extent(GlyphPtr glyph, struct glamor_glyph *priv,
+			     PicturePtr glyph_picture)
+{
+	Bool left_edge_inked, right_edge_inked;
+	PixmapPtr glyph_pixmap = (PixmapPtr) glyph_picture->pDrawable;
+	struct glamor_pixmap_private *pixmap_priv;
+	int j;
+	int y1, y2, y3, y4;
+	int bitsPerPixel;
+	int stride;
+	void *bits;
+	int width;
+
+	bitsPerPixel = glyph_pixmap->drawable.bitsPerPixel;
+	stride = glyph_pixmap->devKind;
+	bits = glyph_pixmap->devPrivate.ptr;
+	width = glyph->info.width;
+	pixmap_priv = glamor_get_pixmap_private(glyph_pixmap);
+
+	if (glyph_pixmap->drawable.width < 4
+	    || !(glyph_pixmap->drawable.depth == 8
+		|| glyph_pixmap->drawable.depth == 1
+		|| glyph_pixmap->drawable.depth == 32)) {
+		priv->has_edge_y = FALSE;
+		return;
+	}
+
+	y1 = y3 = MAXSHORT;
+	y2 = y4 = MINSHORT;
+
+	for(j = 0; j < glyph_pixmap->drawable.height; j++)
+	{
+		if (bitsPerPixel == 8) {
+			unsigned short *data;
+			data =	(unsigned short*)((unsigned char*)bits + stride * j);
+			left_edge_inked = (*data != 0);
+			data =	(unsigned short*)((unsigned char*)bits + stride * j + width - 2);
+			right_edge_inked = (*data !=0);
+		} else if (bitsPerPixel == 32) {
+			unsigned int *data, *data1;
+			data = (unsigned int*)bits + stride * j;
+			data1 = (unsigned int*)bits + stride * j + 1;
+			left_edge_inked = (*data != 0) || (*data1 != 0);
+			data = (unsigned int*)bits + stride * j + width - 2;
+			data1 = (unsigned int*)bits + stride * j + width - 1;
+			right_edge_inked = (*data != 0) || (*data1 != 0);
+		} else if (bitsPerPixel == 1) {
+			unsigned char temp;
+			left_edge_inked = ((*((unsigned char*)glyph_pixmap->devPrivate.ptr
+				+ glyph_pixmap->devKind * j) & 0x3) != 0);
+			temp = *((unsigned char*)glyph_pixmap->devPrivate.ptr
+				+ glyph_pixmap->devKind * j
+				+ (glyph_pixmap->drawable.width - 2)/8);
+			right_edge_inked = ((temp
+				    & (1 << ((glyph_pixmap->drawable.width - 2) % 8))) != 0);
+			if (!right_edge_inked) {
+				temp = *((unsigned char*)glyph_pixmap->devPrivate.ptr
+					+ glyph_pixmap->devKind * j
+					+ (glyph_pixmap->drawable.width - 1)/8);
+				right_edge_inked = ((temp
+					   & (1 << ((glyph_pixmap->drawable.width - 1) % 8))) != 0);
+			}
+		}
+		if (left_edge_inked) {
+			if (j < y1)
+				y1 = j;
+			if (j > y2)
+				y2 = j;
+		}
+		if (right_edge_inked) {
+			if (j < y3)
+				y3 = j;
+			if (j > y4)
+				y4 = j;
+		}
+	}
+
+	priv->y1 = y1;
+	priv->y2 = y2;
+	priv->y3 = y3;
+	priv->y4 = y4;
+	priv->has_edge_y = TRUE;
+	return;
+}
+
 static PicturePtr
 glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x,
 		   int *out_y)
@@ -457,7 +605,7 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x,
 	glamor_glyph_cache_t *cache =
 	    &glamor->glyphCaches[PICT_FORMAT_RGB(glyph_picture->format) !=
 				 0];
-	struct glamor_glyph *priv = NULL;
+	struct glamor_glyph *priv = NULL, *evicted_priv = NULL;
 	int size, mask, pos, s;
 
 	if (glyph->info.width > GLYPH_MAX_SIZE
@@ -472,6 +620,8 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x,
 	s = glamor_glyph_size_to_count(size);
 	mask = glamor_glyph_count_to_mask(s);
 	pos = (cache->count + s - 1) & mask;
+
+	priv = glamor_glyph_get_private(glyph);
 	if (pos < GLYPH_CACHE_SIZE) {
 		cache->count = pos + s;
 	} else {
@@ -482,34 +632,35 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x,
 			if (evicted == NULL)
 				continue;
 
-			priv = glamor_glyph_get_private(evicted);
-			if (priv->size >= s) {
+			evicted_priv = glamor_glyph_get_private(evicted);
+			assert(evicted_priv->pos == i);
+			if (evicted_priv->size >= s) {
 				cache->glyphs[i] = NULL;
-				glamor_glyph_set_private(evicted, NULL);
+				evicted_priv->cached = FALSE;
 				pos = cache->evict &
 				    glamor_glyph_size_to_mask(size);
 			} else
-				priv = NULL;
+				evicted_priv = NULL;
 			break;
 		}
-		if (priv == NULL) {
+		if (evicted_priv == NULL) {
 			int count = glamor_glyph_size_to_count(size);
 			mask = glamor_glyph_count_to_mask(count);
 			pos = cache->evict & mask;
 			for (s = 0; s < count; s++) {
 				GlyphPtr evicted = cache->glyphs[pos + s];
 				if (evicted != NULL) {
-					if (priv != NULL)
-						free(priv);
 
-					priv =
+					evicted_priv =
 					    glamor_glyph_get_private
 					    (evicted);
-					glamor_glyph_set_private(evicted,
-								 NULL);
+
+					assert(evicted_priv->pos == pos + s);
+					evicted_priv->cached = FALSE;
 					cache->glyphs[pos + s] = NULL;
 				}
 			}
+
 		}
 		/* And pick a new eviction position */
 		cache->evict = rand() % GLYPH_CACHE_SIZE;
@@ -519,9 +670,10 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x,
 		priv = malloc(sizeof(struct glamor_glyph));
 		if (priv == NULL)
 			return NULL;
+		glamor_glyph_set_private(glyph, priv);
+		priv->has_edge_y = FALSE;
 	}
 
-	glamor_glyph_set_private(glyph, priv);
 	cache->glyphs[pos] = glyph;
 
 	priv->cache = cache;
@@ -544,6 +696,10 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x,
 	glamor_glyph_cache_upload_glyph(screen, cache, glyph, priv->x,
 					priv->y);
 
+	if (priv->has_edge_y == FALSE && glyph->info.width >= 4)
+		glamor_glyph_priv_get_edge_extent(glyph, priv, glyph_picture);
+	priv->cached = TRUE;
+
 	*out_x = priv->x;
 	*out_y = priv->y;
 	return cache->picture;
@@ -554,6 +710,7 @@ static glamor_glyph_cache_result_t
 glamor_buffer_glyph(ScreenPtr screen,
 		    glamor_glyph_buffer_t * buffer,
 		    GlyphPtr glyph, int x_glyph, int y_glyph,
+		    int dx, int dy, int w, int h,
 		    glyphs_flush glyphs_flush, void *flush_arg)
 {
 	glamor_screen_private *glamor_screen =
@@ -588,23 +745,25 @@ glamor_buffer_glyph(ScreenPtr screen,
 
 	priv = glamor_glyph_get_private(glyph);
 
-	if (priv) {
+	if (priv && priv->cached) {
 		rect = &buffer->rects[buffer->count++];
-		rect->x_src = priv->x;
-		rect->y_src = priv->y;
+		rect->x_src = priv->x + dx;
+		rect->y_src = priv->y + dy;
 		if (buffer->source == NULL)
 			buffer->source = priv->cache->picture;
+		assert(priv->cache->glyphs[priv->pos] == glyph);
 	} else {
 		if (glyphs_flush)
 			(*glyphs_flush)(flush_arg);
 		source = glamor_glyph_cache(screen, glyph, &x, &y);
 		if (source != NULL) {
 			rect = &buffer->rects[buffer->count++];
-			rect->x_src = x;
-			rect->y_src = y;
+			rect->x_src = x + dx;
+			rect->y_src = y + dy;
 			if (buffer->source == NULL)
 				buffer->source = source;
 		} else {
+	/* Couldn't find the glyph in the cache, use the glyph picture directly */
 			source = GlyphPicture(glyph)[screen->myNum];
 			if (buffer->source
 			    && buffer->source != source
@@ -613,18 +772,16 @@ glamor_buffer_glyph(ScreenPtr screen,
 			buffer->source = source;
 
 			rect = &buffer->rects[buffer->count++];
-			rect->x_src = 0;
-			rect->y_src = 0;
+			rect->x_src = 0 + dx;
+			rect->y_src = 0 + dy;
 		}
+		priv = glamor_glyph_get_private(glyph);
 	}
 
 	rect->x_dst = x_glyph - glyph->info.x;
 	rect->y_dst = y_glyph - glyph->info.y;
-	rect->width = glyph->info.width;
-	rect->height = glyph->info.height;
-
-	/* Couldn't find the glyph in the cache, use the glyph picture directly */
-
+	rect->width = w;
+	rect->height = h;
 	return GLAMOR_GLYPH_SUCCESS;
 }
 
@@ -708,7 +865,6 @@ glamor_glyphs_via_mask(CARD8 op,
 	fill_rect.width = width;
 	fill_rect.height = height;
 	gc->ops->PolyFillRect(&mask_pixmap->drawable, gc, 1, &fill_rect);
-	
 	FreeScratchGC(gc);
 	x = -extents.x1;
 	y = -extents.y1;
@@ -734,6 +890,8 @@ glamor_glyphs_via_mask(CARD8 op,
 
 				glamor_buffer_glyph(screen, &buffer,
 						    glyph, x, y,
+						    0, 0,
+						    glyph->info.width, glyph->info.height,
 						    flush_func,
 						    (void*)&arg);
 			}
@@ -800,7 +958,8 @@ glamor_glyphs_to_dst(CARD8 op,
 		     PicturePtr dst,
 		     INT16 x_src,
 		     INT16 y_src,
-		     int nlist, GlyphListPtr list, GlyphPtr * glyphs)
+		     int nlist, GlyphListPtr list,
+		     GlyphPtr * glyphs)
 {
 	ScreenPtr screen = dst->pDrawable->pScreen;
 	int x = 0, y = 0;
@@ -809,14 +968,21 @@ glamor_glyphs_to_dst(CARD8 op,
 	GlyphPtr glyph;
 	glamor_glyph_buffer_t buffer;
 	struct glyphs_flush_dst_arg arg;
+	BoxPtr rects;
+	int nrect;
 
 	buffer.count = 0;
 	buffer.source = NULL;
+
+	rects = REGION_RECTS(dst->pCompositeClip);
+	nrect = REGION_NUM_RECTS(dst->pCompositeClip);
+
 	while (nlist--) {
 		x += list->xOff;
 		y += list->yOff;
 		n = list->len;
 		while (n--) {
+			int i;
 			glyph = *glyphs++;
 
 			if (glyph->info.width > 0
@@ -836,12 +1002,41 @@ glamor_glyphs_to_dst(CARD8 op,
 				} else
 					flush_func = NULL;
 
-				glamor_buffer_glyph(screen,
-						    &buffer,
-						    glyph, x, y,
-						    flush_func,
-						    (void*)&arg);
-
+				for (i = 0; i < nrect; i++) {
+					int dst_x, dst_y;
+					int dx, dy;
+					int x2, y2;
+
+					dst_x = x - glyph->info.x;
+					dst_y = y - glyph->info.y;
+					x2 = dst_x + glyph->info.width;
+					y2 = dst_y + glyph->info.height;
+					dx = dy = 0;
+					if (rects[i].y1 >= y2)
+						break;
+
+					if (dst_x < rects[i].x1)
+						dx = rects[i].x1 - dst_x, dst_x = rects[i].x1;
+					if (x2 > rects[i].x2)
+						x2 = rects[i].x2;
+					if (dst_y < rects[i].y1)
+						dy = rects[i].y1 - dst_y, dst_y = rects[i].y1;
+					if (y2 > rects[i].y2)
+						y2 = rects[i].y2;
+
+					if (dst_x < x2 && dst_y < y2) {
+
+						glamor_buffer_glyph(screen,
+								    &buffer,
+								    glyph,
+								    dst_x + glyph->info.x,
+								    dst_y + glyph->info.y,
+								    dx, dy,
+								    x2 - dst_x, y2 - dst_y,
+								    flush_func,
+								    (void*)&arg);
+					}
+				}
 			}
 
 			x += glyph->info.xOff;
@@ -869,13 +1064,14 @@ _glamor_glyphs(CARD8 op,
 	       PicturePtr dst,
 	       PictFormatPtr mask_format,
 	       INT16 x_src,
-	       INT16 y_src, int nlist, GlyphListPtr list, 
+	       INT16 y_src, int nlist, GlyphListPtr list,
 	       GlyphPtr * glyphs, Bool fallback)
 {
-	/* If we don't have a mask format but all the glyphs have the same format
-	 * and don't intersect, use the glyph format as mask format for the full
-	 * benefits of the glyph cache.
-	 */
+	Bool intersected = FALSE;
+	PictFormatShort format;
+	Bool format_checked = FALSE;
+	int check_fake_overlap = TRUE;
+
 	if (!mask_format) {
 		Bool same_format = TRUE;
 		int i;
@@ -889,19 +1085,50 @@ _glamor_glyphs(CARD8 op,
 			}
 		}
 
-		if (!same_format || (mask_format->depth != 1 &&
-				     glamor_glyphs_intersect(nlist, list,
-							     glyphs))) {
+		if (!same_format)
 			mask_format = NULL;
-		}
+		format_checked = TRUE;
 	}
 
-	if (mask_format)
-		glamor_glyphs_via_mask(op, src, dst, mask_format,
-				       x_src, y_src, nlist, list, glyphs);
+
+	if (mask_format && !format_checked)
+		format = mask_format->depth << 24 | mask_format->format;
 	else
+		format = 0;
+
+	if (!(op == PictOpOver
+	    || op == PictOpAdd
+	    || op == PictOpXor)) {
+	/* C = (0,0,0,0) D = glyphs , SRC = A, DEST = B (faked overlapped glyphs, overlapped with (0,0,0,0)).
+	 * For those op, (A IN (C ADD D)) OP B !=  (A IN D) OP ((A IN C) OP B)
+	 *		or (A IN (D ADD C)) OP B != (A IN C) OP ((A IN D) OP B)
+	 * We need to split the faked regions to three or two, and composite the disoverlapped small
+	 * boxes one by one. For other Ops, it's safe to composite the whole box.  */
+		check_fake_overlap = FALSE;
+	}
+	intersected = glamor_glyphs_intersect(nlist, list, glyphs,
+				format, dst->pDrawable->pScreen,
+				check_fake_overlap);
+
+	if (!intersected
+	     || (((nlist == 1 && list->len == 1) || op == PictOpAdd)
+	       && dst->format == (mask_format->depth << 24 | mask_format->format))) {
+
 		glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist,
 				     list, glyphs);
+		return TRUE;
+	}
+
+	if (mask_format)
+		glamor_glyphs_via_mask(op, src, dst, mask_format,
+				       x_src, y_src, nlist, list, glyphs);
+	else {
+		/* No mask_format and has intersect and glyphs have different format.
+		 * XXX do we need to implement a new glyphs rendering function for
+		 * this case?*/
+		glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, list, glyphs);
+	}
+
 	return TRUE;
 }
 
@@ -913,7 +1140,7 @@ glamor_glyphs(CARD8 op,
 	      INT16 x_src,
 	      INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
 {
-	_glamor_glyphs(op, src, dst, mask_format, x_src, 
+	_glamor_glyphs(op, src, dst, mask_format, x_src,
 		       y_src, nlist, list, glyphs, TRUE);
 }
 
@@ -923,10 +1150,10 @@ glamor_glyphs_nf(CARD8 op,
 		 PicturePtr dst,
 		 PictFormatPtr mask_format,
 		 INT16 x_src,
-		 INT16 y_src, int nlist, 
+		 INT16 y_src, int nlist,
 		 GlyphListPtr list, GlyphPtr * glyphs)
 {
-	return _glamor_glyphs(op, src, dst, mask_format, x_src, 
+	return _glamor_glyphs(op, src, dst, mask_format, x_src,
 			      y_src, nlist, list, glyphs, FALSE);
 }
 
-- 
1.7.4.4



More information about the Glamor mailing list