diff options
Diffstat (limited to 'xorg-server/glamor/glamor_largepixmap.c')
-rw-r--r-- | xorg-server/glamor/glamor_largepixmap.c | 2429 |
1 files changed, 1262 insertions, 1167 deletions
diff --git a/xorg-server/glamor/glamor_largepixmap.c b/xorg-server/glamor/glamor_largepixmap.c index 91ee8f2df..b8c064038 100644 --- a/xorg-server/glamor/glamor_largepixmap.c +++ b/xorg-server/glamor/glamor_largepixmap.c @@ -17,117 +17,117 @@ static glamor_pixmap_clipped_regions * __glamor_compute_clipped_regions(int block_w, - int block_h, - int block_stride, - int x, int y, - int w, int h, - RegionPtr region, - int *n_region, - int reverse, - int upsidedown) + int block_h, + int block_stride, + int x, int y, + int w, int h, + RegionPtr 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 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; - RegionRec temp_region; - RegionPtr current_region; - int block_idx; - int k = 0; - int temp_block_idx; - - extent = RegionExtents(region); - start_x = MAX(x, extent->x1); - start_y = MAX(y, extent->y1); - end_x = MIN(x + w, extent->x2); - end_y = MIN(y + h, extent->y2); - - DEBUGF("start compute clipped regions:\n"); - DEBUGF("block w %d h %d x %d y %d w %d h %d, block_stride %d \n", - block_w, block_h, x, y, w, h, block_stride); - DEBUGRegionPrint(region); - - DEBUGF("start_x %d start_y %d end_x %d end_y %d \n", start_x, start_y, end_x, end_y); - - if (start_x >= end_x || start_y >= end_y) { - *n_region = 0; - return NULL; - } - - start_block_x = (start_x - x)/ block_w; - start_block_y = (start_y - y)/ block_h; - end_block_x = (end_x - x)/ block_w; - end_block_y = (end_y - y)/ block_h; - - clipped_regions = calloc((end_block_x - start_block_x + 1) - * (end_block_y - start_block_y + 1), - sizeof(*clipped_regions)); - - - 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); - - 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 += 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; - temp_box.y1 = y + j * block_h; - temp_box.x2 = MIN(temp_box.x1 + block_w, end_x); - temp_box.y2 = MIN(temp_box.y1 + block_h, end_y); - RegionInitBoxes(&temp_region, &temp_box, 1); - DEBUGF("block idx %d \n",temp_block_idx); - DEBUGRegionPrint(&temp_region); - current_region = RegionCreate(NULL, 4); - RegionIntersect(current_region, &temp_region, region); - DEBUGF("i %d j %d region: \n",i ,j); - DEBUGRegionPrint(current_region); - if (RegionNumRects(current_region)) { - clipped_regions[k].region = current_region; - clipped_regions[k].block_idx = temp_block_idx; - k++; - } else - RegionDestroy(current_region); - RegionUninit(&temp_region); - } - } - - *n_region = k; - return clipped_regions; + 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 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; + RegionRec temp_region; + RegionPtr current_region; + int block_idx; + int k = 0; + int temp_block_idx; + + extent = RegionExtents(region); + start_x = MAX(x, extent->x1); + start_y = MAX(y, extent->y1); + end_x = MIN(x + w, extent->x2); + end_y = MIN(y + h, extent->y2); + + DEBUGF("start compute clipped regions:\n"); + DEBUGF("block w %d h %d x %d y %d w %d h %d, block_stride %d \n", + block_w, block_h, x, y, w, h, block_stride); + DEBUGRegionPrint(region); + + DEBUGF("start_x %d start_y %d end_x %d end_y %d \n", start_x, start_y, + end_x, end_y); + + if (start_x >= end_x || start_y >= end_y) { + *n_region = 0; + return NULL; + } + + start_block_x = (start_x - x) / block_w; + start_block_y = (start_y - y) / block_h; + end_block_x = (end_x - x) / block_w; + end_block_y = (end_y - y) / block_h; + + clipped_regions = calloc((end_block_x - start_block_x + 1) + * (end_block_y - start_block_y + 1), + sizeof(*clipped_regions)); + + 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); + + 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 += 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; + temp_box.y1 = y + j * block_h; + temp_box.x2 = MIN(temp_box.x1 + block_w, end_x); + temp_box.y2 = MIN(temp_box.y1 + block_h, end_y); + RegionInitBoxes(&temp_region, &temp_box, 1); + DEBUGF("block idx %d \n", temp_block_idx); + DEBUGRegionPrint(&temp_region); + current_region = RegionCreate(NULL, 4); + RegionIntersect(current_region, &temp_region, region); + DEBUGF("i %d j %d region: \n", i, j); + DEBUGRegionPrint(current_region); + if (RegionNumRects(current_region)) { + clipped_regions[k].region = current_region; + clipped_regions[k].block_idx = temp_block_idx; + k++; + } + else + RegionDestroy(current_region); + RegionUninit(&temp_region); + } + } + + *n_region = k; + return clipped_regions; } /** @@ -145,82 +145,87 @@ __glamor_compute_clipped_regions(int block_w, 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 reverse, int upsidedown) + RegionPtr region, + int *n_region, + 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; - int width, height; - glamor_pixmap_private_large_t *priv; - priv = &pixmap_priv->large; - - DEBUGF("ext called \n"); - - if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { - clipped_regions = calloc(1, sizeof(*clipped_regions)); - if (clipped_regions == NULL) { - *n_region = 0; - return NULL; - } - clipped_regions[0].region = RegionCreate(NULL, 1); - clipped_regions[0].block_idx = 0; - RegionCopy(clipped_regions[0].region, region); - *n_region = 1; - priv->block_w = priv->base.pixmap->drawable.width; - priv->block_h = priv->base.pixmap->drawable.height; - priv->box_array = &priv->box; - priv->box.x1 = priv->box.y1 = 0; - priv->box.x2 = priv->block_w; - priv->box.y2 = priv->block_h; - } else { - clipped_regions = __glamor_compute_clipped_regions(priv->block_w, - priv->block_h, - priv->block_wcnt, - 0, 0, - priv->base.pixmap->drawable.width, - priv->base.pixmap->drawable.height, - region, n_region, reverse, upsidedown - ); - - if (clipped_regions == NULL) { - *n_region = 0; - return NULL; - } - } - if (inner_block_w >= priv->block_w - && inner_block_h >= priv->block_h) - return clipped_regions; - result_regions = calloc(*n_region - * ((priv->block_w + inner_block_w - 1)/inner_block_w) - * ((priv->block_h + inner_block_h - 1)/ inner_block_h), - sizeof(*result_regions)); - k = 0; - for(i = 0; i < *n_region; i++) - { - x = priv->box_array[clipped_regions[i].block_idx].x1; - y = priv->box_array[clipped_regions[i].block_idx].y1; - width = priv->box_array[clipped_regions[i].block_idx].x2 - x; - height = priv->box_array[clipped_regions[i].block_idx].y2 - y; - inner_regions = __glamor_compute_clipped_regions(inner_block_w, - inner_block_h, - 0, x, y, - width, - height, - clipped_regions[i].region, - &inner_n_regions, reverse, upsidedown); - for(j = 0; j < inner_n_regions; j++) - { - result_regions[k].region = inner_regions[j].region; - result_regions[k].block_idx = clipped_regions[i].block_idx; - k++; - } - free(inner_regions); - } - *n_region = k; - free(clipped_regions); - return result_regions; + glamor_pixmap_clipped_regions *clipped_regions, *inner_regions, + *result_regions; + int i, j, x, y, k, inner_n_regions; + int width, height; + glamor_pixmap_private_large_t *priv; + + priv = &pixmap_priv->large; + + DEBUGF("ext called \n"); + + if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { + clipped_regions = calloc(1, sizeof(*clipped_regions)); + if (clipped_regions == NULL) { + *n_region = 0; + return NULL; + } + clipped_regions[0].region = RegionCreate(NULL, 1); + clipped_regions[0].block_idx = 0; + RegionCopy(clipped_regions[0].region, region); + *n_region = 1; + priv->block_w = priv->base.pixmap->drawable.width; + priv->block_h = priv->base.pixmap->drawable.height; + priv->box_array = &priv->box; + priv->box.x1 = priv->box.y1 = 0; + priv->box.x2 = priv->block_w; + priv->box.y2 = priv->block_h; + } + else { + clipped_regions = __glamor_compute_clipped_regions(priv->block_w, + priv->block_h, + priv->block_wcnt, + 0, 0, + priv->base.pixmap-> + drawable.width, + priv->base.pixmap-> + drawable.height, + region, n_region, + reverse, upsidedown); + + if (clipped_regions == NULL) { + *n_region = 0; + return NULL; + } + } + if (inner_block_w >= priv->block_w && inner_block_h >= priv->block_h) + return clipped_regions; + result_regions = calloc(*n_region + * ((priv->block_w + inner_block_w - 1) / + inner_block_w) + * ((priv->block_h + inner_block_h - 1) / + inner_block_h), sizeof(*result_regions)); + k = 0; + for (i = 0; i < *n_region; i++) { + x = priv->box_array[clipped_regions[i].block_idx].x1; + y = priv->box_array[clipped_regions[i].block_idx].y1; + width = priv->box_array[clipped_regions[i].block_idx].x2 - x; + height = priv->box_array[clipped_regions[i].block_idx].y2 - y; + inner_regions = __glamor_compute_clipped_regions(inner_block_w, + inner_block_h, + 0, x, y, + width, + height, + clipped_regions[i]. + region, + &inner_n_regions, + reverse, upsidedown); + for (j = 0; j < inner_n_regions; j++) { + result_regions[k].region = inner_regions[j].region; + result_regions[k].block_idx = clipped_regions[i].block_idx; + k++; + } + free(inner_regions); + } + *n_region = k; + free(clipped_regions); + return result_regions; } /* @@ -232,35 +237,36 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, static RegionPtr _glamor_convert_pad_region(RegionPtr region, int w, int h) { - RegionPtr pad_region; - int nrect; - BoxPtr box; - int overlap; - - nrect = RegionNumRects(region); - box = RegionRects(region); - pad_region = RegionCreate(NULL, 4); - if (pad_region == NULL) - return NULL; - while(nrect--) { - BoxRec pad_box; - RegionRec temp_region; - pad_box = *box; - if (pad_box.x1 < 0 && pad_box.x2 <= 0) - pad_box.x2 = 1; - else if (pad_box.x1 >= w && pad_box.x2 > w) - pad_box.x1 = w - 1; - if (pad_box.y1 < 0 && pad_box.y2 <=0) - pad_box.y2 = 1; - else if (pad_box.y1 >= h && pad_box.y2 > h) - pad_box.y1 = h - 1; - RegionInitBoxes(&temp_region, &pad_box, 1); - RegionAppend(pad_region, &temp_region); - RegionUninit(&temp_region); - box++; - } - RegionValidate(pad_region, &overlap); - return pad_region; + RegionPtr pad_region; + int nrect; + BoxPtr box; + int overlap; + + nrect = RegionNumRects(region); + box = RegionRects(region); + pad_region = RegionCreate(NULL, 4); + if (pad_region == NULL) + return NULL; + while (nrect--) { + BoxRec pad_box; + RegionRec temp_region; + + pad_box = *box; + if (pad_box.x1 < 0 && pad_box.x2 <= 0) + pad_box.x2 = 1; + else if (pad_box.x1 >= w && pad_box.x2 > w) + pad_box.x1 = w - 1; + if (pad_box.y1 < 0 && pad_box.y2 <= 0) + pad_box.y2 = 1; + else if (pad_box.y1 >= h && pad_box.y2 > h) + pad_box.y1 = h - 1; + RegionInitBoxes(&temp_region, &pad_box, 1); + RegionAppend(pad_region, &temp_region); + RegionUninit(&temp_region); + box++; + } + RegionValidate(pad_region, &overlap); + return pad_region; } /* @@ -278,32 +284,35 @@ _glamor_convert_pad_region(RegionPtr region, int w, int h) static void _glamor_largepixmap_reflect_fixup(short *xy1, short *xy2, int wh) { - int odd1, odd2; - int c1, c2; - - if (*xy2 - *xy1 > wh) { - *xy1 = 0; - *xy2 = wh; - return; - } - modulus(*xy1, wh, c1); - odd1 = ((*xy1 - c1) / wh) & 0x1; - modulus(*xy2, wh, c2); - odd2 = ((*xy2 - c2) / wh) & 0x1; - - if (odd1 && odd2) { - *xy1 = wh - c2; - *xy2 = wh - c1; - } else if (odd1 && !odd2) { - *xy1 = 0; - *xy2 = MAX(c2, wh - c1); - } else if (!odd1 && odd2) { - *xy2 = wh; - *xy1 = MIN(c1, wh - c2); - } else { - *xy1 = c1; - *xy2 = c2; - } + int odd1, odd2; + int c1, c2; + + if (*xy2 - *xy1 > wh) { + *xy1 = 0; + *xy2 = wh; + return; + } + modulus(*xy1, wh, c1); + odd1 = ((*xy1 - c1) / wh) & 0x1; + modulus(*xy2, wh, c2); + odd2 = ((*xy2 - c2) / wh) & 0x1; + + if (odd1 && odd2) { + *xy1 = wh - c2; + *xy2 = wh - c1; + } + else if (odd1 && !odd2) { + *xy1 = 0; + *xy2 = MAX(c2, wh - c1); + } + else if (!odd1 && odd2) { + *xy2 = wh; + *xy1 = MIN(c1, wh - c2); + } + else { + *xy1 = c1; + *xy2 = c2; + } } /** @@ -317,366 +326,404 @@ _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 reverse, int upsidedown) + RegionPtr region, int *n_region, + int repeat_type, int is_transform, + int reverse, int upsidedown) { - glamor_pixmap_clipped_regions * clipped_regions; - BoxPtr extent; - int i, j; - RegionPtr current_region; - int pixmap_width, pixmap_height; - int m; - BoxRec repeat_box; - RegionRec repeat_region; - int right_shift = 0; - int down_shift = 0; - int x_center_shift = 0, y_center_shift = 0; - glamor_pixmap_private_large_t *priv; - priv = &pixmap_priv->large; - - DEBUGRegionPrint(region); - if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { - clipped_regions = calloc(1, sizeof(*clipped_regions)); - clipped_regions[0].region = RegionCreate(NULL, 1); - clipped_regions[0].block_idx = 0; - RegionCopy(clipped_regions[0].region, region); - *n_region = 1; - return clipped_regions; - } - - pixmap_width = priv->base.pixmap->drawable.width; - pixmap_height = priv->base.pixmap->drawable.height; - if (repeat_type == 0 || repeat_type == RepeatPad) { - RegionPtr saved_region = NULL; - if (repeat_type == RepeatPad) { - saved_region = region; - region = _glamor_convert_pad_region(saved_region, pixmap_width, pixmap_height); - if (region == NULL) { - *n_region = 0; - return NULL; - } - } - clipped_regions = __glamor_compute_clipped_regions(priv->block_w, - priv->block_h, - priv->block_wcnt, - 0, 0, - priv->base.pixmap->drawable.width, - priv->base.pixmap->drawable.height, - region, n_region, reverse, upsidedown - ); - if (saved_region) - RegionDestroy(region); - return clipped_regions; - } - extent = RegionExtents(region); - - x_center_shift = extent->x1 / pixmap_width; - if (x_center_shift < 0) - x_center_shift--; - if (abs(x_center_shift) & 1) - x_center_shift++; - y_center_shift = extent->y1 / pixmap_height; - if (y_center_shift < 0) - y_center_shift--; - if (abs(y_center_shift) & 1) - y_center_shift++; - - if (extent->x1 < 0) - right_shift = ((-extent->x1 + pixmap_width - 1) / pixmap_width ); - if (extent->y1 < 0) - down_shift = ((-extent->y1 + pixmap_height - 1) / pixmap_height ); - - if (right_shift != 0 || down_shift != 0) { - if (repeat_type == RepeatReflect) { - right_shift = (right_shift + 1)&~1; - down_shift = (down_shift + 1)&~1; - } - RegionTranslate(region, right_shift * pixmap_width, down_shift * pixmap_height); - } - - extent = RegionExtents(region); - /* Tile a large pixmap to another large pixmap. - * We can't use the target large pixmap as the - * loop variable, instead we need to loop for all - * the blocks in the tile pixmap. - * - * simulate repeat each single block to cover the - * target's blocks. Two special case: - * a block_wcnt == 1 or block_hcnt ==1, then we - * only need to loop one direction as the other - * direction is fully included in the first block. - * - * For the other cases, just need to start - * from a proper shiftx/shifty, and then increase - * y by tile_height each time to walk trhough the - * target block and then walk trhough the target - * at x direction by increate tile_width each time. - * - * This way, we can consolidate all the sub blocks - * of the target boxes into one tile source's block. - * - * */ - m = 0; - clipped_regions = calloc(priv->block_wcnt * priv->block_hcnt, - sizeof(*clipped_regions)); - if (clipped_regions == NULL) { - *n_region = 0; - return NULL; - } - if (right_shift != 0 || down_shift != 0) { - DEBUGF("region to be repeated shifted \n"); - DEBUGRegionPrint(region); - } - DEBUGF("repeat pixmap width %d height %d \n", pixmap_width, pixmap_height); - DEBUGF("extent x1 %d y1 %d x2 %d y2 %d \n", extent->x1, extent->y1, extent->x2, extent->y2); - for(j = 0; j < priv->block_hcnt; j++) - { - for(i = 0; i < priv->block_wcnt; i++) - { - int dx = pixmap_width; - int dy = pixmap_height; - int idx; - int shift_x; - int shift_y; - int saved_y1, saved_y2; - int x_idx = 0, y_idx = 0, saved_y_idx = 0; - RegionRec temp_region; - BoxRec reflect_repeat_box; - BoxPtr valid_repeat_box; - - shift_x = (extent->x1 / pixmap_width) * pixmap_width; - shift_y = (extent->y1 / pixmap_height) * pixmap_height; - idx = j * priv->block_wcnt + i; - if (repeat_type == RepeatReflect) { - x_idx = (extent->x1 / pixmap_width); - y_idx = (extent->y1 / pixmap_height); - } - - /* Construct a rect to clip the target region. */ - repeat_box.x1 = shift_x + priv->box_array[idx].x1; - repeat_box.y1 = shift_y + priv->box_array[idx].y1; - if (priv->block_wcnt == 1) { - repeat_box.x2 = extent->x2; - dx = extent->x2 - repeat_box.x1; - } else - repeat_box.x2 = shift_x + priv->box_array[idx].x2; - if (priv->block_hcnt == 1) { - repeat_box.y2 = extent->y2; - dy = extent->y2 - repeat_box.y1; - } else - repeat_box.y2 = shift_y + priv->box_array[idx].y2; - - current_region = RegionCreate(NULL, 4); - RegionInit(&temp_region, NULL, 4); - DEBUGF("init repeat box %d %d %d %d \n", - repeat_box.x1, repeat_box.y1, repeat_box.x2, repeat_box.y2); - - if (repeat_type == RepeatNormal) { - saved_y1 = repeat_box.y1; - saved_y2 = repeat_box.y2; - for(; repeat_box.x1 < extent->x2; - repeat_box.x1 += dx, repeat_box.x2 += dx) - { - repeat_box.y1 = saved_y1; - repeat_box.y2 = saved_y2; - for( repeat_box.y1 = saved_y1, repeat_box.y2 = saved_y2; - repeat_box.y1 < extent->y2; - repeat_box.y1 += dy, repeat_box.y2 += dy) - { - - RegionInitBoxes(&repeat_region, &repeat_box, 1); - DEBUGF("Start to clip repeat region: \n"); - DEBUGRegionPrint(&repeat_region); - RegionIntersect(&temp_region, &repeat_region, region); - DEBUGF("clip result:\n"); - DEBUGRegionPrint(&temp_region); - RegionAppend(current_region, &temp_region); - RegionUninit(&repeat_region); - } - } - } else if (repeat_type == RepeatReflect) { - saved_y1 = repeat_box.y1; - saved_y2 = repeat_box.y2; - saved_y_idx = y_idx; - for(; ; repeat_box.x1 += dx, repeat_box.x2 += dx) - { - repeat_box.y1 = saved_y1; - repeat_box.y2 = saved_y2; - y_idx = saved_y_idx; - reflect_repeat_box.x1 = (x_idx & 1) ? - ((2 * x_idx + 1) * dx - repeat_box.x2) : repeat_box.x1; - reflect_repeat_box.x2 = (x_idx & 1) ? - ((2 * x_idx + 1) * dx - repeat_box.x1) : repeat_box.x2; - valid_repeat_box = &reflect_repeat_box; - - if (valid_repeat_box->x1 >= extent->x2) - break; - for( repeat_box.y1 = saved_y1, repeat_box.y2 = saved_y2; - ; - repeat_box.y1 += dy, repeat_box.y2 += dy) - { - - DEBUGF("x_idx %d y_idx %d dx %d dy %d\n", x_idx, y_idx, dx, dy); - DEBUGF("repeat box %d %d %d %d \n", - repeat_box.x1, repeat_box.y1, repeat_box.x2, repeat_box.y2); - - if (priv->block_hcnt > 1) { - reflect_repeat_box.y1 = (y_idx & 1) ? - ((2 * y_idx + 1) * dy - repeat_box.y2) : repeat_box.y1; - reflect_repeat_box.y2 = (y_idx & 1) ? - ((2 * y_idx + 1) * dy - repeat_box.y1) : repeat_box.y2; - } else { - reflect_repeat_box.y1 = repeat_box.y1; - reflect_repeat_box.y2 = repeat_box.y2; - } - - DEBUGF("valid_repeat_box x1 %d y1 %d \n", - valid_repeat_box->x1, valid_repeat_box->y1); - if (valid_repeat_box->y1 >= extent->y2) - break; - RegionInitBoxes(&repeat_region, valid_repeat_box, 1); - DEBUGF("start to clip repeat[reflect] region: \n"); - DEBUGRegionPrint(&repeat_region); - RegionIntersect(&temp_region, &repeat_region, region); - DEBUGF("result:\n"); - DEBUGRegionPrint(&temp_region); - if (is_transform && RegionNumRects(&temp_region)) { - BoxRec temp_box; - BoxPtr temp_extent; - temp_extent = RegionExtents(&temp_region); - if (priv->block_wcnt > 1) { - if (x_idx & 1) { - temp_box.x1 = ((2 * x_idx + 1)*dx - temp_extent->x2); - temp_box.x2 = ((2 * x_idx + 1)*dx - temp_extent->x1); - } else { - temp_box.x1 = temp_extent->x1; - temp_box.x2 = temp_extent->x2; - } - modulus(temp_box.x1, pixmap_width, temp_box.x1); - modulus(temp_box.x2, pixmap_width, temp_box.x2); - if (temp_box.x2 == 0) temp_box.x2 = pixmap_width; - } else { - temp_box.x1 = temp_extent->x1; - temp_box.x2 = temp_extent->x2; - _glamor_largepixmap_reflect_fixup(&temp_box.x1, &temp_box.x2, pixmap_width); - } - - if (priv->block_hcnt > 1) { - if (y_idx & 1) { - temp_box.y1 = ((2 * y_idx + 1)*dy - temp_extent->y2); - temp_box.y2 = ((2 * y_idx + 1)*dy - temp_extent->y1); - } else { - temp_box.y1 = temp_extent->y1; - temp_box.y2 = temp_extent->y2; - } - - modulus(temp_box.y1, pixmap_height, temp_box.y1); - modulus(temp_box.y2, pixmap_height, temp_box.y2); - if (temp_box.y2 == 0) temp_box.y2 = pixmap_height; - } else { - temp_box.y1 = temp_extent->y1; - temp_box.y2 = temp_extent->y2; - _glamor_largepixmap_reflect_fixup(&temp_box.y1, &temp_box.y2, pixmap_height); - } - - RegionInitBoxes(&temp_region, &temp_box, 1); - RegionTranslate(&temp_region, x_center_shift * pixmap_width, y_center_shift * pixmap_height); - DEBUGF("for transform result:\n"); - DEBUGRegionPrint(&temp_region); - } - RegionAppend(current_region, &temp_region); - RegionUninit(&repeat_region); - y_idx++; - } - x_idx++; - } - } - DEBUGF("dx %d dy %d \n", dx, dy); - - if (RegionNumRects(current_region)) { - - if ((right_shift != 0 || down_shift != 0) && !(is_transform && repeat_type == RepeatReflect)) - RegionTranslate(current_region, - -right_shift * pixmap_width, - -down_shift * pixmap_height); - clipped_regions[m].region = current_region; - clipped_regions[m].block_idx = idx; - m++; - } else - RegionDestroy(current_region); - RegionUninit(&temp_region); - } - } - - if (right_shift != 0 || down_shift != 0) - RegionTranslate(region, -right_shift * pixmap_width, -down_shift * pixmap_height); - *n_region = m; - - return clipped_regions; + glamor_pixmap_clipped_regions *clipped_regions; + BoxPtr extent; + int i, j; + RegionPtr current_region; + int pixmap_width, pixmap_height; + int m; + BoxRec repeat_box; + RegionRec repeat_region; + int right_shift = 0; + int down_shift = 0; + int x_center_shift = 0, y_center_shift = 0; + glamor_pixmap_private_large_t *priv; + + priv = &pixmap_priv->large; + + DEBUGRegionPrint(region); + if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { + clipped_regions = calloc(1, sizeof(*clipped_regions)); + clipped_regions[0].region = RegionCreate(NULL, 1); + clipped_regions[0].block_idx = 0; + RegionCopy(clipped_regions[0].region, region); + *n_region = 1; + return clipped_regions; + } + + pixmap_width = priv->base.pixmap->drawable.width; + pixmap_height = priv->base.pixmap->drawable.height; + if (repeat_type == 0 || repeat_type == RepeatPad) { + RegionPtr saved_region = NULL; + + if (repeat_type == RepeatPad) { + saved_region = region; + region = + _glamor_convert_pad_region(saved_region, pixmap_width, + pixmap_height); + if (region == NULL) { + *n_region = 0; + return NULL; + } + } + clipped_regions = __glamor_compute_clipped_regions(priv->block_w, + priv->block_h, + priv->block_wcnt, + 0, 0, + priv->base.pixmap-> + drawable.width, + priv->base.pixmap-> + drawable.height, + region, n_region, + reverse, upsidedown); + if (saved_region) + RegionDestroy(region); + return clipped_regions; + } + extent = RegionExtents(region); + + x_center_shift = extent->x1 / pixmap_width; + if (x_center_shift < 0) + x_center_shift--; + if (abs(x_center_shift) & 1) + x_center_shift++; + y_center_shift = extent->y1 / pixmap_height; + if (y_center_shift < 0) + y_center_shift--; + if (abs(y_center_shift) & 1) + y_center_shift++; + + if (extent->x1 < 0) + right_shift = ((-extent->x1 + pixmap_width - 1) / pixmap_width); + if (extent->y1 < 0) + down_shift = ((-extent->y1 + pixmap_height - 1) / pixmap_height); + + if (right_shift != 0 || down_shift != 0) { + if (repeat_type == RepeatReflect) { + right_shift = (right_shift + 1) & ~1; + down_shift = (down_shift + 1) & ~1; + } + RegionTranslate(region, right_shift * pixmap_width, + down_shift * pixmap_height); + } + + extent = RegionExtents(region); + /* Tile a large pixmap to another large pixmap. + * We can't use the target large pixmap as the + * loop variable, instead we need to loop for all + * the blocks in the tile pixmap. + * + * simulate repeat each single block to cover the + * target's blocks. Two special case: + * a block_wcnt == 1 or block_hcnt ==1, then we + * only need to loop one direction as the other + * direction is fully included in the first block. + * + * For the other cases, just need to start + * from a proper shiftx/shifty, and then increase + * y by tile_height each time to walk trhough the + * target block and then walk trhough the target + * at x direction by increate tile_width each time. + * + * This way, we can consolidate all the sub blocks + * of the target boxes into one tile source's block. + * + * */ + m = 0; + clipped_regions = calloc(priv->block_wcnt * priv->block_hcnt, + sizeof(*clipped_regions)); + if (clipped_regions == NULL) { + *n_region = 0; + return NULL; + } + if (right_shift != 0 || down_shift != 0) { + DEBUGF("region to be repeated shifted \n"); + DEBUGRegionPrint(region); + } + DEBUGF("repeat pixmap width %d height %d \n", pixmap_width, pixmap_height); + DEBUGF("extent x1 %d y1 %d x2 %d y2 %d \n", extent->x1, extent->y1, + extent->x2, extent->y2); + for (j = 0; j < priv->block_hcnt; j++) { + for (i = 0; i < priv->block_wcnt; i++) { + int dx = pixmap_width; + int dy = pixmap_height; + int idx; + int shift_x; + int shift_y; + int saved_y1, saved_y2; + int x_idx = 0, y_idx = 0, saved_y_idx = 0; + RegionRec temp_region; + BoxRec reflect_repeat_box; + BoxPtr valid_repeat_box; + + shift_x = (extent->x1 / pixmap_width) * pixmap_width; + shift_y = (extent->y1 / pixmap_height) * pixmap_height; + idx = j * priv->block_wcnt + i; + if (repeat_type == RepeatReflect) { + x_idx = (extent->x1 / pixmap_width); + y_idx = (extent->y1 / pixmap_height); + } + + /* Construct a rect to clip the target region. */ + repeat_box.x1 = shift_x + priv->box_array[idx].x1; + repeat_box.y1 = shift_y + priv->box_array[idx].y1; + if (priv->block_wcnt == 1) { + repeat_box.x2 = extent->x2; + dx = extent->x2 - repeat_box.x1; + } + else + repeat_box.x2 = shift_x + priv->box_array[idx].x2; + if (priv->block_hcnt == 1) { + repeat_box.y2 = extent->y2; + dy = extent->y2 - repeat_box.y1; + } + else + repeat_box.y2 = shift_y + priv->box_array[idx].y2; + + current_region = RegionCreate(NULL, 4); + RegionInit(&temp_region, NULL, 4); + DEBUGF("init repeat box %d %d %d %d \n", + repeat_box.x1, repeat_box.y1, repeat_box.x2, repeat_box.y2); + + if (repeat_type == RepeatNormal) { + saved_y1 = repeat_box.y1; + saved_y2 = repeat_box.y2; + for (; repeat_box.x1 < extent->x2; + repeat_box.x1 += dx, repeat_box.x2 += dx) { + repeat_box.y1 = saved_y1; + repeat_box.y2 = saved_y2; + for (repeat_box.y1 = saved_y1, repeat_box.y2 = saved_y2; + repeat_box.y1 < extent->y2; + repeat_box.y1 += dy, repeat_box.y2 += dy) { + + RegionInitBoxes(&repeat_region, &repeat_box, 1); + DEBUGF("Start to clip repeat region: \n"); + DEBUGRegionPrint(&repeat_region); + RegionIntersect(&temp_region, &repeat_region, region); + DEBUGF("clip result:\n"); + DEBUGRegionPrint(&temp_region); + RegionAppend(current_region, &temp_region); + RegionUninit(&repeat_region); + } + } + } + else if (repeat_type == RepeatReflect) { + saved_y1 = repeat_box.y1; + saved_y2 = repeat_box.y2; + saved_y_idx = y_idx; + for (;; repeat_box.x1 += dx, repeat_box.x2 += dx) { + repeat_box.y1 = saved_y1; + repeat_box.y2 = saved_y2; + y_idx = saved_y_idx; + reflect_repeat_box.x1 = (x_idx & 1) ? + ((2 * x_idx + 1) * dx - repeat_box.x2) : repeat_box.x1; + reflect_repeat_box.x2 = (x_idx & 1) ? + ((2 * x_idx + 1) * dx - repeat_box.x1) : repeat_box.x2; + valid_repeat_box = &reflect_repeat_box; + + if (valid_repeat_box->x1 >= extent->x2) + break; + for (repeat_box.y1 = saved_y1, repeat_box.y2 = saved_y2;; + repeat_box.y1 += dy, repeat_box.y2 += dy) { + + DEBUGF("x_idx %d y_idx %d dx %d dy %d\n", x_idx, y_idx, + dx, dy); + DEBUGF("repeat box %d %d %d %d \n", repeat_box.x1, + repeat_box.y1, repeat_box.x2, repeat_box.y2); + + if (priv->block_hcnt > 1) { + reflect_repeat_box.y1 = (y_idx & 1) ? + ((2 * y_idx + 1) * dy - + repeat_box.y2) : repeat_box.y1; + reflect_repeat_box.y2 = + (y_idx & 1) ? ((2 * y_idx + 1) * dy - + repeat_box.y1) : repeat_box.y2; + } + else { + reflect_repeat_box.y1 = repeat_box.y1; + reflect_repeat_box.y2 = repeat_box.y2; + } + + DEBUGF("valid_repeat_box x1 %d y1 %d \n", + valid_repeat_box->x1, valid_repeat_box->y1); + if (valid_repeat_box->y1 >= extent->y2) + break; + RegionInitBoxes(&repeat_region, valid_repeat_box, 1); + DEBUGF("start to clip repeat[reflect] region: \n"); + DEBUGRegionPrint(&repeat_region); + RegionIntersect(&temp_region, &repeat_region, region); + DEBUGF("result:\n"); + DEBUGRegionPrint(&temp_region); + if (is_transform && RegionNumRects(&temp_region)) { + BoxRec temp_box; + BoxPtr temp_extent; + + temp_extent = RegionExtents(&temp_region); + if (priv->block_wcnt > 1) { + if (x_idx & 1) { + temp_box.x1 = + ((2 * x_idx + 1) * dx - + temp_extent->x2); + temp_box.x2 = + ((2 * x_idx + 1) * dx - + temp_extent->x1); + } + else { + temp_box.x1 = temp_extent->x1; + temp_box.x2 = temp_extent->x2; + } + modulus(temp_box.x1, pixmap_width, temp_box.x1); + modulus(temp_box.x2, pixmap_width, temp_box.x2); + if (temp_box.x2 == 0) + temp_box.x2 = pixmap_width; + } + else { + temp_box.x1 = temp_extent->x1; + temp_box.x2 = temp_extent->x2; + _glamor_largepixmap_reflect_fixup(&temp_box.x1, + &temp_box.x2, + pixmap_width); + } + + if (priv->block_hcnt > 1) { + if (y_idx & 1) { + temp_box.y1 = + ((2 * y_idx + 1) * dy - + temp_extent->y2); + temp_box.y2 = + ((2 * y_idx + 1) * dy - + temp_extent->y1); + } + else { + temp_box.y1 = temp_extent->y1; + temp_box.y2 = temp_extent->y2; + } + + modulus(temp_box.y1, pixmap_height, + temp_box.y1); + modulus(temp_box.y2, pixmap_height, + temp_box.y2); + if (temp_box.y2 == 0) + temp_box.y2 = pixmap_height; + } + else { + temp_box.y1 = temp_extent->y1; + temp_box.y2 = temp_extent->y2; + _glamor_largepixmap_reflect_fixup(&temp_box.y1, + &temp_box.y2, + pixmap_height); + } + + RegionInitBoxes(&temp_region, &temp_box, 1); + RegionTranslate(&temp_region, + x_center_shift * pixmap_width, + y_center_shift * pixmap_height); + DEBUGF("for transform result:\n"); + DEBUGRegionPrint(&temp_region); + } + RegionAppend(current_region, &temp_region); + RegionUninit(&repeat_region); + y_idx++; + } + x_idx++; + } + } + DEBUGF("dx %d dy %d \n", dx, dy); + + if (RegionNumRects(current_region)) { + + if ((right_shift != 0 || down_shift != 0) && + !(is_transform && repeat_type == RepeatReflect)) + RegionTranslate(current_region, -right_shift * pixmap_width, + -down_shift * pixmap_height); + clipped_regions[m].region = current_region; + clipped_regions[m].block_idx = idx; + m++; + } + else + RegionDestroy(current_region); + RegionUninit(&temp_region); + } + } + + if (right_shift != 0 || down_shift != 0) + RegionTranslate(region, -right_shift * pixmap_width, + -down_shift * pixmap_height); + *n_region = m; + + return clipped_regions; } glamor_pixmap_clipped_regions * glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, - int *n_region, int repeat_type, - int reverse, int upsidedown) + int *n_region, int repeat_type, + int reverse, int upsidedown) { - return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, 0, reverse, upsidedown); + 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. * by default. Or just use region32 for repeat cases? **/ 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, - int reverse, int upsidedown) +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, + int reverse, int upsidedown) { - BoxPtr temp_extent; - struct pixman_box32 temp_box; - struct pixman_box16 short_box; - RegionPtr temp_region; - glamor_pixmap_clipped_regions *ret; - - temp_region = RegionCreate(NULL, 4); - temp_extent = RegionExtents(region); - DEBUGF("dest region \n"); - DEBUGRegionPrint(region); - /* dx/dy may exceed MAX SHORT. we have to use - * a box32 to represent it.*/ - temp_box.x1 = temp_extent->x1 + dx; - temp_box.x2 = temp_extent->x2 + dx; - temp_box.y1 = temp_extent->y1 + dy; - temp_box.y2 = temp_extent->y2 + dy; - - DEBUGF("source box %d %d %d %d \n", temp_box.x1, temp_box.y1, temp_box.x2, temp_box.y2); - if (transform) - glamor_get_transform_extent_from_box(&temp_box, transform); - if (repeat_type == RepeatNone) { - if (temp_box.x1 < 0) temp_box.x1 = 0; - if (temp_box.y1 < 0) temp_box.y1 = 0; - temp_box.x2 = MIN(temp_box.x2, priv->base.pixmap->drawable.width); - temp_box.y2 = MIN(temp_box.y2, priv->base.pixmap->drawable.height); - } - /* Now copy back the box32 to a box16 box. */ - short_box.x1 = temp_box.x1; - short_box.y1 = temp_box.y1; - short_box.x2 = temp_box.x2; - short_box.y2 = temp_box.y2; - RegionInitBoxes(temp_region, &short_box, 1); - DEBUGF("copy to temp source region \n"); - DEBUGRegionPrint(temp_region); - ret = _glamor_compute_clipped_regions(priv, - temp_region, - n_region, - repeat_type, - 1, reverse, - upsidedown); - DEBUGF("n_regions = %d \n", *n_region); - RegionDestroy(temp_region); - - return ret; + BoxPtr temp_extent; + struct pixman_box32 temp_box; + struct pixman_box16 short_box; + RegionPtr temp_region; + glamor_pixmap_clipped_regions *ret; + + temp_region = RegionCreate(NULL, 4); + temp_extent = RegionExtents(region); + DEBUGF("dest region \n"); + DEBUGRegionPrint(region); + /* dx/dy may exceed MAX SHORT. we have to use + * a box32 to represent it.*/ + temp_box.x1 = temp_extent->x1 + dx; + temp_box.x2 = temp_extent->x2 + dx; + temp_box.y1 = temp_extent->y1 + dy; + temp_box.y2 = temp_extent->y2 + dy; + + DEBUGF("source box %d %d %d %d \n", temp_box.x1, temp_box.y1, temp_box.x2, + temp_box.y2); + if (transform) + glamor_get_transform_extent_from_box(&temp_box, transform); + if (repeat_type == RepeatNone) { + if (temp_box.x1 < 0) + temp_box.x1 = 0; + if (temp_box.y1 < 0) + temp_box.y1 = 0; + temp_box.x2 = MIN(temp_box.x2, priv->base.pixmap->drawable.width); + temp_box.y2 = MIN(temp_box.y2, priv->base.pixmap->drawable.height); + } + /* Now copy back the box32 to a box16 box. */ + short_box.x1 = temp_box.x1; + short_box.y1 = temp_box.y1; + short_box.x2 = temp_box.x2; + short_box.y2 = temp_box.y2; + RegionInitBoxes(temp_region, &short_box, 1); + DEBUGF("copy to temp source region \n"); + DEBUGRegionPrint(temp_region); + ret = _glamor_compute_clipped_regions(priv, + temp_region, + n_region, + repeat_type, 1, reverse, upsidedown); + DEBUGF("n_regions = %d \n", *n_region); + RegionDestroy(temp_region); + + return ret; } + /* * As transform and repeatpad mode. * We may get a clipped result which in multipe regions. @@ -689,120 +736,121 @@ glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pix * if the clipped result cross the region boundary. */ static void -glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, int repeat_type, - glamor_pixmap_clipped_regions *clipped_regions, - int *n_regions, int *need_clean_fbo) +glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, + int repeat_type, + glamor_pixmap_clipped_regions *clipped_regions, + int *n_regions, int *need_clean_fbo) { - BoxPtr temp_extent; - BoxRec temp_box, copy_box; - RegionPtr temp_region; - glamor_pixmap_private *temp_priv; - PixmapPtr temp_pixmap; - int overlap; - int i; - int pixmap_width, pixmap_height; - glamor_pixmap_private_large_t *priv; - - priv = &pixmap_priv->large; - pixmap_width = priv->base.pixmap->drawable.width; - pixmap_height = priv->base.pixmap->drawable.height; - - temp_region = RegionCreate(NULL, 4); - for(i = 0; i < *n_regions; i++) - { - DEBUGF("Region %d:\n", i); - DEBUGRegionPrint(clipped_regions[i].region); - RegionAppend(temp_region, clipped_regions[i].region); - } - - RegionValidate(temp_region, &overlap); - DEBUGF("temp region: \n"); - DEBUGRegionPrint(temp_region); - temp_extent = RegionExtents(temp_region); - - temp_box = *temp_extent; - - DEBUGF("need copy region: \n"); - DEBUGF("%d %d %d %d \n", temp_box.x1, temp_box.y1, temp_box.x2, temp_box.y2); - temp_pixmap = glamor_create_pixmap(priv->base.pixmap->drawable.pScreen, - temp_box.x2 - temp_box.x1, - temp_box.y2 - temp_box.y1, - priv->base.pixmap->drawable.depth, - GLAMOR_CREATE_PIXMAP_FIXUP); - if (temp_pixmap == NULL) { - assert(0); - return; - } - - temp_priv = glamor_get_pixmap_private(temp_pixmap); - assert(temp_priv->type != GLAMOR_TEXTURE_LARGE); - - priv->box = temp_box; - if (temp_extent->x1 >= 0 && temp_extent->x2 <= pixmap_width - && temp_extent->y1 >= 0 && temp_extent->y2 <= pixmap_height) { - int dx, dy; - copy_box.x1 = 0; - copy_box.y1 = 0; - copy_box.x2 = temp_extent->x2 - temp_extent->x1; - copy_box.y2 = temp_extent->y2 - temp_extent->y1; - dx = temp_extent->x1; - dy = temp_extent->y1; - glamor_copy_n_to_n(&priv->base.pixmap->drawable, - &temp_pixmap->drawable, - NULL, ©_box, 1, dx, - dy, 0, 0, 0, NULL); -// glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width, -// temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff00); - } else { - for (i = 0; i < *n_regions; i++) - { - BoxPtr box; - int nbox; - box = REGION_RECTS(clipped_regions[i].region); - nbox = REGION_NUM_RECTS(clipped_regions[i].region); - while(nbox--) { - int dx, dy, c, d; - DEBUGF("box x1 %d y1 %d x2 %d y2 %d \n", - box->x1, box->y1, box->x2, box->y2); - modulus(box->x1, pixmap_width, c); - dx = c - (box->x1 - temp_box.x1); - copy_box.x1 = box->x1 - temp_box.x1; - copy_box.x2 = box->x2 - temp_box.x1; - - modulus(box->y1, pixmap_height, d); - dy = d - (box->y1 - temp_box.y1); - copy_box.y1 = box->y1 - temp_box.y1; - copy_box.y2 = box->y2 - temp_box.y1; - - DEBUGF("copying box %d %d %d %d, dx %d dy %d\n", - copy_box.x1, copy_box.y1, copy_box.x2, - copy_box.y2, dx, dy); - - glamor_copy_n_to_n(&priv->base.pixmap->drawable, - &temp_pixmap->drawable, - NULL, ©_box, 1, dx, - dy, 0, 0, 0, NULL); - box++; - } - } - //glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width, - // temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff); - } - /* The first region will be released at caller side. */ - for(i = 1; i < *n_regions; i++) - RegionDestroy(clipped_regions[i].region); - RegionDestroy(temp_region); - priv->box = temp_box; - priv->base.fbo = glamor_pixmap_detach_fbo(temp_priv); - DEBUGF("priv box x1 %d y1 %d x2 %d y2 %d \n", - priv->box.x1, priv->box.y1, priv->box.x2, priv->box.y2); - glamor_destroy_pixmap(temp_pixmap); - *need_clean_fbo = 1; - *n_regions = 1; + BoxPtr temp_extent; + BoxRec temp_box, copy_box; + RegionPtr temp_region; + glamor_pixmap_private *temp_priv; + PixmapPtr temp_pixmap; + int overlap; + int i; + int pixmap_width, pixmap_height; + glamor_pixmap_private_large_t *priv; + + priv = &pixmap_priv->large; + pixmap_width = priv->base.pixmap->drawable.width; + pixmap_height = priv->base.pixmap->drawable.height; + + temp_region = RegionCreate(NULL, 4); + for (i = 0; i < *n_regions; i++) { + DEBUGF("Region %d:\n", i); + DEBUGRegionPrint(clipped_regions[i].region); + RegionAppend(temp_region, clipped_regions[i].region); + } + + RegionValidate(temp_region, &overlap); + DEBUGF("temp region: \n"); + DEBUGRegionPrint(temp_region); + temp_extent = RegionExtents(temp_region); + + temp_box = *temp_extent; + + DEBUGF("need copy region: \n"); + DEBUGF("%d %d %d %d \n", temp_box.x1, temp_box.y1, temp_box.x2, + temp_box.y2); + temp_pixmap = + glamor_create_pixmap(priv->base.pixmap->drawable.pScreen, + temp_box.x2 - temp_box.x1, + temp_box.y2 - temp_box.y1, + priv->base.pixmap->drawable.depth, + GLAMOR_CREATE_PIXMAP_FIXUP); + if (temp_pixmap == NULL) { + assert(0); + return; + } + + temp_priv = glamor_get_pixmap_private(temp_pixmap); + assert(temp_priv->type != GLAMOR_TEXTURE_LARGE); + + priv->box = temp_box; + if (temp_extent->x1 >= 0 && temp_extent->x2 <= pixmap_width + && temp_extent->y1 >= 0 && temp_extent->y2 <= pixmap_height) { + int dx, dy; + + copy_box.x1 = 0; + copy_box.y1 = 0; + copy_box.x2 = temp_extent->x2 - temp_extent->x1; + copy_box.y2 = temp_extent->y2 - temp_extent->y1; + dx = temp_extent->x1; + dy = temp_extent->y1; + glamor_copy_n_to_n(&priv->base.pixmap->drawable, + &temp_pixmap->drawable, + NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL); +// glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width, +// temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff00); + } + else { + for (i = 0; i < *n_regions; i++) { + BoxPtr box; + int nbox; + + box = REGION_RECTS(clipped_regions[i].region); + nbox = REGION_NUM_RECTS(clipped_regions[i].region); + while (nbox--) { + int dx, dy, c, d; + + DEBUGF("box x1 %d y1 %d x2 %d y2 %d \n", + box->x1, box->y1, box->x2, box->y2); + modulus(box->x1, pixmap_width, c); + dx = c - (box->x1 - temp_box.x1); + copy_box.x1 = box->x1 - temp_box.x1; + copy_box.x2 = box->x2 - temp_box.x1; + + modulus(box->y1, pixmap_height, d); + dy = d - (box->y1 - temp_box.y1); + copy_box.y1 = box->y1 - temp_box.y1; + copy_box.y2 = box->y2 - temp_box.y1; + + DEBUGF("copying box %d %d %d %d, dx %d dy %d\n", + copy_box.x1, copy_box.y1, copy_box.x2, + copy_box.y2, dx, dy); + + glamor_copy_n_to_n(&priv->base.pixmap->drawable, + &temp_pixmap->drawable, + NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL); + box++; + } + } + //glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width, + // temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff); + } + /* The first region will be released at caller side. */ + for (i = 1; i < *n_regions; i++) + RegionDestroy(clipped_regions[i].region); + RegionDestroy(temp_region); + priv->box = temp_box; + priv->base.fbo = glamor_pixmap_detach_fbo(temp_priv); + DEBUGF("priv box x1 %d y1 %d x2 %d y2 %d \n", + priv->box.x1, priv->box.y1, priv->box.x2, priv->box.y2); + glamor_destroy_pixmap(temp_pixmap); + *need_clean_fbo = 1; + *n_regions = 1; } - - /** * Given an expected transformed block width and block height, * @@ -817,45 +865,47 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, int repeat_type **/ Bool glamor_get_transform_block_size(struct pixman_transform *transform, - int block_w, int block_h, - int *transformed_block_w, - int *transformed_block_h) + int block_w, int block_h, + int *transformed_block_w, + int *transformed_block_h) { - double a,b,c,d,e,f,g,h; - double scale; - int width, height; - a = pixman_fixed_to_double(transform->matrix[0][0]); - b = pixman_fixed_to_double(transform->matrix[0][1]); - c = pixman_fixed_to_double(transform->matrix[1][0]); - d = pixman_fixed_to_double(transform->matrix[1][1]); - scale = pixman_fixed_to_double(transform->matrix[2][2]); - if (block_w > 2048) { - /* For large block size, we shrink it to smaller box, - * thus latter we may get less cross boundary regions and - * thus can avoid some extra copy. - * - **/ - width = block_w / 4; - height = block_h / 4; - } else { - width = block_w - 2; - height = block_h - 2; - } - e = a + b; - f = c + d; - - g = a - b; - h = c - d; - - e = MIN(block_w, floor(width * scale) / MAX(fabs(e), fabs(g))); - f = MIN(block_h, floor(height * scale) / MAX(fabs(f), fabs(h))); - *transformed_block_w = MIN(e, f) - 1; - *transformed_block_h = *transformed_block_w; - if (*transformed_block_w <= 0 || *transformed_block_h <= 0) - return FALSE; - DEBUGF("original block_w/h %d %d, fixed %d %d \n", block_w, block_h, - *transformed_block_w, *transformed_block_h); - return TRUE; + double a, b, c, d, e, f, g, h; + double scale; + int width, height; + + a = pixman_fixed_to_double(transform->matrix[0][0]); + b = pixman_fixed_to_double(transform->matrix[0][1]); + c = pixman_fixed_to_double(transform->matrix[1][0]); + d = pixman_fixed_to_double(transform->matrix[1][1]); + scale = pixman_fixed_to_double(transform->matrix[2][2]); + if (block_w > 2048) { + /* For large block size, we shrink it to smaller box, + * thus latter we may get less cross boundary regions and + * thus can avoid some extra copy. + * + **/ + width = block_w / 4; + height = block_h / 4; + } + else { + width = block_w - 2; + height = block_h - 2; + } + e = a + b; + f = c + d; + + g = a - b; + h = c - d; + + e = MIN(block_w, floor(width * scale) / MAX(fabs(e), fabs(g))); + f = MIN(block_h, floor(height * scale) / MAX(fabs(f), fabs(h))); + *transformed_block_w = MIN(e, f) - 1; + *transformed_block_h = *transformed_block_w; + if (*transformed_block_w <= 0 || *transformed_block_h <= 0) + return FALSE; + DEBUGF("original block_w/h %d %d, fixed %d %d \n", block_w, block_h, + *transformed_block_w, *transformed_block_h); + return TRUE; } #define VECTOR_FROM_POINT(p, x, y) \ @@ -864,314 +914,341 @@ glamor_get_transform_block_size(struct pixman_transform *transform, p.v[2] = 1.0; void glamor_get_transform_extent_from_box(struct pixman_box32 *box, - struct pixman_transform *transform) + struct pixman_transform *transform) { - struct pixman_f_vector p0, p1, p2, p3; - float min_x, min_y, max_x, max_y; - - struct pixman_f_transform ftransform; - - VECTOR_FROM_POINT(p0, box->x1, box->y1) - VECTOR_FROM_POINT(p1, box->x2, box->y1) - VECTOR_FROM_POINT(p2, box->x2, box->y2) - VECTOR_FROM_POINT(p3, box->x1, box->y2) - - pixman_f_transform_from_pixman_transform(&ftransform, transform); - pixman_f_transform_point(&ftransform, &p0); - pixman_f_transform_point(&ftransform, &p1); - pixman_f_transform_point(&ftransform, &p2); - pixman_f_transform_point(&ftransform, &p3); - - min_x = MIN(p0.v[0], p1.v[0]); - min_x = MIN(min_x, p2.v[0]); - min_x = MIN(min_x, p3.v[0]); - - min_y = MIN(p0.v[1], p1.v[1]); - min_y = MIN(min_y, p2.v[1]); - min_y = MIN(min_y, p3.v[1]); - - max_x = MAX(p0.v[0], p1.v[0]); - max_x = MAX(max_x, p2.v[0]); - max_x = MAX(max_x, p3.v[0]); - - max_y = MAX(p0.v[1], p1.v[1]); - max_y = MAX(max_y, p2.v[1]); - max_y = MAX(max_y, p3.v[1]); - box->x1 = floor(min_x) - 1; - box->y1 = floor(min_y) - 1; - box->x2 = ceil(max_x) + 1; - box->y2 = ceil(max_y) + 1; + struct pixman_f_vector p0, p1, p2, p3; + float min_x, min_y, max_x, max_y; + + struct pixman_f_transform ftransform; + + VECTOR_FROM_POINT(p0, box->x1, box->y1) + VECTOR_FROM_POINT(p1, box->x2, box->y1) + VECTOR_FROM_POINT(p2, box->x2, box->y2) + VECTOR_FROM_POINT(p3, box->x1, box->y2) + + pixman_f_transform_from_pixman_transform(&ftransform, transform); + pixman_f_transform_point(&ftransform, &p0); + pixman_f_transform_point(&ftransform, &p1); + pixman_f_transform_point(&ftransform, &p2); + pixman_f_transform_point(&ftransform, &p3); + + min_x = MIN(p0.v[0], p1.v[0]); + min_x = MIN(min_x, p2.v[0]); + min_x = MIN(min_x, p3.v[0]); + + min_y = MIN(p0.v[1], p1.v[1]); + min_y = MIN(min_y, p2.v[1]); + min_y = MIN(min_y, p3.v[1]); + + max_x = MAX(p0.v[0], p1.v[0]); + max_x = MAX(max_x, p2.v[0]); + max_x = MAX(max_x, p3.v[0]); + + max_y = MAX(p0.v[1], p1.v[1]); + max_y = MAX(max_y, p2.v[1]); + max_y = MAX(max_y, p3.v[1]); + box->x1 = floor(min_x) - 1; + box->y1 = floor(min_y) - 1; + box->x2 = ceil(max_x) + 1; + box->y2 = ceil(max_y) + 1; } static void _glamor_process_transformed_clipped_region(glamor_pixmap_private *priv, - int repeat_type, - glamor_pixmap_clipped_regions *clipped_regions, - int *n_regions, int *need_clean_fbo) + int repeat_type, + glamor_pixmap_clipped_regions * + clipped_regions, int *n_regions, + int *need_clean_fbo) { - int shift_x, shift_y; - if (*n_regions != 1) { - /* Merge all source regions into one region. */ - glamor_merge_clipped_regions(priv, repeat_type, - clipped_regions, n_regions, - need_clean_fbo); - } else { - SET_PIXMAP_FBO_CURRENT(priv, - clipped_regions[0].block_idx); - if (repeat_type == RepeatReflect || repeat_type == RepeatNormal) { - /* The required source areas are in one region, - * we need to shift the corresponding box's coords to proper position, - * thus we can calculate the relative coords correctly.*/ - BoxPtr temp_box; - int rem; - temp_box = RegionExtents(clipped_regions[0].region); - modulus(temp_box->x1, priv->base.pixmap->drawable.width, rem); - shift_x = (temp_box->x1 - rem) / priv->base.pixmap->drawable.width; - modulus(temp_box->y1, priv->base.pixmap->drawable.height, rem); - shift_y = (temp_box->y1 - rem) / priv->base.pixmap->drawable.height; - - if (shift_x != 0) { - priv->large.box.x1 += shift_x * priv->base.pixmap->drawable.width; - priv->large.box.x2 += shift_x * priv->base.pixmap->drawable.width; - } - if (shift_y != 0) { - priv->large.box.y1 += shift_y * priv->base.pixmap->drawable.height; - priv->large.box.y2 += shift_y * priv->base.pixmap->drawable.height; - } - } - } + int shift_x, shift_y; + + if (*n_regions != 1) { + /* Merge all source regions into one region. */ + glamor_merge_clipped_regions(priv, repeat_type, + clipped_regions, n_regions, + need_clean_fbo); + } + else { + SET_PIXMAP_FBO_CURRENT(priv, clipped_regions[0].block_idx); + if (repeat_type == RepeatReflect || repeat_type == RepeatNormal) { + /* The required source areas are in one region, + * we need to shift the corresponding box's coords to proper position, + * thus we can calculate the relative coords correctly.*/ + BoxPtr temp_box; + int rem; + + temp_box = RegionExtents(clipped_regions[0].region); + modulus(temp_box->x1, priv->base.pixmap->drawable.width, rem); + shift_x = (temp_box->x1 - rem) / priv->base.pixmap->drawable.width; + modulus(temp_box->y1, priv->base.pixmap->drawable.height, rem); + shift_y = (temp_box->y1 - rem) / priv->base.pixmap->drawable.height; + + if (shift_x != 0) { + priv->large.box.x1 += + shift_x * priv->base.pixmap->drawable.width; + priv->large.box.x2 += + shift_x * priv->base.pixmap->drawable.width; + } + if (shift_y != 0) { + priv->large.box.y1 += + shift_y * priv->base.pixmap->drawable.height; + priv->large.box.y2 += + shift_y * priv->base.pixmap->drawable.height; + } + } + } } - Bool glamor_composite_largepixmap_region(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - glamor_pixmap_private * source_pixmap_priv, - glamor_pixmap_private * mask_pixmap_priv, - glamor_pixmap_private * dest_pixmap_priv, - RegionPtr region, Bool force_clip, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, - CARD16 width, CARD16 height) + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + glamor_pixmap_private *source_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, + RegionPtr region, Bool force_clip, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height) { - glamor_screen_private *glamor_priv; - glamor_pixmap_clipped_regions *clipped_dest_regions; - glamor_pixmap_clipped_regions *clipped_source_regions; - glamor_pixmap_clipped_regions *clipped_mask_regions; - int n_dest_regions; - int n_mask_regions; - int n_source_regions; - int i,j,k; - int need_clean_source_fbo = 0; - int need_clean_mask_fbo = 0; - int is_normal_source_fbo = 0; - int is_normal_mask_fbo = 0; - int fixed_block_width, fixed_block_height; - int null_source, null_mask; - glamor_pixmap_private * need_free_source_pixmap_priv = NULL; - glamor_pixmap_private * need_free_mask_pixmap_priv = NULL; - int source_repeat_type = 0, mask_repeat_type = 0; - int ok = TRUE; - - if (source->repeat) - source_repeat_type = source->repeatType; - else - source_repeat_type = RepeatNone; - - if (mask && mask->repeat) - mask_repeat_type = mask->repeatType; - else - mask_repeat_type = RepeatNone; - - glamor_priv = dest_pixmap_priv->base.glamor_priv; - fixed_block_width = glamor_priv->max_fbo_size; - fixed_block_height = glamor_priv->max_fbo_size; - /* If we got an totally out-of-box region for a source or mask - * region without repeat, we need to set it as null_source and - * give it a solid color (0,0,0,0). */ - null_source = 0; - null_mask = 0; - RegionTranslate(region, -dest->pDrawable->x, - -dest->pDrawable->y); - - /* need to transform the dest region to the correct sourcei/mask region. - * it's a little complex, as one single edge of the - * target region may be transformed to cross a block boundary of the - * source or mask. Then it's impossible to handle it as usual way. - * We may have to split the original dest region to smaller region, and - * make sure each region's transformed region can fit into one texture, - * and then continue this loop again, and each time when a transformed region - * cross the bound, we need to copy it to a single pixmap and do the composition - * with the new pixmap. If the transformed region doesn't cross a source/mask's - * boundary then we don't need to copy. - * - */ - if (source_pixmap_priv - && source->transform - && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - int source_transformed_block_width, source_transformed_block_height; - if (!glamor_get_transform_block_size(source->transform, - source_pixmap_priv->large.block_w, - source_pixmap_priv->large.block_h, - &source_transformed_block_width, - &source_transformed_block_height)) { - DEBUGF("source block size less than 1, fallback.\n"); - RegionTranslate(region, dest->pDrawable->x, - dest->pDrawable->y); - return FALSE; - } - fixed_block_width = min(fixed_block_width , source_transformed_block_width); - fixed_block_height = min(fixed_block_height , source_transformed_block_height); - DEBUGF("new source block size %d x %d \n", fixed_block_width, fixed_block_height); - } - - if (mask_pixmap_priv - && mask->transform - && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - int mask_transformed_block_width, mask_transformed_block_height; - if (!glamor_get_transform_block_size(mask->transform, - mask_pixmap_priv->large.block_w, - mask_pixmap_priv->large.block_h, - &mask_transformed_block_width, - &mask_transformed_block_height)) { - DEBUGF("mask block size less than 1, fallback.\n"); - RegionTranslate(region, dest->pDrawable->x, - dest->pDrawable->y); - return FALSE; - } - fixed_block_width = min(fixed_block_width , mask_transformed_block_width); - fixed_block_height = min(fixed_block_height , mask_transformed_block_height); - DEBUGF("new mask block size %d x %d \n", fixed_block_width, fixed_block_height); - } - - /*compute the correct block width and height whose transformed source/mask - *region can fit into one texture.*/ - if (force_clip || fixed_block_width < glamor_priv->max_fbo_size - || fixed_block_height < glamor_priv->max_fbo_size) - clipped_dest_regions = glamor_compute_clipped_regions_ext(dest_pixmap_priv, - region, - &n_dest_regions, - fixed_block_width, - fixed_block_height, - 0, 0); - else - clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap_priv, - region, - &n_dest_regions, - 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) - && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - /* XXX self-copy...*/ - need_free_source_pixmap_priv = source_pixmap_priv; - source_pixmap_priv = malloc(sizeof(*source_pixmap_priv)); - *source_pixmap_priv = *need_free_source_pixmap_priv; - need_free_source_pixmap_priv = source_pixmap_priv; - } - assert(mask_pixmap_priv != dest_pixmap_priv); - - for(i = 0; i < n_dest_regions; i++) - { - DEBUGF("dest region %d idx %d\n", i, clipped_dest_regions[i].block_idx); - DEBUGRegionPrint(clipped_dest_regions[i].region); - SET_PIXMAP_FBO_CURRENT(dest_pixmap_priv, clipped_dest_regions[i].block_idx); - if ( source_pixmap_priv && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - if (!source->transform && source_repeat_type != RepeatPad) { - RegionTranslate(clipped_dest_regions[i].region, - x_source - x_dest, - 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, - 0, 0); - is_normal_source_fbo = 1; - } - else { - clipped_source_regions = glamor_compute_transform_clipped_regions(source_pixmap_priv, - source->transform, - clipped_dest_regions[i].region, - &n_source_regions, - x_source - x_dest, y_source - y_dest, - 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). */ - null_source = 1; - n_source_regions = 1; - } else - _glamor_process_transformed_clipped_region(source_pixmap_priv, - source_repeat_type, clipped_source_regions, &n_source_regions, - &need_clean_source_fbo); - } - DEBUGF("source clipped result %d region: \n", n_source_regions); - for(j = 0; j < n_source_regions; j++) - { - if (is_normal_source_fbo) - SET_PIXMAP_FBO_CURRENT(source_pixmap_priv, - clipped_source_regions[j].block_idx); - - if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - if (is_normal_mask_fbo && is_normal_source_fbo) { - /* both mask and source are normal fbo box without transform or repeatpad. - * The region is clipped against source and then we clip it against mask here.*/ - DEBUGF("source region %d idx %d\n", j, clipped_source_regions[j].block_idx); - DEBUGRegionPrint(clipped_source_regions[j].region); - RegionTranslate(clipped_source_regions[j].region, - - x_source + x_mask, - - 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, - 0, 0); - is_normal_mask_fbo = 1; - } else if (is_normal_mask_fbo && !is_normal_source_fbo) { - assert(n_source_regions == 1); - /* The source fbo is not a normal fbo box, it has transform or repeatpad. - * the valid clip region should be the clip dest region rather than the - * clip source region.*/ - RegionTranslate(clipped_dest_regions[i].region, - - x_dest + x_mask, - - 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, - 0, 0); - is_normal_mask_fbo = 1; - } else { - /* This mask region has transform or repeatpad, we need clip it agains the previous - * valid region rather than the mask region. */ - if (!is_normal_source_fbo) - clipped_mask_regions = glamor_compute_transform_clipped_regions(mask_pixmap_priv, - mask->transform, - clipped_dest_regions[i].region, - &n_mask_regions, - x_mask - x_dest, - y_mask - y_dest, - 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, 0, 0); - is_normal_mask_fbo = 0; - if (n_mask_regions == 0) { - /* Pad the out-of-box region to (0,0,0,0). */ - null_mask = 1; - n_mask_regions = 1; - } else - _glamor_process_transformed_clipped_region(mask_pixmap_priv, - mask_repeat_type, clipped_mask_regions, &n_mask_regions, - &need_clean_mask_fbo); - } - DEBUGF("mask clipped result %d region: \n", n_mask_regions); + glamor_screen_private *glamor_priv; + glamor_pixmap_clipped_regions *clipped_dest_regions; + glamor_pixmap_clipped_regions *clipped_source_regions; + glamor_pixmap_clipped_regions *clipped_mask_regions; + int n_dest_regions; + int n_mask_regions; + int n_source_regions; + int i, j, k; + int need_clean_source_fbo = 0; + int need_clean_mask_fbo = 0; + int is_normal_source_fbo = 0; + int is_normal_mask_fbo = 0; + int fixed_block_width, fixed_block_height; + int null_source, null_mask; + glamor_pixmap_private *need_free_source_pixmap_priv = NULL; + glamor_pixmap_private *need_free_mask_pixmap_priv = NULL; + int source_repeat_type = 0, mask_repeat_type = 0; + int ok = TRUE; + + if (source->repeat) + source_repeat_type = source->repeatType; + else + source_repeat_type = RepeatNone; + + if (mask && mask->repeat) + mask_repeat_type = mask->repeatType; + else + mask_repeat_type = RepeatNone; + + glamor_priv = dest_pixmap_priv->base.glamor_priv; + fixed_block_width = glamor_priv->max_fbo_size; + fixed_block_height = glamor_priv->max_fbo_size; + /* If we got an totally out-of-box region for a source or mask + * region without repeat, we need to set it as null_source and + * give it a solid color (0,0,0,0). */ + null_source = 0; + null_mask = 0; + RegionTranslate(region, -dest->pDrawable->x, -dest->pDrawable->y); + + /* need to transform the dest region to the correct sourcei/mask region. + * it's a little complex, as one single edge of the + * target region may be transformed to cross a block boundary of the + * source or mask. Then it's impossible to handle it as usual way. + * We may have to split the original dest region to smaller region, and + * make sure each region's transformed region can fit into one texture, + * and then continue this loop again, and each time when a transformed region + * cross the bound, we need to copy it to a single pixmap and do the composition + * with the new pixmap. If the transformed region doesn't cross a source/mask's + * boundary then we don't need to copy. + * + */ + if (source_pixmap_priv + && source->transform + && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + int source_transformed_block_width, source_transformed_block_height; + + if (!glamor_get_transform_block_size(source->transform, + source_pixmap_priv->large.block_w, + source_pixmap_priv->large.block_h, + &source_transformed_block_width, + &source_transformed_block_height)) + { + DEBUGF("source block size less than 1, fallback.\n"); + RegionTranslate(region, dest->pDrawable->x, dest->pDrawable->y); + return FALSE; + } + fixed_block_width = + min(fixed_block_width, source_transformed_block_width); + fixed_block_height = + min(fixed_block_height, source_transformed_block_height); + DEBUGF("new source block size %d x %d \n", fixed_block_width, + fixed_block_height); + } + + if (mask_pixmap_priv + && mask->transform && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + int mask_transformed_block_width, mask_transformed_block_height; + + if (!glamor_get_transform_block_size(mask->transform, + mask_pixmap_priv->large.block_w, + mask_pixmap_priv->large.block_h, + &mask_transformed_block_width, + &mask_transformed_block_height)) { + DEBUGF("mask block size less than 1, fallback.\n"); + RegionTranslate(region, dest->pDrawable->x, dest->pDrawable->y); + return FALSE; + } + fixed_block_width = + min(fixed_block_width, mask_transformed_block_width); + fixed_block_height = + min(fixed_block_height, mask_transformed_block_height); + DEBUGF("new mask block size %d x %d \n", fixed_block_width, + fixed_block_height); + } + + /*compute the correct block width and height whose transformed source/mask + *region can fit into one texture.*/ + if (force_clip || fixed_block_width < glamor_priv->max_fbo_size + || fixed_block_height < glamor_priv->max_fbo_size) + clipped_dest_regions = + glamor_compute_clipped_regions_ext(dest_pixmap_priv, region, + &n_dest_regions, + fixed_block_width, + fixed_block_height, 0, 0); + else + clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap_priv, + region, + &n_dest_regions, + 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) + && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + /* XXX self-copy... */ + need_free_source_pixmap_priv = source_pixmap_priv; + source_pixmap_priv = malloc(sizeof(*source_pixmap_priv)); + *source_pixmap_priv = *need_free_source_pixmap_priv; + need_free_source_pixmap_priv = source_pixmap_priv; + } + assert(mask_pixmap_priv != dest_pixmap_priv); + + for (i = 0; i < n_dest_regions; i++) { + DEBUGF("dest region %d idx %d\n", i, + clipped_dest_regions[i].block_idx); + DEBUGRegionPrint(clipped_dest_regions[i].region); + SET_PIXMAP_FBO_CURRENT(dest_pixmap_priv, + clipped_dest_regions[i].block_idx); + if (source_pixmap_priv && + source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (!source->transform && source_repeat_type != RepeatPad) { + RegionTranslate(clipped_dest_regions[i].region, + x_source - x_dest, 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, 0, 0); + is_normal_source_fbo = 1; + } + else { + clipped_source_regions = + glamor_compute_transform_clipped_regions(source_pixmap_priv, + source->transform, + clipped_dest_regions + [i].region, + &n_source_regions, + x_source - x_dest, + y_source - y_dest, + 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). */ + null_source = 1; + n_source_regions = 1; + } + else + _glamor_process_transformed_clipped_region + (source_pixmap_priv, source_repeat_type, + clipped_source_regions, &n_source_regions, + &need_clean_source_fbo); + } + DEBUGF("source clipped result %d region: \n", n_source_regions); + for (j = 0; j < n_source_regions; j++) { + if (is_normal_source_fbo) + SET_PIXMAP_FBO_CURRENT(source_pixmap_priv, + clipped_source_regions[j].block_idx); + + if (mask_pixmap_priv && + mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (is_normal_mask_fbo && is_normal_source_fbo) { + /* both mask and source are normal fbo box without transform or repeatpad. + * The region is clipped against source and then we clip it against mask here.*/ + DEBUGF("source region %d idx %d\n", j, + clipped_source_regions[j].block_idx); + DEBUGRegionPrint(clipped_source_regions[j].region); + RegionTranslate(clipped_source_regions[j].region, + -x_source + x_mask, -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, 0, + 0); + is_normal_mask_fbo = 1; + } + else if (is_normal_mask_fbo && !is_normal_source_fbo) { + assert(n_source_regions == 1); + /* The source fbo is not a normal fbo box, it has transform or repeatpad. + * the valid clip region should be the clip dest region rather than the + * clip source region.*/ + RegionTranslate(clipped_dest_regions[i].region, + -x_dest + x_mask, -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, 0, + 0); + is_normal_mask_fbo = 1; + } + else { + /* This mask region has transform or repeatpad, we need clip it agains the previous + * valid region rather than the mask region. */ + if (!is_normal_source_fbo) + clipped_mask_regions = + glamor_compute_transform_clipped_regions + (mask_pixmap_priv, mask->transform, + clipped_dest_regions[i].region, + &n_mask_regions, x_mask - x_dest, + y_mask - y_dest, 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, 0, 0); + is_normal_mask_fbo = 0; + if (n_mask_regions == 0) { + /* Pad the out-of-box region to (0,0,0,0). */ + null_mask = 1; + n_mask_regions = 1; + } + else + _glamor_process_transformed_clipped_region + (mask_pixmap_priv, mask_repeat_type, + clipped_mask_regions, &n_mask_regions, + &need_clean_mask_fbo); + } + DEBUGF("mask clipped result %d region: \n", n_mask_regions); #define COMPOSITE_REGION(region) do { \ if (!glamor_composite_clipped_region(op, \ @@ -1186,139 +1263,157 @@ glamor_composite_largepixmap_region(CARD8 op, } \ } while(0) - for(k = 0; k < n_mask_regions; k++) - { - DEBUGF("mask region %d idx %d\n", k, clipped_mask_regions[k].block_idx); - DEBUGRegionPrint(clipped_mask_regions[k].region); - if (is_normal_mask_fbo) { - SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, - clipped_mask_regions[k].block_idx); - DEBUGF("mask fbo off %d %d \n", - mask_pixmap_priv->large.box.x1, - mask_pixmap_priv->large.box.y1); - DEBUGF("start composite mask hasn't transform.\n"); - RegionTranslate(clipped_mask_regions[k].region, - x_dest - x_mask + dest->pDrawable->x, - y_dest - y_mask + dest->pDrawable->y); - COMPOSITE_REGION(clipped_mask_regions[k].region); - } else if (!is_normal_mask_fbo && !is_normal_source_fbo) { - DEBUGF("start composite both mask and source have transform.\n"); - RegionTranslate(clipped_dest_regions[i].region, - dest->pDrawable->x, - dest->pDrawable->y); - COMPOSITE_REGION(clipped_dest_regions[i].region); - } else { - DEBUGF("start composite only mask has transform.\n"); - RegionTranslate(clipped_source_regions[j].region, - x_dest - x_source + dest->pDrawable->x, - y_dest - y_source + dest->pDrawable->y); - COMPOSITE_REGION(clipped_source_regions[j].region); - } - RegionDestroy(clipped_mask_regions[k].region); - } - free(clipped_mask_regions); - if (null_mask) null_mask = 0; - if (need_clean_mask_fbo) { - assert(is_normal_mask_fbo == 0); - glamor_destroy_fbo(mask_pixmap_priv->base.fbo); - mask_pixmap_priv->base.fbo = NULL; - need_clean_mask_fbo = 0; - } - } else { - if (is_normal_source_fbo) { - RegionTranslate(clipped_source_regions[j].region, - -x_source + x_dest + dest->pDrawable->x, - -y_source + y_dest + dest->pDrawable->y); - COMPOSITE_REGION(clipped_source_regions[j].region); - } else { - /* Source has transform or repeatPad. dest regions is the right - * region to do the composite. */ - RegionTranslate(clipped_dest_regions[i].region, - dest->pDrawable->x, - dest->pDrawable->y); - COMPOSITE_REGION(clipped_dest_regions[i].region); - } - } - if (clipped_source_regions && clipped_source_regions[j].region) - RegionDestroy(clipped_source_regions[j].region); - } - free(clipped_source_regions); - if (null_source) null_source = 0; - if (need_clean_source_fbo) { - assert(is_normal_source_fbo == 0); - glamor_destroy_fbo(source_pixmap_priv->base.fbo); - source_pixmap_priv->base.fbo = NULL; - need_clean_source_fbo = 0; - } - } - else { - if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - if (!mask->transform && mask_repeat_type != RepeatPad) { - RegionTranslate(clipped_dest_regions[i].region, - x_mask - x_dest, - 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, 0, 0); - is_normal_mask_fbo = 1; - } - else { - clipped_mask_regions = glamor_compute_transform_clipped_regions(mask_pixmap_priv, - mask->transform, - clipped_dest_regions[i].region, - &n_mask_regions, - x_mask - x_dest, y_mask - y_dest, - 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). */ - null_mask = 1; - n_mask_regions = 1; - } else - _glamor_process_transformed_clipped_region(mask_pixmap_priv, - mask_repeat_type, clipped_mask_regions, &n_mask_regions, - &need_clean_mask_fbo); - } - - for(k = 0; k < n_mask_regions; k++) - { - DEBUGF("mask region %d idx %d\n", k, clipped_mask_regions[k].block_idx); - DEBUGRegionPrint(clipped_mask_regions[k].region); - if (is_normal_mask_fbo) { - SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, - clipped_mask_regions[k].block_idx); - RegionTranslate(clipped_mask_regions[k].region, - x_dest - x_mask + dest->pDrawable->x, - y_dest - y_mask + dest->pDrawable->y); - COMPOSITE_REGION(clipped_mask_regions[k].region); - } else { - RegionTranslate(clipped_dest_regions[i].region, - dest->pDrawable->x, - dest->pDrawable->y); - COMPOSITE_REGION(clipped_dest_regions[i].region); - } - RegionDestroy(clipped_mask_regions[k].region); - } - free(clipped_mask_regions); - if (null_mask) null_mask = 0; - if (need_clean_mask_fbo) { - glamor_destroy_fbo(mask_pixmap_priv->base.fbo); - mask_pixmap_priv->base.fbo = NULL; - need_clean_mask_fbo = 0; - } - } - else { - RegionTranslate(clipped_dest_regions[i].region, - dest->pDrawable->x, - dest->pDrawable->y); - COMPOSITE_REGION(clipped_dest_regions[i].region); - } - } - RegionDestroy(clipped_dest_regions[i].region); - } - free(clipped_dest_regions); - free(need_free_source_pixmap_priv); - free(need_free_mask_pixmap_priv); - ok = TRUE; - return ok; + for (k = 0; k < n_mask_regions; k++) { + DEBUGF("mask region %d idx %d\n", k, + clipped_mask_regions[k].block_idx); + DEBUGRegionPrint(clipped_mask_regions[k].region); + if (is_normal_mask_fbo) { + SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, + clipped_mask_regions[k]. + block_idx); + DEBUGF("mask fbo off %d %d \n", + mask_pixmap_priv->large.box.x1, + mask_pixmap_priv->large.box.y1); + DEBUGF("start composite mask hasn't transform.\n"); + RegionTranslate(clipped_mask_regions[k].region, + x_dest - x_mask + + dest->pDrawable->x, + y_dest - y_mask + + dest->pDrawable->y); + COMPOSITE_REGION(clipped_mask_regions[k].region); + } + else if (!is_normal_mask_fbo && !is_normal_source_fbo) { + DEBUGF + ("start composite both mask and source have transform.\n"); + RegionTranslate(clipped_dest_regions[i].region, + dest->pDrawable->x, + dest->pDrawable->y); + COMPOSITE_REGION(clipped_dest_regions[i].region); + } + else { + DEBUGF + ("start composite only mask has transform.\n"); + RegionTranslate(clipped_source_regions[j].region, + x_dest - x_source + + dest->pDrawable->x, + y_dest - y_source + + dest->pDrawable->y); + COMPOSITE_REGION(clipped_source_regions[j].region); + } + RegionDestroy(clipped_mask_regions[k].region); + } + free(clipped_mask_regions); + if (null_mask) + null_mask = 0; + if (need_clean_mask_fbo) { + assert(is_normal_mask_fbo == 0); + glamor_destroy_fbo(mask_pixmap_priv->base.fbo); + mask_pixmap_priv->base.fbo = NULL; + need_clean_mask_fbo = 0; + } + } + else { + if (is_normal_source_fbo) { + RegionTranslate(clipped_source_regions[j].region, + -x_source + x_dest + dest->pDrawable->x, + -y_source + y_dest + + dest->pDrawable->y); + COMPOSITE_REGION(clipped_source_regions[j].region); + } + else { + /* Source has transform or repeatPad. dest regions is the right + * region to do the composite. */ + RegionTranslate(clipped_dest_regions[i].region, + dest->pDrawable->x, dest->pDrawable->y); + COMPOSITE_REGION(clipped_dest_regions[i].region); + } + } + if (clipped_source_regions && clipped_source_regions[j].region) + RegionDestroy(clipped_source_regions[j].region); + } + free(clipped_source_regions); + if (null_source) + null_source = 0; + if (need_clean_source_fbo) { + assert(is_normal_source_fbo == 0); + glamor_destroy_fbo(source_pixmap_priv->base.fbo); + source_pixmap_priv->base.fbo = NULL; + need_clean_source_fbo = 0; + } + } + else { + if (mask_pixmap_priv && + mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (!mask->transform && mask_repeat_type != RepeatPad) { + RegionTranslate(clipped_dest_regions[i].region, + x_mask - x_dest, 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, 0, 0); + is_normal_mask_fbo = 1; + } + else { + clipped_mask_regions = + glamor_compute_transform_clipped_regions + (mask_pixmap_priv, mask->transform, + clipped_dest_regions[i].region, &n_mask_regions, + x_mask - x_dest, y_mask - y_dest, 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). */ + null_mask = 1; + n_mask_regions = 1; + } + else + _glamor_process_transformed_clipped_region + (mask_pixmap_priv, mask_repeat_type, + clipped_mask_regions, &n_mask_regions, + &need_clean_mask_fbo); + } + + for (k = 0; k < n_mask_regions; k++) { + DEBUGF("mask region %d idx %d\n", k, + clipped_mask_regions[k].block_idx); + DEBUGRegionPrint(clipped_mask_regions[k].region); + if (is_normal_mask_fbo) { + SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, + clipped_mask_regions[k]. + block_idx); + RegionTranslate(clipped_mask_regions[k].region, + x_dest - x_mask + dest->pDrawable->x, + y_dest - y_mask + dest->pDrawable->y); + COMPOSITE_REGION(clipped_mask_regions[k].region); + } + else { + RegionTranslate(clipped_dest_regions[i].region, + dest->pDrawable->x, dest->pDrawable->y); + COMPOSITE_REGION(clipped_dest_regions[i].region); + } + RegionDestroy(clipped_mask_regions[k].region); + } + free(clipped_mask_regions); + if (null_mask) + null_mask = 0; + if (need_clean_mask_fbo) { + glamor_destroy_fbo(mask_pixmap_priv->base.fbo); + mask_pixmap_priv->base.fbo = NULL; + need_clean_mask_fbo = 0; + } + } + else { + RegionTranslate(clipped_dest_regions[i].region, + dest->pDrawable->x, dest->pDrawable->y); + COMPOSITE_REGION(clipped_dest_regions[i].region); + } + } + RegionDestroy(clipped_dest_regions[i].region); + } + free(clipped_dest_regions); + free(need_free_source_pixmap_priv); + free(need_free_mask_pixmap_priv); + ok = TRUE; + return ok; } |