Sample Blit Acceleration (Windows Embedded CE 6.0)

1/6/2010

By default, a display driver routes all blits to the GPE. As alternatives, a display driver can route blit handling to the emulation library or directly to the hardware.

The ATI display driver serves as a model to demonstrate how a display driver can invoke all three of these methods. The ATI sample code is located in the %_WINCEROOT%\Public\Common\OAK\Drivers\Display\ATI directory.

The following code example is from the sample ATI display driver and shows how blit processing begins when the GDI calls the driver's BltPrepare function.

The driver initializes the blit parameters and determines which function to use to perform the individual blits. Typically, the driver initializes the GPE to handle default blit processing.

SCODE ATI::BltPrepare(GPEBltParms *pBltParms)
{
// Put debug messages and optional timing processing here.

pBltParms->pBlt = EmulatedBlt; // Generic BLT processing

For improved performance, BltPrepare can examine the characteristics of the blit and the associated display surfaces to determine whether an accelerated blit is appropriate. After the initialization code, the display driver can contain code for hardware or software accelerations.

After setting the default handler, the ATI driver dispatches blits to hardware acceleration, if available, and then to software-accelerated emulation, if available.

First it verifies whether the destination surface is in video memory. This is an important verification that most display drivers must make before using hardware acceleration because the GDI uses the display driver to render printer output, as well as display output. Printer output is rendered in system memory, not in video memory.

Most display hardware can perform accelerated drawing in only two situations:

  • When the destination surface is in video memory (for example, for blits without a source surface)
  • When the source and destination surfaces are in video memory (for example, for blits with a source surface)

Therefore, if the hardware has this limitation, the driver must check the source and destination surfaces before calling the acceleration function.

The following code example shows how the driver evaluates the raster operation (ROP) code and directs the blit to supported hardware acceleration, when available.

The SRCCOPY ROP illustrates how the driver checks for a source surface in video memory before invoking hardware acceleration.

if (((ATISurf*)(pBltParms->pDst))->InVideoMemory() ) {
    switch( pBltParms->rop4 ) {
        case 0x0000:// BLACKNESS
            pBltParms->solidColor = 0x0;
            pBltParms->pBlt = (SCODE (GPE::*)
           (struct GPEBltParms *)) AcceleratedFillRect;
            break;
        case 0xFFFF:// WHITENESS
            pBltParms->solidColor = 0xffffff;
            pBltParms->pBlt = (SCODE (GPE::*)
            (struct GPEBltParms *))AcceleratedFillRect;
            break;
        case 0xF0F0:// PATCOPY and PATINVERT: emulate color 
        case 0x5A5A:// conversion.
            if (pBltParms->solidColor == -1) // emulate if not solid
            {                                // color
                break;
            }
            pBltParms->pBlt = (SCODE (GPE::*)(struct GPEBltParms *))
                              AcceleratedFillRect;
            break; 
        case 0x6666:// SRCINVERT, SRCAND, SRCCOPY and SRCPAINT:
        case 0x8888:// cannot accelerate if src is not in video ram.
        case 0xCCCC:// cannot accelerate if there are color translations.
        case 0xEEEE: 
            if (!pBltParms->pSrc->InVideoMemory() ||
                pBltParms->pLookup ||
                pBltParms->pConvert ||
                pBltParms->bltFlags & BLT_STRETCH)
                break;
            pBltParms->pBlt = (SCODE (GPE::*)(struct GPEBltParms *))
            AcceleratedSrcCopyBlt;
            break; 
    } // end switch

The ATI display driver shows how to use the blit emulation library. After setting the default blit handler and handling hardware accelerations, the driver searches for possible software accelerations.

The emulation library contains blit selection functions for modes that are 8 and 16 bpp. These selection functions make it easy to select the correct software accelerated blit function. You can use these selection functions directly in your driver or you can use them as a template for writing your own selection logic.

The following code example shows how the ATI driver sample uses the selection functions to select from any available software accelerated blit function.

if (pBltParms->pBlt == EmulatedBlt)
    {
        EmulatedBltSelect08 (pBltParms);
        EmulatedBltSelect16 (pBltParms);
    }

Because the ATI driver can run at several different color depths, the selection function must search for conditions that would prevent the blit from using emulation.

The software accelerated blit functions in the emulation library include the following restrictions:

  • The destination surface's color depth and the emulated function's color depth must match.
  • No transparency or stretching is allowed.
  • No color conversion or lookup is allowed.

The following code example shows how the selection function determines whether the blit can use the software accelerated blit functions.

// check the input parameters for validity
if (pBltParms->pDst->Format() != gpe8Bpp)
{
    return S_OK;
}
if ((pParms->bltFlags & (BLT_TRANSPARENT | BLT_STRETCH)))
{
    return S_OK;
}
if ((pParms->pLookup) || (pParms->pConvert))
{
    return S_OK;
}

After confirming that the emulation library functions can perform a blit, the selection function examines the ROPs, dispatching supported ROPs to the appropriate function.

The following code example shows how the selection function searches the ROP4 value to choose which blit function to use.

#define FUNCNAME(basename) (SCODE (GPE::*)(struct GPEBltParms \
*))Emulator::Emulated##basename
switch (pBltParms->rop4) {
    case 0x0000:    // BLACKNESS
        pBltParms->solidColor = 0;
        pBltParms->pBlt = FUNCNAME(BltFill08);
        break;
    case 0xFFFF:    // WHITENESS
        pBltParms->solidColor = 0x00ffffff;
        pBltParms->pBlt = FUNCNAME(BltFill08);
        break;
    case 0xF0F0: // PATCOPY
        if (pParms->solidColor == -1) // really a patterned brush?
        {
            pParms->pBlt = FUNCNAME(BltPatternCopy08);
        }
        else // must be a solid colored brush
        {
            pParms->pBlt = FUNCNAME(BltFill08);
        }
        break;

See Also

Concepts

Display Driver Samples
FLAT Sample Display Driver
ATI Sample Display Driver
ATI Sample Display Driver Optimization
Sample DrvEscape Function
Display Driver Performance Profiling
Display Driver Registry Settings
Display Driver Development Concepts
Display Driver Extensions
Display Driver Recommendations