uxa-render.c revision 03b705cf
103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 2001 Keith Packard
303b705cfSriastradh *
403b705cfSriastradh * Partly based on code that is Copyright © The XFree86 Project Inc.
503b705cfSriastradh *
603b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its
703b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that
803b705cfSriastradh * the above copyright notice appear in all copies and that both that
903b705cfSriastradh * copyright notice and this permission notice appear in supporting
1003b705cfSriastradh * documentation, and that the name of Keith Packard not be used in
1103b705cfSriastradh * advertising or publicity pertaining to distribution of the software without
1203b705cfSriastradh * specific, written prior permission.  Keith Packard makes no
1303b705cfSriastradh * representations about the suitability of this software for any purpose.  It
1403b705cfSriastradh * is provided "as is" without express or implied warranty.
1503b705cfSriastradh *
1603b705cfSriastradh * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1703b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1803b705cfSriastradh * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1903b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2003b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2103b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2203b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE.
2303b705cfSriastradh */
2403b705cfSriastradh
2503b705cfSriastradh#ifdef HAVE_DIX_CONFIG_H
2603b705cfSriastradh#include <dix-config.h>
2703b705cfSriastradh#endif
2803b705cfSriastradh
2903b705cfSriastradh#include <stdlib.h>
3003b705cfSriastradh
3103b705cfSriastradh#include "uxa-priv.h"
3203b705cfSriastradh#include "uxa-glamor.h"
3303b705cfSriastradh#include <xorgVersion.h>
3403b705cfSriastradh
3503b705cfSriastradh#ifdef RENDER
3603b705cfSriastradh#include "mipict.h"
3703b705cfSriastradh
3803b705cfSriastradh/* Note: when using glamor we can not fail through to the ordinary UXA
3903b705cfSriastradh * code paths, as glamor keeps an internal texture which will become
4003b705cfSriastradh * inconsistent with the original bo. (The texture is replaced whenever
4103b705cfSriastradh * the format changes, e.g. switching between xRGB and ARGB, for which mesa
4203b705cfSriastradh * will allocate its own bo.)
4303b705cfSriastradh *
4403b705cfSriastradh * Ergo it is unsafe to fall through to the original backend operations if
4503b705cfSriastradh * glamor is enabled.
4603b705cfSriastradh *
4703b705cfSriastradh * XXX This has some serious implications for mixing Render, DRI, scanout...
4803b705cfSriastradh */
4903b705cfSriastradh
5003b705cfSriastradhstatic void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string,
5103b705cfSriastradh					     int n)
5203b705cfSriastradh{
5303b705cfSriastradh	char format[20];
5403b705cfSriastradh	char size[20];
5503b705cfSriastradh	char loc;
5603b705cfSriastradh
5703b705cfSriastradh	if (!pict) {
5803b705cfSriastradh		snprintf(string, n, "None");
5903b705cfSriastradh		return;
6003b705cfSriastradh	}
6103b705cfSriastradh
6203b705cfSriastradh	if (pict->pDrawable == NULL) {
6303b705cfSriastradh		snprintf(string, n, "source-only");
6403b705cfSriastradh		return;
6503b705cfSriastradh	}
6603b705cfSriastradh
6703b705cfSriastradh	switch (pict->format) {
6803b705cfSriastradh	case PICT_a8r8g8b8:
6903b705cfSriastradh		snprintf(format, 20, "ARGB8888");
7003b705cfSriastradh		break;
7103b705cfSriastradh	case PICT_x8r8g8b8:
7203b705cfSriastradh		snprintf(format, 20, "XRGB8888");
7303b705cfSriastradh		break;
7403b705cfSriastradh	case PICT_r5g6b5:
7503b705cfSriastradh		snprintf(format, 20, "RGB565  ");
7603b705cfSriastradh		break;
7703b705cfSriastradh	case PICT_x1r5g5b5:
7803b705cfSriastradh		snprintf(format, 20, "RGB555  ");
7903b705cfSriastradh		break;
8003b705cfSriastradh	case PICT_a8:
8103b705cfSriastradh		snprintf(format, 20, "A8      ");
8203b705cfSriastradh		break;
8303b705cfSriastradh	case PICT_a1:
8403b705cfSriastradh		snprintf(format, 20, "A1      ");
8503b705cfSriastradh		break;
8603b705cfSriastradh	default:
8703b705cfSriastradh		snprintf(format, 20, "0x%x", (int)pict->format);
8803b705cfSriastradh		break;
8903b705cfSriastradh	}
9003b705cfSriastradh
9103b705cfSriastradh	loc = uxa_drawable_is_offscreen(pict->pDrawable) ? 's' : 'm';
9203b705cfSriastradh
9303b705cfSriastradh	snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
9403b705cfSriastradh		 pict->pDrawable->height, pict->repeat ? " R" : "");
9503b705cfSriastradh
9603b705cfSriastradh	snprintf(string, n, "%p:%c fmt %s (%s)%s",
9703b705cfSriastradh		 pict->pDrawable, loc, format, size,
9803b705cfSriastradh		 pict->alphaMap ? " with alpha map" :"");
9903b705cfSriastradh}
10003b705cfSriastradh
10103b705cfSriastradhstatic const char *
10203b705cfSriastradhop_to_string(CARD8 op)
10303b705cfSriastradh{
10403b705cfSriastradh    switch (op) {
10503b705cfSriastradh#define C(x) case PictOp##x: return #x
10603b705cfSriastradh	C(Clear);
10703b705cfSriastradh	C(Src);
10803b705cfSriastradh	C(Dst);
10903b705cfSriastradh	C(Over);
11003b705cfSriastradh	C(OverReverse);
11103b705cfSriastradh	C(In);
11203b705cfSriastradh	C(InReverse);
11303b705cfSriastradh	C(Out);
11403b705cfSriastradh	C(OutReverse);
11503b705cfSriastradh	C(Atop);
11603b705cfSriastradh	C(AtopReverse);
11703b705cfSriastradh	C(Xor);
11803b705cfSriastradh	C(Add);
11903b705cfSriastradh	C(Saturate);
12003b705cfSriastradh
12103b705cfSriastradh	/*
12203b705cfSriastradh	 * Operators only available in version 0.2
12303b705cfSriastradh	 */
12403b705cfSriastradh#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 2
12503b705cfSriastradh	C(DisjointClear);
12603b705cfSriastradh	C(DisjointSrc);
12703b705cfSriastradh	C(DisjointDst);
12803b705cfSriastradh	C(DisjointOver);
12903b705cfSriastradh	C(DisjointOverReverse);
13003b705cfSriastradh	C(DisjointIn);
13103b705cfSriastradh	C(DisjointInReverse);
13203b705cfSriastradh	C(DisjointOut);
13303b705cfSriastradh	C(DisjointOutReverse);
13403b705cfSriastradh	C(DisjointAtop);
13503b705cfSriastradh	C(DisjointAtopReverse);
13603b705cfSriastradh	C(DisjointXor);
13703b705cfSriastradh
13803b705cfSriastradh	C(ConjointClear);
13903b705cfSriastradh	C(ConjointSrc);
14003b705cfSriastradh	C(ConjointDst);
14103b705cfSriastradh	C(ConjointOver);
14203b705cfSriastradh	C(ConjointOverReverse);
14303b705cfSriastradh	C(ConjointIn);
14403b705cfSriastradh	C(ConjointInReverse);
14503b705cfSriastradh	C(ConjointOut);
14603b705cfSriastradh	C(ConjointOutReverse);
14703b705cfSriastradh	C(ConjointAtop);
14803b705cfSriastradh	C(ConjointAtopReverse);
14903b705cfSriastradh	C(ConjointXor);
15003b705cfSriastradh#endif
15103b705cfSriastradh
15203b705cfSriastradh	/*
15303b705cfSriastradh	 * Operators only available in version 0.11
15403b705cfSriastradh	 */
15503b705cfSriastradh#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 11
15603b705cfSriastradh	C(Multiply);
15703b705cfSriastradh	C(Screen);
15803b705cfSriastradh	C(Overlay);
15903b705cfSriastradh	C(Darken);
16003b705cfSriastradh	C(Lighten);
16103b705cfSriastradh	C(ColorDodge);
16203b705cfSriastradh	C(ColorBurn);
16303b705cfSriastradh	C(HardLight);
16403b705cfSriastradh	C(SoftLight);
16503b705cfSriastradh	C(Difference);
16603b705cfSriastradh	C(Exclusion);
16703b705cfSriastradh	C(HSLHue);
16803b705cfSriastradh	C(HSLSaturation);
16903b705cfSriastradh	C(HSLColor);
17003b705cfSriastradh	C(HSLLuminosity);
17103b705cfSriastradh#endif
17203b705cfSriastradh    default: return "garbage";
17303b705cfSriastradh#undef C
17403b705cfSriastradh    }
17503b705cfSriastradh}
17603b705cfSriastradh
17703b705cfSriastradhstatic void
17803b705cfSriastradhuxa_print_composite_fallback(const char *func, CARD8 op,
17903b705cfSriastradh			     PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst)
18003b705cfSriastradh{
18103b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
18203b705cfSriastradh	char srcdesc[40], maskdesc[40], dstdesc[40];
18303b705cfSriastradh
18403b705cfSriastradh	if (! uxa_screen->fallback_debug)
18503b705cfSriastradh		return;
18603b705cfSriastradh
18703b705cfSriastradh	/* Limit the noise if fallbacks are expected. */
18803b705cfSriastradh	if (uxa_screen->force_fallback)
18903b705cfSriastradh		return;
19003b705cfSriastradh
19103b705cfSriastradh	uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40);
19203b705cfSriastradh	uxa_composite_fallback_pict_desc(pMask, maskdesc, 40);
19303b705cfSriastradh	uxa_composite_fallback_pict_desc(pDst, dstdesc, 40);
19403b705cfSriastradh
19503b705cfSriastradh	ErrorF("Composite fallback at %s:\n"
19603b705cfSriastradh	       "  op   %s, \n"
19703b705cfSriastradh	       "  src  %s, \n"
19803b705cfSriastradh	       "  mask %s, \n"
19903b705cfSriastradh	       "  dst  %s, \n",
20003b705cfSriastradh	       func, op_to_string (op), srcdesc, maskdesc, dstdesc);
20103b705cfSriastradh}
20203b705cfSriastradh
20303b705cfSriastradhBool uxa_op_reads_destination(CARD8 op)
20403b705cfSriastradh{
20503b705cfSriastradh	/* FALSE (does not read destination) is the list of ops in the protocol
20603b705cfSriastradh	 * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
20703b705cfSriastradh	 * That's just Clear and Src.  ReduceCompositeOp() will already have
20803b705cfSriastradh	 * converted con/disjoint clear/src to Clear or Src.
20903b705cfSriastradh	 */
21003b705cfSriastradh	switch (op) {
21103b705cfSriastradh	case PictOpClear:
21203b705cfSriastradh	case PictOpSrc:
21303b705cfSriastradh		return FALSE;
21403b705cfSriastradh	default:
21503b705cfSriastradh		return TRUE;
21603b705cfSriastradh	}
21703b705cfSriastradh}
21803b705cfSriastradh
21903b705cfSriastradhstatic Bool
22003b705cfSriastradhuxa_get_pixel_from_rgba(CARD32 * pixel,
22103b705cfSriastradh			CARD16 red,
22203b705cfSriastradh			CARD16 green,
22303b705cfSriastradh			CARD16 blue,
22403b705cfSriastradh			CARD16 alpha,
22503b705cfSriastradh			CARD32 format)
22603b705cfSriastradh{
22703b705cfSriastradh	int rbits, bbits, gbits, abits;
22803b705cfSriastradh	int rshift, bshift, gshift, ashift;
22903b705cfSriastradh
23003b705cfSriastradh	rbits = PICT_FORMAT_R(format);
23103b705cfSriastradh	gbits = PICT_FORMAT_G(format);
23203b705cfSriastradh	bbits = PICT_FORMAT_B(format);
23303b705cfSriastradh	abits = PICT_FORMAT_A(format);
23403b705cfSriastradh	if (abits == 0)
23503b705cfSriastradh	    abits = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits);
23603b705cfSriastradh
23703b705cfSriastradh	if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
23803b705cfSriastradh		*pixel = alpha >> (16 - abits);
23903b705cfSriastradh		return TRUE;
24003b705cfSriastradh	}
24103b705cfSriastradh
24203b705cfSriastradh	if (!PICT_FORMAT_COLOR(format))
24303b705cfSriastradh		return FALSE;
24403b705cfSriastradh
24503b705cfSriastradh	if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
24603b705cfSriastradh		bshift = 0;
24703b705cfSriastradh		gshift = bbits;
24803b705cfSriastradh		rshift = gshift + gbits;
24903b705cfSriastradh		ashift = rshift + rbits;
25003b705cfSriastradh	} else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
25103b705cfSriastradh		rshift = 0;
25203b705cfSriastradh		gshift = rbits;
25303b705cfSriastradh		bshift = gshift + gbits;
25403b705cfSriastradh		ashift = bshift + bbits;
25503b705cfSriastradh#if XORG_VERSION_CURRENT >= 10699900
25603b705cfSriastradh	} else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
25703b705cfSriastradh		ashift = 0;
25803b705cfSriastradh		rshift = abits;
25903b705cfSriastradh		gshift = rshift + rbits;
26003b705cfSriastradh		bshift = gshift + gbits;
26103b705cfSriastradh#endif
26203b705cfSriastradh	} else {
26303b705cfSriastradh		return FALSE;
26403b705cfSriastradh	}
26503b705cfSriastradh
26603b705cfSriastradh	*pixel = 0;
26703b705cfSriastradh	*pixel |= (blue  >> (16 - bbits)) << bshift;
26803b705cfSriastradh	*pixel |= (green >> (16 - gbits)) << gshift;
26903b705cfSriastradh	*pixel |= (red   >> (16 - rbits)) << rshift;
27003b705cfSriastradh	*pixel |= (alpha >> (16 - abits)) << ashift;
27103b705cfSriastradh
27203b705cfSriastradh	return TRUE;
27303b705cfSriastradh}
27403b705cfSriastradh
27503b705cfSriastradhBool
27603b705cfSriastradhuxa_get_rgba_from_pixel(CARD32 pixel,
27703b705cfSriastradh			CARD16 * red,
27803b705cfSriastradh			CARD16 * green,
27903b705cfSriastradh			CARD16 * blue,
28003b705cfSriastradh			CARD16 * alpha,
28103b705cfSriastradh			CARD32 format)
28203b705cfSriastradh{
28303b705cfSriastradh	int rbits, bbits, gbits, abits;
28403b705cfSriastradh	int rshift, bshift, gshift, ashift;
28503b705cfSriastradh
28603b705cfSriastradh	rbits = PICT_FORMAT_R(format);
28703b705cfSriastradh	gbits = PICT_FORMAT_G(format);
28803b705cfSriastradh	bbits = PICT_FORMAT_B(format);
28903b705cfSriastradh	abits = PICT_FORMAT_A(format);
29003b705cfSriastradh
29103b705cfSriastradh	if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
29203b705cfSriastradh		rshift = gshift = bshift = ashift = 0;
29303b705cfSriastradh        } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
29403b705cfSriastradh		bshift = 0;
29503b705cfSriastradh		gshift = bbits;
29603b705cfSriastradh		rshift = gshift + gbits;
29703b705cfSriastradh		ashift = rshift + rbits;
29803b705cfSriastradh        } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
29903b705cfSriastradh		rshift = 0;
30003b705cfSriastradh		gshift = rbits;
30103b705cfSriastradh		bshift = gshift + gbits;
30203b705cfSriastradh		ashift = bshift + bbits;
30303b705cfSriastradh#if XORG_VERSION_CURRENT >= 10699900
30403b705cfSriastradh        } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
30503b705cfSriastradh		ashift = 0;
30603b705cfSriastradh		rshift = abits;
30703b705cfSriastradh		if (abits == 0)
30803b705cfSriastradh			rshift = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits);
30903b705cfSriastradh		gshift = rshift + rbits;
31003b705cfSriastradh		bshift = gshift + gbits;
31103b705cfSriastradh#endif
31203b705cfSriastradh	} else {
31303b705cfSriastradh		return FALSE;
31403b705cfSriastradh	}
31503b705cfSriastradh
31603b705cfSriastradh	if (rbits) {
31703b705cfSriastradh		*red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits);
31803b705cfSriastradh		while (rbits < 16) {
31903b705cfSriastradh			*red |= *red >> rbits;
32003b705cfSriastradh			rbits <<= 1;
32103b705cfSriastradh		}
32203b705cfSriastradh	} else
32303b705cfSriastradh		*red = 0;
32403b705cfSriastradh
32503b705cfSriastradh	if (gbits) {
32603b705cfSriastradh		*green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits);
32703b705cfSriastradh		while (gbits < 16) {
32803b705cfSriastradh			*green |= *green >> gbits;
32903b705cfSriastradh			gbits <<= 1;
33003b705cfSriastradh		}
33103b705cfSriastradh	} else
33203b705cfSriastradh		*green = 0;
33303b705cfSriastradh
33403b705cfSriastradh	if (bbits) {
33503b705cfSriastradh		*blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits);
33603b705cfSriastradh		while (bbits < 16) {
33703b705cfSriastradh			*blue |= *blue >> bbits;
33803b705cfSriastradh			bbits <<= 1;
33903b705cfSriastradh		}
34003b705cfSriastradh	} else
34103b705cfSriastradh		*blue = 0;
34203b705cfSriastradh
34303b705cfSriastradh	if (abits) {
34403b705cfSriastradh		*alpha =
34503b705cfSriastradh		    ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits);
34603b705cfSriastradh		while (abits < 16) {
34703b705cfSriastradh			*alpha |= *alpha >> abits;
34803b705cfSriastradh			abits <<= 1;
34903b705cfSriastradh		}
35003b705cfSriastradh	} else
35103b705cfSriastradh		*alpha = 0xffff;
35203b705cfSriastradh
35303b705cfSriastradh	return TRUE;
35403b705cfSriastradh}
35503b705cfSriastradh
35603b705cfSriastradhBool
35703b705cfSriastradhuxa_get_color_for_pixmap (PixmapPtr	 pixmap,
35803b705cfSriastradh			  CARD32	 src_format,
35903b705cfSriastradh			  CARD32	 dst_format,
36003b705cfSriastradh			  CARD32	*pixel)
36103b705cfSriastradh{
36203b705cfSriastradh	CARD16 red, green, blue, alpha;
36303b705cfSriastradh
36403b705cfSriastradh	*pixel = uxa_get_pixmap_first_pixel(pixmap);
36503b705cfSriastradh
36603b705cfSriastradh	if (src_format != dst_format) {
36703b705cfSriastradh	    if (!uxa_get_rgba_from_pixel(*pixel,
36803b705cfSriastradh					 &red, &green, &blue, &alpha,
36903b705cfSriastradh					 src_format))
37003b705cfSriastradh		return FALSE;
37103b705cfSriastradh
37203b705cfSriastradh	    if (!uxa_get_pixel_from_rgba(pixel,
37303b705cfSriastradh					 red, green, blue, alpha,
37403b705cfSriastradh					 dst_format))
37503b705cfSriastradh		return FALSE;
37603b705cfSriastradh	}
37703b705cfSriastradh
37803b705cfSriastradh	return TRUE;
37903b705cfSriastradh}
38003b705cfSriastradh
38103b705cfSriastradhstatic int
38203b705cfSriastradhuxa_try_driver_solid_fill(PicturePtr pSrc,
38303b705cfSriastradh			  PicturePtr pDst,
38403b705cfSriastradh			  INT16 xSrc,
38503b705cfSriastradh			  INT16 ySrc,
38603b705cfSriastradh			  INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
38703b705cfSriastradh{
38803b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
38903b705cfSriastradh	RegionRec region;
39003b705cfSriastradh	BoxPtr pbox;
39103b705cfSriastradh	int nbox;
39203b705cfSriastradh	int dst_off_x, dst_off_y;
39303b705cfSriastradh	PixmapPtr pSrcPix = NULL, pDstPix;
39403b705cfSriastradh	CARD32 pixel;
39503b705cfSriastradh
39603b705cfSriastradh	if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDst->pDrawable, GXcopy, FB_ALLONES))
39703b705cfSriastradh		return -1;
39803b705cfSriastradh
39903b705cfSriastradh	pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
40003b705cfSriastradh	if (!pDstPix)
40103b705cfSriastradh		return -1;
40203b705cfSriastradh
40303b705cfSriastradh	xDst += pDst->pDrawable->x;
40403b705cfSriastradh	yDst += pDst->pDrawable->y;
40503b705cfSriastradh
40603b705cfSriastradh	if (pSrc->pDrawable) {
40703b705cfSriastradh		pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
40803b705cfSriastradh		xSrc += pSrc->pDrawable->x;
40903b705cfSriastradh		ySrc += pSrc->pDrawable->y;
41003b705cfSriastradh	}
41103b705cfSriastradh
41203b705cfSriastradh	if (!miComputeCompositeRegion(&region, pSrc, NULL, pDst,
41303b705cfSriastradh				      xSrc, ySrc, 0, 0, xDst, yDst,
41403b705cfSriastradh				      width, height))
41503b705cfSriastradh		return 1;
41603b705cfSriastradh
41703b705cfSriastradh	if (pSrcPix) {
41803b705cfSriastradh		if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) {
41903b705cfSriastradh			REGION_UNINIT(pDst->pDrawable->pScreen, &region);
42003b705cfSriastradh			return -1;
42103b705cfSriastradh		}
42203b705cfSriastradh	} else {
42303b705cfSriastradh		SourcePict *source = pSrc->pSourcePict;
42403b705cfSriastradh		PictSolidFill *solid = &source->solidFill;
42503b705cfSriastradh
42603b705cfSriastradh		if (source == NULL || source->type != SourcePictTypeSolidFill) {
42703b705cfSriastradh			REGION_UNINIT(pDst->pDrawable->pScreen, &region);
42803b705cfSriastradh			return -1;
42903b705cfSriastradh		}
43003b705cfSriastradh
43103b705cfSriastradh		if (pDst->format == PICT_a8r8g8b8) {
43203b705cfSriastradh			pixel = solid->color;
43303b705cfSriastradh		} else if (pDst->format == PICT_x8r8g8b8) {
43403b705cfSriastradh			pixel = solid->color | 0xff000000;
43503b705cfSriastradh		} else {
43603b705cfSriastradh			CARD16 red, green, blue, alpha;
43703b705cfSriastradh
43803b705cfSriastradh			if (!uxa_get_rgba_from_pixel(solid->color,
43903b705cfSriastradh						     &red, &green, &blue, &alpha,
44003b705cfSriastradh						     PICT_a8r8g8b8) ||
44103b705cfSriastradh			    !uxa_get_pixel_from_rgba(&pixel,
44203b705cfSriastradh						     red, green, blue, alpha,
44303b705cfSriastradh						     pDst->format)) {
44403b705cfSriastradh				REGION_UNINIT(pDst->pDrawable->pScreen, &region);
44503b705cfSriastradh				return -1;
44603b705cfSriastradh			}
44703b705cfSriastradh		}
44803b705cfSriastradh	}
44903b705cfSriastradh
45003b705cfSriastradh	if (!(*uxa_screen->info->prepare_solid)
45103b705cfSriastradh	    (pDstPix, GXcopy, FB_ALLONES, pixel)) {
45203b705cfSriastradh		REGION_UNINIT(pDst->pDrawable->pScreen, &region);
45303b705cfSriastradh		return -1;
45403b705cfSriastradh	}
45503b705cfSriastradh
45603b705cfSriastradh	REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
45703b705cfSriastradh
45803b705cfSriastradh	nbox = REGION_NUM_RECTS(&region);
45903b705cfSriastradh	pbox = REGION_RECTS(&region);
46003b705cfSriastradh
46103b705cfSriastradh	while (nbox--) {
46203b705cfSriastradh		(*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1,
46303b705cfSriastradh					    pbox->x2, pbox->y2);
46403b705cfSriastradh		pbox++;
46503b705cfSriastradh	}
46603b705cfSriastradh
46703b705cfSriastradh	(*uxa_screen->info->done_solid) (pDstPix);
46803b705cfSriastradh
46903b705cfSriastradh	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
47003b705cfSriastradh	return 1;
47103b705cfSriastradh}
47203b705cfSriastradh
47303b705cfSriastradhstatic PicturePtr
47403b705cfSriastradhuxa_picture_for_pixman_format(ScreenPtr screen,
47503b705cfSriastradh			      pixman_format_code_t format,
47603b705cfSriastradh			      int width, int height)
47703b705cfSriastradh{
47803b705cfSriastradh	PicturePtr picture;
47903b705cfSriastradh	PixmapPtr pixmap;
48003b705cfSriastradh	int error;
48103b705cfSriastradh
48203b705cfSriastradh	if (format == PIXMAN_a1)
48303b705cfSriastradh		format = PIXMAN_a8;
48403b705cfSriastradh
48503b705cfSriastradh	/* fill alpha if unset */
48603b705cfSriastradh	if (PIXMAN_FORMAT_A(format) == 0)
48703b705cfSriastradh	    format = PIXMAN_a8r8g8b8;
48803b705cfSriastradh
48903b705cfSriastradh	pixmap = screen->CreatePixmap(screen, width, height,
49003b705cfSriastradh					PIXMAN_FORMAT_DEPTH(format),
49103b705cfSriastradh					UXA_CREATE_PIXMAP_FOR_MAP);
49203b705cfSriastradh	if (!pixmap)
49303b705cfSriastradh		return 0;
49403b705cfSriastradh
49503b705cfSriastradh	if (!uxa_pixmap_is_offscreen(pixmap)) {
49603b705cfSriastradh		screen->DestroyPixmap(pixmap);
49703b705cfSriastradh		return 0;
49803b705cfSriastradh	}
49903b705cfSriastradh
50003b705cfSriastradh	picture = CreatePicture(0, &pixmap->drawable,
50103b705cfSriastradh				PictureMatchFormat(screen,
50203b705cfSriastradh						   PIXMAN_FORMAT_DEPTH(format),
50303b705cfSriastradh						   format),
50403b705cfSriastradh				0, 0, serverClient, &error);
50503b705cfSriastradh	screen->DestroyPixmap(pixmap);
50603b705cfSriastradh	if (!picture)
50703b705cfSriastradh		return 0;
50803b705cfSriastradh
50903b705cfSriastradh	ValidatePicture(picture);
51003b705cfSriastradh
51103b705cfSriastradh	return picture;
51203b705cfSriastradh}
51303b705cfSriastradh
51403b705cfSriastradhstatic PicturePtr
51503b705cfSriastradhuxa_picture_from_pixman_image(ScreenPtr screen,
51603b705cfSriastradh			      pixman_image_t * image,
51703b705cfSriastradh			      pixman_format_code_t format)
51803b705cfSriastradh{
51903b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
52003b705cfSriastradh	PicturePtr picture;
52103b705cfSriastradh	PixmapPtr pixmap;
52203b705cfSriastradh	int width, height;
52303b705cfSriastradh
52403b705cfSriastradh	width = pixman_image_get_width(image);
52503b705cfSriastradh	height = pixman_image_get_height(image);
52603b705cfSriastradh
52703b705cfSriastradh	picture = uxa_picture_for_pixman_format(screen, format,
52803b705cfSriastradh						width, height);
52903b705cfSriastradh	if (!picture)
53003b705cfSriastradh		return 0;
53103b705cfSriastradh
53203b705cfSriastradh	if (uxa_screen->info->put_image &&
53303b705cfSriastradh	    ((picture->pDrawable->depth << 24) | picture->format) == format &&
53403b705cfSriastradh	    uxa_screen->info->put_image((PixmapPtr)picture->pDrawable,
53503b705cfSriastradh					0, 0,
53603b705cfSriastradh					width, height,
53703b705cfSriastradh					(char *)pixman_image_get_data(image),
53803b705cfSriastradh					pixman_image_get_stride(image)))
53903b705cfSriastradh		return picture;
54003b705cfSriastradh
54103b705cfSriastradh	pixmap = GetScratchPixmapHeader(screen, width, height,
54203b705cfSriastradh					PIXMAN_FORMAT_DEPTH(format),
54303b705cfSriastradh					PIXMAN_FORMAT_BPP(format),
54403b705cfSriastradh					pixman_image_get_stride(image),
54503b705cfSriastradh					pixman_image_get_data(image));
54603b705cfSriastradh	if (!pixmap) {
54703b705cfSriastradh		FreePicture(picture, 0);
54803b705cfSriastradh		return 0;
54903b705cfSriastradh	}
55003b705cfSriastradh
55103b705cfSriastradh	if (((picture->pDrawable->depth << 24) | picture->format) == format) {
55203b705cfSriastradh		GCPtr gc;
55303b705cfSriastradh
55403b705cfSriastradh		gc = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), screen);
55503b705cfSriastradh		if (!gc) {
55603b705cfSriastradh			FreeScratchPixmapHeader(pixmap);
55703b705cfSriastradh			FreePicture(picture, 0);
55803b705cfSriastradh			return 0;
55903b705cfSriastradh		}
56003b705cfSriastradh		ValidateGC(picture->pDrawable, gc);
56103b705cfSriastradh
56203b705cfSriastradh		(*gc->ops->CopyArea) (&pixmap->drawable, picture->pDrawable,
56303b705cfSriastradh				      gc, 0, 0, width, height, 0, 0);
56403b705cfSriastradh
56503b705cfSriastradh		FreeScratchGC(gc);
56603b705cfSriastradh	} else {
56703b705cfSriastradh		PicturePtr src;
56803b705cfSriastradh		int error;
56903b705cfSriastradh
57003b705cfSriastradh		src = CreatePicture(0, &pixmap->drawable,
57103b705cfSriastradh				    PictureMatchFormat(screen,
57203b705cfSriastradh						       PIXMAN_FORMAT_DEPTH(format),
57303b705cfSriastradh						       format),
57403b705cfSriastradh				    0, 0, serverClient, &error);
57503b705cfSriastradh		if (!src) {
57603b705cfSriastradh			FreeScratchPixmapHeader(pixmap);
57703b705cfSriastradh			FreePicture(picture, 0);
57803b705cfSriastradh			return 0;
57903b705cfSriastradh		}
58003b705cfSriastradh		ValidatePicture(src);
58103b705cfSriastradh
58203b705cfSriastradh		if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) {
58303b705cfSriastradh			fbComposite(PictOpSrc, src, NULL, picture,
58403b705cfSriastradh				    0, 0, 0, 0, 0, 0, width, height);
58503b705cfSriastradh			uxa_picture_finish_access(picture, UXA_ACCESS_RW);
58603b705cfSriastradh		}
58703b705cfSriastradh
58803b705cfSriastradh		FreePicture(src, 0);
58903b705cfSriastradh	}
59003b705cfSriastradh	FreeScratchPixmapHeader(pixmap);
59103b705cfSriastradh
59203b705cfSriastradh	return picture;
59303b705cfSriastradh}
59403b705cfSriastradh
59503b705cfSriastradhstatic PicturePtr
59603b705cfSriastradhuxa_create_solid(ScreenPtr screen, uint32_t color)
59703b705cfSriastradh{
59803b705cfSriastradh	PixmapPtr pixmap;
59903b705cfSriastradh	PicturePtr picture;
60003b705cfSriastradh	XID repeat = RepeatNormal;
60103b705cfSriastradh	int error = 0;
60203b705cfSriastradh
60303b705cfSriastradh	pixmap = (*screen->CreatePixmap)(screen, 1, 1, 32,
60403b705cfSriastradh					 UXA_CREATE_PIXMAP_FOR_MAP);
60503b705cfSriastradh	if (!pixmap)
60603b705cfSriastradh		return 0;
60703b705cfSriastradh
60803b705cfSriastradh	if (!uxa_prepare_access((DrawablePtr)pixmap, UXA_ACCESS_RW)) {
60903b705cfSriastradh		(*screen->DestroyPixmap)(pixmap);
61003b705cfSriastradh		return 0;
61103b705cfSriastradh	}
61203b705cfSriastradh	*((uint32_t *)pixmap->devPrivate.ptr) = color;
61303b705cfSriastradh	uxa_finish_access((DrawablePtr)pixmap, UXA_ACCESS_RW);
61403b705cfSriastradh
61503b705cfSriastradh	picture = CreatePicture(0, &pixmap->drawable,
61603b705cfSriastradh				PictureMatchFormat(screen, 32, PICT_a8r8g8b8),
61703b705cfSriastradh				CPRepeat, &repeat, serverClient, &error);
61803b705cfSriastradh	(*screen->DestroyPixmap)(pixmap);
61903b705cfSriastradh
62003b705cfSriastradh	return picture;
62103b705cfSriastradh}
62203b705cfSriastradh
62303b705cfSriastradhstatic PicturePtr
62403b705cfSriastradhuxa_solid_clear(ScreenPtr screen)
62503b705cfSriastradh{
62603b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
62703b705cfSriastradh	PicturePtr picture;
62803b705cfSriastradh
62903b705cfSriastradh	if (!uxa_screen->solid_clear) {
63003b705cfSriastradh		uxa_screen->solid_clear = uxa_create_solid(screen, 0);
63103b705cfSriastradh		if (!uxa_screen->solid_clear)
63203b705cfSriastradh			return 0;
63303b705cfSriastradh	}
63403b705cfSriastradh	picture = uxa_screen->solid_clear;
63503b705cfSriastradh	return picture;
63603b705cfSriastradh}
63703b705cfSriastradh
63803b705cfSriastradhPicturePtr
63903b705cfSriastradhuxa_acquire_solid(ScreenPtr screen, SourcePict *source)
64003b705cfSriastradh{
64103b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
64203b705cfSriastradh	PictSolidFill *solid = &source->solidFill;
64303b705cfSriastradh	PicturePtr picture;
64403b705cfSriastradh	int i;
64503b705cfSriastradh
64603b705cfSriastradh	if ((solid->color >> 24) == 0) {
64703b705cfSriastradh		picture = uxa_solid_clear(screen);
64803b705cfSriastradh		if (!picture)
64903b705cfSriastradh		    return 0;
65003b705cfSriastradh
65103b705cfSriastradh		goto DONE;
65203b705cfSriastradh	} else if (solid->color == 0xff000000) {
65303b705cfSriastradh		if (!uxa_screen->solid_black) {
65403b705cfSriastradh			uxa_screen->solid_black = uxa_create_solid(screen, 0xff000000);
65503b705cfSriastradh			if (!uxa_screen->solid_black)
65603b705cfSriastradh				return 0;
65703b705cfSriastradh		}
65803b705cfSriastradh		picture = uxa_screen->solid_black;
65903b705cfSriastradh		goto DONE;
66003b705cfSriastradh	} else if (solid->color == 0xffffffff) {
66103b705cfSriastradh		if (!uxa_screen->solid_white) {
66203b705cfSriastradh			uxa_screen->solid_white = uxa_create_solid(screen, 0xffffffff);
66303b705cfSriastradh			if (!uxa_screen->solid_white)
66403b705cfSriastradh				return 0;
66503b705cfSriastradh		}
66603b705cfSriastradh		picture = uxa_screen->solid_white;
66703b705cfSriastradh		goto DONE;
66803b705cfSriastradh	}
66903b705cfSriastradh
67003b705cfSriastradh	for (i = 0; i < uxa_screen->solid_cache_size; i++) {
67103b705cfSriastradh		if (uxa_screen->solid_cache[i].color == solid->color) {
67203b705cfSriastradh			picture = uxa_screen->solid_cache[i].picture;
67303b705cfSriastradh			goto DONE;
67403b705cfSriastradh		}
67503b705cfSriastradh	}
67603b705cfSriastradh
67703b705cfSriastradh	picture = uxa_create_solid(screen, solid->color);
67803b705cfSriastradh	if (!picture)
67903b705cfSriastradh		return 0;
68003b705cfSriastradh
68103b705cfSriastradh	if (uxa_screen->solid_cache_size == UXA_NUM_SOLID_CACHE) {
68203b705cfSriastradh		i = rand() % UXA_NUM_SOLID_CACHE;
68303b705cfSriastradh		FreePicture(uxa_screen->solid_cache[i].picture, 0);
68403b705cfSriastradh	} else
68503b705cfSriastradh		uxa_screen->solid_cache_size++;
68603b705cfSriastradh
68703b705cfSriastradh	uxa_screen->solid_cache[i].picture = picture;
68803b705cfSriastradh	uxa_screen->solid_cache[i].color = solid->color;
68903b705cfSriastradh
69003b705cfSriastradhDONE:
69103b705cfSriastradh	picture->refcnt++;
69203b705cfSriastradh	return picture;
69303b705cfSriastradh}
69403b705cfSriastradh
69503b705cfSriastradhPicturePtr
69603b705cfSriastradhuxa_acquire_pattern(ScreenPtr pScreen,
69703b705cfSriastradh		    PicturePtr pSrc,
69803b705cfSriastradh		    pixman_format_code_t format,
69903b705cfSriastradh		    INT16 x, INT16 y, CARD16 width, CARD16 height)
70003b705cfSriastradh{
70103b705cfSriastradh	PicturePtr pDst;
70203b705cfSriastradh
70303b705cfSriastradh	if (pSrc->pSourcePict) {
70403b705cfSriastradh		SourcePict *source = pSrc->pSourcePict;
70503b705cfSriastradh		if (source->type == SourcePictTypeSolidFill)
70603b705cfSriastradh			return uxa_acquire_solid (pScreen, source);
70703b705cfSriastradh	}
70803b705cfSriastradh
70903b705cfSriastradh	pDst = uxa_picture_for_pixman_format(pScreen, format, width, height);
71003b705cfSriastradh	if (!pDst)
71103b705cfSriastradh		return 0;
71203b705cfSriastradh
71303b705cfSriastradh	if (uxa_picture_prepare_access(pDst, UXA_ACCESS_RW)) {
71403b705cfSriastradh		fbComposite(PictOpSrc, pSrc, NULL, pDst,
71503b705cfSriastradh			    x, y, 0, 0, 0, 0, width, height);
71603b705cfSriastradh		uxa_picture_finish_access(pDst, UXA_ACCESS_RW);
71703b705cfSriastradh		return pDst;
71803b705cfSriastradh	} else {
71903b705cfSriastradh		FreePicture(pDst, 0);
72003b705cfSriastradh		return 0;
72103b705cfSriastradh	}
72203b705cfSriastradh}
72303b705cfSriastradh
72403b705cfSriastradhstatic Bool
72503b705cfSriastradhtransform_is_integer_translation(PictTransformPtr t, int *tx, int *ty)
72603b705cfSriastradh{
72703b705cfSriastradh	if (t == NULL) {
72803b705cfSriastradh		*tx = *ty = 0;
72903b705cfSriastradh		return TRUE;
73003b705cfSriastradh	}
73103b705cfSriastradh
73203b705cfSriastradh	if (t->matrix[0][0] != IntToxFixed(1) ||
73303b705cfSriastradh	    t->matrix[0][1] != 0 ||
73403b705cfSriastradh	    t->matrix[1][0] != 0 ||
73503b705cfSriastradh	    t->matrix[1][1] != IntToxFixed(1) ||
73603b705cfSriastradh	    t->matrix[2][0] != 0 ||
73703b705cfSriastradh	    t->matrix[2][1] != 0 ||
73803b705cfSriastradh	    t->matrix[2][2] != IntToxFixed(1))
73903b705cfSriastradh		return FALSE;
74003b705cfSriastradh
74103b705cfSriastradh	if (xFixedFrac(t->matrix[0][2]) != 0 ||
74203b705cfSriastradh	    xFixedFrac(t->matrix[1][2]) != 0)
74303b705cfSriastradh		return FALSE;
74403b705cfSriastradh
74503b705cfSriastradh	*tx = xFixedToInt(t->matrix[0][2]);
74603b705cfSriastradh	*ty = xFixedToInt(t->matrix[1][2]);
74703b705cfSriastradh	return TRUE;
74803b705cfSriastradh}
74903b705cfSriastradh
75003b705cfSriastradhstatic PicturePtr
75103b705cfSriastradhuxa_render_picture(ScreenPtr screen,
75203b705cfSriastradh		   PicturePtr src,
75303b705cfSriastradh		   pixman_format_code_t format,
75403b705cfSriastradh		   INT16 x, INT16 y,
75503b705cfSriastradh		   CARD16 width, CARD16 height)
75603b705cfSriastradh{
75703b705cfSriastradh	PicturePtr picture;
75803b705cfSriastradh	int ret = 0;
75903b705cfSriastradh
76003b705cfSriastradh	/* XXX we need a mechanism for the card to choose the fallback format */
76103b705cfSriastradh
76203b705cfSriastradh	/* force alpha channel in case source does not entirely cover the extents */
76303b705cfSriastradh	if (PIXMAN_FORMAT_A(format) == 0)
76403b705cfSriastradh		format = PIXMAN_a8r8g8b8; /* available on all hardware */
76503b705cfSriastradh
76603b705cfSriastradh	picture = uxa_picture_for_pixman_format(screen, format, width, height);
76703b705cfSriastradh	if (!picture)
76803b705cfSriastradh		return 0;
76903b705cfSriastradh
77003b705cfSriastradh	if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) {
77103b705cfSriastradh		if (uxa_picture_prepare_access(src, UXA_ACCESS_RO)) {
77203b705cfSriastradh			ret = 1;
77303b705cfSriastradh			fbComposite(PictOpSrc, src, NULL, picture,
77403b705cfSriastradh				    x, y, 0, 0, 0, 0, width, height);
77503b705cfSriastradh			uxa_picture_finish_access(src, UXA_ACCESS_RO);
77603b705cfSriastradh		}
77703b705cfSriastradh		uxa_picture_finish_access(picture, UXA_ACCESS_RW);
77803b705cfSriastradh	}
77903b705cfSriastradh
78003b705cfSriastradh	if (!ret) {
78103b705cfSriastradh		FreePicture(picture, 0);
78203b705cfSriastradh		return 0;
78303b705cfSriastradh	}
78403b705cfSriastradh
78503b705cfSriastradh	return picture;
78603b705cfSriastradh}
78703b705cfSriastradh
78803b705cfSriastradhstatic int
78903b705cfSriastradhdrawable_contains (DrawablePtr drawable, int x, int y, int w, int h)
79003b705cfSriastradh{
79103b705cfSriastradh	if (x < 0 || y < 0)
79203b705cfSriastradh		return FALSE;
79303b705cfSriastradh
79403b705cfSriastradh	if (x + w > drawable->width)
79503b705cfSriastradh		return FALSE;
79603b705cfSriastradh
79703b705cfSriastradh	if (y + h > drawable->height)
79803b705cfSriastradh		return FALSE;
79903b705cfSriastradh
80003b705cfSriastradh	return TRUE;
80103b705cfSriastradh}
80203b705cfSriastradh
80303b705cfSriastradhPicturePtr
80403b705cfSriastradhuxa_acquire_drawable(ScreenPtr pScreen,
80503b705cfSriastradh		     PicturePtr pSrc,
80603b705cfSriastradh		     INT16 x, INT16 y,
80703b705cfSriastradh		     CARD16 width, CARD16 height,
80803b705cfSriastradh		     INT16 * out_x, INT16 * out_y)
80903b705cfSriastradh{
81003b705cfSriastradh	PixmapPtr pPixmap;
81103b705cfSriastradh	PicturePtr pDst;
81203b705cfSriastradh	int depth, error;
81303b705cfSriastradh	int tx, ty;
81403b705cfSriastradh	GCPtr pGC;
81503b705cfSriastradh
81603b705cfSriastradh	depth = pSrc->pDrawable->depth;
81703b705cfSriastradh	if (!transform_is_integer_translation(pSrc->transform, &tx, &ty) ||
81803b705cfSriastradh	    !drawable_contains(pSrc->pDrawable, x + tx, y + ty, width, height) ||
81903b705cfSriastradh	    depth == 1 ||
82003b705cfSriastradh	    pSrc->filter == PictFilterConvolution) {
82103b705cfSriastradh		/* XXX extract the sample extents and do the transformation on the GPU */
82203b705cfSriastradh		pDst = uxa_render_picture(pScreen, pSrc,
82303b705cfSriastradh					  pSrc->format | (BitsPerPixel(pSrc->pDrawable->depth) << 24),
82403b705cfSriastradh					  x, y, width, height);
82503b705cfSriastradh		if (!pDst)
82603b705cfSriastradh			return 0;
82703b705cfSriastradh
82803b705cfSriastradh		goto done;
82903b705cfSriastradh	} else {
83003b705cfSriastradh		if (width == pSrc->pDrawable->width && height == pSrc->pDrawable->height) {
83103b705cfSriastradh			*out_x = x + pSrc->pDrawable->x;
83203b705cfSriastradh			*out_y = y + pSrc->pDrawable->y;
83303b705cfSriastradh			return pSrc;
83403b705cfSriastradh		}
83503b705cfSriastradh	}
83603b705cfSriastradh
83703b705cfSriastradh	pPixmap = pScreen->CreatePixmap(pScreen,
83803b705cfSriastradh					width, height, depth,
83903b705cfSriastradh					CREATE_PIXMAP_USAGE_SCRATCH);
84003b705cfSriastradh	if (!pPixmap)
84103b705cfSriastradh		return 0;
84203b705cfSriastradh
84303b705cfSriastradh	/* Skip the copy if the result remains in memory and not a bo */
84403b705cfSriastradh	if (!uxa_pixmap_is_offscreen(pPixmap)) {
84503b705cfSriastradh		pScreen->DestroyPixmap(pPixmap);
84603b705cfSriastradh		return 0;
84703b705cfSriastradh	}
84803b705cfSriastradh
84903b705cfSriastradh	pGC = GetScratchGC(depth, pScreen);
85003b705cfSriastradh	if (!pGC) {
85103b705cfSriastradh		pScreen->DestroyPixmap(pPixmap);
85203b705cfSriastradh		return 0;
85303b705cfSriastradh	}
85403b705cfSriastradh
85503b705cfSriastradh	ValidateGC(&pPixmap->drawable, pGC);
85603b705cfSriastradh	pGC->ops->CopyArea(pSrc->pDrawable, &pPixmap->drawable, pGC,
85703b705cfSriastradh			   x + tx, y + ty, width, height, 0, 0);
85803b705cfSriastradh	FreeScratchGC(pGC);
85903b705cfSriastradh
86003b705cfSriastradh	pDst = CreatePicture(0, &pPixmap->drawable,
86103b705cfSriastradh			     PictureMatchFormat(pScreen, depth, pSrc->format),
86203b705cfSriastradh			     0, 0, serverClient, &error);
86303b705cfSriastradh	pScreen->DestroyPixmap(pPixmap);
86403b705cfSriastradh	if (!pDst)
86503b705cfSriastradh		return 0;
86603b705cfSriastradh
86703b705cfSriastradh	ValidatePicture(pDst);
86803b705cfSriastradhdone:
86903b705cfSriastradh	pDst->componentAlpha = pSrc->componentAlpha;
87003b705cfSriastradh	*out_x = 0;
87103b705cfSriastradh	*out_y = 0;
87203b705cfSriastradh	return pDst;
87303b705cfSriastradh}
87403b705cfSriastradh
87503b705cfSriastradhstatic PicturePtr
87603b705cfSriastradhuxa_acquire_picture(ScreenPtr screen,
87703b705cfSriastradh		    PicturePtr src,
87803b705cfSriastradh		    pixman_format_code_t format,
87903b705cfSriastradh		    INT16 x, INT16 y,
88003b705cfSriastradh		    CARD16 width, CARD16 height,
88103b705cfSriastradh		    INT16 * out_x, INT16 * out_y)
88203b705cfSriastradh{
88303b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
88403b705cfSriastradh
88503b705cfSriastradh	if (uxa_screen->info->check_composite_texture &&
88603b705cfSriastradh	    uxa_screen->info->check_composite_texture(screen, src)) {
88703b705cfSriastradh		if (src->pDrawable) {
88803b705cfSriastradh			*out_x = x + src->pDrawable->x;
88903b705cfSriastradh			*out_y = y + src->pDrawable->y;
89003b705cfSriastradh		} else {
89103b705cfSriastradh			*out_x = x;
89203b705cfSriastradh			*out_y = y;
89303b705cfSriastradh		}
89403b705cfSriastradh		return src;
89503b705cfSriastradh	}
89603b705cfSriastradh
89703b705cfSriastradh	if (src->pDrawable) {
89803b705cfSriastradh		PicturePtr dst;
89903b705cfSriastradh
90003b705cfSriastradh		dst = uxa_acquire_drawable(screen, src,
90103b705cfSriastradh					   x, y, width, height,
90203b705cfSriastradh					   out_x, out_y);
90303b705cfSriastradh		if (!dst)
90403b705cfSriastradh			return 0;
90503b705cfSriastradh
90603b705cfSriastradh		if (uxa_screen->info->check_composite_texture &&
90703b705cfSriastradh		    !uxa_screen->info->check_composite_texture(screen, dst)) {
90803b705cfSriastradh			if (dst != src)
90903b705cfSriastradh				FreePicture(dst, 0);
91003b705cfSriastradh			return 0;
91103b705cfSriastradh		}
91203b705cfSriastradh
91303b705cfSriastradh		return dst;
91403b705cfSriastradh	}
91503b705cfSriastradh
91603b705cfSriastradh	*out_x = 0;
91703b705cfSriastradh	*out_y = 0;
91803b705cfSriastradh	return uxa_acquire_pattern(screen, src,
91903b705cfSriastradh				   format, x, y, width, height);
92003b705cfSriastradh}
92103b705cfSriastradh
92203b705cfSriastradhstatic PicturePtr
92303b705cfSriastradhuxa_acquire_source(ScreenPtr screen,
92403b705cfSriastradh		   PicturePtr pict,
92503b705cfSriastradh		   INT16 x, INT16 y,
92603b705cfSriastradh		   CARD16 width, CARD16 height,
92703b705cfSriastradh		   INT16 * out_x, INT16 * out_y)
92803b705cfSriastradh{
92903b705cfSriastradh	return uxa_acquire_picture (screen, pict,
93003b705cfSriastradh				    PICT_a8r8g8b8,
93103b705cfSriastradh				    x, y,
93203b705cfSriastradh				    width, height,
93303b705cfSriastradh				    out_x, out_y);
93403b705cfSriastradh}
93503b705cfSriastradh
93603b705cfSriastradhstatic PicturePtr
93703b705cfSriastradhuxa_acquire_mask(ScreenPtr screen,
93803b705cfSriastradh		 PicturePtr pict,
93903b705cfSriastradh		 INT16 x, INT16 y,
94003b705cfSriastradh		 INT16 width, INT16 height,
94103b705cfSriastradh		 INT16 * out_x, INT16 * out_y)
94203b705cfSriastradh{
94303b705cfSriastradh	return uxa_acquire_picture (screen, pict,
94403b705cfSriastradh				    PICT_a8,
94503b705cfSriastradh				    x, y,
94603b705cfSriastradh				    width, height,
94703b705cfSriastradh				    out_x, out_y);
94803b705cfSriastradh}
94903b705cfSriastradh
95003b705cfSriastradhstatic int
95103b705cfSriastradhuxa_try_driver_composite(CARD8 op,
95203b705cfSriastradh			 PicturePtr pSrc,
95303b705cfSriastradh			 PicturePtr pMask,
95403b705cfSriastradh			 PicturePtr pDst,
95503b705cfSriastradh			 INT16 xSrc, INT16 ySrc,
95603b705cfSriastradh			 INT16 xMask, INT16 yMask,
95703b705cfSriastradh			 INT16 xDst, INT16 yDst,
95803b705cfSriastradh			 CARD16 width, CARD16 height)
95903b705cfSriastradh{
96003b705cfSriastradh	ScreenPtr screen = pDst->pDrawable->pScreen;
96103b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
96203b705cfSriastradh	RegionRec region;
96303b705cfSriastradh	BoxPtr pbox;
96403b705cfSriastradh	int nbox;
96503b705cfSriastradh	int xDst_copy = 0, yDst_copy = 0;
96603b705cfSriastradh	int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
96703b705cfSriastradh	PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
96803b705cfSriastradh	PicturePtr localSrc, localMask = NULL;
96903b705cfSriastradh	PicturePtr localDst = pDst;
97003b705cfSriastradh
97103b705cfSriastradh	if (uxa_screen->info->check_composite &&
97203b705cfSriastradh	    !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst, width, height))
97303b705cfSriastradh		return -1;
97403b705cfSriastradh
97503b705cfSriastradh	if (uxa_screen->info->check_composite_target &&
97603b705cfSriastradh	    !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
97703b705cfSriastradh		int depth = pDst->pDrawable->depth;
97803b705cfSriastradh		PixmapPtr pixmap;
97903b705cfSriastradh		int error;
98003b705cfSriastradh		GCPtr gc;
98103b705cfSriastradh
98203b705cfSriastradh		pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
98303b705cfSriastradh		if (uxa_screen->info->check_copy &&
98403b705cfSriastradh		    !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
98503b705cfSriastradh			return -1;
98603b705cfSriastradh
98703b705cfSriastradh		pixmap = screen->CreatePixmap(screen,
98803b705cfSriastradh					      width, height, depth,
98903b705cfSriastradh					      CREATE_PIXMAP_USAGE_SCRATCH);
99003b705cfSriastradh		if (!pixmap)
99103b705cfSriastradh			return 0;
99203b705cfSriastradh
99303b705cfSriastradh		gc = GetScratchGC(depth, screen);
99403b705cfSriastradh		if (!gc) {
99503b705cfSriastradh			screen->DestroyPixmap(pixmap);
99603b705cfSriastradh			return 0;
99703b705cfSriastradh		}
99803b705cfSriastradh
99903b705cfSriastradh		ValidateGC(&pixmap->drawable, gc);
100003b705cfSriastradh		gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
100103b705cfSriastradh				  xDst, yDst, width, height, 0, 0);
100203b705cfSriastradh		FreeScratchGC(gc);
100303b705cfSriastradh
100403b705cfSriastradh		xDst_copy = xDst; xDst = 0;
100503b705cfSriastradh		yDst_copy = yDst; yDst = 0;
100603b705cfSriastradh
100703b705cfSriastradh		localDst = CreatePicture(0, &pixmap->drawable,
100803b705cfSriastradh					 PictureMatchFormat(screen, depth, pDst->format),
100903b705cfSriastradh					 0, 0, serverClient, &error);
101003b705cfSriastradh		screen->DestroyPixmap(pixmap);
101103b705cfSriastradh
101203b705cfSriastradh		if (!localDst)
101303b705cfSriastradh			return 0;
101403b705cfSriastradh
101503b705cfSriastradh		ValidatePicture(localDst);
101603b705cfSriastradh	}
101703b705cfSriastradh
101803b705cfSriastradh	pDstPix =
101903b705cfSriastradh	    uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y);
102003b705cfSriastradh	if (!pDstPix) {
102103b705cfSriastradh		if (localDst != pDst)
102203b705cfSriastradh			FreePicture(localDst, 0);
102303b705cfSriastradh		return -1;
102403b705cfSriastradh	}
102503b705cfSriastradh
102603b705cfSriastradh	xDst += localDst->pDrawable->x;
102703b705cfSriastradh	yDst += localDst->pDrawable->y;
102803b705cfSriastradh
102903b705cfSriastradh	localSrc = uxa_acquire_source(screen, pSrc,
103003b705cfSriastradh				      xSrc, ySrc,
103103b705cfSriastradh				      width, height,
103203b705cfSriastradh				      &xSrc, &ySrc);
103303b705cfSriastradh	if (!localSrc) {
103403b705cfSriastradh		if (localDst != pDst)
103503b705cfSriastradh			FreePicture(localDst, 0);
103603b705cfSriastradh		return 0;
103703b705cfSriastradh	}
103803b705cfSriastradh
103903b705cfSriastradh	if (pMask) {
104003b705cfSriastradh		localMask = uxa_acquire_mask(screen, pMask,
104103b705cfSriastradh					     xMask, yMask,
104203b705cfSriastradh					     width, height,
104303b705cfSriastradh					     &xMask, &yMask);
104403b705cfSriastradh		if (!localMask) {
104503b705cfSriastradh			if (localSrc != pSrc)
104603b705cfSriastradh				FreePicture(localSrc, 0);
104703b705cfSriastradh			if (localDst != pDst)
104803b705cfSriastradh				FreePicture(localDst, 0);
104903b705cfSriastradh
105003b705cfSriastradh			return 0;
105103b705cfSriastradh		}
105203b705cfSriastradh	}
105303b705cfSriastradh
105403b705cfSriastradh	if (!miComputeCompositeRegion(&region, localSrc, localMask, localDst,
105503b705cfSriastradh				      xSrc, ySrc, xMask, yMask, xDst, yDst,
105603b705cfSriastradh				      width, height)) {
105703b705cfSriastradh		if (localSrc != pSrc)
105803b705cfSriastradh			FreePicture(localSrc, 0);
105903b705cfSriastradh		if (localMask && localMask != pMask)
106003b705cfSriastradh			FreePicture(localMask, 0);
106103b705cfSriastradh		if (localDst != pDst)
106203b705cfSriastradh			FreePicture(localDst, 0);
106303b705cfSriastradh
106403b705cfSriastradh		return 1;
106503b705cfSriastradh	}
106603b705cfSriastradh
106703b705cfSriastradh	pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable,
106803b705cfSriastradh					   &src_off_x, &src_off_y);
106903b705cfSriastradh	if (!pSrcPix) {
107003b705cfSriastradh		REGION_UNINIT(screen, &region);
107103b705cfSriastradh
107203b705cfSriastradh		if (localSrc != pSrc)
107303b705cfSriastradh			FreePicture(localSrc, 0);
107403b705cfSriastradh		if (localMask && localMask != pMask)
107503b705cfSriastradh			FreePicture(localMask, 0);
107603b705cfSriastradh		if (localDst != pDst)
107703b705cfSriastradh			FreePicture(localDst, 0);
107803b705cfSriastradh
107903b705cfSriastradh		return 0;
108003b705cfSriastradh	}
108103b705cfSriastradh
108203b705cfSriastradh	if (localMask) {
108303b705cfSriastradh		pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable,
108403b705cfSriastradh						    &mask_off_x, &mask_off_y);
108503b705cfSriastradh		if (!pMaskPix) {
108603b705cfSriastradh			REGION_UNINIT(screen, &region);
108703b705cfSriastradh
108803b705cfSriastradh			if (localSrc != pSrc)
108903b705cfSriastradh				FreePicture(localSrc, 0);
109003b705cfSriastradh			if (localMask && localMask != pMask)
109103b705cfSriastradh				FreePicture(localMask, 0);
109203b705cfSriastradh			if (localDst != pDst)
109303b705cfSriastradh				FreePicture(localDst, 0);
109403b705cfSriastradh
109503b705cfSriastradh			return 0;
109603b705cfSriastradh		}
109703b705cfSriastradh	}
109803b705cfSriastradh
109903b705cfSriastradh	if (!(*uxa_screen->info->prepare_composite)
110003b705cfSriastradh	    (op, localSrc, localMask, localDst, pSrcPix, pMaskPix, pDstPix)) {
110103b705cfSriastradh		REGION_UNINIT(screen, &region);
110203b705cfSriastradh
110303b705cfSriastradh		if (localSrc != pSrc)
110403b705cfSriastradh			FreePicture(localSrc, 0);
110503b705cfSriastradh		if (localMask && localMask != pMask)
110603b705cfSriastradh			FreePicture(localMask, 0);
110703b705cfSriastradh		if (localDst != pDst)
110803b705cfSriastradh			FreePicture(localDst, 0);
110903b705cfSriastradh
111003b705cfSriastradh		return -1;
111103b705cfSriastradh	}
111203b705cfSriastradh
111303b705cfSriastradh	if (pMask) {
111403b705cfSriastradh		xMask = xMask + mask_off_x - xDst;
111503b705cfSriastradh		yMask = yMask + mask_off_y - yDst;
111603b705cfSriastradh	}
111703b705cfSriastradh
111803b705cfSriastradh	xSrc = xSrc + src_off_x - xDst;
111903b705cfSriastradh	ySrc = ySrc + src_off_y - yDst;
112003b705cfSriastradh
112103b705cfSriastradh	nbox = REGION_NUM_RECTS(&region);
112203b705cfSriastradh	pbox = REGION_RECTS(&region);
112303b705cfSriastradh	while (nbox--) {
112403b705cfSriastradh		(*uxa_screen->info->composite) (pDstPix,
112503b705cfSriastradh						pbox->x1 + xSrc,
112603b705cfSriastradh						pbox->y1 + ySrc,
112703b705cfSriastradh						pbox->x1 + xMask,
112803b705cfSriastradh						pbox->y1 + yMask,
112903b705cfSriastradh						pbox->x1 + dst_off_x,
113003b705cfSriastradh						pbox->y1 + dst_off_y,
113103b705cfSriastradh						pbox->x2 - pbox->x1,
113203b705cfSriastradh						pbox->y2 - pbox->y1);
113303b705cfSriastradh		pbox++;
113403b705cfSriastradh	}
113503b705cfSriastradh	(*uxa_screen->info->done_composite) (pDstPix);
113603b705cfSriastradh
113703b705cfSriastradh	REGION_UNINIT(screen, &region);
113803b705cfSriastradh
113903b705cfSriastradh	if (localSrc != pSrc)
114003b705cfSriastradh		FreePicture(localSrc, 0);
114103b705cfSriastradh	if (localMask && localMask != pMask)
114203b705cfSriastradh		FreePicture(localMask, 0);
114303b705cfSriastradh
114403b705cfSriastradh	if (localDst != pDst) {
114503b705cfSriastradh		GCPtr gc;
114603b705cfSriastradh
114703b705cfSriastradh		gc = GetScratchGC(pDst->pDrawable->depth, screen);
114803b705cfSriastradh		if (gc) {
114903b705cfSriastradh			ValidateGC(pDst->pDrawable, gc);
115003b705cfSriastradh			gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
115103b705cfSriastradh					  0, 0, width, height, xDst_copy, yDst_copy);
115203b705cfSriastradh			FreeScratchGC(gc);
115303b705cfSriastradh		}
115403b705cfSriastradh
115503b705cfSriastradh		FreePicture(localDst, 0);
115603b705cfSriastradh	}
115703b705cfSriastradh
115803b705cfSriastradh	return 1;
115903b705cfSriastradh}
116003b705cfSriastradh
116103b705cfSriastradh/**
116203b705cfSriastradh * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of
116303b705cfSriastradh * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
116403b705cfSriastradh * alpha and limited 1-tmu cards.
116503b705cfSriastradh *
116603b705cfSriastradh * From http://anholt.livejournal.com/32058.html:
116703b705cfSriastradh *
116803b705cfSriastradh * The trouble is that component-alpha rendering requires two different sources
116903b705cfSriastradh * for blending: one for the source value to the blender, which is the
117003b705cfSriastradh * per-channel multiplication of source and mask, and one for the source alpha
117103b705cfSriastradh * for multiplying with the destination channels, which is the multiplication
117203b705cfSriastradh * of the source channels by the mask alpha. So the equation for Over is:
117303b705cfSriastradh *
117403b705cfSriastradh * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
117503b705cfSriastradh * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
117603b705cfSriastradh * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
117703b705cfSriastradh * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
117803b705cfSriastradh *
117903b705cfSriastradh * But we can do some simpler operations, right? How about PictOpOutReverse,
118003b705cfSriastradh * which has a source factor of 0 and dest factor of (1 - source alpha). We
118103b705cfSriastradh * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
118203b705cfSriastradh * blenders pretty easily. So we can do a component-alpha OutReverse, which
118303b705cfSriastradh * gets us:
118403b705cfSriastradh *
118503b705cfSriastradh * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
118603b705cfSriastradh * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
118703b705cfSriastradh * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
118803b705cfSriastradh * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
118903b705cfSriastradh *
119003b705cfSriastradh * OK. And if an op doesn't use the source alpha value for the destination
119103b705cfSriastradh * factor, then we can do the channel multiplication in the texture blenders
119203b705cfSriastradh * to get the source value, and ignore the source alpha that we wouldn't use.
119303b705cfSriastradh * We've supported this in the Radeon driver for a long time. An example would
119403b705cfSriastradh * be PictOpAdd, which does:
119503b705cfSriastradh *
119603b705cfSriastradh * dst.A = src.A * mask.A + dst.A
119703b705cfSriastradh * dst.R = src.R * mask.R + dst.R
119803b705cfSriastradh * dst.G = src.G * mask.G + dst.G
119903b705cfSriastradh * dst.B = src.B * mask.B + dst.B
120003b705cfSriastradh *
120103b705cfSriastradh * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
120203b705cfSriastradh * after it, we get:
120303b705cfSriastradh *
120403b705cfSriastradh * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
120503b705cfSriastradh * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
120603b705cfSriastradh * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
120703b705cfSriastradh * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
120803b705cfSriastradh */
120903b705cfSriastradh
121003b705cfSriastradhstatic int
121103b705cfSriastradhuxa_try_magic_two_pass_composite_helper(CARD8 op,
121203b705cfSriastradh					PicturePtr pSrc,
121303b705cfSriastradh					PicturePtr pMask,
121403b705cfSriastradh					PicturePtr pDst,
121503b705cfSriastradh					INT16 xSrc, INT16 ySrc,
121603b705cfSriastradh					INT16 xMask, INT16 yMask,
121703b705cfSriastradh					INT16 xDst, INT16 yDst,
121803b705cfSriastradh					CARD16 width, CARD16 height)
121903b705cfSriastradh{
122003b705cfSriastradh	ScreenPtr screen = pDst->pDrawable->pScreen;
122103b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
122203b705cfSriastradh	PicturePtr localDst = pDst;
122303b705cfSriastradh	int xDst_copy, yDst_copy;
122403b705cfSriastradh
122503b705cfSriastradh	assert(op == PictOpOver);
122603b705cfSriastradh
122703b705cfSriastradh	if (uxa_screen->info->check_composite &&
122803b705cfSriastradh	    (!(*uxa_screen->info->check_composite) (PictOpOutReverse, pSrc,
122903b705cfSriastradh						    pMask, pDst, width, height)
123003b705cfSriastradh	     || !(*uxa_screen->info->check_composite) (PictOpAdd, pSrc, pMask,
123103b705cfSriastradh						       pDst, width, height))) {
123203b705cfSriastradh		return -1;
123303b705cfSriastradh	}
123403b705cfSriastradh
123503b705cfSriastradh	if (uxa_screen->info->check_composite_target &&
123603b705cfSriastradh	    !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
123703b705cfSriastradh		int depth = pDst->pDrawable->depth;
123803b705cfSriastradh		PixmapPtr pixmap;
123903b705cfSriastradh		int error;
124003b705cfSriastradh		GCPtr gc;
124103b705cfSriastradh
124203b705cfSriastradh		pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
124303b705cfSriastradh		if (uxa_screen->info->check_copy &&
124403b705cfSriastradh		    !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
124503b705cfSriastradh			return -1;
124603b705cfSriastradh
124703b705cfSriastradh		pixmap = screen->CreatePixmap(screen,
124803b705cfSriastradh					      width, height, depth,
124903b705cfSriastradh					      CREATE_PIXMAP_USAGE_SCRATCH);
125003b705cfSriastradh		if (!pixmap)
125103b705cfSriastradh			return 0;
125203b705cfSriastradh
125303b705cfSriastradh		gc = GetScratchGC(depth, screen);
125403b705cfSriastradh		if (!gc) {
125503b705cfSriastradh			screen->DestroyPixmap(pixmap);
125603b705cfSriastradh			return 0;
125703b705cfSriastradh		}
125803b705cfSriastradh
125903b705cfSriastradh		ValidateGC(&pixmap->drawable, gc);
126003b705cfSriastradh		gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
126103b705cfSriastradh				  xDst, yDst, width, height, 0, 0);
126203b705cfSriastradh		FreeScratchGC(gc);
126303b705cfSriastradh
126403b705cfSriastradh		xDst_copy = xDst; xDst = 0;
126503b705cfSriastradh		yDst_copy = yDst; yDst = 0;
126603b705cfSriastradh
126703b705cfSriastradh		localDst = CreatePicture(0, &pixmap->drawable,
126803b705cfSriastradh					 PictureMatchFormat(screen, depth, pDst->format),
126903b705cfSriastradh					 0, 0, serverClient, &error);
127003b705cfSriastradh		screen->DestroyPixmap(pixmap);
127103b705cfSriastradh
127203b705cfSriastradh		if (!localDst)
127303b705cfSriastradh			return 0;
127403b705cfSriastradh
127503b705cfSriastradh		ValidatePicture(localDst);
127603b705cfSriastradh	}
127703b705cfSriastradh
127803b705cfSriastradh	/* Now, we think we should be able to accelerate this operation. First,
127903b705cfSriastradh	 * composite the destination to be the destination times the source alpha
128003b705cfSriastradh	 * factors.
128103b705cfSriastradh	 */
128203b705cfSriastradh	uxa_composite(PictOpOutReverse, pSrc, pMask, localDst,
128303b705cfSriastradh		      xSrc, ySrc,
128403b705cfSriastradh		      xMask, yMask,
128503b705cfSriastradh		      xDst, yDst,
128603b705cfSriastradh		      width, height);
128703b705cfSriastradh
128803b705cfSriastradh	/* Then, add in the source value times the destination alpha factors (1.0).
128903b705cfSriastradh	 */
129003b705cfSriastradh	uxa_composite(PictOpAdd, pSrc, pMask, localDst,
129103b705cfSriastradh		      xSrc, ySrc,
129203b705cfSriastradh		      xMask, yMask,
129303b705cfSriastradh		      xDst, yDst,
129403b705cfSriastradh		      width, height);
129503b705cfSriastradh
129603b705cfSriastradh	if (localDst != pDst) {
129703b705cfSriastradh		GCPtr gc;
129803b705cfSriastradh
129903b705cfSriastradh		gc = GetScratchGC(pDst->pDrawable->depth, screen);
130003b705cfSriastradh		if (gc) {
130103b705cfSriastradh			ValidateGC(pDst->pDrawable, gc);
130203b705cfSriastradh			gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
130303b705cfSriastradh					0, 0, width, height, xDst_copy, yDst_copy);
130403b705cfSriastradh			FreeScratchGC(gc);
130503b705cfSriastradh		}
130603b705cfSriastradh
130703b705cfSriastradh		FreePicture(localDst, 0);
130803b705cfSriastradh	}
130903b705cfSriastradh
131003b705cfSriastradh	return 1;
131103b705cfSriastradh}
131203b705cfSriastradh
131303b705cfSriastradhstatic int
131403b705cfSriastradhcompatible_formats (CARD8 op, PicturePtr dst, PicturePtr src)
131503b705cfSriastradh{
131603b705cfSriastradh	if (op == PictOpSrc) {
131703b705cfSriastradh		if (src->format == dst->format)
131803b705cfSriastradh			return 1;
131903b705cfSriastradh
132003b705cfSriastradh		/* Is the destination an alpha-less version of source? */
132103b705cfSriastradh		if (dst->format == PICT_FORMAT(PICT_FORMAT_BPP(src->format),
132203b705cfSriastradh					       PICT_FORMAT_TYPE(src->format),
132303b705cfSriastradh					       0,
132403b705cfSriastradh					       PICT_FORMAT_R(src->format),
132503b705cfSriastradh					       PICT_FORMAT_G(src->format),
132603b705cfSriastradh					       PICT_FORMAT_B(src->format)))
132703b705cfSriastradh			return 1;
132803b705cfSriastradh
132903b705cfSriastradh		/* XXX xrgb is promoted to argb during image upload... */
133003b705cfSriastradh#if 0
133103b705cfSriastradh		if (dst->format == PICT_a8r8g8b8 && src->format == PICT_x8r8g8b8)
133203b705cfSriastradh			return 1;
133303b705cfSriastradh#endif
133403b705cfSriastradh	} else if (op == PictOpOver) {
133503b705cfSriastradh		if (PICT_FORMAT_A(src->format))
133603b705cfSriastradh			return 0;
133703b705cfSriastradh
133803b705cfSriastradh		return src->format == dst->format;
133903b705cfSriastradh	}
134003b705cfSriastradh
134103b705cfSriastradh	return 0;
134203b705cfSriastradh}
134303b705cfSriastradh
134403b705cfSriastradhvoid
134503b705cfSriastradhuxa_composite(CARD8 op,
134603b705cfSriastradh	      PicturePtr pSrc,
134703b705cfSriastradh	      PicturePtr pMask,
134803b705cfSriastradh	      PicturePtr pDst,
134903b705cfSriastradh	      INT16 xSrc, INT16 ySrc,
135003b705cfSriastradh	      INT16 xMask, INT16 yMask,
135103b705cfSriastradh	      INT16 xDst, INT16 yDst,
135203b705cfSriastradh	      CARD16 width, CARD16 height)
135303b705cfSriastradh{
135403b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
135503b705cfSriastradh	int ret = -1;
135603b705cfSriastradh	Bool saveSrcRepeat = pSrc->repeat;
135703b705cfSriastradh	Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
135803b705cfSriastradh	RegionRec region;
135903b705cfSriastradh	int tx, ty;
136003b705cfSriastradh
136103b705cfSriastradh	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
136203b705cfSriastradh		int ok;
136303b705cfSriastradh
136403b705cfSriastradh		uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW);
136503b705cfSriastradh		uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO);
136603b705cfSriastradh		if (pMask)
136703b705cfSriastradh			uxa_picture_prepare_access(pMask, UXA_GLAMOR_ACCESS_RO);
136803b705cfSriastradh
136903b705cfSriastradh		ok = glamor_composite_nf(op,
137003b705cfSriastradh					 pSrc, pMask, pDst, xSrc, ySrc,
137103b705cfSriastradh					 xMask, yMask, xDst, yDst,
137203b705cfSriastradh					 width, height);
137303b705cfSriastradh
137403b705cfSriastradh		if (pMask)
137503b705cfSriastradh			uxa_picture_finish_access(pMask, UXA_GLAMOR_ACCESS_RO);
137603b705cfSriastradh		uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO);
137703b705cfSriastradh		uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW);
137803b705cfSriastradh
137903b705cfSriastradh		if (!ok)
138003b705cfSriastradh			goto fallback;
138103b705cfSriastradh
138203b705cfSriastradh		return;
138303b705cfSriastradh	}
138403b705cfSriastradh
138503b705cfSriastradh	if (uxa_screen->force_fallback)
138603b705cfSriastradh		goto fallback;
138703b705cfSriastradh
138803b705cfSriastradh	if (!uxa_drawable_is_offscreen(pDst->pDrawable))
138903b705cfSriastradh		goto fallback;
139003b705cfSriastradh
139103b705cfSriastradh	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
139203b705cfSriastradh		goto fallback;
139303b705cfSriastradh
139403b705cfSriastradh	/* Remove repeat in source if useless */
139503b705cfSriastradh	if (pSrc->pDrawable && pSrc->repeat && pSrc->filter != PictFilterConvolution &&
139603b705cfSriastradh	    transform_is_integer_translation(pSrc->transform, &tx, &ty) &&
139703b705cfSriastradh	    (pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) &&
139803b705cfSriastradh	    drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height))
139903b705cfSriastradh		pSrc->repeat = 0;
140003b705cfSriastradh
140103b705cfSriastradh	if (!pMask) {
140203b705cfSriastradh		if (op == PictOpClear) {
140303b705cfSriastradh			PicturePtr clear = uxa_solid_clear(pDst->pDrawable->pScreen);
140403b705cfSriastradh			if (clear &&
140503b705cfSriastradh			    uxa_try_driver_solid_fill(clear, pDst,
140603b705cfSriastradh						      xSrc, ySrc,
140703b705cfSriastradh						      xDst, yDst,
140803b705cfSriastradh						      width, height) == 1)
140903b705cfSriastradh				goto done;
141003b705cfSriastradh		}
141103b705cfSriastradh
141203b705cfSriastradh		if (pSrc->pDrawable == NULL) {
141303b705cfSriastradh			if (pSrc->pSourcePict) {
141403b705cfSriastradh				SourcePict *source = pSrc->pSourcePict;
141503b705cfSriastradh				if (source->type == SourcePictTypeSolidFill) {
141603b705cfSriastradh					if (op == PictOpSrc ||
141703b705cfSriastradh					    (op == PictOpOver &&
141803b705cfSriastradh					     (source->solidFill.color & 0xff000000) == 0xff000000)) {
141903b705cfSriastradh						ret = uxa_try_driver_solid_fill(pSrc, pDst,
142003b705cfSriastradh										xSrc, ySrc,
142103b705cfSriastradh										xDst, yDst,
142203b705cfSriastradh										width, height);
142303b705cfSriastradh						if (ret == 1)
142403b705cfSriastradh							goto done;
142503b705cfSriastradh					}
142603b705cfSriastradh				}
142703b705cfSriastradh			}
142803b705cfSriastradh		} else if (pSrc->pDrawable->width == 1 &&
142903b705cfSriastradh			   pSrc->pDrawable->height == 1 &&
143003b705cfSriastradh			   pSrc->repeat &&
143103b705cfSriastradh			   (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) {
143203b705cfSriastradh			ret = uxa_try_driver_solid_fill(pSrc, pDst,
143303b705cfSriastradh							xSrc, ySrc,
143403b705cfSriastradh							xDst, yDst,
143503b705cfSriastradh							width, height);
143603b705cfSriastradh			if (ret == 1)
143703b705cfSriastradh				goto done;
143803b705cfSriastradh		} else if (compatible_formats (op, pDst, pSrc) &&
143903b705cfSriastradh			   pSrc->filter != PictFilterConvolution &&
144003b705cfSriastradh			   transform_is_integer_translation(pSrc->transform, &tx, &ty)) {
144103b705cfSriastradh			if (!pSrc->repeat &&
144203b705cfSriastradh			    drawable_contains(pSrc->pDrawable,
144303b705cfSriastradh					     xSrc + tx, ySrc + ty,
144403b705cfSriastradh					     width, height)) {
144503b705cfSriastradh				xDst += pDst->pDrawable->x;
144603b705cfSriastradh				yDst += pDst->pDrawable->y;
144703b705cfSriastradh				xSrc += pSrc->pDrawable->x + tx;
144803b705cfSriastradh				ySrc += pSrc->pDrawable->y + ty;
144903b705cfSriastradh
145003b705cfSriastradh				if (!miComputeCompositeRegion
145103b705cfSriastradh				    (&region, pSrc, pMask, pDst, xSrc, ySrc,
145203b705cfSriastradh				     xMask, yMask, xDst, yDst, width, height))
145303b705cfSriastradh					goto done;
145403b705cfSriastradh
145503b705cfSriastradh				uxa_copy_n_to_n(pSrc->pDrawable,
145603b705cfSriastradh						pDst->pDrawable, NULL,
145703b705cfSriastradh						REGION_RECTS(&region),
145803b705cfSriastradh						REGION_NUM_RECTS(&region),
145903b705cfSriastradh						xSrc - xDst, ySrc - yDst, FALSE,
146003b705cfSriastradh						FALSE, 0, NULL);
146103b705cfSriastradh				REGION_UNINIT(pDst->pDrawable->pScreen,
146203b705cfSriastradh					      &region);
146303b705cfSriastradh				goto done;
146403b705cfSriastradh			} else if (pSrc->repeat && pSrc->repeatType == RepeatNormal &&
146503b705cfSriastradh				   pSrc->pDrawable->type == DRAWABLE_PIXMAP) {
146603b705cfSriastradh				DDXPointRec patOrg;
146703b705cfSriastradh
146803b705cfSriastradh				/* Let's see if the driver can do the repeat
146903b705cfSriastradh				 * in one go
147003b705cfSriastradh				 */
147103b705cfSriastradh				if (uxa_screen->info->prepare_composite) {
147203b705cfSriastradh					ret = uxa_try_driver_composite(op, pSrc,
147303b705cfSriastradh								       pMask, pDst,
147403b705cfSriastradh								       xSrc, ySrc,
147503b705cfSriastradh								       xMask, yMask,
147603b705cfSriastradh								       xDst, yDst,
147703b705cfSriastradh								       width, height);
147803b705cfSriastradh					if (ret == 1)
147903b705cfSriastradh						goto done;
148003b705cfSriastradh				}
148103b705cfSriastradh
148203b705cfSriastradh				/* Now see if we can use
148303b705cfSriastradh				 * uxa_fill_region_tiled()
148403b705cfSriastradh				 */
148503b705cfSriastradh				xDst += pDst->pDrawable->x;
148603b705cfSriastradh				yDst += pDst->pDrawable->y;
148703b705cfSriastradh				xSrc += pSrc->pDrawable->x + tx;
148803b705cfSriastradh				ySrc += pSrc->pDrawable->y + ty;
148903b705cfSriastradh
149003b705cfSriastradh				if (!miComputeCompositeRegion
149103b705cfSriastradh				    (&region, pSrc, pMask, pDst, xSrc, ySrc,
149203b705cfSriastradh				     xMask, yMask, xDst, yDst, width, height))
149303b705cfSriastradh					goto done;
149403b705cfSriastradh
149503b705cfSriastradh				/* pattern origin is the point in the
149603b705cfSriastradh				 * destination drawable
149703b705cfSriastradh				 * corresponding to (0,0) in the source */
149803b705cfSriastradh				patOrg.x = xDst - xSrc;
149903b705cfSriastradh				patOrg.y = yDst - ySrc;
150003b705cfSriastradh
150103b705cfSriastradh				ret = uxa_fill_region_tiled(pDst->pDrawable,
150203b705cfSriastradh							    &region,
150303b705cfSriastradh							    (PixmapPtr) pSrc->
150403b705cfSriastradh							    pDrawable, &patOrg,
150503b705cfSriastradh							    FB_ALLONES, GXcopy);
150603b705cfSriastradh
150703b705cfSriastradh				REGION_UNINIT(pDst->pDrawable->pScreen,
150803b705cfSriastradh					      &region);
150903b705cfSriastradh
151003b705cfSriastradh				if (ret)
151103b705cfSriastradh					goto done;
151203b705cfSriastradh			}
151303b705cfSriastradh		}
151403b705cfSriastradh	}
151503b705cfSriastradh
151603b705cfSriastradh	/* Remove repeat in mask if useless */
151703b705cfSriastradh	if (pMask && pMask->pDrawable && pMask->repeat &&
151803b705cfSriastradh	    pMask->filter != PictFilterConvolution &&
151903b705cfSriastradh	    transform_is_integer_translation(pMask->transform, &tx, &ty) &&
152003b705cfSriastradh	    (pMask->pDrawable->width > 1 || pMask->pDrawable->height > 1) &&
152103b705cfSriastradh	    drawable_contains(pMask->pDrawable, xMask + tx, yMask + ty, width, height))
152203b705cfSriastradh		pMask->repeat = 0;
152303b705cfSriastradh
152403b705cfSriastradh	if (uxa_screen->info->prepare_composite) {
152503b705cfSriastradh		Bool isSrcSolid;
152603b705cfSriastradh
152703b705cfSriastradh		ret =
152803b705cfSriastradh		    uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc,
152903b705cfSriastradh					     xMask, yMask, xDst, yDst, width,
153003b705cfSriastradh					     height);
153103b705cfSriastradh		if (ret == 1)
153203b705cfSriastradh			goto done;
153303b705cfSriastradh
153403b705cfSriastradh		/* For generic masks and solid src pictures, mach64 can do
153503b705cfSriastradh		 * Over in two passes, similar to the component-alpha case.
153603b705cfSriastradh		 */
153703b705cfSriastradh
153803b705cfSriastradh		isSrcSolid =
153903b705cfSriastradh			pSrc->pDrawable ?
154003b705cfSriastradh				pSrc->pDrawable->width == 1 &&
154103b705cfSriastradh				pSrc->pDrawable->height == 1 &&
154203b705cfSriastradh				pSrc->repeat :
154303b705cfSriastradh			pSrc->pSourcePict ?
154403b705cfSriastradh				pSrc->pSourcePict->type == SourcePictTypeSolidFill :
154503b705cfSriastradh			0;
154603b705cfSriastradh
154703b705cfSriastradh		/* If we couldn't do the Composite in a single pass, and it
154803b705cfSriastradh		 * was a component-alpha Over, see if we can do it in two
154903b705cfSriastradh		 * passes with an OutReverse and then an Add.
155003b705cfSriastradh		 */
155103b705cfSriastradh		if (ret == -1 && op == PictOpOver && pMask &&
155203b705cfSriastradh		    (pMask->componentAlpha || isSrcSolid)) {
155303b705cfSriastradh			ret =
155403b705cfSriastradh			    uxa_try_magic_two_pass_composite_helper(op, pSrc,
155503b705cfSriastradh								    pMask, pDst,
155603b705cfSriastradh								    xSrc, ySrc,
155703b705cfSriastradh								    xMask, yMask,
155803b705cfSriastradh								    xDst, yDst,
155903b705cfSriastradh								    width, height);
156003b705cfSriastradh			if (ret == 1)
156103b705cfSriastradh				goto done;
156203b705cfSriastradh		}
156303b705cfSriastradh
156403b705cfSriastradh	}
156503b705cfSriastradh
156603b705cfSriastradhfallback:
156703b705cfSriastradh	uxa_print_composite_fallback("uxa_composite",
156803b705cfSriastradh				     op, pSrc, pMask, pDst);
156903b705cfSriastradh
157003b705cfSriastradh	uxa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc,
157103b705cfSriastradh			    xMask, yMask, xDst, yDst, width, height);
157203b705cfSriastradh
157303b705cfSriastradhdone:
157403b705cfSriastradh	pSrc->repeat = saveSrcRepeat;
157503b705cfSriastradh	if (pMask)
157603b705cfSriastradh		pMask->repeat = saveMaskRepeat;
157703b705cfSriastradh}
157803b705cfSriastradh#endif
157903b705cfSriastradh
158003b705cfSriastradh/**
158103b705cfSriastradh * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead
158203b705cfSriastradh * of PolyFillRect to initialize the pixmap after creating it, to prevent
158303b705cfSriastradh * the pixmap from being migrated.
158403b705cfSriastradh *
158503b705cfSriastradh * See the comments about uxa_trapezoids and uxa_triangles.
158603b705cfSriastradh */
158703b705cfSriastradhstatic PicturePtr
158803b705cfSriastradhuxa_create_alpha_picture(ScreenPtr pScreen,
158903b705cfSriastradh			 PicturePtr pDst,
159003b705cfSriastradh			 PictFormatPtr pPictFormat, CARD16 width, CARD16 height)
159103b705cfSriastradh{
159203b705cfSriastradh	PixmapPtr pPixmap;
159303b705cfSriastradh	PicturePtr pPicture;
159403b705cfSriastradh	int error;
159503b705cfSriastradh
159603b705cfSriastradh	if (width > 32767 || height > 32767)
159703b705cfSriastradh		return 0;
159803b705cfSriastradh
159903b705cfSriastradh	if (!pPictFormat) {
160003b705cfSriastradh		if (pDst->polyEdge == PolyEdgeSharp)
160103b705cfSriastradh			pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
160203b705cfSriastradh		else
160303b705cfSriastradh			pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
160403b705cfSriastradh		if (!pPictFormat)
160503b705cfSriastradh			return 0;
160603b705cfSriastradh	}
160703b705cfSriastradh
160803b705cfSriastradh	pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
160903b705cfSriastradh					    pPictFormat->depth,
161003b705cfSriastradh					    UXA_CREATE_PIXMAP_FOR_MAP);
161103b705cfSriastradh	if (!pPixmap)
161203b705cfSriastradh		return 0;
161303b705cfSriastradh	pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
161403b705cfSriastradh				 0, 0, serverClient, &error);
161503b705cfSriastradh	(*pScreen->DestroyPixmap) (pPixmap);
161603b705cfSriastradh	return pPicture;
161703b705cfSriastradh}
161803b705cfSriastradh
161903b705cfSriastradhstatic void
162003b705cfSriastradhuxa_check_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
162103b705cfSriastradh		     PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
162203b705cfSriastradh		     int ntrap, xTrapezoid * traps)
162303b705cfSriastradh{
162403b705cfSriastradh	ScreenPtr screen = dst->pDrawable->pScreen;
162503b705cfSriastradh
162603b705cfSriastradh	if (maskFormat) {
162703b705cfSriastradh		PixmapPtr scratch = NULL;
162803b705cfSriastradh		PicturePtr mask;
162903b705cfSriastradh		INT16 xDst, yDst;
163003b705cfSriastradh		INT16 xRel, yRel;
163103b705cfSriastradh		BoxRec bounds;
163203b705cfSriastradh		int width, height;
163303b705cfSriastradh		pixman_image_t *image;
163403b705cfSriastradh		pixman_format_code_t format;
163503b705cfSriastradh		int error;
163603b705cfSriastradh
163703b705cfSriastradh		xDst = traps[0].left.p1.x >> 16;
163803b705cfSriastradh		yDst = traps[0].left.p1.y >> 16;
163903b705cfSriastradh
164003b705cfSriastradh		miTrapezoidBounds (ntrap, traps, &bounds);
164103b705cfSriastradh		if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
164203b705cfSriastradh			return;
164303b705cfSriastradh
164403b705cfSriastradh		width  = bounds.x2 - bounds.x1;
164503b705cfSriastradh		height = bounds.y2 - bounds.y1;
164603b705cfSriastradh
164703b705cfSriastradh		format = maskFormat->format |
164803b705cfSriastradh			(BitsPerPixel(maskFormat->depth) << 24);
164903b705cfSriastradh		image =
165003b705cfSriastradh		    pixman_image_create_bits(format, width, height, NULL, 0);
165103b705cfSriastradh		if (!image)
165203b705cfSriastradh			return;
165303b705cfSriastradh
165403b705cfSriastradh		for (; ntrap; ntrap--, traps++)
165503b705cfSriastradh			pixman_rasterize_trapezoid(image,
165603b705cfSriastradh						   (pixman_trapezoid_t *) traps,
165703b705cfSriastradh						   -bounds.x1, -bounds.y1);
165803b705cfSriastradh
165903b705cfSriastradh
166003b705cfSriastradh		scratch = GetScratchPixmapHeader(screen, width, height,
166103b705cfSriastradh						 PIXMAN_FORMAT_DEPTH(format),
166203b705cfSriastradh						 PIXMAN_FORMAT_BPP(format),
166303b705cfSriastradh						 pixman_image_get_stride(image),
166403b705cfSriastradh						 pixman_image_get_data(image));
166503b705cfSriastradh		if (!scratch) {
166603b705cfSriastradh			pixman_image_unref(image);
166703b705cfSriastradh			return;
166803b705cfSriastradh		}
166903b705cfSriastradh
167003b705cfSriastradh		mask = CreatePicture(0, &scratch->drawable,
167103b705cfSriastradh				     PictureMatchFormat(screen,
167203b705cfSriastradh							PIXMAN_FORMAT_DEPTH(format),
167303b705cfSriastradh							format),
167403b705cfSriastradh				     0, 0, serverClient, &error);
167503b705cfSriastradh		if (!mask) {
167603b705cfSriastradh			FreeScratchPixmapHeader(scratch);
167703b705cfSriastradh			pixman_image_unref(image);
167803b705cfSriastradh			return;
167903b705cfSriastradh		}
168003b705cfSriastradh
168103b705cfSriastradh		xRel = bounds.x1 + xSrc - xDst;
168203b705cfSriastradh		yRel = bounds.y1 + ySrc - yDst;
168303b705cfSriastradh		CompositePicture(op, src, mask, dst,
168403b705cfSriastradh				 xRel, yRel,
168503b705cfSriastradh				 0, 0,
168603b705cfSriastradh				 bounds.x1, bounds.y1,
168703b705cfSriastradh				 width, height);
168803b705cfSriastradh		FreePicture(mask, 0);
168903b705cfSriastradh
169003b705cfSriastradh		FreeScratchPixmapHeader(scratch);
169103b705cfSriastradh		pixman_image_unref(image);
169203b705cfSriastradh	} else {
169303b705cfSriastradh		if (dst->polyEdge == PolyEdgeSharp)
169403b705cfSriastradh			maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
169503b705cfSriastradh		else
169603b705cfSriastradh			maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
169703b705cfSriastradh
169803b705cfSriastradh		for (; ntrap; ntrap--, traps++)
169903b705cfSriastradh			uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, 1, traps);
170003b705cfSriastradh	}
170103b705cfSriastradh}
170203b705cfSriastradh
170303b705cfSriastradh/**
170403b705cfSriastradh * uxa_trapezoids is essentially a copy of miTrapezoids that uses
170503b705cfSriastradh * uxa_create_alpha_picture instead of miCreateAlphaPicture.
170603b705cfSriastradh *
170703b705cfSriastradh * The problem with miCreateAlphaPicture is that it calls PolyFillRect
170803b705cfSriastradh * to initialize the contents after creating the pixmap, which
170903b705cfSriastradh * causes the pixmap to be moved in for acceleration. The subsequent
171003b705cfSriastradh * call to RasterizeTrapezoid won't be accelerated however, which
171103b705cfSriastradh * forces the pixmap to be moved out again.
171203b705cfSriastradh *
171303b705cfSriastradh * uxa_create_alpha_picture avoids this roundtrip by using
171403b705cfSriastradh * uxa_check_poly_fill_rect to initialize the contents.
171503b705cfSriastradh */
171603b705cfSriastradhvoid
171703b705cfSriastradhuxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
171803b705cfSriastradh	       PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
171903b705cfSriastradh	       int ntrap, xTrapezoid * traps)
172003b705cfSriastradh{
172103b705cfSriastradh	ScreenPtr screen = dst->pDrawable->pScreen;
172203b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
172303b705cfSriastradh	BoxRec bounds;
172403b705cfSriastradh	Bool direct;
172503b705cfSriastradh
172603b705cfSriastradh	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
172703b705cfSriastradh		int ok;
172803b705cfSriastradh
172903b705cfSriastradh		uxa_picture_prepare_access(dst, UXA_GLAMOR_ACCESS_RW);
173003b705cfSriastradh		uxa_picture_prepare_access(src, UXA_GLAMOR_ACCESS_RO);
173103b705cfSriastradh		ok = glamor_trapezoids_nf(op,
173203b705cfSriastradh					  src, dst, maskFormat, xSrc,
173303b705cfSriastradh					  ySrc, ntrap, traps);
173403b705cfSriastradh		uxa_picture_finish_access(src, UXA_GLAMOR_ACCESS_RO);
173503b705cfSriastradh		uxa_picture_finish_access(dst, UXA_GLAMOR_ACCESS_RW);
173603b705cfSriastradh
173703b705cfSriastradh		if (!ok)
173803b705cfSriastradh			goto fallback;
173903b705cfSriastradh
174003b705cfSriastradh		return;
174103b705cfSriastradh	}
174203b705cfSriastradh
174303b705cfSriastradh	if (uxa_screen->force_fallback) {
174403b705cfSriastradhfallback:
174503b705cfSriastradh		uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, ntrap, traps);
174603b705cfSriastradh		return;
174703b705cfSriastradh	}
174803b705cfSriastradh
174903b705cfSriastradh	direct = op == PictOpAdd && miIsSolidAlpha(src);
175003b705cfSriastradh	if (maskFormat || direct) {
175103b705cfSriastradh		miTrapezoidBounds(ntrap, traps, &bounds);
175203b705cfSriastradh
175303b705cfSriastradh		if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
175403b705cfSriastradh			return;
175503b705cfSriastradh	}
175603b705cfSriastradh
175703b705cfSriastradh	/*
175803b705cfSriastradh	 * Check for solid alpha add
175903b705cfSriastradh	 */
176003b705cfSriastradh	if (direct) {
176103b705cfSriastradh		DrawablePtr pDraw = dst->pDrawable;
176203b705cfSriastradh		PixmapPtr pixmap = uxa_get_drawable_pixmap(pDraw);
176303b705cfSriastradh		int xoff, yoff;
176403b705cfSriastradh
176503b705cfSriastradh		uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff);
176603b705cfSriastradh
176703b705cfSriastradh		xoff += pDraw->x;
176803b705cfSriastradh		yoff += pDraw->y;
176903b705cfSriastradh
177003b705cfSriastradh		if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
177103b705cfSriastradh			PictureScreenPtr ps = GetPictureScreen(screen);
177203b705cfSriastradh
177303b705cfSriastradh			for (; ntrap; ntrap--, traps++)
177403b705cfSriastradh				(*ps->RasterizeTrapezoid) (dst, traps, 0, 0);
177503b705cfSriastradh			uxa_finish_access(pDraw, UXA_ACCESS_RW);
177603b705cfSriastradh		}
177703b705cfSriastradh	} else if (maskFormat) {
177803b705cfSriastradh		PixmapPtr scratch = NULL;
177903b705cfSriastradh		PicturePtr mask;
178003b705cfSriastradh		INT16 xDst, yDst;
178103b705cfSriastradh		INT16 xRel, yRel;
178203b705cfSriastradh		int width, height;
178303b705cfSriastradh		pixman_image_t *image;
178403b705cfSriastradh		pixman_format_code_t format;
178503b705cfSriastradh
178603b705cfSriastradh		xDst = traps[0].left.p1.x >> 16;
178703b705cfSriastradh		yDst = traps[0].left.p1.y >> 16;
178803b705cfSriastradh
178903b705cfSriastradh		width  = bounds.x2 - bounds.x1;
179003b705cfSriastradh		height = bounds.y2 - bounds.y1;
179103b705cfSriastradh
179203b705cfSriastradh		format = maskFormat->format |
179303b705cfSriastradh			(BitsPerPixel(maskFormat->depth) << 24);
179403b705cfSriastradh		image =
179503b705cfSriastradh		    pixman_image_create_bits(format, width, height, NULL, 0);
179603b705cfSriastradh		if (!image)
179703b705cfSriastradh			return;
179803b705cfSriastradh
179903b705cfSriastradh		for (; ntrap; ntrap--, traps++)
180003b705cfSriastradh			pixman_rasterize_trapezoid(image,
180103b705cfSriastradh						   (pixman_trapezoid_t *) traps,
180203b705cfSriastradh						   -bounds.x1, -bounds.y1);
180303b705cfSriastradh		if (uxa_drawable_is_offscreen(dst->pDrawable)) {
180403b705cfSriastradh			mask = uxa_picture_from_pixman_image(screen, image, format);
180503b705cfSriastradh		} else {
180603b705cfSriastradh			int error;
180703b705cfSriastradh
180803b705cfSriastradh			scratch = GetScratchPixmapHeader(screen, width, height,
180903b705cfSriastradh							PIXMAN_FORMAT_DEPTH(format),
181003b705cfSriastradh							PIXMAN_FORMAT_BPP(format),
181103b705cfSriastradh							pixman_image_get_stride(image),
181203b705cfSriastradh							pixman_image_get_data(image));
181303b705cfSriastradh			mask = CreatePicture(0, &scratch->drawable,
181403b705cfSriastradh					     PictureMatchFormat(screen,
181503b705cfSriastradh								PIXMAN_FORMAT_DEPTH(format),
181603b705cfSriastradh								format),
181703b705cfSriastradh					     0, 0, serverClient, &error);
181803b705cfSriastradh		}
181903b705cfSriastradh		if (!mask) {
182003b705cfSriastradh			if (scratch)
182103b705cfSriastradh				FreeScratchPixmapHeader(scratch);
182203b705cfSriastradh			pixman_image_unref(image);
182303b705cfSriastradh			return;
182403b705cfSriastradh		}
182503b705cfSriastradh
182603b705cfSriastradh		xRel = bounds.x1 + xSrc - xDst;
182703b705cfSriastradh		yRel = bounds.y1 + ySrc - yDst;
182803b705cfSriastradh		CompositePicture(op, src, mask, dst,
182903b705cfSriastradh				 xRel, yRel,
183003b705cfSriastradh				 0, 0,
183103b705cfSriastradh				 bounds.x1, bounds.y1,
183203b705cfSriastradh				 width, height);
183303b705cfSriastradh		FreePicture(mask, 0);
183403b705cfSriastradh
183503b705cfSriastradh		if (scratch)
183603b705cfSriastradh			FreeScratchPixmapHeader(scratch);
183703b705cfSriastradh		pixman_image_unref(image);
183803b705cfSriastradh	} else {
183903b705cfSriastradh		if (dst->polyEdge == PolyEdgeSharp)
184003b705cfSriastradh			maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
184103b705cfSriastradh		else
184203b705cfSriastradh			maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
184303b705cfSriastradh		for (; ntrap; ntrap--, traps++)
184403b705cfSriastradh			uxa_trapezoids(op, src, dst, maskFormat, xSrc, ySrc,
184503b705cfSriastradh				       1, traps);
184603b705cfSriastradh	}
184703b705cfSriastradh}
184803b705cfSriastradh
184903b705cfSriastradhstatic void
185003b705cfSriastradhuxa_check_triangles(CARD8 op, PicturePtr src, PicturePtr dst,
185103b705cfSriastradh		    PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
185203b705cfSriastradh		    int ntri, xTriangle *tri)
185303b705cfSriastradh{
185403b705cfSriastradh	ScreenPtr screen = dst->pDrawable->pScreen;
185503b705cfSriastradh
185603b705cfSriastradh	if (maskFormat) {
185703b705cfSriastradh		PixmapPtr scratch = NULL;
185803b705cfSriastradh		PicturePtr mask;
185903b705cfSriastradh		INT16 xDst, yDst;
186003b705cfSriastradh		INT16 xRel, yRel;
186103b705cfSriastradh		BoxRec bounds;
186203b705cfSriastradh		int width, height;
186303b705cfSriastradh		pixman_image_t *image;
186403b705cfSriastradh		pixman_format_code_t format;
186503b705cfSriastradh		int error;
186603b705cfSriastradh
186703b705cfSriastradh		xDst = pixman_fixed_to_int(tri[0].p1.x);
186803b705cfSriastradh		yDst = pixman_fixed_to_int(tri[0].p1.y);
186903b705cfSriastradh
187003b705cfSriastradh		miTriangleBounds (ntri, tri, &bounds);
187103b705cfSriastradh		if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
187203b705cfSriastradh			return;
187303b705cfSriastradh
187403b705cfSriastradh		width  = bounds.x2 - bounds.x1;
187503b705cfSriastradh		height = bounds.y2 - bounds.y1;
187603b705cfSriastradh
187703b705cfSriastradh		format = maskFormat->format |
187803b705cfSriastradh			(BitsPerPixel(maskFormat->depth) << 24);
187903b705cfSriastradh		image =
188003b705cfSriastradh		    pixman_image_create_bits(format, width, height, NULL, 0);
188103b705cfSriastradh		if (!image)
188203b705cfSriastradh			return;
188303b705cfSriastradh
188403b705cfSriastradh		pixman_add_triangles(image,
188503b705cfSriastradh				     -bounds.x1, -bounds.y1,
188603b705cfSriastradh				     ntri, (pixman_triangle_t *)tri);
188703b705cfSriastradh
188803b705cfSriastradh		scratch = GetScratchPixmapHeader(screen, width, height,
188903b705cfSriastradh						 PIXMAN_FORMAT_DEPTH(format),
189003b705cfSriastradh						 PIXMAN_FORMAT_BPP(format),
189103b705cfSriastradh						 pixman_image_get_stride(image),
189203b705cfSriastradh						 pixman_image_get_data(image));
189303b705cfSriastradh		if (!scratch) {
189403b705cfSriastradh			pixman_image_unref(image);
189503b705cfSriastradh			return;
189603b705cfSriastradh		}
189703b705cfSriastradh
189803b705cfSriastradh		mask = CreatePicture(0, &scratch->drawable,
189903b705cfSriastradh				     PictureMatchFormat(screen,
190003b705cfSriastradh							PIXMAN_FORMAT_DEPTH(format),
190103b705cfSriastradh							format),
190203b705cfSriastradh				     0, 0, serverClient, &error);
190303b705cfSriastradh		if (!mask) {
190403b705cfSriastradh			FreeScratchPixmapHeader(scratch);
190503b705cfSriastradh			pixman_image_unref(image);
190603b705cfSriastradh			return;
190703b705cfSriastradh		}
190803b705cfSriastradh
190903b705cfSriastradh		xRel = bounds.x1 + xSrc - xDst;
191003b705cfSriastradh		yRel = bounds.y1 + ySrc - yDst;
191103b705cfSriastradh		CompositePicture(op, src, mask, dst,
191203b705cfSriastradh				 xRel, yRel,
191303b705cfSriastradh				 0, 0,
191403b705cfSriastradh				 bounds.x1, bounds.y1,
191503b705cfSriastradh				 width, height);
191603b705cfSriastradh		FreePicture(mask, 0);
191703b705cfSriastradh
191803b705cfSriastradh		FreeScratchPixmapHeader(scratch);
191903b705cfSriastradh		pixman_image_unref(image);
192003b705cfSriastradh	} else {
192103b705cfSriastradh		if (dst->polyEdge == PolyEdgeSharp)
192203b705cfSriastradh			maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
192303b705cfSriastradh		else
192403b705cfSriastradh			maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
192503b705cfSriastradh
192603b705cfSriastradh		for (; ntri; ntri--, tri++)
192703b705cfSriastradh			uxa_check_triangles(op, src, dst, maskFormat, xSrc, ySrc, 1, tri);
192803b705cfSriastradh	}
192903b705cfSriastradh}
193003b705cfSriastradh
193103b705cfSriastradh/**
193203b705cfSriastradh * uxa_triangles is essentially a copy of miTriangles that uses
193303b705cfSriastradh * uxa_create_alpha_picture instead of miCreateAlphaPicture.
193403b705cfSriastradh *
193503b705cfSriastradh * The problem with miCreateAlphaPicture is that it calls PolyFillRect
193603b705cfSriastradh * to initialize the contents after creating the pixmap, which
193703b705cfSriastradh * causes the pixmap to be moved in for acceleration. The subsequent
193803b705cfSriastradh * call to AddTriangles won't be accelerated however, which forces the pixmap
193903b705cfSriastradh * to be moved out again.
194003b705cfSriastradh *
194103b705cfSriastradh * uxa_create_alpha_picture avoids this roundtrip by using
194203b705cfSriastradh * uxa_check_poly_fill_rect to initialize the contents.
194303b705cfSriastradh */
194403b705cfSriastradhvoid
194503b705cfSriastradhuxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
194603b705cfSriastradh	      PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
194703b705cfSriastradh	      int ntri, xTriangle * tris)
194803b705cfSriastradh{
194903b705cfSriastradh	ScreenPtr pScreen = pDst->pDrawable->pScreen;
195003b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
195103b705cfSriastradh	PictureScreenPtr ps = GetPictureScreen(pScreen);
195203b705cfSriastradh	BoxRec bounds;
195303b705cfSriastradh	Bool direct;
195403b705cfSriastradh
195503b705cfSriastradh	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
195603b705cfSriastradh		int ok;
195703b705cfSriastradh
195803b705cfSriastradh		uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW);
195903b705cfSriastradh		uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO);
196003b705cfSriastradh		ok = glamor_triangles_nf(op,
196103b705cfSriastradh				        pSrc, pDst, maskFormat, xSrc,
196203b705cfSriastradh					ySrc, ntri, tris);
196303b705cfSriastradh		uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO);
196403b705cfSriastradh		uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW);
196503b705cfSriastradh
196603b705cfSriastradh		if (!ok)
196703b705cfSriastradh			goto fallback;
196803b705cfSriastradh
196903b705cfSriastradh		return;
197003b705cfSriastradh	}
197103b705cfSriastradh
197203b705cfSriastradh	if (uxa_screen->force_fallback) {
197303b705cfSriastradhfallback:
197403b705cfSriastradh		uxa_check_triangles(op, pSrc, pDst, maskFormat,
197503b705cfSriastradh				    xSrc, ySrc, ntri, tris);
197603b705cfSriastradh		return;
197703b705cfSriastradh	}
197803b705cfSriastradh
197903b705cfSriastradh	direct = op == PictOpAdd && miIsSolidAlpha(pSrc);
198003b705cfSriastradh	if (maskFormat || direct) {
198103b705cfSriastradh		miTriangleBounds(ntri, tris, &bounds);
198203b705cfSriastradh
198303b705cfSriastradh		if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
198403b705cfSriastradh			return;
198503b705cfSriastradh	}
198603b705cfSriastradh
198703b705cfSriastradh	/*
198803b705cfSriastradh	 * Check for solid alpha add
198903b705cfSriastradh	 */
199003b705cfSriastradh	if (direct) {
199103b705cfSriastradh		DrawablePtr pDraw = pDst->pDrawable;
199203b705cfSriastradh		if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
199303b705cfSriastradh			(*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
199403b705cfSriastradh			uxa_finish_access(pDraw, UXA_ACCESS_RW);
199503b705cfSriastradh		}
199603b705cfSriastradh	} else if (maskFormat) {
199703b705cfSriastradh		PicturePtr pPicture;
199803b705cfSriastradh		INT16 xDst, yDst;
199903b705cfSriastradh		INT16 xRel, yRel;
200003b705cfSriastradh		int width = bounds.x2 - bounds.x1;
200103b705cfSriastradh		int height = bounds.y2 - bounds.y1;
200203b705cfSriastradh		GCPtr pGC;
200303b705cfSriastradh		xRectangle rect;
200403b705cfSriastradh
200503b705cfSriastradh		xDst = tris[0].p1.x >> 16;
200603b705cfSriastradh		yDst = tris[0].p1.y >> 16;
200703b705cfSriastradh
200803b705cfSriastradh		pPicture = uxa_create_alpha_picture(pScreen, pDst, maskFormat,
200903b705cfSriastradh						    width, height);
201003b705cfSriastradh		if (!pPicture)
201103b705cfSriastradh			return;
201203b705cfSriastradh
201303b705cfSriastradh		/* Clear the alpha picture to 0. */
201403b705cfSriastradh		pGC = GetScratchGC(pPicture->pDrawable->depth, pScreen);
201503b705cfSriastradh		if (!pGC) {
201603b705cfSriastradh			FreePicture(pPicture, 0);
201703b705cfSriastradh			return;
201803b705cfSriastradh		}
201903b705cfSriastradh		ValidateGC(pPicture->pDrawable, pGC);
202003b705cfSriastradh		rect.x = 0;
202103b705cfSriastradh		rect.y = 0;
202203b705cfSriastradh		rect.width = width;
202303b705cfSriastradh		rect.height = height;
202403b705cfSriastradh		uxa_check_poly_fill_rect(pPicture->pDrawable, pGC, 1, &rect);
202503b705cfSriastradh		FreeScratchGC(pGC);
202603b705cfSriastradh
202703b705cfSriastradh		if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) {
202803b705cfSriastradh			(*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1,
202903b705cfSriastradh					     ntri, tris);
203003b705cfSriastradh			uxa_finish_access(pPicture->pDrawable, UXA_ACCESS_RW);
203103b705cfSriastradh		}
203203b705cfSriastradh
203303b705cfSriastradh		xRel = bounds.x1 + xSrc - xDst;
203403b705cfSriastradh		yRel = bounds.y1 + ySrc - yDst;
203503b705cfSriastradh		CompositePicture(op, pSrc, pPicture, pDst,
203603b705cfSriastradh				 xRel, yRel, 0, 0, bounds.x1, bounds.y1,
203703b705cfSriastradh				 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
203803b705cfSriastradh		FreePicture(pPicture, 0);
203903b705cfSriastradh	} else {
204003b705cfSriastradh		if (pDst->polyEdge == PolyEdgeSharp)
204103b705cfSriastradh			maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
204203b705cfSriastradh		else
204303b705cfSriastradh			maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
204403b705cfSriastradh
204503b705cfSriastradh		for (; ntri; ntri--, tris++)
204603b705cfSriastradh			uxa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1,
204703b705cfSriastradh				      tris);
204803b705cfSriastradh	}
204903b705cfSriastradh}
205003b705cfSriastradh
205103b705cfSriastradhvoid
205203b705cfSriastradhuxa_add_traps(PicturePtr pPicture,
205303b705cfSriastradh	      INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
205403b705cfSriastradh{
205503b705cfSriastradh	ScreenPtr pScreen = pPicture->pDrawable->pScreen;
205603b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
205703b705cfSriastradh
205803b705cfSriastradh	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
205903b705cfSriastradh		int ok;
206003b705cfSriastradh
206103b705cfSriastradh		uxa_picture_prepare_access(pPicture, UXA_GLAMOR_ACCESS_RW);
206203b705cfSriastradh		ok = glamor_add_traps_nf(pPicture,
206303b705cfSriastradh					 x_off, y_off, ntrap, traps);
206403b705cfSriastradh		uxa_picture_finish_access(pPicture, UXA_GLAMOR_ACCESS_RW);
206503b705cfSriastradh
206603b705cfSriastradh		if (!ok)
206703b705cfSriastradh			goto fallback;
206803b705cfSriastradh
206903b705cfSriastradh		return;
207003b705cfSriastradh	}
207103b705cfSriastradh
207203b705cfSriastradhfallback:
207303b705cfSriastradh	uxa_check_add_traps(pPicture, x_off, y_off, ntrap, traps);
207403b705cfSriastradh}
2075