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