Direct3D 设备管理器
Microsoft Direct3D 设备管理器允许两个或多个对象共享同一个 Microsoft Direct3D 9 设备。 一个对象充当 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;
}
相关主题