Creating a DirectGDI Adaptation

This topic provides information about creating a DirectGDI adaptation.

Target audience: Device creators.

Note: DirectGDI is deprecated in Symbian^3.

Required background

This topic assumes an understanding of the material contained in the following:

Packaging the DLL

When packaging the adaptation, the following rules apply:

  • The DirectGDI adaptation must be packaged as a DLL with the name directgdiadapter.dll.

  • The second and third UIDs must be 0x1000008D and 0x102858E9, respectively.

  • All capabilities except TCB (Trusted Computing Base) are required.

  • The NOEXPORTLIBRARY keyword must be used in the MMP file to prevent the generation of LIB/DSO files during the build process.

Here is a snippet of an example MMP file:

TARGET directgdiadapter.dll
TARGETTYPE DLL
CAPABILITY All -Tcb
UID 0x1000008D 0x102858E9
VENDORID <Your vendor ID in hex>
NOEXPORTLIBRARY

The reference adaptation component has several implementations for different configurations. These have different names and the one that is to be used in the device is renamed to directgdiadapter.dll during the ROM building process. You may want to use a similar approach. See Selection of Adaptations for more information.

Because the DirectGDI Adaptation component is optional, the DirectGDI component provides a stub implementation for platform security reasons. When a functional adaptation is not present, the stub implementation is compiled into a DLL called directgdiadapter.dll and is installed in the ROM in order to prevent a SIS file installing a rogue DLL with this name.

The exported function

The DirectGDI adaptation DLL is a polymorphic interface DLL that must export a single function at ordinal position one. The function that must be exported is CDirectGdiDriverInternal::New(). Here is its definition in the stub implementation:

EXPORT_C TInt CDirectGdiDriverInternal::New(CDirectGdiDriverInternal*& aInternal, RLibrary /*aLibrary*/)
    {
    aInternal = NULL;
    return KErrNotSupported;
    }

This simply returns KErrNotSupported to indicate that the DirectGDI functionality is not supported. This is because, as mentioned above, the stub implementation is used for platform security reasons when no functional DirectGDI adaptation is present.

In a functional implementation, the function must create a new instance of the class that is derived from CDirectGdiDriverInternal and return it in the pointer argument.

Implementing the interfaces

The DirectGDI Interface component provides a Hardware Adaptation Interface (HAI), which separates the generic and adaptation parts of the DirectGDI framework. The component defines a set of interfaces for which the adaptation must provide an implementation. As long as the implementation conforms to the interface specifications and contracts, you are free to write the adaptation as you see fit.

Driver adapter. You must create a concrete driver adapter class that implements all the pure virtual functions of CDirectGdiDriverInternal. This driver adapter is a singleton class. A single instance can be created for each process or each thread that uses the DirectGDI API, depending on your requirements. The driver adapter is responsible for creating and destroying drawing engines, and creating and destroying implementations of RDirectGdiDrawableSource and RDirectGdiImageTarget.

Engine adapter. You must create a concrete engine adapter class that implements the MDirectGdiEngine interface. A concrete engine adapter instance is created for each instance of CDirectGdiContext. The engine adapter performs the actual drawing and blitting routines that enable rendering to an RDirectGdiImageTarget instance. Because DirectGDI is a replacement for BitGDI, the behaviour of the engine adapter must match the behaviour of BitGDI as far as possible. If an exact match is not possible, the behaviour must be as close as possible.

In addition, you must create implementations of adaptation-specific resources that correspond to the following handle classes:

Extension interfaces

The CDirectGdiDriver::GetInterface() function provides an optional mechanism for DirectGDI adaptations to extend the HAI by defining extension interfaces. The DirectGDI client can access these by using the CDirectGdiDriver::GetInterface() method.

Performance considerations

Sometimes the requirements of graphics hardware mean that images and glyphs must be converted from one format to another (for example, from CFbsBitmap to VGImage) every time they are drawn. In these circumstances, you may want to consider introducing a caching mechanism to store the converted images and glyphs in order to reduce unnecessary format conversions.

Conformance testing

DirectGDI should produce output that is comparable to BitGDI. You can test your DirectGDI adaptation by using the DirectGDI test suite. This compares test images created using all of the CDirectGDIContext APIs with those generated using BitGDI. Fine tuning the adaptation to match the BitGDI reference images as closely as possible ensures a continued look and feel.