DirectDrawウィンドウモードでのティアリング回避 (1)
DWMの無いXPでも垂直同期を待てばティアリングを防ぐことは出来ます。
ただしウィンドウモードで垂直同期を待てるようになったのはつい最近で、DirectX9.0になってからです。
あたりから始まって色々コメントを書いた成り行き上,ちょいとばかり昔の資料を漁って書いてみます.と言っても私もそんなに詳しくないので,嘘を書いちゃった場合はひげねこさんの突っ込みに期待.
まずは基礎編から.
DirectDraw ウィンドウモードでのティアリング回避アルゴリズム
実際のところ DirectDraw ウィンドウモードでのティアリング回避アルゴリズムは,DirectDraw 初期から変わっていないはずです.
アルゴリズムのコンセプトは単純で,デスクトップへの BilBlt が走査線通過中に行われないようにタイミング調整を行うというもの.走査線のタイミングに合わせるのは DirectDraw 初期の頃から存在する GetScanLine / WaitForVerticalBlank が使えます.即時的な BitBlt には,いわゆる NOWAIT 系のフラグが利用できて,ドライバ内でブロックされてタイミングが狂う可能性を減らすことができます.
ドライバモデルについて
Windows 2000,Windows XP,Windows Server 2003 は同じドライバモデルを利用しています.このドライバモデルは,DirectDraw のファンクションを基本とし,建て増し的にコマンドバッファ方式の DrawPrimitive 機能を追加した構造をしています.
さて,Windows 2000 から Windows XP,Windows Server 2003 までの間に DirectX 6 から DirectX 9までがリリースされましたが,実はこの間にドライバモデルは変わっていません.一般には DirectX 8 で DirectDraw と Direct3D が統合されたと思われていますが,あれは単に API 層でラップしただけです.実際には Direct3D のランタイムライブラリがラッパー化していき,内部でせっせと DirectDraw 相当のドライバファンクションを使い分けるようになっただけでした.
例として,先ほど登場した GetScanLine を見てみましょう.Windows 2000 のドライバモデルで,ドライバは以下のファンクションを提供します.
Windows 2000 から Windows Server 2003 までの間で,この仕組みは基本的に変わりません.一方でアプリケーションからは,走査線位置の取得方法が複数あるように見えます.
- IDirectDraw::GetScanLine
- IDirectDraw2::GetScanLine
- IDirectDraw4::GetScanLine
- IDirectDraw7::GetScanLine
- IDirect3DDevice8::GetRasterStatus
- IDirect3DDevice9::GetRasterStatus
- IDirect3DSwapChain9::GetRasterStatus
- NtGdiDdGetScanLine
しかしこれらの API,同一のドライバファンクションの異なるラッパーに過ぎません.
(続く)