uxa-render.c revision 42542f5f
1/*
2 * Copyright © 2001 Keith Packard
3 *
4 * Partly based on code that is Copyright © The XFree86 Project Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission.  Keith Packard makes no
13 * representations about the suitability of this software for any purpose.  It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25#ifdef HAVE_DIX_CONFIG_H
26#include <dix-config.h>
27#endif
28
29#include <stdlib.h>
30
31#include "uxa-priv.h"
32#include "uxa-glamor.h"
33
34#ifdef RENDER
35#include "mipict.h"
36
37/* Note: when using glamor we can not fail through to the ordinary UXA
38 * code paths, as glamor keeps an internal texture which will become
39 * inconsistent with the original bo. (The texture is replaced whenever
40 * the format changes, e.g. switching between xRGB and ARGB, for which mesa
41 * will allocate its own bo.)
42 *
43 * Ergo it is unsafe to fall through to the original backend operations if
44 * glamor is enabled.
45 *
46 * XXX This has some serious implications for mixing Render, DRI, scanout...
47 */
48
49static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string,
50					     int n)
51{
52	char format[20];
53	char size[20];
54	char loc;
55
56	if (!pict) {
57		snprintf(string, n, "None");
58		return;
59	}
60
61	if (pict->pDrawable == NULL) {
62		snprintf(string, n, "source-only");
63		return;
64	}
65
66	switch (pict->format) {
67	case PICT_a8r8g8b8:
68		snprintf(format, 20, "ARGB8888");
69		break;
70	case PICT_x8r8g8b8:
71		snprintf(format, 20, "XRGB8888");
72		break;
73	case PICT_r5g6b5:
74		snprintf(format, 20, "RGB565  ");
75		break;
76	case PICT_x1r5g5b5:
77		snprintf(format, 20, "RGB555  ");
78		break;
79	case PICT_a8:
80		snprintf(format, 20, "A8      ");
81		break;
82	case PICT_a1:
83		snprintf(format, 20, "A1      ");
84		break;
85	default:
86		snprintf(format, 20, "0x%x", (int)pict->format);
87		break;
88	}
89
90	loc = uxa_drawable_is_offscreen(pict->pDrawable) ? 's' : 'm';
91
92	snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
93		 pict->pDrawable->height, pict->repeat ? " R" : "");
94
95	snprintf(string, n, "%p:%c fmt %s (%s)%s",
96		 pict->pDrawable, loc, format, size,
97		 pict->alphaMap ? " with alpha map" :"");
98}
99
100static const char *
101op_to_string(CARD8 op)
102{
103    switch (op) {
104#define C(x) case PictOp##x: return #x
105	C(Clear);
106	C(Src);
107	C(Dst);
108	C(Over);
109	C(OverReverse);
110	C(In);
111	C(InReverse);
112	C(Out);
113	C(OutReverse);
114	C(Atop);
115	C(AtopReverse);
116	C(Xor);
117	C(Add);
118	C(Saturate);
119
120	/*
121	 * Operators only available in version 0.2
122	 */
123#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 2
124	C(DisjointClear);
125	C(DisjointSrc);
126	C(DisjointDst);
127	C(DisjointOver);
128	C(DisjointOverReverse);
129	C(DisjointIn);
130	C(DisjointInReverse);
131	C(DisjointOut);
132	C(DisjointOutReverse);
133	C(DisjointAtop);
134	C(DisjointAtopReverse);
135	C(DisjointXor);
136
137	C(ConjointClear);
138	C(ConjointSrc);
139	C(ConjointDst);
140	C(ConjointOver);
141	C(ConjointOverReverse);
142	C(ConjointIn);
143	C(ConjointInReverse);
144	C(ConjointOut);
145	C(ConjointOutReverse);
146	C(ConjointAtop);
147	C(ConjointAtopReverse);
148	C(ConjointXor);
149#endif
150
151	/*
152	 * Operators only available in version 0.11
153	 */
154#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 11
155	C(Multiply);
156	C(Screen);
157	C(Overlay);
158	C(Darken);
159	C(Lighten);
160	C(ColorDodge);
161	C(ColorBurn);
162	C(HardLight);
163	C(SoftLight);
164	C(Difference);
165	C(Exclusion);
166	C(HSLHue);
167	C(HSLSaturation);
168	C(HSLColor);
169	C(HSLLuminosity);
170#endif
171    default: return "garbage";
172#undef C
173    }
174}
175
176static void
177uxa_print_composite_fallback(const char *func, CARD8 op,
178			     PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst)
179{
180	uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
181	char srcdesc[40], maskdesc[40], dstdesc[40];
182
183	if (! uxa_screen->fallback_debug)
184		return;
185
186	/* Limit the noise if fallbacks are expected. */
187	if (uxa_screen->force_fallback)
188		return;
189
190	uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40);
191	uxa_composite_fallback_pict_desc(pMask, maskdesc, 40);
192	uxa_composite_fallback_pict_desc(pDst, dstdesc, 40);
193
194	ErrorF("Composite fallback at %s:\n"
195	       "  op   %s, \n"
196	       "  src  %s, \n"
197	       "  mask %s, \n"
198	       "  dst  %s, \n",
199	       func, op_to_string (op), srcdesc, maskdesc, dstdesc);
200}
201
202Bool uxa_op_reads_destination(CARD8 op)
203{
204	/* FALSE (does not read destination) is the list of ops in the protocol
205	 * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
206	 * That's just Clear and Src.  ReduceCompositeOp() will already have
207	 * converted con/disjoint clear/src to Clear or Src.
208	 */
209	switch (op) {
210	case PictOpClear:
211	case PictOpSrc:
212		return FALSE;
213	default:
214		return TRUE;
215	}
216}
217
218static Bool
219uxa_get_pixel_from_rgba(CARD32 * pixel,
220			CARD16 red,
221			CARD16 green,
222			CARD16 blue,
223			CARD16 alpha,
224			CARD32 format)
225{
226	int rbits, bbits, gbits, abits;
227	int rshift, bshift, gshift, ashift;
228
229	rbits = PICT_FORMAT_R(format);
230	gbits = PICT_FORMAT_G(format);
231	bbits = PICT_FORMAT_B(format);
232	abits = PICT_FORMAT_A(format);
233	if (abits == 0)
234	    abits = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits);
235
236	if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
237		*pixel = alpha >> (16 - abits);
238		return TRUE;
239	}
240
241	if (!PICT_FORMAT_COLOR(format))
242		return FALSE;
243
244	if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
245		bshift = 0;
246		gshift = bbits;
247		rshift = gshift + gbits;
248		ashift = rshift + rbits;
249	} else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
250		rshift = 0;
251		gshift = rbits;
252		bshift = gshift + gbits;
253		ashift = bshift + bbits;
254#if XORG_VERSION_CURRENT >= 10699900
255	} else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
256		ashift = 0;
257		rshift = abits;
258		gshift = rshift + rbits;
259		bshift = gshift + gbits;
260#endif
261	} else {
262		return FALSE;
263	}
264
265	*pixel = 0;
266	*pixel |= (blue  >> (16 - bbits)) << bshift;
267	*pixel |= (green >> (16 - gbits)) << gshift;
268	*pixel |= (red   >> (16 - rbits)) << rshift;
269	*pixel |= (alpha >> (16 - abits)) << ashift;
270
271	return TRUE;
272}
273
274Bool
275uxa_get_rgba_from_pixel(CARD32 pixel,
276			CARD16 * red,
277			CARD16 * green,
278			CARD16 * blue,
279			CARD16 * alpha,
280			CARD32 format)
281{
282	int rbits, bbits, gbits, abits;
283	int rshift, bshift, gshift, ashift;
284
285	rbits = PICT_FORMAT_R(format);
286	gbits = PICT_FORMAT_G(format);
287	bbits = PICT_FORMAT_B(format);
288	abits = PICT_FORMAT_A(format);
289
290	if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
291		rshift = gshift = bshift = ashift = 0;
292        } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
293		bshift = 0;
294		gshift = bbits;
295		rshift = gshift + gbits;
296		ashift = rshift + rbits;
297        } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
298		rshift = 0;
299		gshift = rbits;
300		bshift = gshift + gbits;
301		ashift = bshift + bbits;
302#if XORG_VERSION_CURRENT >= 10699900
303        } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
304		ashift = 0;
305		rshift = abits;
306		if (abits == 0)
307			rshift = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits);
308		gshift = rshift + rbits;
309		bshift = gshift + gbits;
310#endif
311	} else {
312		return FALSE;
313	}
314
315	if (rbits) {
316		*red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits);
317		while (rbits < 16) {
318			*red |= *red >> rbits;
319			rbits <<= 1;
320		}
321	} else
322		*red = 0;
323
324	if (gbits) {
325		*green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits);
326		while (gbits < 16) {
327			*green |= *green >> gbits;
328			gbits <<= 1;
329		}
330	} else
331		*green = 0;
332
333	if (bbits) {
334		*blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits);
335		while (bbits < 16) {
336			*blue |= *blue >> bbits;
337			bbits <<= 1;
338		}
339	} else
340		*blue = 0;
341
342	if (abits) {
343		*alpha =
344		    ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits);
345		while (abits < 16) {
346			*alpha |= *alpha >> abits;
347			abits <<= 1;
348		}
349	} else
350		*alpha = 0xffff;
351
352	return TRUE;
353}
354
355Bool
356uxa_get_color_for_pixmap (PixmapPtr	 pixmap,
357			  CARD32	 src_format,
358			  CARD32	 dst_format,
359			  CARD32	*pixel)
360{
361	CARD16 red, green, blue, alpha;
362
363	*pixel = uxa_get_pixmap_first_pixel(pixmap);
364
365	if (src_format != dst_format) {
366	    if (!uxa_get_rgba_from_pixel(*pixel,
367					 &red, &green, &blue, &alpha,
368					 src_format))
369		return FALSE;
370
371	    if (!uxa_get_pixel_from_rgba(pixel,
372					 red, green, blue, alpha,
373					 dst_format))
374		return FALSE;
375	}
376
377	return TRUE;
378}
379
380static int
381uxa_try_driver_solid_fill(PicturePtr pSrc,
382			  PicturePtr pDst,
383			  INT16 xSrc,
384			  INT16 ySrc,
385			  INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
386{
387	uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
388	RegionRec region;
389	BoxPtr pbox;
390	int nbox;
391	int dst_off_x, dst_off_y;
392	PixmapPtr pSrcPix = NULL, pDstPix;
393	CARD32 pixel;
394
395	if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDst->pDrawable, GXcopy, FB_ALLONES))
396		return -1;
397
398	pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
399	if (!pDstPix)
400		return -1;
401
402	xDst += pDst->pDrawable->x;
403	yDst += pDst->pDrawable->y;
404
405	if (pSrc->pDrawable) {
406		pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
407		xSrc += pSrc->pDrawable->x;
408		ySrc += pSrc->pDrawable->y;
409	}
410
411	if (!miComputeCompositeRegion(&region, pSrc, NULL, pDst,
412				      xSrc, ySrc, 0, 0, xDst, yDst,
413				      width, height))
414		return 1;
415
416	if (pSrcPix) {
417		if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) {
418			REGION_UNINIT(pDst->pDrawable->pScreen, &region);
419			return -1;
420		}
421	} else {
422		SourcePict *source = pSrc->pSourcePict;
423		PictSolidFill *solid = &source->solidFill;
424
425		if (source == NULL || source->type != SourcePictTypeSolidFill) {
426			REGION_UNINIT(pDst->pDrawable->pScreen, &region);
427			return -1;
428		}
429
430		if (pDst->format == PICT_a8r8g8b8) {
431			pixel = solid->color;
432		} else if (pDst->format == PICT_x8r8g8b8) {
433			pixel = solid->color | 0xff000000;
434		} else {
435			CARD16 red, green, blue, alpha;
436
437			if (!uxa_get_rgba_from_pixel(solid->color,
438						     &red, &green, &blue, &alpha,
439						     PICT_a8r8g8b8) ||
440			    !uxa_get_pixel_from_rgba(&pixel,
441						     red, green, blue, alpha,
442						     pDst->format)) {
443				REGION_UNINIT(pDst->pDrawable->pScreen, &region);
444				return -1;
445			}
446		}
447	}
448
449	if (!(*uxa_screen->info->prepare_solid)
450	    (pDstPix, GXcopy, FB_ALLONES, pixel)) {
451		REGION_UNINIT(pDst->pDrawable->pScreen, &region);
452		return -1;
453	}
454
455	REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
456
457	nbox = REGION_NUM_RECTS(&region);
458	pbox = REGION_RECTS(&region);
459
460	while (nbox--) {
461		(*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1,
462					    pbox->x2, pbox->y2);
463		pbox++;
464	}
465
466	(*uxa_screen->info->done_solid) (pDstPix);
467
468	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
469	return 1;
470}
471
472static PicturePtr
473uxa_picture_for_pixman_format(ScreenPtr screen,
474			      pixman_format_code_t format,
475			      int width, int height)
476{
477	PicturePtr picture;
478	PixmapPtr pixmap;
479	int error;
480
481	if (format == PIXMAN_a1)
482		format = PIXMAN_a8;
483
484	/* fill alpha if unset */
485	if (PIXMAN_FORMAT_A(format) == 0)
486	    format = PIXMAN_a8r8g8b8;
487
488	pixmap = screen->CreatePixmap(screen, width, height,
489					PIXMAN_FORMAT_DEPTH(format),
490					UXA_CREATE_PIXMAP_FOR_MAP);
491	if (!pixmap)
492		return 0;
493
494	if (!uxa_pixmap_is_offscreen(pixmap)) {
495		screen->DestroyPixmap(pixmap);
496		return 0;
497	}
498
499	picture = CreatePicture(0, &pixmap->drawable,
500				PictureMatchFormat(screen,
501						   PIXMAN_FORMAT_DEPTH(format),
502						   format),
503				0, 0, serverClient, &error);
504	screen->DestroyPixmap(pixmap);
505	if (!picture)
506		return 0;
507
508	ValidatePicture(picture);
509
510	return picture;
511}
512
513static PicturePtr
514uxa_picture_from_pixman_image(ScreenPtr screen,
515			      pixman_image_t * image,
516			      pixman_format_code_t format)
517{
518	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
519	PicturePtr picture;
520	PixmapPtr pixmap;
521	int width, height;
522
523	width = pixman_image_get_width(image);
524	height = pixman_image_get_height(image);
525
526	picture = uxa_picture_for_pixman_format(screen, format,
527						width, height);
528	if (!picture)
529		return 0;
530
531	if (uxa_screen->info->put_image &&
532	    ((picture->pDrawable->depth << 24) | picture->format) == format &&
533	    uxa_screen->info->put_image((PixmapPtr)picture->pDrawable,
534					0, 0,
535					width, height,
536					(char *)pixman_image_get_data(image),
537					pixman_image_get_stride(image)))
538		return picture;
539
540	pixmap = GetScratchPixmapHeader(screen, width, height,
541					PIXMAN_FORMAT_DEPTH(format),
542					PIXMAN_FORMAT_BPP(format),
543					pixman_image_get_stride(image),
544					pixman_image_get_data(image));
545	if (!pixmap) {
546		FreePicture(picture, 0);
547		return 0;
548	}
549
550	if (((picture->pDrawable->depth << 24) | picture->format) == format) {
551		GCPtr gc;
552
553		gc = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), screen);
554		if (!gc) {
555			FreeScratchPixmapHeader(pixmap);
556			FreePicture(picture, 0);
557			return 0;
558		}
559		ValidateGC(picture->pDrawable, gc);
560
561		(*gc->ops->CopyArea) (&pixmap->drawable, picture->pDrawable,
562				      gc, 0, 0, width, height, 0, 0);
563
564		FreeScratchGC(gc);
565	} else {
566		PicturePtr src;
567		int error;
568
569		src = CreatePicture(0, &pixmap->drawable,
570				    PictureMatchFormat(screen,
571						       PIXMAN_FORMAT_DEPTH(format),
572						       format),
573				    0, 0, serverClient, &error);
574		if (!src) {
575			FreeScratchPixmapHeader(pixmap);
576			FreePicture(picture, 0);
577			return 0;
578		}
579		ValidatePicture(src);
580
581		if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) {
582			fbComposite(PictOpSrc, src, NULL, picture,
583				    0, 0, 0, 0, 0, 0, width, height);
584			uxa_picture_finish_access(picture, UXA_ACCESS_RW);
585		}
586
587		FreePicture(src, 0);
588	}
589	FreeScratchPixmapHeader(pixmap);
590
591	return picture;
592}
593
594static PicturePtr
595uxa_create_solid(ScreenPtr screen, uint32_t color)
596{
597	PixmapPtr pixmap;
598	PicturePtr picture;
599	XID repeat = RepeatNormal;
600	int error = 0;
601
602	pixmap = (*screen->CreatePixmap)(screen, 1, 1, 32,
603					 UXA_CREATE_PIXMAP_FOR_MAP);
604	if (!pixmap)
605		return 0;
606
607	if (!uxa_prepare_access((DrawablePtr)pixmap, UXA_ACCESS_RW)) {
608		(*screen->DestroyPixmap)(pixmap);
609		return 0;
610	}
611	*((uint32_t *)pixmap->devPrivate.ptr) = color;
612	uxa_finish_access((DrawablePtr)pixmap, UXA_ACCESS_RW);
613
614	picture = CreatePicture(0, &pixmap->drawable,
615				PictureMatchFormat(screen, 32, PICT_a8r8g8b8),
616				CPRepeat, &repeat, serverClient, &error);
617	(*screen->DestroyPixmap)(pixmap);
618
619	return picture;
620}
621
622static PicturePtr
623uxa_solid_clear(ScreenPtr screen)
624{
625	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
626	PicturePtr picture;
627
628	if (!uxa_screen->solid_clear) {
629		uxa_screen->solid_clear = uxa_create_solid(screen, 0);
630		if (!uxa_screen->solid_clear)
631			return 0;
632	}
633	picture = uxa_screen->solid_clear;
634	return picture;
635}
636
637PicturePtr
638uxa_acquire_solid(ScreenPtr screen, SourcePict *source)
639{
640	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
641	PictSolidFill *solid = &source->solidFill;
642	PicturePtr picture;
643	int i;
644
645	if ((solid->color >> 24) == 0) {
646		picture = uxa_solid_clear(screen);
647		if (!picture)
648		    return 0;
649
650		goto DONE;
651	} else if (solid->color == 0xff000000) {
652		if (!uxa_screen->solid_black) {
653			uxa_screen->solid_black = uxa_create_solid(screen, 0xff000000);
654			if (!uxa_screen->solid_black)
655				return 0;
656		}
657		picture = uxa_screen->solid_black;
658		goto DONE;
659	} else if (solid->color == 0xffffffff) {
660		if (!uxa_screen->solid_white) {
661			uxa_screen->solid_white = uxa_create_solid(screen, 0xffffffff);
662			if (!uxa_screen->solid_white)
663				return 0;
664		}
665		picture = uxa_screen->solid_white;
666		goto DONE;
667	}
668
669	for (i = 0; i < uxa_screen->solid_cache_size; i++) {
670		if (uxa_screen->solid_cache[i].color == solid->color) {
671			picture = uxa_screen->solid_cache[i].picture;
672			goto DONE;
673		}
674	}
675
676	picture = uxa_create_solid(screen, solid->color);
677	if (!picture)
678		return 0;
679
680	if (uxa_screen->solid_cache_size == UXA_NUM_SOLID_CACHE) {
681		i = rand() % UXA_NUM_SOLID_CACHE;
682		FreePicture(uxa_screen->solid_cache[i].picture, 0);
683	} else
684		uxa_screen->solid_cache_size++;
685
686	uxa_screen->solid_cache[i].picture = picture;
687	uxa_screen->solid_cache[i].color = solid->color;
688
689DONE:
690	picture->refcnt++;
691	return picture;
692}
693
694PicturePtr
695uxa_acquire_pattern(ScreenPtr pScreen,
696		    PicturePtr pSrc,
697		    pixman_format_code_t format,
698		    INT16 x, INT16 y, CARD16 width, CARD16 height)
699{
700	PicturePtr pDst;
701
702	if (pSrc->pSourcePict) {
703		SourcePict *source = pSrc->pSourcePict;
704		if (source->type == SourcePictTypeSolidFill)
705			return uxa_acquire_solid (pScreen, source);
706	}
707
708	pDst = uxa_picture_for_pixman_format(pScreen, format, width, height);
709	if (!pDst)
710		return 0;
711
712	if (uxa_picture_prepare_access(pDst, UXA_ACCESS_RW)) {
713		fbComposite(PictOpSrc, pSrc, NULL, pDst,
714			    x, y, 0, 0, 0, 0, width, height);
715		uxa_picture_finish_access(pDst, UXA_ACCESS_RW);
716		return pDst;
717	} else {
718		FreePicture(pDst, 0);
719		return 0;
720	}
721}
722
723static Bool
724transform_is_integer_translation(PictTransformPtr t, int *tx, int *ty)
725{
726	if (t == NULL) {
727		*tx = *ty = 0;
728		return TRUE;
729	}
730
731	if (t->matrix[0][0] != IntToxFixed(1) ||
732	    t->matrix[0][1] != 0 ||
733	    t->matrix[1][0] != 0 ||
734	    t->matrix[1][1] != IntToxFixed(1) ||
735	    t->matrix[2][0] != 0 ||
736	    t->matrix[2][1] != 0 ||
737	    t->matrix[2][2] != IntToxFixed(1))
738		return FALSE;
739
740	if (xFixedFrac(t->matrix[0][2]) != 0 ||
741	    xFixedFrac(t->matrix[1][2]) != 0)
742		return FALSE;
743
744	*tx = xFixedToInt(t->matrix[0][2]);
745	*ty = xFixedToInt(t->matrix[1][2]);
746	return TRUE;
747}
748
749static PicturePtr
750uxa_render_picture(ScreenPtr screen,
751		   PicturePtr src,
752		   pixman_format_code_t format,
753		   INT16 x, INT16 y,
754		   CARD16 width, CARD16 height)
755{
756	PicturePtr picture;
757	int ret = 0;
758
759	/* XXX we need a mechanism for the card to choose the fallback format */
760
761	/* force alpha channel in case source does not entirely cover the extents */
762	if (PIXMAN_FORMAT_A(format) == 0)
763		format = PIXMAN_a8r8g8b8; /* available on all hardware */
764
765	picture = uxa_picture_for_pixman_format(screen, format, width, height);
766	if (!picture)
767		return 0;
768
769	if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) {
770		if (uxa_picture_prepare_access(src, UXA_ACCESS_RO)) {
771			ret = 1;
772			fbComposite(PictOpSrc, src, NULL, picture,
773				    x, y, 0, 0, 0, 0, width, height);
774			uxa_picture_finish_access(src, UXA_ACCESS_RO);
775		}
776		uxa_picture_finish_access(picture, UXA_ACCESS_RW);
777	}
778
779	if (!ret) {
780		FreePicture(picture, 0);
781		return 0;
782	}
783
784	return picture;
785}
786
787static int
788drawable_contains (DrawablePtr drawable, int x, int y, int w, int h)
789{
790	if (x < 0 || y < 0)
791		return FALSE;
792
793	if (x + w > drawable->width)
794		return FALSE;
795
796	if (y + h > drawable->height)
797		return FALSE;
798
799	return TRUE;
800}
801
802PicturePtr
803uxa_acquire_drawable(ScreenPtr pScreen,
804		     PicturePtr pSrc,
805		     INT16 x, INT16 y,
806		     CARD16 width, CARD16 height,
807		     INT16 * out_x, INT16 * out_y)
808{
809	PixmapPtr pPixmap;
810	PicturePtr pDst;
811	int depth, error;
812	int tx, ty;
813	GCPtr pGC;
814
815	depth = pSrc->pDrawable->depth;
816	if (!transform_is_integer_translation(pSrc->transform, &tx, &ty) ||
817	    !drawable_contains(pSrc->pDrawable, x + tx, y + ty, width, height) ||
818	    depth == 1 ||
819	    pSrc->filter == PictFilterConvolution) {
820		/* XXX extract the sample extents and do the transformation on the GPU */
821		pDst = uxa_render_picture(pScreen, pSrc,
822					  pSrc->format | (BitsPerPixel(pSrc->pDrawable->depth) << 24),
823					  x, y, width, height);
824		if (!pDst)
825			return 0;
826
827		goto done;
828	} else {
829		if (width == pSrc->pDrawable->width && height == pSrc->pDrawable->height) {
830			*out_x = x + pSrc->pDrawable->x;
831			*out_y = y + pSrc->pDrawable->y;
832			return pSrc;
833		}
834	}
835
836	pPixmap = pScreen->CreatePixmap(pScreen,
837					width, height, depth,
838					CREATE_PIXMAP_USAGE_SCRATCH);
839	if (!pPixmap)
840		return 0;
841
842	/* Skip the copy if the result remains in memory and not a bo */
843	if (!uxa_pixmap_is_offscreen(pPixmap)) {
844		pScreen->DestroyPixmap(pPixmap);
845		return 0;
846	}
847
848	pGC = GetScratchGC(depth, pScreen);
849	if (!pGC) {
850		pScreen->DestroyPixmap(pPixmap);
851		return 0;
852	}
853
854	ValidateGC(&pPixmap->drawable, pGC);
855	pGC->ops->CopyArea(pSrc->pDrawable, &pPixmap->drawable, pGC,
856			   x + tx, y + ty, width, height, 0, 0);
857	FreeScratchGC(pGC);
858
859	pDst = CreatePicture(0, &pPixmap->drawable,
860			     PictureMatchFormat(pScreen, depth, pSrc->format),
861			     0, 0, serverClient, &error);
862	pScreen->DestroyPixmap(pPixmap);
863	if (!pDst)
864		return 0;
865
866	ValidatePicture(pDst);
867done:
868	pDst->componentAlpha = pSrc->componentAlpha;
869	*out_x = 0;
870	*out_y = 0;
871	return pDst;
872}
873
874static PicturePtr
875uxa_acquire_picture(ScreenPtr screen,
876		    PicturePtr src,
877		    pixman_format_code_t format,
878		    INT16 x, INT16 y,
879		    CARD16 width, CARD16 height,
880		    INT16 * out_x, INT16 * out_y)
881{
882	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
883
884	if (uxa_screen->info->check_composite_texture &&
885	    uxa_screen->info->check_composite_texture(screen, src)) {
886		if (src->pDrawable) {
887			*out_x = x + src->pDrawable->x;
888			*out_y = y + src->pDrawable->y;
889		} else {
890			*out_x = x;
891			*out_y = y;
892		}
893		return src;
894	}
895
896	if (src->pDrawable) {
897		PicturePtr dst;
898
899		dst = uxa_acquire_drawable(screen, src,
900					   x, y, width, height,
901					   out_x, out_y);
902		if (!dst)
903			return 0;
904
905		if (uxa_screen->info->check_composite_texture &&
906		    !uxa_screen->info->check_composite_texture(screen, dst)) {
907			if (dst != src)
908				FreePicture(dst, 0);
909			return 0;
910		}
911
912		return dst;
913	}
914
915	*out_x = 0;
916	*out_y = 0;
917	return uxa_acquire_pattern(screen, src,
918				   format, x, y, width, height);
919}
920
921static PicturePtr
922uxa_acquire_source(ScreenPtr screen,
923		   PicturePtr pict,
924		   INT16 x, INT16 y,
925		   CARD16 width, CARD16 height,
926		   INT16 * out_x, INT16 * out_y)
927{
928	return uxa_acquire_picture (screen, pict,
929				    PIXMAN_a8r8g8b8,
930				    x, y,
931				    width, height,
932				    out_x, out_y);
933}
934
935static PicturePtr
936uxa_acquire_mask(ScreenPtr screen,
937		 PicturePtr pict,
938		 INT16 x, INT16 y,
939		 INT16 width, INT16 height,
940		 INT16 * out_x, INT16 * out_y)
941{
942	return uxa_acquire_picture (screen, pict,
943				    PIXMAN_a8,
944				    x, y,
945				    width, height,
946				    out_x, out_y);
947}
948
949static int
950uxa_try_driver_composite(CARD8 op,
951			 PicturePtr pSrc,
952			 PicturePtr pMask,
953			 PicturePtr pDst,
954			 INT16 xSrc, INT16 ySrc,
955			 INT16 xMask, INT16 yMask,
956			 INT16 xDst, INT16 yDst,
957			 CARD16 width, CARD16 height)
958{
959	ScreenPtr screen = pDst->pDrawable->pScreen;
960	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
961	RegionRec region;
962	BoxPtr pbox;
963	int nbox;
964	int xDst_copy = 0, yDst_copy = 0;
965	int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
966	PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
967	PicturePtr localSrc, localMask = NULL;
968	PicturePtr localDst = pDst;
969
970	if (uxa_screen->info->check_composite &&
971	    !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst, width, height))
972		return -1;
973
974	if (uxa_screen->info->check_composite_target &&
975	    !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
976		int depth = pDst->pDrawable->depth;
977		PixmapPtr pixmap;
978		int error;
979		GCPtr gc;
980
981		pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
982		if (uxa_screen->info->check_copy &&
983		    !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
984			return -1;
985
986		pixmap = screen->CreatePixmap(screen,
987					      width, height, depth,
988					      CREATE_PIXMAP_USAGE_SCRATCH);
989		if (!pixmap)
990			return 0;
991
992		gc = GetScratchGC(depth, screen);
993		if (!gc) {
994			screen->DestroyPixmap(pixmap);
995			return 0;
996		}
997
998		ValidateGC(&pixmap->drawable, gc);
999		gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
1000				  xDst, yDst, width, height, 0, 0);
1001		FreeScratchGC(gc);
1002
1003		xDst_copy = xDst; xDst = 0;
1004		yDst_copy = yDst; yDst = 0;
1005
1006		localDst = CreatePicture(0, &pixmap->drawable,
1007					 PictureMatchFormat(screen, depth, pDst->format),
1008					 0, 0, serverClient, &error);
1009		screen->DestroyPixmap(pixmap);
1010
1011		if (!localDst)
1012			return 0;
1013
1014		ValidatePicture(localDst);
1015	}
1016
1017	pDstPix =
1018	    uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y);
1019	if (!pDstPix) {
1020		if (localDst != pDst)
1021			FreePicture(localDst, 0);
1022		return -1;
1023	}
1024
1025	xDst += localDst->pDrawable->x;
1026	yDst += localDst->pDrawable->y;
1027
1028	localSrc = uxa_acquire_source(screen, pSrc,
1029				      xSrc, ySrc,
1030				      width, height,
1031				      &xSrc, &ySrc);
1032	if (!localSrc) {
1033		if (localDst != pDst)
1034			FreePicture(localDst, 0);
1035		return 0;
1036	}
1037
1038	if (pMask) {
1039		localMask = uxa_acquire_mask(screen, pMask,
1040					     xMask, yMask,
1041					     width, height,
1042					     &xMask, &yMask);
1043		if (!localMask) {
1044			if (localSrc != pSrc)
1045				FreePicture(localSrc, 0);
1046			if (localDst != pDst)
1047				FreePicture(localDst, 0);
1048
1049			return 0;
1050		}
1051	}
1052
1053	if (!miComputeCompositeRegion(&region, localSrc, localMask, localDst,
1054				      xSrc, ySrc, xMask, yMask, xDst, yDst,
1055				      width, height)) {
1056		if (localSrc != pSrc)
1057			FreePicture(localSrc, 0);
1058		if (localMask && localMask != pMask)
1059			FreePicture(localMask, 0);
1060		if (localDst != pDst)
1061			FreePicture(localDst, 0);
1062
1063		return 1;
1064	}
1065
1066	pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable,
1067					   &src_off_x, &src_off_y);
1068	if (!pSrcPix) {
1069		REGION_UNINIT(screen, &region);
1070
1071		if (localSrc != pSrc)
1072			FreePicture(localSrc, 0);
1073		if (localMask && localMask != pMask)
1074			FreePicture(localMask, 0);
1075		if (localDst != pDst)
1076			FreePicture(localDst, 0);
1077
1078		return 0;
1079	}
1080
1081	if (localMask) {
1082		pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable,
1083						    &mask_off_x, &mask_off_y);
1084		if (!pMaskPix) {
1085			REGION_UNINIT(screen, &region);
1086
1087			if (localSrc != pSrc)
1088				FreePicture(localSrc, 0);
1089			if (localMask && localMask != pMask)
1090				FreePicture(localMask, 0);
1091			if (localDst != pDst)
1092				FreePicture(localDst, 0);
1093
1094			return 0;
1095		}
1096	}
1097
1098	if (!(*uxa_screen->info->prepare_composite)
1099	    (op, localSrc, localMask, localDst, pSrcPix, pMaskPix, pDstPix)) {
1100		REGION_UNINIT(screen, &region);
1101
1102		if (localSrc != pSrc)
1103			FreePicture(localSrc, 0);
1104		if (localMask && localMask != pMask)
1105			FreePicture(localMask, 0);
1106		if (localDst != pDst)
1107			FreePicture(localDst, 0);
1108
1109		return -1;
1110	}
1111
1112	if (pMask) {
1113		xMask = xMask + mask_off_x - xDst;
1114		yMask = yMask + mask_off_y - yDst;
1115	}
1116
1117	xSrc = xSrc + src_off_x - xDst;
1118	ySrc = ySrc + src_off_y - yDst;
1119
1120	nbox = REGION_NUM_RECTS(&region);
1121	pbox = REGION_RECTS(&region);
1122	while (nbox--) {
1123		(*uxa_screen->info->composite) (pDstPix,
1124						pbox->x1 + xSrc,
1125						pbox->y1 + ySrc,
1126						pbox->x1 + xMask,
1127						pbox->y1 + yMask,
1128						pbox->x1 + dst_off_x,
1129						pbox->y1 + dst_off_y,
1130						pbox->x2 - pbox->x1,
1131						pbox->y2 - pbox->y1);
1132		pbox++;
1133	}
1134	(*uxa_screen->info->done_composite) (pDstPix);
1135
1136	REGION_UNINIT(screen, &region);
1137
1138	if (localSrc != pSrc)
1139		FreePicture(localSrc, 0);
1140	if (localMask && localMask != pMask)
1141		FreePicture(localMask, 0);
1142
1143	if (localDst != pDst) {
1144		GCPtr gc;
1145
1146		gc = GetScratchGC(pDst->pDrawable->depth, screen);
1147		if (gc) {
1148			ValidateGC(pDst->pDrawable, gc);
1149			gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
1150					  0, 0, width, height, xDst_copy, yDst_copy);
1151			FreeScratchGC(gc);
1152		}
1153
1154		FreePicture(localDst, 0);
1155	}
1156
1157	return 1;
1158}
1159
1160/**
1161 * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of
1162 * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
1163 * alpha and limited 1-tmu cards.
1164 *
1165 * From http://anholt.livejournal.com/32058.html:
1166 *
1167 * The trouble is that component-alpha rendering requires two different sources
1168 * for blending: one for the source value to the blender, which is the
1169 * per-channel multiplication of source and mask, and one for the source alpha
1170 * for multiplying with the destination channels, which is the multiplication
1171 * of the source channels by the mask alpha. So the equation for Over is:
1172 *
1173 * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
1174 * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
1175 * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
1176 * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
1177 *
1178 * But we can do some simpler operations, right? How about PictOpOutReverse,
1179 * which has a source factor of 0 and dest factor of (1 - source alpha). We
1180 * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
1181 * blenders pretty easily. So we can do a component-alpha OutReverse, which
1182 * gets us:
1183 *
1184 * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
1185 * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
1186 * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
1187 * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
1188 *
1189 * OK. And if an op doesn't use the source alpha value for the destination
1190 * factor, then we can do the channel multiplication in the texture blenders
1191 * to get the source value, and ignore the source alpha that we wouldn't use.
1192 * We've supported this in the Radeon driver for a long time. An example would
1193 * be PictOpAdd, which does:
1194 *
1195 * dst.A = src.A * mask.A + dst.A
1196 * dst.R = src.R * mask.R + dst.R
1197 * dst.G = src.G * mask.G + dst.G
1198 * dst.B = src.B * mask.B + dst.B
1199 *
1200 * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
1201 * after it, we get:
1202 *
1203 * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
1204 * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
1205 * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
1206 * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
1207 */
1208
1209static int
1210uxa_try_magic_two_pass_composite_helper(CARD8 op,
1211					PicturePtr pSrc,
1212					PicturePtr pMask,
1213					PicturePtr pDst,
1214					INT16 xSrc, INT16 ySrc,
1215					INT16 xMask, INT16 yMask,
1216					INT16 xDst, INT16 yDst,
1217					CARD16 width, CARD16 height)
1218{
1219	ScreenPtr screen = pDst->pDrawable->pScreen;
1220	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
1221	PicturePtr localDst = pDst;
1222	int xDst_copy, yDst_copy;
1223
1224	assert(op == PictOpOver);
1225
1226	if (uxa_screen->info->check_composite &&
1227	    (!(*uxa_screen->info->check_composite) (PictOpOutReverse, pSrc,
1228						    pMask, pDst, width, height)
1229	     || !(*uxa_screen->info->check_composite) (PictOpAdd, pSrc, pMask,
1230						       pDst, width, height))) {
1231		return -1;
1232	}
1233
1234	if (uxa_screen->info->check_composite_target &&
1235	    !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
1236		int depth = pDst->pDrawable->depth;
1237		PixmapPtr pixmap;
1238		int error;
1239		GCPtr gc;
1240
1241		pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
1242		if (uxa_screen->info->check_copy &&
1243		    !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
1244			return -1;
1245
1246		pixmap = screen->CreatePixmap(screen,
1247					      width, height, depth,
1248					      CREATE_PIXMAP_USAGE_SCRATCH);
1249		if (!pixmap)
1250			return 0;
1251
1252		gc = GetScratchGC(depth, screen);
1253		if (!gc) {
1254			screen->DestroyPixmap(pixmap);
1255			return 0;
1256		}
1257
1258		ValidateGC(&pixmap->drawable, gc);
1259		gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
1260				  xDst, yDst, width, height, 0, 0);
1261		FreeScratchGC(gc);
1262
1263		xDst_copy = xDst; xDst = 0;
1264		yDst_copy = yDst; yDst = 0;
1265
1266		localDst = CreatePicture(0, &pixmap->drawable,
1267					 PictureMatchFormat(screen, depth, pDst->format),
1268					 0, 0, serverClient, &error);
1269		screen->DestroyPixmap(pixmap);
1270
1271		if (!localDst)
1272			return 0;
1273
1274		ValidatePicture(localDst);
1275	}
1276
1277	/* Now, we think we should be able to accelerate this operation. First,
1278	 * composite the destination to be the destination times the source alpha
1279	 * factors.
1280	 */
1281	uxa_composite(PictOpOutReverse, pSrc, pMask, localDst,
1282		      xSrc, ySrc,
1283		      xMask, yMask,
1284		      xDst, yDst,
1285		      width, height);
1286
1287	/* Then, add in the source value times the destination alpha factors (1.0).
1288	 */
1289	uxa_composite(PictOpAdd, pSrc, pMask, localDst,
1290		      xSrc, ySrc,
1291		      xMask, yMask,
1292		      xDst, yDst,
1293		      width, height);
1294
1295	if (localDst != pDst) {
1296		GCPtr gc;
1297
1298		gc = GetScratchGC(pDst->pDrawable->depth, screen);
1299		if (gc) {
1300			ValidateGC(pDst->pDrawable, gc);
1301			gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
1302					0, 0, width, height, xDst_copy, yDst_copy);
1303			FreeScratchGC(gc);
1304		}
1305
1306		FreePicture(localDst, 0);
1307	}
1308
1309	return 1;
1310}
1311
1312static int
1313compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src)
1314{
1315	if (op == PictOpSrc) {
1316		if (src->format == dst->format)
1317			return 1;
1318
1319		/* Is the destination an alpha-less version of source? */
1320		if (dst->format == PICT_FORMAT(PICT_FORMAT_BPP(src->format),
1321					       PICT_FORMAT_TYPE(src->format),
1322					       0,
1323					       PICT_FORMAT_R(src->format),
1324					       PICT_FORMAT_G(src->format),
1325					       PICT_FORMAT_B(src->format)))
1326			return 1;
1327
1328		/* XXX xrgb is promoted to argb during image upload... */
1329#if 0
1330		if (dst->format == PICT_a8r8g8b8 && src->format == PICT_x8r8g8b8)
1331			return 1;
1332#endif
1333	} else if (op == PictOpOver) {
1334		if (PICT_FORMAT_A(src->format))
1335			return 0;
1336
1337		return src->format == dst->format;
1338	}
1339
1340	return 0;
1341}
1342
1343void
1344uxa_composite(CARD8 op,
1345	      PicturePtr pSrc,
1346	      PicturePtr pMask,
1347	      PicturePtr pDst,
1348	      INT16 xSrc, INT16 ySrc,
1349	      INT16 xMask, INT16 yMask,
1350	      INT16 xDst, INT16 yDst,
1351	      CARD16 width, CARD16 height)
1352{
1353	uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
1354	int ret = -1;
1355	Bool saveSrcRepeat = pSrc->repeat;
1356	Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
1357	RegionRec region;
1358	int tx, ty;
1359
1360	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
1361		int ok;
1362
1363		uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW);
1364		uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO);
1365		if (pMask)
1366			uxa_picture_prepare_access(pMask, UXA_GLAMOR_ACCESS_RO);
1367
1368		ok = glamor_composite_nf(op,
1369					 pSrc, pMask, pDst, xSrc, ySrc,
1370					 xMask, yMask, xDst, yDst,
1371					 width, height);
1372
1373		if (pMask)
1374			uxa_picture_finish_access(pMask, UXA_GLAMOR_ACCESS_RO);
1375		uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO);
1376		uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW);
1377
1378		if (!ok)
1379			goto fallback;
1380
1381		return;
1382	}
1383
1384	if (uxa_screen->force_fallback)
1385		goto fallback;
1386
1387	if (!uxa_drawable_is_offscreen(pDst->pDrawable))
1388		goto fallback;
1389
1390	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
1391		goto fallback;
1392
1393	/* Remove repeat in source if useless */
1394	if (pSrc->pDrawable && pSrc->repeat && pSrc->filter != PictFilterConvolution &&
1395	    transform_is_integer_translation(pSrc->transform, &tx, &ty) &&
1396	    (pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) &&
1397	    drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height))
1398		pSrc->repeat = 0;
1399
1400	if (!pMask) {
1401		if (op == PictOpClear) {
1402			PicturePtr clear = uxa_solid_clear(pDst->pDrawable->pScreen);
1403			if (clear &&
1404			    uxa_try_driver_solid_fill(clear, pDst,
1405						      xSrc, ySrc,
1406						      xDst, yDst,
1407						      width, height) == 1)
1408				goto done;
1409		}
1410
1411		if (pSrc->pDrawable == NULL) {
1412			if (pSrc->pSourcePict) {
1413				SourcePict *source = pSrc->pSourcePict;
1414				if (source->type == SourcePictTypeSolidFill) {
1415					if (op == PictOpSrc ||
1416					    (op == PictOpOver &&
1417					     (source->solidFill.color & 0xff000000) == 0xff000000)) {
1418						ret = uxa_try_driver_solid_fill(pSrc, pDst,
1419										xSrc, ySrc,
1420										xDst, yDst,
1421										width, height);
1422						if (ret == 1)
1423							goto done;
1424					}
1425				}
1426			}
1427		} else if (pSrc->pDrawable->width == 1 &&
1428			   pSrc->pDrawable->height == 1 &&
1429			   pSrc->repeat &&
1430			   (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) {
1431			ret = uxa_try_driver_solid_fill(pSrc, pDst,
1432							xSrc, ySrc,
1433							xDst, yDst,
1434							width, height);
1435			if (ret == 1)
1436				goto done;
1437		} else if (compatible_formats (op, pDst, pSrc) &&
1438			   pSrc->filter != PictFilterConvolution &&
1439			   transform_is_integer_translation(pSrc->transform, &tx, &ty)) {
1440			if (!pSrc->repeat &&
1441			    drawable_contains(pSrc->pDrawable,
1442					     xSrc + tx, ySrc + ty,
1443					     width, height)) {
1444				xDst += pDst->pDrawable->x;
1445				yDst += pDst->pDrawable->y;
1446				xSrc += pSrc->pDrawable->x + tx;
1447				ySrc += pSrc->pDrawable->y + ty;
1448
1449				if (!miComputeCompositeRegion
1450				    (&region, pSrc, pMask, pDst, xSrc, ySrc,
1451				     xMask, yMask, xDst, yDst, width, height))
1452					goto done;
1453
1454				uxa_copy_n_to_n(pSrc->pDrawable,
1455						pDst->pDrawable, NULL,
1456						REGION_RECTS(&region),
1457						REGION_NUM_RECTS(&region),
1458						xSrc - xDst, ySrc - yDst, FALSE,
1459						FALSE, 0, NULL);
1460				REGION_UNINIT(pDst->pDrawable->pScreen,
1461					      &region);
1462				goto done;
1463			} else if (pSrc->repeat && pSrc->repeatType == RepeatNormal &&
1464				   pSrc->pDrawable->type == DRAWABLE_PIXMAP) {
1465				DDXPointRec patOrg;
1466
1467				/* Let's see if the driver can do the repeat
1468				 * in one go
1469				 */
1470				if (uxa_screen->info->prepare_composite) {
1471					ret = uxa_try_driver_composite(op, pSrc,
1472								       pMask, pDst,
1473								       xSrc, ySrc,
1474								       xMask, yMask,
1475								       xDst, yDst,
1476								       width, height);
1477					if (ret == 1)
1478						goto done;
1479				}
1480
1481				/* Now see if we can use
1482				 * uxa_fill_region_tiled()
1483				 */
1484				xDst += pDst->pDrawable->x;
1485				yDst += pDst->pDrawable->y;
1486				xSrc += pSrc->pDrawable->x + tx;
1487				ySrc += pSrc->pDrawable->y + ty;
1488
1489				if (!miComputeCompositeRegion
1490				    (&region, pSrc, pMask, pDst, xSrc, ySrc,
1491				     xMask, yMask, xDst, yDst, width, height))
1492					goto done;
1493
1494				/* pattern origin is the point in the
1495				 * destination drawable
1496				 * corresponding to (0,0) in the source */
1497				patOrg.x = xDst - xSrc;
1498				patOrg.y = yDst - ySrc;
1499
1500				ret = uxa_fill_region_tiled(pDst->pDrawable,
1501							    &region,
1502							    (PixmapPtr) pSrc->
1503							    pDrawable, &patOrg,
1504							    FB_ALLONES, GXcopy);
1505
1506				REGION_UNINIT(pDst->pDrawable->pScreen,
1507					      &region);
1508
1509				if (ret)
1510					goto done;
1511			}
1512		}
1513	}
1514
1515	/* Remove repeat in mask if useless */
1516	if (pMask && pMask->pDrawable && pMask->repeat &&
1517	    pMask->filter != PictFilterConvolution &&
1518	    transform_is_integer_translation(pMask->transform, &tx, &ty) &&
1519	    (pMask->pDrawable->width > 1 || pMask->pDrawable->height > 1) &&
1520	    drawable_contains(pMask->pDrawable, xMask + tx, yMask + ty, width, height))
1521		pMask->repeat = 0;
1522
1523	if (uxa_screen->info->prepare_composite) {
1524		Bool isSrcSolid;
1525
1526		ret =
1527		    uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc,
1528					     xMask, yMask, xDst, yDst, width,
1529					     height);
1530		if (ret == 1)
1531			goto done;
1532
1533		/* For generic masks and solid src pictures, mach64 can do
1534		 * Over in two passes, similar to the component-alpha case.
1535		 */
1536
1537		isSrcSolid =
1538			pSrc->pDrawable ?
1539				pSrc->pDrawable->width == 1 &&
1540				pSrc->pDrawable->height == 1 &&
1541				pSrc->repeat :
1542			pSrc->pSourcePict ?
1543				pSrc->pSourcePict->type == SourcePictTypeSolidFill :
1544			0;
1545
1546		/* If we couldn't do the Composite in a single pass, and it
1547		 * was a component-alpha Over, see if we can do it in two
1548		 * passes with an OutReverse and then an Add.
1549		 */
1550		if (ret == -1 && op == PictOpOver && pMask &&
1551		    (pMask->componentAlpha || isSrcSolid)) {
1552			ret =
1553			    uxa_try_magic_two_pass_composite_helper(op, pSrc,
1554								    pMask, pDst,
1555								    xSrc, ySrc,
1556								    xMask, yMask,
1557								    xDst, yDst,
1558								    width, height);
1559			if (ret == 1)
1560				goto done;
1561		}
1562
1563	}
1564
1565fallback:
1566	uxa_print_composite_fallback("uxa_composite",
1567				     op, pSrc, pMask, pDst);
1568
1569	uxa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc,
1570			    xMask, yMask, xDst, yDst, width, height);
1571
1572done:
1573	pSrc->repeat = saveSrcRepeat;
1574	if (pMask)
1575		pMask->repeat = saveMaskRepeat;
1576}
1577#endif
1578
1579/**
1580 * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead
1581 * of PolyFillRect to initialize the pixmap after creating it, to prevent
1582 * the pixmap from being migrated.
1583 *
1584 * See the comments about uxa_trapezoids and uxa_triangles.
1585 */
1586static PicturePtr
1587uxa_create_alpha_picture(ScreenPtr pScreen,
1588			 PicturePtr pDst,
1589			 PictFormatPtr pPictFormat, CARD16 width, CARD16 height)
1590{
1591	PixmapPtr pPixmap;
1592	PicturePtr pPicture;
1593	int error;
1594
1595	if (width > 32767 || height > 32767)
1596		return 0;
1597
1598	if (!pPictFormat) {
1599		if (pDst->polyEdge == PolyEdgeSharp)
1600			pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
1601		else
1602			pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
1603		if (!pPictFormat)
1604			return 0;
1605	}
1606
1607	pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
1608					    pPictFormat->depth,
1609					    UXA_CREATE_PIXMAP_FOR_MAP);
1610	if (!pPixmap)
1611		return 0;
1612	pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
1613				 0, 0, serverClient, &error);
1614	(*pScreen->DestroyPixmap) (pPixmap);
1615	return pPicture;
1616}
1617
1618static void
1619uxa_check_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
1620		     PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1621		     int ntrap, xTrapezoid * traps)
1622{
1623	ScreenPtr screen = dst->pDrawable->pScreen;
1624
1625	if (maskFormat) {
1626		PixmapPtr scratch = NULL;
1627		PicturePtr mask;
1628		INT16 xDst, yDst;
1629		INT16 xRel, yRel;
1630		BoxRec bounds;
1631		int width, height;
1632		pixman_image_t *image;
1633		pixman_format_code_t format;
1634		int error;
1635
1636		xDst = traps[0].left.p1.x >> 16;
1637		yDst = traps[0].left.p1.y >> 16;
1638
1639		miTrapezoidBounds (ntrap, traps, &bounds);
1640		if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1641			return;
1642
1643		width  = bounds.x2 - bounds.x1;
1644		height = bounds.y2 - bounds.y1;
1645
1646		format = maskFormat->format |
1647			(BitsPerPixel(maskFormat->depth) << 24);
1648		image =
1649		    pixman_image_create_bits(format, width, height, NULL, 0);
1650		if (!image)
1651			return;
1652
1653		for (; ntrap; ntrap--, traps++)
1654			pixman_rasterize_trapezoid(image,
1655						   (pixman_trapezoid_t *) traps,
1656						   -bounds.x1, -bounds.y1);
1657
1658
1659		scratch = GetScratchPixmapHeader(screen, width, height,
1660						 PIXMAN_FORMAT_DEPTH(format),
1661						 PIXMAN_FORMAT_BPP(format),
1662						 pixman_image_get_stride(image),
1663						 pixman_image_get_data(image));
1664		if (!scratch) {
1665			pixman_image_unref(image);
1666			return;
1667		}
1668
1669		mask = CreatePicture(0, &scratch->drawable,
1670				     PictureMatchFormat(screen,
1671							PIXMAN_FORMAT_DEPTH(format),
1672							format),
1673				     0, 0, serverClient, &error);
1674		if (!mask) {
1675			FreeScratchPixmapHeader(scratch);
1676			pixman_image_unref(image);
1677			return;
1678		}
1679
1680		xRel = bounds.x1 + xSrc - xDst;
1681		yRel = bounds.y1 + ySrc - yDst;
1682		CompositePicture(op, src, mask, dst,
1683				 xRel, yRel,
1684				 0, 0,
1685				 bounds.x1, bounds.y1,
1686				 width, height);
1687		FreePicture(mask, 0);
1688
1689		FreeScratchPixmapHeader(scratch);
1690		pixman_image_unref(image);
1691	} else {
1692		if (dst->polyEdge == PolyEdgeSharp)
1693			maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
1694		else
1695			maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
1696
1697		for (; ntrap; ntrap--, traps++)
1698			uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, 1, traps);
1699	}
1700}
1701
1702/**
1703 * uxa_trapezoids is essentially a copy of miTrapezoids that uses
1704 * uxa_create_alpha_picture instead of miCreateAlphaPicture.
1705 *
1706 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
1707 * to initialize the contents after creating the pixmap, which
1708 * causes the pixmap to be moved in for acceleration. The subsequent
1709 * call to RasterizeTrapezoid won't be accelerated however, which
1710 * forces the pixmap to be moved out again.
1711 *
1712 * uxa_create_alpha_picture avoids this roundtrip by using
1713 * uxa_check_poly_fill_rect to initialize the contents.
1714 */
1715void
1716uxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
1717	       PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1718	       int ntrap, xTrapezoid * traps)
1719{
1720	ScreenPtr screen = dst->pDrawable->pScreen;
1721	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
1722	BoxRec bounds;
1723	Bool direct;
1724
1725	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
1726		int ok;
1727
1728		uxa_picture_prepare_access(dst, UXA_GLAMOR_ACCESS_RW);
1729		uxa_picture_prepare_access(src, UXA_GLAMOR_ACCESS_RO);
1730		ok = glamor_trapezoids_nf(op,
1731					  src, dst, maskFormat, xSrc,
1732					  ySrc, ntrap, traps);
1733		uxa_picture_finish_access(src, UXA_GLAMOR_ACCESS_RO);
1734		uxa_picture_finish_access(dst, UXA_GLAMOR_ACCESS_RW);
1735
1736		if (!ok)
1737			goto fallback;
1738
1739		return;
1740	}
1741
1742	if (uxa_screen->force_fallback) {
1743fallback:
1744		uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, ntrap, traps);
1745		return;
1746	}
1747
1748	direct = op == PictOpAdd && miIsSolidAlpha(src);
1749	if (maskFormat || direct) {
1750		miTrapezoidBounds(ntrap, traps, &bounds);
1751
1752		if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1753			return;
1754	}
1755
1756	/*
1757	 * Check for solid alpha add
1758	 */
1759	if (direct) {
1760		DrawablePtr pDraw = dst->pDrawable;
1761		PixmapPtr pixmap = uxa_get_drawable_pixmap(pDraw);
1762		int xoff, yoff;
1763
1764		uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff);
1765
1766		xoff += pDraw->x;
1767		yoff += pDraw->y;
1768
1769		if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
1770			PictureScreenPtr ps = GetPictureScreen(screen);
1771
1772			for (; ntrap; ntrap--, traps++)
1773				(*ps->RasterizeTrapezoid) (dst, traps, 0, 0);
1774			uxa_finish_access(pDraw, UXA_ACCESS_RW);
1775		}
1776	} else if (maskFormat) {
1777		PixmapPtr scratch = NULL;
1778		PicturePtr mask;
1779		INT16 xDst, yDst;
1780		INT16 xRel, yRel;
1781		int width, height;
1782		pixman_image_t *image;
1783		pixman_format_code_t format;
1784
1785		xDst = traps[0].left.p1.x >> 16;
1786		yDst = traps[0].left.p1.y >> 16;
1787
1788		width  = bounds.x2 - bounds.x1;
1789		height = bounds.y2 - bounds.y1;
1790
1791		format = maskFormat->format |
1792			(BitsPerPixel(maskFormat->depth) << 24);
1793		image =
1794		    pixman_image_create_bits(format, width, height, NULL, 0);
1795		if (!image)
1796			return;
1797
1798		for (; ntrap; ntrap--, traps++)
1799			pixman_rasterize_trapezoid(image,
1800						   (pixman_trapezoid_t *) traps,
1801						   -bounds.x1, -bounds.y1);
1802		if (uxa_drawable_is_offscreen(dst->pDrawable)) {
1803			mask = uxa_picture_from_pixman_image(screen, image, format);
1804		} else {
1805			int error;
1806
1807			scratch = GetScratchPixmapHeader(screen, width, height,
1808							PIXMAN_FORMAT_DEPTH(format),
1809							PIXMAN_FORMAT_BPP(format),
1810							pixman_image_get_stride(image),
1811							pixman_image_get_data(image));
1812			mask = CreatePicture(0, &scratch->drawable,
1813					     PictureMatchFormat(screen,
1814								PIXMAN_FORMAT_DEPTH(format),
1815								format),
1816					     0, 0, serverClient, &error);
1817		}
1818		if (!mask) {
1819			if (scratch)
1820				FreeScratchPixmapHeader(scratch);
1821			pixman_image_unref(image);
1822			return;
1823		}
1824
1825		xRel = bounds.x1 + xSrc - xDst;
1826		yRel = bounds.y1 + ySrc - yDst;
1827		CompositePicture(op, src, mask, dst,
1828				 xRel, yRel,
1829				 0, 0,
1830				 bounds.x1, bounds.y1,
1831				 width, height);
1832		FreePicture(mask, 0);
1833
1834		if (scratch)
1835			FreeScratchPixmapHeader(scratch);
1836		pixman_image_unref(image);
1837	} else {
1838		if (dst->polyEdge == PolyEdgeSharp)
1839			maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
1840		else
1841			maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
1842		for (; ntrap; ntrap--, traps++)
1843			uxa_trapezoids(op, src, dst, maskFormat, xSrc, ySrc,
1844				       1, traps);
1845	}
1846}
1847
1848static void
1849uxa_check_triangles(CARD8 op, PicturePtr src, PicturePtr dst,
1850		    PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1851		    int ntri, xTriangle *tri)
1852{
1853	ScreenPtr screen = dst->pDrawable->pScreen;
1854
1855	if (maskFormat) {
1856		PixmapPtr scratch = NULL;
1857		PicturePtr mask;
1858		INT16 xDst, yDst;
1859		INT16 xRel, yRel;
1860		BoxRec bounds;
1861		int width, height;
1862		pixman_image_t *image;
1863		pixman_format_code_t format;
1864		int error;
1865
1866		xDst = pixman_fixed_to_int(tri[0].p1.x);
1867		yDst = pixman_fixed_to_int(tri[0].p1.y);
1868
1869		miTriangleBounds (ntri, tri, &bounds);
1870		if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1871			return;
1872
1873		width  = bounds.x2 - bounds.x1;
1874		height = bounds.y2 - bounds.y1;
1875
1876		format = maskFormat->format |
1877			(BitsPerPixel(maskFormat->depth) << 24);
1878		image =
1879		    pixman_image_create_bits(format, width, height, NULL, 0);
1880		if (!image)
1881			return;
1882
1883		pixman_add_triangles(image,
1884				     -bounds.x1, -bounds.y1,
1885				     ntri, (pixman_triangle_t *)tri);
1886
1887		scratch = GetScratchPixmapHeader(screen, width, height,
1888						 PIXMAN_FORMAT_DEPTH(format),
1889						 PIXMAN_FORMAT_BPP(format),
1890						 pixman_image_get_stride(image),
1891						 pixman_image_get_data(image));
1892		if (!scratch) {
1893			pixman_image_unref(image);
1894			return;
1895		}
1896
1897		mask = CreatePicture(0, &scratch->drawable,
1898				     PictureMatchFormat(screen,
1899							PIXMAN_FORMAT_DEPTH(format),
1900							format),
1901				     0, 0, serverClient, &error);
1902		if (!mask) {
1903			FreeScratchPixmapHeader(scratch);
1904			pixman_image_unref(image);
1905			return;
1906		}
1907
1908		xRel = bounds.x1 + xSrc - xDst;
1909		yRel = bounds.y1 + ySrc - yDst;
1910		CompositePicture(op, src, mask, dst,
1911				 xRel, yRel,
1912				 0, 0,
1913				 bounds.x1, bounds.y1,
1914				 width, height);
1915		FreePicture(mask, 0);
1916
1917		FreeScratchPixmapHeader(scratch);
1918		pixman_image_unref(image);
1919	} else {
1920		if (dst->polyEdge == PolyEdgeSharp)
1921			maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
1922		else
1923			maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
1924
1925		for (; ntri; ntri--, tri++)
1926			uxa_check_triangles(op, src, dst, maskFormat, xSrc, ySrc, 1, tri);
1927	}
1928}
1929
1930/**
1931 * uxa_triangles is essentially a copy of miTriangles that uses
1932 * uxa_create_alpha_picture instead of miCreateAlphaPicture.
1933 *
1934 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
1935 * to initialize the contents after creating the pixmap, which
1936 * causes the pixmap to be moved in for acceleration. The subsequent
1937 * call to AddTriangles won't be accelerated however, which forces the pixmap
1938 * to be moved out again.
1939 *
1940 * uxa_create_alpha_picture avoids this roundtrip by using
1941 * uxa_check_poly_fill_rect to initialize the contents.
1942 */
1943void
1944uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1945	      PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1946	      int ntri, xTriangle * tris)
1947{
1948	ScreenPtr pScreen = pDst->pDrawable->pScreen;
1949	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
1950	PictureScreenPtr ps = GetPictureScreen(pScreen);
1951	BoxRec bounds;
1952	Bool direct;
1953
1954	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
1955		int ok;
1956
1957		uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW);
1958		uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO);
1959		ok = glamor_triangles_nf(op,
1960				        pSrc, pDst, maskFormat, xSrc,
1961					ySrc, ntri, tris);
1962		uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO);
1963		uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW);
1964
1965		if (!ok)
1966			goto fallback;
1967
1968		return;
1969	}
1970
1971	if (uxa_screen->force_fallback) {
1972fallback:
1973		uxa_check_triangles(op, pSrc, pDst, maskFormat,
1974				    xSrc, ySrc, ntri, tris);
1975		return;
1976	}
1977
1978	direct = op == PictOpAdd && miIsSolidAlpha(pSrc);
1979	if (maskFormat || direct) {
1980		miTriangleBounds(ntri, tris, &bounds);
1981
1982		if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
1983			return;
1984	}
1985
1986	/*
1987	 * Check for solid alpha add
1988	 */
1989	if (direct) {
1990		DrawablePtr pDraw = pDst->pDrawable;
1991		if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
1992			(*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
1993			uxa_finish_access(pDraw, UXA_ACCESS_RW);
1994		}
1995	} else if (maskFormat) {
1996		PicturePtr pPicture;
1997		INT16 xDst, yDst;
1998		INT16 xRel, yRel;
1999		int width = bounds.x2 - bounds.x1;
2000		int height = bounds.y2 - bounds.y1;
2001		GCPtr pGC;
2002		xRectangle rect;
2003
2004		xDst = tris[0].p1.x >> 16;
2005		yDst = tris[0].p1.y >> 16;
2006
2007		pPicture = uxa_create_alpha_picture(pScreen, pDst, maskFormat,
2008						    width, height);
2009		if (!pPicture)
2010			return;
2011
2012		/* Clear the alpha picture to 0. */
2013		pGC = GetScratchGC(pPicture->pDrawable->depth, pScreen);
2014		if (!pGC) {
2015			FreePicture(pPicture, 0);
2016			return;
2017		}
2018		ValidateGC(pPicture->pDrawable, pGC);
2019		rect.x = 0;
2020		rect.y = 0;
2021		rect.width = width;
2022		rect.height = height;
2023		uxa_check_poly_fill_rect(pPicture->pDrawable, pGC, 1, &rect);
2024		FreeScratchGC(pGC);
2025
2026		if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) {
2027			(*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1,
2028					     ntri, tris);
2029			uxa_finish_access(pPicture->pDrawable, UXA_ACCESS_RW);
2030		}
2031
2032		xRel = bounds.x1 + xSrc - xDst;
2033		yRel = bounds.y1 + ySrc - yDst;
2034		CompositePicture(op, pSrc, pPicture, pDst,
2035				 xRel, yRel, 0, 0, bounds.x1, bounds.y1,
2036				 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
2037		FreePicture(pPicture, 0);
2038	} else {
2039		if (pDst->polyEdge == PolyEdgeSharp)
2040			maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
2041		else
2042			maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
2043
2044		for (; ntri; ntri--, tris++)
2045			uxa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1,
2046				      tris);
2047	}
2048}
2049
2050void
2051uxa_add_traps(PicturePtr pPicture,
2052	      INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
2053{
2054	ScreenPtr pScreen = pPicture->pDrawable->pScreen;
2055	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
2056
2057	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
2058		int ok;
2059
2060		uxa_picture_prepare_access(pPicture, UXA_GLAMOR_ACCESS_RW);
2061		ok = glamor_add_traps_nf(pPicture,
2062					 x_off, y_off, ntrap, traps);
2063		uxa_picture_finish_access(pPicture, UXA_GLAMOR_ACCESS_RW);
2064
2065		if (!ok)
2066			goto fallback;
2067
2068		return;
2069	}
2070
2071fallback:
2072	uxa_check_add_traps(pPicture, x_off, y_off, ntrap, traps);
2073}
2074