初始化Direct3D
Direct3D渲染可以通過Surface和Texture來實現,后者比較復雜,只是顯示視頻的化用Surface足以。Direct3D有幾個重要的概念需要說明以下:
Device:就是渲染設備實例
Resources:可以理解成一個參數結構體,描述怎樣渲染的細節。
Swap Chains:交換鏈,由一個或者多個緩沖區組成,可以理解成包含多個緩沖區的數組,如下圖所示。
創建Direct3D物理設備對象實例
這一步為了得到IDirect3D9* 實例 m_pD3d9;
m_hD3dDll = LoadLibrary("d3d9.dll");
pDirect3DCreate9 *createD3D = (pDirect3DCreate9 *)GetProcAddress(m_hD3dDll, "Direct3DCreate9");
m_pD3d9 = createD3D(D3D_SDK_VERSION);// 怎樣指定GPU?
創建Direct3D渲染設備實例
這一步為了得到IDirect3DDevice9* 實例 m_pD3d9Dev;
// 獲取顯示適配器參數
D3DDISPLAYMODE displayModel;
if (m_pD3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayModel) < 0)
{
return FALSE;
}
D3DPRESENT_PARAMETERS presentParms = { 0 };
presentParms.Windowed = TRUE; // 是否窗口顯示
presentParms.BackBufferCount = 0; // 后台緩沖表面數量,指定為0時會被視為1
presentParms.hDeviceWindow = m_hWnd; // 顯示窗口句柄
presentParms.SwapEffect = D3DSWAPEFFECT_DISCARD; // 交換鏈設置,后台緩沖使用后直接丟棄
presentParms.BackBufferFormat = displayModel.Format;// 后台緩沖表面格式
presentParms.EnableAutoDepthStencil = FALSE; // 是否自動創建深度模板緩沖,適用於3D場景
presentParms.Flags = D3DPRESENTFLAG_VIDEO; // 附加特性,顯示視頻
presentParms.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; // 刷新率,窗口模式時必須為0
presentParms.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; // 前后台緩沖區的交換頻率
// 查詢設備是否支持硬件加速渲染
DWORD behaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED;
D3DDEVTYPE devType = D3DDEVTYPE_HAL;
D3DCAPS9 caps;
if (m_pD3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, devType, &caps) >= 0)
{
if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
{
behaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
}
else
{
behaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
}
}
else
{
return FALSE;
}
// 創建渲染設備實例
if (m_pD3d9->CreateDevice(D3DADAPTER_DEFAULT, devType, m_hWnd,
behaviorFlags, &presentParms, &m_pD3d9Dev) < 0)
{
return FALSE;
}
創建Direct3D視頻解碼服務
這一步為了得到IDirectXVideoDecoderService* 實例 m_pDecoderService;
m_hDxva2Dll = LoadLibrary("dxva2.dll");
if (!m_hDxva2Dll)
{
return FALSE;
}
pCreateDeviceManager9 *createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(m_hDxva2Dll, "DXVA2CreateDirect3DDeviceManager9");
// 設備管理器實例標識
unsigned resetToken = 0;
if (createDeviceManager(&resetToken, &m_pD3d9DevMgr) < 0)
{
return FALSE;
}
// 重置渲染設備
HRESULT hr = m_pD3d9DevMgr->ResetDevice(m_pD3d9Dev, resetToken);
if (FAILED(hr))
{
return FALSE;
}
// 打開渲染設備
hr = m_pD3d9DevMgr->OpenDeviceHandle(&m_hDev);
if (FAILED(hr))
{
return FALSE;
}
// 獲取視頻渲染服務實例
hr = m_pD3d9DevMgr->GetVideoService(m_hDev, IID_IDirectXVideoDecoderService, (void **)&m_pDecoderService);
if (FAILED(hr))
{
return FALSE;
}