Диспетчер устройств Direct3D

Диспетчер устройств Microsoft Direct3D позволяет двум или более объектам совместно использовать одно и то же устройство Microsoft Direct3D 9. Один объект выступает в качестве владельца устройства Direct3D 9. Чтобы предоставить общий доступ к устройству, владелец устройства создает диспетчер устройств Direct3D. Другие объекты могут получить указатель на диспетчер устройств от владельца устройства, а затем использовать диспетчер устройств, чтобы получить указатель на устройство Direct3D. Любой объект, использующий устройство, удерживает монопольную блокировку, которая не позволяет другим объектам одновременно использовать устройство.

Примечание

Диспетчер устройств Direct3D поддерживает только устройства Direct3D 9. Он не поддерживает устройства DXGI.

 

Чтобы создать диспетчер устройств Direct3D, вызовите DXVA2CreateDirect3DDeviceManager9. Эта функция возвращает указатель на интерфейс IDirect3DeviceManager9 диспетчера устройств вместе с маркером сброса. Маркер сброса позволяет владельцу устройства 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;
}

Владелец устройства должен предоставить другим объектам способ получения указателя на интерфейс IDirect3DDeviceManager9 . Стандартный механизм заключается в реализации интерфейса IMFGetService . Guid службы MR_VIDEO_ACCELERATION_SERVICE.

Чтобы предоставить общий доступ к устройству нескольким объектам, каждый объект (включая владельца устройства) должен получить доступ к устройству через диспетчер устройств следующим образом:

  1. Вызовите IDirect3DDeviceManager9::OpenDeviceHandle , чтобы получить дескриптор устройства.
  2. Чтобы использовать устройство, вызовите IDirect3DDeviceManager9::LockDevice и передайте дескриптор устройства. Метод возвращает указатель на интерфейс IDirect3DDevice9 . Метод может вызываться в режиме блокировки или неблокировке в зависимости от значения параметра fBlock .
  3. Завершив работу с устройством, вызовите IDirect3DeviceManager9::UnlockDevice. Этот метод делает устройство доступным для других объектов.
  4. Перед выходом вызовите 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;
}

DirectX Video Acceleration 2.0