Поделиться через


Поддержка аппаратного наложения

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

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

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

Создание аппаратного наложения Surface

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

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

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

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

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

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

Новые флаги D3DPRESENT_PARAMETERS

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

Флаг Описание
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.

 

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

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

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

Флаг Описание
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