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:
parent
e641000b98
commit
37943e2f1a
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue