|
Introduction to Writing Windows CE Display Drivers(4) Writing display drivers using the DDI directly can involve a lot of duplication of code from one display driver to the next. To greatly simplify and speed up development, Microsoft has provided a set of C++ classes that contain most of the base code that is required from any display driver. What this means for the display driver developer in Windows CE is that code only needs to be added for functionality that is specific to the device, such as initialization and mode setting, hardware cursors, and accelerated blits and line drawing. You can really appreciate how much time these classes save if you have ever done display driver development for other Windows operating systems. In a typical Windows CE display driver, the most time consuming tasks usually involve device initialization and mode setting. This is due to the fact that Windows CE does not support executing a video BIOS, where initialization and mode setting would normally be handled. The one exception to this is the CEPC platform, where the bootloader, LOADCEPC, does make video BIOS calls to initialize and set the mode for the display device. This is possible since LOADCEPC is actually a DOS application. However, for the typical Windows CE system this is not an option.
Microsoft makes several recommendations for display hardware, intended to improve driver performance and simplify development. The most important of these is that the display hardware uses a linear frame buffer. What this means is that the display memory needs to be contiguous, with this entire block of memory being directly accessible by the CPU. Therefore, access to display memory through bank selection, should not be used. Another important recommendation is not to use bit planes. This is when each color channel or intensity component is in a separate buffer. Display memory bank selection and bit planes exist as part of legacy VGA support, with most newer VGA controllers now also including support for a linear frame buffer as well as for packed pixel, or non-planar, display modes. It is important to follow these recommendations if you wish to take advantage of the default blit and line drawing functions provided in the C++ classes. Graphics Primitive Engine ClassesAs previously mentioned, Microsoft provides a set of C++ classes called the Graphics Primitive Engine, or GPE, that simplify display driver development in Windows CE. The most important of these is the GPE class, which represents the display device. It is a pure virtual class, which means that it must be derived from and that certain base class functions must be implemented. Since source code is not provided in Platform Builder for this class or how the DDI functions interface with it, it is useful to review these functions that require implementation. They are: - NumModes - Returns the number of display modes supported by the display driver.
- GetModeInfo - Returns information about a specific display mode, such as display width and height in pixels and number of bits per pixel. This function should handle the number of display modes returned by the NumModes() function. The first mode entry in the list of supported modes is always the one selected for configuration when SetMode() is later called.
- SetMode - Sets the display mode. This can be the most time consuming function to write in the entire driver, especially for VGA controllers, since configuration of the display device can be a fairly involved process.
- AllocSurface - Allocates a surface, which is just a block of system or video memory to store pixel data. The GPESurf class can be used to represent surfaces in system memory. To represent surfaces in video memory, the GPESurf class must be derived from. The GPESurf class is discussed in more detail later.
- SetPointerShape - Sets the cursor bitmap and cursor hotspot.
- MovePointer - Moves the cursor.
- BltPrepare - Called before the blit operation is performed. It allows the driver to setup the blit hardware for performing the operation, if it is supported. It must return the actual function to be called to perform the blit operation, which can be the default blit function provided in the GPE class.
- BltComplete - Called after the blit operation has been performed. It allows the driver to do any cleanup required after the blit operation, if necessary.
- Line - Called before and after a line drawing operation. When it is called before the line drawing is done, the function can setup the line drawing hardware for performing the operation, if it is supported. It must return the actual function to be called to perform the line drawing operation, which can be the default line drawing function in the GPE class. When it is called after the line drawing is done, the function can do any cleanup required after the line drawing operation, if necessary.
- SetPalette - Sets the palette. This only applies for modes that support a palette, which is typically 8 bits per pixel or less.
- InVBlank - Indicates if the display update is in the vertical blanking period. This is useful for reducing an animation problem known as tearing, where the display memory update is not in sync with the display refresh on the monitor.
There are other functions in the GPE class that have default implementations, but can be overridden for non-default behavior. These functions are: - IsPaletteSettable - Returns TRUE if the palette is settable or FALSE if the palette is fixed or if the mode doesn't require a palette, such as 16-bit or 24-bit per pixel modes. The default implementation checks the Bpp field of the m_pMode variable and returns TRUE if it equals 8, otherwise it returns FALSE.
- GetGraphicsCaps - Indicates if the display driver supports additional graphics features. The default implementation returns 0.
- ContrastControl - Receives commands related to contrast control, such as getting and setting the current contrast value. It is useful if the display is a LCD panel. The default implementation does nothing and always returns 1.
- PowerHandler - Receives power on and power off notification. The function can be used to suspend or resume power to the display device. As with any driver that receives power notifications, it is important to note that this function should not make any calls that could cause the thread to block as it is the only thread running at the time it is called.
Besides these, there is a set of functions in the GPE class that are described as being required for DDHAL support. The implication is that these functions are part of the DirectDraw hardware abstraction layer, or HAL. Since the display driver model for version 2.0 was developed well ahead of the release of DirectDraw for Windows CE, these functions were probably included as a best "guess" of the display driver requirements for DirectDraw support. As it stands, these functions are only part of the story for DirectDraw support and are not required for a standard display driver so I will not specifically discuss them here. I will add, however, that these functions do provide additional capabilities that, if properly exported, could be used by applications to bypass GDI for improved performance.
|