From 3ed87725dc79c6dd51598a4ed060ad8c53306d55 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 13:05:48 +0800 Subject: largepixmap: Fix the selfcopy issue. If the source and destination are the same pixmap/fbo, and we need to split the copy to small pieces. Then we do need to consider the sequence of the small pieces when the copy area has overlaps. This commit take the reverse/upsidedown into the clipping function, thus it can generate correct sequence and avoid corruption self copying. Signed-off-by: Zhigang Gong --- src/glamor_copyarea.c | 19 +++++----- src/glamor_fill.c | 2 +- src/glamor_largepixmap.c | 91 ++++++++++++++++++++++++++++++++++-------------- src/glamor_pixmap.c | 4 +-- src/glamor_priv.h | 10 ++++-- src/glamor_tile.c | 4 +-- 6 files changed, 86 insertions(+), 44 deletions(-) diff --git a/src/glamor_copyarea.c b/src/glamor_copyarea.c index 4d68dbe..bfd957a 100644 --- a/src/glamor_copyarea.c +++ b/src/glamor_copyarea.c @@ -458,17 +458,18 @@ _glamor_copy_n_to_n(DrawablePtr src, int n_dst_region, i, j; PixmapPtr temp_source_pixmap; glamor_pixmap_private *temp_source_priv = NULL; - int temp_dx = 0, temp_dy = 0; RegionTranslate(®ion, dst_x_off, dst_y_off); if (!force_clip) clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, - ®ion, &n_dst_region, 0); + ®ion, &n_dst_region, 0, + reverse, upsidedown); else clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv, ®ion, &n_dst_region, glamor_priv->max_fbo_size, - glamor_priv->max_fbo_size); + glamor_priv->max_fbo_size, + reverse, upsidedown); for(i = 0; i < n_dst_region; i++) { int n_src_region; @@ -484,7 +485,8 @@ _glamor_copy_n_to_n(DrawablePtr src, -dst_x_off + src_x_off + dx, -dst_y_off + src_y_off + dy); clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, clipped_dst_regions[i].region, - &n_src_region, 0); + &n_src_region, 0, + reverse, upsidedown); DEBUGF("Source is large pixmap.\n"); for (j = 0; j < n_src_region; j++) { @@ -507,9 +509,7 @@ _glamor_copy_n_to_n(DrawablePtr src, *temp_source_priv = *src_pixmap_priv; temp_source_priv->large.box = src_pixmap_priv->large.box_array[clipped_src_regions[j].block_idx]; temp_source_priv->base.fbo = src_pixmap_priv->large.fbo_array[clipped_src_regions[j].block_idx]; - /* XXX need revisit here. */ - temp_dx = dx/* - src_x_off*/; - temp_dy = dy/* - src_y_off*/; + temp_source_priv->base.pixmap = temp_source_pixmap; } assert(temp_source_pixmap || !(src_pixmap_priv == dst_pixmap_priv && (clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx))); @@ -531,8 +531,9 @@ _glamor_copy_n_to_n(DrawablePtr src, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); else { - ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, dst, gc, current_boxes, - n_current_boxes, temp_dx, temp_dy, reverse, + ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, + dst, gc, current_boxes, + n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); temp_source_priv->type = GLAMOR_MEMORY; temp_source_priv->base.fbo = NULL; diff --git a/src/glamor_fill.c b/src/glamor_fill.c index 5b84dd6..e371148 100644 --- a/src/glamor_fill.c +++ b/src/glamor_fill.c @@ -273,7 +273,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, box.x2 = x + width; box.y2 = y + height; RegionInitBoxes(®ion, &box, 1); - clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); for(i = 0; i < n_region; i++) { BoxPtr boxes; diff --git a/src/glamor_largepixmap.c b/src/glamor_largepixmap.c index 80cd6ad..f07095a 100644 --- a/src/glamor_largepixmap.c +++ b/src/glamor_largepixmap.c @@ -22,14 +22,19 @@ __glamor_compute_clipped_regions(int block_w, int x, int y, int w, int h, RegionPtr region, - int *n_region) + int *n_region, + int reverse, + int upsidedown) { glamor_pixmap_clipped_regions * clipped_regions; BoxPtr extent; int start_x, start_y, end_x, end_y; int start_block_x, start_block_y; int end_block_x, end_block_y; - int i, j; + int loop_start_block_x, loop_start_block_y; + int loop_end_block_x, loop_end_block_y; + int loop_block_stride; + int i, j, delta_i, delta_j; int width, height; RegionRec temp_region; RegionPtr current_region; @@ -66,19 +71,41 @@ __glamor_compute_clipped_regions(int block_w, * (end_block_y - start_block_y + 1), sizeof(*clipped_regions)); - block_idx = (start_block_y - 1) * block_stride; DEBUGF("startx %d starty %d endx %d endy %d \n", start_x, start_y, end_x, end_y); DEBUGF("start_block_x %d end_block_x %d \n", start_block_x, end_block_x); DEBUGF("start_block_y %d end_block_y %d \n", start_block_y, end_block_y); - for(j = start_block_y; j <= end_block_y; j++) + if (!reverse) { + loop_start_block_x = start_block_x; + loop_end_block_x = end_block_x + 1; + delta_i = 1; + } else { + loop_start_block_x = end_block_x; + loop_end_block_x = start_block_x - 1; + delta_i = -1; + } + + if (!upsidedown) { + loop_start_block_y = start_block_y; + loop_end_block_y = end_block_y + 1; + delta_j = 1; + } else { + loop_start_block_y = end_block_y; + loop_end_block_y = start_block_y - 1; + delta_j = -1; + } + + loop_block_stride = delta_j * block_stride; + block_idx = (loop_start_block_y - delta_j) * block_stride; + + for(j = loop_start_block_y; j != loop_end_block_y; j += delta_j) { - block_idx += block_stride; - temp_block_idx = block_idx + start_block_x; - for(i = start_block_x; - i <= end_block_x; i++, temp_block_idx++) + block_idx += loop_block_stride; + temp_block_idx = block_idx + loop_start_block_x; + for(i = loop_start_block_x; + i != loop_end_block_x; i += delta_i, temp_block_idx += delta_i) { BoxRec temp_box; temp_box.x1 = x + i * block_w; @@ -123,7 +150,8 @@ glamor_pixmap_clipped_regions * glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, RegionPtr region, int *n_region, - int inner_block_w, int inner_block_h) + int inner_block_w, int inner_block_h, + int reverse, int upsidedown) { glamor_pixmap_clipped_regions * clipped_regions, *inner_regions, *result_regions; int i, j, x, y, k, inner_n_regions; @@ -156,7 +184,7 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, 0, 0, priv->base.pixmap->drawable.width, priv->base.pixmap->drawable.height, - region, n_region + region, n_region, reverse, upsidedown ); if (clipped_regions == NULL) { @@ -184,7 +212,7 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, width, height, clipped_regions[i].region, - &inner_n_regions); + &inner_n_regions, reverse, upsidedown); for(j = 0; j < inner_n_regions; j++) { result_regions[k].region = inner_regions[j].region; @@ -293,7 +321,8 @@ _glamor_largepixmap_reflect_fixup(short *xy1, short *xy2, int wh) static glamor_pixmap_clipped_regions * _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, RegionPtr region, int *n_region, - int repeat_type, int is_transform) + int repeat_type, int is_transform, + int reverse, int upsidedown) { glamor_pixmap_clipped_regions * clipped_regions; BoxPtr extent; @@ -338,7 +367,7 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, 0, 0, priv->base.pixmap->drawable.width, priv->base.pixmap->drawable.height, - region, n_region + region, n_region, reverse, upsidedown ); if (saved_region) RegionDestroy(region); @@ -592,9 +621,11 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, } glamor_pixmap_clipped_regions * -glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, int *n_region, int repeat_type) +glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, + int *n_region, int repeat_type, + int reverse, int upsidedown) { - return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, 0); + return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, 0, reverse, upsidedown); } /* XXX overflow still exist. maybe we need to change to use region32. @@ -602,7 +633,8 @@ glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, in **/ glamor_pixmap_clipped_regions * glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pixman_transform *transform, - RegionPtr region, int *n_region, int dx, int dy, int repeat_type) + RegionPtr region, int *n_region, int dx, int dy, int repeat_type, + int reverse, int upsidedown) { BoxPtr temp_extent; struct pixman_box32 temp_box; @@ -642,7 +674,8 @@ glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pix temp_region, n_region, repeat_type, - 1); + 1, reverse, + upsidedown); DEBUGF("n_regions = %d \n", *n_region); RegionDestroy(temp_region); @@ -1036,12 +1069,13 @@ glamor_composite_largepixmap_region(CARD8 op, region, &n_dest_regions, fixed_block_width, - fixed_block_height); + fixed_block_height, + 0, 0); else clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap_priv, region, &n_dest_regions, - 0); + 0, 0, 0); DEBUGF("dest clipped result %d region: \n", n_dest_regions); if (source_pixmap_priv && (source_pixmap_priv == dest_pixmap_priv || source_pixmap_priv == mask_pixmap_priv) @@ -1066,7 +1100,8 @@ glamor_composite_largepixmap_region(CARD8 op, y_source - y_dest); clipped_source_regions = glamor_compute_clipped_regions(source_pixmap_priv, clipped_dest_regions[i].region, - &n_source_regions, source_repeat_type); + &n_source_regions, source_repeat_type, + 0, 0); is_normal_source_fbo = 1; } else { @@ -1075,7 +1110,7 @@ glamor_composite_largepixmap_region(CARD8 op, clipped_dest_regions[i].region, &n_source_regions, x_source - x_dest, y_source - y_dest, - source_repeat_type); + source_repeat_type, 0, 0); is_normal_source_fbo = 0; if (n_source_regions == 0) { /* Pad the out-of-box region to (0,0,0,0). */ @@ -1104,7 +1139,8 @@ glamor_composite_largepixmap_region(CARD8 op, - y_source + y_mask); clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, clipped_source_regions[j].region, - &n_mask_regions, mask_repeat_type); + &n_mask_regions, mask_repeat_type, + 0, 0); is_normal_mask_fbo = 1; } else if (is_normal_mask_fbo && !is_normal_source_fbo) { assert(n_source_regions == 1); @@ -1116,7 +1152,8 @@ glamor_composite_largepixmap_region(CARD8 op, - y_dest + y_mask); clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, clipped_dest_regions[i].region, - &n_mask_regions, mask_repeat_type); + &n_mask_regions, mask_repeat_type, + 0, 0); is_normal_mask_fbo = 1; } else { /* This mask region has transform or repeatpad, we need clip it agains the previous @@ -1128,14 +1165,14 @@ glamor_composite_largepixmap_region(CARD8 op, &n_mask_regions, x_mask - x_dest, y_mask - y_dest, - mask_repeat_type); + mask_repeat_type, 0, 0); else clipped_mask_regions = glamor_compute_transform_clipped_regions(mask_pixmap_priv, mask->transform, clipped_source_regions[j].region, &n_mask_regions, x_mask - x_source, y_mask - y_source, - mask_repeat_type); + mask_repeat_type, 0, 0); is_normal_mask_fbo = 0; if (n_mask_regions == 0) { /* Pad the out-of-box region to (0,0,0,0). */ @@ -1234,7 +1271,7 @@ glamor_composite_largepixmap_region(CARD8 op, y_mask - y_dest); clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, clipped_dest_regions[i].region, - &n_mask_regions, mask_repeat_type); + &n_mask_regions, mask_repeat_type, 0, 0); is_normal_mask_fbo = 1; } else { @@ -1243,7 +1280,7 @@ glamor_composite_largepixmap_region(CARD8 op, clipped_dest_regions[i].region, &n_mask_regions, x_mask - x_dest, y_mask - y_dest, - mask_repeat_type); + mask_repeat_type, 0, 0); is_normal_mask_fbo = 0; if (n_mask_regions == 0) { /* Pad the out-of-box region to (0,0,0,0). */ diff --git a/src/glamor_pixmap.c b/src/glamor_pixmap.c index ca38a2b..10d6df3 100644 --- a/src/glamor_pixmap.c +++ b/src/glamor_pixmap.c @@ -715,7 +715,7 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h box.x2 = x + w; box.y2 = y + h; RegionInitBoxes(®ion, &box, 1); - clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap); for(i = 0; i < n_region; i++) { @@ -1091,7 +1091,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, box.x2 = x + w; box.y2 = y + h; RegionInitBoxes(®ion, &box, 1); - clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h); for(i = 0; i < n_region; i++) { diff --git a/src/glamor_priv.h b/src/glamor_priv.h index c15f189..2af17f0 100644 --- a/src/glamor_priv.h +++ b/src/glamor_priv.h @@ -798,17 +798,21 @@ glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access); glamor_pixmap_clipped_regions * -glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, int *clipped_nbox, int repeat_type); +glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, + int *clipped_nbox, int repeat_type, + int reverse, int upsidedown); glamor_pixmap_clipped_regions * glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, RegionPtr region, int *n_region, - int inner_block_w, int inner_block_h); + int inner_block_w, int inner_block_h, + int reverse, int upsidedown); glamor_pixmap_clipped_regions * glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pixman_transform *transform, - RegionPtr region, int *n_region, int dx, int dy, int repeat_type); + RegionPtr region, int *n_region, int dx, int dy, int repeat_type, + int reverse, int upsidedown); Bool glamor_composite_largepixmap_region(CARD8 op, diff --git a/src/glamor_tile.c b/src/glamor_tile.c index 871479b..206485f 100644 --- a/src/glamor_tile.c +++ b/src/glamor_tile.c @@ -242,7 +242,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, box.y2 = y + height; RegionInitBoxes(®ion, &box, 1); clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, - ®ion, &n_dst_region, 0); + ®ion, &n_dst_region, 0, 0, 0); for(i = 0; i < n_dst_region; i++) { int n_src_region; @@ -258,7 +258,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, DEBUGF("tiled a large src pixmap. %dx%d \n", tile->drawable.width, tile->drawable.height); clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, clipped_dst_regions[i].region, - &n_src_region, 1); + &n_src_region, 1, 0, 0); DEBUGF("got %d src regions %d \n", n_src_region); for (j = 0; j < n_src_region; j++) { -- cgit v1.2.3