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 <zhigang.gong@linux.intel.com>
This commit is contained in:
Zhigang Gong 2012-06-11 13:05:48 +08:00 committed by Eric Anholt
parent 5325c800f7
commit 8ca16754f7
6 changed files with 86 additions and 44 deletions

View File

@ -458,17 +458,18 @@ _glamor_copy_n_to_n(DrawablePtr src,
int n_dst_region, i, j; int n_dst_region, i, j;
PixmapPtr temp_source_pixmap; PixmapPtr temp_source_pixmap;
glamor_pixmap_private *temp_source_priv = NULL; glamor_pixmap_private *temp_source_priv = NULL;
int temp_dx = 0, temp_dy = 0;
RegionTranslate(&region, dst_x_off, dst_y_off); RegionTranslate(&region, dst_x_off, dst_y_off);
if (!force_clip) if (!force_clip)
clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
&region, &n_dst_region, 0); &region, &n_dst_region, 0,
reverse, upsidedown);
else else
clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv, clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv,
&region, &n_dst_region, &region, &n_dst_region,
glamor_priv->max_fbo_size, 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++) for(i = 0; i < n_dst_region; i++)
{ {
int n_src_region; 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); -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_src_regions = glamor_compute_clipped_regions(src_pixmap_priv,
clipped_dst_regions[i].region, clipped_dst_regions[i].region,
&n_src_region, 0); &n_src_region, 0,
reverse, upsidedown);
DEBUGF("Source is large pixmap.\n"); DEBUGF("Source is large pixmap.\n");
for (j = 0; j < n_src_region; j++) 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 = *src_pixmap_priv;
temp_source_priv->large.box = src_pixmap_priv->large.box_array[clipped_src_regions[j].block_idx]; 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]; temp_source_priv->base.fbo = src_pixmap_priv->large.fbo_array[clipped_src_regions[j].block_idx];
/* XXX need revisit here. */ temp_source_priv->base.pixmap = temp_source_pixmap;
temp_dx = dx/* - src_x_off*/;
temp_dy = dy/* - src_y_off*/;
} }
assert(temp_source_pixmap || !(src_pixmap_priv == dst_pixmap_priv assert(temp_source_pixmap || !(src_pixmap_priv == dst_pixmap_priv
&& (clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx))); && (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, n_current_boxes, dx, dy, reverse,
upsidedown, bitplane, closure); upsidedown, bitplane, closure);
else { else {
ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, dst, gc, current_boxes, ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable,
n_current_boxes, temp_dx, temp_dy, reverse, dst, gc, current_boxes,
n_current_boxes, dx, dy, reverse,
upsidedown, bitplane, closure); upsidedown, bitplane, closure);
temp_source_priv->type = GLAMOR_MEMORY; temp_source_priv->type = GLAMOR_MEMORY;
temp_source_priv->base.fbo = NULL; temp_source_priv->base.fbo = NULL;

View File

@ -273,7 +273,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
box.x2 = x + width; box.x2 = x + width;
box.y2 = y + height; box.y2 = y + height;
RegionInitBoxes(&region, &box, 1); RegionInitBoxes(&region, &box, 1);
clipped_regions = glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0); clipped_regions = glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0, 0, 0);
for(i = 0; i < n_region; i++) for(i = 0; i < n_region; i++)
{ {
BoxPtr boxes; BoxPtr boxes;

View File

@ -22,14 +22,19 @@ __glamor_compute_clipped_regions(int block_w,
int x, int y, int x, int y,
int w, int h, int w, int h,
RegionPtr region, RegionPtr region,
int *n_region) int *n_region,
int reverse,
int upsidedown)
{ {
glamor_pixmap_clipped_regions * clipped_regions; glamor_pixmap_clipped_regions * clipped_regions;
BoxPtr extent; BoxPtr extent;
int start_x, start_y, end_x, end_y; int start_x, start_y, end_x, end_y;
int start_block_x, start_block_y; int start_block_x, start_block_y;
int end_block_x, end_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; int width, height;
RegionRec temp_region; RegionRec temp_region;
RegionPtr current_region; RegionPtr current_region;
@ -66,19 +71,41 @@ __glamor_compute_clipped_regions(int block_w,
* (end_block_y - start_block_y + 1), * (end_block_y - start_block_y + 1),
sizeof(*clipped_regions)); sizeof(*clipped_regions));
block_idx = (start_block_y - 1) * block_stride;
DEBUGF("startx %d starty %d endx %d endy %d \n", DEBUGF("startx %d starty %d endx %d endy %d \n",
start_x, start_y, end_x, end_y); 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_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); 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; block_idx += loop_block_stride;
temp_block_idx = block_idx + start_block_x; temp_block_idx = block_idx + loop_start_block_x;
for(i = start_block_x; for(i = loop_start_block_x;
i <= end_block_x; i++, temp_block_idx++) i != loop_end_block_x; i += delta_i, temp_block_idx += delta_i)
{ {
BoxRec temp_box; BoxRec temp_box;
temp_box.x1 = x + i * block_w; 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, glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv,
RegionPtr region, RegionPtr region,
int *n_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; glamor_pixmap_clipped_regions * clipped_regions, *inner_regions, *result_regions;
int i, j, x, y, k, inner_n_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, 0, 0,
priv->base.pixmap->drawable.width, priv->base.pixmap->drawable.width,
priv->base.pixmap->drawable.height, priv->base.pixmap->drawable.height,
region, n_region region, n_region, reverse, upsidedown
); );
if (clipped_regions == NULL) { if (clipped_regions == NULL) {
@ -184,7 +212,7 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv,
width, width,
height, height,
clipped_regions[i].region, clipped_regions[i].region,
&inner_n_regions); &inner_n_regions, reverse, upsidedown);
for(j = 0; j < inner_n_regions; j++) for(j = 0; j < inner_n_regions; j++)
{ {
result_regions[k].region = inner_regions[j].region; 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 * static glamor_pixmap_clipped_regions *
_glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv,
RegionPtr region, int *n_region, 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; glamor_pixmap_clipped_regions * clipped_regions;
BoxPtr extent; BoxPtr extent;
@ -338,7 +367,7 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv,
0, 0, 0, 0,
priv->base.pixmap->drawable.width, priv->base.pixmap->drawable.width,
priv->base.pixmap->drawable.height, priv->base.pixmap->drawable.height,
region, n_region region, n_region, reverse, upsidedown
); );
if (saved_region) if (saved_region)
RegionDestroy(region); RegionDestroy(region);
@ -592,9 +621,11 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv,
} }
glamor_pixmap_clipped_regions * 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. /* 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_pixmap_clipped_regions *
glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pixman_transform *transform, 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; BoxPtr temp_extent;
struct pixman_box32 temp_box; struct pixman_box32 temp_box;
@ -642,7 +674,8 @@ glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pix
temp_region, temp_region,
n_region, n_region,
repeat_type, repeat_type,
1); 1, reverse,
upsidedown);
DEBUGF("n_regions = %d \n", *n_region); DEBUGF("n_regions = %d \n", *n_region);
RegionDestroy(temp_region); RegionDestroy(temp_region);
@ -1036,12 +1069,13 @@ glamor_composite_largepixmap_region(CARD8 op,
region, region,
&n_dest_regions, &n_dest_regions,
fixed_block_width, fixed_block_width,
fixed_block_height); fixed_block_height,
0, 0);
else else
clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap_priv, clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap_priv,
region, region,
&n_dest_regions, &n_dest_regions,
0); 0, 0, 0);
DEBUGF("dest clipped result %d region: \n", n_dest_regions); DEBUGF("dest clipped result %d region: \n", n_dest_regions);
if (source_pixmap_priv if (source_pixmap_priv
&& (source_pixmap_priv == dest_pixmap_priv || source_pixmap_priv == mask_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); y_source - y_dest);
clipped_source_regions = glamor_compute_clipped_regions(source_pixmap_priv, clipped_source_regions = glamor_compute_clipped_regions(source_pixmap_priv,
clipped_dest_regions[i].region, clipped_dest_regions[i].region,
&n_source_regions, source_repeat_type); &n_source_regions, source_repeat_type,
0, 0);
is_normal_source_fbo = 1; is_normal_source_fbo = 1;
} }
else { else {
@ -1075,7 +1110,7 @@ glamor_composite_largepixmap_region(CARD8 op,
clipped_dest_regions[i].region, clipped_dest_regions[i].region,
&n_source_regions, &n_source_regions,
x_source - x_dest, y_source - y_dest, x_source - x_dest, y_source - y_dest,
source_repeat_type); source_repeat_type, 0, 0);
is_normal_source_fbo = 0; is_normal_source_fbo = 0;
if (n_source_regions == 0) { if (n_source_regions == 0) {
/* Pad the out-of-box region to (0,0,0,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); - y_source + y_mask);
clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv,
clipped_source_regions[j].region, clipped_source_regions[j].region,
&n_mask_regions, mask_repeat_type); &n_mask_regions, mask_repeat_type,
0, 0);
is_normal_mask_fbo = 1; is_normal_mask_fbo = 1;
} else if (is_normal_mask_fbo && !is_normal_source_fbo) { } else if (is_normal_mask_fbo && !is_normal_source_fbo) {
assert(n_source_regions == 1); assert(n_source_regions == 1);
@ -1116,7 +1152,8 @@ glamor_composite_largepixmap_region(CARD8 op,
- y_dest + y_mask); - y_dest + y_mask);
clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv,
clipped_dest_regions[i].region, clipped_dest_regions[i].region,
&n_mask_regions, mask_repeat_type); &n_mask_regions, mask_repeat_type,
0, 0);
is_normal_mask_fbo = 1; is_normal_mask_fbo = 1;
} else { } else {
/* This mask region has transform or repeatpad, we need clip it agains the previous /* 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, &n_mask_regions,
x_mask - x_dest, x_mask - x_dest,
y_mask - y_dest, y_mask - y_dest,
mask_repeat_type); mask_repeat_type, 0, 0);
else else
clipped_mask_regions = glamor_compute_transform_clipped_regions(mask_pixmap_priv, clipped_mask_regions = glamor_compute_transform_clipped_regions(mask_pixmap_priv,
mask->transform, mask->transform,
clipped_source_regions[j].region, clipped_source_regions[j].region,
&n_mask_regions, &n_mask_regions,
x_mask - x_source, y_mask - y_source, x_mask - x_source, y_mask - y_source,
mask_repeat_type); mask_repeat_type, 0, 0);
is_normal_mask_fbo = 0; is_normal_mask_fbo = 0;
if (n_mask_regions == 0) { if (n_mask_regions == 0) {
/* Pad the out-of-box region to (0,0,0,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); y_mask - y_dest);
clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv,
clipped_dest_regions[i].region, clipped_dest_regions[i].region,
&n_mask_regions, mask_repeat_type); &n_mask_regions, mask_repeat_type, 0, 0);
is_normal_mask_fbo = 1; is_normal_mask_fbo = 1;
} }
else { else {
@ -1243,7 +1280,7 @@ glamor_composite_largepixmap_region(CARD8 op,
clipped_dest_regions[i].region, clipped_dest_regions[i].region,
&n_mask_regions, &n_mask_regions,
x_mask - x_dest, y_mask - y_dest, x_mask - x_dest, y_mask - y_dest,
mask_repeat_type); mask_repeat_type, 0, 0);
is_normal_mask_fbo = 0; is_normal_mask_fbo = 0;
if (n_mask_regions == 0) { if (n_mask_regions == 0) {
/* Pad the out-of-box region to (0,0,0,0). */ /* Pad the out-of-box region to (0,0,0,0). */

