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