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