Secondary Display Drivers

In addition to the primary display, Windows CE–based platforms can support additional display devices. These additional controllers might be used, for example, to support a VGA output to a CRT screen. Display drivers for such additional display devices are called secondary display drivers. Secondary display drivers are only loaded when an application calls the CreateDC function with the name of the secondary display driver’s .dll file. CreateDC returns a handle to a DC that is associated with the secondary display driver. An application can use this DC just like a DC associated with the primary display driver; all of the text and graphics APIs work with the DC. However, applications may not use any Window Manager functions with the DC since the Window Manager was not involved in creating it. Thus, applications are responsible for rendering the entire display on the secondary display device. If you want to create the appearance of windows, menus, dialog boxes, scroll bars, and so on, on the secondary display, your application must draw those items itself, using the text and graphics APIs. If you want to show the contents of the primary display on the secondary display, your application can copy the frame buffer for the primary display to the frame buffer for the secondary display. The secondary display driver is unloaded when there are no remaining DCs associated with it. When multiple display devices are being used, the GDI makes sure that all drawing calls are routed to the appropriate display driver.

Windows CE–based platforms can provide a built-in secondary display controller. The controller must be managed by a secondary display driver. The secondary display driver must be implemented as an ordinary Windows CE display driver, and expose the same DDI as other display drivers.

If the display controller resides on a removable medium, such as a PC Card, the secondary display driver can be implemented as two DLLs or as a single DLL. In practice, most device driver writers choose to implement two separate DLLs: a secondary display driver that exposes the native display driver DDI and a stream driver that exposes the 11 stream interfaces. The Device Manager loads the stream interface driver when the user connects the display adapter to the system and registers the driver’s special device file name, for example, “VGA1:”. The secondary display driver is loaded when an application calls CreateDC and passes in the name of the secondary display driver’s .dll file. The secondary display driver gets a handle to the stream interface driver by calling the FileOpen function on the “VGA1:” special device file. The secondary display driver handles all of the graphics processing. When it needs to communicate with the display controller, it uses the stream interface driver’s IOControl function.

You may choose to create a single DLL that acts as both secondary display driver and stream driver instead. In this case, the Device Manager loads this combined driver in its own process space to serve as an ordinary stream interface driver, whereas GWES would load the same driver in its process space to act as the secondary display driver. If you choose to implement a combined driver, be aware that because the driver DLL is loaded in separate process spaces, it cannot share global data without using shared memory or a memory-mapped file. Furthermore, having the driver loaded twice wastes system resources.

Many of the stream interface functions are not used by display device drivers since display devices are not particularly oriented to working with streams of data. Display drivers need only have stubs for those functions. For these interfaces, the driver should handle the call and return. The driver’s XXX_Init and XXX_Deinit functions are exceptions. The driver should handle calls to these functions correctly, as described in Developing Stream Interface Drivers. The Device Manager calls XXX_Init when the display adapter is connected to the system. When the adapter is disconnected, the Device Manager calls XXX_Deinit. XXX_Deinit deletes any data structures and registry entries that were created by the driver’s XXX_Init function.

Like all PCMCIA-based drivers, the stream interface driver must create Registry entries that enable the device to be detected. For more information, see Registry Keys for Display Drivers.