Premultiplied alpha handle for driver

Huang, FrankR FrankR.Huang at
Sun Jun 6 19:32:34 PDT 2010

	Sorry for late reply. My holiday is in weekend.
	Thanks for your clarify of how the driver to handle the CA composite operation. I have checked with your code. The result is that our geode driver can not handle the mask value with separate A,R,G,B 8bit value to mulitiply with the source ARGB. Our driver can only do that with a sole mask value(that is to say it is PICT_a4 and PICT_a8).
	I will make the driver return false with check_composite() when meeting this condition and let the server to do the SW rendering with this operation.


-----Original Message-----
From: Jonathan Morton [mailto:jonathan.morton at] 
Sent: 2010年6月4日 20:06
To: Huang, FrankR
Cc: Siarhei Siamashka; xorg-devel at
Subject: RE: Premultiplied alpha handle for driver

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

From: Jonathan Morton
      jonathan.morton at

More information about the xorg-devel mailing list