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;
PixmapPtr temp_source_pixmap;
glamor_pixmap_private *temp_source_priv = NULL;
int temp_dx = 0, temp_dy = 0;
RegionTranslate(&region, dst_x_off, dst_y_off);
if (!force_clip)
clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
&region, &n_dst_region, 0);
&region, &n_dst_region, 0,
reverse, upsidedown);
else
clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv,
&region, &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;

View File

@ -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(&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++)
{
BoxPtr boxes;

View File

@ -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). */

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.y2 = y + h;
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);
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(&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);
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);
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,

View File

@ -242,7 +242,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
box.y2 = y + height;
RegionInitBoxes(&region, &box, 1);
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++)
{
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++)
{