Introduction to Graphics Drivers

This chapter includes:

Graphics drivers

In Neutrino, graphics drivers are independent of the graphics system. The driver that you supply is implemented as a shared object that can be used by Photon (io-graphics) or by applications using the Neutrino Graphics Framework (via io-display).

Note: Photon and GF applications can coexist on a target, if there are hardware layers for each to run. They can't share a single layer.

You provide a set of well defined entry points, and the appropriate graphics system dynamically loads your driver and calls the entry points.

GF-Based graphics system

Under GF, different entry points can be called from different places, and some knowledge of where and when the various entry points may be called is necessary in order to determine how your driver should be structured.

All access to graphical functionality is provided to the application by the GF client library. The GF client library may, in turn, initiate a call into the graphics driver. This could happen in one of two ways:

  1. A direct call into the graphics driver, within the application's address space
  2. A message pass to io-display, which in turn could initiate calls into the graphics driver within io-display's address space.

Graphics driver called by application and io-display

A GF-based application

Since a driver may be called from within different address spaces, your driver will need to keep track of shared data (which is stored in memory visible to all address spaces) as well as state data which is only accessible within a single address space.

The driver is provided with a shared memory area, in which it can store “global” driver state data. The driver should include a global symbol, of type int, named devg_shmem_size, which indicates how much memory needs to be allocated by the Framework to store the shared data.

Caution: The driver should be very careful about storing pointers in this shared memory, since a pointer does not have any meaning outside of the address space in which it was created.

Additionally, a driver may allocate per-address-space state data, which can be used to keep track of per-client rendering state.

Later, we will specify which entry points may be called from within the address space of io-display, and which ones may be called directly from within the address space of the client (see Address spaces and calling rules).

For more information about the architecture of the QNX Graphics Framework, see the Advanced Graphics Developer's Guide.

Photon-based graphics system

By way of example, this is how your driver interacts with Photon and the graphics driver subsystem, io-graphics, under QNX Neutrino:

Driver interaction with Photon.

How a driver interacts with Photon.

As you can see from the above diagram, a set of Photon infrastructure components are responsible for the interface to Photon:

Presents the graphical region to Photon. This is the area that's defined to be shown on the graphical screen.
Draw stream interpreter
Interprets Photon's draw stream and decodes the graphical commands into scans, bitmaps, images, and fills, and passes them to the graphics driver. The interpreter also converts the draw stream from whatever endian format it's in to native-endian format.
Render library
Converts complex shapes (such as circles) into lower-level drawing primitives (scans, bitmaps, images, and fills) that the graphics driver can handle.
Font manager
Converts textual information into bitmaps.
Rasterizer (FFB)
Converts lower-level drawing primitives into a raster format, using the Flat Frame Buffer (FFB) library.
Graphics driver
Your graphics driver, supplied as one or more shared objects.