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 
uxa_composite_fallback_pict_desc(PicturePtr pict,char * string,int n)36 static 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 
87 static const char *
op_to_string(CARD8 op)88 op_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 
163 static void
uxa_print_composite_fallback(const char * func,CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst)164 uxa_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 
uxa_op_reads_destination(CARD8 op)189 Bool 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 
205 static Bool
uxa_get_pixel_from_rgba(CARD32 * pixel,CARD16 red,CARD16 green,CARD16 blue,CARD16 alpha,CARD32 format)206 uxa_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 
261 Bool
uxa_get_rgba_from_pixel(CARD32 pixel,CARD16 * red,CARD16 * green,CARD16 * blue,CARD16 * alpha,CARD32 format)262 uxa_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 
342 Bool
uxa_get_color_for_pixmap(PixmapPtr pixmap,CARD32 src_format,CARD32 dst_format,CARD32 * pixel)343 uxa_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 
367 static int
uxa_try_driver_solid_fill(PicturePtr pSrc,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)368 uxa_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 
459 static PicturePtr
uxa_picture_for_pixman_format(ScreenPtr screen,pixman_format_code_t format,int width,int height)460 uxa_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 
500 static PicturePtr
uxa_picture_from_pixman_image(ScreenPtr screen,pixman_image_t * image,pixman_format_code_t format)501 uxa_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 
581 static PicturePtr
uxa_create_solid(ScreenPtr screen,uint32_t color)582 uxa_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 
609 static PicturePtr
uxa_solid_clear(ScreenPtr screen)610 uxa_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 
624 PicturePtr
uxa_acquire_solid(ScreenPtr screen,SourcePict * source)625 uxa_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 
676 DONE:
677 	picture->refcnt++;
678 	return picture;
679 }
680 
681 PicturePtr
uxa_acquire_pattern(ScreenPtr pScreen,PicturePtr pSrc,pixman_format_code_t format,INT16 x,INT16 y,CARD16 width,CARD16 height)682 uxa_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 
710 static Bool
transform_is_integer_translation(PictTransformPtr t,int * tx,int * ty)711 transform_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 
736 static PicturePtr
uxa_render_picture(ScreenPtr screen,PicturePtr src,pixman_format_code_t format,INT16 x,INT16 y,CARD16 width,CARD16 height)737 uxa_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 
774 static int
drawable_contains(DrawablePtr drawable,int x,int y,int w,int h)775 drawable_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 
789 PicturePtr
uxa_acquire_drawable(ScreenPtr pScreen,PicturePtr pSrc,INT16 x,INT16 y,CARD16 width,CARD16 height,INT16 * out_x,INT16 * out_y)790 uxa_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);
854 done:
855 	pDst->componentAlpha = pSrc->componentAlpha;
856 	*out_x = 0;
857 	*out_y = 0;
858 	return pDst;
859 }
860 
861 static PicturePtr
uxa_acquire_picture(ScreenPtr screen,PicturePtr src,pixman_format_code_t format,INT16 x,INT16 y,CARD16 width,CARD16 height,INT16 * out_x,INT16 * out_y)862 uxa_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 
908 static PicturePtr
uxa_acquire_source(ScreenPtr screen,PicturePtr pict,INT16 x,INT16 y,CARD16 width,CARD16 height,INT16 * out_x,INT16 * out_y)909 uxa_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 
922 static PicturePtr
uxa_acquire_mask(ScreenPtr screen,PicturePtr pict,INT16 x,INT16 y,INT16 width,INT16 height,INT16 * out_x,INT16 * out_y)923 uxa_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 
936 static int
uxa_try_driver_composite(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)937 uxa_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 
1196 static int
uxa_try_magic_two_pass_composite_helper(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)1197 uxa_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 
1299 static int
compatible_formats(CARD8 op,PicturePtr dst,PicturePtr src)1300 compatible_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 
1330 void
uxa_composite(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)1331 uxa_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 
1528 fallback:
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 
1535 done:
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  */
1549 static PicturePtr
uxa_create_alpha_picture(ScreenPtr pScreen,PicturePtr pDst,PictFormatPtr pPictFormat,CARD16 width,CARD16 height)1550 uxa_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 
1581 static void
uxa_check_trapezoids(CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntrap,xTrapezoid * traps)1582 uxa_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  */
1678 void
uxa_trapezoids(CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntrap,xTrapezoid * traps)1679 uxa_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 
1793 static void
uxa_check_triangles(CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntri,xTriangle * tri)1794 uxa_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  */
1888 void
uxa_triangles(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntri,xTriangle * tris)1889 uxa_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 
1977 void
uxa_add_traps(PicturePtr pPicture,INT16 x_off,INT16 y_off,int ntrap,xTrap * traps)1978 uxa_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