Premultiplied alpha handle for driver

Jonathan Morton jonathan.morton at movial.com
Fri Jun 4 05:06:13 PDT 2010


On Fri, 2010-06-04 at 10:20 +0800, Huang, FrankR wrote:
> I still want to get understand to you CA operation on rendercheck.

> I see the code, the mask is not a simple PICT_A8 format, it is a 32
> bit value, and each 8 bit alpha value for A, R, G, B?

Okay, I've refreshed my memory of the code - there are subtleties in the
Pixman implementation that are hard to read.  Recalling the code example
I gave you to clarify the straight masked-over operation, here's a
version that implements the component-wise masking operation.

void PixelsDoComponentMask (
    PixelsColour * src,
    PixelsColour * msk,
    PixelsColour * tmp,
    const u32 count )
{
    for(u32 c=0; c < count; c++) {
        tmp[c].a = divBy255(src[c].a * msk[c].a);
        tmp[c].r = divBy255(src[c].r * msk[c].r);
        tmp[c].g = divBy255(src[c].g * msk[c].g);
        tmp[c].b = divBy255(src[c].b * msk[c].b);

        if(src[c].a < 255) {
            u32 sa = src[c].a;
            msk[c].a = divBy255(msk[c].a * sa);
            msk[c].r = divBy255(msk[c].r * sa);
            msk[c].g = divBy255(msk[c].g * sa);
            msk[c].b = divBy255(msk[c].b * sa);
        }
    }
}

void PixelsDoOpOverComponent (
    const PixelsColour * const src,
    const PixelsColour * const msk,
          PixelsColour *       dst,
    const u32 count )
{
    for(u32 c=0; c < count; c++) {
        dst[c].a = sat255(divBy255(dst[c].a * (255 - msk[c].a)) + src[c].a);
        dst[c].r = sat255(divBy255(dst[c].r * (255 - msk[c].r)) + src[c].r);
        dst[c].g = sat255(divBy255(dst[c].g * (255 - msk[c].g)) + src[c].g);
        dst[c].b = sat255(divBy255(dst[c].b * (255 - msk[c].b)) + src[c].b);
    }
}

The calling convention changes to:

if(msk) {
	if(attr.ComponentAlpha) {
		PixelsDoComponentMask(src, msk, tmp, count);
		PixelsDoOpOverComponent(tmp, msk, dst, count);
	} else {
	        PixelsDoMask(src, msk, tmp, count);
	        PixelsDoOpOver(tmp, dst, count);
	}
} else {
        PixelsDoOpOver(src, dst, count);
}

Notice that both the masking operation and the OVER operation are
changed to use component-wise blending, and that extra information needs
to be passed forward from the masking to the operation.

It is entirely possible that Geode hardware cannot implement this
operation directly.  In that case, EXA already has logic that can
convert common cases of it into two conventional operations.  Simply
reject acceleration of it and accept the simpler operations that are
substituted.

-- 
------
From: Jonathan Morton
      jonathan.morton at movial.com




More information about the xorg-devel mailing list