程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Direct3D設備管理器(Direct3D device manager),direct3dmanager

Direct3D設備管理器(Direct3D device manager),direct3dmanager

編輯:C++入門知識

Direct3D設備管理器(Direct3D device manager),direct3dmanager


  這幾天在做dxva2硬件加速,找不到什麼資料,翻譯了一下微軟的兩篇相關文檔。並准備記錄一下用ffmpeg實現dxva2,將在第三篇寫到。這是第一篇,英文原址:https://msdn.microsoft.com/en-us/library/aa965267(v=vs.85).aspx 

  Direct3D設備管理器(Direct3D device manager)允許兩個或多個對象(object)共用同一個Direct3D 9 設備(device)。其中一個對象作為Direct3D 9 設備的擁有者。要能共享設備,擁有設備的對象(the owner)要創建Direct3D設備管理器,其他對象可以獲得一個指向這個設備管理器的指針,然後通過設備管理器獲得一個指向Direct3D 設備的指針。每個使用這個設備的的對象都有一個互斥鎖,防止與其他設備同時使用這個設備。(我的注釋:即一次只能有一個對象使用設備,不能兩個對象同時使用同一個設備。這就是鎖的互斥功能)

注意:Direct3D 設備管理器只支持Direct3D 9 設備。不支持DXGI 設備.

    要創建Direct3D 設備管理器, 需要調用DXVA2CreateDirect3DDeviceManager9函數。這個函數返回一個指向這個創建的設備管理器的IDirect3DDeviceManager9接口的指針,以及一個重置標志(reset token)。重置標志使得使用Direct3D 設備的對象能夠通過這個設備管理器設置(或重置)設備。調用IDirect3DDeviceManager9::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)用完設備後,應調用IDirect3DDeviceManager9::UnlockDevice。這樣其他對象就可以使用這個設備了。

(4)退出前,調用IDirect3DDeviceManager9::CloseDeviceHandle關閉設備句柄。

    你應當只在使用設備的時候才設置設備鎖(the device lock),因為設置設備鎖會阻止其他對象使用設備。(我的注釋:這一點如果有疑惑,百度一下互斥鎖的定義就會明白了,就是一個防止多個對象同時使用同一個設備導致混亂的互斥機制)

    擁有設備的對象(the ownder)可以通過調用ResetDevice函數在任意時候切換到其他設備,特別地,在原始設備丟失的情況下。設備丟失可以由各種原因造成,包括改變顯示器分辨率,電源管理操作,鎖定或解鎖電腦,等等。更多情況,請轉Direct3D文檔。

    ResetDevice函數會把任何之前打開的設備句柄置為無效。設備無效後,LockDevice函數返回DXVA2_E_NEW_VIDEO_DEVICE。如果發生這種情況,關閉句柄並再次調用OpenDeviceHandle以重新獲得新的設備句柄,如以下代碼鎖展示的。

下面的例子展示了如何打開設備句柄和鎖設備(lock the device)。

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;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved