Поддержка наложения оборудования

Аппаратное наложение — это выделенная область видеопамяти, которую можно наложить на основную поверхность. Копирование при отображении наложения не выполняется. Операция наложения выполняется на оборудовании без изменения данных на основной поверхности.

Использование аппаратных наложений для воспроизведения видео было распространено в более ранних версиях Windows, так как наложения эффективны для видеосодержимого с высокой частотой кадров. Начиная с Windows 7 Direct3D 9 поддерживает аппаратные наложения. Эта поддержка предназначена в основном для воспроизведения видео и в некоторых отношениях отличается от более ранних API DirectDraw:

  • Наложение не может быть сжато, зеркально или деинтерлейировано.
  • Исходные цветовые ключи и альфа-смешивание не поддерживаются.
  • Наложения могут быть растянуты, если это поддерживается оборудованием наложения. В противном случае растяжение не поддерживается. На практике не все графические драйверы поддерживают растяжение.
  • Каждое устройство поддерживает не более одного наложения.
  • Наложение выполняется с помощью ключа цвета назначения, но среда выполнения Direct3D автоматически выбирает цвет и рисует прямоугольник назначения. Direct3D автоматически отслеживает положение окна и обновляет положение наложения при каждом вызове PresentEx .

Создание аппаратной поверхности наложения

Чтобы запросить поддержку наложения, вызовите IDirect3D9::GetDeviceCaps. Если драйвер поддерживает аппаратное наложение, флаг D3DCAPS_OVERLAY устанавливается в D3DCAPS9. Элемент CAPS .

Чтобы узнать, поддерживается ли определенный формат наложения для заданного режима отображения, вызовите IDirect3D9ExOverlayExtension::CheckDeviceOverlayType.

Чтобы создать наложение, вызовите метод IDirect3D9Ex::CreateDeviceEx и укажите D3DSWAPEFFECT_OVERLAY эффект переключения . Задний буфер может использовать формат, отличный от RGB, если его поддерживает оборудование.

Поверхности наложения имеют следующие ограничения:

  • Приложение не может создать более одной цепочки буферов наложения.
  • Наложение должно использоваться в оконном режиме. Его нельзя использовать в полноэкранном режиме.
  • Эффект переключения наложения необходимо использовать с интерфейсом IDirect3Ddevice9Ex . Он не поддерживается для IDirect3DDevice9.
  • Использование множественной дискретизации невозможно.
  • Флаги D3DPRESENT_DONOTFLIP и D3DPRESENT_FLIPRESTART не поддерживаются.
  • Статистика представления недоступна для поверхности наложения.

Если оборудование не поддерживает растяжение, рекомендуется создать цепочку буферов размером с режимом отображения, чтобы размер окна можно было изменить до любых размеров. Повторное создание цепочки буферов не является оптимальным способом обработки размера окна, так как это может привести к серьезным артефактам отрисовки. Кроме того, из-за того, как GPU управляет памятью наложения, повторное создание цепочки буферов может привести к нехватке видеопамяти в приложении.

Новые флаги D3DPRESENT_PARAMETERS

Следующие D3DPRESENT_PARAMETERS флаги определены для создания наложений.

Flag Описание
D3DPRESENTFLAG_OVERLAY_LIMITEDRGB Диапазон RGB — 16–235. Значение по умолчанию — 0–255.
Требуется возможность D3DOVERLAYCAPS_LIMITEDRANGERGB .
D3DPRESENTFLAG_OVERLAY_YCbCr_BT709 Цвета YUV используют определение BT.709. Значение по умолчанию — BT.601.
Требуется возможность D3DOVERLAYCAPS_YCbCr_BT709 .
D3DPRESENTFLAG_OVERLAY_YCbCr_xvYCC Вывод данных с помощью расширенного YCbCr (xvYCC).
Требуется возможность D3DOVERLAYCAPS_YCbCr_BT601_xvYCC или D3DOVERLAYCAPS_YCbCr_BT709_xvYCC .

 

Использование аппаратных наложений

Для отображения поверхности наложения приложение вызывает IDirect3Device9Ex::P resentEx. Среда выполнения Direct3D автоматически рисует ключ цвета назначения.

Для наложений определены следующие флаги PresentEx .

