IDXGIFactory
COM公式ドキュメント
IDXGIFactory インターフェースは、(全画面遷移を処理する)DXGI オブジェクトを生成するためのメソッドを実装します。
解説(Remarks)
CreateDXGIFactory を呼び出してファクトリを作成します。
スワップチェーンを作成しなくても Direct3D デバイスを作成できるため、スワップチェーンを作成するには、デバイスの作成に使用されるファクトリを取得する必要がある場合があります。Direct3D デバイスから IDXGIDevice インターフェースを要求し、続いて IDXGIObject::GetParent メソッドを使用してファクトリを見つけることができます。次のコードにその方法を示します。
IDXGIDevice * pDXGIDevice = nullptr;
hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
IDXGIAdapter * pDXGIAdapter = nullptr;
hr = pDXGIDevice->GetAdapter( &pDXGIAdapter );
IDXGIFactory * pIDXGIFactory = nullptr;
pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&pIDXGIFactory);
Windows Phone 8: この API はサポートされています。
メソッド 5
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
アダプター(ビデオカード)を列挙します。
| Adapter | DWORD | in | 列挙するアダプターのインデックス。 |
| ppAdapter | IDXGIAdapter** | out | Adapter パラメーターで指定された位置にある IDXGIAdapter インターフェースへのポインターのアドレス。このパラメーターに NULL を指定することはできません。 |
戻り値
Type: HRESULT
成功した場合は S_OK を返します。それ以外の場合、インデックスがローカルシステム内のアダプター数以上であれば DXGI_ERROR_NOT_FOUND を、ppAdapter パラメーターが NULL であれば DXGI_ERROR_INVALID_CALL を返します。
解説(Remarks)
ファクトリを作成すると、そのファクトリはシステムで利用可能なアダプターの集合を列挙します。そのため、システムのアダプターを変更した場合は、IDXGIFactory オブジェクトを破棄して再作成する必要があります。ディスプレイカードの追加や取り外し、あるいはノートパソコンのドッキングやドッキング解除を行うと、システム内のアダプター数は変化します。
EnumAdapters メソッドが成功し、ppAdapter パラメーターにアダプターインターフェースへのポインターのアドレスが格納されると、EnumAdapters はそのアダプターインターフェースの参照カウントをインクリメントします。アダプターインターフェースの使用を終えたら、ポインターを破棄する前に Release メソッドを呼び出して参照カウントをデクリメントしてください。
EnumAdapters は最初に、デスクトップのプライマリが表示される出力を持つアダプターを返します。このアダプターはインデックス 0 に対応します。次に EnumAdapters は出力を持つその他のアダプターを返します。最後に EnumAdapters は出力を持たないアダプターを返します。
例
アダプターの列挙
次のコード例は、EnumAdapters メソッドを使用してアダプターを列挙する方法を示しています。
UINT i = 0;
IDXGIAdapter * pAdapter;
std::vector <IDXGIAdapter*> vAdapters;
while(pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND)
{
vAdapters.push_back(pAdapter);
++i;
}
DXGI がアプリケーションのメッセージキューを監視して、alt-enter キーシーケンス(アプリケーションをウィンドウモードから全画面へ、またはその逆へ切り替えます)を検出できるようにします。
| WindowHandle | HWND | in | 監視対象となるウィンドウのハンドル。このパラメーターに NULL を指定できますが、それは Flags も 0 の場合に限ります。 |
| Flags | DXGI_MWA_FLAGS | in | 次の値の 1 つ以上。
|
戻り値
Type: HRESULT
WindowHandle が無効な場合は DXGI_ERROR_INVALID_CALL、または E_OUTOFMEMORY。
解説(Remarks)
アプリケーションが全画面モードに切り替わると、DXGI は現在のバックバッファーのサイズ以上で、かつサポートされている中で最小の解像度を全画面解像度として選択します。
アプリケーションは、ウィンドウモードから全画面への遷移をより効率的にするためにいくつかの変更を加えることができます。たとえば、WM_SIZE メッセージを受け取ったら、アプリケーションは未解放のスワップチェーンのバックバッファーをすべて解放し、IDXGISwapChain::ResizeBuffers を呼び出してから、スワップチェーンからバックバッファーを再取得する必要があります。これにより、スワップチェーンはバックバッファーのサイズを変更したり、全画面のフリッピング動作を有効にするためにバックバッファーを再作成したりする機会を得られます。アプリケーションがこの手順を実行しない場合でも、DXGI は全画面とウィンドウモードの遷移を行いますが、(バックバッファーが正しいサイズでない可能性があるため)ストレッチ処理の使用を強いられることがあり、効率が低下する場合があります。ストレッチが不要な場合でも、バックバッファーがフロントバッファーと直接交換できない可能性があるため、表示が最適にならないことがあります。したがって、WM_SIZE は全画面遷移中に必ず送信されるため、WM_SIZE 時に ResizeBuffers を呼び出すことが常に推奨されます。
ウィンドウモードの間、アプリケーションは必要に応じて、ウィンドウのクライアント領域のサイズを、快適にレンダリングできるサイズに制限できます。完全に柔軟なアプリケーションであればそのような制限は設けませんが、UI 要素やその他の設計上の理由によって、当然ながらこの柔軟性が実現できないこともあります。さらにアプリケーションが、ウィンドウのクライアント領域を、サポートされている全画面解像度に一致するものだけに制限したい場合は、WM_SIZING を処理し、IDXGIOutput::FindClosestMatchingMode と照合できます。一致するモードが見つかった場合は、サイズ変更を許可します。(IDXGIOutput は IDXGISwapChain::GetContainingOutput から取得できます。その後にデスクトップトポロジーの変更がなければ、これは alt-enter が処理されてそのスワップチェーンの全画面モードが開始されるときに選択される出力と同じになります。)
モード変更や Alt+Enter を自分で処理したいアプリケーションは、スワップチェーンの作成後に DXGI_MWA_NO_WINDOW_CHANGES フラグを指定して MakeWindowAssociation を呼び出す必要があります。WindowHandle 引数が非 NULL の場合、特定のターゲット HWND のすべてのスワップチェーンについて、アプリケーションのメッセージキューが DXGI ランタイムによって処理されないように指定します。スワップチェーンの作成後に DXGI_MWA_NO_WINDOW_CHANGES フラグを指定して MakeWindowAssociation を呼び出すことで、DXGI がアプリケーションによるウィンドウモード変更や Alt+Enter の処理に干渉しないことが保証されます。
MakeWindowAssociation メソッドは、ターゲットの HWND スワップチェーンに関連付けられているファクトリオブジェクトに対して呼び出す必要があります。それを保証するには、スワップチェーンに対して IDXGIObject::GetParent メソッドを呼び出してファクトリを見つけます。次にその方法のコード例を示します。
void MakeWindowAssociationWithLocatedFactory(
winrt::com_ptr<IDXGISwapChain> const& swapChain,
HWND hWnd,
UINT flags)
{
winrt::com_ptr<IDXGIFactory1> factory;
factory.capture(swapChain, &IDXGISwapChain::GetParent);
factory->MakeWindowAssociation(hWnd, flags);
}
Windows ストアアプリに関する注意事項
Windows ストアアプリが MakeWindowAssociation を呼び出すと、DXGI_ERROR_NOT_CURRENTLY_AVAILABLE で失敗します。Microsoft Win32 アプリケーションは、MakeWindowAssociation を使用して、Alt+Enter キーの組み合わせによる全画面遷移や、全画面時の print screen の動作を制御できます。Windows ストアアプリの場合、DXGI は全画面遷移を実行できないため、Windows ストアアプリには全画面遷移を制御する手段がありません。
全画面への遷移および全画面からの遷移をユーザーが制御するためのウィンドウを取得します。
| pWindowHandle | HWND* | out | ウィンドウハンドルへのポインター。 |
戻り値
Type: HRESULT
成功または失敗を示すコードを返します。S_OK は成功を示し、DXGI_ERROR_INVALID_CALL は pWindowHandle が NULL として渡されたことを示します。
解説(Remarks)
スワップチェーンを作成します。
| pDevice | IUnknown* | in | Direct3D 11 およびそれ以前のバージョンの Direct3D では、これはスワップチェーン用の Direct3D デバイスへのポインターです。Direct3D 12 では、これはダイレクトコマンドキュー(ID3D12CommandQueue を参照)へのポインターです。このパラメーターに NULL を指定することはできません。 |
| pDesc | DXGI_SWAP_CHAIN_DESC* | in | スワップチェーンの記述を表す DXGI_SWAP_CHAIN_DESC 構造体へのポインター。このパラメーターに NULL を指定することはできません。 |
| ppSwapChain | IDXGISwapChain** | out | CreateSwapChain が作成するスワップチェーンの IDXGISwapChain インターフェースへのポインターを受け取る変数へのポインター。 |
戻り値
Type: HRESULT
pDesc または ppSwapChain が NULL の場合は DXGI_ERROR_INVALID_CALL、全画面モードを要求したが利用できない場合は DXGI_STATUS_OCCLUDED、または E_OUTOFMEMORY。渡されたデバイスの種類によって定義される他のエラーコードが返されることもあります。
解説(Remarks)
バッファーの幅またはバッファーの高さが 0 の場合、サイズはスワップチェーンの記述にある出力ウィンドウのサイズから推測されます。
スワップチェーンの作成時にターゲットの出力を明示的に選択することはできないため、全画面のスワップチェーンを作成しないことをお勧めします。スワップチェーンのサイズと出力ウィンドウのサイズが一致しない場合、表示のパフォーマンスが低下することがあります。サイズを一致させるには、次の 2 つの方法があります。
- ウィンドウモードのスワップチェーンを作成し、その後 IDXGISwapChain::SetFullscreenState を使用して全画面に設定します。
- 作成直後にスワップチェーンへのポインターを保存し、WM_SIZE イベント中にそれを使用して出力ウィンドウのサイズを取得します。次に、ウィンドウモードから全画面への遷移中に、(IDXGISwapChain::ResizeBuffers を使用して)スワップチェーンのバッファーのサイズを変更します。
ランタイムが全画面で最初のフレームをレンダリングした後、IDXGISwapChain::Present の呼び出し中にランタイムが予期せず全画面を終了することがあります。この問題を回避するには、全画面のスワップチェーンを作成するために CreateSwapChain を呼び出した(DXGI_SWAP_CHAIN_DESC の Windowed メンバーを FALSE に設定した)直後に、次のコードを実行することをお勧めします。
// Detect if newly created full-screen swap chain isn't actually full screen.
IDXGIOutput* pTarget; BOOL bFullscreen;
if (SUCCEEDED(pSwapChain->GetFullscreenState(&bFullscreen, &pTarget)))
{
pTarget->Release();
}
else
bFullscreen = FALSE;
// If not full screen, enable full screen again.
if (!bFullscreen)
{
ShowWindow(hWnd, SW_MINIMIZE);
ShowWindow(hWnd, SW_RESTORE);
pSwapChain->SetFullscreenState(TRUE, NULL);
}
pDesc が指すスワップチェーンの記述には、DXGI_SWAP_EFFECT と DXGI_SWAP_CHAIN_FLAG の値を指定できます。これらの値により、Windows 8 より前の API を使用して、フリップモデルの表示やコンテンツ保護などの機能を利用できます。
ただし、ステレオ表示を使用したり、フリップモデルのサイズ変更動作を変更したりするには、アプリケーションは IDXGIFactory2::CreateSwapChainForHwnd メソッドを使用する必要があります。そうしない場合、バックバッファーの内容は表示ターゲットのサイズに合わせて暗黙的にスケーリングされます。つまり、スケーリングをオフにすることはできません。
Windows ストアアプリに関する注意事項
Windows ストアアプリが全画面を指定して CreateSwapChain を呼び出すと、CreateSwapChain は失敗します。Windows ストアアプリは、IDXGIFactory2::CreateSwapChainForCoreWindow メソッドを呼び出してスワップチェーンを作成します。
スワップチェーンのバックバッファーの形式を選択する方法については、色空間のためのデータ変換を参照してください。
ソフトウェアアダプターを表すアダプターインターフェースを作成します。
| Module | HMODULE | in | ソフトウェアアダプターの dll へのハンドル。HMODULE は GetModuleHandle または LoadLibrary で取得できます。 |
| ppAdapter | IDXGIAdapter** | out | アダプター(IDXGIAdapter を参照)へのポインターのアドレス。 |
戻り値
解説(Remarks)
ソフトウェアアダプターは、デバイスドライバーインターフェース全体に加え、必要に応じて Windows のカーネルモードグラフィックスコンポーネントのエミュレーションを実装する DLL です。ソフトウェアアダプターの実装の詳細は、Windows Vista Driver Development Kit に記載されています。これは非常に複雑な開発作業であり、一般の読者にはお勧めしません。
このメソッドを呼び出すと、モジュールの参照カウントが 1 つインクリメントされます。参照カウントは、FreeLibrary を呼び出すことでデクリメントできます。
一般的な呼び出しの流れは、LoadLibrary を呼び出し、そのハンドルを CreateSoftwareAdapter に渡し、その後すぐに DLL に対して FreeLibrary を呼び出して、DLL の HMODULE を忘れる、というものです。ソフトウェアアダプターは破棄されるときに FreeLibrary を呼び出すため、DLL のライフタイムはアダプターが所有することになり、アプリケーションはそのライフタイムについてこれ以上考慮する必要がなくなります。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IDXGIFactory "{7B7166EC-21C7-44AE-B21A-C9AE321AE369}" #usecom global IDXGIFactory IID_IDXGIFactory "{}" #comfunc global IDXGIFactory_EnumAdapters 7 int,sptr #comfunc global IDXGIFactory_MakeWindowAssociation 8 sptr,int #comfunc global IDXGIFactory_GetWindowAssociation 9 sptr #comfunc global IDXGIFactory_CreateSwapChain 10 sptr,var,sptr #comfunc global IDXGIFactory_CreateSoftwareAdapter 11 sptr,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_IDXGIFactory "{7B7166EC-21C7-44AE-B21A-C9AE321AE369}" #usecom global IDXGIFactory IID_IDXGIFactory "{}" #comfunc global IDXGIFactory_EnumAdapters 7 int,sptr #comfunc global IDXGIFactory_MakeWindowAssociation 8 sptr,int #comfunc global IDXGIFactory_GetWindowAssociation 9 sptr #comfunc global IDXGIFactory_CreateSwapChain 10 sptr,sptr,sptr #comfunc global IDXGIFactory_CreateSoftwareAdapter 11 sptr,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。