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