uxa-render.c revision fa225cbc
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
37static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string, 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    {
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 ?
82	     " R" : "");
83
84    snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, size);
85}
86
87static void
88uxa_print_composite_fallback(CARD8 op,
89			  PicturePtr pSrc,
90			  PicturePtr pMask,
91			  PicturePtr pDst)
92{
93    char sop[20];
94    char srcdesc[40], maskdesc[40], dstdesc[40];
95
96    switch(op)
97    {
98    case PictOpSrc:
99	sprintf(sop, "Src");
100	break;
101    case PictOpOver:
102	sprintf(sop, "Over");
103	break;
104    default:
105	sprintf(sop, "0x%x", (int)op);
106	break;
107    }
108
109    uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40);
110    uxa_composite_fallback_pict_desc(pMask, maskdesc, 40);
111    uxa_composite_fallback_pict_desc(pDst, dstdesc, 40);
112
113    ErrorF("Composite fallback: op %s, \n"
114	   "                    src  %s, \n"
115	   "                    mask %s, \n"
116	   "                    dst  %s, \n",
117	   sop, srcdesc, maskdesc, dstdesc);
118}
119
120Bool
121uxa_op_reads_destination (CARD8 op)
122{
123    /* FALSE (does not read destination) is the list of ops in the protocol
124     * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
125     * That's just Clear and Src.  ReduceCompositeOp() will already have
126     * converted con/disjoint clear/src to Clear or Src.
127     */
128    switch (op) {
129    case PictOpClear:
130    case PictOpSrc:
131	return FALSE;
132    default:
133	return TRUE;
134    }
135}
136
137
138static Bool
139uxa_get_pixel_from_rgba(CARD32	*pixel,
140		    CARD16	red,
141		    CARD16	green,
142		    CARD16	blue,
143		    CARD16	alpha,
144		    CARD32	format)
145{
146    int rbits, bbits, gbits, abits;
147    int rshift, bshift, gshift, ashift;
148
149    *pixel = 0;
150
151    if (!PICT_FORMAT_COLOR(format))
152	return FALSE;
153
154    rbits = PICT_FORMAT_R(format);
155    gbits = PICT_FORMAT_G(format);
156    bbits = PICT_FORMAT_B(format);
157    abits = PICT_FORMAT_A(format);
158
159    if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
160	bshift = 0;
161	gshift = bbits;
162	rshift = gshift + gbits;
163	ashift = rshift + rbits;
164    } else {  /* PICT_TYPE_ABGR */
165	rshift = 0;
166	gshift = rbits;
167	bshift = gshift + gbits;
168	ashift = bshift + bbits;
169    }
170
171    *pixel |=  ( blue >> (16 - bbits)) << bshift;
172    *pixel |=  (  red >> (16 - rbits)) << rshift;
173    *pixel |=  (green >> (16 - gbits)) << gshift;
174    *pixel |=  (alpha >> (16 - abits)) << ashift;
175
176    return TRUE;
177}
178
179static Bool
180uxa_get_rgba_from_pixel(CARD32	pixel,
181		    CARD16	*red,
182		    CARD16	*green,
183		    CARD16	*blue,
184		    CARD16	*alpha,
185		    CARD32	format)
186{
187    int rbits, bbits, gbits, abits;
188    int rshift, bshift, gshift, ashift;
189
190    if (!PICT_FORMAT_COLOR(format))
191	return FALSE;
192
193    rbits = PICT_FORMAT_R(format);
194    gbits = PICT_FORMAT_G(format);
195    bbits = PICT_FORMAT_B(format);
196    abits = PICT_FORMAT_A(format);
197
198    if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
199	bshift = 0;
200	gshift = bbits;
201	rshift = gshift + gbits;
202	ashift = rshift + rbits;
203    } else {  /* PICT_TYPE_ABGR */
204	rshift = 0;
205	gshift = rbits;
206	bshift = gshift + gbits;
207	ashift = bshift + bbits;
208    }
209
210    *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
211    while (rbits < 16) {
212	*red |= *red >> rbits;
213	rbits <<= 1;
214    }
215
216    *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
217    while (gbits < 16) {
218	*green |= *green >> gbits;
219	gbits <<= 1;
220    }
221
222    *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
223    while (bbits < 16) {
224	*blue |= *blue >> bbits;
225	bbits <<= 1;
226    }
227
228    if (abits) {
229	*alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits);
230	while (abits < 16) {
231	    *alpha |= *alpha >> abits;
232	    abits <<= 1;
233	}
234    } else
235	*alpha = 0xffff;
236
237    return TRUE;
238}
239
240static int
241uxa_try_driver_solid_fill(PicturePtr	pSrc,
242		      PicturePtr	pDst,
243		      INT16		xSrc,
244		      INT16		ySrc,
245		      INT16		xDst,
246		      INT16		yDst,
247		      CARD16		width,
248		      CARD16		height)
249{
250    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
251    RegionRec region;
252    BoxPtr pbox;
253    int nbox;
254    int dst_off_x, dst_off_y;
255    PixmapPtr pSrcPix, pDstPix;
256    CARD32 pixel;
257    CARD16 red, green, blue, alpha;
258
259    pDstPix = uxa_get_drawable_pixmap (pDst->pDrawable);
260    pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
261
262    xDst += pDst->pDrawable->x;
263    yDst += pDst->pDrawable->y;
264    xSrc += pSrc->pDrawable->x;
265    ySrc += pSrc->pDrawable->y;
266
267    if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
268				   xSrc, ySrc, 0, 0, xDst, yDst,
269				   width, height))
270	return 1;
271
272    uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
273
274    REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
275
276    pixel = uxa_get_pixmap_first_pixel (pSrcPix);
277
278    if (!uxa_pixmap_is_offscreen(pDstPix)) {
279	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
280	return 0;
281    }
282
283    if (!uxa_get_rgba_from_pixel(pixel, &red, &green, &blue, &alpha,
284			 pSrc->format))
285    {
286	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
287	return -1;
288    }
289
290    if (!uxa_get_pixel_from_rgba(&pixel, red, green, blue, alpha,
291			pDst->format))
292    {
293	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
294	return -1;
295    }
296
297    if (!(*uxa_screen->info->prepare_solid) (pDstPix, GXcopy, 0xffffffff, pixel))
298    {
299	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
300	return -1;
301    }
302
303    nbox = REGION_NUM_RECTS(&region);
304    pbox = REGION_RECTS(&region);
305
306    while (nbox--)
307    {
308	(*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2);
309	pbox++;
310    }
311
312    (*uxa_screen->info->done_solid) (pDstPix);
313
314    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
315    return 1;
316}
317
318/* In order to avoid fallbacks when using an a1 source/mask,
319 * for example with non-antialiased trapezoids, we need to
320 * expand the bitmap into an a8 Picture. We do so by using the generic
321 * composition routines, which while may not be perfect is far faster
322 * than causing a fallback.
323 */
324static PicturePtr
325uxa_picture_from_a1_pixman_image (ScreenPtr pScreen,
326				  pixman_image_t *image)
327{
328    PicturePtr pPicture;
329    PicturePtr pSrc;
330    PixmapPtr pPixmap;
331    int width, height;
332    int error;
333
334    width = pixman_image_get_width (image);
335    height = pixman_image_get_height (image);
336
337    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 8,
338					UXA_CREATE_PIXMAP_FOR_MAP);
339    if (!pPixmap)
340	return 0;
341
342    pPicture = CreatePicture (0, &pPixmap->drawable,
343			      PictureMatchFormat (pScreen, 8, PICT_a8),
344			      0, 0, serverClient, &error);
345    (*pScreen->DestroyPixmap) (pPixmap);
346    if (!pPicture)
347	return 0;
348
349    ValidatePicture (pPicture);
350
351    pPixmap = GetScratchPixmapHeader(pScreen, width, height, 1,
352				     BitsPerPixel (1),
353				     pixman_image_get_stride (image),
354				     pixman_image_get_data (image));
355    if (!pPixmap) {
356	FreePicture (pPicture, 0);
357	return 0;
358    }
359
360    pSrc = CreatePicture (0, &pPixmap->drawable,
361			  PictureMatchFormat (pScreen, 1, PICT_a1),
362			  0, 0, serverClient, &error);
363    if (!pSrc) {
364	FreeScratchPixmapHeader (pPixmap);
365	FreePicture (pPicture, 0);
366	return 0;
367    }
368
369    CompositePicture (PictOpSrc, pSrc, NULL, pPicture,
370		      0, 0,
371		      0, 0,
372		      0, 0,
373		      width, height);
374
375    FreePicture (pSrc, 0);
376    FreeScratchPixmapHeader (pPixmap);
377
378    return pPicture;
379}
380
381static PicturePtr
382uxa_picture_from_pixman_image (ScreenPtr pScreen,
383			       pixman_image_t *image,
384			       pixman_format_code_t format)
385{
386    PicturePtr pPicture;
387    PixmapPtr pPixmap;
388    GCPtr pGC;
389    int width, height, depth;
390    int error;
391
392    if (format == PICT_a1)
393	return uxa_picture_from_a1_pixman_image (pScreen, image);
394
395    width = pixman_image_get_width (image);
396    height = pixman_image_get_height (image);
397    depth = pixman_image_get_depth (image);
398
399    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth,
400					UXA_CREATE_PIXMAP_FOR_MAP);
401    if (!pPixmap)
402	return 0;
403
404    pPicture = CreatePicture (0, &pPixmap->drawable,
405			      PictureMatchFormat (pScreen, depth, format),
406			      0, 0, serverClient, &error);
407    (*pScreen->DestroyPixmap) (pPixmap);
408    if (!pPicture)
409	return 0;
410
411    ValidatePicture (pPicture);
412
413    pPixmap = GetScratchPixmapHeader(pScreen, width, height, depth,
414				     BitsPerPixel (depth),
415				     pixman_image_get_stride (image),
416				     pixman_image_get_data (image));
417    if (!pPixmap)
418    {
419	FreePicture (pPicture, 0);
420	return 0;
421    }
422
423    pGC = GetScratchGC (depth, pScreen);
424    if (!pGC)
425    {
426	FreeScratchPixmapHeader (pPixmap);
427	FreePicture (pPicture, 0);
428	return 0;
429    }
430    ValidateGC (pPicture->pDrawable, pGC);
431
432    (*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable,
433			   pGC, 0, 0, width, height, 0, 0);
434
435    FreeScratchGC (pGC);
436    FreeScratchPixmapHeader (pPixmap);
437
438    return pPicture;
439}
440
441#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC (1,6,99,1,0)
442#define IMAGE_FROM_PICT(P) image_from_pict(P, 0)
443#else
444#define IMAGE_FROM_PICT(P) image_from_pict(P, 0, 0)
445#endif
446
447static PicturePtr
448uxa_acquire_pattern (ScreenPtr pScreen,
449		     PicturePtr pPict,
450		     pixman_format_code_t format,
451		     INT16 x, INT16 y,
452		     CARD16 width, CARD16 height)
453{
454    pixman_image_t *source, *image;
455
456    source = IMAGE_FROM_PICT (pPict);
457    if (!source)
458	return 0;
459
460    image = pixman_image_create_bits (format, width, height, NULL, 0);
461    if (!image) {
462	pixman_image_unref (source);
463	return 0;
464    }
465
466    pixman_image_composite (PIXMAN_OP_SRC,
467			    source, NULL, image,
468			    x, y,
469			    0, 0,
470			    0, 0,
471			    width, height);
472    pixman_image_unref (source);
473
474    pPict = uxa_picture_from_pixman_image (pScreen, image, format);
475    pixman_image_unref (image);
476
477    return pPict;
478}
479
480static PicturePtr
481uxa_acquire_source (ScreenPtr pScreen,
482		    PicturePtr pPict,
483		    INT16 x, INT16 y,
484		    CARD16 width, CARD16 height,
485		    INT16 *out_x, INT16 *out_y)
486{
487    if (pPict->pDrawable) {
488	*out_x = x + pPict->pDrawable->x;
489	*out_y = y + pPict->pDrawable->y;
490	return pPict;
491    }
492
493    *out_x = 0;
494    *out_y = 0;
495    return uxa_acquire_pattern (pScreen, pPict,
496				PICT_a8r8g8b8, x, y, width, height);
497}
498
499static PicturePtr
500uxa_acquire_mask (ScreenPtr pScreen,
501		  PicturePtr pPict,
502		  INT16 x, INT16 y,
503		  INT16 width, INT16 height,
504		  INT16 *out_x, INT16 *out_y)
505{
506    if (pPict->pDrawable) {
507	*out_x = x + pPict->pDrawable->x;
508	*out_y = y + pPict->pDrawable->y;
509	return pPict;
510    }
511
512    *out_x = 0;
513    *out_y = 0;
514    return uxa_acquire_pattern (pScreen, pPict,
515				PICT_a8, x, y, width, height);
516}
517
518static int
519uxa_try_driver_composite_rects(CARD8		    op,
520			       PicturePtr	    pSrc,
521			       PicturePtr	    pDst,
522			       int		    nrect,
523			       uxa_composite_rect_t *rects)
524{
525    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
526    int src_off_x, src_off_y, dst_off_x, dst_off_y;
527    PixmapPtr pSrcPix, pDstPix;
528
529    if (!uxa_screen->info->prepare_composite || uxa_screen->swappedOut)
530	return -1;
531
532    if (uxa_screen->info->check_composite &&
533	!(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst))
534    {
535	return -1;
536    }
537
538    pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
539    if (!pDstPix)
540	return 0;
541
542    pSrcPix = uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
543    if (!pSrcPix)
544	return 0;
545
546    if (!(*uxa_screen->info->prepare_composite) (op, pSrc, NULL, pDst, pSrcPix,
547						 NULL, pDstPix))
548	return -1;
549
550    while (nrect--)
551    {
552	INT16 xDst = rects->xDst + pDst->pDrawable->x;
553	INT16 yDst = rects->yDst + pDst->pDrawable->y;
554	INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
555	INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
556
557	RegionRec region;
558	BoxPtr pbox;
559	int nbox;
560
561	if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
562				       xSrc, ySrc, 0, 0, xDst, yDst,
563				       rects->width, rects->height))
564	    goto next_rect;
565
566	REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
567
568	nbox = REGION_NUM_RECTS(&region);
569	pbox = REGION_RECTS(&region);
570
571	xSrc = xSrc + src_off_x - xDst - dst_off_x;
572	ySrc = ySrc + src_off_y - yDst - dst_off_y;
573
574	while (nbox--)
575	{
576	    (*uxa_screen->info->composite) (pDstPix,
577					    pbox->x1 + xSrc,
578					    pbox->y1 + ySrc,
579					    0, 0,
580					    pbox->x1,
581					    pbox->y1,
582					    pbox->x2 - pbox->x1,
583					    pbox->y2 - pbox->y1);
584	    pbox++;
585	}
586
587    next_rect:
588	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
589
590	rects++;
591    }
592    (*uxa_screen->info->done_composite) (pDstPix);
593
594    return 1;
595}
596
597/**
598 * Copy a number of rectangles from source to destination in a single
599 * operation. This is specialized for building a glyph mask: we don'y
600 * have a mask argument because we don't need it for that, and we
601 * don't have he special-case fallbacks found in uxa_composite() - if the
602 * driver can support it, we use the driver functionality, otherwise we
603 * fallback straight to software.
604 */
605void
606uxa_composite_rects(CARD8	          op,
607		    PicturePtr		  pSrc,
608		    PicturePtr		  pDst,
609		    int			  nrect,
610		    uxa_composite_rect_t  *rects)
611{
612    int			   n;
613    uxa_composite_rect_t   *r;
614
615    /************************************************************/
616
617    ValidatePicture (pSrc);
618    ValidatePicture (pDst);
619
620    if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) {
621	n = nrect;
622	r = rects;
623	while (n--) {
624	    uxa_check_composite (op, pSrc, NULL, pDst,
625			       r->xSrc, r->ySrc,
626			       0, 0,
627			       r->xDst, r->yDst,
628			       r->width, r->height);
629	    r++;
630	}
631    }
632
633    /************************************************************/
634
635}
636
637static int
638uxa_try_driver_composite(CARD8		op,
639			 PicturePtr	pSrc,
640			 PicturePtr	pMask,
641			 PicturePtr	pDst,
642			 INT16		xSrc,
643			 INT16		ySrc,
644			 INT16		xMask,
645			 INT16		yMask,
646			 INT16		xDst,
647			 INT16		yDst,
648			 CARD16		width,
649			 CARD16		height)
650{
651    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
652    RegionRec region;
653    BoxPtr pbox;
654    int nbox;
655    int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
656    PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
657    PicturePtr localSrc, localMask = NULL;
658
659    xDst += pDst->pDrawable->x;
660    yDst += pDst->pDrawable->y;
661
662    localSrc = uxa_acquire_source (pDst->pDrawable->pScreen,
663				   pSrc, xSrc, ySrc, width, height,
664				   &xSrc, &ySrc);
665    if (! localSrc)
666	return 0;
667
668    if (pMask) {
669	localMask = uxa_acquire_mask (pDst->pDrawable->pScreen,
670				      pMask, xMask, yMask, width, height,
671				      &xMask, &yMask);
672	if (! localMask) {
673	    if (localSrc != pSrc)
674		FreePicture (localSrc, 0);
675
676	    return 0;
677	}
678    }
679
680    if (uxa_screen->info->check_composite &&
681	!(*uxa_screen->info->check_composite) (op, localSrc, localMask, pDst))
682    {
683	if (localSrc != pSrc)
684	    FreePicture (localSrc, 0);
685	if (localMask && localMask != pMask)
686	    FreePicture (localMask, 0);
687
688	return -1;
689    }
690
691    if (!miComputeCompositeRegion (&region, localSrc, localMask, pDst,
692				   xSrc, ySrc, xMask, yMask, xDst, yDst,
693				   width, height))
694    {
695	if (localSrc != pSrc)
696	    FreePicture (localSrc, 0);
697	if (localMask && localMask != pMask)
698	    FreePicture (localMask, 0);
699
700	return 1;
701    }
702
703    pDstPix = uxa_get_offscreen_pixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
704
705    pSrcPix = uxa_get_offscreen_pixmap (localSrc->pDrawable,
706					&src_off_x, &src_off_y);
707
708    if (localMask)
709	pMaskPix = uxa_get_offscreen_pixmap (localMask->pDrawable,
710					     &mask_off_x, &mask_off_y);
711
712    if (!pDstPix || !pSrcPix || (localMask && !pMaskPix)) {
713	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
714
715	if (localSrc != pSrc)
716	    FreePicture (localSrc, 0);
717	if (localMask && localMask != pMask)
718	    FreePicture (localMask, 0);
719
720	return 0;
721    }
722
723    REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
724
725    if (!(*uxa_screen->info->prepare_composite) (op, localSrc, localMask, pDst,
726						 pSrcPix, pMaskPix, pDstPix))
727    {
728	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
729
730	if (localSrc != pSrc)
731	    FreePicture (localSrc, 0);
732	if (localMask && localMask != pMask)
733	    FreePicture (localMask, 0);
734
735	return -1;
736    }
737
738    nbox = REGION_NUM_RECTS(&region);
739    pbox = REGION_RECTS(&region);
740
741    xMask = xMask + mask_off_x - xDst - dst_off_x;
742    yMask = yMask + mask_off_y - yDst - dst_off_y;
743
744    xSrc = xSrc + src_off_x - xDst - dst_off_x;
745    ySrc = ySrc + src_off_y - yDst - dst_off_y;
746
747    while (nbox--)
748    {
749	(*uxa_screen->info->composite) (pDstPix,
750					pbox->x1 + xSrc,
751					pbox->y1 + ySrc,
752					pbox->x1 + xMask,
753					pbox->y1 + yMask,
754					pbox->x1,
755					pbox->y1,
756					pbox->x2 - pbox->x1,
757					pbox->y2 - pbox->y1);
758	pbox++;
759    }
760    (*uxa_screen->info->done_composite) (pDstPix);
761
762    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
763
764    if (localSrc != pSrc)
765	FreePicture (localSrc, 0);
766    if (localMask && localMask != pMask)
767	FreePicture (localMask, 0);
768
769    return 1;
770}
771
772/**
773 * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of
774 * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
775 * alpha and limited 1-tmu cards.
776 *
777 * From http://anholt.livejournal.com/32058.html:
778 *
779 * The trouble is that component-alpha rendering requires two different sources
780 * for blending: one for the source value to the blender, which is the
781 * per-channel multiplication of source and mask, and one for the source alpha
782 * for multiplying with the destination channels, which is the multiplication
783 * of the source channels by the mask alpha. So the equation for Over is:
784 *
785 * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
786 * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
787 * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
788 * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
789 *
790 * But we can do some simpler operations, right? How about PictOpOutReverse,
791 * which has a source factor of 0 and dest factor of (1 - source alpha). We
792 * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
793 * blenders pretty easily. So we can do a component-alpha OutReverse, which
794 * gets us:
795 *
796 * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
797 * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
798 * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
799 * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
800 *
801 * OK. And if an op doesn't use the source alpha value for the destination
802 * factor, then we can do the channel multiplication in the texture blenders
803 * to get the source value, and ignore the source alpha that we wouldn't use.
804 * We've supported this in the Radeon driver for a long time. An example would
805 * be PictOpAdd, which does:
806 *
807 * dst.A = src.A * mask.A + dst.A
808 * dst.R = src.R * mask.R + dst.R
809 * dst.G = src.G * mask.G + dst.G
810 * dst.B = src.B * mask.B + dst.B
811 *
812 * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
813 * after it, we get:
814 *
815 * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
816 * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
817 * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
818 * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
819 */
820
821static int
822uxa_try_magic_two_pass_composite_helper(CARD8 op,
823				  PicturePtr pSrc,
824				  PicturePtr pMask,
825				  PicturePtr pDst,
826				  INT16 xSrc,
827				  INT16 ySrc,
828				  INT16 xMask,
829				  INT16 yMask,
830				  INT16 xDst,
831				  INT16 yDst,
832				  CARD16 width,
833				  CARD16 height)
834{
835    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
836
837    assert(op == PictOpOver);
838
839    if (uxa_screen->info->check_composite &&
840	(!(*uxa_screen->info->check_composite)(PictOpOutReverse, pSrc, pMask,
841					   pDst) ||
842	 !(*uxa_screen->info->check_composite)(PictOpAdd, pSrc, pMask, pDst)))
843    {
844	return -1;
845    }
846
847    /* Now, we think we should be able to accelerate this operation. First,
848     * composite the destination to be the destination times the source alpha
849     * factors.
850     */
851    uxa_composite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
852		 xDst, yDst, width, height);
853
854    /* Then, add in the source value times the destination alpha factors (1.0).
855     */
856    uxa_composite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
857		 xDst, yDst, width, height);
858
859    return 1;
860}
861
862void
863uxa_composite(CARD8	op,
864	     PicturePtr pSrc,
865	     PicturePtr pMask,
866	     PicturePtr pDst,
867	     INT16	xSrc,
868	     INT16	ySrc,
869	     INT16	xMask,
870	     INT16	yMask,
871	     INT16	xDst,
872	     INT16	yDst,
873	     CARD16	width,
874	     CARD16	height)
875{
876    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
877    int ret = -1;
878    Bool saveSrcRepeat = pSrc->repeat;
879    Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
880    RegionRec region;
881
882    if (uxa_screen->swappedOut)
883	goto fallback;
884
885    if (pSrc->pDrawable == NULL || (pMask && pMask->pDrawable == NULL))
886	goto composite;
887
888    /* Remove repeat in source if useless */
889    if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
890	(xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
891	(ySrc + height) <= pSrc->pDrawable->height)
892	    pSrc->repeat = 0;
893
894    if (!pMask)
895    {
896      if ((op == PictOpSrc &&
897	   ((pSrc->format == pDst->format) ||
898	    (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
899	    (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
900	  (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
901	   pSrc->format == pDst->format &&
902	   (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))
903	{
904	    if (pSrc->pDrawable->width == 1 &&
905		pSrc->pDrawable->height == 1 &&
906		pSrc->repeat)
907	    {
908		ret = uxa_try_driver_solid_fill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
909					    width, height);
910		if (ret == 1)
911		    goto done;
912	    }
913	    else if (pSrc->pDrawable != NULL &&
914		     !pSrc->repeat &&
915		     !pSrc->transform)
916	    {
917		xDst += pDst->pDrawable->x;
918		yDst += pDst->pDrawable->y;
919		xSrc += pSrc->pDrawable->x;
920		ySrc += pSrc->pDrawable->y;
921
922		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
923					       xSrc, ySrc, xMask, yMask, xDst,
924					       yDst, width, height))
925		    goto done;
926
927
928		uxa_copy_n_to_n (pSrc->pDrawable, pDst->pDrawable, NULL,
929			     REGION_RECTS(&region), REGION_NUM_RECTS(&region),
930			     xSrc - xDst, ySrc - yDst,
931			     FALSE, FALSE, 0, NULL);
932		REGION_UNINIT(pDst->pDrawable->pScreen, &region);
933		goto done;
934	    }
935	    else if (pSrc->pDrawable != NULL &&
936		     pSrc->pDrawable->type == DRAWABLE_PIXMAP &&
937		     !pSrc->transform &&
938		     pSrc->repeatType == RepeatNormal)
939	    {
940		DDXPointRec patOrg;
941
942		/* Let's see if the driver can do the repeat in one go */
943		if (uxa_screen->info->prepare_composite && !pSrc->alphaMap &&
944		    !pDst->alphaMap)
945		{
946		    ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc,
947						ySrc, xMask, yMask, xDst, yDst,
948						width, height);
949		    if (ret == 1)
950			goto done;
951		}
952
953		/* Now see if we can use uxa_fill_region_tiled() */
954		xDst += pDst->pDrawable->x;
955		yDst += pDst->pDrawable->y;
956		xSrc += pSrc->pDrawable->x;
957		ySrc += pSrc->pDrawable->y;
958
959		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst, xSrc,
960					       ySrc, xMask, yMask, xDst, yDst,
961					       width, height))
962		    goto done;
963
964		/* pattern origin is the point in the destination drawable
965		 * corresponding to (0,0) in the source */
966		patOrg.x = xDst - xSrc;
967		patOrg.y = yDst - ySrc;
968
969		ret = uxa_fill_region_tiled(pDst->pDrawable, &region,
970					 (PixmapPtr)pSrc->pDrawable,
971					 &patOrg, FB_ALLONES, GXcopy);
972
973		REGION_UNINIT(pDst->pDrawable->pScreen, &region);
974
975		if (ret)
976		    goto done;
977	    }
978	}
979    }
980
981composite:
982    /* Remove repeat in mask if useless */
983    if (pMask && pMask->repeat && !pMask->transform && pMask->pDrawable &&
984	xMask >= 0 && (xMask + width) <= pMask->pDrawable->width &&
985	yMask >= 0 && (yMask + height) <= pMask->pDrawable->height)
986	    pMask->repeat = 0;
987
988    if (uxa_screen->info->prepare_composite &&
989	!pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
990    {
991	Bool isSrcSolid;
992
993	ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask,
994				    yMask, xDst, yDst, width, height);
995	if (ret == 1)
996	    goto done;
997
998	/* For generic masks and solid src pictures, mach64 can do Over in two
999	 * passes, similar to the component-alpha case.
1000	 */
1001	isSrcSolid = pSrc->pDrawable &&
1002		     pSrc->pDrawable->width == 1 &&
1003		     pSrc->pDrawable->height == 1 &&
1004		     pSrc->repeat;
1005
1006	/* If we couldn't do the Composite in a single pass, and it was a
1007	 * component-alpha Over, see if we can do it in two passes with
1008	 * an OutReverse and then an Add.
1009	 */
1010	if (ret == -1 && op == PictOpOver && pMask &&
1011	    (pMask->componentAlpha || isSrcSolid)) {
1012	    ret = uxa_try_magic_two_pass_composite_helper(op, pSrc, pMask, pDst,
1013						    xSrc, ySrc,
1014						    xMask, yMask, xDst, yDst,
1015						    width, height);
1016	    if (ret == 1)
1017		goto done;
1018	}
1019    }
1020
1021fallback:
1022    if (uxa_screen->fallback_debug)
1023	uxa_print_composite_fallback (op, pSrc, pMask, pDst);
1024
1025    uxa_check_composite (op, pSrc, pMask, pDst, xSrc, ySrc,
1026		      xMask, yMask, xDst, yDst, width, height);
1027
1028done:
1029    pSrc->repeat = saveSrcRepeat;
1030    if (pMask)
1031	pMask->repeat = saveMaskRepeat;
1032}
1033#endif
1034
1035/**
1036 * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead
1037 * of PolyFillRect to initialize the pixmap after creating it, to prevent
1038 * the pixmap from being migrated.
1039 *
1040 * See the comments about uxa_trapezoids and uxa_triangles.
1041 */
1042static PicturePtr
1043uxa_create_alpha_picture (ScreenPtr     pScreen,
1044                       PicturePtr    pDst,
1045                       PictFormatPtr pPictFormat,
1046                       CARD16        width,
1047                       CARD16        height)
1048{
1049    PixmapPtr	    pPixmap;
1050    PicturePtr	    pPicture;
1051    int		    error;
1052
1053    if (width > 32767 || height > 32767)
1054	return 0;
1055
1056    if (!pPictFormat)
1057    {
1058	if (pDst->polyEdge == PolyEdgeSharp)
1059	    pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
1060	else
1061	    pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
1062	if (!pPictFormat)
1063	    return 0;
1064    }
1065
1066    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
1067					pPictFormat->depth,
1068					UXA_CREATE_PIXMAP_FOR_MAP);
1069    if (!pPixmap)
1070	return 0;
1071    pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat,
1072			      0, 0, serverClient, &error);
1073    (*pScreen->DestroyPixmap) (pPixmap);
1074    return pPicture;
1075}
1076
1077/**
1078 * uxa_trapezoids is essentially a copy of miTrapezoids that uses
1079 * uxa_create_alpha_picture instead of miCreateAlphaPicture.
1080 *
1081 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
1082 * to initialize the contents after creating the pixmap, which
1083 * causes the pixmap to be moved in for acceleration. The subsequent
1084 * call to RasterizeTrapezoid won't be accelerated however, which
1085 * forces the pixmap to be moved out again.
1086 *
1087 * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect
1088 * to initialize the contents.
1089 */
1090void
1091uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1092               PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1093               int ntrap, xTrapezoid *traps)
1094{
1095    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
1096    PictureScreenPtr    ps = GetPictureScreen(pScreen);
1097    BoxRec		bounds;
1098    Bool		direct = op == PictOpAdd && miIsSolidAlpha (pSrc);
1099
1100    if (maskFormat || direct) {
1101	miTrapezoidBounds (ntrap, traps, &bounds);
1102
1103	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1104	    return;
1105    }
1106
1107    /*
1108     * Check for solid alpha add
1109     */
1110    if (direct)
1111    {
1112	DrawablePtr pDraw = pDst->pDrawable;
1113	PixmapPtr pixmap = uxa_get_drawable_pixmap (pDraw);
1114	int xoff, yoff;
1115
1116	uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff);
1117
1118	xoff += pDraw->x;
1119	yoff += pDraw->y;
1120
1121	if (uxa_prepare_access(pDraw, UXA_ACCESS_RW))
1122	{
1123	    for (; ntrap; ntrap--, traps++)
1124		(*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
1125	    uxa_finish_access(pDraw);
1126	}
1127    }
1128    else if (maskFormat)
1129    {
1130	PicturePtr	pPicture;
1131	INT16		xDst, yDst;
1132	INT16		xRel, yRel;
1133	int		width, height;
1134	pixman_image_t	*image;
1135	pixman_format_code_t format;
1136
1137	xDst = traps[0].left.p1.x >> 16;
1138	yDst = traps[0].left.p1.y >> 16;
1139
1140	width = bounds.x2 - bounds.x1;
1141	height = bounds.y2 - bounds.y1;
1142
1143	format = maskFormat->format | (BitsPerPixel (maskFormat->depth) << 24);
1144	image = pixman_image_create_bits (format, width, height, NULL, 0);
1145	if (!image)
1146	    return;
1147
1148	for (; ntrap; ntrap--, traps++)
1149	    pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *) traps,
1150					-bounds.x1, -bounds.y1);
1151
1152	pPicture = uxa_picture_from_pixman_image (pScreen, image, format);
1153	pixman_image_unref (image);
1154	if (!pPicture)
1155	    return;
1156
1157	xRel = bounds.x1 + xSrc - xDst;
1158	yRel = bounds.y1 + ySrc - yDst;
1159	CompositePicture (op, pSrc, pPicture, pDst,
1160			  xRel, yRel, 0, 0, bounds.x1, bounds.y1,
1161			  bounds.x2 - bounds.x1,
1162			  bounds.y2 - bounds.y1);
1163	FreePicture (pPicture, 0);
1164    }
1165    else
1166    {
1167	if (pDst->polyEdge == PolyEdgeSharp)
1168	    maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
1169	else
1170	    maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
1171	for (; ntrap; ntrap--, traps++)
1172	    uxa_trapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
1173    }
1174}
1175
1176/**
1177 * uxa_triangles is essentially a copy of miTriangles that uses
1178 * uxa_create_alpha_picture instead of miCreateAlphaPicture.
1179 *
1180 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
1181 * to initialize the contents after creating the pixmap, which
1182 * causes the pixmap to be moved in for acceleration. The subsequent
1183 * call to AddTriangles won't be accelerated however, which forces the pixmap
1184 * to be moved out again.
1185 *
1186 * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect
1187 * to initialize the contents.
1188 */
1189void
1190uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1191	      PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1192	      int ntri, xTriangle *tris)
1193{
1194    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
1195    PictureScreenPtr    ps = GetPictureScreen(pScreen);
1196    BoxRec		bounds;
1197    Bool		direct = op == PictOpAdd && miIsSolidAlpha (pSrc);
1198
1199    if (maskFormat || direct) {
1200	miTriangleBounds (ntri, tris, &bounds);
1201
1202	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1203	    return;
1204    }
1205
1206    /*
1207     * Check for solid alpha add
1208     */
1209    if (direct)
1210    {
1211	DrawablePtr pDraw = pDst->pDrawable;
1212	if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
1213	    (*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
1214	    uxa_finish_access(pDraw);
1215	}
1216    }
1217    else if (maskFormat)
1218    {
1219	PicturePtr	pPicture;
1220	INT16		xDst, yDst;
1221	INT16		xRel, yRel;
1222	int width = bounds.x2 - bounds.x1;
1223	int height = bounds.y2 - bounds.y1;
1224	GCPtr pGC;
1225	xRectangle rect;
1226
1227	xDst = tris[0].p1.x >> 16;
1228	yDst = tris[0].p1.y >> 16;
1229
1230	pPicture = uxa_create_alpha_picture (pScreen, pDst, maskFormat,
1231					     width, height);
1232	if (!pPicture)
1233	    return;
1234
1235	/* Clear the alpha picture to 0. */
1236	pGC = GetScratchGC (pPicture->pDrawable->depth, pScreen);
1237	if (!pGC) {
1238	    FreePicture (pPicture, 0);
1239	    return;
1240	}
1241	ValidateGC (pPicture->pDrawable, pGC);
1242	rect.x = 0;
1243	rect.y = 0;
1244	rect.width = width;
1245	rect.height = height;
1246	uxa_check_poly_fill_rect (pPicture->pDrawable, pGC, 1, &rect);
1247	FreeScratchGC (pGC);
1248
1249	if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) {
1250	    (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
1251	    uxa_finish_access(pPicture->pDrawable);
1252	}
1253
1254	xRel = bounds.x1 + xSrc - xDst;
1255	yRel = bounds.y1 + ySrc - yDst;
1256	CompositePicture (op, pSrc, pPicture, pDst,
1257			  xRel, yRel, 0, 0, bounds.x1, bounds.y1,
1258			  bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
1259	FreePicture (pPicture, 0);
1260    }
1261    else
1262    {
1263	if (pDst->polyEdge == PolyEdgeSharp)
1264	    maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
1265	else
1266	    maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
1267
1268	for (; ntri; ntri--, tris++)
1269	    uxa_triangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
1270    }
1271}
1272