Windows Mobile 6.5 Raw Display Buffer APIs

Rendering high-performance graphics, games, and video playback on Windows Mobile 6.5 required developers to bypass standard Graphics Device Interface (GDI) rendering pipelines to minimize latency and overhead. In native C++, developers relied on a handful of specialized interfaces to gain direct, raw access to display buffers: DirectDraw, the driver-level GETRAWFRAMEBUFFER escape code, and legacy Game API (GAPI) implementations. This article examines these low-level APIs, detailing how they provided direct linear frame buffer pointers and how they functioned within the Windows CE 5.2 architecture underlying Windows Mobile 6.5.

DirectDraw (DirectX for Windows CE)

DirectDraw was the official, Microsoft-recommended native C++ API for hardware-accelerated 2D graphics and direct video memory manipulation on Windows Mobile 6.5. It was exposed via COM-style interfaces declared in ddraw.h.

To access the raw display memory using DirectDraw:

  1. Initialize the DirectDraw object via DirectDrawCreate().
  2. Set the cooperative level to full-screen or normal using IDirectDraw::SetCooperativeLevel().
  3. Create a primary surface representing the physical display via IDirectDraw::CreateSurface().
  4. Call IDirectDrawSurface::Lock() to obtain a direct pointer to the video memory buffer.
  5. The resulting DDSURFACEDESC structure returned the lpSurface member (a linear pointer to raw pixel data) along with the pitch/stride of the display line.
  6. Once drawing finished, calling IDirectDrawSurface::Unlock() released the hardware lock, allowing the screen to update.

DirectDraw took advantage of hardware acceleration if supported by the original equipment manufacturer (OEM) display driver, while still offering a software emulation fallback.

GDI ExtEscape: GETRAWFRAMEBUFFER

Because DirectDraw support varied across OEM devices, high-performance multimedia applications (such as media players and console emulators) frequently utilized a native driver backdoor through the GDI ExtEscape function.

Developers queried the display driver using the GETRAWFRAMEBUFFER control code:

#define GETRAWFRAMEBUFFER 0x00020001

struct RawFrameBufferInfo {
    WORD wFormat;
    WORD wBPP;
    VOID *pFrameBuffer;
    LONG lStride;
    LONG lCx;
    LONG lCy;
};

HDC hdc = GetDC(NULL);
RawFrameBufferInfo rfbi = { 0 };

if (ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(rfbi), (LPSTR)&rfbi) > 0) {
    void* pBuffer = rfbi.pFrameBuffer; // Direct linear pointer to screen memory
    long stride = rfbi.lStride;
}
ReleaseDC(NULL, hdc);

If the underlying display driver supported this call, it returned the physical base address or a mapped virtual pointer (pFrameBuffer), the bits per pixel (wBPP), and the scanline stride (lStride). This bypassed the entire window manager and compositor, allowing uninterrupted, blisteringly fast writes directly to hardware memory.

Game API (GAPI)

The Windows Mobile Game API (gx.h, linked with gx.lib) was Microsoft’s original raw access API introduced in early Pocket PC systems.

GAPI provided a simple procedural C-style interface:

  • GXOpenDisplay(): Initialized the display for exclusive graphics mode.
  • GXGetDisplayProperties(): Populated a GXDisplayProperties struct containing the linear display pointer (cbxPitch, cbyPitch, and screen dimensions).
  • GXBeginDraw(): Locked the display buffer and returned the write pointer.
  • GXEndDraw(): Released the display buffer to trigger the screen refresh.
  • GXCloseDisplay(): Cleaned up the session.

By the release of Windows Mobile 6.5, GAPI was officially deprecated. Most devices implemented GAPI as an emulation wrapper over DirectDraw or GDI, which often degraded performance. However, legacy native C++ applications continued to use GAPI by deploying custom wrapper libraries (such as GXOpen or PocketHAL) that redirected GAPI calls into raw ExtEscape or DirectDraw implementations.

Software Framebuffers: CreateDIBSection

When hardware display buffers were locked down or driver access was restricted by OEM security policies, the standard fallback was allocating an off-screen software frame buffer using CreateDIBSection.

While this did not write directly to the screen's physical memory:

  • CreateDIBSection() provided a raw pointer (void** ppvBits) to an in-memory pixel array.
  • The application wrote raw pixel data into this memory array via native C++ pointers.
  • The updated buffer was blitted to the display device context using BitBlt() or StretchBlt().

Although not a true hardware frame buffer mechanism, it remained the standard fail-safe approach for native graphics code requiring deterministic memory layouts across every Windows Mobile 6.5 device.