1 /*
2 * Copyright © 2001 Keith Packard
3 *
4 * Partly based on code that is Copyright © The XFree86 Project Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
27 #endif
28
29 #include <stdlib.h>
30
31 #include "uxa-priv.h"
32
33 #ifdef RENDER
34 #include "mipict.h"
35
uxa_composite_fallback_pict_desc(PicturePtr pict,char * string,int n)36 static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string,
37 int n)
38 {
39 char format[20];
40 char size[20];
41 char loc;
42
43 if (!pict) {
44 snprintf(string, n, "None");
45 return;
46 }
47
48 if (pict->pDrawable == NULL) {
49 snprintf(string, n, "source-only");
50 return;
51 }
52
53 switch (pict->format) {
54 case PICT_a8r8g8b8:
55 snprintf(format, 20, "ARGB8888");
56 break;
57 case PICT_x8r8g8b8:
58 snprintf(format, 20, "XRGB8888");
59 break;
60 case PICT_r5g6b5:
61 snprintf(format, 20, "RGB565 ");
62 break;
63 case PICT_x1r5g5b5:
64 snprintf(format, 20, "RGB555 ");
65 break;
66 case PICT_a8:
67 snprintf(format, 20, "A8 ");
68 break;
69 case PICT_a1:
70 snprintf(format, 20, "A1 ");
71 break;
72 default:
73 snprintf(format, 20, "0x%x", (int)pict->format);
74 break;
75 }
76
77 loc = uxa_drawable_is_offscreen(pict->pDrawable) ? 's' : 'm';
78
79 snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
80 pict->pDrawable->height, pict->repeat ? " R" : "");
81
82 snprintf(string, n, "%p:%c fmt %s (%s)%s",
83 pict->pDrawable, loc, format, size,
84 pict->alphaMap ? " with alpha map" :"");
85 }
86
87 static const char *
op_to_string(CARD8 op)88 op_to_string(CARD8 op)
89 {
90 switch (op) {
91 #define C(x) case PictOp##x: return #x
92 C(Clear);
93 C(Src);
94 C(Dst);
95 C(Over);
96 C(OverReverse);
97 C(In);
98 C(InReverse);
99 C(Out);
100 C(OutReverse);
101 C(Atop);
102 C(AtopReverse);
103 C(Xor);
104 C(Add);
105 C(Saturate);
106
107 /*
108 * Operators only available in version 0.2
109 */
110 #if RENDER_MAJOR >= 1 || RENDER_MINOR >= 2
111 C(DisjointClear);
112 C(DisjointSrc);
113 C(DisjointDst);
114 C(DisjointOver);
115 C(DisjointOverReverse);
116 C(DisjointIn);
117 C(DisjointInReverse);
118 C(DisjointOut);
119 C(DisjointOutReverse);
120 C(DisjointAtop);
121 C(DisjointAtopReverse);
122 C(DisjointXor);
123
124 C(ConjointClear);
125 C(ConjointSrc);
126 C(ConjointDst);
127 C(ConjointOver);
128 C(ConjointOverReverse);
129 C(ConjointIn);
130 C(ConjointInReverse);
131 C(ConjointOut);
132 C(ConjointOutReverse);
133 C(ConjointAtop);
134 C(ConjointAtopReverse);
135 C(ConjointXor);
136 #endif
137
138 /*
139 * Operators only available in version 0.11
140 */
141 #if RENDER_MAJOR >= 1 || RENDER_MINOR >= 11
142 C(Multiply);
143 C(Screen);
144 C(Overlay);
145 C(Darken);
146 C(Lighten);
147 C(ColorDodge);
148 C(ColorBurn);
149 C(HardLight);
150 C(SoftLight);
151 C(Difference);
152 C(Exclusion);
153 C(HSLHue);
154 C(HSLSaturation);
155 C(HSLColor);
156 C(HSLLuminosity);
157 #endif
158 default: return "garbage";
159 #undef C
160 }
161 }
162
163 static void
uxa_print_composite_fallback(const char * func,CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst)164 uxa_print_composite_fallback(const char *func, CARD8 op,
165 PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst)
166 {
167 uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
168 char srcdesc[40], maskdesc[40], dstdesc[40];
169
170 if (! uxa_screen->fallback_debug)
171 return;
172
173 /* Limit the noise if fallbacks are expected. */
174 if (uxa_screen->force_fallback)
175 return;
176
177 uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40);
178 uxa_composite_fallback_pict_desc(pMask, maskdesc, 40);
179 uxa_composite_fallback_pict_desc(pDst, dstdesc, 40);
180
181 ErrorF("Composite fallback at %s:\n"
182 " op %s, \n"
183 " src %s, \n"
184 " mask %s, \n"
185 " dst %s, \n",
186 func, op_to_string (op), srcdesc, maskdesc, dstdesc);
187 }
188
uxa_op_reads_destination(CARD8 op)189 Bool uxa_op_reads_destination(CARD8 op)
190 {
191 /* FALSE (does not read destination) is the list of ops in the protocol
192 * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
193 * That's just Clear and Src. ReduceCompositeOp() will already have
194 * converted con/disjoint clear/src to Clear or Src.
195 */
196 switch (op) {
197 case PictOpClear:
198 case PictOpSrc:
199 return FALSE;
200 default:
201 return TRUE;
202 }
203 }
204
205 static Bool
uxa_get_pixel_from_rgba(CARD32 * pixel,CARD16 red,CARD16 green,CARD16 blue,CARD16 alpha,CARD32 format)206 uxa_get_pixel_from_rgba(CARD32 * pixel,
207 CARD16 red,
208 CARD16 green,
209 CARD16 blue,
210 CARD16 alpha,
211 CARD32 format)
212 {
213 int rbits, bbits, gbits, abits;
214 int rshift, bshift, gshift, ashift;
215
216 rbits = PICT_FORMAT_R(format);
217 gbits = PICT_FORMAT_G(format);
218 bbits = PICT_FORMAT_B(format);
219 abits = PICT_FORMAT_A(format);
220 if (abits == 0)
221 abits = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits);
222
223 if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
224 *pixel = alpha >> (16 - abits);
225 return TRUE;
226 }
227
228 if (!PICT_FORMAT_COLOR(format))
229 return FALSE;
230
231 if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
232 bshift = 0;
233 gshift = bbits;
234 rshift = gshift + gbits;
235 ashift = rshift + rbits;
236 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
237 rshift = 0;
238 gshift = rbits;
239 bshift = gshift + gbits;
240 ashift = bshift + bbits;
241 #if XORG_VERSION_CURRENT >= 10699900
242 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
243 ashift = 0;
244 rshift = abits;
245 gshift = rshift + rbits;
246 bshift = gshift + gbits;
247 #endif
248 } else {
249 return FALSE;
250 }
251
252 *pixel = 0;
253 *pixel |= (blue >> (16 - bbits)) << bshift;
254 *pixel |= (green >> (16 - gbits)) << gshift;
255 *pixel |= (red >> (16 - rbits)) << rshift;
256 *pixel |= (alpha >> (16 - abits)) << ashift;
257
258 return TRUE;
259 }
260
261 Bool
uxa_get_rgba_from_pixel(CARD32 pixel,CARD16 * red,CARD16 * green,CARD16 * blue,CARD16 * alpha,CARD32 format)262 uxa_get_rgba_from_pixel(CARD32 pixel,
263 CARD16 * red,
264 CARD16 * green,
265 CARD16 * blue,
266 CARD16 * alpha,
267 CARD32 format)
268 {
269 int rbits, bbits, gbits, abits;
270 int rshift, bshift, gshift, ashift;
271
272 rbits = PICT_FORMAT_R(format);
273 gbits = PICT_FORMAT_G(format);
274 bbits = PICT_FORMAT_B(format);
275 abits = PICT_FORMAT_A(format);
276
277 if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
278 rshift = gshift = bshift = ashift = 0;
279 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
280 bshift = 0;
281 gshift = bbits;
282 rshift = gshift + gbits;
283 ashift = rshift + rbits;
284 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
285 rshift = 0;
286 gshift = rbits;
287 bshift = gshift + gbits;
288 ashift = bshift + bbits;
289 #if XORG_VERSION_CURRENT >= 10699900
290 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
291 ashift = 0;
292 rshift = abits;
293 if (abits == 0)
294 rshift = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits);
295 gshift = rshift + rbits;
296 bshift = gshift + gbits;
297 #endif
298 } else {
299 return FALSE;
300 }
301
302 if (rbits) {
303 *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits);
304 while (rbits < 16) {
305 *red |= *red >> rbits;
306 rbits <<= 1;
307 }
308 } else
309 *red = 0;
310
311 if (gbits) {
312 *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits);
313 while (gbits < 16) {
314 *green |= *green >> gbits;
315 gbits <<= 1;
316 }
317 } else
318 *green = 0;
319
320 if (bbits) {
321 *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits);
322 while (bbits < 16) {
323 *blue |= *blue >> bbits;
324 bbits <<= 1;
325 }
326 } else
327 *blue = 0;
328
329 if (abits) {
330 *alpha =
331 ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits);
332 while (abits < 16) {
333 *alpha |= *alpha >> abits;
334 abits <<= 1;
335 }
336 } else
337 *alpha = 0xffff;
338
339 return TRUE;
340 }
341
342 Bool
uxa_get_color_for_pixmap(PixmapPtr pixmap,CARD32 src_format,CARD32 dst_format,CARD32 * pixel)343 uxa_get_color_for_pixmap (PixmapPtr pixmap,
344 CARD32 src_format,
345 CARD32 dst_format,
346 CARD32 *pixel)
347 {
348 CARD16 red, green, blue, alpha;
349
350 *pixel = uxa_get_pixmap_first_pixel(pixmap);
351
352 if (src_format != dst_format) {
353 if (!uxa_get_rgba_from_pixel(*pixel,
354 &red, &green, &blue, &alpha,
355 src_format))
356 return FALSE;
357
358 if (!uxa_get_pixel_from_rgba(pixel,
359 red, green, blue, alpha,
360 dst_format))
361 return FALSE;
362 }
363
364 return TRUE;
365 }
366
367 static int
uxa_try_driver_solid_fill(PicturePtr pSrc,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)368 uxa_try_driver_solid_fill(PicturePtr pSrc,
369 PicturePtr pDst,
370 INT16 xSrc,
371 INT16 ySrc,
372 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
373 {
374 uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
375 RegionRec region;
376 BoxPtr pbox;
377 int nbox;
378 int dst_off_x, dst_off_y;
379 PixmapPtr pSrcPix = NULL, pDstPix;
380 CARD32 pixel;
381
382 if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDst->pDrawable, GXcopy, FB_ALLONES))
383 return -1;
384
385 pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
386 if (!pDstPix)
387 return -1;
388
389 xDst += pDst->pDrawable->x;
390 yDst += pDst->pDrawable->y;
391
392 if (pSrc->pDrawable) {
393 pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
394 xSrc += pSrc->pDrawable->x;
395 ySrc += pSrc->pDrawable->y;
396 }
397
398 if (!miComputeCompositeRegion(®ion, pSrc, NULL, pDst,
399 xSrc, ySrc, 0, 0, xDst, yDst,
400 width, height))
401 return 1;
402
403 if (pSrcPix) {
404 if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) {
405 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
406 return -1;
407 }
408 } else {
409 SourcePict *source = pSrc->pSourcePict;
410 PictSolidFill *solid = &source->solidFill;
411
412 if (source == NULL || source->type != SourcePictTypeSolidFill) {
413 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
414 return -1;
415 }
416
417 if (pDst->format == PICT_a8r8g8b8) {
418 pixel = solid->color;
419 } else if (pDst->format == PICT_x8r8g8b8) {
420 pixel = solid->color | 0xff000000;
421 } else {
422 CARD16 red, green, blue, alpha;
423
424 if (!uxa_get_rgba_from_pixel(solid->color,
425 &red, &green, &blue, &alpha,
426 PICT_a8r8g8b8) ||
427 !uxa_get_pixel_from_rgba(&pixel,
428 red, green, blue, alpha,
429 pDst->format)) {
430 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
431 return -1;
432 }
433 }
434 }
435
436 if (!(*uxa_screen->info->prepare_solid)
437 (pDstPix, GXcopy, FB_ALLONES, pixel)) {
438 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
439 return -1;
440 }
441
442 REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y);
443
444 nbox = REGION_NUM_RECTS(®ion);
445 pbox = REGION_RECTS(®ion);
446
447 while (nbox--) {
448 (*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1,
449 pbox->x2, pbox->y2);
450 pbox++;
451 }
452
453 (*uxa_screen->info->done_solid) (pDstPix);
454
455 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
456 return 1;
457 }
458
459 static PicturePtr
uxa_picture_for_pixman_format(ScreenPtr screen,pixman_format_code_t format,int width,int height)460 uxa_picture_for_pixman_format(ScreenPtr screen,
461 pixman_format_code_t format,
462 int width, int height)
463 {
464 PicturePtr picture;
465 PixmapPtr pixmap;
466 int error;
467
468 if (format == PIXMAN_a1)
469 format = PIXMAN_a8;
470
471 /* fill alpha if unset */
472 if (PIXMAN_FORMAT_A(format) == 0)
473 format = PIXMAN_a8r8g8b8;
474
475 pixmap = screen->CreatePixmap(screen, width, height,
476 PIXMAN_FORMAT_DEPTH(format),
477 UXA_CREATE_PIXMAP_FOR_MAP);
478 if (!pixmap)
479 return 0;
480
481 if (!uxa_pixmap_is_offscreen(pixmap)) {
482 screen->DestroyPixmap(pixmap);
483 return 0;
484 }
485
486 picture = CreatePicture(0, &pixmap->drawable,
487 PictureMatchFormat(screen,
488 PIXMAN_FORMAT_DEPTH(format),
489 format),
490 0, 0, serverClient, &error);
491 screen->DestroyPixmap(pixmap);
492 if (!picture)
493 return 0;
494
495 ValidatePicture(picture);
496
497 return picture;
498 }
499
500 static PicturePtr
uxa_picture_from_pixman_image(ScreenPtr screen,pixman_image_t * image,pixman_format_code_t format)501 uxa_picture_from_pixman_image(ScreenPtr screen,
502 pixman_image_t * image,
503 pixman_format_code_t format)
504 {
505 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
506 PicturePtr picture;
507 PixmapPtr pixmap;
508 int width, height;
509
510 width = pixman_image_get_width(image);
511 height = pixman_image_get_height(image);
512
513 picture = uxa_picture_for_pixman_format(screen, format,
514 width, height);
515 if (!picture)
516 return 0;
517
518 if (uxa_screen->info->put_image &&
519 ((picture->pDrawable->depth << 24) | picture->format) == format &&
520 uxa_screen->info->put_image((PixmapPtr)picture->pDrawable,
521 0, 0,
522 width, height,
523 (char *)pixman_image_get_data(image),
524 pixman_image_get_stride(image)))
525 return picture;
526
527 pixmap = GetScratchPixmapHeader(screen, width, height,
528 PIXMAN_FORMAT_DEPTH(format),
529 PIXMAN_FORMAT_BPP(format),
530 pixman_image_get_stride(image),
531 pixman_image_get_data(image));
532 if (!pixmap) {
533 FreePicture(picture, 0);
534 return 0;
535 }
536
537 if (((picture->pDrawable->depth << 24) | picture->format) == format) {
538 GCPtr gc;
539
540 gc = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), screen);
541 if (!gc) {
542 FreeScratchPixmapHeader(pixmap);
543 FreePicture(picture, 0);
544 return 0;
545 }
546 ValidateGC(picture->pDrawable, gc);
547
548 (*gc->ops->CopyArea) (&pixmap->drawable, picture->pDrawable,
549 gc, 0, 0, width, height, 0, 0);
550
551 FreeScratchGC(gc);
552 } else {
553 PicturePtr src;
554 int error;
555
556 src = CreatePicture(0, &pixmap->drawable,
557 PictureMatchFormat(screen,
558 PIXMAN_FORMAT_DEPTH(format),
559 format),
560 0, 0, serverClient, &error);
561 if (!src) {
562 FreeScratchPixmapHeader(pixmap);
563 FreePicture(picture, 0);
564 return 0;
565 }
566 ValidatePicture(src);
567
568 if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) {
569 fbComposite(PictOpSrc, src, NULL, picture,
570 0, 0, 0, 0, 0, 0, width, height);
571 uxa_picture_finish_access(picture, UXA_ACCESS_RW);
572 }
573
574 FreePicture(src, 0);
575 }
576 FreeScratchPixmapHeader(pixmap);
577
578 return picture;
579 }
580
581 static PicturePtr
uxa_create_solid(ScreenPtr screen,uint32_t color)582 uxa_create_solid(ScreenPtr screen, uint32_t color)
583 {
584 PixmapPtr pixmap;
585 PicturePtr picture;
586 XID repeat = RepeatNormal;
587 int error = 0;
588
589 pixmap = (*screen->CreatePixmap)(screen, 1, 1, 32,
590 UXA_CREATE_PIXMAP_FOR_MAP);
591 if (!pixmap)
592 return 0;
593
594 if (!uxa_prepare_access((DrawablePtr)pixmap, UXA_ACCESS_RW)) {
595 (*screen->DestroyPixmap)(pixmap);
596 return 0;
597 }
598 *((uint32_t *)pixmap->devPrivate.ptr) = color;
599 uxa_finish_access((DrawablePtr)pixmap, UXA_ACCESS_RW);
600
601 picture = CreatePicture(0, &pixmap->drawable,
602 PictureMatchFormat(screen, 32, PICT_a8r8g8b8),
603 CPRepeat, &repeat, serverClient, &error);
604 (*screen->DestroyPixmap)(pixmap);
605
606 return picture;
607 }
608
609 static PicturePtr
uxa_solid_clear(ScreenPtr screen)610 uxa_solid_clear(ScreenPtr screen)
611 {
612 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
613 PicturePtr picture;
614
615 if (!uxa_screen->solid_clear) {
616 uxa_screen->solid_clear = uxa_create_solid(screen, 0);
617 if (!uxa_screen->solid_clear)
618 return 0;
619 }
620 picture = uxa_screen->solid_clear;
621 return picture;
622 }
623
624 PicturePtr
uxa_acquire_solid(ScreenPtr screen,SourcePict * source)625 uxa_acquire_solid(ScreenPtr screen, SourcePict *source)
626 {
627 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
628 PictSolidFill *solid = &source->solidFill;
629 PicturePtr picture;
630 int i;
631
632 if ((solid->color >> 24) == 0) {
633 picture = uxa_solid_clear(screen);
634 if (!picture)
635 return 0;
636
637 goto DONE;
638 } else if (solid->color == 0xff000000) {
639 if (!uxa_screen->solid_black) {
640 uxa_screen->solid_black = uxa_create_solid(screen, 0xff000000);
641 if (!uxa_screen->solid_black)
642 return 0;
643 }
644 picture = uxa_screen->solid_black;
645 goto DONE;
646 } else if (solid->color == 0xffffffff) {
647 if (!uxa_screen->solid_white) {
648 uxa_screen->solid_white = uxa_create_solid(screen, 0xffffffff);
649 if (!uxa_screen->solid_white)
650 return 0;
651 }
652 picture = uxa_screen->solid_white;
653 goto DONE;
654 }
655
656 for (i = 0; i < uxa_screen->solid_cache_size; i++) {
657 if (uxa_screen->solid_cache[i].color == solid->color) {
658 picture = uxa_screen->solid_cache[i].picture;
659 goto DONE;
660 }
661 }
662
663 picture = uxa_create_solid(screen, solid->color);
664 if (!picture)
665 return 0;
666
667 if (uxa_screen->solid_cache_size == UXA_NUM_SOLID_CACHE) {
668 i = rand() % UXA_NUM_SOLID_CACHE;
669 FreePicture(uxa_screen->solid_cache[i].picture, 0);
670 } else
671 uxa_screen->solid_cache_size++;
672
673 uxa_screen->solid_cache[i].picture = picture;
674 uxa_screen->solid_cache[i].color = solid->color;
675
676 DONE:
677 picture->refcnt++;
678 return picture;
679 }
680
681 PicturePtr
uxa_acquire_pattern(ScreenPtr pScreen,PicturePtr pSrc,pixman_format_code_t format,INT16 x,INT16 y,CARD16 width,CARD16 height)682 uxa_acquire_pattern(ScreenPtr pScreen,
683 PicturePtr pSrc,
684 pixman_format_code_t format,
685 INT16 x, INT16 y, CARD16 width, CARD16 height)
686 {
687 PicturePtr pDst;
688
689 if (pSrc->pSourcePict) {
690 SourcePict *source = pSrc->pSourcePict;
691 if (source->type == SourcePictTypeSolidFill)
692 return uxa_acquire_solid (pScreen, source);
693 }
694
695 pDst = uxa_picture_for_pixman_format(pScreen, format, width, height);
696 if (!pDst)
697 return 0;
698
699 if (uxa_picture_prepare_access(pDst, UXA_ACCESS_RW)) {
700 fbComposite(PictOpSrc, pSrc, NULL, pDst,
701 x, y, 0, 0, 0, 0, width, height);
702 uxa_picture_finish_access(pDst, UXA_ACCESS_RW);
703 return pDst;
704 } else {
705 FreePicture(pDst, 0);
706 return 0;
707 }
708 }
709
710 static Bool
transform_is_integer_translation(PictTransformPtr t,int * tx,int * ty)711 transform_is_integer_translation(PictTransformPtr t, int *tx, int *ty)
712 {
713 if (t == NULL) {
714 *tx = *ty = 0;
715 return TRUE;
716 }
717
718 if (t->matrix[0][0] != IntToxFixed(1) ||
719 t->matrix[0][1] != 0 ||
720 t->matrix[1][0] != 0 ||
721 t->matrix[1][1] != IntToxFixed(1) ||
722 t->matrix[2][0] != 0 ||
723 t->matrix[2][1] != 0 ||
724 t->matrix[2][2] != IntToxFixed(1))
725 return FALSE;
726
727 if (xFixedFrac(t->matrix[0][2]) != 0 ||
728 xFixedFrac(t->matrix[1][2]) != 0)
729 return FALSE;
730
731 *tx = xFixedToInt(t->matrix[0][2]);
732 *ty = xFixedToInt(t->matrix[1][2]);
733 return TRUE;
734 }
735
736 static PicturePtr
uxa_render_picture(ScreenPtr screen,PicturePtr src,pixman_format_code_t format,INT16 x,INT16 y,CARD16 width,CARD16 height)737 uxa_render_picture(ScreenPtr screen,
738 PicturePtr src,
739 pixman_format_code_t format,
740 INT16 x, INT16 y,
741 CARD16 width, CARD16 height)
742 {
743 PicturePtr picture;
744 int ret = 0;
745
746 /* XXX we need a mechanism for the card to choose the fallback format */
747
748 /* force alpha channel in case source does not entirely cover the extents */
749 if (PIXMAN_FORMAT_A(format) == 0)
750 format = PIXMAN_a8r8g8b8; /* available on all hardware */
751
752 picture = uxa_picture_for_pixman_format(screen, format, width, height);
753 if (!picture)
754 return 0;
755
756 if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) {
757 if (uxa_picture_prepare_access(src, UXA_ACCESS_RO)) {
758 ret = 1;
759 fbComposite(PictOpSrc, src, NULL, picture,
760 x, y, 0, 0, 0, 0, width, height);
761 uxa_picture_finish_access(src, UXA_ACCESS_RO);
762 }
763 uxa_picture_finish_access(picture, UXA_ACCESS_RW);
764 }
765
766 if (!ret) {
767 FreePicture(picture, 0);
768 return 0;
769 }
770
771 return picture;
772 }
773
774 static int
drawable_contains(DrawablePtr drawable,int x,int y,int w,int h)775 drawable_contains (DrawablePtr drawable, int x, int y, int w, int h)
776 {
777 if (x < 0 || y < 0)
778 return FALSE;
779
780 if (x + w > drawable->width)
781 return FALSE;
782
783 if (y + h > drawable->height)
784 return FALSE;
785
786 return TRUE;
787 }
788
789 PicturePtr
uxa_acquire_drawable(ScreenPtr pScreen,PicturePtr pSrc,INT16 x,INT16 y,CARD16 width,CARD16 height,INT16 * out_x,INT16 * out_y)790 uxa_acquire_drawable(ScreenPtr pScreen,
791 PicturePtr pSrc,
792 INT16 x, INT16 y,
793 CARD16 width, CARD16 height,
794 INT16 * out_x, INT16 * out_y)
795 {
796 PixmapPtr pPixmap;
797 PicturePtr pDst;
798 int depth, error;
799 int tx, ty;
800 GCPtr pGC;
801
802 depth = pSrc->pDrawable->depth;
803 if (!transform_is_integer_translation(pSrc->transform, &tx, &ty) ||
804 !drawable_contains(pSrc->pDrawable, x + tx, y + ty, width, height) ||
805 depth == 1 ||
806 pSrc->filter == PictFilterConvolution) {
807 /* XXX extract the sample extents and do the transformation on the GPU */
808 pDst = uxa_render_picture(pScreen, pSrc,
809 pSrc->format | (BitsPerPixel(pSrc->pDrawable->depth) << 24),
810 x, y, width, height);
811 if (!pDst)
812 return 0;
813
814 goto done;
815 } else {
816 if (width == pSrc->pDrawable->width && height == pSrc->pDrawable->height) {
817 *out_x = x + pSrc->pDrawable->x;
818 *out_y = y + pSrc->pDrawable->y;
819 return pSrc;
820 }
821 }
822
823 pPixmap = pScreen->CreatePixmap(pScreen,
824 width, height, depth,
825 CREATE_PIXMAP_USAGE_SCRATCH);
826 if (!pPixmap)
827 return 0;
828
829 /* Skip the copy if the result remains in memory and not a bo */
830 if (!uxa_pixmap_is_offscreen(pPixmap)) {
831 pScreen->DestroyPixmap(pPixmap);
832 return 0;
833 }
834
835 pGC = GetScratchGC(depth, pScreen);
836 if (!pGC) {
837 pScreen->DestroyPixmap(pPixmap);
838 return 0;
839 }
840
841 ValidateGC(&pPixmap->drawable, pGC);
842 pGC->ops->CopyArea(pSrc->pDrawable, &pPixmap->drawable, pGC,
843 x + tx, y + ty, width, height, 0, 0);
844 FreeScratchGC(pGC);
845
846 pDst = CreatePicture(0, &pPixmap->drawable,
847 PictureMatchFormat(pScreen, depth, pSrc->format),
848 0, 0, serverClient, &error);
849 pScreen->DestroyPixmap(pPixmap);
850 if (!pDst)
851 return 0;
852
853 ValidatePicture(pDst);
854 done:
855 pDst->componentAlpha = pSrc->componentAlpha;
856 *out_x = 0;
857 *out_y = 0;
858 return pDst;
859 }
860
861 static PicturePtr
uxa_acquire_picture(ScreenPtr screen,PicturePtr src,pixman_format_code_t format,INT16 x,INT16 y,CARD16 width,CARD16 height,INT16 * out_x,INT16 * out_y)862 uxa_acquire_picture(ScreenPtr screen,
863 PicturePtr src,
864 pixman_format_code_t format,
865 INT16 x, INT16 y,
866 CARD16 width, CARD16 height,
867 INT16 * out_x, INT16 * out_y)
868 {
869 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
870
871 if (uxa_screen->info->check_composite_texture &&
872 uxa_screen->info->check_composite_texture(screen, src)) {
873 if (src->pDrawable) {
874 *out_x = x + src->pDrawable->x;
875 *out_y = y + src->pDrawable->y;
876 } else {
877 *out_x = x;
878 *out_y = y;
879 }
880 return src;
881 }
882
883 if (src->pDrawable) {
884 PicturePtr dst;
885
886 dst = uxa_acquire_drawable(screen, src,
887 x, y, width, height,
888 out_x, out_y);
889 if (!dst)
890 return 0;
891
892 if (uxa_screen->info->check_composite_texture &&
893 !uxa_screen->info->check_composite_texture(screen, dst)) {
894 if (dst != src)
895 FreePicture(dst, 0);
896 return 0;
897 }
898
899 return dst;
900 }
901
902 *out_x = 0;
903 *out_y = 0;
904 return uxa_acquire_pattern(screen, src,
905 format, x, y, width, height);
906 }
907
908 static PicturePtr
uxa_acquire_source(ScreenPtr screen,PicturePtr pict,INT16 x,INT16 y,CARD16 width,CARD16 height,INT16 * out_x,INT16 * out_y)909 uxa_acquire_source(ScreenPtr screen,
910 PicturePtr pict,
911 INT16 x, INT16 y,
912 CARD16 width, CARD16 height,
913 INT16 * out_x, INT16 * out_y)
914 {
915 return uxa_acquire_picture (screen, pict,
916 PIXMAN_a8r8g8b8,
917 x, y,
918 width, height,
919 out_x, out_y);
920 }
921
922 static PicturePtr
uxa_acquire_mask(ScreenPtr screen,PicturePtr pict,INT16 x,INT16 y,INT16 width,INT16 height,INT16 * out_x,INT16 * out_y)923 uxa_acquire_mask(ScreenPtr screen,
924 PicturePtr pict,
925 INT16 x, INT16 y,
926 INT16 width, INT16 height,
927 INT16 * out_x, INT16 * out_y)
928 {
929 return uxa_acquire_picture (screen, pict,
930 PIXMAN_a8,
931 x, y,
932 width, height,
933 out_x, out_y);
934 }
935
936 static int
uxa_try_driver_composite(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)937 uxa_try_driver_composite(CARD8 op,
938 PicturePtr pSrc,
939 PicturePtr pMask,
940 PicturePtr pDst,
941 INT16 xSrc, INT16 ySrc,
942 INT16 xMask, INT16 yMask,
943 INT16 xDst, INT16 yDst,
944 CARD16 width, CARD16 height)
945 {
946 ScreenPtr screen = pDst->pDrawable->pScreen;
947 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
948 RegionRec region;
949 BoxPtr pbox;
950 int nbox;
951 int xDst_copy = 0, yDst_copy = 0;
952 int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
953 PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
954 PicturePtr localSrc, localMask = NULL;
955 PicturePtr localDst = pDst;
956
957 if (uxa_screen->info->check_composite &&
958 !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst, width, height))
959 return -1;
960
961 if (uxa_screen->info->check_composite_target &&
962 !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
963 int depth = pDst->pDrawable->depth;
964 PixmapPtr pixmap;
965 int error;
966 GCPtr gc;
967
968 pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
969 if (uxa_screen->info->check_copy &&
970 !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
971 return -1;
972
973 pixmap = screen->CreatePixmap(screen,
974 width, height, depth,
975 CREATE_PIXMAP_USAGE_SCRATCH);
976 if (!pixmap)
977 return 0;
978
979 gc = GetScratchGC(depth, screen);
980 if (!gc) {
981 screen->DestroyPixmap(pixmap);
982 return 0;
983 }
984
985 ValidateGC(&pixmap->drawable, gc);
986 gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
987 xDst, yDst, width, height, 0, 0);
988 FreeScratchGC(gc);
989
990 xDst_copy = xDst; xDst = 0;
991 yDst_copy = yDst; yDst = 0;
992
993 localDst = CreatePicture(0, &pixmap->drawable,
994 PictureMatchFormat(screen, depth, pDst->format),
995 0, 0, serverClient, &error);
996 screen->DestroyPixmap(pixmap);
997
998 if (!localDst)
999 return 0;
1000
1001 ValidatePicture(localDst);
1002 }
1003
1004 pDstPix =
1005 uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y);
1006 if (!pDstPix) {
1007 if (localDst != pDst)
1008 FreePicture(localDst, 0);
1009 return -1;
1010 }
1011
1012 xDst += localDst->pDrawable->x;
1013 yDst += localDst->pDrawable->y;
1014
1015 localSrc = uxa_acquire_source(screen, pSrc,
1016 xSrc, ySrc,
1017 width, height,
1018 &xSrc, &ySrc);
1019 if (!localSrc) {
1020 if (localDst != pDst)
1021 FreePicture(localDst, 0);
1022 return 0;
1023 }
1024
1025 if (pMask) {
1026 localMask = uxa_acquire_mask(screen, pMask,
1027 xMask, yMask,
1028 width, height,
1029 &xMask, &yMask);
1030 if (!localMask) {
1031 if (localSrc != pSrc)
1032 FreePicture(localSrc, 0);
1033 if (localDst != pDst)
1034 FreePicture(localDst, 0);
1035
1036 return 0;
1037 }
1038 }
1039
1040 if (!miComputeCompositeRegion(®ion, localSrc, localMask, localDst,
1041 xSrc, ySrc, xMask, yMask, xDst, yDst,
1042 width, height)) {
1043 if (localSrc != pSrc)
1044 FreePicture(localSrc, 0);
1045 if (localMask && localMask != pMask)
1046 FreePicture(localMask, 0);
1047 if (localDst != pDst)
1048 FreePicture(localDst, 0);
1049
1050 return 1;
1051 }
1052
1053 pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable,
1054 &src_off_x, &src_off_y);
1055 if (!pSrcPix) {
1056 REGION_UNINIT(screen, ®ion);
1057
1058 if (localSrc != pSrc)
1059 FreePicture(localSrc, 0);
1060 if (localMask && localMask != pMask)
1061 FreePicture(localMask, 0);
1062 if (localDst != pDst)
1063 FreePicture(localDst, 0);
1064
1065 return 0;
1066 }
1067
1068 if (localMask) {
1069 pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable,
1070 &mask_off_x, &mask_off_y);
1071 if (!pMaskPix) {
1072 REGION_UNINIT(screen, ®ion);
1073
1074 if (localSrc != pSrc)
1075 FreePicture(localSrc, 0);
1076 if (localMask && localMask != pMask)
1077 FreePicture(localMask, 0);
1078 if (localDst != pDst)
1079 FreePicture(localDst, 0);
1080
1081 return 0;
1082 }
1083 }
1084
1085 if (!(*uxa_screen->info->prepare_composite)
1086 (op, localSrc, localMask, localDst, pSrcPix, pMaskPix, pDstPix)) {
1087 REGION_UNINIT(screen, ®ion);
1088
1089 if (localSrc != pSrc)
1090 FreePicture(localSrc, 0);
1091 if (localMask && localMask != pMask)
1092 FreePicture(localMask, 0);
1093 if (localDst != pDst)
1094 FreePicture(localDst, 0);
1095
1096 return -1;
1097 }
1098
1099 if (pMask) {
1100 xMask = xMask + mask_off_x - xDst;
1101 yMask = yMask + mask_off_y - yDst;
1102 }
1103
1104 xSrc = xSrc + src_off_x - xDst;
1105 ySrc = ySrc + src_off_y - yDst;
1106
1107 nbox = REGION_NUM_RECTS(®ion);
1108 pbox = REGION_RECTS(®ion);
1109 while (nbox--) {
1110 (*uxa_screen->info->composite) (pDstPix,
1111 pbox->x1 + xSrc,
1112 pbox->y1 + ySrc,
1113 pbox->x1 + xMask,
1114 pbox->y1 + yMask,
1115 pbox->x1 + dst_off_x,
1116 pbox->y1 + dst_off_y,
1117 pbox->x2 - pbox->x1,
1118 pbox->y2 - pbox->y1);
1119 pbox++;
1120 }
1121 (*uxa_screen->info->done_composite) (pDstPix);
1122
1123 REGION_UNINIT(screen, ®ion);
1124
1125 if (localSrc != pSrc)
1126 FreePicture(localSrc, 0);
1127 if (localMask && localMask != pMask)
1128 FreePicture(localMask, 0);
1129
1130 if (localDst != pDst) {
1131 GCPtr gc;
1132
1133 gc = GetScratchGC(pDst->pDrawable->depth, screen);
1134 if (gc) {
1135 ValidateGC(pDst->pDrawable, gc);
1136 gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
1137 0, 0, width, height, xDst_copy, yDst_copy);
1138 FreeScratchGC(gc);
1139 }
1140
1141 FreePicture(localDst, 0);
1142 }
1143
1144 return 1;
1145 }
1146
1147 /**
1148 * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of
1149 * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
1150 * alpha and limited 1-tmu cards.
1151 *
1152 * From http://anholt.livejournal.com/32058.html:
1153 *
1154 * The trouble is that component-alpha rendering requires two different sources
1155 * for blending: one for the source value to the blender, which is the
1156 * per-channel multiplication of source and mask, and one for the source alpha
1157 * for multiplying with the destination channels, which is the multiplication
1158 * of the source channels by the mask alpha. So the equation for Over is:
1159 *
1160 * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
1161 * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
1162 * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
1163 * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
1164 *
1165 * But we can do some simpler operations, right? How about PictOpOutReverse,
1166 * which has a source factor of 0 and dest factor of (1 - source alpha). We
1167 * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
1168 * blenders pretty easily. So we can do a component-alpha OutReverse, which
1169 * gets us:
1170 *
1171 * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
1172 * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
1173 * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
1174 * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
1175 *
1176 * OK. And if an op doesn't use the source alpha value for the destination
1177 * factor, then we can do the channel multiplication in the texture blenders
1178 * to get the source value, and ignore the source alpha that we wouldn't use.
1179 * We've supported this in the Radeon driver for a long time. An example would
1180 * be PictOpAdd, which does:
1181 *
1182 * dst.A = src.A * mask.A + dst.A
1183 * dst.R = src.R * mask.R + dst.R
1184 * dst.G = src.G * mask.G + dst.G
1185 * dst.B = src.B * mask.B + dst.B
1186 *
1187 * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
1188 * after it, we get:
1189 *
1190 * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
1191 * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
1192 * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
1193 * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
1194 */
1195
1196 static int
uxa_try_magic_two_pass_composite_helper(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)1197 uxa_try_magic_two_pass_composite_helper(CARD8 op,
1198 PicturePtr pSrc,
1199 PicturePtr pMask,
1200 PicturePtr pDst,
1201 INT16 xSrc, INT16 ySrc,
1202 INT16 xMask, INT16 yMask,
1203 INT16 xDst, INT16 yDst,
1204 CARD16 width, CARD16 height)
1205 {
1206 ScreenPtr screen = pDst->pDrawable->pScreen;
1207 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
1208 PicturePtr localDst = pDst;
1209 int xDst_copy, yDst_copy;
1210
1211 assert(op == PictOpOver);
1212
1213 if (uxa_screen->info->check_composite &&
1214 (!(*uxa_screen->info->check_composite) (PictOpOutReverse, pSrc,
1215 pMask, pDst, width, height)
1216 || !(*uxa_screen->info->check_composite) (PictOpAdd, pSrc, pMask,
1217 pDst, width, height))) {
1218 return -1;
1219 }
1220
1221 if (uxa_screen->info->check_composite_target &&
1222 !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
1223 int depth = pDst->pDrawable->depth;
1224 PixmapPtr pixmap;
1225 int error;
1226 GCPtr gc;
1227
1228 pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
1229 if (uxa_screen->info->check_copy &&
1230 !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
1231 return -1;
1232
1233 pixmap = screen->CreatePixmap(screen,
1234 width, height, depth,
1235 CREATE_PIXMAP_USAGE_SCRATCH);
1236 if (!pixmap)
1237 return 0;
1238
1239 gc = GetScratchGC(depth, screen);
1240 if (!gc) {
1241 screen->DestroyPixmap(pixmap);
1242 return 0;
1243 }
1244
1245 ValidateGC(&pixmap->drawable, gc);
1246 gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
1247 xDst, yDst, width, height, 0, 0);
1248 FreeScratchGC(gc);
1249
1250 xDst_copy = xDst; xDst = 0;
1251 yDst_copy = yDst; yDst = 0;
1252
1253 localDst = CreatePicture(0, &pixmap->drawable,
1254 PictureMatchFormat(screen, depth, pDst->format),
1255 0, 0, serverClient, &error);
1256 screen->DestroyPixmap(pixmap);
1257
1258 if (!localDst)
1259 return 0;
1260
1261 ValidatePicture(localDst);
1262 }
1263
1264 /* Now, we think we should be able to accelerate this operation. First,
1265 * composite the destination to be the destination times the source alpha
1266 * factors.
1267 */
1268 uxa_composite(PictOpOutReverse, pSrc, pMask, localDst,
1269 xSrc, ySrc,
1270 xMask, yMask,
1271 xDst, yDst,
1272 width, height);
1273
1274 /* Then, add in the source value times the destination alpha factors (1.0).
1275 */
1276 uxa_composite(PictOpAdd, pSrc, pMask, localDst,
1277 xSrc, ySrc,
1278 xMask, yMask,
1279 xDst, yDst,
1280 width, height);
1281
1282 if (localDst != pDst) {
1283 GCPtr gc;
1284
1285 gc = GetScratchGC(pDst->pDrawable->depth, screen);
1286 if (gc) {
1287 ValidateGC(pDst->pDrawable, gc);
1288 gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
1289 0, 0, width, height, xDst_copy, yDst_copy);
1290 FreeScratchGC(gc);
1291 }
1292
1293 FreePicture(localDst, 0);
1294 }
1295
1296 return 1;
1297 }
1298
1299 static int
compatible_formats(CARD8 op,PicturePtr dst,PicturePtr src)1300 compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src)
1301 {
1302 if (op == PictOpSrc) {
1303 if (src->format == dst->format)
1304 return 1;
1305
1306 /* Is the destination an alpha-less version of source? */
1307 if (dst->format == PICT_FORMAT(PICT_FORMAT_BPP(src->format),
1308 PICT_FORMAT_TYPE(src->format),
1309 0,
1310 PICT_FORMAT_R(src->format),
1311 PICT_FORMAT_G(src->format),
1312 PICT_FORMAT_B(src->format)))
1313 return 1;
1314
1315 /* XXX xrgb is promoted to argb during image upload... */
1316 #if 0
1317 if (dst->format == PICT_a8r8g8b8 && src->format == PICT_x8r8g8b8)
1318 return 1;
1319 #endif
1320 } else if (op == PictOpOver) {
1321 if (PICT_FORMAT_A(src->format))
1322 return 0;
1323
1324 return src->format == dst->format;
1325 }
1326
1327 return 0;
1328 }
1329
1330 void
uxa_composite(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)1331 uxa_composite(CARD8 op,
1332 PicturePtr pSrc,
1333 PicturePtr pMask,
1334 PicturePtr pDst,
1335 INT16 xSrc, INT16 ySrc,
1336 INT16 xMask, INT16 yMask,
1337 INT16 xDst, INT16 yDst,
1338 CARD16 width, CARD16 height)
1339 {
1340 uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
1341 int ret = -1;
1342 Bool saveSrcRepeat = pSrc->repeat;
1343 Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
1344 RegionRec region;
1345 int tx, ty;
1346
1347 if (uxa_screen->force_fallback)
1348 goto fallback;
1349
1350 if (!uxa_drawable_is_offscreen(pDst->pDrawable))
1351 goto fallback;
1352
1353 if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
1354 goto fallback;
1355
1356 /* Remove repeat in source if useless */
1357 if (pSrc->pDrawable && pSrc->repeat && pSrc->filter != PictFilterConvolution &&
1358 transform_is_integer_translation(pSrc->transform, &tx, &ty) &&
1359 (pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) &&
1360 drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height))
1361 pSrc->repeat = 0;
1362
1363 if (!pMask) {
1364 if (op == PictOpClear) {
1365 PicturePtr clear = uxa_solid_clear(pDst->pDrawable->pScreen);
1366 if (clear &&
1367 uxa_try_driver_solid_fill(clear, pDst,
1368 xSrc, ySrc,
1369 xDst, yDst,
1370 width, height) == 1)
1371 goto done;
1372 }
1373
1374 if (pSrc->pDrawable == NULL) {
1375 if (pSrc->pSourcePict) {
1376 SourcePict *source = pSrc->pSourcePict;
1377 if (source->type == SourcePictTypeSolidFill) {
1378 if (op == PictOpSrc ||
1379 (op == PictOpOver &&
1380 (source->solidFill.color & 0xff000000) == 0xff000000)) {
1381 ret = uxa_try_driver_solid_fill(pSrc, pDst,
1382 xSrc, ySrc,
1383 xDst, yDst,
1384 width, height);
1385 if (ret == 1)
1386 goto done;
1387 }
1388 }
1389 }
1390 } else if (pSrc->pDrawable->width == 1 &&
1391 pSrc->pDrawable->height == 1 &&
1392 pSrc->repeat &&
1393 (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) {
1394 ret = uxa_try_driver_solid_fill(pSrc, pDst,
1395 xSrc, ySrc,
1396 xDst, yDst,
1397 width, height);
1398 if (ret == 1)
1399 goto done;
1400 } else if (compatible_formats (op, pDst, pSrc) &&
1401 pSrc->filter != PictFilterConvolution &&
1402 transform_is_integer_translation(pSrc->transform, &tx, &ty)) {
1403 if (!pSrc->repeat &&
1404 drawable_contains(pSrc->pDrawable,
1405 xSrc + tx, ySrc + ty,
1406 width, height)) {
1407 xDst += pDst->pDrawable->x;
1408 yDst += pDst->pDrawable->y;
1409 xSrc += pSrc->pDrawable->x + tx;
1410 ySrc += pSrc->pDrawable->y + ty;
1411
1412 if (!miComputeCompositeRegion
1413 (®ion, pSrc, pMask, pDst, xSrc, ySrc,
1414 xMask, yMask, xDst, yDst, width, height))
1415 goto done;
1416
1417 uxa_copy_n_to_n(pSrc->pDrawable,
1418 pDst->pDrawable, NULL,
1419 REGION_RECTS(®ion),
1420 REGION_NUM_RECTS(®ion),
1421 xSrc - xDst, ySrc - yDst, FALSE,
1422 FALSE, 0, NULL);
1423 REGION_UNINIT(pDst->pDrawable->pScreen,
1424 ®ion);
1425 goto done;
1426 } else if (pSrc->repeat && pSrc->repeatType == RepeatNormal &&
1427 pSrc->pDrawable->type == DRAWABLE_PIXMAP) {
1428 DDXPointRec patOrg;
1429
1430 /* Let's see if the driver can do the repeat
1431 * in one go
1432 */
1433 if (uxa_screen->info->prepare_composite) {
1434 ret = uxa_try_driver_composite(op, pSrc,
1435 pMask, pDst,
1436 xSrc, ySrc,
1437 xMask, yMask,
1438 xDst, yDst,
1439 width, height);
1440 if (ret == 1)
1441 goto done;
1442 }
1443
1444 /* Now see if we can use
1445 * uxa_fill_region_tiled()
1446 */
1447 xDst += pDst->pDrawable->x;
1448 yDst += pDst->pDrawable->y;
1449 xSrc += pSrc->pDrawable->x + tx;
1450 ySrc += pSrc->pDrawable->y + ty;
1451
1452 if (!miComputeCompositeRegion
1453 (®ion, pSrc, pMask, pDst, xSrc, ySrc,
1454 xMask, yMask, xDst, yDst, width, height))
1455 goto done;
1456
1457 /* pattern origin is the point in the
1458 * destination drawable
1459 * corresponding to (0,0) in the source */
1460 patOrg.x = xDst - xSrc;
1461 patOrg.y = yDst - ySrc;
1462
1463 ret = uxa_fill_region_tiled(pDst->pDrawable,
1464 ®ion,
1465 (PixmapPtr) pSrc->
1466 pDrawable, &patOrg,
1467 FB_ALLONES, GXcopy);
1468
1469 REGION_UNINIT(pDst->pDrawable->pScreen,
1470 ®ion);
1471
1472 if (ret)
1473 goto done;
1474 }
1475 }
1476 }
1477
1478 /* Remove repeat in mask if useless */
1479 if (pMask && pMask->pDrawable && pMask->repeat &&
1480 pMask->filter != PictFilterConvolution &&
1481 transform_is_integer_translation(pMask->transform, &tx, &ty) &&
1482 (pMask->pDrawable->width > 1 || pMask->pDrawable->height > 1) &&
1483 drawable_contains(pMask->pDrawable, xMask + tx, yMask + ty, width, height))
1484 pMask->repeat = 0;
1485
1486 if (uxa_screen->info->prepare_composite) {
1487 Bool isSrcSolid;
1488
1489 ret =
1490 uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc,
1491 xMask, yMask, xDst, yDst, width,
1492 height);
1493 if (ret == 1)
1494 goto done;
1495
1496 /* For generic masks and solid src pictures, mach64 can do
1497 * Over in two passes, similar to the component-alpha case.
1498 */
1499
1500 isSrcSolid =
1501 pSrc->pDrawable ?
1502 pSrc->pDrawable->width == 1 &&
1503 pSrc->pDrawable->height == 1 &&
1504 pSrc->repeat :
1505 pSrc->pSourcePict ?
1506 pSrc->pSourcePict->type == SourcePictTypeSolidFill :
1507 0;
1508
1509 /* If we couldn't do the Composite in a single pass, and it
1510 * was a component-alpha Over, see if we can do it in two
1511 * passes with an OutReverse and then an Add.
1512 */
1513 if (ret == -1 && op == PictOpOver && pMask &&
1514 (pMask->componentAlpha || isSrcSolid)) {
1515 ret =
1516 uxa_try_magic_two_pass_composite_helper(op, pSrc,
1517 pMask, pDst,
1518 xSrc, ySrc,
1519 xMask, yMask,
1520 xDst, yDst,
1521 width, height);
1522 if (ret == 1)
1523 goto done;
1524 }
1525
1526 }
1527
1528 fallback:
1529 uxa_print_composite_fallback("uxa_composite",
1530 op, pSrc, pMask, pDst);
1531
1532 uxa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc,
1533 xMask, yMask, xDst, yDst, width, height);
1534
1535 done:
1536 pSrc->repeat = saveSrcRepeat;
1537 if (pMask)
1538 pMask->repeat = saveMaskRepeat;
1539 }
1540 #endif
1541
1542 /**
1543 * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead
1544 * of PolyFillRect to initialize the pixmap after creating it, to prevent
1545 * the pixmap from being migrated.
1546 *
1547 * See the comments about uxa_trapezoids and uxa_triangles.
1548 */
1549 static PicturePtr
uxa_create_alpha_picture(ScreenPtr pScreen,PicturePtr pDst,PictFormatPtr pPictFormat,CARD16 width,CARD16 height)1550 uxa_create_alpha_picture(ScreenPtr pScreen,
1551 PicturePtr pDst,
1552 PictFormatPtr pPictFormat, CARD16 width, CARD16 height)
1553 {
1554 PixmapPtr pPixmap;
1555 PicturePtr pPicture;
1556 int error;
1557
1558 if (width > 32767 || height > 32767)
1559 return 0;
1560
1561 if (!pPictFormat) {
1562 if (pDst->polyEdge == PolyEdgeSharp)
1563 pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
1564 else
1565 pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
1566 if (!pPictFormat)
1567 return 0;
1568 }
1569
1570 pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
1571 pPictFormat->depth,
1572 UXA_CREATE_PIXMAP_FOR_MAP);
1573 if (!pPixmap)
1574 return 0;
1575 pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
1576 0, 0, serverClient, &error);
1577 (*pScreen->DestroyPixmap) (pPixmap);
1578 return pPicture;
1579 }
1580
1581 static void
uxa_check_trapezoids(CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntrap,xTrapezoid * traps)1582 uxa_check_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
1583 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1584 int ntrap, xTrapezoid * traps)
1585 {
1586 ScreenPtr screen = dst->pDrawable->pScreen;
1587
1588 if (maskFormat) {
1589 PixmapPtr scratch = NULL;
1590 PicturePtr mask;
1591 INT16 xDst, yDst;
1592 INT16 xRel, yRel;
1593 BoxRec bounds;
1594 int width, height;
1595 pixman_image_t *image;
1596 pixman_format_code_t format;
1597 int error;
1598
1599 xDst = traps[0].left.p1.x >> 16;
1600 yDst = traps[0].left.p1.y >> 16;
1601
1602 miTrapezoidBounds (ntrap, traps, &bounds);
1603 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1604 return;
1605
1606 width = bounds.x2 - bounds.x1;
1607 height = bounds.y2 - bounds.y1;
1608
1609 format = maskFormat->format |
1610 (BitsPerPixel(maskFormat->depth) << 24);
1611 image =
1612 pixman_image_create_bits(format, width, height, NULL, 0);
1613 if (!image)
1614 return;
1615
1616 for (; ntrap; ntrap--, traps++)
1617 pixman_rasterize_trapezoid(image,
1618 (pixman_trapezoid_t *) traps,
1619 -bounds.x1, -bounds.y1);
1620
1621
1622 scratch = GetScratchPixmapHeader(screen, width, height,
1623 PIXMAN_FORMAT_DEPTH(format),
1624 PIXMAN_FORMAT_BPP(format),
1625 pixman_image_get_stride(image),
1626 pixman_image_get_data(image));
1627 if (!scratch) {
1628 pixman_image_unref(image);
1629 return;
1630 }
1631
1632 mask = CreatePicture(0, &scratch->drawable,
1633 PictureMatchFormat(screen,
1634 PIXMAN_FORMAT_DEPTH(format),
1635 format),
1636 0, 0, serverClient, &error);
1637 if (!mask) {
1638 FreeScratchPixmapHeader(scratch);
1639 pixman_image_unref(image);
1640 return;
1641 }
1642
1643 xRel = bounds.x1 + xSrc - xDst;
1644 yRel = bounds.y1 + ySrc - yDst;
1645 CompositePicture(op, src, mask, dst,
1646 xRel, yRel,
1647 0, 0,
1648 bounds.x1, bounds.y1,
1649 width, height);
1650 FreePicture(mask, 0);
1651
1652 FreeScratchPixmapHeader(scratch);
1653 pixman_image_unref(image);
1654 } else {
1655 if (dst->polyEdge == PolyEdgeSharp)
1656 maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
1657 else
1658 maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
1659
1660 for (; ntrap; ntrap--, traps++)
1661 uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, 1, traps);
1662 }
1663 }
1664
1665 /**
1666 * uxa_trapezoids is essentially a copy of miTrapezoids that uses
1667 * uxa_create_alpha_picture instead of miCreateAlphaPicture.
1668 *
1669 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
1670 * to initialize the contents after creating the pixmap, which
1671 * causes the pixmap to be moved in for acceleration. The subsequent
1672 * call to RasterizeTrapezoid won't be accelerated however, which
1673 * forces the pixmap to be moved out again.
1674 *
1675 * uxa_create_alpha_picture avoids this roundtrip by using
1676 * uxa_check_poly_fill_rect to initialize the contents.
1677 */
1678 void
uxa_trapezoids(CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntrap,xTrapezoid * traps)1679 uxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
1680 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1681 int ntrap, xTrapezoid * traps)
1682 {
1683 ScreenPtr screen = dst->pDrawable->pScreen;
1684 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
1685 BoxRec bounds;
1686 Bool direct;
1687
1688 if (uxa_screen->force_fallback) {
1689 uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, ntrap, traps);
1690 return;
1691 }
1692
1693 direct = op == PictOpAdd && miIsSolidAlpha(src);
1694 if (maskFormat || direct) {
1695 miTrapezoidBounds(ntrap, traps, &bounds);
1696
1697 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1698 return;
1699 }
1700
1701 /*
1702 * Check for solid alpha add
1703 */
1704 if (direct) {
1705 DrawablePtr pDraw = dst->pDrawable;
1706 PixmapPtr pixmap = uxa_get_drawable_pixmap(pDraw);
1707 int xoff, yoff;
1708
1709 uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff);
1710
1711 xoff += pDraw->x;
1712 yoff += pDraw->y;
1713
1714 if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
1715 PictureScreenPtr ps = GetPictureScreen(screen);
1716
1717 for (; ntrap; ntrap--, traps++)
1718 (*ps->RasterizeTrapezoid) (dst, traps, 0, 0);
1719 uxa_finish_access(pDraw, UXA_ACCESS_RW);
1720 }
1721 } else if (maskFormat) {
1722 PixmapPtr scratch = NULL;
1723 PicturePtr mask;
1724 INT16 xDst, yDst;
1725 INT16 xRel, yRel;
1726 int width, height;
1727 pixman_image_t *image;
1728 pixman_format_code_t format;
1729
1730 xDst = traps[0].left.p1.x >> 16;
1731 yDst = traps[0].left.p1.y >> 16;
1732
1733 width = bounds.x2 - bounds.x1;
1734 height = bounds.y2 - bounds.y1;
1735
1736 format = maskFormat->format |
1737 (BitsPerPixel(maskFormat->depth) << 24);
1738 image =
1739 pixman_image_create_bits(format, width, height, NULL, 0);
1740 if (!image)
1741 return;
1742
1743 for (; ntrap; ntrap--, traps++)
1744 pixman_rasterize_trapezoid(image,
1745 (pixman_trapezoid_t *) traps,
1746 -bounds.x1, -bounds.y1);
1747 if (uxa_drawable_is_offscreen(dst->pDrawable)) {
1748 mask = uxa_picture_from_pixman_image(screen, image, format);
1749 } else {
1750 int error;
1751
1752 scratch = GetScratchPixmapHeader(screen, width, height,
1753 PIXMAN_FORMAT_DEPTH(format),
1754 PIXMAN_FORMAT_BPP(format),
1755 pixman_image_get_stride(image),
1756 pixman_image_get_data(image));
1757 mask = CreatePicture(0, &scratch->drawable,
1758 PictureMatchFormat(screen,
1759 PIXMAN_FORMAT_DEPTH(format),
1760 format),
1761 0, 0, serverClient, &error);
1762 }
1763 if (!mask) {
1764 if (scratch)
1765 FreeScratchPixmapHeader(scratch);
1766 pixman_image_unref(image);
1767 return;
1768 }
1769
1770 xRel = bounds.x1 + xSrc - xDst;
1771 yRel = bounds.y1 + ySrc - yDst;
1772 CompositePicture(op, src, mask, dst,
1773 xRel, yRel,
1774 0, 0,
1775 bounds.x1, bounds.y1,
1776 width, height);
1777 FreePicture(mask, 0);
1778
1779 if (scratch)
1780 FreeScratchPixmapHeader(scratch);
1781 pixman_image_unref(image);
1782 } else {
1783 if (dst->polyEdge == PolyEdgeSharp)
1784 maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
1785 else
1786 maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
1787 for (; ntrap; ntrap--, traps++)
1788 uxa_trapezoids(op, src, dst, maskFormat, xSrc, ySrc,
1789 1, traps);
1790 }
1791 }
1792
1793 static void
uxa_check_triangles(CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntri,xTriangle * tri)1794 uxa_check_triangles(CARD8 op, PicturePtr src, PicturePtr dst,
1795 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1796 int ntri, xTriangle *tri)
1797 {
1798 ScreenPtr screen = dst->pDrawable->pScreen;
1799
1800 if (maskFormat) {
1801 PixmapPtr scratch = NULL;
1802 PicturePtr mask;
1803 INT16 xDst, yDst;
1804 INT16 xRel, yRel;
1805 BoxRec bounds;
1806 int width, height;
1807 pixman_image_t *image;
1808 pixman_format_code_t format;
1809 int error;
1810
1811 xDst = pixman_fixed_to_int(tri[0].p1.x);
1812 yDst = pixman_fixed_to_int(tri[0].p1.y);
1813
1814 miTriangleBounds (ntri, tri, &bounds);
1815 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1816 return;
1817
1818 width = bounds.x2 - bounds.x1;
1819 height = bounds.y2 - bounds.y1;
1820
1821 format = maskFormat->format |
1822 (BitsPerPixel(maskFormat->depth) << 24);
1823 image =
1824 pixman_image_create_bits(format, width, height, NULL, 0);
1825 if (!image)
1826 return;
1827
1828 pixman_add_triangles(image,
1829 -bounds.x1, -bounds.y1,
1830 ntri, (pixman_triangle_t *)tri);
1831
1832 scratch = GetScratchPixmapHeader(screen, width, height,
1833 PIXMAN_FORMAT_DEPTH(format),
1834 PIXMAN_FORMAT_BPP(format),
1835 pixman_image_get_stride(image),
1836 pixman_image_get_data(image));
1837 if (!scratch) {
1838 pixman_image_unref(image);
1839 return;
1840 }
1841
1842 mask = CreatePicture(0, &scratch->drawable,
1843 PictureMatchFormat(screen,
1844 PIXMAN_FORMAT_DEPTH(format),
1845 format),
1846 0, 0, serverClient, &error);
1847 if (!mask) {
1848 FreeScratchPixmapHeader(scratch);
1849 pixman_image_unref(image);
1850 return;
1851 }
1852
1853 xRel = bounds.x1 + xSrc - xDst;
1854 yRel = bounds.y1 + ySrc - yDst;
1855 CompositePicture(op, src, mask, dst,
1856 xRel, yRel,
1857 0, 0,
1858 bounds.x1, bounds.y1,
1859 width, height);
1860 FreePicture(mask, 0);
1861
1862 FreeScratchPixmapHeader(scratch);
1863 pixman_image_unref(image);
1864 } else {
1865 if (dst->polyEdge == PolyEdgeSharp)
1866 maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
1867 else
1868 maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
1869
1870 for (; ntri; ntri--, tri++)
1871 uxa_check_triangles(op, src, dst, maskFormat, xSrc, ySrc, 1, tri);
1872 }
1873 }
1874
1875 /**
1876 * uxa_triangles is essentially a copy of miTriangles that uses
1877 * uxa_create_alpha_picture instead of miCreateAlphaPicture.
1878 *
1879 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
1880 * to initialize the contents after creating the pixmap, which
1881 * causes the pixmap to be moved in for acceleration. The subsequent
1882 * call to AddTriangles won't be accelerated however, which forces the pixmap
1883 * to be moved out again.
1884 *
1885 * uxa_create_alpha_picture avoids this roundtrip by using
1886 * uxa_check_poly_fill_rect to initialize the contents.
1887 */
1888 void
uxa_triangles(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntri,xTriangle * tris)1889 uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1890 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1891 int ntri, xTriangle * tris)
1892 {
1893 ScreenPtr pScreen = pDst->pDrawable->pScreen;
1894 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
1895 PictureScreenPtr ps = GetPictureScreen(pScreen);
1896 BoxRec bounds;
1897 Bool direct;
1898
1899 if (uxa_screen->force_fallback) {
1900 uxa_check_triangles(op, pSrc, pDst, maskFormat,
1901 xSrc, ySrc, ntri, tris);
1902 return;
1903 }
1904
1905 direct = op == PictOpAdd && miIsSolidAlpha(pSrc);
1906 if (maskFormat || direct) {
1907 miTriangleBounds(ntri, tris, &bounds);
1908
1909 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1910 return;
1911 }
1912
1913 /*
1914 * Check for solid alpha add
1915 */
1916 if (direct) {
1917 DrawablePtr pDraw = pDst->pDrawable;
1918 if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
1919 (*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
1920 uxa_finish_access(pDraw, UXA_ACCESS_RW);
1921 }
1922 } else if (maskFormat) {
1923 PicturePtr pPicture;
1924 INT16 xDst, yDst;
1925 INT16 xRel, yRel;
1926 int width = bounds.x2 - bounds.x1;
1927 int height = bounds.y2 - bounds.y1;
1928 GCPtr pGC;
1929 xRectangle rect;
1930
1931 xDst = tris[0].p1.x >> 16;
1932 yDst = tris[0].p1.y >> 16;
1933
1934 pPicture = uxa_create_alpha_picture(pScreen, pDst, maskFormat,
1935 width, height);
1936 if (!pPicture)
1937 return;
1938
1939 /* Clear the alpha picture to 0. */
1940 pGC = GetScratchGC(pPicture->pDrawable->depth, pScreen);
1941 if (!pGC) {
1942 FreePicture(pPicture, 0);
1943 return;
1944 }
1945 ValidateGC(pPicture->pDrawable, pGC);
1946 rect.x = 0;
1947 rect.y = 0;
1948 rect.width = width;
1949 rect.height = height;
1950 uxa_check_poly_fill_rect(pPicture->pDrawable, pGC, 1, &rect);
1951 FreeScratchGC(pGC);
1952
1953 if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) {
1954 (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1,
1955 ntri, tris);
1956 uxa_finish_access(pPicture->pDrawable, UXA_ACCESS_RW);
1957 }
1958
1959 xRel = bounds.x1 + xSrc - xDst;
1960 yRel = bounds.y1 + ySrc - yDst;
1961 CompositePicture(op, pSrc, pPicture, pDst,
1962 xRel, yRel, 0, 0, bounds.x1, bounds.y1,
1963 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
1964 FreePicture(pPicture, 0);
1965 } else {
1966 if (pDst->polyEdge == PolyEdgeSharp)
1967 maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
1968 else
1969 maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
1970
1971 for (; ntri; ntri--, tris++)
1972 uxa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1,
1973 tris);
1974 }
1975 }
1976
1977 void
uxa_add_traps(PicturePtr pPicture,INT16 x_off,INT16 y_off,int ntrap,xTrap * traps)1978 uxa_add_traps(PicturePtr pPicture,
1979 INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
1980 {
1981 uxa_check_add_traps(pPicture, x_off, y_off, ntrap, traps);
1982 }
1983