core: added DirectX interop implementation (OpenCL) with samples
authorAlexander Alekhin <alexander.alekhin@itseez.com>
Sun, 1 Dec 2013 21:50:24 +0000 (01:50 +0400)
committerAlexander Alekhin <alexander.alekhin@itseez.com>
Fri, 13 Dec 2013 15:02:41 +0000 (19:02 +0400)
15 files changed:
modules/core/include/opencv2/core.hpp
modules/core/include/opencv2/core/base.hpp
modules/core/include/opencv2/core/directx.hpp [new file with mode: 0644]
modules/core/include/opencv2/core/ocl.hpp
modules/core/src/directx.cpp [new file with mode: 0644]
modules/core/src/directx.inc.hpp [new file with mode: 0644]
modules/core/src/ocl.cpp
modules/core/src/precomp.hpp
samples/CMakeLists.txt
samples/directx/CMakeLists.txt [new file with mode: 0644]
samples/directx/d3d10_interop.cpp [new file with mode: 0644]
samples/directx/d3d11_interop.cpp [new file with mode: 0644]
samples/directx/d3d9_interop.cpp [new file with mode: 0644]
samples/directx/d3d9ex_interop.cpp [new file with mode: 0644]
samples/directx/d3d_base.inl.hpp [new file with mode: 0644]

index 87263fa..5e72764 100644 (file)
@@ -1262,5 +1262,4 @@ template<> struct ParamType<uchar>
 #include "opencv2/core/operations.hpp"
 #include "opencv2/core/cvstd.inl.hpp"
 
-
 #endif /*__OPENCV_CORE_HPP__*/
index 18a996b..6e78300 100644 (file)
@@ -223,19 +223,26 @@ enum {
 CV_EXPORTS void error(int _code, const String& _err, const char* _func, const char* _file, int _line);
 
 #ifdef __GNUC__
-#  if defined __clang__ || defined __APPLE__
-#    pragma GCC diagnostic push
-#    pragma GCC diagnostic ignored "-Winvalid-noreturn"
-#  endif
+# if defined __clang__ || defined __APPLE__
+#   pragma GCC diagnostic push
+#   pragma GCC diagnostic ignored "-Winvalid-noreturn"
+# endif
 #endif
 CV_INLINE CV_NORETURN void errorNoReturn(int _code, const String& _err, const char* _func, const char* _file, int _line)
 {
     error(_code, _err, _func, _file, _line);
+#ifdef __GNUC__
+# if !defined __clang__ && !defined __APPLE__
+    // this suppresses this warning: "noreturn" function does return [enabled by default]
+    __builtin_trap();
+    // or use infinite loop: for (;;) {}
+# endif
+#endif
 }
 #ifdef __GNUC__
-#  if defined __clang__ || defined __APPLE__
-#    pragma GCC diagnostic pop
-#  endif
+# if defined __clang__ || defined __APPLE__
+#   pragma GCC diagnostic pop
+# endif
 #endif
 
 
diff --git a/modules/core/include/opencv2/core/directx.hpp b/modules/core/include/opencv2/core/directx.hpp
new file mode 100644 (file)
index 0000000..2a8991a
--- /dev/null
@@ -0,0 +1,95 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors as is and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the copyright holders or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_CORE_DIRECTX_HPP__
+#define __OPENCV_CORE_DIRECTX_HPP__
+
+#include "mat.hpp"
+#include "ocl.hpp"
+
+#if !defined(__d3d11_h__)
+struct ID3D11Device;
+struct ID3D11Texture2D;
+#endif
+
+#if !defined(__d3d10_h__)
+struct ID3D10Device;
+struct ID3D10Texture2D;
+#endif
+
+#if !defined(_D3D9_H_)
+struct IDirect3DDevice9;
+struct IDirect3DDevice9Ex;
+struct IDirect3DSurface9;
+#endif
+
+namespace cv { namespace directx {
+
+namespace ocl {
+using namespace cv::ocl;
+
+// TODO static functions in the Context class
+CV_EXPORTS Context2& initializeContextFromD3D11Device(ID3D11Device* pD3D11Device);
+CV_EXPORTS Context2& initializeContextFromD3D10Device(ID3D10Device* pD3D10Device);
+CV_EXPORTS Context2& initializeContextFromDirect3DDevice9Ex(IDirect3DDevice9Ex* pDirect3DDevice9Ex);
+CV_EXPORTS Context2& initializeContextFromDirect3DDevice9(IDirect3DDevice9* pDirect3DDevice9);
+
+} // namespace cv::directx::ocl
+
+CV_EXPORTS void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D);
+CV_EXPORTS void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst);
+
+CV_EXPORTS void convertToD3D10Texture2D(InputArray src, ID3D10Texture2D* pD3D10Texture2D);
+CV_EXPORTS void convertFromD3D10Texture2D(ID3D10Texture2D* pD3D10Texture2D, OutputArray dst);
+
+CV_EXPORTS void convertToDirect3DSurface9(InputArray src, IDirect3DSurface9* pDirect3DSurface9, void* surfaceSharedHandle = NULL);
+CV_EXPORTS void convertFromDirect3DSurface9(IDirect3DSurface9* pDirect3DSurface9, OutputArray dst, void* surfaceSharedHandle = NULL);
+
+// Get OpenCV type from DirectX type, return -1 if there is no equivalent
+CV_EXPORTS int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT); // enum DXGI_FORMAT for D3D10/D3D11
+
+// Get OpenCV type from DirectX type, return -1 if there is no equivalent
+CV_EXPORTS int getTypeFromD3DFORMAT(const int iD3DFORMAT); // enum D3DTYPE for D3D9
+
+
+} } // namespace cv::directx
+
+#endif // __OPENCV_CORE_DIRECTX_HPP__
index f253594..a9fdf1e 100644 (file)
@@ -214,10 +214,33 @@ public:
     Program getProg(const ProgramSource2& prog,
                     const String& buildopt, String& errmsg);
 
-    static Context2& getDefault();
+    static Context2& getDefault(bool initialize = true);
     void* ptr() const;
+
+    struct Impl;
+    inline struct Impl* _getImpl() const { return p; };
 protected:
+    Impl* p;
+};
+
+
+// TODO Move to internal header
+void initializeContextFromHandle(Context2& ctx, void* platform, void* context, void* device);
+
+class CV_EXPORTS Platform
+{
+public:
+    Platform();
+    ~Platform();
+    Platform(const Platform& p);
+    Platform& operator = (const Platform& p);
+
+    void* ptr() const;
+    static Platform& getDefault();
+
     struct Impl;
+    inline struct Impl* _getImpl() const { return p; };
+protected:
     Impl* p;
 };
 
