2 #include <stdint.h> /* For INT16_MAX */
4 #include "glamor_priv.h"
7 glamor_get_transform_extent_from_box(struct pixman_box32
*box
,
8 struct pixman_transform
*transform
);
10 static inline glamor_pixmap_private
*
11 __glamor_large(glamor_pixmap_private
*pixmap_priv
) {
12 assert(glamor_pixmap_priv_is_large(pixmap_priv
));
17 * Clip the boxes regards to each pixmap's block array.
19 * Should translate the region to relative coords to the pixmap,
23 //#define DEBUGF(str, ...) do {} while(0)
24 #define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__)
25 //#define DEBUGRegionPrint(x) do {} while (0)
26 #define DEBUGRegionPrint RegionPrint
29 static glamor_pixmap_clipped_regions
*
30 __glamor_compute_clipped_regions(int block_w
,
36 int *n_region
, int reverse
, int upsidedown
)
38 glamor_pixmap_clipped_regions
*clipped_regions
;
40 int start_x
, start_y
, end_x
, end_y
;
41 int start_block_x
, start_block_y
;
42 int end_block_x
, end_block_y
;
43 int loop_start_block_x
, loop_start_block_y
;
44 int loop_end_block_x
, loop_end_block_y
;
45 int loop_block_stride
;
46 int i
, j
, delta_i
, delta_j
;
47 RegionRec temp_region
;
48 RegionPtr current_region
;
53 extent
= RegionExtents(region
);
54 start_x
= MAX(x
, extent
->x1
);
55 start_y
= MAX(y
, extent
->y1
);
56 end_x
= MIN(x
+ w
, extent
->x2
);
57 end_y
= MIN(y
+ h
, extent
->y2
);
59 DEBUGF("start compute clipped regions:\n");
60 DEBUGF("block w %d h %d x %d y %d w %d h %d, block_stride %d \n",
61 block_w
, block_h
, x
, y
, w
, h
, block_stride
);
62 DEBUGRegionPrint(region
);
64 DEBUGF("start_x %d start_y %d end_x %d end_y %d \n", start_x
, start_y
,
67 if (start_x
>= end_x
|| start_y
>= end_y
) {
72 start_block_x
= (start_x
- x
) / block_w
;
73 start_block_y
= (start_y
- y
) / block_h
;
74 end_block_x
= (end_x
- x
) / block_w
;
75 end_block_y
= (end_y
- y
) / block_h
;
77 clipped_regions
= calloc((end_block_x
- start_block_x
+ 1)
78 * (end_block_y
- start_block_y
+ 1),
79 sizeof(*clipped_regions
));
81 DEBUGF("startx %d starty %d endx %d endy %d \n",
82 start_x
, start_y
, end_x
, end_y
);
83 DEBUGF("start_block_x %d end_block_x %d \n", start_block_x
, end_block_x
);
84 DEBUGF("start_block_y %d end_block_y %d \n", start_block_y
, end_block_y
);
87 loop_start_block_x
= start_block_x
;
88 loop_end_block_x
= end_block_x
+ 1;
92 loop_start_block_x
= end_block_x
;
93 loop_end_block_x
= start_block_x
- 1;
98 loop_start_block_y
= start_block_y
;
99 loop_end_block_y
= end_block_y
+ 1;
103 loop_start_block_y
= end_block_y
;
104 loop_end_block_y
= start_block_y
- 1;
108 loop_block_stride
= delta_j
* block_stride
;
109 block_idx
= (loop_start_block_y
- delta_j
) * block_stride
;
111 for (j
= loop_start_block_y
; j
!= loop_end_block_y
; j
+= delta_j
) {
112 block_idx
+= loop_block_stride
;
113 temp_block_idx
= block_idx
+ loop_start_block_x
;
114 for (i
= loop_start_block_x
;
115 i
!= loop_end_block_x
; i
+= delta_i
, temp_block_idx
+= delta_i
) {
118 temp_box
.x1
= x
+ i
* block_w
;
119 temp_box
.y1
= y
+ j
* block_h
;
120 temp_box
.x2
= MIN(temp_box
.x1
+ block_w
, end_x
);
121 temp_box
.y2
= MIN(temp_box
.y1
+ block_h
, end_y
);
122 RegionInitBoxes(&temp_region
, &temp_box
, 1);
123 DEBUGF("block idx %d \n", temp_block_idx
);
124 DEBUGRegionPrint(&temp_region
);
125 current_region
= RegionCreate(NULL
, 4);
126 RegionIntersect(current_region
, &temp_region
, region
);
127 DEBUGF("i %d j %d region: \n", i
, j
);
128 DEBUGRegionPrint(current_region
);
129 if (RegionNumRects(current_region
)) {
130 clipped_regions
[k
].region
= current_region
;
131 clipped_regions
[k
].block_idx
= temp_block_idx
;
135 RegionDestroy(current_region
);
136 RegionUninit(&temp_region
);
141 return clipped_regions
;
145 * Do a two round clipping,
146 * first is to clip the region regard to current pixmap's
147 * block array. Then for each clipped region, do a inner
148 * block clipping. This is to make sure the final result
149 * will be shapped by inner_block_w and inner_block_h, and
150 * the final region also will not cross the pixmap's block
153 * This is mainly used by transformation support when do
157 glamor_pixmap_clipped_regions
*
158 glamor_compute_clipped_regions_ext(PixmapPtr pixmap
,
161 int inner_block_w
, int inner_block_h
,
162 int reverse
, int upsidedown
)
164 glamor_pixmap_private
*pixmap_priv
= glamor_get_pixmap_private(pixmap
);
165 glamor_pixmap_clipped_regions
*clipped_regions
, *inner_regions
,
167 int i
, j
, x
, y
, k
, inner_n_regions
;
171 int block_w
, block_h
;
173 DEBUGF("ext called \n");
175 if (glamor_pixmap_priv_is_small(pixmap_priv
)) {
176 clipped_regions
= calloc(1, sizeof(*clipped_regions
));
177 if (clipped_regions
== NULL
) {
181 clipped_regions
[0].region
= RegionCreate(NULL
, 1);
182 clipped_regions
[0].block_idx
= 0;
183 RegionCopy(clipped_regions
[0].region
, region
);
185 block_w
= pixmap
->drawable
.width
;
186 block_h
= pixmap
->drawable
.height
;
187 box_array
= &small_box
;
188 small_box
.x1
= small_box
.y1
= 0;
189 small_box
.x2
= block_w
;
190 small_box
.y2
= block_h
;
193 glamor_pixmap_private
*priv
= __glamor_large(pixmap_priv
);
195 clipped_regions
= __glamor_compute_clipped_regions(priv
->block_w
,
199 pixmap
->drawable
.width
,
200 pixmap
->drawable
.height
,
202 reverse
, upsidedown
);
204 if (clipped_regions
== NULL
) {
208 block_w
= priv
->block_w
;
209 block_h
= priv
->block_h
;
210 box_array
= priv
->box_array
;
212 if (inner_block_w
>= block_w
&& inner_block_h
>= block_h
)
213 return clipped_regions
;
214 result_regions
= calloc(*n_region
215 * ((block_w
+ inner_block_w
- 1) /
217 * ((block_h
+ inner_block_h
- 1) /
218 inner_block_h
), sizeof(*result_regions
));
220 for (i
= 0; i
< *n_region
; i
++) {
221 x
= box_array
[clipped_regions
[i
].block_idx
].x1
;
222 y
= box_array
[clipped_regions
[i
].block_idx
].y1
;
223 width
= box_array
[clipped_regions
[i
].block_idx
].x2
- x
;
224 height
= box_array
[clipped_regions
[i
].block_idx
].y2
- y
;
225 inner_regions
= __glamor_compute_clipped_regions(inner_block_w
,
233 reverse
, upsidedown
);
234 for (j
= 0; j
< inner_n_regions
; j
++) {
235 result_regions
[k
].region
= inner_regions
[j
].region
;
236 result_regions
[k
].block_idx
= clipped_regions
[i
].block_idx
;
242 free(clipped_regions
);
243 return result_regions
;
248 * For the repeat pad mode, we can simply convert the region and
249 * let the out-of-box region can cover the needed edge of the source/mask
250 * Then apply a normal clip we can get what we want.
253 _glamor_convert_pad_region(RegionPtr region
, int w
, int h
)
255 RegionPtr pad_region
;
260 nrect
= RegionNumRects(region
);
261 box
= RegionRects(region
);
262 pad_region
= RegionCreate(NULL
, 4);
263 if (pad_region
== NULL
)
267 RegionRec temp_region
;
270 if (pad_box
.x1
< 0 && pad_box
.x2
<= 0)
272 else if (pad_box
.x1
>= w
&& pad_box
.x2
> w
)
274 if (pad_box
.y1
< 0 && pad_box
.y2
<= 0)
276 else if (pad_box
.y1
>= h
&& pad_box
.y2
> h
)
278 RegionInitBoxes(&temp_region
, &pad_box
, 1);
279 RegionAppend(pad_region
, &temp_region
);
280 RegionUninit(&temp_region
);
283 RegionValidate(pad_region
, &overlap
);
288 * For one type of large pixmap, its one direction is not exceed the
289 * size limitation, and in another word, on one direction it has only
292 * This case of reflect repeating, we can optimize it and avoid repeat
293 * clip on that direction. We can just enlarge the repeat box and can
294 * cover all the dest region on that direction. But latter, we need to
295 * fixup the clipped result to get a correct coords for the subsequent
296 * processing. This function is to do the coords correction.
300 _glamor_largepixmap_reflect_fixup(short *xy1
, short *xy2
, int wh
)
305 if (*xy2
- *xy1
> wh
) {
310 modulus(*xy1
, wh
, c1
);
311 odd1
= ((*xy1
- c1
) / wh
) & 0x1;
312 modulus(*xy2
, wh
, c2
);
313 odd2
= ((*xy2
- c2
) / wh
) & 0x1;
319 else if (odd1
&& !odd2
) {
321 *xy2
= MAX(c2
, wh
- c1
);
323 else if (!odd1
&& odd2
) {
325 *xy1
= MIN(c1
, wh
- c2
);
334 * Clip the boxes regards to each pixmap's block array.
336 * Should translate the region to relative coords to the pixmap,
339 * @is_transform: if it is set, it has a transform matrix.
342 static glamor_pixmap_clipped_regions
*
343 _glamor_compute_clipped_regions(PixmapPtr pixmap
,
344 glamor_pixmap_private
*pixmap_priv
,
345 RegionPtr region
, int *n_region
,
346 int repeat_type
, int is_transform
,
347 int reverse
, int upsidedown
)
349 glamor_pixmap_clipped_regions
*clipped_regions
;
352 RegionPtr current_region
;
353 int pixmap_width
, pixmap_height
;
356 RegionRec repeat_region
;
359 int x_center_shift
= 0, y_center_shift
= 0;
360 glamor_pixmap_private
*priv
;
362 DEBUGRegionPrint(region
);
363 if (glamor_pixmap_priv_is_small(pixmap_priv
)) {
364 clipped_regions
= calloc(1, sizeof(*clipped_regions
));
365 clipped_regions
[0].region
= RegionCreate(NULL
, 1);
366 clipped_regions
[0].block_idx
= 0;
367 RegionCopy(clipped_regions
[0].region
, region
);
369 return clipped_regions
;
372 priv
= __glamor_large(pixmap_priv
);
374 pixmap_width
= pixmap
->drawable
.width
;
375 pixmap_height
= pixmap
->drawable
.height
;
376 if (repeat_type
== 0 || repeat_type
== RepeatPad
) {
377 RegionPtr saved_region
= NULL
;
379 if (repeat_type
== RepeatPad
) {
380 saved_region
= region
;
382 _glamor_convert_pad_region(saved_region
, pixmap_width
,
384 if (region
== NULL
) {
389 clipped_regions
= __glamor_compute_clipped_regions(priv
->block_w
,
393 pixmap
->drawable
.width
,
394 pixmap
->drawable
.height
,
396 reverse
, upsidedown
);
398 RegionDestroy(region
);
399 return clipped_regions
;
401 extent
= RegionExtents(region
);
403 x_center_shift
= extent
->x1
/ pixmap_width
;
404 if (x_center_shift
< 0)
406 if (abs(x_center_shift
) & 1)
408 y_center_shift
= extent
->y1
/ pixmap_height
;
409 if (y_center_shift
< 0)
411 if (abs(y_center_shift
) & 1)
415 right_shift
= ((-extent
->x1
+ pixmap_width
- 1) / pixmap_width
);
417 down_shift
= ((-extent
->y1
+ pixmap_height
- 1) / pixmap_height
);
419 if (right_shift
!= 0 || down_shift
!= 0) {
420 if (repeat_type
== RepeatReflect
) {
421 right_shift
= (right_shift
+ 1) & ~1;
422 down_shift
= (down_shift
+ 1) & ~1;
424 RegionTranslate(region
, right_shift
* pixmap_width
,
425 down_shift
* pixmap_height
);
428 extent
= RegionExtents(region
);
429 /* Tile a large pixmap to another large pixmap.
430 * We can't use the target large pixmap as the
431 * loop variable, instead we need to loop for all
432 * the blocks in the tile pixmap.
434 * simulate repeat each single block to cover the
435 * target's blocks. Two special case:
436 * a block_wcnt == 1 or block_hcnt ==1, then we
437 * only need to loop one direction as the other
438 * direction is fully included in the first block.
440 * For the other cases, just need to start
441 * from a proper shiftx/shifty, and then increase
442 * y by tile_height each time to walk trhough the
443 * target block and then walk trhough the target
444 * at x direction by increate tile_width each time.
446 * This way, we can consolidate all the sub blocks
447 * of the target boxes into one tile source's block.
451 clipped_regions
= calloc(priv
->block_wcnt
* priv
->block_hcnt
,
452 sizeof(*clipped_regions
));
453 if (clipped_regions
== NULL
) {
457 if (right_shift
!= 0 || down_shift
!= 0) {
458 DEBUGF("region to be repeated shifted \n");
459 DEBUGRegionPrint(region
);
461 DEBUGF("repeat pixmap width %d height %d \n", pixmap_width
, pixmap_height
);
462 DEBUGF("extent x1 %d y1 %d x2 %d y2 %d \n", extent
->x1
, extent
->y1
,
463 extent
->x2
, extent
->y2
);
464 for (j
= 0; j
< priv
->block_hcnt
; j
++) {
465 for (i
= 0; i
< priv
->block_wcnt
; i
++) {
466 int dx
= pixmap_width
;
467 int dy
= pixmap_height
;
471 int saved_y1
, saved_y2
;
472 int x_idx
= 0, y_idx
= 0, saved_y_idx
= 0;
473 RegionRec temp_region
;
474 BoxRec reflect_repeat_box
;
475 BoxPtr valid_repeat_box
;
477 shift_x
= (extent
->x1
/ pixmap_width
) * pixmap_width
;
478 shift_y
= (extent
->y1
/ pixmap_height
) * pixmap_height
;
479 idx
= j
* priv
->block_wcnt
+ i
;
480 if (repeat_type
== RepeatReflect
) {
481 x_idx
= (extent
->x1
/ pixmap_width
);
482 y_idx
= (extent
->y1
/ pixmap_height
);
485 /* Construct a rect to clip the target region. */
486 repeat_box
.x1
= shift_x
+ priv
->box_array
[idx
].x1
;
487 repeat_box
.y1
= shift_y
+ priv
->box_array
[idx
].y1
;
488 if (priv
->block_wcnt
== 1) {
489 repeat_box
.x2
= extent
->x2
;
490 dx
= extent
->x2
- repeat_box
.x1
;
493 repeat_box
.x2
= shift_x
+ priv
->box_array
[idx
].x2
;
494 if (priv
->block_hcnt
== 1) {
495 repeat_box
.y2
= extent
->y2
;
496 dy
= extent
->y2
- repeat_box
.y1
;
499 repeat_box
.y2
= shift_y
+ priv
->box_array
[idx
].y2
;
501 current_region
= RegionCreate(NULL
, 4);
502 RegionInit(&temp_region
, NULL
, 4);
503 DEBUGF("init repeat box %d %d %d %d \n",
504 repeat_box
.x1
, repeat_box
.y1
, repeat_box
.x2
, repeat_box
.y2
);
506 if (repeat_type
== RepeatNormal
) {
507 saved_y1
= repeat_box
.y1
;
508 saved_y2
= repeat_box
.y2
;
509 for (; repeat_box
.x1
< extent
->x2
;
510 repeat_box
.x1
+= dx
, repeat_box
.x2
+= dx
) {
511 repeat_box
.y1
= saved_y1
;
512 repeat_box
.y2
= saved_y2
;
513 for (repeat_box
.y1
= saved_y1
, repeat_box
.y2
= saved_y2
;
514 repeat_box
.y1
< extent
->y2
;
515 repeat_box
.y1
+= dy
, repeat_box
.y2
+= dy
) {
517 RegionInitBoxes(&repeat_region
, &repeat_box
, 1);
518 DEBUGF("Start to clip repeat region: \n");
519 DEBUGRegionPrint(&repeat_region
);
520 RegionIntersect(&temp_region
, &repeat_region
, region
);
521 DEBUGF("clip result:\n");
522 DEBUGRegionPrint(&temp_region
);
523 RegionAppend(current_region
, &temp_region
);
524 RegionUninit(&repeat_region
);
528 else if (repeat_type
== RepeatReflect
) {
529 saved_y1
= repeat_box
.y1
;
530 saved_y2
= repeat_box
.y2
;
532 for (;; repeat_box
.x1
+= dx
, repeat_box
.x2
+= dx
) {
533 repeat_box
.y1
= saved_y1
;
534 repeat_box
.y2
= saved_y2
;
536 reflect_repeat_box
.x1
= (x_idx
& 1) ?
537 ((2 * x_idx
+ 1) * dx
- repeat_box
.x2
) : repeat_box
.x1
;
538 reflect_repeat_box
.x2
= (x_idx
& 1) ?
539 ((2 * x_idx
+ 1) * dx
- repeat_box
.x1
) : repeat_box
.x2
;
540 valid_repeat_box
= &reflect_repeat_box
;
542 if (valid_repeat_box
->x1
>= extent
->x2
)
544 for (repeat_box
.y1
= saved_y1
, repeat_box
.y2
= saved_y2
;;
545 repeat_box
.y1
+= dy
, repeat_box
.y2
+= dy
) {
547 DEBUGF("x_idx %d y_idx %d dx %d dy %d\n", x_idx
, y_idx
,
549 DEBUGF("repeat box %d %d %d %d \n", repeat_box
.x1
,
550 repeat_box
.y1
, repeat_box
.x2
, repeat_box
.y2
);
552 if (priv
->block_hcnt
> 1) {
553 reflect_repeat_box
.y1
= (y_idx
& 1) ?
554 ((2 * y_idx
+ 1) * dy
-
555 repeat_box
.y2
) : repeat_box
.y1
;
556 reflect_repeat_box
.y2
=
557 (y_idx
& 1) ? ((2 * y_idx
+ 1) * dy
-
558 repeat_box
.y1
) : repeat_box
.y2
;
561 reflect_repeat_box
.y1
= repeat_box
.y1
;
562 reflect_repeat_box
.y2
= repeat_box
.y2
;
565 DEBUGF("valid_repeat_box x1 %d y1 %d \n",
566 valid_repeat_box
->x1
, valid_repeat_box
->y1
);
567 if (valid_repeat_box
->y1
>= extent
->y2
)
569 RegionInitBoxes(&repeat_region
, valid_repeat_box
, 1);
570 DEBUGF("start to clip repeat[reflect] region: \n");
571 DEBUGRegionPrint(&repeat_region
);
572 RegionIntersect(&temp_region
, &repeat_region
, region
);
574 DEBUGRegionPrint(&temp_region
);
575 if (is_transform
&& RegionNumRects(&temp_region
)) {
579 temp_extent
= RegionExtents(&temp_region
);
580 if (priv
->block_wcnt
> 1) {
583 ((2 * x_idx
+ 1) * dx
-
586 ((2 * x_idx
+ 1) * dx
-
590 temp_box
.x1
= temp_extent
->x1
;
591 temp_box
.x2
= temp_extent
->x2
;
593 modulus(temp_box
.x1
, pixmap_width
, temp_box
.x1
);
594 modulus(temp_box
.x2
, pixmap_width
, temp_box
.x2
);
595 if (temp_box
.x2
== 0)
596 temp_box
.x2
= pixmap_width
;
599 temp_box
.x1
= temp_extent
->x1
;
600 temp_box
.x2
= temp_extent
->x2
;
601 _glamor_largepixmap_reflect_fixup(&temp_box
.x1
,
606 if (priv
->block_hcnt
> 1) {
609 ((2 * y_idx
+ 1) * dy
-
612 ((2 * y_idx
+ 1) * dy
-
616 temp_box
.y1
= temp_extent
->y1
;
617 temp_box
.y2
= temp_extent
->y2
;
620 modulus(temp_box
.y1
, pixmap_height
,
622 modulus(temp_box
.y2
, pixmap_height
,
624 if (temp_box
.y2
== 0)
625 temp_box
.y2
= pixmap_height
;
628 temp_box
.y1
= temp_extent
->y1
;
629 temp_box
.y2
= temp_extent
->y2
;
630 _glamor_largepixmap_reflect_fixup(&temp_box
.y1
,
635 RegionInitBoxes(&temp_region
, &temp_box
, 1);
636 RegionTranslate(&temp_region
,
637 x_center_shift
* pixmap_width
,
638 y_center_shift
* pixmap_height
);
639 DEBUGF("for transform result:\n");
640 DEBUGRegionPrint(&temp_region
);
642 RegionAppend(current_region
, &temp_region
);
643 RegionUninit(&repeat_region
);
649 DEBUGF("dx %d dy %d \n", dx
, dy
);
651 if (RegionNumRects(current_region
)) {
653 if ((right_shift
!= 0 || down_shift
!= 0) &&
654 !(is_transform
&& repeat_type
== RepeatReflect
))
655 RegionTranslate(current_region
, -right_shift
* pixmap_width
,
656 -down_shift
* pixmap_height
);
657 clipped_regions
[m
].region
= current_region
;
658 clipped_regions
[m
].block_idx
= idx
;
662 RegionDestroy(current_region
);
663 RegionUninit(&temp_region
);
667 if (right_shift
!= 0 || down_shift
!= 0)
668 RegionTranslate(region
, -right_shift
* pixmap_width
,
669 -down_shift
* pixmap_height
);
672 return clipped_regions
;
675 glamor_pixmap_clipped_regions
*
676 glamor_compute_clipped_regions(PixmapPtr pixmap
,
678 int *n_region
, int repeat_type
,
679 int reverse
, int upsidedown
)
681 glamor_pixmap_private
*priv
= glamor_get_pixmap_private(pixmap
);
682 return _glamor_compute_clipped_regions(pixmap
, priv
, region
, n_region
, repeat_type
,
683 0, reverse
, upsidedown
);
686 /* XXX overflow still exist. maybe we need to change to use region32.
687 * by default. Or just use region32 for repeat cases?
689 static glamor_pixmap_clipped_regions
*
690 glamor_compute_transform_clipped_regions(PixmapPtr pixmap
,
691 struct pixman_transform
*transform
,
692 RegionPtr region
, int *n_region
,
693 int dx
, int dy
, int repeat_type
,
694 int reverse
, int upsidedown
)
696 glamor_pixmap_private
*priv
= glamor_get_pixmap_private(pixmap
);
698 struct pixman_box32 temp_box
;
699 struct pixman_box16 short_box
;
700 RegionPtr temp_region
;
701 glamor_pixmap_clipped_regions
*ret
;
703 temp_region
= RegionCreate(NULL
, 4);
704 temp_extent
= RegionExtents(region
);
705 DEBUGF("dest region \n");
706 DEBUGRegionPrint(region
);
707 /* dx/dy may exceed MAX SHORT. we have to use
708 * a box32 to represent it.*/
709 temp_box
.x1
= temp_extent
->x1
+ dx
;
710 temp_box
.x2
= temp_extent
->x2
+ dx
;
711 temp_box
.y1
= temp_extent
->y1
+ dy
;
712 temp_box
.y2
= temp_extent
->y2
+ dy
;
714 DEBUGF("source box %d %d %d %d \n", temp_box
.x1
, temp_box
.y1
, temp_box
.x2
,
717 glamor_get_transform_extent_from_box(&temp_box
, transform
);
718 if (repeat_type
== RepeatNone
) {
723 temp_box
.x2
= MIN(temp_box
.x2
, pixmap
->drawable
.width
);
724 temp_box
.y2
= MIN(temp_box
.y2
, pixmap
->drawable
.height
);
726 /* Now copy back the box32 to a box16 box, avoiding overflow. */
727 short_box
.x1
= MIN(temp_box
.x1
, INT16_MAX
);
728 short_box
.y1
= MIN(temp_box
.y1
, INT16_MAX
);
729 short_box
.x2
= MIN(temp_box
.x2
, INT16_MAX
);
730 short_box
.y2
= MIN(temp_box
.y2
, INT16_MAX
);
731 RegionInitBoxes(temp_region
, &short_box
, 1);
732 DEBUGF("copy to temp source region \n");
733 DEBUGRegionPrint(temp_region
);
734 ret
= _glamor_compute_clipped_regions(pixmap
,
738 repeat_type
, 1, reverse
, upsidedown
);
739 DEBUGF("n_regions = %d \n", *n_region
);
740 RegionDestroy(temp_region
);
746 * As transform and repeatpad mode.
747 * We may get a clipped result which in multiple regions.
748 * It's not easy to do a 2nd round clipping just as we do
749 * without transform/repeatPad. As it's not easy to reverse
750 * the 2nd round clipping result with a transform/repeatPad mode,
751 * or even impossible for some transformation.
753 * So we have to merge the fragmental region into one region
754 * if the clipped result cross the region boundary.
757 glamor_merge_clipped_regions(PixmapPtr pixmap
,
758 glamor_pixmap_private
*pixmap_priv
,
760 glamor_pixmap_clipped_regions
*clipped_regions
,
761 int *n_regions
, int *need_clean_fbo
)
763 BoxRec temp_box
, copy_box
;
764 RegionPtr temp_region
;
765 glamor_pixmap_private
*temp_priv
;
766 PixmapPtr temp_pixmap
;
769 int pixmap_width
, pixmap_height
;
770 glamor_pixmap_private
*priv
;
772 priv
= __glamor_large(pixmap_priv
);
773 pixmap_width
= pixmap
->drawable
.width
;
774 pixmap_height
=pixmap
->drawable
.height
;
776 temp_region
= RegionCreate(NULL
, 4);
777 for (i
= 0; i
< *n_regions
; i
++) {
778 DEBUGF("Region %d:\n", i
);
779 DEBUGRegionPrint(clipped_regions
[i
].region
);
780 RegionAppend(temp_region
, clipped_regions
[i
].region
);
783 RegionValidate(temp_region
, &overlap
);
784 DEBUGF("temp region: \n");
785 DEBUGRegionPrint(temp_region
);
787 temp_box
= *RegionExtents(temp_region
);
789 DEBUGF("need copy region: \n");
790 DEBUGF("%d %d %d %d \n", temp_box
.x1
, temp_box
.y1
, temp_box
.x2
,
793 glamor_create_pixmap(pixmap
->drawable
.pScreen
,
794 temp_box
.x2
- temp_box
.x1
,
795 temp_box
.y2
- temp_box
.y1
,
796 pixmap
->drawable
.depth
,
797 GLAMOR_CREATE_PIXMAP_FIXUP
);
798 if (temp_pixmap
== NULL
) {
803 temp_priv
= glamor_get_pixmap_private(temp_pixmap
);
804 assert(glamor_pixmap_priv_is_small(temp_priv
));
806 priv
->box
= temp_box
;
807 if (temp_box
.x1
>= 0 && temp_box
.x2
<= pixmap_width
808 && temp_box
.y1
>= 0 && temp_box
.y2
<= pixmap_height
) {
813 copy_box
.x2
= temp_box
.x2
- temp_box
.x1
;
814 copy_box
.y2
= temp_box
.y2
- temp_box
.y1
;
817 glamor_copy(&pixmap
->drawable
,
818 &temp_pixmap
->drawable
,
819 NULL
, ©_box
, 1, dx
, dy
, 0, 0, 0, NULL
);
820 // glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width,
821 // temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff00);
824 for (i
= 0; i
< *n_regions
; i
++) {
828 box
= REGION_RECTS(clipped_regions
[i
].region
);
829 nbox
= REGION_NUM_RECTS(clipped_regions
[i
].region
);
833 DEBUGF("box x1 %d y1 %d x2 %d y2 %d \n",
834 box
->x1
, box
->y1
, box
->x2
, box
->y2
);
835 modulus(box
->x1
, pixmap_width
, c
);
836 dx
= c
- (box
->x1
- temp_box
.x1
);
837 copy_box
.x1
= box
->x1
- temp_box
.x1
;
838 copy_box
.x2
= box
->x2
- temp_box
.x1
;
840 modulus(box
->y1
, pixmap_height
, d
);
841 dy
= d
- (box
->y1
- temp_box
.y1
);
842 copy_box
.y1
= box
->y1
- temp_box
.y1
;
843 copy_box
.y2
= box
->y2
- temp_box
.y1
;
845 DEBUGF("copying box %d %d %d %d, dx %d dy %d\n",
846 copy_box
.x1
, copy_box
.y1
, copy_box
.x2
,
847 copy_box
.y2
, dx
, dy
);
849 glamor_copy(&pixmap
->drawable
,
850 &temp_pixmap
->drawable
,
851 NULL
, ©_box
, 1, dx
, dy
, 0, 0, 0, NULL
);
856 //glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width,
857 // temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff);
859 /* The first region will be released at caller side. */
860 for (i
= 1; i
< *n_regions
; i
++)
861 RegionDestroy(clipped_regions
[i
].region
);
862 RegionDestroy(temp_region
);
863 priv
->box
= temp_box
;
864 priv
->fbo
= glamor_pixmap_detach_fbo(temp_priv
);
865 DEBUGF("priv box x1 %d y1 %d x2 %d y2 %d \n",
866 priv
->box
.x1
, priv
->box
.y1
, priv
->box
.x2
, priv
->box
.y2
);
867 glamor_destroy_pixmap(temp_pixmap
);
873 * Given an expected transformed block width and block height,
875 * This function calculate a new block width and height which
876 * guarantee the transform result will not exceed the given
877 * block width and height.
879 * For large block width and height (> 2048), we choose a
880 * smaller new width and height and to reduce the cross region
881 * boundary and can avoid some overhead.
885 glamor_get_transform_block_size(struct pixman_transform
*transform
,
886 int block_w
, int block_h
,
887 int *transformed_block_w
,
888 int *transformed_block_h
)
890 double a
, b
, c
, d
, e
, f
, g
, h
;
894 a
= pixman_fixed_to_double(transform
->matrix
[0][0]);
895 b
= pixman_fixed_to_double(transform
->matrix
[0][1]);
896 c
= pixman_fixed_to_double(transform
->matrix
[1][0]);
897 d
= pixman_fixed_to_double(transform
->matrix
[1][1]);
898 scale
= pixman_fixed_to_double(transform
->matrix
[2][2]);
899 if (block_w
> 2048) {
900 /* For large block size, we shrink it to smaller box,
901 * thus latter we may get less cross boundary regions and
902 * thus can avoid some extra copy.
906 height
= block_h
/ 4;
910 height
= block_h
- 2;
918 e
= MIN(block_w
, floor(width
* scale
) / MAX(fabs(e
), fabs(g
)));
919 f
= MIN(block_h
, floor(height
* scale
) / MAX(fabs(f
), fabs(h
)));
920 *transformed_block_w
= MIN(e
, f
) - 1;
921 *transformed_block_h
= *transformed_block_w
;
922 if (*transformed_block_w
<= 0 || *transformed_block_h
<= 0)
924 DEBUGF("original block_w/h %d %d, fixed %d %d \n", block_w
, block_h
,
925 *transformed_block_w
, *transformed_block_h
);
929 #define VECTOR_FROM_POINT(p, x, y) do {\
932 p.v[2] = 1.0; } while (0)
934 glamor_get_transform_extent_from_box(struct pixman_box32
*box
,
935 struct pixman_transform
*transform
)
937 struct pixman_f_vector p0
, p1
, p2
, p3
;
938 float min_x
, min_y
, max_x
, max_y
;
940 struct pixman_f_transform ftransform
;
942 VECTOR_FROM_POINT(p0
, box
->x1
, box
->y1
);
943 VECTOR_FROM_POINT(p1
, box
->x2
, box
->y1
);
944 VECTOR_FROM_POINT(p2
, box
->x2
, box
->y2
);
945 VECTOR_FROM_POINT(p3
, box
->x1
, box
->y2
);
947 pixman_f_transform_from_pixman_transform(&ftransform
, transform
);
948 pixman_f_transform_point(&ftransform
, &p0
);
949 pixman_f_transform_point(&ftransform
, &p1
);
950 pixman_f_transform_point(&ftransform
, &p2
);
951 pixman_f_transform_point(&ftransform
, &p3
);
953 min_x
= MIN(p0
.v
[0], p1
.v
[0]);
954 min_x
= MIN(min_x
, p2
.v
[0]);
955 min_x
= MIN(min_x
, p3
.v
[0]);
957 min_y
= MIN(p0
.v
[1], p1
.v
[1]);
958 min_y
= MIN(min_y
, p2
.v
[1]);
959 min_y
= MIN(min_y
, p3
.v
[1]);
961 max_x
= MAX(p0
.v
[0], p1
.v
[0]);
962 max_x
= MAX(max_x
, p2
.v
[0]);
963 max_x
= MAX(max_x
, p3
.v
[0]);
965 max_y
= MAX(p0
.v
[1], p1
.v
[1]);
966 max_y
= MAX(max_y
, p2
.v
[1]);
967 max_y
= MAX(max_y
, p3
.v
[1]);
968 box
->x1
= floor(min_x
) - 1;
969 box
->y1
= floor(min_y
) - 1;
970 box
->x2
= ceil(max_x
) + 1;
971 box
->y2
= ceil(max_y
) + 1;
975 _glamor_process_transformed_clipped_region(PixmapPtr pixmap
,
976 glamor_pixmap_private
*priv
,
978 glamor_pixmap_clipped_regions
*
979 clipped_regions
, int *n_regions
,
982 int shift_x
, shift_y
;
984 if (*n_regions
!= 1) {
985 /* Merge all source regions into one region. */
986 glamor_merge_clipped_regions(pixmap
, priv
, repeat_type
,
987 clipped_regions
, n_regions
,
991 glamor_set_pixmap_fbo_current(priv
, clipped_regions
[0].block_idx
);
992 if (repeat_type
== RepeatReflect
|| repeat_type
== RepeatNormal
) {
993 /* The required source areas are in one region,
994 * we need to shift the corresponding box's coords to proper position,
995 * thus we can calculate the relative coords correctly.*/
999 temp_box
= RegionExtents(clipped_regions
[0].region
);
1000 modulus(temp_box
->x1
, pixmap
->drawable
.width
, rem
);
1001 shift_x
= (temp_box
->x1
- rem
) / pixmap
->drawable
.width
;
1002 modulus(temp_box
->y1
, pixmap
->drawable
.height
, rem
);
1003 shift_y
= (temp_box
->y1
- rem
) / pixmap
->drawable
.height
;
1006 __glamor_large(priv
)->box
.x1
+=
1007 shift_x
* pixmap
->drawable
.width
;
1008 __glamor_large(priv
)->box
.x2
+=
1009 shift_x
* pixmap
->drawable
.width
;
1012 __glamor_large(priv
)->box
.y1
+=
1013 shift_y
* pixmap
->drawable
.height
;
1014 __glamor_large(priv
)->box
.y2
+=
1015 shift_y
* pixmap
->drawable
.height
;
1022 glamor_composite_largepixmap_region(CARD8 op
,
1026 PixmapPtr source_pixmap
,
1027 PixmapPtr mask_pixmap
,
1028 PixmapPtr dest_pixmap
,
1029 RegionPtr region
, Bool force_clip
,
1034 INT16 x_dest
, INT16 y_dest
,
1035 CARD16 width
, CARD16 height
)
1037 ScreenPtr screen
= dest_pixmap
->drawable
.pScreen
;
1038 glamor_screen_private
*glamor_priv
= glamor_get_screen_private(screen
);
1039 glamor_pixmap_private
*source_pixmap_priv
= glamor_get_pixmap_private(source_pixmap
);
1040 glamor_pixmap_private
*mask_pixmap_priv
= glamor_get_pixmap_private(mask_pixmap
);
1041 glamor_pixmap_private
*dest_pixmap_priv
= glamor_get_pixmap_private(dest_pixmap
);
1042 glamor_pixmap_clipped_regions
*clipped_dest_regions
;
1043 glamor_pixmap_clipped_regions
*clipped_source_regions
;
1044 glamor_pixmap_clipped_regions
*clipped_mask_regions
;
1047 int n_source_regions
;
1049 int need_clean_source_fbo
= 0;
1050 int need_clean_mask_fbo
= 0;
1051 int is_normal_source_fbo
= 0;
1052 int is_normal_mask_fbo
= 0;
1053 int fixed_block_width
, fixed_block_height
;
1054 int dest_block_width
, dest_block_height
;
1055 int null_source
, null_mask
;
1056 glamor_pixmap_private
*need_free_source_pixmap_priv
= NULL
;
1057 glamor_pixmap_private
*need_free_mask_pixmap_priv
= NULL
;
1058 int source_repeat_type
= 0, mask_repeat_type
= 0;
1061 if (source_pixmap
== dest_pixmap
) {
1062 glamor_fallback("source and dest pixmaps are the same\n");
1065 if (mask_pixmap
== dest_pixmap
) {
1066 glamor_fallback("mask and dest pixmaps are the same\n");
1071 source_repeat_type
= source
->repeatType
;
1073 source_repeat_type
= RepeatNone
;
1075 if (mask
&& mask
->repeat
)
1076 mask_repeat_type
= mask
->repeatType
;
1078 mask_repeat_type
= RepeatNone
;
1080 if (glamor_pixmap_priv_is_large(dest_pixmap_priv
)) {
1081 dest_block_width
= __glamor_large(dest_pixmap_priv
)->block_w
;
1082 dest_block_height
= __glamor_large(dest_pixmap_priv
)->block_h
;
1084 dest_block_width
= dest_pixmap
->drawable
.width
;
1085 dest_block_height
= dest_pixmap
->drawable
.height
;
1087 fixed_block_width
= dest_block_width
;
1088 fixed_block_height
= dest_block_height
;
1090 /* If we got an totally out-of-box region for a source or mask
1091 * region without repeat, we need to set it as null_source and
1092 * give it a solid color (0,0,0,0). */
1095 RegionTranslate(region
, -dest
->pDrawable
->x
, -dest
->pDrawable
->y
);
1097 /* need to transform the dest region to the correct sourcei/mask region.
1098 * it's a little complex, as one single edge of the
1099 * target region may be transformed to cross a block boundary of the
1100 * source or mask. Then it's impossible to handle it as usual way.
1101 * We may have to split the original dest region to smaller region, and
1102 * make sure each region's transformed region can fit into one texture,
1103 * and then continue this loop again, and each time when a transformed region
1104 * cross the bound, we need to copy it to a single pixmap and do the composition
1105 * with the new pixmap. If the transformed region doesn't cross a source/mask's
1106 * boundary then we don't need to copy.
1109 if (source_pixmap_priv
1110 && source
->transform
1111 && glamor_pixmap_priv_is_large(source_pixmap_priv
)) {
1112 int source_transformed_block_width
, source_transformed_block_height
;
1114 if (!glamor_get_transform_block_size(source
->transform
,
1115 __glamor_large(source_pixmap_priv
)->block_w
,
1116 __glamor_large(source_pixmap_priv
)->block_h
,
1117 &source_transformed_block_width
,
1118 &source_transformed_block_height
))
1120 DEBUGF("source block size less than 1, fallback.\n");
1121 RegionTranslate(region
, dest
->pDrawable
->x
, dest
->pDrawable
->y
);
1125 min(fixed_block_width
, source_transformed_block_width
);
1126 fixed_block_height
=
1127 min(fixed_block_height
, source_transformed_block_height
);
1128 DEBUGF("new source block size %d x %d \n", fixed_block_width
,
1129 fixed_block_height
);
1132 if (mask_pixmap_priv
1133 && mask
->transform
&& glamor_pixmap_priv_is_large(mask_pixmap_priv
)) {
1134 int mask_transformed_block_width
, mask_transformed_block_height
;
1136 if (!glamor_get_transform_block_size(mask
->transform
,
1137 __glamor_large(mask_pixmap_priv
)->block_w
,
1138 __glamor_large(mask_pixmap_priv
)->block_h
,
1139 &mask_transformed_block_width
,
1140 &mask_transformed_block_height
)) {
1141 DEBUGF("mask block size less than 1, fallback.\n");
1142 RegionTranslate(region
, dest
->pDrawable
->x
, dest
->pDrawable
->y
);
1146 min(fixed_block_width
, mask_transformed_block_width
);
1147 fixed_block_height
=
1148 min(fixed_block_height
, mask_transformed_block_height
);
1149 DEBUGF("new mask block size %d x %d \n", fixed_block_width
,
1150 fixed_block_height
);
1153 /*compute the correct block width and height whose transformed source/mask
1154 *region can fit into one texture.*/
1155 if (force_clip
|| fixed_block_width
< dest_block_width
1156 || fixed_block_height
< dest_block_height
)
1157 clipped_dest_regions
=
1158 glamor_compute_clipped_regions_ext(dest_pixmap
, region
,
1161 fixed_block_height
, 0, 0);
1163 clipped_dest_regions
= glamor_compute_clipped_regions(dest_pixmap
,
1167 DEBUGF("dest clipped result %d region: \n", n_dest_regions
);
1168 if (source_pixmap_priv
1169 && (source_pixmap_priv
== dest_pixmap_priv
||
1170 source_pixmap_priv
== mask_pixmap_priv
)
1171 && glamor_pixmap_priv_is_large(source_pixmap_priv
)) {
1172 /* XXX self-copy... */
1173 need_free_source_pixmap_priv
= source_pixmap_priv
;
1174 source_pixmap_priv
= malloc(sizeof(*source_pixmap_priv
));
1175 *source_pixmap_priv
= *need_free_source_pixmap_priv
;
1176 need_free_source_pixmap_priv
= source_pixmap_priv
;
1178 assert(mask_pixmap_priv
!= dest_pixmap_priv
);
1180 for (i
= 0; i
< n_dest_regions
; i
++) {
1181 DEBUGF("dest region %d idx %d\n", i
,
1182 clipped_dest_regions
[i
].block_idx
);
1183 DEBUGRegionPrint(clipped_dest_regions
[i
].region
);
1184 glamor_set_pixmap_fbo_current(dest_pixmap_priv
,
1185 clipped_dest_regions
[i
].block_idx
);
1186 if (source_pixmap_priv
&&
1187 glamor_pixmap_priv_is_large(source_pixmap_priv
)) {
1188 if (!source
->transform
&& source_repeat_type
!= RepeatPad
) {
1189 RegionTranslate(clipped_dest_regions
[i
].region
,
1190 x_source
- x_dest
, y_source
- y_dest
);
1191 clipped_source_regions
=
1192 glamor_compute_clipped_regions(source_pixmap
,
1193 clipped_dest_regions
[i
].
1194 region
, &n_source_regions
,
1195 source_repeat_type
, 0, 0);
1196 is_normal_source_fbo
= 1;
1199 clipped_source_regions
=
1200 glamor_compute_transform_clipped_regions(source_pixmap
,
1202 clipped_dest_regions
1209 is_normal_source_fbo
= 0;
1210 if (n_source_regions
== 0) {
1211 /* Pad the out-of-box region to (0,0,0,0). */
1213 n_source_regions
= 1;
1216 _glamor_process_transformed_clipped_region
1217 (source_pixmap
, source_pixmap_priv
, source_repeat_type
,
1218 clipped_source_regions
, &n_source_regions
,
1219 &need_clean_source_fbo
);
1221 DEBUGF("source clipped result %d region: \n", n_source_regions
);
1222 for (j
= 0; j
< n_source_regions
; j
++) {
1223 if (is_normal_source_fbo
)
1224 glamor_set_pixmap_fbo_current(source_pixmap_priv
,
1225 clipped_source_regions
[j
].block_idx
);
1227 if (mask_pixmap_priv
&&
1228 glamor_pixmap_priv_is_large(mask_pixmap_priv
)) {
1229 if (is_normal_mask_fbo
&& is_normal_source_fbo
) {
1230 /* both mask and source are normal fbo box without transform or repeatpad.
1231 * The region is clipped against source and then we clip it against mask here.*/
1232 DEBUGF("source region %d idx %d\n", j
,
1233 clipped_source_regions
[j
].block_idx
);
1234 DEBUGRegionPrint(clipped_source_regions
[j
].region
);
1235 RegionTranslate(clipped_source_regions
[j
].region
,
1236 -x_source
+ x_mask
, -y_source
+ y_mask
);
1237 clipped_mask_regions
=
1238 glamor_compute_clipped_regions(mask_pixmap
,
1239 clipped_source_regions
1242 mask_repeat_type
, 0,
1244 is_normal_mask_fbo
= 1;
1246 else if (is_normal_mask_fbo
&& !is_normal_source_fbo
) {
1247 assert(n_source_regions
== 1);
1248 /* The source fbo is not a normal fbo box, it has transform or repeatpad.
1249 * the valid clip region should be the clip dest region rather than the
1250 * clip source region.*/
1251 RegionTranslate(clipped_dest_regions
[i
].region
,
1252 -x_dest
+ x_mask
, -y_dest
+ y_mask
);
1253 clipped_mask_regions
=
1254 glamor_compute_clipped_regions(mask_pixmap
,
1255 clipped_dest_regions
1258 mask_repeat_type
, 0,
1260 is_normal_mask_fbo
= 1;
1263 /* This mask region has transform or repeatpad, we need clip it against the previous
1264 * valid region rather than the mask region. */
1265 if (!is_normal_source_fbo
)
1266 clipped_mask_regions
=
1267 glamor_compute_transform_clipped_regions
1268 (mask_pixmap
, mask
->transform
,
1269 clipped_dest_regions
[i
].region
,
1270 &n_mask_regions
, x_mask
- x_dest
,
1271 y_mask
- y_dest
, mask_repeat_type
, 0, 0);
1273 clipped_mask_regions
=
1274 glamor_compute_transform_clipped_regions
1275 (mask_pixmap
, mask
->transform
,
1276 clipped_source_regions
[j
].region
,
1277 &n_mask_regions
, x_mask
- x_source
,
1278 y_mask
- y_source
, mask_repeat_type
, 0, 0);
1279 is_normal_mask_fbo
= 0;
1280 if (n_mask_regions
== 0) {
1281 /* Pad the out-of-box region to (0,0,0,0). */
1286 _glamor_process_transformed_clipped_region
1287 (mask_pixmap
, mask_pixmap_priv
, mask_repeat_type
,
1288 clipped_mask_regions
, &n_mask_regions
,
1289 &need_clean_mask_fbo
);
1291 DEBUGF("mask clipped result %d region: \n", n_mask_regions
);
1293 #define COMPOSITE_REGION(region) do { \
1294 if (!glamor_composite_clipped_region(op, \
1295 null_source ? NULL : source, \
1296 null_mask ? NULL : mask, dest, \
1297 null_source ? NULL : source_pixmap, \
1298 null_mask ? NULL : mask_pixmap, \
1299 dest_pixmap, region, \
1300 x_source, y_source, x_mask, y_mask, \
1301 x_dest, y_dest)) { \
1306 for (k
= 0; k
< n_mask_regions
; k
++) {
1307 DEBUGF("mask region %d idx %d\n", k
,
1308 clipped_mask_regions
[k
].block_idx
);
1309 DEBUGRegionPrint(clipped_mask_regions
[k
].region
);
1310 if (is_normal_mask_fbo
) {
1311 glamor_set_pixmap_fbo_current(mask_pixmap_priv
,
1312 clipped_mask_regions
[k
].
1314 DEBUGF("mask fbo off %d %d \n",
1315 __glamor_large(mask_pixmap_priv
)->box
.x1
,
1316 __glamor_large(mask_pixmap_priv
)->box
.y1
);
1317 DEBUGF("start composite mask hasn't transform.\n");
1318 RegionTranslate(clipped_mask_regions
[k
].region
,
1322 dest
->pDrawable
->y
);
1323 COMPOSITE_REGION(clipped_mask_regions
[k
].region
);
1325 else if (!is_normal_mask_fbo
&& !is_normal_source_fbo
) {
1327 ("start composite both mask and source have transform.\n");
1328 RegionTranslate(clipped_dest_regions
[i
].region
,
1330 dest
->pDrawable
->y
);
1331 COMPOSITE_REGION(clipped_dest_regions
[i
].region
);
1335 ("start composite only mask has transform.\n");
1336 RegionTranslate(clipped_source_regions
[j
].region
,
1340 dest
->pDrawable
->y
);
1341 COMPOSITE_REGION(clipped_source_regions
[j
].region
);
1343 RegionDestroy(clipped_mask_regions
[k
].region
);
1345 free(clipped_mask_regions
);
1348 if (need_clean_mask_fbo
) {
1349 assert(is_normal_mask_fbo
== 0);
1350 glamor_destroy_fbo(glamor_priv
, mask_pixmap_priv
->fbo
);
1351 mask_pixmap_priv
->fbo
= NULL
;
1352 need_clean_mask_fbo
= 0;
1356 if (is_normal_source_fbo
) {
1357 RegionTranslate(clipped_source_regions
[j
].region
,
1358 -x_source
+ x_dest
+ dest
->pDrawable
->x
,
1359 -y_source
+ y_dest
+
1360 dest
->pDrawable
->y
);
1361 COMPOSITE_REGION(clipped_source_regions
[j
].region
);
1364 /* Source has transform or repeatPad. dest regions is the right
1365 * region to do the composite. */
1366 RegionTranslate(clipped_dest_regions
[i
].region
,
1367 dest
->pDrawable
->x
, dest
->pDrawable
->y
);
1368 COMPOSITE_REGION(clipped_dest_regions
[i
].region
);
1371 if (clipped_source_regions
&& clipped_source_regions
[j
].region
)
1372 RegionDestroy(clipped_source_regions
[j
].region
);
1374 free(clipped_source_regions
);
1377 if (need_clean_source_fbo
) {
1378 assert(is_normal_source_fbo
== 0);
1379 glamor_destroy_fbo(glamor_priv
, source_pixmap_priv
->fbo
);
1380 source_pixmap_priv
->fbo
= NULL
;
1381 need_clean_source_fbo
= 0;
1385 if (mask_pixmap_priv
&&
1386 glamor_pixmap_priv_is_large(mask_pixmap_priv
)) {
1387 if (!mask
->transform
&& mask_repeat_type
!= RepeatPad
) {
1388 RegionTranslate(clipped_dest_regions
[i
].region
,
1389 x_mask
- x_dest
, y_mask
- y_dest
);
1390 clipped_mask_regions
=
1391 glamor_compute_clipped_regions(mask_pixmap
,
1392 clipped_dest_regions
[i
].
1393 region
, &n_mask_regions
,
1394 mask_repeat_type
, 0, 0);
1395 is_normal_mask_fbo
= 1;
1398 clipped_mask_regions
=
1399 glamor_compute_transform_clipped_regions
1400 (mask_pixmap
, mask
->transform
,
1401 clipped_dest_regions
[i
].region
, &n_mask_regions
,
1402 x_mask
- x_dest
, y_mask
- y_dest
, mask_repeat_type
, 0,
1404 is_normal_mask_fbo
= 0;
1405 if (n_mask_regions
== 0) {
1406 /* Pad the out-of-box region to (0,0,0,0). */
1411 _glamor_process_transformed_clipped_region
1412 (mask_pixmap
, mask_pixmap_priv
, mask_repeat_type
,
1413 clipped_mask_regions
, &n_mask_regions
,
1414 &need_clean_mask_fbo
);
1417 for (k
= 0; k
< n_mask_regions
; k
++) {
1418 DEBUGF("mask region %d idx %d\n", k
,
1419 clipped_mask_regions
[k
].block_idx
);
1420 DEBUGRegionPrint(clipped_mask_regions
[k
].region
);
1421 if (is_normal_mask_fbo
) {
1422 glamor_set_pixmap_fbo_current(mask_pixmap_priv
,
1423 clipped_mask_regions
[k
].
1425 RegionTranslate(clipped_mask_regions
[k
].region
,
1426 x_dest
- x_mask
+ dest
->pDrawable
->x
,
1427 y_dest
- y_mask
+ dest
->pDrawable
->y
);
1428 COMPOSITE_REGION(clipped_mask_regions
[k
].region
);
1431 RegionTranslate(clipped_dest_regions
[i
].region
,
1432 dest
->pDrawable
->x
, dest
->pDrawable
->y
);
1433 COMPOSITE_REGION(clipped_dest_regions
[i
].region
);
1435 RegionDestroy(clipped_mask_regions
[k
].region
);
1437 free(clipped_mask_regions
);
1440 if (need_clean_mask_fbo
) {
1441 glamor_destroy_fbo(glamor_priv
, mask_pixmap_priv
->fbo
);
1442 mask_pixmap_priv
->fbo
= NULL
;
1443 need_clean_mask_fbo
= 0;
1447 RegionTranslate(clipped_dest_regions
[i
].region
,
1448 dest
->pDrawable
->x
, dest
->pDrawable
->y
);
1449 COMPOSITE_REGION(clipped_dest_regions
[i
].region
);
1452 RegionDestroy(clipped_dest_regions
[i
].region
);
1454 free(clipped_dest_regions
);
1455 free(need_free_source_pixmap_priv
);
1456 free(need_free_mask_pixmap_priv
);