common_directx11.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /*****************************************************************************
  2. INTEL CORPORATION PROPRIETARY INFORMATION
  3. This software is supplied under the terms of a license agreement or
  4. nondisclosure agreement with Intel Corporation and may not be copied
  5. or disclosed except in accordance with the terms of that agreement.
  6. Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved.
  7. *****************************************************************************/
  8. #include "common_directx11.h"
  9. #include<map>
  10. ID3D11Device* g_pD3D11Device;
  11. ID3D11DeviceContext* g_pD3D11Ctx;
  12. IDXGIFactory2* g_pDXGIFactory;
  13. IDXGIAdapter* g_pAdapter;
  14. std::map<mfxMemId*, mfxHDL> allocResponses;
  15. std::map<mfxHDL, mfxFrameAllocResponse> allocDecodeResponses;
  16. std::map<mfxHDL, int> allocDecodeRefCount;
  17. typedef struct {
  18. mfxMemId memId;
  19. mfxMemId memIdStage;
  20. mfxU16 rw;
  21. } CustomMemId;
  22. const struct {
  23. mfxIMPL impl; // actual implementation
  24. mfxU32 adapterID; // device adapter number
  25. } implTypes[] = {
  26. {MFX_IMPL_HARDWARE, 0},
  27. {MFX_IMPL_HARDWARE2, 1},
  28. {MFX_IMPL_HARDWARE3, 2},
  29. {MFX_IMPL_HARDWARE4, 3}
  30. };
  31. // =================================================================
  32. // DirectX functionality required to manage DX11 device and surfaces
  33. //
  34. IDXGIAdapter* GetIntelDeviceAdapterHandle(mfxSession session)
  35. {
  36. mfxU32 adapterNum = 0;
  37. mfxIMPL impl;
  38. MFXQueryIMPL(session, &impl);
  39. mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); // Extract Media SDK base implementation type
  40. // get corresponding adapter number
  41. for (mfxU8 i = 0; i < sizeof(implTypes)/sizeof(implTypes[0]); i++) {
  42. if (implTypes[i].impl == baseImpl) {
  43. adapterNum = implTypes[i].adapterID;
  44. break;
  45. }
  46. }
  47. HRESULT hres = CreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)(&g_pDXGIFactory) );
  48. if (FAILED(hres)) return NULL;
  49. IDXGIAdapter* adapter;
  50. hres = g_pDXGIFactory->EnumAdapters(adapterNum, &adapter);
  51. if (FAILED(hres)) return NULL;
  52. return adapter;
  53. }
  54. // Create HW device context
  55. mfxStatus CreateHWDevice(mfxSession session, mfxHDL* deviceHandle, HWND hWnd, bool bCreateSharedHandles)
  56. {
  57. //Note: not using bCreateSharedHandles for DX11 -- for API consistency only
  58. hWnd; // Window handle not required by DX11 since we do not showcase rendering.
  59. bCreateSharedHandles; // For rendering, not used here. Just for consistencies sake.
  60. HRESULT hres = S_OK;
  61. static D3D_FEATURE_LEVEL FeatureLevels[] = {
  62. D3D_FEATURE_LEVEL_11_1,
  63. D3D_FEATURE_LEVEL_11_0,
  64. D3D_FEATURE_LEVEL_10_1,
  65. D3D_FEATURE_LEVEL_10_0
  66. };
  67. D3D_FEATURE_LEVEL pFeatureLevelsOut;
  68. g_pAdapter = GetIntelDeviceAdapterHandle(session);
  69. if (NULL == g_pAdapter)
  70. return MFX_ERR_DEVICE_FAILED;
  71. UINT dxFlags = 0;
  72. //UINT dxFlags = D3D11_CREATE_DEVICE_DEBUG;
  73. hres = D3D11CreateDevice( g_pAdapter,
  74. D3D_DRIVER_TYPE_UNKNOWN,
  75. NULL,
  76. dxFlags,
  77. FeatureLevels,
  78. (sizeof(FeatureLevels) / sizeof(FeatureLevels[0])),
  79. D3D11_SDK_VERSION,
  80. &g_pD3D11Device,
  81. &pFeatureLevelsOut,
  82. &g_pD3D11Ctx);
  83. if (FAILED(hres))
  84. return MFX_ERR_DEVICE_FAILED;
  85. // turn on multithreading for the DX11 context
  86. CComQIPtr<ID3D10Multithread> p_mt(g_pD3D11Ctx);
  87. if (p_mt)
  88. p_mt->SetMultithreadProtected(true);
  89. else
  90. return MFX_ERR_DEVICE_FAILED;
  91. *deviceHandle = (mfxHDL)g_pD3D11Device;
  92. return MFX_ERR_NONE;
  93. }
  94. void SetHWDeviceContext(CComPtr<ID3D11DeviceContext> devCtx)
  95. {
  96. g_pD3D11Ctx = devCtx;
  97. devCtx->GetDevice(&g_pD3D11Device);
  98. }
  99. // Free HW device context
  100. void CleanupHWDevice()
  101. {
  102. if (g_pAdapter)
  103. {
  104. g_pAdapter->Release();
  105. g_pAdapter = NULL;
  106. }
  107. if (g_pD3D11Device)
  108. {
  109. g_pD3D11Device->Release();
  110. g_pD3D11Device = NULL;
  111. }
  112. if (g_pD3D11Ctx)
  113. {
  114. g_pD3D11Ctx->Release();
  115. g_pD3D11Ctx = NULL;
  116. }
  117. if (g_pDXGIFactory)
  118. {
  119. g_pDXGIFactory->Release();
  120. g_pDXGIFactory = NULL;
  121. }
  122. }
  123. CComPtr<ID3D11DeviceContext> GetHWDeviceContext()
  124. {
  125. return g_pD3D11Ctx;
  126. }
  127. /* (Hugh) Functions currently unused */
  128. #if 0
  129. void ClearYUVSurfaceD3D(mfxMemId memId)
  130. {
  131. // TBD
  132. }
  133. void ClearRGBSurfaceD3D(mfxMemId memId)
  134. {
  135. // TBD
  136. }
  137. #endif
  138. //
  139. // Intel Media SDK memory allocator entrypoints....
  140. //
  141. mfxStatus _simple_alloc(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
  142. {
  143. HRESULT hRes;
  144. // Determine surface format
  145. DXGI_FORMAT format;
  146. if (MFX_FOURCC_NV12 == request->Info.FourCC)
  147. format = DXGI_FORMAT_NV12;
  148. else if (MFX_FOURCC_RGB4 == request->Info.FourCC)
  149. format = DXGI_FORMAT_B8G8R8A8_UNORM;
  150. else if (MFX_FOURCC_YUY2== request->Info.FourCC)
  151. format = DXGI_FORMAT_YUY2;
  152. else if (MFX_FOURCC_P8 == request->Info.FourCC ) //|| MFX_FOURCC_P8_TEXTURE == request->Info.FourCC
  153. format = DXGI_FORMAT_P8;
  154. else
  155. format = DXGI_FORMAT_UNKNOWN;
  156. if (DXGI_FORMAT_UNKNOWN == format)
  157. return MFX_ERR_UNSUPPORTED;
  158. // Allocate custom container to keep texture and stage buffers for each surface
  159. // Container also stores the intended read and/or write operation.
  160. CustomMemId** mids = (CustomMemId**)calloc(request->NumFrameSuggested, sizeof(CustomMemId*));
  161. if (!mids) return MFX_ERR_MEMORY_ALLOC;
  162. for (int i=0; i<request->NumFrameSuggested; i++) {
  163. mids[i] = (CustomMemId*)calloc(1, sizeof(CustomMemId));
  164. if (!mids[i]) {
  165. return MFX_ERR_MEMORY_ALLOC;
  166. }
  167. mids[i]->rw = request->Type & 0xF000; // Set intended read/write operation
  168. }
  169. request->Type = request->Type & 0x0FFF;
  170. // because P8 data (bitstream) for h264 encoder should be allocated by CreateBuffer()
  171. // but P8 data (MBData) for MPEG2 encoder should be allocated by CreateTexture2D()
  172. if (request->Info.FourCC == MFX_FOURCC_P8) {
  173. D3D11_BUFFER_DESC desc = { 0 };
  174. if (!request->NumFrameSuggested) return MFX_ERR_MEMORY_ALLOC;
  175. desc.ByteWidth = request->Info.Width * request->Info.Height;
  176. desc.Usage = D3D11_USAGE_STAGING;
  177. desc.BindFlags = 0;
  178. desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  179. desc.MiscFlags = 0;
  180. desc.StructureByteStride = 0;
  181. ID3D11Buffer* buffer = 0;
  182. hRes = g_pD3D11Device->CreateBuffer(&desc, 0, &buffer);
  183. if (FAILED(hRes))
  184. return MFX_ERR_MEMORY_ALLOC;
  185. mids[0]->memId = reinterpret_cast<ID3D11Texture2D*>(buffer);
  186. } else {
  187. D3D11_TEXTURE2D_DESC desc = {0};
  188. desc.Width = request->Info.Width;
  189. desc.Height = request->Info.Height;
  190. desc.MipLevels = 1;
  191. desc.ArraySize = 1; // number of subresources is 1 in this case
  192. desc.Format = format;
  193. desc.SampleDesc.Count = 1;
  194. desc.Usage = D3D11_USAGE_DEFAULT;
  195. desc.BindFlags = D3D11_BIND_DECODER;
  196. desc.MiscFlags = 0;
  197. //desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
  198. if ( (MFX_MEMTYPE_FROM_VPPIN & request->Type) &&
  199. (DXGI_FORMAT_B8G8R8A8_UNORM == desc.Format) ) {
  200. desc.BindFlags = D3D11_BIND_RENDER_TARGET;
  201. if (desc.ArraySize > 2)
  202. return MFX_ERR_MEMORY_ALLOC;
  203. }
  204. if ( (MFX_MEMTYPE_FROM_VPPOUT & request->Type) ||
  205. (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & request->Type)) {
  206. desc.BindFlags = D3D11_BIND_RENDER_TARGET;
  207. if (desc.ArraySize > 2)
  208. return MFX_ERR_MEMORY_ALLOC;
  209. }
  210. if ( DXGI_FORMAT_P8 == desc.Format )
  211. desc.BindFlags = 0;
  212. ID3D11Texture2D* pTexture2D;
  213. // Create surface textures
  214. for (size_t i = 0; i < request->NumFrameSuggested / desc.ArraySize; i++) {
  215. hRes = g_pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D);
  216. if (FAILED(hRes))
  217. return MFX_ERR_MEMORY_ALLOC;
  218. mids[i]->memId = pTexture2D;
  219. }
  220. desc.ArraySize = 1;
  221. desc.Usage = D3D11_USAGE_STAGING;
  222. desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;// | D3D11_CPU_ACCESS_WRITE;
  223. desc.BindFlags = 0;
  224. desc.MiscFlags = 0;
  225. //desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
  226. // Create surface staging textures
  227. for (size_t i = 0; i < request->NumFrameSuggested; i++) {
  228. hRes = g_pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D);
  229. if (FAILED(hRes))
  230. return MFX_ERR_MEMORY_ALLOC;
  231. mids[i]->memIdStage = pTexture2D;
  232. }
  233. }
  234. response->mids = (mfxMemId*)mids;
  235. response->NumFrameActual = request->NumFrameSuggested;
  236. return MFX_ERR_NONE;
  237. }
  238. mfxStatus simple_alloc(mfxHDL pthis, mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
  239. {
  240. mfxStatus sts = MFX_ERR_NONE;
  241. if (request->Type & MFX_MEMTYPE_SYSTEM_MEMORY)
  242. return MFX_ERR_UNSUPPORTED;
  243. if (allocDecodeResponses.find(pthis) != allocDecodeResponses.end() &&
  244. MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
  245. MFX_MEMTYPE_FROM_DECODE & request->Type) {
  246. // Memory for this request was already allocated during manual allocation stage. Return saved response
  247. // When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed.
  248. // Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response
  249. // (No such restriction applies to Encode or VPP)
  250. *response = allocDecodeResponses[pthis];
  251. allocDecodeRefCount[pthis]++;
  252. } else {
  253. sts = _simple_alloc(request, response);
  254. if (MFX_ERR_NONE == sts) {
  255. if ( MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
  256. MFX_MEMTYPE_FROM_DECODE & request->Type) {
  257. // Decode alloc response handling
  258. allocDecodeResponses[pthis] = *response;
  259. allocDecodeRefCount[pthis]++;
  260. } else {
  261. // Encode and VPP alloc response handling
  262. allocResponses[response->mids] = pthis;
  263. }
  264. }
  265. }
  266. return sts;
  267. }
  268. mfxStatus simple_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr)
  269. {
  270. pthis; // To suppress warning for this unused parameter
  271. HRESULT hRes = S_OK;
  272. D3D11_TEXTURE2D_DESC desc = {0};
  273. D3D11_MAPPED_SUBRESOURCE lockedRect = {0};
  274. CustomMemId* memId = (CustomMemId*)mid;
  275. ID3D11Texture2D* pSurface = (ID3D11Texture2D*)memId->memId;
  276. ID3D11Texture2D* pStage = (ID3D11Texture2D*)memId->memIdStage;
  277. D3D11_MAP mapType = D3D11_MAP_READ;
  278. UINT mapFlags = D3D11_MAP_FLAG_DO_NOT_WAIT;
  279. if (NULL == pStage) {
  280. hRes = g_pD3D11Ctx->Map(pSurface, 0, mapType, mapFlags, &lockedRect);
  281. desc.Format = DXGI_FORMAT_P8;
  282. } else {
  283. pSurface->GetDesc(&desc);
  284. // copy data only in case of user wants to read from stored surface
  285. if (memId->rw & WILL_READ)
  286. g_pD3D11Ctx->CopySubresourceRegion(pStage, 0, 0, 0, 0, pSurface, 0, NULL);
  287. do {
  288. hRes = g_pD3D11Ctx->Map(pStage, 0, mapType, mapFlags, &lockedRect);
  289. if (S_OK != hRes && DXGI_ERROR_WAS_STILL_DRAWING != hRes)
  290. return MFX_ERR_LOCK_MEMORY;
  291. } while (DXGI_ERROR_WAS_STILL_DRAWING == hRes);
  292. }
  293. if (FAILED(hRes))
  294. return MFX_ERR_LOCK_MEMORY;
  295. switch (desc.Format) {
  296. case DXGI_FORMAT_NV12:
  297. ptr->Pitch = (mfxU16)lockedRect.RowPitch;
  298. ptr->Y = (mfxU8*)lockedRect.pData;
  299. ptr->U = (mfxU8*)lockedRect.pData + desc.Height * lockedRect.RowPitch;
  300. ptr->V = ptr->U + 1;
  301. break;
  302. case DXGI_FORMAT_B8G8R8A8_UNORM :
  303. ptr->Pitch = (mfxU16)lockedRect.RowPitch;
  304. ptr->B = (mfxU8*)lockedRect.pData;
  305. ptr->G = ptr->B + 1;
  306. ptr->R = ptr->B + 2;
  307. ptr->A = ptr->B + 3;
  308. break;
  309. case DXGI_FORMAT_YUY2:
  310. ptr->Pitch = (mfxU16)lockedRect.RowPitch;
  311. ptr->Y = (mfxU8*)lockedRect.pData;
  312. ptr->U = ptr->Y + 1;
  313. ptr->V = ptr->Y + 3;
  314. break;
  315. case DXGI_FORMAT_P8 :
  316. ptr->Pitch = (mfxU16)lockedRect.RowPitch;
  317. ptr->Y = (mfxU8*)lockedRect.pData;
  318. ptr->U = 0;
  319. ptr->V = 0;
  320. break;
  321. default:
  322. return MFX_ERR_LOCK_MEMORY;
  323. }
  324. return MFX_ERR_NONE;
  325. }
  326. mfxStatus simple_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr)
  327. {
  328. pthis; // To suppress warning for this unused parameter
  329. CustomMemId* memId = (CustomMemId*)mid;
  330. ID3D11Texture2D* pSurface = (ID3D11Texture2D*)memId->memId;
  331. ID3D11Texture2D* pStage = (ID3D11Texture2D*)memId->memIdStage;
  332. if (NULL == pStage) {
  333. g_pD3D11Ctx->Unmap(pSurface, 0);
  334. } else {
  335. g_pD3D11Ctx->Unmap(pStage, 0);
  336. // copy data only in case of user wants to write to stored surface
  337. if (memId->rw & WILL_WRITE)
  338. g_pD3D11Ctx->CopySubresourceRegion(pSurface, 0, 0, 0, 0, pStage, 0, NULL);
  339. }
  340. if (ptr) {
  341. ptr->Pitch=0;
  342. ptr->U=ptr->V=ptr->Y=0;
  343. ptr->A=ptr->R=ptr->G=ptr->B=0;
  344. }
  345. return MFX_ERR_NONE;
  346. }
  347. mfxStatus simple_gethdl(mfxHDL pthis, mfxMemId mid, mfxHDL* handle)
  348. {
  349. pthis; // To suppress warning for this unused parameter
  350. if (NULL == handle)
  351. return MFX_ERR_INVALID_HANDLE;
  352. mfxHDLPair* pPair = (mfxHDLPair*)handle;
  353. CustomMemId* memId = (CustomMemId*)mid;
  354. pPair->first = memId->memId; // surface texture
  355. pPair->second = 0;
  356. return MFX_ERR_NONE;
  357. }
  358. mfxStatus _simple_free(mfxFrameAllocResponse* response)
  359. {
  360. if (response->mids) {
  361. for (mfxU32 i = 0; i < response->NumFrameActual; i++) {
  362. if (response->mids[i]) {
  363. CustomMemId* mid = (CustomMemId*)response->mids[i];
  364. ID3D11Texture2D* pSurface = (ID3D11Texture2D*)mid->memId;
  365. ID3D11Texture2D* pStage = (ID3D11Texture2D*)mid->memIdStage;
  366. if (pSurface)
  367. pSurface->Release();
  368. if (pStage)
  369. pStage->Release();
  370. free(mid);
  371. }
  372. }
  373. free(response->mids);
  374. response->mids = NULL;
  375. }
  376. return MFX_ERR_NONE;
  377. }
  378. mfxStatus simple_free(mfxHDL pthis, mfxFrameAllocResponse* response)
  379. {
  380. if (NULL == response)
  381. return MFX_ERR_NULL_PTR;
  382. if (allocResponses.find(response->mids) == allocResponses.end()) {
  383. // Decode free response handling
  384. if (--allocDecodeRefCount[pthis] == 0) {
  385. _simple_free(response);
  386. allocDecodeResponses.erase(pthis);
  387. allocDecodeRefCount.erase(pthis);
  388. }
  389. } else {
  390. // Encode and VPP free response handling
  391. allocResponses.erase(response->mids);
  392. _simple_free(response);
  393. }
  394. return MFX_ERR_NONE;
  395. }