diff --git a/modules/core/src/directx.cpp b/modules/core/src/directx.cpp
new file mode 100644 (file)
index 0000000..071df03
--- /dev/null
@@ -0,0 +1,1134 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors as is and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the copyright holders or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "precomp.hpp"
+
+#include "opencv2/core.hpp"
+#include "opencv2/core/ocl.hpp"
+#include "opencv2/core/directx.hpp"
+
+#ifdef HAVE_DIRECTX
+#include <vector>
+# include "directx.inc.hpp"
+#else // HAVE_DIRECTX
+#define NO_DIRECTX_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without DirectX support")
+#endif
+
+#ifndef HAVE_OPENCL
+# define NO_OPENCL_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without OpenCL support")
+#endif // HAVE_OPENCL
+
+namespace cv { namespace directx {
+
+int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT)
+{
+    (void)iDXGI_FORMAT;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#else
+    const int errorType = -1;
+    switch ((enum DXGI_FORMAT)iDXGI_FORMAT)
+    {
+    //case DXGI_FORMAT_UNKNOWN:
+    //case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+    case DXGI_FORMAT_R32G32B32A32_FLOAT: return CV_32FC4;
+    case DXGI_FORMAT_R32G32B32A32_UINT:
+    case DXGI_FORMAT_R32G32B32A32_SINT:  return CV_32SC4;
+    //case DXGI_FORMAT_R32G32B32_TYPELESS:
+    case DXGI_FORMAT_R32G32B32_FLOAT: return CV_32FC3;
+    case DXGI_FORMAT_R32G32B32_UINT:
+    case DXGI_FORMAT_R32G32B32_SINT: return CV_32SC3;
+    //case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+    //case DXGI_FORMAT_R16G16B16A16_FLOAT:
+    case DXGI_FORMAT_R16G16B16A16_UNORM:
+    case DXGI_FORMAT_R16G16B16A16_UINT: return CV_16UC4;
+    case DXGI_FORMAT_R16G16B16A16_SNORM:
+    case DXGI_FORMAT_R16G16B16A16_SINT: return CV_16SC4;
+    //case DXGI_FORMAT_R32G32_TYPELESS:
+    //case DXGI_FORMAT_R32G32_FLOAT:
+    //case DXGI_FORMAT_R32G32_UINT:
+    //case DXGI_FORMAT_R32G32_SINT:
+    //case DXGI_FORMAT_R32G8X24_TYPELESS:
+    //case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+    //case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+    //case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+    //case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+    //case DXGI_FORMAT_R10G10B10A2_UNORM:
+    //case DXGI_FORMAT_R10G10B10A2_UINT:
+    //case DXGI_FORMAT_R11G11B10_FLOAT:
+    //case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+    case DXGI_FORMAT_R8G8B8A8_UNORM:
+    case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+    case DXGI_FORMAT_R8G8B8A8_UINT: return CV_8UC4;
+    case DXGI_FORMAT_R8G8B8A8_SNORM:
+    case DXGI_FORMAT_R8G8B8A8_SINT: return CV_8SC4;
+    //case DXGI_FORMAT_R16G16_TYPELESS:
+    //case DXGI_FORMAT_R16G16_FLOAT:
+    case DXGI_FORMAT_R16G16_UNORM:
+    case DXGI_FORMAT_R16G16_UINT: return CV_16UC2;
+    case DXGI_FORMAT_R16G16_SNORM:
+    case DXGI_FORMAT_R16G16_SINT: return CV_16SC2;
+    //case DXGI_FORMAT_R32_TYPELESS:
+    //case DXGI_FORMAT_D32_FLOAT:
+    case DXGI_FORMAT_R32_FLOAT: return CV_32FC1;
+    case DXGI_FORMAT_R32_UINT:
+    case DXGI_FORMAT_R32_SINT: return CV_32SC1;
+    //case DXGI_FORMAT_R24G8_TYPELESS:
+    //case DXGI_FORMAT_D24_UNORM_S8_UINT:
+    //case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+    //case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+    //case DXGI_FORMAT_R8G8_TYPELESS:
+    case DXGI_FORMAT_R8G8_UNORM:
+    case DXGI_FORMAT_R8G8_UINT: return CV_8UC2;
+    case DXGI_FORMAT_R8G8_SNORM:
+    case DXGI_FORMAT_R8G8_SINT: return CV_8SC2;
+    //case DXGI_FORMAT_R16_TYPELESS:
+    //case DXGI_FORMAT_R16_FLOAT:
+    case DXGI_FORMAT_D16_UNORM:
+    case DXGI_FORMAT_R16_UNORM:
+    case DXGI_FORMAT_R16_UINT: return CV_16UC1;
+    case DXGI_FORMAT_R16_SNORM:
+    case DXGI_FORMAT_R16_SINT: return CV_16SC1;
+    //case DXGI_FORMAT_R8_TYPELESS:
+    case DXGI_FORMAT_R8_UNORM:
+    case DXGI_FORMAT_R8_UINT: return CV_8UC1;
+    case DXGI_FORMAT_R8_SNORM:
+    case DXGI_FORMAT_R8_SINT: return CV_8SC1;
+    case DXGI_FORMAT_A8_UNORM: return CV_8UC1;
+    //case DXGI_FORMAT_R1_UNORM:
+    //case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+    //case DXGI_FORMAT_R8G8_B8G8_UNORM:
+    //case DXGI_FORMAT_G8R8_G8B8_UNORM:
+    //case DXGI_FORMAT_BC1_TYPELESS:
+    //case DXGI_FORMAT_BC1_UNORM:
+    //case DXGI_FORMAT_BC1_UNORM_SRGB:
+    //case DXGI_FORMAT_BC2_TYPELESS:
+    //case DXGI_FORMAT_BC2_UNORM:
+    //case DXGI_FORMAT_BC2_UNORM_SRGB:
+    //case DXGI_FORMAT_BC3_TYPELESS:
+    //case DXGI_FORMAT_BC3_UNORM:
+    //case DXGI_FORMAT_BC3_UNORM_SRGB:
+    //case DXGI_FORMAT_BC4_TYPELESS:
+    //case DXGI_FORMAT_BC4_UNORM:
+    //case DXGI_FORMAT_BC4_SNORM:
+    //case DXGI_FORMAT_BC5_TYPELESS:
+    //case DXGI_FORMAT_BC5_UNORM:
+    //case DXGI_FORMAT_BC5_SNORM:
+    //case DXGI_FORMAT_B5G6R5_UNORM:
+    //case DXGI_FORMAT_B5G5R5A1_UNORM:
+    case DXGI_FORMAT_B8G8R8A8_UNORM:
+    case DXGI_FORMAT_B8G8R8X8_UNORM: return CV_8UC4;
+    //case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+    //case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+    case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return CV_8UC4;
+    //case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+    case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return CV_8UC4;
+    //case DXGI_FORMAT_BC6H_TYPELESS:
+    //case DXGI_FORMAT_BC6H_UF16:
+    //case DXGI_FORMAT_BC6H_SF16:
+    //case DXGI_FORMAT_BC7_TYPELESS:
+    //case DXGI_FORMAT_BC7_UNORM:
+    //case DXGI_FORMAT_BC7_UNORM_SRGB:
+    default: break;
+    }
+    return errorType;
+#endif
+}
+
+int getTypeFromD3DFORMAT(const int iD3DFORMAT)
+{
+    (void)iD3DFORMAT;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#else
+    const int errorType = -1;
+    switch ((enum _D3DFORMAT)iD3DFORMAT)
+    {
+    //case D3DFMT_UNKNOWN:
+    case D3DFMT_R8G8B8: return CV_8UC3;
+    case D3DFMT_A8R8G8B8:
+    case D3DFMT_X8R8G8B8: return CV_8UC4;
+    //case D3DFMT_R5G6B5:
+    //case D3DFMT_X1R5G5B5:
+    //case D3DFMT_A1R5G5B5:
+    //case D3DFMT_A4R4G4B4:
+    //case D3DFMT_R3G3B2:
+    case D3DFMT_A8: return CV_8UC1;
+    //case D3DFMT_A8R3G3B2:
+    //case D3DFMT_X4R4G4B4:
+    //case D3DFMT_A2B10G10R10:
+    case D3DFMT_A8B8G8R8:
+    case D3DFMT_X8B8G8R8: return CV_8UC4;
+    //case D3DFMT_G16R16:
+    //case D3DFMT_A2R10G10B10:
+    //case D3DFMT_A16B16G16R16:
+
+    case D3DFMT_A8P8: return CV_8UC2;
+    case D3DFMT_P8: return CV_8UC1;
+
+    case D3DFMT_L8: return CV_8UC1;
+    case D3DFMT_A8L8: return CV_8UC2;
+    //case D3DFMT_A4L4:
+
+    case D3DFMT_V8U8: return CV_8UC2;
+    //case D3DFMT_L6V5U5:
+    case D3DFMT_X8L8V8U8:
+    case D3DFMT_Q8W8V8U8: return CV_8UC4;
+    case D3DFMT_V16U16: return CV_16UC4; // TODO 16SC4 ?
+    //case D3DFMT_A2W10V10U10:
+
+    case D3DFMT_D16_LOCKABLE: return CV_16UC1;
+    case D3DFMT_D32: return CV_32SC1;
+    //case D3DFMT_D15S1:
+    //case D3DFMT_D24S8:
+    //case D3DFMT_D24X8:
+    //case D3DFMT_D24X4S4:
+    case D3DFMT_D16: return CV_16UC1;
+
+    case D3DFMT_D32F_LOCKABLE: return CV_32FC1;
+    default: break;
+    }
+    return errorType;
+#endif
+}
+
+namespace ocl {
+
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+static bool g_isDirect3DDevice9Ex = false; // Direct3DDevice9Ex or Direct3DDevice9 was used
+#endif
+
+Context2& initializeContextFromD3D11Device(ID3D11Device* pD3D11Device)
+{
+    (void)pD3D11Device;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
+    NO_OPENCL_SUPPORT_ERROR;
+#else
+    cl_uint numPlatforms;
+    cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+    if (numPlatforms == 0)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
+
+    std::vector<cl_platform_id> platforms(numPlatforms);
+    status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+
+    // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
+
+    int found = -1;
+    cl_device_id device = NULL;
+    cl_uint numDevices = 0;
+    cl_context context = NULL;
+
+    // try with CL_PREFERRED_DEVICES_FOR_D3D11_KHR
+    for (int i = 0; i < (int)numPlatforms; i++)
+    {
+        clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
+        if (!clGetDeviceIDsFromD3D11KHR)
+            continue;
+
+        device = NULL;
+        numDevices = 0;
+        status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
+                CL_PREFERRED_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
+        if (status != CL_SUCCESS)
+            continue;
+        if (numDevices > 0)
+        {
+            cl_context_properties properties[] = {
+                    CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                    CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
+                    CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                    NULL, NULL
+            };
+            context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+            if (status != CL_SUCCESS)
+            {
+                clReleaseDevice(device);
+            }
+            else
+            {
+                found = i;
+                break;
+            }
+        }
+    }
+    if (found < 0)
+    {
+        // try with CL_ALL_DEVICES_FOR_D3D11_KHR
+        for (int i = 0; i < (int)numPlatforms; i++)
+        {
+            clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
+                    clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
+            if (!clGetDeviceIDsFromD3D11KHR)
+                continue;
+
+            device = NULL;
+            numDevices = 0;
+            status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
+                    CL_ALL_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
+            if (status != CL_SUCCESS)
+                continue;
+            if (numDevices > 0)
+            {
+                cl_context_properties properties[] = {
+                        CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                        CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
+                        CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                        NULL, NULL
+                };
+                context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+                if (status != CL_SUCCESS)
+                {
+                    clReleaseDevice(device);
+                }
+                else
+                {
+                    found = i;
+                    break;
+                }
+            }
+        }
+        if (found < 0)
+            CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+    }
+
+
+    Context2& ctx = Context2::getDefault(false);
+    initializeContextFromHandle(ctx, platforms[found], context, device);
+    return ctx;
+#endif
+}
+
+Context2& initializeContextFromD3D10Device(ID3D10Device* pD3D10Device)
+{
+    (void)pD3D10Device;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
+    NO_OPENCL_SUPPORT_ERROR;
+#else
+    cl_uint numPlatforms;
+    cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+    if (numPlatforms == 0)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
+
+    std::vector<cl_platform_id> platforms(numPlatforms);
+    status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+
+    // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
+
+    int found = -1;
+    cl_device_id device = NULL;
+    cl_uint numDevices = 0;
+    cl_context context = NULL;
+
+    // try with CL_PREFERRED_DEVICES_FOR_D3D10_KHR
+    for (int i = 0; i < (int)numPlatforms; i++)
+    {
+        clGetDeviceIDsFromD3D10KHR_fn clGetDeviceIDsFromD3D10KHR = (clGetDeviceIDsFromD3D10KHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D10KHR");
+        if (!clGetDeviceIDsFromD3D10KHR)
+            continue;
+
+        device = NULL;
+        numDevices = 0;
+        status = clGetDeviceIDsFromD3D10KHR(platforms[i], CL_D3D10_DEVICE_KHR, pD3D10Device,
+                CL_PREFERRED_DEVICES_FOR_D3D10_KHR, 1, &device, &numDevices);
+        if (status != CL_SUCCESS)
+            continue;
+        if (numDevices > 0)
+        {
+            cl_context_properties properties[] = {
+                    CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                    CL_CONTEXT_D3D10_DEVICE_KHR, (cl_context_properties)(pD3D10Device),
+                    CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                    NULL, NULL
+            };
+            context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+            if (status != CL_SUCCESS)
+            {
+                clReleaseDevice(device);
+            }
+            else
+            {
+                found = i;
+                break;
+            }
+        }
+    }
+    if (found < 0)
+    {
+        // try with CL_ALL_DEVICES_FOR_D3D10_KHR
+        for (int i = 0; i < (int)numPlatforms; i++)
+        {
+            clGetDeviceIDsFromD3D10KHR_fn clGetDeviceIDsFromD3D10KHR = (clGetDeviceIDsFromD3D10KHR_fn)
+                    clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D10KHR");
+            if (!clGetDeviceIDsFromD3D10KHR)
+                continue;
+
+            device = NULL;
+            numDevices = 0;
+            status = clGetDeviceIDsFromD3D10KHR(platforms[i], CL_D3D10_DEVICE_KHR, pD3D10Device,
+                    CL_ALL_DEVICES_FOR_D3D10_KHR, 1, &device, &numDevices);
+            if (status != CL_SUCCESS)
+                continue;
+            if (numDevices > 0)
+            {
+                cl_context_properties properties[] = {
+                        CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                        CL_CONTEXT_D3D10_DEVICE_KHR, (cl_context_properties)(pD3D10Device),
+                        CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                        NULL, NULL
+                };
+                context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+                if (status != CL_SUCCESS)
+                {
+                    clReleaseDevice(device);
+                }
+                else
+                {
+                    found = i;
+                    break;
+                }
+            }
+        }
+        if (found < 0)
+            CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+    }
+
+
+    Context2& ctx = Context2::getDefault(false);
+    initializeContextFromHandle(ctx, platforms[found], context, device);
+    return ctx;
+#endif
+}
+
+Context2& initializeContextFromDirect3DDevice9Ex(IDirect3DDevice9Ex* pDirect3DDevice9Ex)
+{
+    (void)pDirect3DDevice9Ex;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
+    NO_OPENCL_SUPPORT_ERROR;
+#else
+    cl_uint numPlatforms;
+    cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+    if (numPlatforms == 0)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
+
+    std::vector<cl_platform_id> platforms(numPlatforms);
+    status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+
+    // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
+
+    int found = -1;
+    cl_device_id device = NULL;
+    cl_uint numDevices = 0;
+    cl_context context = NULL;
+
+    // try with CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
+    for (int i = 0; i < (int)numPlatforms; i++)
+    {
+        clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
+        if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
+            continue;
+
+        device = NULL;
+        numDevices = 0;
+        cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9EX_KHR;
+        status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9Ex,
+                CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
+        if (status != CL_SUCCESS)
+            continue;
+        if (numDevices > 0)
+        {
+            cl_context_properties properties[] = {
+                    CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                    CL_CONTEXT_ADAPTER_D3D9EX_KHR, (cl_context_properties)(pDirect3DDevice9Ex),
+                    CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                    NULL, NULL
+            };
+            context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+            if (status != CL_SUCCESS)
+            {
+                clReleaseDevice(device);
+            }
+            else
+            {
+                found = i;
+                break;
+            }
+        }
+    }
+    if (found < 0)
+    {
+        // try with CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
+        for (int i = 0; i < (int)numPlatforms; i++)
+        {
+            clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
+                    clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
+            if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
+                continue;
+
+            device = NULL;
+            numDevices = 0;
+            cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9EX_KHR;
+            status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9Ex,
+                    CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
+            if (status != CL_SUCCESS)
+                continue;
+            if (numDevices > 0)
+            {
+                cl_context_properties properties[] = {
+                        CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                        CL_CONTEXT_ADAPTER_D3D9EX_KHR, (cl_context_properties)(pDirect3DDevice9Ex),
+                        CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                        NULL, NULL
+                };
+                context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+                if (status != CL_SUCCESS)
+                {
+                    clReleaseDevice(device);
+                }
+                else
+                {
+                    found = i;
+                    break;
+                }
+            }
+        }
+        if (found < 0)
+            CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+    }
+
+    Context2& ctx = Context2::getDefault(false);
+    initializeContextFromHandle(ctx, platforms[found], context, device);
+    g_isDirect3DDevice9Ex = true;
+    return ctx;
+#endif
+}
+
+Context2& initializeContextFromDirect3DDevice9(IDirect3DDevice9* pDirect3DDevice9)
+{
+    (void)pDirect3DDevice9;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
+    NO_OPENCL_SUPPORT_ERROR;
+#else
+    cl_uint numPlatforms;
+    cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+    if (numPlatforms == 0)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
+
+    std::vector<cl_platform_id> platforms(numPlatforms);
+    status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+
+    // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
+
+    int found = -1;
+    cl_device_id device = NULL;
+    cl_uint numDevices = 0;
+    cl_context context = NULL;
+
+    // try with CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
+    for (int i = 0; i < (int)numPlatforms; i++)
+    {
+        clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
+        if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
+            continue;
+
+        device = NULL;
+        numDevices = 0;
+        cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9_KHR;
+        status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9,
+                CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
+        if (status != CL_SUCCESS)
+            continue;
+        if (numDevices > 0)
+        {
+            cl_context_properties properties[] = {
+                    CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                    CL_CONTEXT_ADAPTER_D3D9_KHR, (cl_context_properties)(pDirect3DDevice9),
+                    CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                    NULL, NULL
+            };
+            context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+            if (status != CL_SUCCESS)
+            {
+                clReleaseDevice(device);
+            }
+            else
+            {
+                found = i;
+                break;
+            }
+        }
+    }
+    if (found < 0)
+    {
+        // try with CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
+        for (int i = 0; i < (int)numPlatforms; i++)
+        {
+            clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
+                    clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
+            if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
+                continue;
+
+            device = NULL;
+            numDevices = 0;
+            cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9_KHR;
+            status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9,
+                    CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
+            if (status != CL_SUCCESS)
+                continue;
+            if (numDevices > 0)
+            {
+                cl_context_properties properties[] = {
+                        CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                        CL_CONTEXT_ADAPTER_D3D9_KHR, (cl_context_properties)(pDirect3DDevice9),
+                        CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                        NULL, NULL
+                };
+                context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+                if (status != CL_SUCCESS)
+                {
+                    clReleaseDevice(device);
+                }
+                else
+                {
+                    found = i;
+                    break;
+                }
+            }
+        }
+        if (found < 0)
+            CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+    }
+
+    Context2& ctx = Context2::getDefault(false);
+    initializeContextFromHandle(ctx, platforms[found], context, device);
+    g_isDirect3DDevice9Ex = false;
+    return ctx;
+#endif
+}
+
+} // namespace cv::ocl
+
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+clCreateFromD3D11Texture2DKHR_fn clCreateFromD3D11Texture2DKHR = NULL;
+clEnqueueAcquireD3D11ObjectsKHR_fn clEnqueueAcquireD3D11ObjectsKHR = NULL;
+clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11ObjectsKHR = NULL;
+
+static void __OpenCLinitializeD3D11()
+{
+    using namespace cv::ocl;
+    static cl_platform_id initializedPlatform = NULL;
+    cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
+    if (initializedPlatform != platform)
+    {
+        clCreateFromD3D11Texture2DKHR = (clCreateFromD3D11Texture2DKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D11Texture2DKHR");
+        clEnqueueAcquireD3D11ObjectsKHR = (clEnqueueAcquireD3D11ObjectsKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D11ObjectsKHR");
+        clEnqueueReleaseD3D11ObjectsKHR = (clEnqueueReleaseD3D11ObjectsKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D11ObjectsKHR");
+        initializedPlatform = platform;
+    }
+    if (!clCreateFromD3D11Texture2DKHR || !clEnqueueAcquireD3D11ObjectsKHR || !clEnqueueReleaseD3D11ObjectsKHR)
+    {
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D11");
+    }
+}
+#endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+
+void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
+{
+    (void)src; (void)pD3D11Texture2D;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D11();
+
+    D3D11_TEXTURE2D_DESC desc = { 0 };
+    pD3D11Texture2D->GetDesc(&desc);
+
+    int srcType = src.type();
+    int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+    CV_Assert(textureType == srcType);
+
+    Size srcSize = src.size();
+    CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    UMat u = src.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_mem clImage = clCreateFromD3D11Texture2DKHR(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed");
+    size_t offset = 0; // TODO
+    size_t dst_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
+    status = clEnqueueReleaseD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO memcpy
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
+{
+    (void)pD3D11Texture2D; (void)dst;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D11();
+
+    D3D11_TEXTURE2D_DESC desc = { 0 };
+    pD3D11Texture2D->GetDesc(&desc);
+
+    int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+    CV_Assert(textureType >= 0);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
+    dst.create(Size(desc.Width, desc.Height), textureType);
+    UMat u = dst.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_mem clImage = clCreateFromD3D11Texture2DKHR(context, CL_MEM_READ_ONLY, pD3D11Texture2D, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed");
+    size_t offset = 0; // TODO
+    size_t src_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
+    status = clEnqueueReleaseD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO memcpy
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+clCreateFromD3D10Texture2DKHR_fn clCreateFromD3D10Texture2DKHR = NULL;
+clEnqueueAcquireD3D10ObjectsKHR_fn clEnqueueAcquireD3D10ObjectsKHR = NULL;
+clEnqueueReleaseD3D10ObjectsKHR_fn clEnqueueReleaseD3D10ObjectsKHR = NULL;
+
+static void __OpenCLinitializeD3D10()
+{
+    using namespace cv::ocl;
+    static cl_platform_id initializedPlatform = NULL;
+    cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
+    if (initializedPlatform != platform)
+    {
+        clCreateFromD3D10Texture2DKHR = (clCreateFromD3D10Texture2DKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D10Texture2DKHR");
+        clEnqueueAcquireD3D10ObjectsKHR = (clEnqueueAcquireD3D10ObjectsKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D10ObjectsKHR");
+        clEnqueueReleaseD3D10ObjectsKHR = (clEnqueueReleaseD3D10ObjectsKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D10ObjectsKHR");
+        initializedPlatform = platform;
+    }
+    if (!clCreateFromD3D10Texture2DKHR || !clEnqueueAcquireD3D10ObjectsKHR || !clEnqueueReleaseD3D10ObjectsKHR)
+    {
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D10");
+    }
+}
+#endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+
+void convertToD3D10Texture2D(InputArray src, ID3D10Texture2D* pD3D10Texture2D)
+{
+    (void)src; (void)pD3D10Texture2D;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D10();
+
+    D3D10_TEXTURE2D_DESC desc = { 0 };
+    pD3D10Texture2D->GetDesc(&desc);
+
+    int srcType = src.type();
+    int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+    CV_Assert(textureType == srcType);
+
+    Size srcSize = src.size();
+    CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    UMat u = src.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_mem clImage = clCreateFromD3D10Texture2DKHR(context, CL_MEM_WRITE_ONLY, pD3D10Texture2D, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D10Texture2DKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed");
+    size_t offset = 0; // TODO
+    size_t dst_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
+    status = clEnqueueReleaseD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D10ObjectsKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO memcpy
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+void convertFromD3D10Texture2D(ID3D10Texture2D* pD3D10Texture2D, OutputArray dst)
+{
+    (void)pD3D10Texture2D; (void)dst;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D10();
+
+    D3D10_TEXTURE2D_DESC desc = { 0 };
+    pD3D10Texture2D->GetDesc(&desc);
+
+    int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+    CV_Assert(textureType >= 0);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
+    dst.create(Size(desc.Width, desc.Height), textureType);
+    UMat u = dst.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_mem clImage = clCreateFromD3D10Texture2DKHR(context, CL_MEM_READ_ONLY, pD3D10Texture2D, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D10Texture2DKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed");
+    size_t offset = 0; // TODO
+    size_t src_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
+    status = clEnqueueReleaseD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D10ObjectsKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO memcpy
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+clCreateFromDX9MediaSurfaceKHR_fn clCreateFromDX9MediaSurfaceKHR = NULL;
+clEnqueueAcquireDX9MediaSurfacesKHR_fn clEnqueueAcquireDX9MediaSurfacesKHR = NULL;
+clEnqueueReleaseDX9MediaSurfacesKHR_fn clEnqueueReleaseDX9MediaSurfacesKHR = NULL;
+
+static void __OpenCLinitializeD3D9()
+{
+    using namespace cv::ocl;
+    static cl_platform_id initializedPlatform = NULL;
+    cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
+    if (initializedPlatform != platform)
+    {
+        clCreateFromDX9MediaSurfaceKHR = (clCreateFromDX9MediaSurfaceKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromDX9MediaSurfaceKHR");
+        clEnqueueAcquireDX9MediaSurfacesKHR = (clEnqueueAcquireDX9MediaSurfacesKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireDX9MediaSurfacesKHR");
+        clEnqueueReleaseDX9MediaSurfacesKHR = (clEnqueueReleaseDX9MediaSurfacesKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseDX9MediaSurfacesKHR");
+        initializedPlatform = platform;
+    }
+    if (!clCreateFromDX9MediaSurfaceKHR || !clEnqueueAcquireDX9MediaSurfacesKHR || !clEnqueueReleaseDX9MediaSurfacesKHR)
+    {
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D9");
+    }
+}
+#endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+
+void convertToDirect3DSurface9(InputArray src, IDirect3DSurface9* pDirect3DSurface9, void* surfaceSharedHandle)
+{
+    (void)src; (void)pDirect3DSurface9; (void)surfaceSharedHandle;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D9();
+
+    D3DSURFACE_DESC desc;
+    if (FAILED(pDirect3DSurface9->GetDesc(&desc)))
+    {
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: Can't get D3D surface description");
+    }
+
+    int srcType = src.type();
+    int surfaceType = getTypeFromD3DFORMAT(desc.Format);
+    CV_Assert(surfaceType == srcType);
+
+    Size srcSize = src.size();
+    CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    UMat u = src.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_dx9_surface_info_khr surfaceInfo = {pDirect3DSurface9, (HANDLE)surfaceSharedHandle};
+    cl_mem clImage = clCreateFromDX9MediaSurfaceKHR(context, CL_MEM_WRITE_ONLY,
+            ocl::g_isDirect3DDevice9Ex ? CL_ADAPTER_D3D9EX_KHR : CL_ADAPTER_D3D9_KHR,
+            &surfaceInfo, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromDX9MediaSurfaceKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed");
+    size_t offset = 0; // TODO
+    size_t dst_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
+    status = clEnqueueReleaseDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseDX9MediaSurfacesKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO pDirect3DSurface9->LockRect() + memcpy + Unlock()
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+
+void convertFromDirect3DSurface9(IDirect3DSurface9* pDirect3DSurface9, OutputArray dst, void* surfaceSharedHandle)
+{
+    (void)pDirect3DSurface9; (void)dst; (void)surfaceSharedHandle;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D9();
+
+    D3DSURFACE_DESC desc;
+    if (FAILED(pDirect3DSurface9->GetDesc(&desc)))
+    {
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: Can't get D3D surface description");
+    }
+
+    int surfaceType = getTypeFromD3DFORMAT(desc.Format);
+    CV_Assert(surfaceType >= 0);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
+    dst.create(Size(desc.Width, desc.Height), surfaceType);
+    UMat u = dst.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_dx9_surface_info_khr surfaceInfo = {pDirect3DSurface9, (HANDLE)surfaceSharedHandle};
+    cl_mem clImage = clCreateFromDX9MediaSurfaceKHR(context, CL_MEM_READ_ONLY,
+            ocl::g_isDirect3DDevice9Ex ? CL_ADAPTER_D3D9EX_KHR : CL_ADAPTER_D3D9_KHR,
+            &surfaceInfo, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromDX9MediaSurfaceKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_WRITE);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed");
+    size_t offset = 0; // TODO
+    size_t src_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
+    status = clEnqueueReleaseDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseDX9MediaSurfacesKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO pDirect3DSurface9->LockRect() + memcpy + Unlock()
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+
+} } // namespace cv::directx
diff --git a/modules/core/src/directx.inc.hpp b/modules/core/src/directx.inc.hpp
new file mode 100644 (file)
index 0000000..a8e7a17
--- /dev/null
@@ -0,0 +1,55 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors as is and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the copyright holders or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#if defined(HAVE_DIRECTX)
+#include <d3d11.h>
+#include <d3d10.h>
+#include <d3d9.h>
+
+#ifdef HAVE_OPENCL
+#include "opencv2/core/opencl/runtime/opencl_core.hpp"
+
+#include <CL/cl_d3d11.h>
+#include <CL/cl_d3d10.h>
+#include <CL/cl_dx9_media_sharing.h>
+#endif // HAVE_OPENCL
+
+#endif // HAVE_DIRECTX
index 6681e81..f56482b 100644 (file)
@@ -1363,21 +1363,6 @@ void finish2()
     void release() { if( CV_XADD(&refcount, -1) == 1 ) delete this; } \
     int refcount
 
-class Platform
-{
-public:
-    Platform();
-    ~Platform();
-    Platform(const Platform& p);
-    Platform& operator = (const Platform& p);
-
-    void* ptr() const;
-    static Platform& getDefault();
-protected:
-    struct Impl;
-    Impl* p;
-};
-
 struct Platform::Impl
 {
     Impl()
@@ -1773,6 +1758,12 @@ const Device& Device::getDefault()
 
 struct Context2::Impl
 {
+    Impl()
+    {
+        refcount = 1;
+        handle = 0;
+    }
+
     Impl(int dtype0)
     {
         refcount = 1;
@@ -1855,7 +1846,6 @@ struct Context2::Impl
 
     cl_context handle;
     std::vector<Device> devices;
-    bool initialized;
 
     typedef ProgramSource2::hash_t hash_t;
 
@@ -1937,22 +1927,29 @@ const Device& Context2::device(size_t idx) const
     return !p || idx >= p->devices.size() ? dummy : p->devices[idx];
 }
 
-Context2& Context2::getDefault()
+Context2& Context2::getDefault(bool initialize)
 {
     static Context2 ctx;
-    if( !ctx.p && haveOpenCL() )
-    {
-        // do not create new Context2 right away.
-        // First, try to retrieve existing context of the same type.
-        // In its turn, Platform::getContext() may call Context2::create()
-        // if there is no such context.
-        ctx.create(Device::TYPE_ACCELERATOR);
-        if(!ctx.p)
-            ctx.create(Device::TYPE_DGPU);
-        if(!ctx.p)
-            ctx.create(Device::TYPE_IGPU);
-        if(!ctx.p)
-            ctx.create(Device::TYPE_CPU);
+    if(!ctx.p && haveOpenCL())
+    {
+        if (initialize)
+        {
+            // do not create new Context2 right away.
+            // First, try to retrieve existing context of the same type.
+            // In its turn, Platform::getContext() may call Context2::create()
+            // if there is no such context.
+            ctx.create(Device::TYPE_ACCELERATOR);
+            if(!ctx.p)
+                ctx.create(Device::TYPE_DGPU);
+            if(!ctx.p)
+                ctx.create(Device::TYPE_IGPU);
+            if(!ctx.p)
+                ctx.create(Device::TYPE_CPU);
+        }
+        else
+        {
+            ctx.p = new Impl();
+        }
     }
 
     return ctx;
@@ -1964,6 +1961,30 @@ Program Context2::getProg(const ProgramSource2& prog,
     return p ? p->getProg(prog, buildopts, errmsg) : Program();
 }
 
+void initializeContextFromHandle(Context2& ctx, void* platform, void* _context, void* _device)
+{
+    cl_context context = (cl_context)_context;
+    cl_device_id device = (cl_device_id)_device;
+
+    // cleanup old context
+    Context2::Impl* impl = ctx._getImpl();
+    if (impl->handle)
+    {
+        cl_int status = clReleaseContext(impl->handle);
+        (void)status;
+    }
+    impl->devices.clear();
+
+    impl->handle = context;
+    impl->devices.resize(1);
+    impl->devices[0].set(device);
+
+    Platform& p = Platform::getDefault();
+    Platform::Impl* pImpl = p._getImpl();
+    pImpl->handle = (cl_platform_id)platform;
+}
+
+
 struct Queue::Impl
 {
     Impl(const Context2& c, const Device& d)
index 47d6fdc..a6a39fa 100644 (file)
@@ -43,6 +43,9 @@
 #ifndef __OPENCV_PRECOMP_H__
 #define __OPENCV_PRECOMP_H__
 
+#include "opencv2/opencv_modules.hpp"
+#include "cvconfig.h"
+
 #include "opencv2/core/utility.hpp"
 #include "opencv2/core/core_c.h"
 #include "opencv2/core/cuda.hpp"
index 48a419d..9dd3df0 100644 (file)
@@ -15,6 +15,10 @@ add_subdirectory(cpp)
 add_subdirectory(gpu)
 add_subdirectory(ocl)
 
+if(WIN32 AND HAVE_DIRECTX)
+  add_subdirectory(directx)
+endif()
+
 if(ANDROID AND BUILD_ANDROID_EXAMPLES)
   add_subdirectory(android)
 endif()
@@ -62,6 +66,10 @@ add_subdirectory(cpp)
 add_subdirectory(ocl)
 # FIXIT: can't use cvconfig.h in samples: add_subdirectory(gpu)
 
+if(WIN32)
+  add_subdirectory(directx)
+endif()
+
 #
 # END OF BUILD CASE 2: Build samples with library binaries
 #
diff --git a/samples/directx/CMakeLists.txt b/samples/directx/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0bd7de9
--- /dev/null
@@ -0,0 +1,45 @@
+SET(OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_highgui)
+
+ocv_check_dependencies(${OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS})
+
+if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
+  set(project "directx")
+  string(TOUPPER "${project}" project_upper)
+
+  project("${project}_samples")
+
+  ocv_include_modules(${OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS})
+
+  # ---------------------------------------------
+  #      Define executable targets
+  # ---------------------------------------------
+  MACRO(OPENCV_DEFINE_DIRECTX_EXAMPLE name srcs)
+    set(the_target "example_${project}_${name}")
+    add_executable(${the_target} ${srcs})
+
+    target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS})
+
+    set_target_properties(${the_target} PROPERTIES
+      OUTPUT_NAME "${project}-example-${name}"
+      PROJECT_LABEL "(EXAMPLE_${project_upper}) ${name}")
+
+    if(ENABLE_SOLUTION_FOLDERS)
+      set_target_properties(${the_target} PROPERTIES FOLDER "samples//${project}")
+    endif()
+
+    if(WIN32)
+      if(MSVC AND NOT BUILD_SHARED_LIBS)
+        set_target_properties(${the_target} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG")
+      endif()
+      install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${project}" COMPONENT main)
+    endif()
+  ENDMACRO()
+
+  file(GLOB all_samples RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
+
+  foreach(sample_filename ${all_samples})
+    get_filename_component(sample ${sample_filename} NAME_WE)
+    file(GLOB sample_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${sample}.*)
+    OPENCV_DEFINE_DIRECTX_EXAMPLE(${sample} ${sample_srcs})
+  endforeach()
+endif()
diff --git a/samples/directx/d3d10_interop.cpp b/samples/directx/d3d10_interop.cpp
new file mode 100644 (file)
index 0000000..a9eccdf
--- /dev/null
@@ -0,0 +1,138 @@
+#include <windows.h>
+#include <d3d10.h>
+#pragma comment (lib, "d3d10.lib")
+
+#define USE_D3D10
+#define WINDOW_NAME "OpenCV Direct3D 10 Sample"
+
+IDXGISwapChain *swapchain = NULL;
+ID3D10Device *dev = NULL;
+ID3D10Texture2D *pBackBufferTexture = NULL;
+ID3D10Texture2D *pCPUWriteTexture = NULL;
+ID3D10Texture2D *pInputTexture = NULL;
+ID3D10RenderTargetView *backbuffer = NULL;
+
+#include "d3d_base.inl.hpp"
+
+bool initDirect3D()
+{
+    DXGI_SWAP_CHAIN_DESC scd;
+
+    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
+
+    scd.BufferCount = 1;                                    // one back buffer
+    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
+    scd.BufferDesc.Width = WIDTH;                    // set the back buffer width
+    scd.BufferDesc.Height = HEIGHT;                  // set the back buffer height
+    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
+    scd.OutputWindow = hWnd;                                // the window to be used
+    scd.SampleDesc.Count = 1;                               // how many multisamples
+    scd.Windowed = TRUE;                                    // windowed/full-screen mode
+    scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;     // allow full-screen switching
+
+    if (FAILED(D3D10CreateDeviceAndSwapChain(
+            NULL,
+            D3D10_DRIVER_TYPE_HARDWARE,
+            NULL,
+            0,
+            D3D10_SDK_VERSION,
+            &scd,
+            &swapchain,
+            &dev)))
+    {
+        return false;
+    }
+
+    if (FAILED(swapchain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBufferTexture)))
+    {
+        return false;
+    }
+
+    if (FAILED(dev->CreateRenderTargetView(pBackBufferTexture, NULL, &backbuffer)))
+    {
+        return false;
+    }
+
+    dev->OMSetRenderTargets(1, &backbuffer, NULL);
+
+    D3D10_VIEWPORT viewport;
+    ZeroMemory(&viewport, sizeof(D3D10_VIEWPORT));
+    viewport.Width = WIDTH;
+    viewport.Height = HEIGHT;
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 0.0f;
+    dev->RSSetViewports(1, &viewport);
+
+    return true;
+}
+
+bool initDirect3DTextures()
+{
+    { // Create texture for demo 0
+        D3D10_TEXTURE2D_DESC desc = { 0 };
+        desc.Width = WIDTH;
+        desc.Height = HEIGHT;
+        desc.MipLevels = desc.ArraySize = 1;
+        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+        desc.SampleDesc.Count = 1;
+        desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
+        desc.Usage = D3D10_USAGE_DYNAMIC;
+        desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
+        if (FAILED(dev->CreateTexture2D(&desc, NULL, &pCPUWriteTexture)))
+        {
+            std::cerr << "Can't create texture for CPU write sample" << std::endl;
+            return false;
+        }
+    }
+
+    { // Create Read-only texture
+        cv::Mat inputMat = getInputTexture();
+
+        D3D10_TEXTURE2D_DESC desc = { 0 };
+        desc.Width = inputMat.size().width;
+        desc.Height = inputMat.size().height;
+        desc.MipLevels = desc.ArraySize = 1;
+        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+        desc.SampleDesc.Count = 1;
+        desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
+        desc.Usage = D3D10_USAGE_IMMUTABLE;
+        desc.CPUAccessFlags = cv::ocl::useOpenCL() ? 0 : D3D10_CPU_ACCESS_READ;
+
+        D3D10_SUBRESOURCE_DATA srInitData;
+        srInitData.pSysMem = inputMat.data;
+        srInitData.SysMemPitch = (UINT)inputMat.step[0];
+
+        if (FAILED(dev->CreateTexture2D(&desc, &srInitData, &pInputTexture)))
+        {
+            std::cerr << "Can't create texture with input image" << std::endl;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void cleanUp(void)
+{
+    if (swapchain) swapchain->SetFullscreenState(FALSE, NULL);    // switch to windowed mode
+
+    SAFE_RELEASE(swapchain);
+    SAFE_RELEASE(pCPUWriteTexture);
+    SAFE_RELEASE(pInputTexture);
+    SAFE_RELEASE(pBackBufferTexture);
+    SAFE_RELEASE(backbuffer);
+    SAFE_RELEASE(dev);
+}
+
+
+void render(void)
+{
+    // check to make sure you have a valid Direct3D device
+    CV_Assert(dev);
+
+    renderToD3DObject();
+
+    // switch the back buffer and the front buffer
+    swapchain->Present(0, 0);
+}
diff --git a/samples/directx/d3d11_interop.cpp b/samples/directx/d3d11_interop.cpp
new file mode 100644 (file)
index 0000000..9db9c31
--- /dev/null
@@ -0,0 +1,143 @@
+#include <windows.h>
+#include <d3d11.h>
+#pragma comment (lib, "d3d11.lib")
+
+#define USE_D3D11
+#define WINDOW_NAME "OpenCV Direct3D 11 Sample"
+
+IDXGISwapChain *swapchain = NULL;
+ID3D11Device *dev = NULL;
+ID3D11DeviceContext *devcon = NULL;
+ID3D11Texture2D *pBackBufferTexture = NULL;
+ID3D11Texture2D *pCPUWriteTexture = NULL;
+ID3D11Texture2D *pInputTexture = NULL;
+ID3D11RenderTargetView *backbuffer = NULL;
+
+#include "d3d_base.inl.hpp"
+
+bool initDirect3D()
+{
+    DXGI_SWAP_CHAIN_DESC scd;
+
+    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
+
+    scd.BufferCount = 1;                                    // one back buffer
+    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
+    scd.BufferDesc.Width = WIDTH;                    // set the back buffer width
+    scd.BufferDesc.Height = HEIGHT;                  // set the back buffer height
+    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
+    scd.OutputWindow = hWnd;                                // the window to be used
+    scd.SampleDesc.Count = 1;                               // how many multisamples
+    scd.Windowed = TRUE;                                    // windowed/full-screen mode
+    scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;     // allow full-screen switching
+
+    if (FAILED(D3D11CreateDeviceAndSwapChain(
+            NULL,
+            D3D_DRIVER_TYPE_HARDWARE,
+            NULL,
+            0,
+            NULL,
+            0,
+            D3D11_SDK_VERSION,
+            &scd,
+            &swapchain,
+            &dev,
+            NULL,
+            &devcon)))
+    {
+        return false;
+    }
+
+    if (FAILED(swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBufferTexture)))
+    {
+        return false;
+    }
+
+    if (FAILED(dev->CreateRenderTargetView(pBackBufferTexture, NULL, &backbuffer)))
+    {
+        return false;
+    }
+
+    devcon->OMSetRenderTargets(1, &backbuffer, NULL);
+
+    D3D11_VIEWPORT viewport = { 0 };
+    viewport.Width = WIDTH;
+    viewport.Height = HEIGHT;
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 0.0f;
+    devcon->RSSetViewports(1, &viewport);
+
+    return true;
+}
+
+bool initDirect3DTextures()
+{
+    { // Create texture for demo 0
+        D3D11_TEXTURE2D_DESC desc = { 0 };
+        desc.Width = WIDTH;
+        desc.Height = HEIGHT;
+        desc.MipLevels = desc.ArraySize = 1;
+        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+        desc.SampleDesc.Count = 1;
+        desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+        desc.Usage = D3D11_USAGE_DYNAMIC;
+        desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+        if (FAILED(dev->CreateTexture2D(&desc, NULL, &pCPUWriteTexture)))
+        {
+            std::cerr << "Can't create texture for CPU write sample" << std::endl;
+            return false;
+        }
+    }
+
+    { // Create Read-only texture
+        cv::Mat inputMat = getInputTexture();
+
+        D3D11_TEXTURE2D_DESC desc = { 0 };
+        desc.Width = inputMat.size().width;
+        desc.Height = inputMat.size().height;
+        desc.MipLevels = desc.ArraySize = 1;
+        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+        desc.SampleDesc.Count = 1;
+        desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+        desc.Usage = D3D11_USAGE_IMMUTABLE;
+        desc.CPUAccessFlags = cv::ocl::useOpenCL() ? 0 : D3D11_CPU_ACCESS_READ;
+
+        D3D11_SUBRESOURCE_DATA srInitData;
+        srInitData.pSysMem = inputMat.data;
+        srInitData.SysMemPitch = (UINT)inputMat.step[0];
+
+        if (FAILED(dev->CreateTexture2D(&desc, &srInitData, &pInputTexture)))
+        {
+            std::cerr << "Can't create texture with input image" << std::endl;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void cleanUp(void)
+{
+    if (swapchain) swapchain->SetFullscreenState(FALSE, NULL);    // switch to windowed mode
+
+    SAFE_RELEASE(swapchain);
+    SAFE_RELEASE(pCPUWriteTexture);
+    SAFE_RELEASE(pInputTexture);
+    SAFE_RELEASE(pBackBufferTexture);
+    SAFE_RELEASE(backbuffer);
+    SAFE_RELEASE(dev);
+    SAFE_RELEASE(devcon);
+}
+
+
+void render(void)
+{
+    // check to make sure you have a valid Direct3D device
+    CV_Assert(dev);
+
+    renderToD3DObject();
+
+    // switch the back buffer and the front buffer
+    swapchain->Present(0, 0);
+}
diff --git a/samples/directx/d3d9_interop.cpp b/samples/directx/d3d9_interop.cpp
new file mode 100644 (file)
index 0000000..fc9bdbd
--- /dev/null
@@ -0,0 +1,149 @@
+#include <windows.h>
+#include <d3d9.h>
+#pragma comment (lib, "d3d9.lib")
+
+#define USE_D3D9
+#define WINDOW_NAME "OpenCV Direct3D 9 Sample"
+
+IDirect3D9 *pD3D = NULL;
+IDirect3DDevice9 *dev = NULL;
+IDirect3DSurface9 *pBackBuffer = NULL;
+IDirect3DSurface9 *pCPUWriteSurface = NULL; // required name
+IDirect3DSurface9 *pReadOnlySurface = NULL; // required name
+HANDLE readOnlySurfaceShared = 0; // required name
+IDirect3DSurface9 *pSurface = NULL; // required name
+HANDLE surfaceShared = 0; // required name
+
+#include "d3d_base.inl.hpp"
+
+bool initDirect3D(void)
+{
+    if (NULL == (pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
+    {
+        return false;
+    }
+
+    D3DPRESENT_PARAMETERS d3dpp;
+    ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
+
+    DWORD flags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE | D3DCREATE_NOWINDOWCHANGES
+            | D3DCREATE_MULTITHREADED;
+
+    d3dpp.Windowed = true;
+    d3dpp.Flags = 0;
+    d3dpp.BackBufferCount = 0;
+    d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
+    d3dpp.BackBufferHeight = HEIGHT;
+    d3dpp.BackBufferWidth = WIDTH;
+    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
+    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    d3dpp.hDeviceWindow = hWnd;
+    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+    if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, flags, &d3dpp, &dev)))
+    {
+        return false;
+    }
+
+    if (FAILED(dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer)))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool initDirect3DTextures()
+{
+    // Note: sharing is not supported on some platforms
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface, NULL/*&surfaceShared*/)))
+    {
+        std::cerr << "Can't create surface for result" << std::endl;
+        return false;
+    }
+
+    // Note: sharing is not supported on some platforms
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pReadOnlySurface, NULL/*&readOnlySurfaceShared*/)))
+    {
+        std::cerr << "Can't create read only surface" << std::endl;
+        return false;
+    }
+    else
+    {
+        IDirect3DSurface9* pTmpSurface;
+        if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTmpSurface, NULL)))
+        {
+            std::cerr << "Can't create temp surface for CPU write" << std::endl;
+            return false;
+        }
+
+        D3DLOCKED_RECT memDesc = {0, NULL};
+        RECT rc = {0, 0, WIDTH, HEIGHT};
+        if (SUCCEEDED(pTmpSurface->LockRect(&memDesc, &rc, 0)))
+        {
+            cv::Mat m(cv::Size(WIDTH, HEIGHT), CV_8UC4, memDesc.pBits, (int)memDesc.Pitch);
+            getInputTexture().copyTo(m);
+            pTmpSurface->UnlockRect();
+            dev->StretchRect(pTmpSurface, NULL, pReadOnlySurface, NULL, D3DTEXF_NONE);
+        }
+        else
+        {
+            std::cerr << "Can't LockRect() on surface" << std::endl;
+        }
+        pTmpSurface->Release();
+    }
+
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pCPUWriteSurface, NULL)))
+    {
+        std::cerr << "Can't create surface for CPU write" << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+void render(void)
+{
+    // check to make sure you have a valid Direct3D device
+    CV_Assert(dev);
+
+    renderToD3DObject();
+
+    if (g_sampleType == 0)
+    {
+        // nothing
+    }
+    else if (g_sampleType == 1)
+    {
+        if (FAILED(dev->StretchRect(pCPUWriteSurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+    }
+    else
+    {
+        if (FAILED(dev->StretchRect(pSurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+    }
+
+    if (SUCCEEDED(dev -> BeginScene()))
+    {
+        // end the scene
+        dev -> EndScene();
+    }
+
+    // present the back buffer contents to the display
+    dev->Present(NULL, NULL, NULL, NULL);
+}
+
+void cleanUp (void)
+{
+    SAFE_RELEASE(pCPUWriteSurface);
+    SAFE_RELEASE(pReadOnlySurface);
+    SAFE_RELEASE(pSurface);
+    SAFE_RELEASE(pBackBuffer);
+    SAFE_RELEASE(dev);
+    SAFE_RELEASE(pD3D);}
diff --git a/samples/directx/d3d9ex_interop.cpp b/samples/directx/d3d9ex_interop.cpp
new file mode 100644 (file)
index 0000000..38d2300
--- /dev/null
@@ -0,0 +1,158 @@
+#include <windows.h>
+#include <d3d9.h>
+#pragma comment (lib, "d3d9.lib")
+
+#define USE_D3DEX
+#define WINDOW_NAME "OpenCV Direct3D 9 Ex Sample"
+
+IDirect3D9Ex *pD3D = NULL;
+IDirect3DDevice9Ex *dev = NULL;
+IDirect3DSurface9 *pBackBuffer = NULL;
+IDirect3DSurface9 *pCPUWriteSurface = NULL; // required name
+IDirect3DSurface9 *pReadOnlySurface = NULL; // required name
+HANDLE readOnlySurfaceShared = 0; // required name
+IDirect3DSurface9 *pSurface = NULL; // required name
+HANDLE surfaceShared = 0; // required name
+
+#include "d3d_base.inl.hpp"
+
+bool initDirect3D(void)
+{
+    if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, &pD3D)))
+    {
+        return false;
+    }
+
+    D3DDISPLAYMODEEX ddm;
+    ZeroMemory(&ddm, sizeof(ddm));
+    ddm.Size = sizeof(D3DDISPLAYMODEEX);
+    D3DDISPLAYROTATION rotation;
+    if (FAILED(pD3D->GetAdapterDisplayModeEx(D3DADAPTER_DEFAULT, &ddm, &rotation)))
+    {
+        return false;
+    }
+
+    D3DPRESENT_PARAMETERS d3dpp;
+    ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
+
+    DWORD flags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE | D3DCREATE_NOWINDOWCHANGES
+            | D3DCREATE_MULTITHREADED;
+
+    d3dpp.Windowed = true;
+    d3dpp.Flags = 0;
+    d3dpp.BackBufferCount = 0;
+    d3dpp.BackBufferFormat = ddm.Format;
+    d3dpp.BackBufferHeight = HEIGHT;
+    d3dpp.BackBufferWidth = WIDTH;
+    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
+    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    d3dpp.hDeviceWindow = hWnd;
+    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+    if (FAILED(pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, flags, &d3dpp, NULL, &dev)))
+    {
+        return false;
+    }
+
+    if (FAILED(dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer)))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool initDirect3DTextures()
+{
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface, &surfaceShared)))
+    {
+        std::cerr << "Can't create surface for result" << std::endl;
+        return false;
+    }
+
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pReadOnlySurface, &readOnlySurfaceShared)))
+    {
+        std::cerr << "Can't create read only surface" << std::endl;
+        return false;
+    }
+    else
+    {
+        IDirect3DSurface9* pTmpSurface;
+        if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTmpSurface, NULL)))
+        {
+            std::cerr << "Can't create temp surface for CPU write" << std::endl;
+            return false;
+        }
+
+        D3DLOCKED_RECT memDesc = {0, NULL};
+        RECT rc = {0, 0, WIDTH, HEIGHT};
+        if (SUCCEEDED(pTmpSurface->LockRect(&memDesc, &rc, 0)))
+        {
+            cv::Mat m(cv::Size(WIDTH, HEIGHT), CV_8UC4, memDesc.pBits, (int)memDesc.Pitch);
+            getInputTexture().copyTo(m);
+            pTmpSurface->UnlockRect();
+            dev->StretchRect(pTmpSurface, NULL, pReadOnlySurface, NULL, D3DTEXF_NONE);
+        }
+        else
+        {
+            std::cerr << "Can't LockRect() on surface" << std::endl;
+        }
+        pTmpSurface->Release();
+    }
+
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pCPUWriteSurface, NULL)))
+    {
+        std::cerr << "Can't create surface for CPU write" << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+
+void render(void)
+{
+    // check to make sure you have a valid Direct3D device
+    CV_Assert(dev);
+
+    renderToD3DObject();
+
+    if (g_sampleType == 0)
+    {
+        // nothing
+    }
+    else if (g_sampleType == 1)
+    {
+        if (FAILED(dev->StretchRect(pCPUWriteSurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+    }
+    else
+    {
+        if (FAILED(dev->StretchRect(pSurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+    }
+
+    if (SUCCEEDED(dev -> BeginScene()))
+    {
+        // end the scene
+        dev -> EndScene();
+    }
+
+    // present the back buffer contents to the display
+    dev->Present(NULL, NULL, NULL, NULL);
+}
+
+void cleanUp (void)
+{
+    SAFE_RELEASE(pCPUWriteSurface);
+    SAFE_RELEASE(pReadOnlySurface);
+    SAFE_RELEASE(pSurface);
+    SAFE_RELEASE(pBackBuffer);
+    SAFE_RELEASE(dev);
+    SAFE_RELEASE(pD3D);
+}
diff --git a/samples/directx/d3d_base.inl.hpp b/samples/directx/d3d_base.inl.hpp
new file mode 100644 (file)
index 0000000..6b6de30
--- /dev/null
@@ -0,0 +1,457 @@
+//
+// Don't use as a standalone file
+//
+
+#include "opencv2/core.hpp"
+#include "opencv2/core/utility.hpp" // cv::format
+#include "opencv2/imgproc.hpp" // cvtColor
+#include "opencv2/imgproc/types_c.h" // cvtColor
+#include "opencv2/highgui.hpp" // imread
+#include "opencv2/core/directx.hpp"
+
+#include <iostream>
+#include <queue>
+
+using namespace cv;
+using namespace cv::directx;
+static const int fontFace = cv::FONT_HERSHEY_DUPLEX;
+#if !defined(USE_D3D9) && !defined(USE_D3DEX)
+const cv::Scalar frameColor(255,128,0,255);
+#else
+const cv::Scalar frameColor(0,128,255,255); // BGRA for D3D9
+#endif
+
+#define SAFE_RELEASE(p) if (p) { p->Release(); p = NULL; }
+
+const int WIDTH = 1024;
+const int HEIGHT = 768;
+
+HINSTANCE hInstance;
+HWND hWnd;
+
+// external declaration
+bool initDirect3D(void);
+bool initDirect3DTextures(void);
+void render(void);
+void cleanUp (void);
+
+#define USAGE_DESCRIPTION_0 "1 - CPU write via LockRect/Map"
+#define USAGE_DESCRIPTION_1 "2* - Mat->D3D"
+#define USAGE_DESCRIPTION_2 "3* - D3D->UMat / change UMat / UMat->D3D"
+#define USAGE_DESCRIPTION_3 "0 - show input texture without any processing"
+#define USAGE_DESCRIPTION_SPACE "SPACE - toggle frame processing (only data transfers)"
+
+static int g_sampleType = 0;
+static int g_disableProcessing = false;
+
+// forward declaration
+static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+
+static bool initWindow()
+{
+    WNDCLASSEX wcex;
+
+    wcex.cbSize             = sizeof(WNDCLASSEX);
+    wcex.style              = CS_HREDRAW | CS_VREDRAW;
+    wcex.lpfnWndProc        = WndProc;
+    wcex.cbClsExtra         = 0;
+    wcex.cbWndExtra         = 0;
+    wcex.hInstance          = hInstance;
+    wcex.hIcon              = LoadIcon(0, IDI_APPLICATION);
+    wcex.hCursor            = LoadCursor(0, IDC_ARROW);
+    wcex.hbrBackground      = 0;
+    wcex.lpszMenuName       = 0L;
+    wcex.lpszClassName      = "OpenCVDirectX";
+    wcex.hIconSm            = 0;
+
+    RegisterClassEx(&wcex);
+
+    RECT rc = {0, 0, WIDTH, HEIGHT};
+    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
+    hWnd = CreateWindow("OpenCVDirectX", WINDOW_NAME,
+            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
+
+    if (!hWnd)
+        return false;
+
+    ShowWindow(hWnd, SW_SHOW);
+    UpdateWindow(hWnd);
+
+    return true;
+}
+
+static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    switch (message)
+    {
+        case WM_DESTROY:
+            PostQuitMessage(0);
+            return 0;
+
+        case WM_CHAR:
+            if (wParam >= '0' && wParam <= '3')
+            {
+                g_sampleType = (char)wParam - '0';
+                return 0;
+            }
+            else if (wParam == ' ')
+            {
+                g_disableProcessing = !g_disableProcessing;
+                return 0;
+            }
+            else if (wParam == VK_ESCAPE)
+            {
+                DestroyWindow(hWnd);
+                return 0;
+            }
+            break;
+    }
+    return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+static float getFps()
+{
+    static std::queue<int64> time_queue;
+
+    int64 now = cv::getTickCount(), then = 0;
+    time_queue.push(now);
+
+    if (time_queue.size() >= 2)
+        then = time_queue.front();
+
+    if (time_queue.size() >= 25)
+        time_queue.pop();
+
+    return time_queue.size() * (float)cv::getTickFrequency() / (now - then);
+}
+
+static int bgColor[4] = {0, 0, 0, 0};
+static cv::Mat* inputMat = NULL;
+
+static void renderToD3DObject(void)
+{
+    static int frame = 0;
+
+    const float fps = getFps();
+
+    String deviceName = cv::ocl::useOpenCL() ? cv::ocl::Context2::getDefault().device(0).name() : "No OpenCL device";
+
+    if ((frame % std::max(1, (int)(fps / 25))) == 0)
+    {
+        String msg = format("%s%s: %s, Sample %d, Frame %d, fps %g (%g ms)",
+                g_disableProcessing ? "(FRAME PROCESSING DISABLED) " : "",
+                WINDOW_NAME, deviceName.c_str(), g_sampleType,
+                frame, fps, (int(10 * 1000.0 / fps)) * 0.1);
+        SetWindowText(hWnd, msg.c_str());
+    }
+
+    // 0..255
+    int c[4] =
+    {
+        std::abs((frame & 0x1ff) - 0x100),
+        std::abs(((frame * 2) & 0x1ff) - 0x100),
+        std::abs(((frame / 2) & 0x1ff) - 0x100),
+        0
+    };
+
+    int c1 = c[0] / 2 - 0x40 - bgColor[0];
+    int c2 = c[1] / 2 - 0x40 - bgColor[1];
+    int c3 = c[2] / 2 - 0x40 - bgColor[2];
+
+    switch (g_sampleType)
+    {
+    case 0:
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+        if (FAILED(dev->StretchRect(pReadOnlySurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+#elif defined(USE_D3D10)
+        dev->CopyResource(pBackBufferTexture, pInputTexture);
+#elif defined(USE_D3D11)
+        devcon->CopyResource(pBackBufferTexture, pInputTexture);
+#else
+#error "Invalid USE_D3D value"
+#endif
+        break;
+
+    case 1:
+    {
+        int BOXSIZE = 50;
+        int x = std::abs(((frame * 1) % (2 * (WIDTH - BOXSIZE))) - (WIDTH - BOXSIZE));
+        int y = std::abs(((frame / 2) % (2 * (HEIGHT - BOXSIZE))) - (HEIGHT - BOXSIZE));
+        cv::Rect boxRect(x, y, BOXSIZE, BOXSIZE);
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+        D3DLOCKED_RECT memDesc = {0, NULL};
+        RECT rc = {0, 0, WIDTH, HEIGHT};
+        if (SUCCEEDED(pCPUWriteSurface->LockRect(&memDesc, &rc, 0)))
+        {
+            if (!g_disableProcessing)
+            {
+                Mat m(Size(WIDTH, HEIGHT), CV_8UC4, memDesc.pBits, (int)memDesc.Pitch);
+                inputMat->copyTo(m);
+                m(boxRect).setTo(Scalar(c[0], c[1], c[2], 255));
+            }
+            pCPUWriteSurface->UnlockRect();
+        }
+        else
+        {
+            std::cerr << "Can't LockRect() on surface" << std::endl;
+        }
+#elif defined(USE_D3D10)
+        D3D10_MAPPED_TEXTURE2D mappedTex;
+        if (SUCCEEDED(pCPUWriteTexture->Map( D3D10CalcSubresource(0, 0, 1), D3D10_MAP_WRITE_DISCARD, 0, &mappedTex)))
+        {
+            if (!g_disableProcessing)
+            {
+                Mat m(Size(WIDTH, HEIGHT), CV_8UC4, mappedTex.pData, (int)mappedTex.RowPitch);
+                inputMat->copyTo(m);
+                m(boxRect).setTo(Scalar(c[0], c[1], c[2], 255));
+            }
+            pCPUWriteTexture->Unmap(D3D10CalcSubresource(0, 0, 1));
+            dev->CopyResource(pBackBufferTexture, pCPUWriteTexture);
+        }
+        else
+        {
+            std::cerr << "Can't Map() texture" << std::endl;
+        }
+#elif defined(USE_D3D11)
+        D3D11_MAPPED_SUBRESOURCE mappedTex;
+        if (SUCCEEDED(devcon->Map(pCPUWriteTexture, D3D11CalcSubresource(0, 0, 1), D3D11_MAP_WRITE_DISCARD, 0, &mappedTex)))
+        {
+            if (!g_disableProcessing)
+            {
+                Mat m(Size(WIDTH, HEIGHT), CV_8UC4, mappedTex.pData, (int)mappedTex.RowPitch);
+                inputMat->copyTo(m);
+                m(boxRect).setTo(Scalar(c[0], c[1], c[2], 255));
+            }
+            devcon->Unmap(pCPUWriteTexture, D3D11CalcSubresource(0, 0, 1));
+            devcon->CopyResource(pBackBufferTexture, pCPUWriteTexture);
+        }
+        else
+        {
+            std::cerr << "Can't Map() texture" << std::endl;
+        }
+#else
+#error "Invalid USE_D3D value"
+#endif
+        break;
+    }
+    case 2:
+    {
+        static Mat m;
+        if (!g_disableProcessing)
+        {
+#if 1
+            cv::add(*inputMat, Scalar(c1, c2, c3, 255), m);
+#else
+            inputMat->copyTo(m);
+#endif
+            cv::putText(m,
+                    cv::format("Frame %d, fps %g (%g ms)",
+                            frame, fps, (int(10 * 1000.0 / fps)) * 0.1),
+                    cv::Point(8, 80), fontFace, 1, frameColor, 2);
+        }
+        else
+        {
+            m.create(Size(WIDTH, HEIGHT), CV_8UC4);
+        }
+        try
+        {
+    #if defined(USE_D3D9) || defined (USE_D3DEX)
+            convertToDirect3DSurface9(m, pSurface, (void*)surfaceShared);
+    #elif defined(USE_D3D10)
+            convertToD3D10Texture2D(m, pBackBufferTexture);
+    #elif defined(USE_D3D11)
+            convertToD3D11Texture2D(m, pBackBufferTexture);
+    #else
+    #error "Invalid USE_D3D value"
+    #endif
+        }
+        catch (cv::Exception& e)
+        {
+            std::cerr << "Can't convert to D3D object: exception: " << e.what() << std::endl;
+        }
+        catch (...)
+        {
+            std::cerr << "Can't convert to D3D object" << std::endl;
+        }
+        break;
+    }
+    case 3:
+    {
+        static UMat tmp;
+        try
+        {
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+            convertFromDirect3DSurface9(pReadOnlySurface, tmp, (void*)readOnlySurfaceShared);
+#elif defined(USE_D3D10)
+            convertFromD3D10Texture2D(pInputTexture, tmp);
+#elif defined(USE_D3D11)
+            convertFromD3D11Texture2D(pInputTexture, tmp);
+#else
+#error "Invalid USE_D3D value"
+#endif
+        }
+        catch (cv::Exception& e)
+        {
+            std::cerr << "Can't convert from D3D object: exception: " << e.what() << std::endl;
+        }
+        catch (...)
+        {
+            std::cerr << "Can't convert from D3D object" << std::endl;
+        }
+        static UMat res;
+        if (!g_disableProcessing)
+        {
+            cv::add(tmp, Scalar(c1, c2, c3, 255), res);
+        }
+        else
+        {
+            res = tmp;
+        }
+        try
+        {
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+            convertToDirect3DSurface9(res, pSurface, (void*)surfaceShared);
+#elif defined(USE_D3D10)
+            convertToD3D10Texture2D(res, pBackBufferTexture);
+#elif defined(USE_D3D11)
+            convertToD3D11Texture2D(res, pBackBufferTexture);
+#else
+#error "Invalid USE_D3D value"
+#endif
+        }
+        catch (cv::Exception& e)
+        {
+            std::cerr << "Can't convert to D3D object: exception: " << e.what() << std::endl;
+        }
+        catch (...)
+        {
+            std::cerr << "Can't convert to D3D object" << std::endl;
+        }
+        break;
+    }
+    }
+    frame++;
+}
+
+
+static cv::Mat getInputTexture()
+{
+    cv::Mat inputMat = cv::imread("input.bmp", cv::IMREAD_COLOR);
+
+    if (inputMat.depth() != CV_8U)
+    {
+        inputMat.convertTo(inputMat, CV_8U);
+    }
+    if (inputMat.type() == CV_8UC3)
+    {
+        cv::cvtColor(inputMat, inputMat, CV_RGB2BGRA);
+    }
+    if (inputMat.type() != CV_8UC4 || inputMat.size().area() == 0)
+    {
+        std::cerr << "Invalid input image format. Generate other" << std::endl;
+        inputMat.create(cv::Size(WIDTH, HEIGHT), CV_8UC4);
+        inputMat.setTo(cv::Scalar(0, 0, 255, 255));
+        bgColor[0] = -128; bgColor[1] = -128; bgColor[2] = 127; bgColor[3] = -128;
+    }
+    if (inputMat.size().width != WIDTH || inputMat.size().height != HEIGHT)
+    {
+        cv::resize(inputMat, inputMat, cv::Size(WIDTH, HEIGHT));
+    }
+    String deviceName = cv::ocl::useOpenCL() ? cv::ocl::Context2::getDefault().device(0).name() : "No OpenCL device";
+    cv::Scalar color(64, 255, 64, 255);
+    cv::putText(inputMat,
+            cv::format("OpenCL Device name: %s", deviceName.c_str()),
+            cv::Point(8,32), fontFace, 1, color);
+    cv::putText(inputMat, WINDOW_NAME, cv::Point(50, HEIGHT - 32), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_0, cv::Point(30, 128), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_1, cv::Point(30, 192), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_2, cv::Point(30, 256), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_3, cv::Point(30, 320), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_SPACE, cv::Point(30, 448), fontFace, 1, color);
+
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+    cv::cvtColor(inputMat, inputMat, CV_RGBA2BGRA);
+    std::swap(bgColor[0], bgColor[2]);
+#endif
+
+    // Make a global copy
+    ::inputMat = new cv::Mat(inputMat);
+
+    return inputMat;
+}
+
+static int mainLoop()
+{
+    hInstance = GetModuleHandle(NULL);
+
+    if (!initWindow())
+        CV_Error(cv::Error::StsError, "Can't create window");
+
+    if (!initDirect3D())
+        CV_Error(cv::Error::StsError, "Can't create D3D object");
+
+    if (cv::ocl::haveOpenCL())
+    {
+#if defined(USE_D3D9)
+        cv::ocl::Context2& ctx = cv::directx::ocl::initializeContextFromDirect3DDevice9(dev);
+#elif defined (USE_D3DEX)
+        cv::ocl::Context2& ctx = cv::directx::ocl::initializeContextFromDirect3DDevice9Ex(dev);
+#elif defined(USE_D3D10)
+        cv::ocl::Context2& ctx = cv::directx::ocl::initializeContextFromD3D10Device(dev);
+#elif defined(USE_D3D11)
+        cv::ocl::Context2& ctx = cv::directx::ocl::initializeContextFromD3D11Device(dev);
+#else
+#error "Invalid USE_D3D value"
+#endif
+        std::cout << "Selected device: " << ctx.device(0).name().c_str() << std::endl;
+        g_sampleType = 2;
+    }
+    else
+    {
+        std::cerr << "OpenCL is not available. DirectX - OpenCL interop will not work" << std::endl;
+    }
+
+    if (!initDirect3DTextures())
+        CV_Error(cv::Error::StsError, "Can't create D3D texture object");
+
+    MSG msg;
+    ZeroMemory(&msg, sizeof(msg));
+
+    while (msg.message != WM_QUIT)
+    {
+        if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
+        {
+            TranslateMessage(&msg);
+            DispatchMessage(&msg);
+        }
+        else
+        {
+            render();
+        }
+    }
+
+    cleanUp();
+
+    return static_cast<int>(msg.wParam);
+}
+
+int main(int /*argc*/, char ** /*argv*/)
+{
+    try
+    {
+        return mainLoop();
+    }
+    catch (cv::Exception& e)
+    {
+        std::cerr << "Exception: " << e.what() << std::endl;
+        return 10;
+    }
+    catch (...)
+    {
+        std::cerr << "FATAL ERROR: Unknown exception" << std::endl;
+        return 11;
+    }
+}