2 * Copyright © 2001 Keith Packard
4 * Partly based on code that is Copyright © The XFree86 Project Inc.
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.
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.
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
37 static void exaCompositeFallbackPictDesc(PicturePtr pict
, char *string
, int n
)
45 snprintf(string
, n
, "None");
52 snprintf(format
, 20, "ARGB8888");
55 snprintf(format
, 20, "RGB565 ");
58 snprintf(format
, 20, "RGB555 ");
61 snprintf(format
, 20, "A8 ");
64 snprintf(format
, 20, "A1 ");
67 snprintf(format
, 20, "0x%x", (int)pict
->format
);
71 loc
= exaGetOffscreenPixmap(pict
->pDrawable
, &temp
, &temp
) ? 's' : 'm';
73 snprintf(size
, 20, "%dx%d%s", pict
->pDrawable
->width
,
74 pict
->pDrawable
->height
, pict
->repeat
?
77 snprintf(string
, n
, "%p:%c fmt %s (%s)", pict
->pDrawable
, loc
, format
, size
);
81 exaPrintCompositeFallback(CARD8 op
,
87 char srcdesc
[40], maskdesc
[40], dstdesc
[40];
98 sprintf(sop
, "0x%x", (int)op
);
102 exaCompositeFallbackPictDesc(pSrc
, srcdesc
, 40);
103 exaCompositeFallbackPictDesc(pMask
, maskdesc
, 40);
104 exaCompositeFallbackPictDesc(pDst
, dstdesc
, 40);
106 ErrorF("Composite fallback: op %s, \n"
110 sop
, srcdesc
, maskdesc
, dstdesc
);
112 #endif /* DEBUG_TRACE_FALL */
115 exaOpReadsDestination (CARD8 op
)
117 /* FALSE (does not read destination) is the list of ops in the protocol
118 * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
119 * That's just Clear and Src. ReduceCompositeOp() will already have
120 * converted con/disjoint clear/src to Clear or Src.
133 exaGetPixelFromRGBA(CARD32
*pixel
,
140 int rbits
, bbits
, gbits
, abits
;
141 int rshift
, bshift
, gshift
, ashift
;
145 if (!PICT_FORMAT_COLOR(format
))
148 rbits
= PICT_FORMAT_R(format
);
149 gbits
= PICT_FORMAT_G(format
);
150 bbits
= PICT_FORMAT_B(format
);
151 abits
= PICT_FORMAT_A(format
);
153 if (PICT_FORMAT_TYPE(format
) == PICT_TYPE_ARGB
) {
156 rshift
= gshift
+ gbits
;
157 ashift
= rshift
+ rbits
;
158 } else { /* PICT_TYPE_ABGR */
161 bshift
= gshift
+ gbits
;
162 ashift
= bshift
+ bbits
;
165 *pixel
|= ( blue
>> (16 - bbits
)) << bshift
;
166 *pixel
|= ( red
>> (16 - rbits
)) << rshift
;
167 *pixel
|= (green
>> (16 - gbits
)) << gshift
;
168 *pixel
|= (alpha
>> (16 - abits
)) << ashift
;
174 exaGetRGBAFromPixel(CARD32 pixel
,
181 int rbits
, bbits
, gbits
, abits
;
182 int rshift
, bshift
, gshift
, ashift
;
184 if (!PICT_FORMAT_COLOR(format
))
187 rbits
= PICT_FORMAT_R(format
);
188 gbits
= PICT_FORMAT_G(format
);
189 bbits
= PICT_FORMAT_B(format
);
190 abits
= PICT_FORMAT_A(format
);
192 if (PICT_FORMAT_TYPE(format
) == PICT_TYPE_ARGB
) {
195 rshift
= gshift
+ gbits
;
196 ashift
= rshift
+ rbits
;
197 } else { /* PICT_TYPE_ABGR */
200 bshift
= gshift
+ gbits
;
201 ashift
= bshift
+ bbits
;
204 *red
= ((pixel
>> rshift
) & ((1 << rbits
) - 1)) << (16 - rbits
);
206 *red
|= *red
>> rbits
;
210 *green
= ((pixel
>> gshift
) & ((1 << gbits
) - 1)) << (16 - gbits
);
212 *green
|= *green
>> gbits
;
216 *blue
= ((pixel
>> bshift
) & ((1 << bbits
) - 1)) << (16 - bbits
);
218 *blue
|= *blue
>> bbits
;
223 *alpha
= ((pixel
>> ashift
) & ((1 << abits
) - 1)) << (16 - abits
);
225 *alpha
|= *alpha
>> abits
;
235 exaTryDriverSolidFill(PicturePtr pSrc
,
244 ExaScreenPriv (pDst
->pDrawable
->pScreen
);
248 int dst_off_x
, dst_off_y
;
249 PixmapPtr pSrcPix
, pDstPix
;
251 CARD16 red
, green
, blue
, alpha
;
252 ExaMigrationRec pixmaps
[1];
254 xDst
+= pDst
->pDrawable
->x
;
255 yDst
+= pDst
->pDrawable
->y
;
256 xSrc
+= pSrc
->pDrawable
->x
;
257 ySrc
+= pSrc
->pDrawable
->y
;
259 if (!miComputeCompositeRegion (®ion
, pSrc
, NULL
, pDst
,
260 xSrc
, ySrc
, 0, 0, xDst
, yDst
,
264 pSrcPix
= exaGetDrawablePixmap (pSrc
->pDrawable
);
265 pixel
= exaGetPixmapFirstPixel (pSrcPix
);
267 pixmaps
[0].as_dst
= TRUE
;
268 pixmaps
[0].as_src
= FALSE
;
269 pixmaps
[0].pPix
= exaGetDrawablePixmap (pDst
->pDrawable
);
270 exaDoMigration(pixmaps
, 1, TRUE
);
272 pDstPix
= exaGetOffscreenPixmap (pDst
->pDrawable
, &dst_off_x
, &dst_off_y
);
274 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
278 if (!exaGetRGBAFromPixel(pixel
, &red
, &green
, &blue
, &alpha
,
281 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
285 if (!exaGetPixelFromRGBA(&pixel
, red
, green
, blue
, alpha
,
288 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
292 if (!(*pExaScr
->info
->PrepareSolid
) (pDstPix
, GXcopy
, 0xffffffff, pixel
))
294 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
298 nbox
= REGION_NUM_RECTS(®ion
);
299 pbox
= REGION_RECTS(®ion
);
303 (*pExaScr
->info
->Solid
) (pDstPix
,
304 pbox
->x1
+ dst_off_x
, pbox
->y1
+ dst_off_y
,
305 pbox
->x2
+ dst_off_x
, pbox
->y2
+ dst_off_y
);
309 (*pExaScr
->info
->DoneSolid
) (pDstPix
);
310 exaMarkSync(pDst
->pDrawable
->pScreen
);
312 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
317 exaTryDriverComposite(CARD8 op
,
330 ExaScreenPriv (pDst
->pDrawable
->pScreen
);
334 int src_off_x
, src_off_y
, mask_off_x
, mask_off_y
, dst_off_x
, dst_off_y
;
335 PixmapPtr pSrcPix
, pMaskPix
= NULL
, pDstPix
;
336 struct _Pixmap scratch
;
337 ExaMigrationRec pixmaps
[3];
339 pSrcPix
= exaGetDrawablePixmap(pSrc
->pDrawable
);
340 pDstPix
= exaGetDrawablePixmap(pDst
->pDrawable
);
342 pMaskPix
= exaGetDrawablePixmap(pMask
->pDrawable
);
344 /* Bail if we might exceed coord limits by rendering from/to these. We
345 * should really be making some scratch pixmaps with offsets and coords
346 * adjusted to deal with this, but it hasn't been done yet.
348 if (pSrcPix
->drawable
.width
> pExaScr
->info
->maxX
||
349 pSrcPix
->drawable
.height
> pExaScr
->info
->maxY
||
350 pDstPix
->drawable
.width
> pExaScr
->info
->maxX
||
351 pDstPix
->drawable
.height
> pExaScr
->info
->maxY
||
352 (pMask
&& (pMaskPix
->drawable
.width
> pExaScr
->info
->maxX
||
353 pMaskPix
->drawable
.height
> pExaScr
->info
->maxY
)))
358 xDst
+= pDst
->pDrawable
->x
;
359 yDst
+= pDst
->pDrawable
->y
;
362 xMask
+= pMask
->pDrawable
->x
;
363 yMask
+= pMask
->pDrawable
->y
;
366 xSrc
+= pSrc
->pDrawable
->x
;
367 ySrc
+= pSrc
->pDrawable
->y
;
369 if (!miComputeCompositeRegion (®ion
, pSrc
, pMask
, pDst
,
370 xSrc
, ySrc
, xMask
, yMask
, xDst
, yDst
,
374 if (pExaScr
->info
->CheckComposite
&&
375 !(*pExaScr
->info
->CheckComposite
) (op
, pSrc
, pMask
, pDst
))
377 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
381 pixmaps
[0].as_dst
= TRUE
;
382 pixmaps
[0].as_src
= exaOpReadsDestination(op
);
383 pixmaps
[0].pPix
= exaGetDrawablePixmap (pDst
->pDrawable
);
384 pixmaps
[1].as_dst
= FALSE
;
385 pixmaps
[1].as_src
= TRUE
;
386 pixmaps
[1].pPix
= exaGetDrawablePixmap (pSrc
->pDrawable
);
388 pixmaps
[2].as_dst
= FALSE
;
389 pixmaps
[2].as_src
= TRUE
;
390 pixmaps
[2].pPix
= exaGetDrawablePixmap (pMask
->pDrawable
);
391 exaDoMigration(pixmaps
, 3, TRUE
);
393 exaDoMigration(pixmaps
, 2, TRUE
);
396 pSrcPix
= exaGetOffscreenPixmap (pSrc
->pDrawable
, &src_off_x
, &src_off_y
);
398 pMaskPix
= exaGetOffscreenPixmap (pMask
->pDrawable
, &mask_off_x
,
400 pDstPix
= exaGetOffscreenPixmap (pDst
->pDrawable
, &dst_off_x
, &dst_off_y
);
403 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
407 if (!pSrcPix
&& (!pMask
|| pMaskPix
) && pExaScr
->info
->UploadToScratch
) {
408 pSrcPix
= exaGetDrawablePixmap (pSrc
->pDrawable
);
409 if ((*pExaScr
->info
->UploadToScratch
) (pSrcPix
, &scratch
))
411 } else if (pSrcPix
&& pMask
&& !pMaskPix
&& pExaScr
->info
->UploadToScratch
) {
412 pMaskPix
= exaGetDrawablePixmap (pMask
->pDrawable
);
413 if ((*pExaScr
->info
->UploadToScratch
) (pMaskPix
, &scratch
))
417 if (!pSrcPix
|| (pMask
&& !pMaskPix
)) {
418 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
422 if (!(*pExaScr
->info
->PrepareComposite
) (op
, pSrc
, pMask
, pDst
, pSrcPix
,
425 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
429 nbox
= REGION_NUM_RECTS(®ion
);
430 pbox
= REGION_RECTS(®ion
);
440 (*pExaScr
->info
->Composite
) (pDstPix
,
441 pbox
->x1
+ xSrc
+ src_off_x
,
442 pbox
->y1
+ ySrc
+ src_off_y
,
443 pbox
->x1
+ xMask
+ mask_off_x
,
444 pbox
->y1
+ yMask
+ mask_off_y
,
445 pbox
->x1
+ dst_off_x
,
446 pbox
->y1
+ dst_off_y
,
448 pbox
->y2
- pbox
->y1
);
451 (*pExaScr
->info
->DoneComposite
) (pDstPix
);
452 exaMarkSync(pDst
->pDrawable
->pScreen
);
454 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
459 * exaTryMagicTwoPassCompositeHelper implements PictOpOver using two passes of
460 * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
461 * alpha and limited 1-tmu cards.
463 * From http://anholt.livejournal.com/32058.html:
465 * The trouble is that component-alpha rendering requires two different sources
466 * for blending: one for the source value to the blender, which is the
467 * per-channel multiplication of source and mask, and one for the source alpha
468 * for multiplying with the destination channels, which is the multiplication
469 * of the source channels by the mask alpha. So the equation for Over is:
471 * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
472 * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
473 * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
474 * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
476 * But we can do some simpler operations, right? How about PictOpOutReverse,
477 * which has a source factor of 0 and dest factor of (1 - source alpha). We
478 * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
479 * blenders pretty easily. So we can do a component-alpha OutReverse, which
482 * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
483 * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
484 * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
485 * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
487 * OK. And if an op doesn't use the source alpha value for the destination
488 * factor, then we can do the channel multiplication in the texture blenders
489 * to get the source value, and ignore the source alpha that we wouldn't use.
490 * We've supported this in the Radeon driver for a long time. An example would
491 * be PictOpAdd, which does:
493 * dst.A = src.A * mask.A + dst.A
494 * dst.R = src.R * mask.R + dst.R
495 * dst.G = src.G * mask.G + dst.G
496 * dst.B = src.B * mask.B + dst.B
498 * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
501 * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
502 * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
503 * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
504 * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
508 exaTryMagicTwoPassCompositeHelper(CARD8 op
,
521 ExaScreenPriv (pDst
->pDrawable
->pScreen
);
522 DrawablePtr pDstDraw
= pDst
->pDrawable
;
523 PixmapPtr pDstPixmap
= exaGetDrawablePixmap(pDstDraw
);
526 assert(op
== PictOpOver
);
528 if (pExaScr
->info
->CheckComposite
&&
529 (!(*pExaScr
->info
->CheckComposite
)(PictOpOutReverse
, pSrc
, pMask
,
531 !(*pExaScr
->info
->CheckComposite
)(PictOpAdd
, pSrc
, pMask
, pDst
)))
536 /* Now, we think we should be able to accelerate this operation. First,
537 * composite the destination to be the destination times the source alpha
540 exaComposite(PictOpOutReverse
, pSrc
, pMask
, pDst
, xSrc
, ySrc
, xMask
, yMask
,
541 xDst
, yDst
, width
, height
);
543 exaGetDrawableDeltas(pDstDraw
, pDstPixmap
, &xoff
, &yoff
);
546 exaPixmapDirty(pDstPixmap
, xDst
+ xoff
, yDst
+ yoff
, xDst
+ xoff
+ width
,
547 yDst
+ yoff
+ height
);
549 /* Then, add in the source value times the destination alpha factors (1.0).
551 exaComposite(PictOpAdd
, pSrc
, pMask
, pDst
, xSrc
, ySrc
, xMask
, yMask
,
552 xDst
, yDst
, width
, height
);
558 exaComposite(CARD8 op
,
571 ExaScreenPriv (pDst
->pDrawable
->pScreen
);
573 Bool saveSrcRepeat
= pSrc
->repeat
;
574 Bool saveMaskRepeat
= pMask
? pMask
->repeat
: 0;
575 ExaMigrationRec pixmaps
[3];
577 PixmapPtr pSrcPixmap
= NULL
;
579 pixmaps
[0].as_dst
= TRUE
;
580 pixmaps
[0].as_src
= exaOpReadsDestination(op
);
581 pixmaps
[0].pPix
= exaGetDrawablePixmap (pDst
->pDrawable
);
583 if (pSrc
->pDrawable
) {
584 pSrcPixmap
= exaGetDrawablePixmap (pSrc
->pDrawable
);
585 pixmaps
[npixmaps
].as_dst
= FALSE
;
586 pixmaps
[npixmaps
].as_src
= TRUE
;
587 pixmaps
[npixmaps
].pPix
= pSrcPixmap
;
591 if (pMask
&& pMask
->pDrawable
) {
592 pixmaps
[npixmaps
].as_dst
= FALSE
;
593 pixmaps
[npixmaps
].as_src
= TRUE
;
594 pixmaps
[npixmaps
].pPix
= exaGetDrawablePixmap (pMask
->pDrawable
);
598 /* We currently don't support acceleration of gradients, or other pictures
599 * with a NULL pDrawable.
601 if (pExaScr
->swappedOut
||
602 pSrc
->pDrawable
== NULL
|| (pMask
!= NULL
&& pMask
->pDrawable
== NULL
))
607 /* Remove repeat in source if useless */
608 if (pSrc
->repeat
&& !pSrc
->transform
&& xSrc
>= 0 &&
609 (xSrc
+ width
) <= pSrc
->pDrawable
->width
&& ySrc
>= 0 &&
610 (ySrc
+ height
) <= pSrc
->pDrawable
->height
)
615 if ((op
== PictOpSrc
&&
616 ((pSrc
->format
== pDst
->format
) ||
617 (pSrc
->format
==PICT_a8r8g8b8
&& pDst
->format
==PICT_x8r8g8b8
) ||
618 (pSrc
->format
==PICT_a8b8g8r8
&& pDst
->format
==PICT_x8b8g8r8
))) ||
619 (op
== PictOpOver
&& !pSrc
->alphaMap
&& !pDst
->alphaMap
&&
620 pSrc
->format
== pDst
->format
&&
621 (pSrc
->format
==PICT_x8r8g8b8
|| pSrc
->format
==PICT_x8b8g8r8
)))
623 if (pSrc
->pDrawable
->width
== 1 &&
624 pSrc
->pDrawable
->height
== 1 &&
627 ret
= exaTryDriverSolidFill(pSrc
, pDst
, xSrc
, ySrc
, xDst
, yDst
,
632 else if (pSrcPixmap
&& !pSrc
->repeat
&& !pSrc
->transform
)
636 xDst
+= pDst
->pDrawable
->x
;
637 yDst
+= pDst
->pDrawable
->y
;
638 xSrc
+= pSrc
->pDrawable
->x
;
639 ySrc
+= pSrc
->pDrawable
->y
;
641 if (!miComputeCompositeRegion (®ion
, pSrc
, pMask
, pDst
,
642 xSrc
, ySrc
, xMask
, yMask
, xDst
,
643 yDst
, width
, height
))
647 exaCopyNtoN (pSrc
->pDrawable
, pDst
->pDrawable
, NULL
,
648 REGION_RECTS(®ion
), REGION_NUM_RECTS(®ion
),
649 xSrc
- xDst
, ySrc
- yDst
,
650 FALSE
, FALSE
, 0, NULL
);
651 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
654 else if (pSrcPixmap
&& !pSrc
->transform
&&
655 pSrc
->repeatType
== RepeatNormal
)
660 /* Let's see if the driver can do the repeat in one go */
661 if (pExaScr
->info
->PrepareComposite
&& !pSrc
->alphaMap
&&
664 ret
= exaTryDriverComposite(op
, pSrc
, pMask
, pDst
, xSrc
,
665 ySrc
, xMask
, yMask
, xDst
, yDst
,
671 /* Now see if we can use exaFillRegionTiled() */
672 xDst
+= pDst
->pDrawable
->x
;
673 yDst
+= pDst
->pDrawable
->y
;
674 xSrc
+= pSrc
->pDrawable
->x
;
675 ySrc
+= pSrc
->pDrawable
->y
;
677 if (!miComputeCompositeRegion (®ion
, pSrc
, pMask
, pDst
, xSrc
,
678 ySrc
, xMask
, yMask
, xDst
, yDst
,
682 srcOrg
.x
= (xSrc
- xDst
) % pSrcPixmap
->drawable
.width
;
683 srcOrg
.y
= (ySrc
- yDst
) % pSrcPixmap
->drawable
.height
;
685 ret
= exaFillRegionTiled(pDst
->pDrawable
, ®ion
, pSrcPixmap
,
686 &srcOrg
, FB_ALLONES
, GXcopy
);
688 REGION_UNINIT(pDst
->pDrawable
->pScreen
, ®ion
);
696 /* Remove repeat in mask if useless */
697 if (pMask
&& pMask
->repeat
&& !pMask
->transform
&& xMask
>= 0 &&
698 (xMask
+ width
) <= pMask
->pDrawable
->width
&& yMask
>= 0 &&
699 (yMask
+ height
) <= pMask
->pDrawable
->height
)
702 if (pExaScr
->info
->PrepareComposite
&&
703 (!pSrc
->repeat
|| pSrc
->repeatType
== RepeatNormal
) &&
704 (!pMask
|| !pMask
->repeat
|| pMask
->repeatType
== RepeatNormal
) &&
705 !pSrc
->alphaMap
&& (!pMask
|| !pMask
->alphaMap
) && !pDst
->alphaMap
)
709 ret
= exaTryDriverComposite(op
, pSrc
, pMask
, pDst
, xSrc
, ySrc
, xMask
,
710 yMask
, xDst
, yDst
, width
, height
);
714 /* For generic masks and solid src pictures, mach64 can do Over in two
715 * passes, similar to the component-alpha case.
717 isSrcSolid
= pSrc
->pDrawable
->width
== 1 &&
718 pSrc
->pDrawable
->height
== 1 &&
721 /* If we couldn't do the Composite in a single pass, and it was a
722 * component-alpha Over, see if we can do it in two passes with
723 * an OutReverse and then an Add.
725 if (ret
== -1 && op
== PictOpOver
&& pMask
&&
726 (pMask
->componentAlpha
|| isSrcSolid
)) {
727 ret
= exaTryMagicTwoPassCompositeHelper(op
, pSrc
, pMask
, pDst
,
729 xMask
, yMask
, xDst
, yDst
,
738 exaPrintCompositeFallback (op
, pSrc
, pMask
, pDst
);
741 exaDoMigration(pixmaps
, npixmaps
, FALSE
);
742 ExaCheckComposite (op
, pSrc
, pMask
, pDst
, xSrc
, ySrc
,
743 xMask
, yMask
, xDst
, yDst
, width
, height
);
746 pSrc
->repeat
= saveSrcRepeat
;
748 pMask
->repeat
= saveMaskRepeat
;
753 * Same as miCreateAlphaPicture, except it uses ExaCheckPolyFillRect instead
754 * of PolyFillRect to initialize the pixmap after creating it, to prevent
755 * the pixmap from being migrated.
757 * See the comments about exaTrapezoids.
760 exaCreateAlphaPicture (ScreenPtr pScreen
,
762 PictFormatPtr pPictFormat
,
772 if (width
> 32767 || height
> 32767)
777 if (pDst
->polyEdge
== PolyEdgeSharp
)
778 pPictFormat
= PictureMatchFormat (pScreen
, 1, PICT_a1
);
780 pPictFormat
= PictureMatchFormat (pScreen
, 8, PICT_a8
);
785 pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
,
789 pGC
= GetScratchGC (pPixmap
->drawable
.depth
, pScreen
);
792 (*pScreen
->DestroyPixmap
) (pPixmap
);
795 ValidateGC (&pPixmap
->drawable
, pGC
);
799 rect
.height
= height
;
800 ExaCheckPolyFillRect (&pPixmap
->drawable
, pGC
, 1, &rect
);
801 exaPixmapDirty (pPixmap
, 0, 0, width
, height
);
803 pPicture
= CreatePicture (0, &pPixmap
->drawable
, pPictFormat
,
804 0, 0, serverClient
, &error
);
805 (*pScreen
->DestroyPixmap
) (pPixmap
);
810 * exaTrapezoids is essentially a copy of miTrapezoids that uses
811 * exaCreateAlphaPicture instead of miCreateAlphaPicture.
813 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
814 * to initialize the contents after creating the pixmap, which
815 * causes the pixmap to be moved in for acceleration. The subsequent
816 * call to RasterizeTrapezoid won't be accelerated however, which
817 * forces the pixmap to be moved out again.
819 * exaCreateAlphaPicture avoids this roundtrip by using ExaCheckPolyFillRect
820 * to initialize the contents.
823 exaTrapezoids (CARD8 op
, PicturePtr pSrc
, PicturePtr pDst
,
824 PictFormatPtr maskFormat
, INT16 xSrc
, INT16 ySrc
,
825 int ntrap
, xTrapezoid
*traps
)
827 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
828 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
831 * Check for solid alpha add
833 if (op
== PictOpAdd
&& miIsSolidAlpha (pSrc
))
835 for (; ntrap
; ntrap
--, traps
++)
836 (*ps
->RasterizeTrapezoid
) (pDst
, traps
, 0, 0);
845 xDst
= traps
[0].left
.p1
.x
>> 16;
846 yDst
= traps
[0].left
.p1
.y
>> 16;
848 miTrapezoidBounds (ntrap
, traps
, &bounds
);
849 if (bounds
.y1
>= bounds
.y2
|| bounds
.x1
>= bounds
.x2
)
851 pPicture
= exaCreateAlphaPicture (pScreen
, pDst
, maskFormat
,
852 bounds
.x2
- bounds
.x1
,
853 bounds
.y2
- bounds
.y1
);
856 for (; ntrap
; ntrap
--, traps
++)
857 (*ps
->RasterizeTrapezoid
) (pPicture
, traps
,
858 -bounds
.x1
, -bounds
.y1
);
859 xRel
= bounds
.x1
+ xSrc
- xDst
;
860 yRel
= bounds
.y1
+ ySrc
- yDst
;
861 CompositePicture (op
, pSrc
, pPicture
, pDst
,
862 xRel
, yRel
, 0, 0, bounds
.x1
, bounds
.y1
,
863 bounds
.x2
- bounds
.x1
,
864 bounds
.y2
- bounds
.y1
);
865 FreePicture (pPicture
, 0);
869 if (pDst
->polyEdge
== PolyEdgeSharp
)
870 maskFormat
= PictureMatchFormat (pScreen
, 1, PICT_a1
);
872 maskFormat
= PictureMatchFormat (pScreen
, 8, PICT_a8
);
873 for (; ntrap
; ntrap
--, traps
++)
874 exaTrapezoids (op
, pSrc
, pDst
, maskFormat
, xSrc
, ySrc
, 1, traps
);
878 #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
881 * exaRasterizeTrapezoid is just a wrapper around the software implementation.
883 * The trapezoid specification is basically too hard to be done in hardware (at
884 * the very least, without programmability), so we just do the appropriate
885 * Prepare/FinishAccess for it before using fbtrap.c.
888 exaRasterizeTrapezoid (PicturePtr pPicture
, xTrapezoid
*trap
,
889 int x_off
, int y_off
)
891 DrawablePtr pDraw
= pPicture
->pDrawable
;
892 ExaMigrationRec pixmaps
[1];
895 pixmaps
[0].as_dst
= TRUE
;
896 pixmaps
[0].as_src
= TRUE
;
897 pixmaps
[0].pPix
= exaGetDrawablePixmap (pDraw
);
898 exaDoMigration(pixmaps
, 1, FALSE
);
900 exaPrepareAccess(pDraw
, EXA_PREPARE_DEST
);
901 fbRasterizeTrapezoid(pPicture
, trap
, x_off
, y_off
);
902 exaGetDrawableDeltas(pDraw
, pixmaps
[0].pPix
, &xoff
, &yoff
);
903 exaPixmapDirty(pixmaps
[0].pPix
, pDraw
->x
+ xoff
, pDraw
->y
+ yoff
,
904 pDraw
->x
+ xoff
+ pDraw
->width
,
905 pDraw
->y
+ yoff
+ pDraw
->height
);
906 exaFinishAccess(pDraw
, EXA_PREPARE_DEST
);
910 * exaAddTriangles does migration and syncing before dumping down to the
911 * software implementation.
914 exaAddTriangles (PicturePtr pPicture
, INT16 x_off
, INT16 y_off
, int ntri
,
917 DrawablePtr pDraw
= pPicture
->pDrawable
;
918 ExaMigrationRec pixmaps
[1];
921 pixmaps
[0].as_dst
= TRUE
;
922 pixmaps
[0].as_src
= TRUE
;
923 pixmaps
[0].pPix
= exaGetDrawablePixmap (pDraw
);
924 exaDoMigration(pixmaps
, 1, FALSE
);
926 exaPrepareAccess(pDraw
, EXA_PREPARE_DEST
);
927 fbAddTriangles(pPicture
, x_off
, y_off
, ntri
, tris
);
928 exaGetDrawableDeltas(pDraw
, pixmaps
[0].pPix
, &xoff
, &yoff
);
929 exaPixmapDirty(pixmaps
[0].pPix
, pDraw
->x
+ xoff
, pDraw
->y
+ yoff
,
930 pDraw
->x
+ xoff
+ pDraw
->width
,
931 pDraw
->y
+ yoff
+ pDraw
->height
);
932 exaFinishAccess(pDraw
, EXA_PREPARE_DEST
);
936 * Returns TRUE if the glyphs in the lists intersect. Only checks based on
937 * bounding box, which appears to be good enough to catch most cases at least.
940 exaGlyphsIntersect(int nlist
, GlyphListPtr list
, GlyphPtr
*glyphs
)
959 if (glyph
->info
.width
== 0 || glyph
->info
.height
== 0) {
960 x
+= glyph
->info
.xOff
;
961 y
+= glyph
->info
.yOff
;
965 x1
= x
- glyph
->info
.x
;
968 y1
= y
- glyph
->info
.y
;
971 x2
= x1
+ glyph
->info
.width
;
974 y2
= y1
+ glyph
->info
.height
;
985 if (x1
< extents
.x2
&& x2
> extents
.x1
&&
986 y1
< extents
.y2
&& y2
> extents
.y1
)
1000 x
+= glyph
->info
.xOff
;
1001 y
+= glyph
->info
.yOff
;
1008 /* exaGlyphs is a slight variation on miGlyphs, to support acceleration. The
1009 * issue is that miGlyphs' use of ModifyPixmapHeader makes it impossible to
1010 * migrate these pixmaps. So, instead we create a pixmap at the beginning of
1011 * the loop and upload each glyph into the pixmap before compositing.
1014 exaGlyphs (CARD8 op
,
1017 PictFormatPtr maskFormat
,
1024 ExaScreenPriv (pDst
->pDrawable
->pScreen
);
1025 PixmapPtr pPixmap
= NULL
;
1026 PicturePtr pPicture
;
1027 PixmapPtr pMaskPixmap
= NULL
;
1028 PixmapPtr pDstPixmap
= exaGetDrawablePixmap(pDst
->pDrawable
);
1030 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
1031 int width
= 0, height
= 0;
1032 int x
, y
, x1
, y1
, xoff
, yoff
;
1033 int xDst
= list
->xOff
, yDst
= list
->yOff
;
1037 CARD32 component_alpha
;
1039 /* If we have a mask format but it's the same as all the glyphs and
1040 * the glyphs don't intersect, we can avoid accumulating the glyphs in the
1041 * temporary picture.
1043 if (maskFormat
!= NULL
) {
1044 Bool sameFormat
= TRUE
;
1047 for (i
= 0; i
< nlist
; i
++) {
1048 if (maskFormat
->format
!= list
[i
].format
->format
) {
1054 if (!exaGlyphsIntersect(nlist
, list
, glyphs
)) {
1060 /* If the driver doesn't support accelerated composite, there's no point in
1061 * going to this extra work. Assume that any driver that supports Composite
1062 * will be able to support component alpha using the two-pass helper.
1064 if (!pExaScr
->info
->PrepareComposite
)
1066 miGlyphs(op
, pSrc
, pDst
, maskFormat
, xSrc
, ySrc
, nlist
, list
, glyphs
);
1075 miGlyphExtents (nlist
, list
, glyphs
, &extents
);
1077 extents
.x1
= max(extents
.x1
, 0);
1078 extents
.y1
= max(extents
.y1
, 0);
1079 extents
.x2
= min(extents
.x2
, pDst
->pDrawable
->width
);
1080 extents
.y2
= min(extents
.y2
, pDst
->pDrawable
->height
);
1082 if (extents
.x2
<= extents
.x1
|| extents
.y2
<= extents
.y1
)
1084 width
= extents
.x2
- extents
.x1
;
1085 height
= extents
.y2
- extents
.y1
;
1086 pMaskPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
,
1090 component_alpha
= NeedsComponent(maskFormat
->format
);
1091 pMask
= CreatePicture (0, &pMaskPixmap
->drawable
,
1092 maskFormat
, CPComponentAlpha
, &component_alpha
,
1093 serverClient
, &error
);
1096 (*pScreen
->DestroyPixmap
) (pMaskPixmap
);
1099 ValidatePicture(pMask
);
1100 pGC
= GetScratchGC (pMaskPixmap
->drawable
.depth
, pScreen
);
1101 ValidateGC (&pMaskPixmap
->drawable
, pGC
);
1105 rect
.height
= height
;
1106 (*pGC
->ops
->PolyFillRect
) (&pMaskPixmap
->drawable
, pGC
, 1, &rect
);
1107 exaPixmapDirty(pMaskPixmap
, 0, 0, width
, height
);
1108 FreeScratchGC (pGC
);
1119 exaGetDrawableDeltas(pDst
->pDrawable
, pDstPixmap
, &xoff
, &yoff
);
1124 int maxwidth
= 0, maxheight
= 0, i
;
1125 ExaMigrationRec pixmaps
[1];
1126 PixmapPtr pScratchPixmap
= NULL
;
1131 for (i
= 0; i
< n
; i
++) {
1132 if (glyphs
[i
]->info
.width
> maxwidth
)
1133 maxwidth
= glyphs
[i
]->info
.width
;
1134 if (glyphs
[i
]->info
.height
> maxheight
)
1135 maxheight
= glyphs
[i
]->info
.height
;
1137 if (maxwidth
== 0 || maxheight
== 0) {
1143 x
+= glyph
->info
.xOff
;
1144 y
+= glyph
->info
.yOff
;
1150 /* Create the (real) temporary pixmap to store the current glyph in */
1151 pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, maxwidth
, maxheight
,
1152 list
->format
->depth
);
1156 /* Create a temporary picture to wrap the temporary pixmap, so it can be
1157 * used as a source for Composite.
1159 component_alpha
= NeedsComponent(list
->format
->format
);
1160 pPicture
= CreatePicture (0, &pPixmap
->drawable
, list
->format
,
1161 CPComponentAlpha
, &component_alpha
,
1162 serverClient
, &error
);
1164 (*pScreen
->DestroyPixmap
) (pPixmap
);
1167 ValidatePicture(pPicture
);
1169 /* Give the temporary pixmap an initial kick towards the screen, so
1170 * it'll stick there.
1172 pixmaps
[0].as_dst
= TRUE
;
1173 pixmaps
[0].as_src
= TRUE
;
1174 pixmaps
[0].pPix
= pPixmap
;
1175 exaDoMigration (pixmaps
, 1, pExaScr
->info
->PrepareComposite
!= NULL
);
1179 GlyphPtr glyph
= *glyphs
++;
1180 pointer glyphdata
= (pointer
) (glyph
+ 1);
1181 DrawablePtr pCmpDrw
= (maskFormat
? pMask
: pDst
)->pDrawable
;
1183 x1
= x
- glyph
->info
.x
;
1184 y1
= y
- glyph
->info
.y
;
1186 if (x1
>= pCmpDrw
->width
|| y1
>= pCmpDrw
->height
||
1187 (x1
+ glyph
->info
.width
) <= 0 || (y1
+ glyph
->info
.height
) <= 0)
1190 (*pScreen
->ModifyPixmapHeader
) (pScratchPixmap
,
1193 0, 0, -1, glyphdata
);
1195 /* Copy the glyph data into the proper pixmap instead of a fake.
1196 * First we try to use UploadToScreen, if we can, then we fall back
1197 * to a plain exaCopyArea in case of failure.
1199 if (pExaScr
->info
->UploadToScreen
&&
1200 exaPixmapIsOffscreen(pPixmap
) &&
1201 (*pExaScr
->info
->UploadToScreen
) (pPixmap
, 0, 0,
1205 PixmapBytePad(glyph
->info
.width
,
1206 list
->format
->depth
)))
1208 exaMarkSync (pScreen
);
1210 /* Set up the scratch pixmap/GC for doing a CopyArea. */
1211 if (pScratchPixmap
== NULL
) {
1212 /* Get a scratch pixmap to wrap the original glyph data */
1213 pScratchPixmap
= GetScratchPixmapHeader (pScreen
,
1216 list
->format
->depth
,
1217 list
->format
->depth
,
1219 if (!pScratchPixmap
) {
1220 FreePicture(pPicture
, 0);
1221 (*pScreen
->DestroyPixmap
) (pPixmap
);
1225 /* Get a scratch GC with which to copy the glyph data from
1226 * scratch to temporary
1228 pGC
= GetScratchGC (list
->format
->depth
, pScreen
);
1229 ValidateGC (&pPixmap
->drawable
, pGC
);
1231 (*pScreen
->ModifyPixmapHeader
) (pScratchPixmap
,
1234 0, 0, -1, glyphdata
);
1235 pScratchPixmap
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
1238 exaCopyArea (&pScratchPixmap
->drawable
, &pPixmap
->drawable
, pGC
,
1239 0, 0, glyph
->info
.width
, glyph
->info
.height
, 0, 0);
1242 exaPixmapDirty (pPixmap
, 0, 0,
1243 glyph
->info
.width
, glyph
->info
.height
);
1247 exaComposite (PictOpAdd
, pPicture
, NULL
, pMask
, 0, 0, 0, 0,
1248 x1
, y1
, glyph
->info
.width
, glyph
->info
.height
);
1249 exaPixmapDirty(pMaskPixmap
, x1
, y1
, x1
+ glyph
->info
.width
,
1250 y1
+ glyph
->info
.height
);
1254 exaComposite (op
, pSrc
, pPicture
, pDst
,
1255 xSrc
+ x1
- xDst
, ySrc
+ y1
- yDst
,
1256 0, 0, x1
, y1
, glyph
->info
.width
,
1257 glyph
->info
.height
);
1258 x1
+= pDst
->pDrawable
->x
+ xoff
;
1259 y1
+= pDst
->pDrawable
->y
+ yoff
;
1260 exaPixmapDirty(pDstPixmap
, x1
, y1
, x1
+ glyph
->info
.width
,
1261 y1
+ glyph
->info
.height
);
1264 x
+= glyph
->info
.xOff
;
1265 y
+= glyph
->info
.yOff
;
1269 FreeScratchGC (pGC
);
1270 FreePicture ((pointer
) pPicture
, 0);
1271 (*pScreen
->DestroyPixmap
) (pPixmap
);
1272 if (pScratchPixmap
!= NULL
)
1273 FreeScratchPixmapHeader (pScratchPixmap
);
1279 exaComposite (op
, pSrc
, pMask
, pDst
, xSrc
+ x
- xDst
, ySrc
+ y
- yDst
,
1280 0, 0, x
, y
, width
, height
);
1281 FreePicture ((pointer
) pMask
, (XID
) 0);
1282 (*pScreen
->DestroyPixmap
) (pMaskPixmap
);