GDI アクセラレーションについて整理する

WDK 公開から約1ヶ月遅れになってしまったが,公開されたドキュメントから,Windows 7 で復活する GDI アクセラレーションがどんなものか,かなりのところまで推測することができる.ドキュメントはすでにオンラインで誰でも読むことが可能になっている.

筆者も軽く目を通してみたが,WDDM 1.1 で新設される GDI アクセラレーションは,XPDM までで行われていた GDI アクセラレーションとだいぶ内容が異なりそうだ.その意味では,これを GDI アクセラレーションの「復活」と呼ぶのは語弊があるかもしれない.
何より印象的だったのが,GDI アクセラレーションと称してドライバが受け取るコマンドが以下の 7 種類 (うち,将来の拡張用のエスケープコマンドが 1 種類) しか存在しなかったことだ.これは XPDM 時代の GDI ドライバファンクションの数に比べて圧倒的に少ない.

The DXGK_RENDERKM_OPERATION enumeration indicates the type of GDI hardware-accelerated rendering operation to perform when the DxgkDdiRenderKm function is called.

typedef enum _DXGK_RENDERKM_OPERATION {
  DXGK_GDIOP_BITBLT         = 1,
  DXGK_GDIOP_COLORFILL      = 2,
  DXGK_GDIOP_ALPHABLEND     = 3,
  DXGK_GDIOP_STRETCHBLT     = 4,
  DXGK_GDIOP_ESCAPE         = 5,
  DXGK_GDIOP_TRANSPARENTBLT = 6,
  DXGK_GDIOP_CLEARTYPEBLEND = 7,
} DXGK_RENDERKM_OPERATION;

定義されている OpCode は,いわゆる BitBlt (矩形転送) 系に絞られている.線分や円の描画に関しては影も形もない.
それでは線分や円の描画をどうするかだが,筆者はサーフェスロックによるソフトウェア描画ではないかと予想している.例えばこちらの D3DKMDT_GDISURFACETYPE 列挙体 が興味深い.

The D3DKMDT_GDISURFACETYPE enumeration indicates the type of lockable surface that is used by the Desktop Windows Manager (DWM) for redirection.

typedef enum _D3DKMDT_GDISURFACETYPE {
  D3DKMDT_GDISURFACE_INVALID            = 0,
  D3DKMDT_GDISURFACE_TEXTURE            = 1,
  D3DKMDT_GDISURFACE_STAGING_CPUVISIBLE = 2,
  D3DKMDT_GDISURFACE_STAGING            = 3,
  D3DKMDT_GDISURFACE_LOOKUPTABLE        = 4,
  D3DKMDT_GDISURFACE_EXISTINGSYSMEM     = 5,
} D3DKMDT_GDISURFACETYPE;

考えてみれば,サーフェスロック方式の採用は合理的だ.
既報のように,Windows 7 DWM でのウィンドウイメージの保持は DXGI サーフェイスに一元化される.このサーフェスが,GDI 描画時に一時的にロックされ,CPU から直接読み書き可能なメモリ空間にマッピングされるとしよう.いったん通常のメモリ空間にマッピングされてしまえば,あとは従来のソフトウェア描画と同じである.実際,メインメモリ上に描画するソフトウェアレンダラは Windows Vista で実装済みだ.違いがあるとすれば,Vista DWM のころは必要だったソフトウェアでのピクセルフォーマット変換が,WDDM 1.1 では不要なことか.WDDM 1.1 は GDI 互換のピクセルフォーマットのサポートを義務付けたので,ピクセルフォーマット変換は最終合成段階にハードウェアで行えばよい.
以上が,WDK のドキュメントをざっと眺めてみての筆者の予想である.
自分でベンチマークを書いてテストできる人は,これらのことに注意して調査してみると何か収穫があるのではなかろうか.矩形処理以外の GDI 描画処理のスループットを計測してみて,もしそこに塗りつぶし面積に比例するような傾向が見られれば興味深い.それはソフトウェアレンダリングで説明が可能な振る舞いだ.

Windows7 の GDI 系ネイティブ API

実装詳細を占うという意味では,Windows SDK for Windows 7 and .NET Framework 3.5 SP1: BETA に付属する ntgdi.h も興味深い.前回リリースされた Windows SDK *1 に含まれる ntgdi.h との差分をとったところ,以下の API の追加が確認できた.

  • NtGdiGetFontFileData
  • NtGdiGetFontFileInfo
  • NtGdiCreateBitmapFromDxSurface
  • NtGdiBeginGdiRendering
  • NtGdiEndGdiRendering
  • NtGdiSfmGetNotificationTokens
  • NtGdiSfmRegisterLogicalSurfaceForSignaling
  • NtGdiDwmGetHighColorMode
  • NtGdiDwmSetHighColorMode
  • NtGdiDwmCaptureScreen
  • NtGdiDdCreateFullscreenSprite
  • NtGdiDdNotifyFullscreenSpriteUpdate
  • NtGdiDdDestroyFullscreenSprite
  • NtGdiDdQueryVisRgnUniqueness
  • NtGdiHLSurfGetInformation
  • NtGdiHLSurfSetInformation

これらの API はいわゆるNT ネイティブ API に相当し,通常のアプリケーションからの使用が意図されたものではない.が,先ほどの WDK のドキュメントと併せて,Windows 7 のグラフィックスシステムの実装を考えるヒントになるだろう.
NtGdiCreateBitmapFromDxSurface などは,いかにも DWM が使いそうな響きである.

*1:Windows SDK for Windows Server 2008 and .NET Framework 3.5 (6001.18000.367)