Implementing Overlay Flipping in a DirectDraw Driver (Windows Embedded CE 6.0)
1/6/2010
The DirectDraw API provides support for both surface flipping and for overlay surfaces. Applications can combine these two capabilities within DirectDraw to flip overlay surfaces just as they can with primary display surfaces. For more information, see Flipping Surfaces, Overlay Surface Overview, and Flipping Overlay Surfaces.
The DirectDraw middleware provides the infrastructure to maintain display surfaces support and allow flipping between them. The digital-to-analog converter (DAC) within the graphics hardware handles the composition of the primary and overlay surfaces. The driver acts as an intermediary between the middleware and the DAC, correctly exposing the hardware's capabilities to the DirectDraw middleware and also managing the flow of data to the graphics hardware.
Overlay surfaces must always be stored in video memory. To implement overlay flipping, your display hardware must have enough video memory to support as many overlay back buffers as you need for your overlay's flipping chain.
To let DirectDraw applications know that your driver supports overlay flipping, you must prepare a DDHAL_DDSURFACECALLBACKS structure by setting the capability bits and by specifying your driver's implementations of the DirectDraw surface management functions. Specifically, your driver must set the DDHAL_SURFCB32_FLIP and DDHAL_SURFCB32_UPDATEOVERLAY flags and provide implementations for the Flip and UpdateOverlay functions. You expose the information in this DDHAL_DDSURFACECALLBACKS structure when you prepare your DDHALINFO structure in your implementation of HALInit.
Just as with the primary surface, you should flip between overlay surfaces during the vertical blanking period. This process, called tearing, prevents a partial view your new display surface from appearing while the previous surface is still being drawn. Tearing depends on whether your display hardware is able to send an interrupt for the vertical blanking period.
The preferred method to handle vertical blanking is to have the display driver, when it first loads, set up a vertical blanking interrupt on your system bus. This allows you to implement an interrupt handler that runs on its own infinite thread and reacts to your vertical blanking events from calls to WaitForSingleObject. This approach eliminates guesswork about when the vertical blanking period will occur. It is not only exact, but also efficient because it requires an absolute minimum amount of CPU time while waiting for the vertical blanking period, which is just enough to monitor the handler's thread. When your driver's interrupt handler is triggered, it can then release the right data to the display hardware at the right time.
If your display hardware does not support a vertical blanking interrupt, then your driver must spend some CPU time to determine when the vertical blanking will occur. A good approach is to have the driver's surface flipping thread predict when the next vertical blank will occur, and then sleep until that time. This frees the CPU for other tasks while the scan lines for the current surface are being drawn. It is preferable to having the driver actively monitor the location of each scan line, and thereby stall the CPU. For an example, see the implementation of the HalFlip function in the Tvia5000 sample driver code %_WINCEROOT%\Public\Common\OAK\Drivers\Display\Tvia5000\Halsurf.cpp.