Blending HOWTO
From DirectFBWiki
| Table of contents |
Introduction
This document describes a simple step by step usage of the DirectFB API for alpha blending.
Alpha Blending
This section will give a very short overview of alpha blending, based on the Porter-Duff article.
The key concepts:
- A transparency value (alpha value) is stored with every pixel.
- When writing a pixel to an existing surface, the pixel can be merged in different ways with the existing pixel. For the purpose of this HowTo we will distinguish three methods:
- CLEAR
- SRC
- SRC_OVER
- For all compositing rules all pixel values must have the color components pre multiplied by the alpha value. This means that for an original rgb tuple Co=(r, g, b) with an alpha value of a (0.0 ≤ a ≤ 1.0), the pre multiplied pixel value is Cp=(r*a, g*a, b*a, a). Pre multiplying pixel values makes blending more efficient and is necessary for hardware acceleration.
- Extra Alpha
This is a “global” alpha value that can be used to influence all pixels in a blitting operation.
Compositing rules
The original pixel value Co, is expressed as Co=(ro, go, bo, a). The pre multiplied value is expressed as Cp=( ro*a, go*a, bo*a, a), extra alpha is Aextra.
All pixel values used below are assumed to be pre multiplied.
Cd = “destination pixel value” Cs = “source pixel value” Ad = “destination alpha value” As = “source alpha value” If “extraAlpha” is used all alpha values are multiplied with Aextra, i.e.
As’ = As *Aextra
CLEAR
Clear the destination pixel
- Cd = Cs * 0.0 + Cd * 0.0 = (0, 0, 0, 0)
SRC
Overwrite the destination pixel with the source pixel.
- Cd = Cs * 1.0 + Cd * 0.0 = Cs
SRC_OVER
Blend the destination pixel with the source pixel as follows:
- Cd = Cs * 1.0 + Cd * (1-As)
DirectFB
In the example below all pixel values being used as colors are already pre multiplied, hence the use of the flag DSCAPS_PREMULTIPLIED and the lack of the blitting flag DSBLIT_[SRC|DST]_PREMULTIPLY. If you were to use this last flag, DirectFB will do the multiplication for you.
The flag DSCAPS_PREMULTIPLIED is only used when the window stacking is being repainted by DirectFB. It is a hint to the system that the values are already pre multiplied.
If you want to use “extraAlpha”, you need to set up the blitting flags to do this for you, i.e. add the flag DSBLIT_SRC_PREMULTCOLOR.
Setting up the primary surface
DFBCHECK(DirectFBInit( &argc, &argv )); /* create the super interface */ DFBCHECK(DirectFBCreate( &dfb )); /* set our cooperative level to DFSCL_FULLSCREEN for exclusive access to the primary layer */ dfb->SetCooperativeLevel( dfb, DFSCL_FULLSCREEN ); /* get the primary surface, i.e. the surface of the primary layer we have exclusive access to */ sdsc.flags = DSDESC_CAPS; sdsc.caps = DSCAPS_PRIMARY | DSCAPS_PREMULTIPLIED; DFBCHECK(dfb->CreateSurface( dfb, &sdsc, &primary ));
Performing a drawing operation
Perform a drawing operation with pre-multiplied colors in SetColor()
// blend primary->SetDrawingFlags(primary, DSDRAW_BLEND); // specify porter duff rule, this will setup the drawing functions // for you, you can also set them directly using // Set[Src|Dst]BlendFunction() primary->SetPorterDuff(primary, DSPD_SRC); // Red, semi-transparent (r,g,b,a) pre multiplied, thus the original // pixel value would be (0xFF, 0x0, 0x0, 0x80) primary->SetColor(primary, 0x80, 0x0, 0x0, 0x80); primary->DrawLine(primary, 10, 10, 300, 200);
Perform a drawing operation with non-pre-multiplied colors in SetColor()
Changes:
1. Specify DSDRAW_SRC_PREMULTIPLY as the drawingflag primary->SetDrawingFlags(primary, DSDRAW_SRC_PREMULTIPLY); 2. Use a non-premultiplied color primary->SetColor(primary, 0xFF, 0x0, 0x0, 0x80);
Performing a blit operation
Setup a new surface that will be blitted to the primary surface.
/* create a surface */ sdsc.flags = DSDESC_CAPS | DSDESC_PIXELFORMAT | DSDESC_WIDTH | DSDESC_HEIGHT; sdsc.caps = DSCAPS_PREMULTIPLIED; sdsc.pixelformat = DSPF_ARGB; sdsc.width = screen_width; sdsc.height = screen_height; DFBCHECK(dfb->CreateSurface( dfb, &sdsc, &blitsurf )); primary->SetDrawingFlags(primary, DSDRAW_BLEND); // Porter Duff blitsurf->SetPorterDuff(blitsurf, DSPD_SRC_OVER); // Draw a rectangle in the blit surface, blue semi-transparent. // (a,r,g,b) pre multiplied. thus the original // pixel value would be (0x80, 0x0, 0x0, 0xFF) blitsurf->SetColor(blitsurf, 0x80, 0x0, 0x0, 0x80); blitsurf->FillRectangle(blitsurf, 10, 10, 200, 300); // The alpha value of the color set with SetColor() will be used for // the “extraAlpha”. ExtraAlpha is a global alpha value applied to // all pixels when blitting. To use this add ‘DSBLIT_SRC_PREMULTCOLOR’ // to the blitting flags. primary->SetBlittingFlags(blitsurf, DSBLIT_BLEND_ALPHACHANNEL); // Now blit it to the primary surface primary->Blit(primary, blitsurf, NULL, 15, 15);
--Marc 20:49, 30 Jun 2006 (CEST)
