Creating an Extended Bitmap Rasterizer

An extended bitmap rasterizer is a DLL that decompresses extended bitmaps in order that they can be drawn by using the legacy BitGDI API.

Variant: ScreenPlay and non-ScreenPlay. Target audience: Device creators.

This topic assumes an understanding of the material covered in Extended Bitmaps.

Introduction

The standard Font and Bitmap Server client library (fbscli.dll) dynamically links against the extended bitmap rasterizer DLL.

When an application calls RFbsSession::Connect() to create a session with the Font and Bitmap Server, an instance of the extended bitmap rasterizer DLL is instantiated in the context of the application thread. This extended bitmap rasterizer DLL instance is used by the thread in which it is created and it is destroyed when the RFbsSession is closed. Multiple threads across the system can simultaneously use their own extended bitmap rasterizer DLL instances.

BitGDI uses the extended bitmap rasterizer DLL through the Font and Bitmap Server client-side library to obtain scan lines from extended bitmaps as if they are compressed bitmaps.

Implementing the CFbsRasterizer interface

An extended bitmap rasterizer DLL must provide an implementation of the CFbsRasterizer interface. This interface provides BitGDI with APIs for rasterizing extended bitmaps and retrieving scan lines from them. The following table provides a brief description of the key functions. For more detailed documentation, see CFbsRasterizer.

Function Description

New()

Returns a new instance of the extended bitmap rasterizer DLL for use by the calling thread.

BeginBitmap()

Registers an extended bitmap with the extended bitmap rasterizer DLL so that scan line requests can be made on that bitmap. BeginBitmap() is a signal to the extended bitmap rasterizer DLL that scan lines are about to be requested for a particular extended bitmap. It is therefore an opportunity for the extended bitmap rasterizer DLL to pre-rasterize all of the extended bitmap or the requested region of it. This makes it possible to return a portion of the pre-rasterized bitmap quickly when ScanLine() is subsequently called. Because ScanLine() is often called repeatedly, pre-rasterizing the bitmap at the BeginBitmap() stage can improve performance considerably.

EndBitmap()

Unregisters an extended bitmap that was previously registered using BeginBitmap(). EndBitmap() allows any resources that were allocated for the extended bitmap to be released. However, you may want to implement a cache of the most recently used extended bitmaps. This can improve performance of applications that make multiple calls to CFbsBitmap::GetScanLine(), CFbsBitmap::GetPixel() or CFbsBitmap::GetVerticalScanLine(). See Performance considerations below for more information.

ScanLine()

Returns a scan line of pixels for a particular extended bitmap. The scan lines must be 32-bit aligned. Although an x-coordinate and length are passed in, ScanLine() must return a pointer to the start of the whole scan line. However, only the portion defined by the x-coordinate and the length need to contain correct data.

The first call to ScanLine() from BitGDI for an extended bitmap is always preceded by a call to BeginBitmap().

GetInterface()

Returns a pointer to an extension interface. This provides a mechanism for extending the CFbsRasterizer interface without breaking existing implementations. If the extended bitmap rasterizer DLL does not support any extended interfaces, this function must return KErrExtensionNotSupported.

Error handling

It is important that your extended bitmap rasterizer DLL is robust and does not cause any exceptions or panics, because a copy is loaded for each Font and Bitmap Server session. When the extended bitmap rasterizer DLL encounters an error, it must fail silently in order to avoid causing a system failure.

When testing your extended bitmap rasterizer DLL using the CFbsBitGc blitting and drawing operations, you will see a white rectangle drawn if an error occurs in the extended bitmap rasterizer DLL. BitGDI draws a white scan line when a scan line cannot be retrieved from the extended bitmap rasterizer DLL.

Performance considerations

Caching

Adding a cache of previously rasterized extended bitmaps to your extended bitmap rasterizer DLL might improve performance significantly, especially for applications that make repeated calls to CFbsBitmap::GetScanLine(), CFbsBitmap::GetPixel() or CFbsBitmap::GetVerticalScanLine(). The following pseudocode shows what happens when an application calls CFbsBitmap::GetScanLine() repeatedly for an extended bitmap:

for each (scanline)
    {
    BeginBitmap() 
    ScanLine()
    EndBitmap()
    }

In contrast, when drawing an extended bitmap using CFbsBitGc::BitBlt() or CFbsBitGc::DrawBitmap(), the sequence is as follows:

BeginBitmap()
for each (scanline)
    {
    ScanLine()
    }
EndBitmap()

If the extended bitmap rasterizer DLL has a cache of previously rasterized extended bitmaps, calls to CFbsBitmap::GetScanLine(), CFbsBitmap::GetPixel() and CFbsBitmap::GetVerticalScanLine() do not need to rasterize the bitmap for each call, which can improve performance dramatically.

An extended bitmap rasterizer DLL cache contains the previously rasterized content for the most recently used extended bitmaps. Typically the extended bitmap rasterizer DLL adds new bitmaps to the cache when CFbsRasterizer::BeginBitmap() is called (if they are not already in the cache) and does not automatically remove bitmaps from the cache when CFbsRasterizer::EndBitmap() is called.

It is possible for an extended bitmap to be deleted before its cached information is deleted from the cache. It is therefore important that the cache does not store pointers to the data that was used to create the pre-rasterized content.

There are two approaches that can be used to manage the cache:

  • Remove the oldest items when a maximum cache size is reached.

  • Associate the extended bitmap rasterizer DLL with a CIdle active object and remove all of the items during idle times.

