Direct3D デバイス マネージャー
Microsoft Direct3D デバイス マネージャーを使用すると、2 つ以上のオブジェクトで同じ Microsoft Direct3D 9 デバイスを共有できます。 1 つのオブジェクトが Direct3D 9 デバイスの所有者として機能します。 デバイスを共有するために、デバイスの所有者が Direct3D デバイス マネージャーを作成します。 他のオブジェクトは、デバイス所有者からデバイス マネージャーへのポインターを取得し、デバイス マネージャーを使用して Direct3D デバイスへのポインターを取得できます。 デバイスを使用するオブジェクトは排他ロックを保持するため、他のオブジェクトが同時にデバイスを使用できなくなります。
注意
Direct3D デバイス マネージャーでは、Direct3D 9 デバイスのみがサポートされます。 DXGI デバイスはサポートされていません。
Direct3D デバイス マネージャーを作成するには、 DXVA2CreateDirect3DDeviceManager9 を呼び出します。 この関数は、デバイス マネージャーの IDirect3DDeviceManager9 インターフェイスへのポインターとリセット トークンを返します。 リセット トークンを使用すると、Direct3D デバイスの所有者はデバイス マネージャーでデバイスを設定 (およびリセット) できます。 デバイス マネージャーを初期化するには、 IDirect3DDeviceManager9::ResetDevice を呼び出します。 リセット トークンと共に、Direct3D デバイスへのポインターを渡します。
次のコードは、デバイス マネージャーを作成して初期化する方法を示しています。
HRESULT CreateD3DDeviceManager(
IDirect3DDevice9 *pDevice,
UINT *pReset,
IDirect3DDeviceManager9 **ppManager
)
{
UINT resetToken = 0;
IDirect3DDeviceManager9 *pD3DManager = NULL;
HRESULT hr = DXVA2CreateDirect3DDeviceManager9(&resetToken, &pD3DManager);
if (FAILED(hr))
{
goto done;
}
hr = pD3DManager->ResetDevice(pDevice, resetToken);
if (FAILED(hr))
{
goto done;
}
*ppManager = pD3DManager;
(*ppManager)->AddRef();
*pReset = resetToken;
done:
SafeRelease(&pD3DManager);
return hr;
}
デバイス所有者は、他のオブジェクトが IDirect3DDeviceManager9 インターフェイスへのポインターを取得する方法を提供する必要があります。 標準的なメカニズムは、 IMFGetService インターフェイスを実装することです。 サービス GUID がMR_VIDEO_ACCELERATION_SERVICE。
複数のオブジェクト間でデバイスを共有するには、次のように、各オブジェクト (デバイスの所有者を含む) がデバイス マネージャーを介してデバイスにアクセスする必要があります。
- IDirect3DDeviceManager9::OpenDeviceHandle を呼び出して、デバイスへのハンドルを取得します。
- デバイスを使用するには、 IDirect3DDeviceManager9::LockDevice を呼び出し、デバイス ハンドルを渡します。 メソッドは、 IDirect3DDevice9 インターフェイスへのポインターを返します。 メソッドは、 fBlock パラメーターの値に応じて、ブロッキング モードまたは非ブロッキング モードで呼び出すことができます。
- デバイスの使用が完了したら、 IDirect3DDeviceManager9::UnlockDevice を呼び出します。 このメソッドを使用すると、デバイスを他のオブジェクトで使用できるようになります。
- 終了する前に、 IDirect3DDeviceManager9::CloseDeviceHandle を呼び出してデバイス ハンドルを閉じます。
デバイス ロックを保持すると、他のオブジェクトがデバイスを使用できなくなるため、デバイスの使用中にのみデバイス ロックを保持する必要があります。
デバイスの所有者は、 ResetDevice を呼び出すことによって、いつでも別のデバイスに切り替えることができます。通常は、元のデバイスが失われたためです。 デバイスの損失は、モニターの解像度の変更、電源管理アクション、コンピューターのロックとロック解除など、さまざまな理由で発生する可能性があります。 詳細については、Direct3D のドキュメントを参照してください。
ResetDevice メソッドは、以前に開いたデバイス ハンドルを無効にします。 デバイス ハンドルが無効な場合、 LockDevice メソッドは DXVA2_E_NEW_VIDEO_DEVICEを返します。 この場合は、次のコードに示すように、ハンドルを閉じて OpenDeviceHandle をもう一度呼び出して、新しいデバイス ハンドルを取得します。
次の例は、デバイス ハンドルを開いてデバイスをロックする方法を示しています。
HRESULT LockDevice(
IDirect3DDeviceManager9 *pDeviceManager,
BOOL fBlock,
IDirect3DDevice9 **ppDevice, // Receives a pointer to the device.
HANDLE *pHandle // Receives a device handle.
)
{
*pHandle = NULL;
*ppDevice = NULL;
HANDLE hDevice = 0;
HRESULT hr = pDeviceManager->OpenDeviceHandle(&hDevice);
if (SUCCEEDED(hr))
{
hr = pDeviceManager->LockDevice(hDevice, ppDevice, fBlock);
}
if (hr == DXVA2_E_NEW_VIDEO_DEVICE)
{
// Invalid device handle. Try to open a new device handle.
hr = pDeviceManager->CloseDeviceHandle(hDevice);
if (SUCCEEDED(hr))
{
hr = pDeviceManager->OpenDeviceHandle(&hDevice);
}
// Try to lock the device again.
if (SUCCEEDED(hr))
{
hr = pDeviceManager->LockDevice(hDevice, ppDevice, TRUE);
}
}
if (SUCCEEDED(hr))
{
*pHandle = hDevice;
}
return hr;
}
関連トピック