Диспетчер устройств Direct3D
Диспетчер устройств Microsoft Direct3D позволяет двум или нескольким объектам совместно использовать одно и то же устройство Microsoft Direct3D 9. Один объект выступает в качестве владельца устройства Direct3D 9. Чтобы предоставить общий доступ к устройству, владелец устройства создает диспетчер устройств Direct3D. Другие объекты могут получить указатель на диспетчер устройств от владельца устройства, а затем использовать диспетчер устройств для получения указателя на устройство Direct3D. Любой объект, использующий устройство, содержит монопольную блокировку, которая не позволяет другим объектам одновременно использовать устройство.
Заметка
Диспетчер устройств Direct3D поддерживает только устройства Direct3D 9. Он не поддерживает устройства DXGI.
Чтобы создать диспетчер устройств Direct3D, вызовите DXVA2CreateDirect3DeviceManager9. Эта функция возвращает указатель на интерфейс IDirect3DDeviceManager 9 диспетчера устройств, а также маркер сброса. Маркер сброса позволяет владельцу устройства Direct3D задать (и сбросить) устройство в диспетчере устройств. Чтобы инициализировать диспетчер устройств, вызовите IDirect3DeviceManager9::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;
}
Владелец устройства должен предоставить способ получения указателя на интерфейс IDirect3DeviceManager9. Стандартный механизм — реализовать интерфейс IMFGetService. GUID службы MR_VIDEO_ACCELERATION_SERVICE.
Чтобы предоставить общий доступ к устройству между несколькими объектами, каждый объект (включая владельца устройства) должен получить доступ к устройству через диспетчер устройств, как показано ниже.
- Вызовите IDirect3DeviceManager9::OpenDeviceHandle, чтобы получить дескриптор устройства.
- Чтобы использовать устройство, вызовите IDirect3DeviceManager9::LockDevice и передайте дескриптор устройства. Метод возвращает указатель на интерфейс IDirect3Device9. Метод можно вызывать в режиме блокировки или в режиме без блокировки в зависимости от значения параметра fBlock.
- По завершении работы с устройством вызовите IDirect3DeviceManager9::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;
}
Связанные разделы