It is recommended that you use both mechanisms in order to optimize memory usage. The example extended bitmap rasterizer DLL does this. It maintains a list of recently used bitmaps, with the most recently used one being first in the list. If the size of the cache exceeds the set maximum, the oldest bitmaps are removed until the size is within limits again. The example extended bitmap rasterizer DLL also uses a CIdle object that clears the cache during idle times.

Memory

The example extended bitmap rasterizer DLL allocates and frees memory during CFbsRasterizer::BeginBitmap() and CFbsRasterizer::EndBitmap(), respectively. This approach may be slow if frequent allocation and freeing of large amounts of memory is required.

A possible solution is to pre-allocate a memory pool from which the extended bitmap rasterizer DLL can use areas of memory. This reduces the number of allocations. However, this solution may be unsuitable for some scenarios, such as when memory usage is more important than performance.

Example extended bitmap rasterizer

The Symbian platform provides a simple example extended bitmap rasterizer, which you can use as a reference when you are creating your own. The source code is located in the os\graphics\fbs\fontandbitmapserver\trasterizer\src folder. It is built as fbsrasterizer_test.dll when you build the test code for the Font and Bitmap Server component.

This extended bitmap rasterizer DLL handles a tricolor flag. The data comprises the flag's three colors and the direction (horizontal or vertical) of the stripes as shown in the following picture.

Figure 1. Tricolor flag with horizontal and vertical stripes
  • When CFbsRasterizer::BeginBitmap() is called for this type of extended bitmap, the extended bitmap rasterizer DLL creates a pixel buffer the size of the whole flag and draws the flag into it. If BitGDI specifies a region, the extended bitmap rasterizer DLL draws only the region and otherwise it draws the whole flag. For some extended bitmap rasterizers it may be faster to ignore the region and draw the whole bitmap area.

  • Calls to CFbsRasterizer::ScanLine() return a pointer to the appropriate place in the pre-rasterized buffer.

  • Calling CFbsRasterizer::EndBitmap() causes the pre-rasterized buffer to be stored in the cache or deleted.

Packaging the DLL

Because an extended bitmap rasterizer DLL is optional, there is a stub implementation for platform security reasons. When a functional extended bitmap rasterizer DLL is not present, the stub implementation is compiled into a DLL and is installed in the ROM in order to prevent a SIS file installing a rogue DLL with the same name.

The MMP file

  • The DLL must have the name fbsrasterizer.dll. If the DLL is renamed during the build process, use the LINKAS keyword in the MMP file to indicate that this is the final name of the DLL. See Selection of Adaptations for more information.

  • Use UIDs 0x1000008D (which indicates a static interface DLL) and 0x10285EAE (which is a unique identifier that indicates that this is an extended bitmap rasterizer DLL).

  • The DLL must have all capabilities except TCB (Trusted Computing Base).

  • Use the NOEXPORTLIBRARY keyword to prevent the generation of LIB/DSO files during the build process.

Here is a snippet from the stub implementation's MMP file:

TARGET fbsrasterizer_stub.dll
TARGETTYPE DLL
CAPABILITY All -Tcb
UID 0x1000008D 0x10285EAE
LINKAS fbsrasterizer.dll
NOEXPORTLIBRARY

ROM building

Building a ROM image for a target platform involves using IBY files. By default the stub implementation is included using the standard mechanism for selecting graphics adaptation components. This is described in Selection of Adaptations.

There is no generic IBY file for the extended bitmap rasterizer. Instead it is included in the main fbserv.iby file like this:

// FBSERV_IBY
    
#ifndef __FBSERV_IBY__
#define __FBSERV_IBY__
    
REM FBSERV - Font and Bitmap Server
    
...
    
// Extended bitmap rasterizer DLL
#include <graphics_adaptation.hby>
#include FBSRASTERIZER_DRV
      
#endif //__FBSERV_IBY__

You must create an implementation-specific IBY file. This should have a unique name of the form fbsrasterizer_vendor.iby, where vendor is the vendor's name, the format of the proprietary data or some other identifying feature of the extended bitmap rasterizer DLL. Here is an example of an implementation-specific IBY file:

// FBSRASTERIZER_VENDOR_IBY
    
#ifndef FBSRASTERIZER_VENDOR_IBY
#define FBSRASTERIZER_VENDOR_IBY
    
file=ABI_DIR\BUILD_DIR\fbsrasterizer_vendor.dll \sys\bin\fbsrasterizer.dll
    
#endif // FBSRASTERIZER_VENDOR_IBY

This IBY file must be exported to the /epoc32/rom/include/core/os/ folder.

You can include this implementation-specific IBY file in a device ROM configuration file by adding the following line to a top-level OBY file like this:

#define FBSRASTERIZER_DRV <fbsrasterizer_vendor.iby>

This is the preferred method. However, an alternative is to specify the IBY on the BUILDROM command line like this:

BUILDROM ... –DFBSRASTERIZER_DRV="^<"fbsrasterizer_vendor.iby"^>" ... 

Notice that the ^ character is used as an escape character for the < and > characters.

See Selection of Adaptations for more information.

The emulator

By default, an extended bitmap rasterizer DLL is not included on the emulator (WINSCW). To include your extended bitmap rasterizer DLL for testing on the emulator add the following line to your epoc.ini file:

FBSRASTERIZER_DLL <your_rasterizer_dll_name>