diff --git a/cmake/OpenCVDetectDirectX.cmake b/cmake/OpenCVDetectDirectX.cmake index 9136986204..2224511a97 100644 --- a/cmake/OpenCVDetectDirectX.cmake +++ b/cmake/OpenCVDetectDirectX.cmake @@ -7,6 +7,17 @@ if(WIN32) if(NOT __VALID_DIRECTX) return() endif() + try_compile(__VALID_DIRECTX_NV12 + "${OpenCV_BINARY_DIR}" + "${OpenCV_SOURCE_DIR}/cmake/checks/directx.cpp" + COMPILE_DEFINITIONS "-DCHECK_NV12" + OUTPUT_VARIABLE TRY_OUT + ) + if(__VALID_DIRECTX_NV12) + set(HAVE_DIRECTX_NV12 ON) + else() + message(STATUS "No support for DirectX NV12 format (install Windows 8 SDK)") + endif() set(HAVE_DIRECTX ON) set(HAVE_D3D11 ON) set(HAVE_D3D10 ON) diff --git a/cmake/checks/directx.cpp b/cmake/checks/directx.cpp index 452a885cd1..c617ac341a 100644 --- a/cmake/checks/directx.cpp +++ b/cmake/checks/directx.cpp @@ -40,7 +40,11 @@ static HRESULT InitDevice() sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; +#ifdef CHECK_NV12 + sd.BufferDesc.Format = DXGI_FORMAT_NV12; +#else sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; +#endif sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index 3330774c14..ec0b2a480b 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -57,6 +57,7 @@ /* DirectX */ #cmakedefine HAVE_DIRECTX +#cmakedefine HAVE_DIRECTX_NV12 #cmakedefine HAVE_D3D11 #cmakedefine HAVE_D3D10 #cmakedefine HAVE_D3D9 diff --git a/modules/core/src/directx.cpp b/modules/core/src/directx.cpp index 480d768663..46f3532402 100644 --- a/modules/core/src/directx.cpp +++ b/modules/core/src/directx.cpp @@ -168,7 +168,9 @@ int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT) //case DXGI_FORMAT_BC7_TYPELESS: //case DXGI_FORMAT_BC7_UNORM: //case DXGI_FORMAT_BC7_UNORM_SRGB: +#ifdef HAVE_DIRECTX_NV12 case DXGI_FORMAT_NV12: return CV_8UC3; +#endif default: break; } return errorType; @@ -709,6 +711,8 @@ static void __OpenCLinitializeD3D11() namespace ocl { #if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL) +#ifdef HAVE_DIRECTX_NV12 + static bool ocl_convert_nv12_to_bgr( cl_mem clImageY, @@ -749,6 +753,8 @@ bool ocl_convert_bgr_to_nv12( size_t globalsize[] = { cols, rows }; return k.run(2, globalsize, 0, false); } + +#endif // HAVE_DIRECTX_NV12 #endif // HAVE_DIRECTX && HAVE_OPENCL } // namespace ocl @@ -794,12 +800,14 @@ void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D) if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed"); +#ifdef HAVE_DIRECTX_NV12 if(DXGI_FORMAT_NV12 == desc.Format) { clImageUV = clCreateFromD3D11Texture2DKHR(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 1, &status); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed"); } +#endif cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); @@ -807,6 +815,7 @@ void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D) if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed"); +#ifdef HAVE_DIRECTX_NV12 if(DXGI_FORMAT_NV12 == desc.Format) { status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImageUV, 0, NULL, NULL); @@ -821,6 +830,7 @@ void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsKHR failed"); } else +#endif { size_t offset = 0; // TODO size_t origin[3] = { 0, 0, 0 }; @@ -843,12 +853,15 @@ void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D) if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed"); +#ifdef HAVE_DIRECTX_NV12 if(DXGI_FORMAT_NV12 == desc.Format) { status = clReleaseMemObject(clImageUV); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed"); } +#endif + #else // TODO memcpy NO_OPENCL_SUPPORT_ERROR; @@ -886,18 +899,20 @@ void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst cl_int status = 0; cl_mem clImage = 0; - cl_mem clImageUV = 0; clImage = clCreateFromD3D11Texture2DKHR(context, CL_MEM_READ_ONLY, pD3D11Texture2D, 0, &status); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed"); +#ifdef HAVE_DIRECTX_NV12 + cl_mem clImageUV = 0; if(DXGI_FORMAT_NV12 == desc.Format) { clImageUV = clCreateFromD3D11Texture2DKHR(context, CL_MEM_READ_ONLY, pD3D11Texture2D, 1, &status); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed"); } +#endif cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); @@ -905,6 +920,7 @@ void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed"); +#ifdef HAVE_DIRECTX_NV12 if(DXGI_FORMAT_NV12 == desc.Format) { status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImageUV, 0, NULL, NULL); @@ -919,6 +935,7 @@ void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsKHR failed"); } else +#endif { size_t offset = 0; // TODO size_t origin[3] = { 0, 0, 0 }; @@ -941,12 +958,15 @@ void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed"); +#ifdef HAVE_DIRECTX_NV12 if(DXGI_FORMAT_NV12 == desc.Format) { status = clReleaseMemObject(clImageUV); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed"); } +#endif + #else // TODO memcpy NO_OPENCL_SUPPORT_ERROR; diff --git a/samples/directx/d3d11_interop.cpp b/samples/directx/d3d11_interop.cpp index a6eab3a328..5012886766 100644 --- a/samples/directx/d3d11_interop.cpp +++ b/samples/directx/d3d11_interop.cpp @@ -27,8 +27,10 @@ using namespace cv; class D3D11WinApp : public D3DSample { public: - D3D11WinApp(int width, int height, std::string& window_name, cv::VideoCapture& cap) : - D3DSample(width, height, window_name, cap) {} + D3D11WinApp(int width, int height, std::string& window_name, cv::VideoCapture& cap) + : D3DSample(width, height, window_name, cap), + m_nv12_available(false) + {} ~D3D11WinApp() {} @@ -74,13 +76,14 @@ public: throw std::runtime_error("D3D11CreateDeviceAndSwapChain() failed!"); } - m_nv12_available = true; +#if defined(_WIN32_WINNT_WIN8) && _WIN32_WINNT >= _WIN32_WINNT_WIN8 UINT fmt = 0; r = m_pD3D11Dev->CheckFormatSupport(DXGI_FORMAT_NV12, &fmt); - if (FAILED(r)) + if (SUCCEEDED(r)) { - m_nv12_available = false; + m_nv12_available = true; } +#endif r = m_pD3D11SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&m_pBackBuffer); if (FAILED(r)) @@ -129,6 +132,7 @@ public: throw std::runtime_error("Can't create DX texture"); } +#if defined(_WIN32_WINNT_WIN8) && _WIN32_WINNT >= _WIN32_WINNT_WIN8 if(m_nv12_available) { D3D11_TEXTURE2D_DESC desc_nv12; @@ -171,6 +175,7 @@ public: throw std::runtime_error("Can't create DX NV12 texture"); } } +#endif // initialize OpenCL context of OpenCV lib from DirectX if (cv::ocl::haveOpenCL())