device_directx9.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. // #include "mfx_samples_config.h"
  2. #if defined(WIN32) || defined(WIN64)
  3. //prefast signature used in combaseapi.h
  4. #ifndef _PREFAST_
  5. #pragma warning(disable : 4068)
  6. #endif
  7. #include "device_directx9.h"
  8. // #include "igfx_s3dcontrol.h"
  9. #include "atlbase.h"
  10. // Macros
  11. #define MSDK_ZERO_MEMORY(VAR) \
  12. { \
  13. memset(&VAR, 0, sizeof(VAR)); \
  14. }
  15. #define MSDK_MEMCPY_VAR(dstVarName, src, count) \
  16. memcpy_s(&(dstVarName), sizeof(dstVarName), (src), (count))
  17. CD3D9Device::CD3D9Device()
  18. {
  19. m_pD3D9 = NULL;
  20. m_pD3DD9 = NULL;
  21. m_pDeviceManager9 = NULL;
  22. MSDK_ZERO_MEMORY(m_D3DPP);
  23. m_resetToken = 0;
  24. m_nViews = 0;
  25. m_pS3DControl = NULL;
  26. MSDK_ZERO_MEMORY(m_backBufferDesc);
  27. m_pDXVAVPS = NULL;
  28. m_pDXVAVP_Left = NULL;
  29. m_pDXVAVP_Right = NULL;
  30. MSDK_ZERO_MEMORY(m_targetRect);
  31. MSDK_ZERO_MEMORY(m_VideoDesc);
  32. MSDK_ZERO_MEMORY(m_BltParams);
  33. MSDK_ZERO_MEMORY(m_Sample);
  34. // Initialize DXVA structures
  35. DXVA2_AYUVSample16 color = {
  36. 0x8000, // Cr
  37. 0x8000, // Cb
  38. 0x1000, // Y
  39. 0xffff // Alpha
  40. };
  41. DXVA2_ExtendedFormat format = {
  42. // DestFormat
  43. DXVA2_SampleProgressiveFrame, // SampleFormat
  44. DXVA2_VideoChromaSubsampling_MPEG2, // VideoChromaSubsampling
  45. DXVA_NominalRange_0_255, // NominalRange
  46. DXVA2_VideoTransferMatrix_BT709, // VideoTransferMatrix
  47. DXVA2_VideoLighting_bright, // VideoLighting
  48. DXVA2_VideoPrimaries_BT709, // VideoPrimaries
  49. DXVA2_VideoTransFunc_709 // VideoTransferFunction
  50. };
  51. // init m_VideoDesc structure
  52. MSDK_MEMCPY_VAR(m_VideoDesc.SampleFormat, &format,
  53. sizeof(DXVA2_ExtendedFormat));
  54. m_VideoDesc.SampleWidth = 0;
  55. m_VideoDesc.SampleHeight = 0;
  56. m_VideoDesc.InputSampleFreq.Numerator = 60;
  57. m_VideoDesc.InputSampleFreq.Denominator = 1;
  58. m_VideoDesc.OutputFrameFreq.Numerator = 60;
  59. m_VideoDesc.OutputFrameFreq.Denominator = 1;
  60. // init m_BltParams structure
  61. MSDK_MEMCPY_VAR(m_BltParams.DestFormat, &format,
  62. sizeof(DXVA2_ExtendedFormat));
  63. MSDK_MEMCPY_VAR(m_BltParams.BackgroundColor, &color,
  64. sizeof(DXVA2_AYUVSample16));
  65. // init m_Sample structure
  66. m_Sample.Start = 0;
  67. m_Sample.End = 1;
  68. m_Sample.SampleFormat = format;
  69. m_Sample.PlanarAlpha.Fraction = 0;
  70. m_Sample.PlanarAlpha.Value = 1;
  71. m_bIsA2rgb10 = FALSE;
  72. }
  73. bool CD3D9Device::CheckOverlaySupport()
  74. {
  75. D3DCAPS9 d3d9caps;
  76. D3DOVERLAYCAPS d3doverlaycaps = {0};
  77. IDirect3D9ExOverlayExtension *d3d9overlay = NULL;
  78. bool overlaySupported = false;
  79. memset(&d3d9caps, 0, sizeof(d3d9caps));
  80. HRESULT hr = m_pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
  81. &d3d9caps);
  82. if (FAILED(hr) || !(d3d9caps.Caps & D3DCAPS_OVERLAY)) {
  83. overlaySupported = false;
  84. } else {
  85. hr = m_pD3D9->QueryInterface(IID_PPV_ARGS(&d3d9overlay));
  86. if (FAILED(hr) || (d3d9overlay == NULL)) {
  87. overlaySupported = false;
  88. } else {
  89. hr = d3d9overlay->CheckDeviceOverlayType(
  90. D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
  91. m_D3DPP.BackBufferWidth,
  92. m_D3DPP.BackBufferHeight,
  93. m_D3DPP.BackBufferFormat, NULL,
  94. D3DDISPLAYROTATION_IDENTITY, &d3doverlaycaps);
  95. MSDK_SAFE_RELEASE(d3d9overlay);
  96. if (FAILED(hr)) {
  97. overlaySupported = false;
  98. } else {
  99. overlaySupported = true;
  100. }
  101. }
  102. }
  103. return overlaySupported;
  104. }
  105. mfxStatus CD3D9Device::FillD3DPP(mfxHDL hWindow, mfxU16 nViews,
  106. D3DPRESENT_PARAMETERS &D3DPP)
  107. {
  108. mfxStatus sts = MFX_ERR_NONE;
  109. D3DPP.Windowed = true;
  110. D3DPP.hDeviceWindow = (HWND)hWindow;
  111. D3DPP.Flags = D3DPRESENTFLAG_VIDEO;
  112. D3DPP.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  113. D3DPP.PresentationInterval =
  114. D3DPRESENT_INTERVAL_ONE; // note that this setting leads to an implicit timeBeginPeriod call
  115. D3DPP.BackBufferCount = 1;
  116. D3DPP.BackBufferFormat = (m_bIsA2rgb10) ? D3DFMT_A2R10G10B10
  117. : D3DFMT_X8R8G8B8;
  118. if (hWindow) {
  119. RECT r;
  120. GetClientRect((HWND)hWindow, &r);
  121. int x = GetSystemMetrics(SM_CXSCREEN);
  122. int y = GetSystemMetrics(SM_CYSCREEN);
  123. D3DPP.BackBufferWidth = min(r.right - r.left, x);
  124. D3DPP.BackBufferHeight = min(r.bottom - r.top, y);
  125. } else {
  126. D3DPP.BackBufferWidth = GetSystemMetrics(SM_CYSCREEN);
  127. D3DPP.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN);
  128. }
  129. //
  130. // Mark the back buffer lockable if software DXVA2 could be used.
  131. // This is because software DXVA2 device requires a lockable render target
  132. // for the optimal performance.
  133. //
  134. {
  135. D3DPP.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
  136. }
  137. bool isOverlaySupported = CheckOverlaySupport();
  138. if (2 == nViews && !isOverlaySupported)
  139. return MFX_ERR_UNSUPPORTED;
  140. bool needOverlay = (2 == nViews) ? true : false;
  141. D3DPP.SwapEffect = needOverlay ? D3DSWAPEFFECT_OVERLAY
  142. : D3DSWAPEFFECT_DISCARD;
  143. return sts;
  144. }
  145. mfxStatus CD3D9Device::Init(mfxHDL hWindow, mfxU16 nViews, mfxU32 nAdapterNum)
  146. {
  147. mfxStatus sts = MFX_ERR_NONE;
  148. if (2 < nViews)
  149. return MFX_ERR_UNSUPPORTED;
  150. m_nViews = nViews;
  151. HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_pD3D9);
  152. if (!m_pD3D9 || FAILED(hr))
  153. return MFX_ERR_DEVICE_FAILED;
  154. ZeroMemory(&m_D3DPP, sizeof(m_D3DPP));
  155. sts = FillD3DPP(hWindow, nViews, m_D3DPP);
  156. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  157. hr = m_pD3D9->CreateDeviceEx(nAdapterNum, D3DDEVTYPE_HAL, (HWND)hWindow,
  158. D3DCREATE_SOFTWARE_VERTEXPROCESSING |
  159. D3DCREATE_MULTITHREADED |
  160. D3DCREATE_FPU_PRESERVE,
  161. &m_D3DPP, NULL, &m_pD3DD9);
  162. if (FAILED(hr))
  163. return MFX_ERR_NULL_PTR;
  164. if (hWindow) {
  165. hr = m_pD3DD9->ResetEx(&m_D3DPP, NULL);
  166. if (FAILED(hr))
  167. return MFX_ERR_UNDEFINED_BEHAVIOR;
  168. hr = m_pD3DD9->Clear(0, NULL, D3DCLEAR_TARGET,
  169. D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
  170. if (FAILED(hr))
  171. return MFX_ERR_UNDEFINED_BEHAVIOR;
  172. }
  173. UINT resetToken = 0;
  174. hr = DXVA2CreateDirect3DDeviceManager9(&resetToken, &m_pDeviceManager9);
  175. if (FAILED(hr))
  176. return MFX_ERR_NULL_PTR;
  177. hr = m_pDeviceManager9->ResetDevice(m_pD3DD9, resetToken);
  178. if (FAILED(hr))
  179. return MFX_ERR_UNDEFINED_BEHAVIOR;
  180. m_resetToken = resetToken;
  181. return sts;
  182. }
  183. mfxStatus CD3D9Device::Reset()
  184. {
  185. HRESULT hr = NO_ERROR;
  186. MSDK_CHECK_POINTER(m_pD3DD9, MFX_ERR_NULL_PTR);
  187. if (m_D3DPP.Windowed) {
  188. RECT r;
  189. GetClientRect((HWND)m_D3DPP.hDeviceWindow, &r);
  190. int x = GetSystemMetrics(SM_CXSCREEN);
  191. int y = GetSystemMetrics(SM_CYSCREEN);
  192. m_D3DPP.BackBufferWidth = min(r.right - r.left, x);
  193. m_D3DPP.BackBufferHeight = min(r.bottom - r.top, y);
  194. } else {
  195. m_D3DPP.BackBufferWidth = GetSystemMetrics(SM_CXSCREEN);
  196. m_D3DPP.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN);
  197. }
  198. // Reset will change the parameters, so use a copy instead.
  199. D3DPRESENT_PARAMETERS d3dpp = m_D3DPP;
  200. hr = m_pD3DD9->ResetEx(&d3dpp, NULL);
  201. if (FAILED(hr))
  202. return MFX_ERR_UNDEFINED_BEHAVIOR;
  203. hr = m_pDeviceManager9->ResetDevice(m_pD3DD9, m_resetToken);
  204. if (FAILED(hr))
  205. return MFX_ERR_UNDEFINED_BEHAVIOR;
  206. return MFX_ERR_NONE;
  207. }
  208. void CD3D9Device::Close()
  209. {
  210. MSDK_SAFE_RELEASE(m_pDXVAVP_Left);
  211. MSDK_SAFE_RELEASE(m_pDXVAVP_Right);
  212. MSDK_SAFE_RELEASE(m_pDXVAVPS);
  213. MSDK_SAFE_RELEASE(m_pDeviceManager9);
  214. MSDK_SAFE_RELEASE(m_pD3DD9);
  215. MSDK_SAFE_RELEASE(m_pD3D9);
  216. m_pS3DControl = NULL;
  217. }
  218. CD3D9Device::~CD3D9Device()
  219. {
  220. Close();
  221. }
  222. mfxStatus CD3D9Device::GetHandle(mfxHandleType type, mfxHDL *pHdl)
  223. {
  224. if (MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9 == type && pHdl != NULL) {
  225. *pHdl = m_pDeviceManager9;
  226. return MFX_ERR_NONE;
  227. } else if (MFX_HANDLE_GFXS3DCONTROL == type && pHdl != NULL) {
  228. *pHdl = m_pS3DControl;
  229. return MFX_ERR_NONE;
  230. }
  231. return MFX_ERR_UNSUPPORTED;
  232. }
  233. mfxStatus CD3D9Device::SetHandle(mfxHandleType type, mfxHDL hdl)
  234. {
  235. if (MFX_HANDLE_GFXS3DCONTROL == type && hdl != NULL) {
  236. m_pS3DControl = (IGFXS3DControl *)hdl;
  237. return MFX_ERR_NONE;
  238. } else if (MFX_HANDLE_DEVICEWINDOW == type &&
  239. hdl != NULL) //for render window handle
  240. {
  241. m_D3DPP.hDeviceWindow = (HWND)hdl;
  242. return MFX_ERR_NONE;
  243. }
  244. return MFX_ERR_UNSUPPORTED;
  245. }
  246. mfxStatus CD3D9Device::RenderFrame(mfxFrameSurface1 *pSurface,
  247. mfxFrameAllocator *pmfxAlloc)
  248. {
  249. HRESULT hr = S_OK;
  250. if (!(1 == m_nViews || (2 == m_nViews && NULL != m_pS3DControl)))
  251. return MFX_ERR_UNDEFINED_BEHAVIOR;
  252. MSDK_CHECK_POINTER(pSurface, MFX_ERR_NULL_PTR);
  253. MSDK_CHECK_POINTER(m_pDeviceManager9, MFX_ERR_NOT_INITIALIZED);
  254. MSDK_CHECK_POINTER(pmfxAlloc, MFX_ERR_NULL_PTR);
  255. // don't try to render second view if output rect changed since first view
  256. if (2 == m_nViews && (0 != pSurface->Info.FrameId.ViewId))
  257. return MFX_ERR_NONE;
  258. hr = m_pD3DD9->TestCooperativeLevel();
  259. switch (hr) {
  260. case D3D_OK:
  261. break;
  262. case D3DERR_DEVICELOST: {
  263. return MFX_ERR_DEVICE_LOST;
  264. }
  265. case D3DERR_DEVICENOTRESET: {
  266. return MFX_ERR_UNKNOWN;
  267. }
  268. default: {
  269. return MFX_ERR_UNKNOWN;
  270. }
  271. }
  272. CComPtr<IDirect3DSurface9> pBackBuffer;
  273. hr = m_pD3DD9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
  274. &pBackBuffer);
  275. mfxHDLPair *dxMemId = (mfxHDLPair *)pSurface->Data.MemId;
  276. hr = m_pD3DD9->StretchRect((IDirect3DSurface9 *)dxMemId->first, NULL,
  277. pBackBuffer, NULL, D3DTEXF_LINEAR);
  278. if (FAILED(hr)) {
  279. return MFX_ERR_UNKNOWN;
  280. }
  281. if (SUCCEEDED(hr) &&
  282. (1 == m_nViews || pSurface->Info.FrameId.ViewId == 1)) {
  283. hr = m_pD3DD9->Present(NULL, NULL, NULL, NULL);
  284. }
  285. return SUCCEEDED(hr) ? MFX_ERR_NONE : MFX_ERR_DEVICE_FAILED;
  286. }
  287. /*
  288. mfxStatus CD3D9Device::CreateVideoProcessors()
  289. {
  290. if (!(1 == m_nViews || (2 == m_nViews && NULL != m_pS3DControl)))
  291. return MFX_ERR_UNDEFINED_BEHAVIOR;
  292. MSDK_SAFE_RELEASE(m_pDXVAVP_Left);
  293. MSDK_SAFE_RELEASE(m_pDXVAVP_Right);
  294. HRESULT hr ;
  295. if (2 == m_nViews && NULL != m_pS3DControl)
  296. {
  297. hr = m_pS3DControl->SetDevice(m_pDeviceManager9);
  298. if (FAILED(hr))
  299. {
  300. return MFX_ERR_DEVICE_FAILED;
  301. }
  302. }
  303. ZeroMemory(&m_backBufferDesc, sizeof(m_backBufferDesc));
  304. IDirect3DSurface9 *backBufferTmp = NULL;
  305. hr = m_pD3DD9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBufferTmp);
  306. if (NULL != backBufferTmp)
  307. backBufferTmp->GetDesc(&m_backBufferDesc);
  308. MSDK_SAFE_RELEASE(backBufferTmp);
  309. if (SUCCEEDED(hr))
  310. {
  311. // Create DXVA2 Video Processor Service.
  312. hr = DXVA2CreateVideoService(m_pD3DD9,
  313. IID_IDirectXVideoProcessorService,
  314. (void**)&m_pDXVAVPS);
  315. }
  316. if (2 == m_nViews)
  317. {
  318. // Activate L channel
  319. if (SUCCEEDED(hr))
  320. {
  321. hr = m_pS3DControl->SelectLeftView();
  322. }
  323. if (SUCCEEDED(hr))
  324. {
  325. // Create VPP device for the L channel
  326. hr = m_pDXVAVPS->CreateVideoProcessor(DXVA2_VideoProcProgressiveDevice,
  327. &m_VideoDesc,
  328. m_D3DPP.BackBufferFormat,
  329. 1,
  330. &m_pDXVAVP_Left);
  331. }
  332. // Activate R channel
  333. if (SUCCEEDED(hr))
  334. {
  335. hr = m_pS3DControl->SelectRightView();
  336. }
  337. }
  338. if (SUCCEEDED(hr))
  339. {
  340. hr = m_pDXVAVPS->CreateVideoProcessor(DXVA2_VideoProcProgressiveDevice,
  341. &m_VideoDesc,
  342. m_D3DPP.BackBufferFormat,
  343. 1,
  344. &m_pDXVAVP_Right);
  345. }
  346. return SUCCEEDED(hr) ? MFX_ERR_NONE : MFX_ERR_DEVICE_FAILED;
  347. }
  348. */
  349. #endif // #if defined(WIN32) || defined(WIN64)