共用方式為


硬體重迭支援

硬體重迭是可在主要介面上重迭的專用視訊記憶體區域。 顯示重迭時不會執行任何複本。 重迭作業會在硬體中執行,而不需修改主要介面中的資料。

在舊版 Windows 中,對於視訊播放使用硬體重迭很常見,因為重迭對於高畫面播放速率的視訊內容有效率。 從 Windows 7 開始,Direct3D 9 支援硬體重迭。 此支援主要是用於視訊播放,而且在某些方面與先前的 DirectDraw API 不同:

  • 重迭無法壓縮、鏡像或取消交錯。
  • 不支援來源色彩索引鍵和 Alpha 混合。
  • 如果重迭硬體支援重迭,可以延展重迭。 否則,不支援延展。 實際上,並非所有圖形驅動程式都支援延展。
  • 每個裝置最多支援一個重迭。
  • 重迭是使用目的地色彩索引鍵來執行,但 Direct3D 執行時間會自動選取色彩並繪製目的地矩形。 Direct3D 會在呼叫 PresentEx 時自動追蹤視窗的位置,並更新重迭位置。

建立硬體重迭介面

若要查詢重迭支援,請呼叫 IDirect3D9::GetDeviceCaps。 如果驅動程式支援硬體重迭, 則會D3DCAPS9 中設定D3DCAPS_OVERLAY旗標。Caps 成員。

若要瞭解特定顯示模式是否支援特定的重迭格式,請呼叫 IDirect3D9ExOverlayExtension::CheckDeviceOverlayType

若要建立重迭,請呼叫 IDirect3D9Ex::CreateDeviceEx 並指定 D3DSWAPEFFECT_OVERLAY 交換效果。 如果硬體支援,後端緩衝區可以使用非 RGB 格式。

重迭表面有下列限制:

  • 應用程式無法建立多個重迭交換鏈結。
  • 重迭必須用於視窗模式。 它無法用於全螢幕模式。
  • 重迭交換效果必須與 IDirect3DDevice9Ex 介面搭配使用。 IDirect3DDevice9不支援它。
  • 無法使用多重取樣。
  • 不支援 D3DPRESENT_DONOTFLIPD3DPRESENT_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_xvYCCD3DOVERLAYCAPS_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;
}

Direct3D 視訊 API