Post

Porting Direct3D to Direct3D Mobile

Recently I had a project to port programs originally written with Direct3D 8 and Direct3D 9 to Windows CE-based embedded devices. The DirectX version used on embedded devices is completely different from desktop, called Direct3D Mobile (D3DM for short). As the name suggests, it’s one of the features ported from Windows Mobile to Windows CE. Actually, before D3DM, I recall that back in the Windows CE .NET 4.2 era, Microsoft once had desktop DX support on CE, with identical API names. They probably realized that wasn’t a good idea and started fresh.

Microsoft claims Direct3D Mobile was completely rewritten for embedded devices. Its interfaces differ from any desktop Direct3D version. But really, how could they reinvent the wheel? The interfaces are somewhat similar to desktop DirectX. Basically, D3DM sits somewhere between DX8 and DX9. Let me summarize the differences:

Features in Direct3D Mobile but NOT in desktop D3D:

  • Support for 16.16 fixed point data: vertex position, normal, texture coords, material colors, and matrices. All D3DM drivers must support both float and fixed point data, and reveal which of the two data types they prefer.
  • Device Profiles, which should make it easier for ISVs to target a particular category of devices rather than having to write a lot of complex caps checking code.



Features in Direct3D8 but NOT in D3DM:

  • Programmable vertex/pixel shaders
  • Cube maps
  • Multiple swap chains
  • Volume textures
  • Spotlights
  • Emissive lighting
  • User clip planes
  • Geometry blending
  • Scissoring
  • Render state blocks
  • Higher-Order primitives
  • DrawPrimitiveUP
  • Point sprites
  • D3D cursors
  • Pure devices
  • HEL TnL fallback
  • D3DM supports a max of 4 texture stages



Features in both Direct3D9 and D3DM:

  • StretchRect
  • ColorFill
  • Depth slope/scale bias

From a code perspective, the porting was mind-numbing. Let me summarize the key points:

  1. Data structure and interface names. To emphasize the difference, Direct3D Mobile renamed desktop interfaces, structs, and enums:
  • IDirect3DDevice8 -> IDirect3DMobileDevice
  • D3DFORMAT -> D3DMFORMAT
  • D3DCOLOR_ARGB -> D3DMCOLOR_ARGB
  • D3DMATRIX -> D3DMMATRIX
  • D3DBLEND_SRCCOLOR -> D3DMBLEND_SRCCOLOR (the worst one…)

Step one: rename all these damned things. It will drive you crazy. If you survive, read on:

  1. Data types. Embedded devices don’t have powerful desktop CPUs. Floating point isn’t always available. Many poor embedded devices simulate floating point in software, which is painfully slow. Even worse, some have no floating point support at all — writing “float x = 3.2 / 2.1;” in C causes inexplicable errors. D3DM supports both floating-point and integer data structures to accommodate the masses.

At first I was puzzled. All D3DM data structures are of type D3DMVALUE, defined in the header as:

typedef signed int D3DMVALUE;

I thought D3DM only supported fixed-point. But actually, although this macro is defined as integer, you can use it as float through an inline conversion function:

inline D3DMVALUE D3DM_MAKE_D3DMVALUE(float Value) { ` typedef int float_and_D3DMVALUE_arent_of_the_same_size[sizeof(D3DMVALUE) == sizeof(float)]; return *reinterpret_cast<D3DMVALUE *>(&Value); }`

This function also provides double, char versions, etc. If D3DMVALUE isn’t the same size as int, the zero-size array typedef triggers a compile error. If it matches, the cast goes through C++’s most powerful conversion — reinterpret_cast.

For code: if you want fixed point, change all floats in your original code (tedious!). If you’re lazy or have an FPU, you still can’t compile directly. Every assignment to D3DMVALUE needs a D3DM_MAKE_D3DMVALUE wrapper. Otherwise, the compiler gives a warning but runtime will error, because the compiler will truncate the float to int.

  1. To be continued.
This post is licensed under CC BY 4.0 by the author.