uxa-render.c revision be514f52
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
441static PicturePtr
442uxa_acquire_pattern (ScreenPtr pScreen,
443		     PicturePtr pPict,
444		     pixman_format_code_t format,
445		     INT16 x, INT16 y,
446		     CARD16 width, CARD16 height)
447{
448    pixman_image_t *source, *image;
449    int src_xoff, src_yoff;
450
451    source = image_from_pict(pPict, FALSE, &src_xoff, &src_yoff);
452    if (!source)
453	return 0;
454
455    image = pixman_image_create_bits (format, width, height, NULL, 0);
456    if (!image) {
457	pixman_image_unref (source);
458	return 0;
459    }
460
461    pixman_image_composite (PIXMAN_OP_SRC,
462			    source, NULL, image,
463			    x, y,
464			    0, 0,
465			    0, 0,
466			    width, height);
467    pixman_image_unref (source);
468
469    pPict = uxa_picture_from_pixman_image (pScreen, image, format);
470    pixman_image_unref (image);
471
472    return pPict;
473}
474
475static PicturePtr
476uxa_acquire_source (ScreenPtr pScreen,
477		    PicturePtr pPict,
478		    INT16 x, INT16 y,
479		    CARD16 width, CARD16 height,
480		    INT16 *out_x, INT16 *out_y)
481{
482    if (pPict->pDrawable) {
483	*out_x = x + pPict->pDrawable->x;
484	*out_y = y + pPict->pDrawable->y;
485	return pPict;
486    }
487
488    *out_x = 0;
489    *out_y = 0;
490    return uxa_acquire_pattern (pScreen, pPict,
491				PICT_a8r8g8b8, x, y, width, height);
492}
493
494static PicturePtr
495uxa_acquire_mask (ScreenPtr pScreen,
496		  PicturePtr pPict,
497		  INT16 x, INT16 y,
498		  INT16 width, INT16 height,
499		  INT16 *out_x, INT16 *out_y)
500{
501    if (pPict->pDrawable) {
502	*out_x = x + pPict->pDrawable->x;
503	*out_y = y + pPict->pDrawable->y;
504	return pPict;
505    }
506
507    *out_x = 0;
508    *out_y = 0;
509    return uxa_acquire_pattern (pScreen, pPict,
510				PICT_a8, x, y, width, height);
511}
512
513static int
514uxa_try_driver_composite_rects(CARD8		    op,
515			       PicturePtr	    pSrc,
516			       PicturePtr	    pDst,
517			       int		    nrect,
518			       uxa_composite_rect_t *rects)
519{
520    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
521    int src_off_x, src_off_y, dst_off_x, dst_off_y;
522    PixmapPtr pSrcPix, pDstPix;
523
524    if (!uxa_screen->info->prepare_composite || uxa_screen->swappedOut)
525	return -1;
526
527    if (uxa_screen->info->check_composite &&
528	!(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst))
529    {
530	return -1;
531    }
532
533    pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
534    if (!pDstPix)
535	return 0;
536
537    pSrcPix = uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
538    if (!pSrcPix)
539	return 0;
540
541    if (!(*uxa_screen->info->prepare_composite) (op, pSrc, NULL, pDst, pSrcPix,
542						 NULL, pDstPix))
543	return -1;
544
545    while (nrect--)
546    {
547	INT16 xDst = rects->xDst + pDst->pDrawable->x;
548	INT16 yDst = rects->yDst + pDst->pDrawable->y;
549	INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
550	INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
551
552	RegionRec region;
553	BoxPtr pbox;
554	int nbox;
555
556	if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
557				       xSrc, ySrc, 0, 0, xDst, yDst,
558				       rects->width, rects->height))
559	    goto next_rect;
560
561	REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
562
563	nbox = REGION_NUM_RECTS(&region);
564	pbox = REGION_RECTS(&region);
565
566	xSrc = xSrc + src_off_x - xDst - dst_off_x;
567	ySrc = ySrc + src_off_y - yDst - dst_off_y;
568
569	while (nbox--)
570	{
571	    (*uxa_screen->info->composite) (pDstPix,
572					    pbox->x1 + xSrc,
573					    pbox->y1 + ySrc,
574					    0, 0,
575					    pbox->x1,
576					    pbox->y1,
577					    pbox->x2 - pbox->x1,
578					    pbox->y2 - pbox->y1);
579	    pbox++;
580	}
581
582    next_rect:
583	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
584
585	rects++;
586    }
587    (*uxa_screen->info->done_composite) (pDstPix);
588
589    return 1;
590}
591
592/**
593 * Copy a number of rectangles from source to destination in a single
594 * operation. This is specialized for building a glyph mask: we don'y
595 * have a mask argument because we don't need it for that, and we
596 * don't have he special-case fallbacks found in uxa_composite() - if the
597 * driver can support it, we use the driver functionality, otherwise we
598 * fallback straight to software.
599 */
600void
601uxa_composite_rects(CARD8	          op,
602		    PicturePtr		  pSrc,
603		    PicturePtr		  pDst,
604		    int			  nrect,
605		    uxa_composite_rect_t  *rects)
606{
607    int			   n;
608    uxa_composite_rect_t   *r;
609
610    /************************************************************/
611
612    ValidatePicture (pSrc);
613    ValidatePicture (pDst);
614
615    if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) {
616	n = nrect;
617	r = rects;
618	while (n--) {
619	    uxa_check_composite (op, pSrc, NULL, pDst,
620			       r->xSrc, r->ySrc,
621			       0, 0,
622			       r->xDst, r->yDst,
623			       r->width, r->height);
624	    r++;
625	}
626    }
627
628    /************************************************************/
629
630}
631
632static int
633uxa_try_driver_composite(CARD8		op,
634			 PicturePtr	pSrc,
635			 PicturePtr	pMask,
636			 PicturePtr	pDst,
637			 INT16		xSrc,
638			 INT16		ySrc,
639			 INT16		xMask,
640			 INT16		yMask,
641			 INT16		xDst,
642			 INT16		yDst,
643			 CARD16		width,
644			 CARD16		height)
645{
646    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
647    RegionRec region;
648    BoxPtr pbox;
649    int nbox;
650    int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
651    PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
652    PicturePtr localSrc, localMask = NULL;
653
654    xDst += pDst->pDrawable->x;
655    yDst += pDst->pDrawable->y;
656
657    localSrc = uxa_acquire_source (pDst->pDrawable->pScreen,
658				   pSrc, xSrc, ySrc, width, height,
659				   &xSrc, &ySrc);
660    if (! localSrc)
661	return 0;
662
663    if (pMask) {
664	localMask = uxa_acquire_mask (pDst->pDrawable->pScreen,
665				      pMask, xMask, yMask, width, height,
666				      &xMask, &yMask);
667	if (! localMask) {
668	    if (localSrc != pSrc)
669		FreePicture (localSrc, 0);
670
671	    return 0;
672	}
673    }
674
675    if (uxa_screen->info->check_composite &&
676	!(*uxa_screen->info->check_composite) (op, localSrc, localMask, pDst))
677    {
678	if (localSrc != pSrc)
679	    FreePicture (localSrc, 0);
680	if (localMask && localMask != pMask)
681	    FreePicture (localMask, 0);
682
683	return -1;
684    }
685
686    if (!miComputeCompositeRegion (&region, localSrc, localMask, pDst,
687				   xSrc, ySrc, xMask, yMask, xDst, yDst,
688				   width, height))
689    {
690	if (localSrc != pSrc)
691	    FreePicture (localSrc, 0);
692	if (localMask && localMask != pMask)
693	    FreePicture (localMask, 0);
694
695	return 1;
696    }
697
698    pDstPix = uxa_get_offscreen_pixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
699
700    pSrcPix = uxa_get_offscreen_pixmap (localSrc->pDrawable,
701					&src_off_x, &src_off_y);
702
703    if (localMask)
704	pMaskPix = uxa_get_offscreen_pixmap (localMask->pDrawable,
705					     &mask_off_x, &mask_off_y);
706
707    if (!pDstPix || !pSrcPix || (localMask && !pMaskPix)) {
708	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
709
710	if (localSrc != pSrc)
711	    FreePicture (localSrc, 0);
712	if (localMask && localMask != pMask)
713	    FreePicture (localMask, 0);
714
715	return 0;
716    }
717
718    REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
719
720    if (!(*uxa_screen->info->prepare_composite) (op, localSrc, localMask, pDst,
721						 pSrcPix, pMaskPix, pDstPix))
722    {
723	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
724
725	if (localSrc != pSrc)
726	    FreePicture (localSrc, 0);
727	if (localMask && localMask != pMask)
728	    FreePicture (localMask, 0);
729
730	return -1;
731    }
732
733    nbox = REGION_NUM_RECTS(&region);
734    pbox = REGION_RECTS(&region);
735
736    xMask = xMask + mask_off_x - xDst - dst_off_x;
737    yMask = yMask + mask_off_y - yDst - dst_off_y;
738
739    xSrc = xSrc + src_off_x - xDst - dst_off_x;
740    ySrc = ySrc + src_off_y - yDst - dst_off_y;
741
742    while (nbox--)
743    {
744	(*uxa_screen->info->composite) (pDstPix,
745					pbox->x1 + xSrc,
746					pbox->y1 + ySrc,
747					pbox->x1 + xMask,
748					pbox->y1 + yMask,
749					pbox->x1,
750					pbox->y1,
751					pbox->x2 - pbox->x1,
752					pbox->y2 - pbox->y1);
753	pbox++;
754    }
755    (*uxa_screen->info->done_composite) (pDstPix);
756
757    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
758
759    if (localSrc != pSrc)
760	FreePicture (localSrc, 0);
761    if (localMask && localMask != pMask)
762	FreePicture (localMask, 0);
763
764    return 1;
765}
766
767/**
768 * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of
769 * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
770 * alpha and limited 1-tmu cards.
771 *
772 * From http://anholt.livejournal.com/32058.html:
773 *
774 * The trouble is that component-alpha rendering requires two different sources
775 * for blending: one for the source value to the blender, which is the
776 * per-channel multiplication of source and mask, and one for the source alpha
777 * for multiplying with the destination channels, which is the multiplication
778 * of the source channels by the mask alpha. So the equation for Over is:
779 *
780 * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
781 * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
782 * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
783 * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
784 *
785 * But we can do some simpler operations, right? How about PictOpOutReverse,
786 * which has a source factor of 0 and dest factor of (1 - source alpha). We
787 * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
788 * blenders pretty easily. So we can do a component-alpha OutReverse, which
789 * gets us:
790 *
791 * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
792 * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
793 * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
794 * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
795 *
796 * OK. And if an op doesn't use the source alpha value for the destination
797 * factor, then we can do the channel multiplication in the texture blenders
798 * to get the source value, and ignore the source alpha that we wouldn't use.
799 * We've supported this in the Radeon driver for a long time. An example would
800 * be PictOpAdd, which does:
801 *
802 * dst.A = src.A * mask.A + dst.A
803 * dst.R = src.R * mask.R + dst.R
804 * dst.G = src.G * mask.G + dst.G
805 * dst.B = src.B * mask.B + dst.B
806 *
807 * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
808 * after it, we get:
809 *
810 * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
811 * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
812 * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
813 * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
814 */
815
816static int
817uxa_try_magic_two_pass_composite_helper(CARD8 op,
818				  PicturePtr pSrc,
819				  PicturePtr pMask,
820				  PicturePtr pDst,
821				  INT16 xSrc,
822				  INT16 ySrc,
823				  INT16 xMask,
824				  INT16 yMask,
825				  INT16 xDst,
826				  INT16 yDst,
827				  CARD16 width,
828				  CARD16 height)
829{
830    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
831
832    assert(op == PictOpOver);
833
834    if (uxa_screen->info->check_composite &&
835	(!(*uxa_screen->info->check_composite)(PictOpOutReverse, pSrc, pMask,
836					   pDst) ||
837	 !(*uxa_screen->info->check_composite)(PictOpAdd, pSrc, pMask, pDst)))
838    {
839	return -1;
840    }
841
842    /* Now, we think we should be able to accelerate this operation. First,
843     * composite the destination to be the destination times the source alpha
844     * factors.
845     */
846    uxa_composite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
847		 xDst, yDst, width, height);
848
849    /* Then, add in the source value times the destination alpha factors (1.0).
850     */
851    uxa_composite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
852		 xDst, yDst, width, height);
853
854    return 1;
855}
856
857void
858uxa_composite(CARD8	op,
859	     PicturePtr pSrc,
860	     PicturePtr pMask,
861	     PicturePtr pDst,
862	     INT16	xSrc,
863	     INT16	ySrc,
864	     INT16	xMask,
865	     INT16	yMask,
866	     INT16	xDst,
867	     INT16	yDst,
868	     CARD16	width,
869	     CARD16	height)
870{
871    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
872    int ret = -1;
873    Bool saveSrcRepeat = pSrc->repeat;
874    Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
875    RegionRec region;
876
877    if (uxa_screen->swappedOut)
878	goto fallback;
879
880    if (pSrc->pDrawable == NULL || (pMask && pMask->pDrawable == NULL))
881	goto composite;
882
883    /* Remove repeat in source if useless */
884    if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
885	(xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
886	(ySrc + height) <= pSrc->pDrawable->height)
887	    pSrc->repeat = 0;
888
889    if (!pMask)
890    {
891      if ((op == PictOpSrc &&
892	   ((pSrc->format == pDst->format) ||
893	    (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
894	    (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
895	  (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
896	   pSrc->format == pDst->format &&
897	   (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))
898	{
899	    if (pSrc->pDrawable->width == 1 &&
900		pSrc->pDrawable->height == 1 &&
901		pSrc->repeat)
902	    {
903		ret = uxa_try_driver_solid_fill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
904					    width, height);
905		if (ret == 1)
906		    goto done;
907	    }
908	    else if (pSrc->pDrawable != NULL &&
909		     !pSrc->repeat &&
910		     !pSrc->transform)
911	    {
912		xDst += pDst->pDrawable->x;
913		yDst += pDst->pDrawable->y;
914		xSrc += pSrc->pDrawable->x;
915		ySrc += pSrc->pDrawable->y;
916
917		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
918					       xSrc, ySrc, xMask, yMask, xDst,
919					       yDst, width, height))
920		    goto done;
921
922
923		uxa_copy_n_to_n (pSrc->pDrawable, pDst->pDrawable, NULL,
924			     REGION_RECTS(&region), REGION_NUM_RECTS(&region),
925			     xSrc - xDst, ySrc - yDst,
926			     FALSE, FALSE, 0, NULL);
927		REGION_UNINIT(pDst->pDrawable->pScreen, &region);
928		goto done;
929	    }
930	    else if (pSrc->pDrawable != NULL &&
931		     pSrc->pDrawable->type == DRAWABLE_PIXMAP &&
932		     !pSrc->transform &&
933		     pSrc->repeatType == RepeatNormal)
934	    {
935		DDXPointRec patOrg;
936
937		/* Let's see if the driver can do the repeat in one go */
938		if (uxa_screen->info->prepare_composite && !pSrc->alphaMap &&
939		    !pDst->alphaMap)
940		{
941		    ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc,
942						ySrc, xMask, yMask, xDst, yDst,
943						width, height);
944		    if (ret == 1)
945			goto done;
946		}
947
948		/* Now see if we can use uxa_fill_region_tiled() */
949		xDst += pDst->pDrawable->x;
950		yDst += pDst->pDrawable->y;
951		xSrc += pSrc->pDrawable->x;
952		ySrc += pSrc->pDrawable->y;
953
954		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst, xSrc,
955					       ySrc, xMask, yMask, xDst, yDst,
956					       width, height))
957		    goto done;
958
959		/* pattern origin is the point in the destination drawable
960		 * corresponding to (0,0) in the source */
961		patOrg.x = xDst - xSrc;
962		patOrg.y = yDst - ySrc;
963
964		ret = uxa_fill_region_tiled(pDst->pDrawable, &region,
965					 (PixmapPtr)pSrc->pDrawable,
966					 &patOrg, FB_ALLONES, GXcopy);
967
968		REGION_UNINIT(pDst->pDrawable->pScreen, &region);
969
970		if (ret)
971		    goto done;
972	    }
973	}
974    }
975
976composite:
977    /* Remove repeat in mask if useless */
978    if (pMask && pMask->repeat && !pMask->transform && pMask->pDrawable &&
979	xMask >= 0 && (xMask + width) <= pMask->pDrawable->width &&
980	yMask >= 0 && (yMask + height) <= pMask->pDrawable->height)
981	    pMask->repeat = 0;
982
983    if (uxa_screen->info->prepare_composite &&
984	!pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
985    {
986	Bool isSrcSolid;
987
988	ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask,
989				    yMask, xDst, yDst, width, height);
990	if (ret == 1)
991	    goto done;
992
993	/* For generic masks and solid src pictures, mach64 can do Over in two
994	 * passes, similar to the component-alpha case.
995	 */
996	isSrcSolid = pSrc->pDrawable &&
997		     pSrc->pDrawable->width == 1 &&
998		     pSrc->pDrawable->height == 1 &&
999		     pSrc->repeat;
1000
1001	/* If we couldn't do the Composite in a single pass, and it was a
1002	 * component-alpha Over, see if we can do it in two passes with
1003	 * an OutReverse and then an Add.
1004	 */
1005	if (ret == -1 && op == PictOpOver && pMask &&
1006	    (pMask->componentAlpha || isSrcSolid)) {
1007	    ret = uxa_try_magic_two_pass_composite_helper(op, pSrc, pMask, pDst,
1008						    xSrc, ySrc,
1009						    xMask, yMask, xDst, yDst,
1010						    width, height);
1011	    if (ret == 1)
1012		goto done;
1013	}
1014    }
1015
1016fallback:
1017    if (uxa_screen->fallback_debug)
1018	uxa_print_composite_fallback (op, pSrc, pMask, pDst);
1019
1020    uxa_check_composite (op, pSrc, pMask, pDst, xSrc, ySrc,
1021		      xMask, yMask, xDst, yDst, width, height);
1022
1023done:
1024    pSrc->repeat = saveSrcRepeat;
1025    if (pMask)
1026	pMask->repeat = saveMaskRepeat;
1027}
1028#endif
1029
1030/**
1031 * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead
1032 * of PolyFillRect to initialize the pixmap after creating it, to prevent
1033 * the pixmap from being migrated.
1034 *
1035 * See the comments about uxa_trapezoids and uxa_triangles.
1036 */
1037static PicturePtr
1038uxa_create_alpha_picture (ScreenPtr     pScreen,
1039                       PicturePtr    pDst,
1040                       PictFormatPtr pPictFormat,
1041                       CARD16        width,
1042                       CARD16        height)
1043{
1044    PixmapPtr	    pPixmap;
1045    PicturePtr	    pPicture;
1046    int		    error;
1047
1048    if (width > 32767 || height > 32767)
1049	return 0;
1050
1051    if (!pPictFormat)
1052    {
1053	if (pDst->polyEdge == PolyEdgeSharp)
1054	    pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
1055	else
1056	    pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
1057	if (!pPictFormat)
1058	    return 0;
1059    }
1060
1061    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
1062					pPictFormat->depth,
1063					UXA_CREATE_PIXMAP_FOR_MAP);
1064    if (!pPixmap)
1065	return 0;
1066    pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat,
1067			      0, 0, serverClient, &error);
1068    (*pScreen->DestroyPixmap) (pPixmap);
1069    return pPicture;
1070}
1071
1072/**
1073 * uxa_trapezoids is essentially a copy of miTrapezoids that uses
1074 * uxa_create_alpha_picture instead of miCreateAlphaPicture.
1075 *
1076 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
1077 * to initialize the contents after creating the pixmap, which
1078 * causes the pixmap to be moved in for acceleration. The subsequent
1079 * call to RasterizeTrapezoid won't be accelerated however, which
1080 * forces the pixmap to be moved out again.
1081 *
1082 * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect
1083 * to initialize the contents.
1084 */
1085void
1086uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1087               PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1088               int ntrap, xTrapezoid *traps)
1089{
1090    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
1091    PictureScreenPtr    ps = GetPictureScreen(pScreen);
1092    BoxRec		bounds;
1093    Bool		direct = op == PictOpAdd && miIsSolidAlpha (pSrc);
1094
1095    if (maskFormat || direct) {
1096	miTrapezoidBounds (ntrap, traps, &bounds);
1097
1098	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1099	    return;
1100    }
1101
1102    /*
1103     * Check for solid alpha add
1104     */
1105    if (direct)
1106    {
1107	DrawablePtr pDraw = pDst->pDrawable;
1108	PixmapPtr pixmap = uxa_get_drawable_pixmap (pDraw);
1109	int xoff, yoff;
1110
1111	uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff);
1112
1113	xoff += pDraw->x;
1114	yoff += pDraw->y;
1115
1116	if (uxa_prepare_access(pDraw, UXA_ACCESS_RW))
1117	{
1118	    for (; ntrap; ntrap--, traps++)
1119		(*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
1120	    uxa_finish_access(pDraw);
1121	}
1122    }
1123    else if (maskFormat)
1124    {
1125	PicturePtr	pPicture;
1126	INT16		xDst, yDst;
1127	INT16		xRel, yRel;
1128	int		width, height;
1129	pixman_image_t	*image;
1130	pixman_format_code_t format;
1131
1132	xDst = traps[0].left.p1.x >> 16;
1133	yDst = traps[0].left.p1.y >> 16;
1134
1135	width = bounds.x2 - bounds.x1;
1136	height = bounds.y2 - bounds.y1;
1137
1138	format = maskFormat->format | (BitsPerPixel (maskFormat->depth) << 24);
1139	image = pixman_image_create_bits (format, width, height, NULL, 0);
1140	if (!image)
1141	    return;
1142
1143	for (; ntrap; ntrap--, traps++)
1144	    pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *) traps,
1145					-bounds.x1, -bounds.y1);
1146
1147	pPicture = uxa_picture_from_pixman_image (pScreen, image, format);
1148	pixman_image_unref (image);
1149	if (!pPicture)
1150	    return;
1151
1152	xRel = bounds.x1 + xSrc - xDst;
1153	yRel = bounds.y1 + ySrc - yDst;
1154	CompositePicture (op, pSrc, pPicture, pDst,
1155			  xRel, yRel, 0, 0, bounds.x1, bounds.y1,
1156			  bounds.x2 - bounds.x1,
1157			  bounds.y2 - bounds.y1);
1158	FreePicture (pPicture, 0);
1159    }
1160    else
1161    {
1162	if (pDst->polyEdge == PolyEdgeSharp)
1163	    maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
1164	else
1165	    maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
1166	for (; ntrap; ntrap--, traps++)
1167	    uxa_trapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
1168    }
1169}
1170
1171/**
1172 * uxa_triangles is essentially a copy of miTriangles that uses
1173 * uxa_create_alpha_picture instead of miCreateAlphaPicture.
1174 *
1175 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
1176 * to initialize the contents after creating the pixmap, which
1177 * causes the pixmap to be moved in for acceleration. The subsequent
1178 * call to AddTriangles won't be accelerated however, which forces the pixmap
1179 * to be moved out again.
1180 *
1181 * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect
1182 * to initialize the contents.
1183 */
1184void
1185uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1186	      PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1187	      int ntri, xTriangle *tris)
1188{
1189    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
1190    PictureScreenPtr    ps = GetPictureScreen(pScreen);
1191    BoxRec		bounds;
1192    Bool		direct = op == PictOpAdd && miIsSolidAlpha (pSrc);
1193
1194    if (maskFormat || direct) {
1195	miTriangleBounds (ntri, tris, &bounds);
1196
1197	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1198	    return;
1199    }
1200
1201    /*
1202     * Check for solid alpha add
1203     */
1204    if (direct)
1205    {
1206	DrawablePtr pDraw = pDst->pDrawable;
1207	if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
1208	    (*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
1209	    uxa_finish_access(pDraw);
1210	}
1211    }
1212    else if (maskFormat)
1213    {
1214	PicturePtr	pPicture;
1215	INT16		xDst, yDst;
1216	INT16		xRel, yRel;
1217	int width = bounds.x2 - bounds.x1;
1218	int height = bounds.y2 - bounds.y1;
1219	GCPtr pGC;
1220	xRectangle rect;
1221
1222	xDst = tris[0].p1.x >> 16;
1223	yDst = tris[0].p1.y >> 16;
1224
1225	pPicture = uxa_create_alpha_picture (pScreen, pDst, maskFormat,
1226					     width, height);
1227	if (!pPicture)
1228	    return;
1229
1230	/* Clear the alpha picture to 0. */
1231	pGC = GetScratchGC (pPicture->pDrawable->depth, pScreen);
1232	if (!pGC) {
1233	    FreePicture (pPicture, 0);
1234	    return;
1235	}
1236	ValidateGC (pPicture->pDrawable, pGC);
1237	rect.x = 0;
1238	rect.y = 0;
1239	rect.width = width;
1240	rect.height = height;
1241	uxa_check_poly_fill_rect (pPicture->pDrawable, pGC, 1, &rect);
1242	FreeScratchGC (pGC);
1243
1244	if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) {
1245	    (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
1246	    uxa_finish_access(pPicture->pDrawable);
1247	}
1248
1249	xRel = bounds.x1 + xSrc - xDst;
1250	yRel = bounds.y1 + ySrc - yDst;
1251	CompositePicture (op, pSrc, pPicture, pDst,
1252			  xRel, yRel, 0, 0, bounds.x1, bounds.y1,
1253			  bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
1254	FreePicture (pPicture, 0);
1255    }
1256    else
1257    {
1258	if (pDst->polyEdge == PolyEdgeSharp)
1259	    maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
1260	else
1261	    maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
1262
1263	for (; ntri; ntri--, tris++)
1264	    uxa_triangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
1265    }
1266}
1267