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;
}
相关主题