Documentation
[SDK Documentation] [The GAPI in GapiDraw]

 

The GAPI in GapiDraw

This document has been updated for use with GapiDraw 3.0 or later.
Last updated on Wednesday, January 14, 2004.

 

Introduction

This document highlights the mappings in GapiDraw to the library gx.dll for display and key access. It is useful for hardware manufacturers that want to provide maximum graphics performance and high application compatibility for their devices.

The first Windows CE device with a color display was released by Casio in early 2000. The "Palm-Sized PC" Cassiopeia E-105 was running Windows CE 2.11 and had a 16-bit color TFT display. Developers immediately wanted to explore this new device for gaming, but since the operating system Windows CE 2.11 did not provide sufficient support for drawing graphics to the display they had to work around the Windows CE system to draw the graphics themselves. One of the first arcade-action games running on Windows CE devices was the game Jimmy Ark (by Jimmy Software), which drew its graphics directly to the frame buffer of the device, bypassing the operating system. Later that year (in July), Microsoft released the runtime module "gx.dll" for Pocket PCs, which was meant to be used to retrieve the address of the frame buffer and lock the keys of the device. The gx.dll library is commonly referred to as "Microsoft GAPI".

GapiDraw uses the frame buffer pointer returned by the gx.dll to draw its graphics. GapiDraw also uses the key lock functionality of "gx.dll" to lock all keys upon request. The following sections outline how this connection is implemented so that hardware manufacturers can use it to improve graphics performance on their devices.

 

Dynamic linkage

GapiDraw will link to the DLL "gx.dll" dynamically, using LoadLibrary(TEXT("gx.dll")). If the DLL was found (it should reside in the application folder or the "Windows" folder), its functions will be mapped using either GetProcAddress (if GapiDraw runs on a stationary PC), or reinterpret_cast (if GapiDraw runs on a Pocket PC).

 

Unsupported devices

Today there are some devices that return incorrect values in their GAPI calls (such as the IPAQ 38xx series and some of the Palmax @migo devices). On such devices GapiDraw will not use gx.dll but instead access the display frame buffer directly, using a surface created in system memory as a backbuffer.

 

Display pitch values

GapiDraw supports all pitch values with unaffected performance. Some examples are:

  • Cassiopeia E-115 (xPitch = 2, yPitch = 512)
  • Toshiba e740 (xPitch = 2, yPitch = 480)
  • HP IPAQ 36xx series (xPitch = 640, yPitch = -2)
  • HP IPAQ 38xx series (xPitch = -640, yPitch = 2)

GapiDraw will always (a) flip xPitch and yPitch so that xPitch is always the smallest value, and (b) invert xPitch so that it always is +1. Hardware manufacturers are encouraged to expose the display in its native rotation, and not try to rotate the backbuffer as it is being copied to the display if double buffered access is used.

 

CGapiDisplay mappings

CGapiDisplay::OpenDisplay
  1. Load gx.dll using dynamic linkage if it has not been previously initialized. If gx.dll could not be initialized the function returns GDERR_NOGAPI.
  2. Call GXOpenDisplay(hWnd, GX_FULLSCREEN) in gx.dll. The hWnd pointer is checked so that it represents a valid window. If the display could not be opened, the function returns GDERR_UNSUPPORTEDMODE.
  3. Call GXGetDisplayProperties() in gx.dll. If the display property gxDP.cBPP is not 16, GXCloseDisplay() is called and the function returns GDERR_UNSUPPORTEDMODE.
  4. Check the value of GXIsDisplayDRAMBuffer(). If TRUE, GapiDraw will call GXBeginDraw() and store the frame buffer address in the backbuffer and disable direct display access using the CGapiDisplay object. If FALSE, GapiDraw will call GXBeginDraw() and store the frame buffer address in the CGapiDisplay object (enabling direct display access), and create a new surface in system memory for the backbuffer.
CGapiDisplay::CloseDisplay
  1. Call GXCloseDisplay() in gx.dll.

CGapiDisplay::Flip
  1. Call GXEndDraw() in gx.dll.
  2. If GXIsDisplayDRAMBuffer() returned TRUE in CGapiDisplay::OpenDisplay, GapiDraw will call GXBeginDraw() and store the new frame buffer address returned from GXBeginDraw() in the backbuffer. If GXIsDisplayDRAMBuffer() returned FALSE, GapiDraw will call GXBeginDraw() and store the new frame buffer address returned from GXBeginDraw() in the CGapiDisplay object.

Please note that GapiDraw supports relocation of the frame buffer address returned by GXBeginDraw().

CGapiDisplay::SuspendDisplay
  1. Call GXSuspend() in gx.dll.
CGapiDisplay::ResumeDisplay
  1. Call GXResume() in gx.dll.

 

CGapiInput mappings

CGapiInput::OpenInput
  1. Load gx.dll using dynamic linkage if it has not been previously initialized. If gx.dll could not be initialized the function returns GDERR_NOGAPI.
  2. Call GXOpenInput() in gx.dll.
  3. Call GXGetDefaultKeys(GX_NORMALKEYS) in gx.dll. The keys are later mapped to the correct display alignment by GapiDraw.

CGapiInput::CloseInput

  1. Call GXCloseInput() in gx.dll.

 

Hardware design guides

The following are a quick list of features to consider when designing a gx.dll interface:

  • GapiDraw calls GXEndDraw() and GXBeginDraw() on each frame. Do not assume that applications only call GXBeginDraw() once on application startup and later call GXEndDraw() on application exit.
  • Make sure that GXIsDisplayDRAMBuffer() returns a correct value. Today there are some devices that return TRUE (double buffered display) that in fact are not double buffered, causing the display updates to flicker (since GapiDraw will then use the display as a backbuffer).