From 88c317fb1e6a9056acab4a76c0ee0bf283e001ce Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 4 Jul 2012 17:59:25 +0800 Subject: [PATCH] glamor_glyphs: Don't merge extents for different lists. If we merge all lists's extent together, than we may have some fail overlap checking. Here is a simple: A E B F C D The first list has vertical "ABCD". And the second list has two char "EF". When detecting E, it can successfully find it doesn't overlap with previous glyphs. But after that, the original code will merge the previous extent with E's extent, then the extent will cover "F", so when detecting F, it will be treated as overlapped. We can simply solve this issue by not merge extent from different list. We can union different list's extent to a global region. And then do the intersect checkint between that region and current glyph extent, then we can avoid that fail checking. Signed-off-by: Zhigang Gong --- glamor/glamor_glyphs.c | 110 ++++++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 39 deletions(-) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index f63feac77..bab2c2465 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -616,7 +616,6 @@ glyph_new_fixed_list(struct glamor_glyph_list *fixed_list, int *head_y, int *fixed_cnt, int type, - GlyphListPtr prev_list, BoxPtr prev_extents ) { @@ -708,26 +707,39 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, int x1, x2, y1, y2; int n; int x, y; - BoxRec extents, prev_extents; - Bool first = TRUE; + BoxPtr extents; + BoxRec prev_extents; + Bool first = TRUE, first_list = TRUE; + Bool need_free_list_region = FALSE; Bool need_free_fixed_list = FALSE; struct glamor_glyph *priv; Bool in_non_intersected_list = -1; - GlyphListPtr head_list, prev_list, saved_list; + GlyphListPtr head_list, saved_list; int head_x, head_y, head_pos; int fixed_cnt = 0; GlyphPtr *head_glyphs; GlyphListPtr cur_list = list; + RegionRec list_region; + RegionRec current_region; + BoxRec current_box; + + if (nlist > 1) { + pixman_region_init(&list_region); + need_free_list_region = TRUE; + } + + pixman_region_init(¤t_region); + + extents = pixman_region_extents(¤t_region); saved_list = list; x = 0; y = 0; - extents.x1 = 0; - extents.y1 = 0; - extents.x2 = 0; - extents.y2 = 0; - prev_extents = extents; - prev_list = list; + extents->x1 = 0; + extents->y1 = 0; + extents->x2 = 0; + extents->y2 = 0; + head_list = list; DEBUGF("has %d lists.\n", nlist); while (nlist--) { @@ -742,6 +754,18 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, left_to_right = TRUE; cur_list = list++; + if (unlikely(!first_list)) { + pixman_region_init_with_extents(¤t_region, extents); + pixman_region_union(&list_region, &list_region, ¤t_region); + first = TRUE; + } else { + head_list = cur_list; + head_pos = cur_list->len - n; + head_x = x; + head_y = y; + head_glyphs = glyphs; + } + DEBUGF("current list %p has %d glyphs\n", cur_list, n); while (n--) { GlyphPtr glyph = *glyphs++; @@ -777,17 +801,14 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, y2 = MAXSHORT; if (first) { - extents.x1 = x1; - extents.y1 = y1; - extents.x2 = x2; - extents.y2 = y2; + extents->x1 = x1; + extents->y1 = y1; + extents->x2 = x2; + extents->y2 = y2; + + prev_extents = *extents; first = FALSE; - head_list = cur_list; - head_pos = cur_list->len - n - 1; - head_x = x; - head_y = y; - head_glyphs = glyphs - 1; if (check_fake_overlap && priv && priv->has_edge_map && glyph->info.yOff == 0) { left_box.x1 = x1; @@ -802,10 +823,20 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, has_right_edge_box = TRUE; } } else { + if (unlikely(!first_list)) { + current_box.x1 = x1; + current_box.y1 = y1; + current_box.x2 = x2; + current_box.y2 = y2; + if (pixman_region_contains_rectangle(&list_region, ¤t_box) != PIXMAN_REGION_OUT) { + need_free_fixed_list = TRUE; + goto done; + } + } - if (x1 < extents.x2 && x2 > extents.x1 - && y1 < extents.y2 - && y2 > extents.y1) { + if (x1 < extents->x2 && x2 > extents->x1 + && y1 < extents->y2 + && y2 > extents->y1) { if (check_fake_overlap && (has_left_edge_box || has_right_edge_box) && priv->has_edge_map && glyph->info.yOff == 0) { @@ -814,7 +845,7 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, left_dx = has_left_edge_box ? 1 : 0; right_dx = has_right_edge_box ? 1 : 0; - if (x1 + 1 < extents.x2 - right_dx && x2 - 1 > extents.x1 + left_dx) + if (x1 + 1 < extents->x2 - right_dx && x2 - 1 > extents->x1 + left_dx) goto real_intersected; if (left_to_right && has_right_edge_box) { @@ -851,7 +882,7 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, goto real_intersected; } } else { - if (x1 < extents.x2 && x1 + 2 > extents.x1) + if (x1 < extents->x2 && x1 + 2 > extents->x1) goto real_intersected; } goto non_intersected; @@ -874,7 +905,6 @@ real_intersected: &head_x, &head_y, &fixed_cnt, NON_INTERSECTED, - prev_list, &prev_extents )){ need_free_fixed_list = TRUE; @@ -904,7 +934,6 @@ non_intersected: &head_x, &head_y, &fixed_cnt, INTERSECTED, - prev_list, &prev_extents )) { need_free_fixed_list = TRUE; @@ -913,12 +942,12 @@ non_intersected: } in_non_intersected_list = 1; } - prev_extents = extents; + prev_extents = *extents; } if (check_fake_overlap && priv && priv->has_edge_map && glyph->info.yOff == 0) { - if (!has_left_edge_box || x1 < extents.x1) { + if (!has_left_edge_box || x1 < extents->x1) { left_box.x1 = x1; left_box.x2 = x1 + 1; left_box.y1 = y1; @@ -926,7 +955,7 @@ non_intersected: left_priv = priv; } - if (!has_right_edge_box || x2 > extents.x2) { + if (!has_right_edge_box || x2 > extents->x2) { right_box.x1 = x2 - 2; right_box.x2 = x2 - 1; right_box.y1 = y1; @@ -935,20 +964,20 @@ non_intersected: } } - if (x1 < extents.x1) - extents.x1 = x1; - if (x2 > extents.x2) - extents.x2 = x2; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; - if (y1 < extents.y1) - extents.y1 = y1; - if (y2 > extents.y2) - extents.y2 = y2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; x += glyph->info.xOff; y += glyph->info.yOff; - prev_list = cur_list; } + first_list = FALSE; } if (in_non_intersected_list == 0 && fixed_cnt == 0) { @@ -973,7 +1002,6 @@ non_intersected: &head_x, &head_y, &fixed_cnt, (!in_non_intersected_list) | 0x80, - prev_list, &prev_extents )) { need_free_fixed_list = TRUE; @@ -982,6 +1010,10 @@ non_intersected: } done: + if (need_free_list_region) + pixman_region_fini(&list_region); + pixman_region_fini(¤t_region); + if (need_free_fixed_list && fixed_cnt >= 0) { while(fixed_cnt--) { free(fixed_list[fixed_cnt].list);