Call exaTryComponentAlphaHelper() for solid src also.

Also, rename to exaTryMagicTwoPassCompositeHelper() as it is now called for
non-component-alpha masks also, and add function description from
http://anholt.livejournal.com/32058.html.
This commit is contained in:
George Sapountzis 2006-08-12 20:54:33 +03:00
parent e641000b98
commit 37943e2f1a

View File

@ -452,24 +452,72 @@ exaTryDriverComposite(CARD8 op,
return 1; return 1;
} }
/**
* exaTryMagicTwoPassCompositeHelper implements PictOpOver using two passes of
* simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
* alpha and limited 1-tmu cards.
*
* From http://anholt.livejournal.com/32058.html:
*
* The trouble is that component-alpha rendering requires two different sources
* for blending: one for the source value to the blender, which is the
* per-channel multiplication of source and mask, and one for the source alpha
* for multiplying with the destination channels, which is the multiplication
* of the source channels by the mask alpha. So the equation for Over is:
*
* dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
* dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
* dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
* dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
*
* But we can do some simpler operations, right? How about PictOpOutReverse,
* which has a source factor of 0 and dest factor of (1 - source alpha). We
* can get the source alpha value (srca.X = src.A * mask.X) out of the texture
* blenders pretty easily. So we can do a component-alpha OutReverse, which
* gets us:
*
* dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
* dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
* dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
* dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
*
* OK. And if an op doesn't use the source alpha value for the destination
* factor, then we can do the channel multiplication in the texture blenders
* to get the source value, and ignore the source alpha that we wouldn't use.
* We've supported this in the Radeon driver for a long time. An example would
* be PictOpAdd, which does:
*
* dst.A = src.A * mask.A + dst.A
* dst.R = src.R * mask.R + dst.R
* dst.G = src.G * mask.G + dst.G
* dst.B = src.B * mask.B + dst.B
*
* Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
* after it, we get:
*
* dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
* dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
* dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
* dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
*/
static int static int
exaTryComponentAlphaHelper(CARD8 op, exaTryMagicTwoPassCompositeHelper(CARD8 op,
PicturePtr pSrc, PicturePtr pSrc,
PicturePtr pMask, PicturePtr pMask,
PicturePtr pDst, PicturePtr pDst,
INT16 xSrc, INT16 xSrc,
INT16 ySrc, INT16 ySrc,
INT16 xMask, INT16 xMask,
INT16 yMask, INT16 yMask,
INT16 xDst, INT16 xDst,
INT16 yDst, INT16 yDst,
CARD16 width, CARD16 width,
CARD16 height) CARD16 height)
{ {
ExaScreenPriv (pDst->pDrawable->pScreen); ExaScreenPriv (pDst->pDrawable->pScreen);
assert(op == PictOpOver); assert(op == PictOpOver);
assert(pMask->componentAlpha == TRUE);
if (pExaScr->info->CheckComposite && if (pExaScr->info->CheckComposite &&
(!(*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask, (!(*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
@ -580,19 +628,30 @@ exaComposite(CARD8 op,
(!pMask || !pMask->repeat || pMask->repeat == RepeatNormal) && (!pMask || !pMask->repeat || pMask->repeat == RepeatNormal) &&
!pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap) !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
{ {
Bool isSrcSolid;
ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask,
yMask, xDst, yDst, width, height); yMask, xDst, yDst, width, height);
if (ret == 1) if (ret == 1)
goto done; goto done;
/* For generic masks and solid src pictures, mach64 can do Over in two
* passes, similar to the component-alpha case.
*/
isSrcSolid = pSrc->pDrawable->width == 1 &&
pSrc->pDrawable->height == 1 &&
pSrc->repeat;
/* If we couldn't do the Composite in a single pass, and it was a /* If we couldn't do the Composite in a single pass, and it was a
* component-alpha Over, see if we can do it in two passes with * component-alpha Over, see if we can do it in two passes with
* an OutReverse and then an Add. * an OutReverse and then an Add.
*/ */
if (ret == -1 && pMask && pMask->componentAlpha && op == PictOpOver) { if (ret == -1 && op == PictOpOver && pMask &&
ret = exaTryComponentAlphaHelper(op, pSrc, pMask, pDst, xSrc, ySrc, (pMask->componentAlpha || isSrcSolid)) {
xMask, yMask, xDst, yDst, ret = exaTryMagicTwoPassCompositeHelper(op, pSrc, pMask, pDst,
width, height); xSrc, ySrc,
xMask, yMask, xDst, yDst,
width, height);
if (ret == 1) if (ret == 1)
goto done; goto done;
} }