Flag Описание
D3DPRESENT_UPDATECOLORKEY Установите этот флаг, если композиция диспетчера окон рабочего стола (DWM) отключена. Этот флаг приводит к тому, что Direct3D перерисовывает ключ цвета.
Если dwm включен, этот флаг не является обязательным, так как Direct3D один раз рисует цветную клавишу на поверхности, которую DWM использует для перенаправления.
D3DPRESENT_HIDEOVERLAY Скрывает наложение.
D3DPRESENT_UPDATEOVERLAYONLY Обновления наложение без изменения содержимого.
Этот флаг полезен, если окно перемещается во время приостановки видео.

 

Приложение должно быть готово к обработке следующих случаев:

  • Если другое приложение использует наложение, PresentEx возвращает D3DERR_NOTAVAILABLE.
  • Если окно перемещено на другой монитор, приложение должно повторно создать цепочку буферов. В противном случае, если приложение вызывает PresentEx для отображения наложения на другом мониторе, PresentEx возвращает D3DERR_INVALIDDEVICE.
  • При изменении режима отображения Direct3D пытается восстановить наложение. Если новый режим не поддерживает наложение, PresentEx возвращает D3DERR_UNSUPPORTEDOVERLAY.

Пример кода

В следующем примере показано, как создать поверхность наложения.

const UINT VIDEO_WIDTH = 256;
const UINT VIDEO_HEIGHT = 256;

HRESULT CreateHWOverlay(
    HWND hwnd, 
    IDirect3D9Ex *pD3D, 
    IDirect3DDevice9Ex **ppDevice
    )
{
    *ppDevice = NULL;

    D3DCAPS9                caps;
    ZeroMemory(&caps, sizeof(caps));

    HRESULT hr = pD3D->GetDeviceCaps(
        D3DADAPTER_DEFAULT,
        D3DDEVTYPE_HAL,
        &caps
        );

    if (FAILED(hr))
    {
        return hr;
    }

    // Check if overlay is supported.
    if (!(caps.Caps & D3DCAPS_OVERLAY))
    {
        return D3DERR_UNSUPPORTEDOVERLAY;
    }

    D3DOVERLAYCAPS          overlayCaps = { 0 };

    IDirect3DDevice9Ex           *pDevice = NULL;
    IDirect3D9ExOverlayExtension *pOverlay = NULL;

    // Check specific overlay capabilities.
    hr = pD3D->QueryInterface(IID_PPV_ARGS(&pOverlay));

    if (SUCCEEDED(hr))
    {
        hr = pOverlay->CheckDeviceOverlayType(
            D3DADAPTER_DEFAULT,
            D3DDEVTYPE_HAL,
            VIDEO_WIDTH,
            VIDEO_HEIGHT,
            D3DFMT_X8R8G8B8,
            NULL,
            D3DDISPLAYROTATION_IDENTITY,
            &overlayCaps
            );
    }

    // Create the overlay.
    if (SUCCEEDED(hr))
    {

        DWORD flags =   D3DCREATE_FPU_PRESERVE | 
                        D3DCREATE_MULTITHREADED | 
                        D3DCREATE_SOFTWARE_VERTEXPROCESSING;

        
        D3DPRESENT_PARAMETERS   pp = { 0 };

        pp.BackBufferWidth = overlayCaps.MaxOverlayDisplayWidth;
        pp.BackBufferHeight = overlayCaps.MaxOverlayDisplayHeight;
        pp.BackBufferFormat = D3DFMT_X8R8G8B8;
        pp.SwapEffect = D3DSWAPEFFECT_OVERLAY;
        pp.hDeviceWindow = hwnd;
        pp.Windowed = TRUE;
        pp.Flags = D3DPRESENTFLAG_VIDEO;
        pp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
        pp.PresentationInterval       = D3DPRESENT_INTERVAL_ONE;

        hr = pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
            NULL, flags, &pp, NULL, &pDevice);
    }

    if (SUCCEEDED(hr))
    {
        (*ppDevice) = pDevice;
        (*ppDevice)->AddRef();
    }

    SafeRelease(&pD3D);
    SafeRelease(&pDevice);
    SafeRelease(&pOverlay);
    return hr;
}

API-интерфейсы Direct3D Video