View File

@ -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.x2 = x + w;
box.y2 = y + h; box.y2 = y + h;
RegionInitBoxes(&region, &box, 1); RegionInitBoxes(&region, &box, 1);
clipped_regions = glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0); clipped_regions = glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0, 0, 0);
DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap); DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap);
for(i = 0; i < n_region; i++) 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.x2 = x + w;
box.y2 = y + h; box.y2 = y + h;
RegionInitBoxes(&region, &box, 1); RegionInitBoxes(&region, &box, 1);
clipped_regions = glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0); clipped_regions = glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0, 0, 0);
DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h); DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h);
for(i = 0; i < n_region; i++) for(i = 0; i < n_region; i++)
{ {

View File

@ -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); int w, int h, glamor_access_t access);
glamor_pixmap_clipped_regions * 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_pixmap_clipped_regions *
glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv,
RegionPtr region, RegionPtr region,
int *n_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_pixmap_clipped_regions *
glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pixman_transform *transform, 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 Bool
glamor_composite_largepixmap_region(CARD8 op, glamor_composite_largepixmap_region(CARD8 op,

View File

@ -242,7 +242,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
box.y2 = y + height; box.y2 = y + height;
RegionInitBoxes(&region, &box, 1); RegionInitBoxes(&region, &box, 1);
clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
&region, &n_dst_region, 0); &region, &n_dst_region, 0, 0, 0);
for(i = 0; i < n_dst_region; i++) for(i = 0; i < n_dst_region; i++)
{ {
int n_src_region; 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); 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_src_regions = glamor_compute_clipped_regions(src_pixmap_priv,
clipped_dst_regions[i].region, 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); DEBUGF("got %d src regions %d \n", n_src_region);
for (j = 0; j < n_src_region; j++) for (j = 0; j < n_src_region; j++)
{ {