共用方式為


硬體重疊支援

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

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

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

建立硬體重疊介面

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

若要瞭解特定顯示模式是否支援特定的重疊格式,請呼叫 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