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