• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of the copyright holders may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors as is and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the copyright holders or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 
42 #include "precomp.hpp"
43 
44 #include "opencv2/core.hpp"
45 #include "opencv2/core/ocl.hpp"
46 #include "opencv2/core/directx.hpp"
47 
48 #ifdef HAVE_DIRECTX
49 #include <vector>
50 # include "directx.inc.hpp"
51 #else // HAVE_DIRECTX
52 #define NO_DIRECTX_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without DirectX support")
53 #endif
54 
55 #ifndef HAVE_OPENCL
56 # define NO_OPENCL_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without OpenCL support")
57 #endif // HAVE_OPENCL
58 
59 namespace cv { namespace directx {
60 
getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT)61 int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT)
62 {
63     (void)iDXGI_FORMAT;
64 #if !defined(HAVE_DIRECTX)
65     NO_DIRECTX_SUPPORT_ERROR;
66 #else
67     const int errorType = -1;
68     switch ((enum DXGI_FORMAT)iDXGI_FORMAT)
69     {
70     //case DXGI_FORMAT_UNKNOWN:
71     //case DXGI_FORMAT_R32G32B32A32_TYPELESS:
72     case DXGI_FORMAT_R32G32B32A32_FLOAT: return CV_32FC4;
73     case DXGI_FORMAT_R32G32B32A32_UINT:
74     case DXGI_FORMAT_R32G32B32A32_SINT:  return CV_32SC4;
75     //case DXGI_FORMAT_R32G32B32_TYPELESS:
76     case DXGI_FORMAT_R32G32B32_FLOAT: return CV_32FC3;
77     case DXGI_FORMAT_R32G32B32_UINT:
78     case DXGI_FORMAT_R32G32B32_SINT: return CV_32SC3;
79     //case DXGI_FORMAT_R16G16B16A16_TYPELESS:
80     //case DXGI_FORMAT_R16G16B16A16_FLOAT:
81     case DXGI_FORMAT_R16G16B16A16_UNORM:
82     case DXGI_FORMAT_R16G16B16A16_UINT: return CV_16UC4;
83     case DXGI_FORMAT_R16G16B16A16_SNORM:
84     case DXGI_FORMAT_R16G16B16A16_SINT: return CV_16SC4;
85     //case DXGI_FORMAT_R32G32_TYPELESS:
86     //case DXGI_FORMAT_R32G32_FLOAT:
87     //case DXGI_FORMAT_R32G32_UINT:
88     //case DXGI_FORMAT_R32G32_SINT:
89     //case DXGI_FORMAT_R32G8X24_TYPELESS:
90     //case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
91     //case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
92     //case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
93     //case DXGI_FORMAT_R10G10B10A2_TYPELESS:
94     //case DXGI_FORMAT_R10G10B10A2_UNORM:
95     //case DXGI_FORMAT_R10G10B10A2_UINT:
96     //case DXGI_FORMAT_R11G11B10_FLOAT:
97     //case DXGI_FORMAT_R8G8B8A8_TYPELESS:
98     case DXGI_FORMAT_R8G8B8A8_UNORM:
99     case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
100     case DXGI_FORMAT_R8G8B8A8_UINT: return CV_8UC4;
101     case DXGI_FORMAT_R8G8B8A8_SNORM:
102     case DXGI_FORMAT_R8G8B8A8_SINT: return CV_8SC4;
103     //case DXGI_FORMAT_R16G16_TYPELESS:
104     //case DXGI_FORMAT_R16G16_FLOAT:
105     case DXGI_FORMAT_R16G16_UNORM:
106     case DXGI_FORMAT_R16G16_UINT: return CV_16UC2;
107     case DXGI_FORMAT_R16G16_SNORM:
108     case DXGI_FORMAT_R16G16_SINT: return CV_16SC2;
109     //case DXGI_FORMAT_R32_TYPELESS:
110     //case DXGI_FORMAT_D32_FLOAT:
111     case DXGI_FORMAT_R32_FLOAT: return CV_32FC1;
112     case DXGI_FORMAT_R32_UINT:
113     case DXGI_FORMAT_R32_SINT: return CV_32SC1;
114     //case DXGI_FORMAT_R24G8_TYPELESS:
115     //case DXGI_FORMAT_D24_UNORM_S8_UINT:
116     //case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
117     //case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
118     //case DXGI_FORMAT_R8G8_TYPELESS:
119     case DXGI_FORMAT_R8G8_UNORM:
120     case DXGI_FORMAT_R8G8_UINT: return CV_8UC2;
121     case DXGI_FORMAT_R8G8_SNORM:
122     case DXGI_FORMAT_R8G8_SINT: return CV_8SC2;
123     //case DXGI_FORMAT_R16_TYPELESS:
124     //case DXGI_FORMAT_R16_FLOAT:
125     case DXGI_FORMAT_D16_UNORM:
126     case DXGI_FORMAT_R16_UNORM:
127     case DXGI_FORMAT_R16_UINT: return CV_16UC1;
128     case DXGI_FORMAT_R16_SNORM:
129     case DXGI_FORMAT_R16_SINT: return CV_16SC1;
130     //case DXGI_FORMAT_R8_TYPELESS:
131     case DXGI_FORMAT_R8_UNORM:
132     case DXGI_FORMAT_R8_UINT: return CV_8UC1;
133     case DXGI_FORMAT_R8_SNORM:
134     case DXGI_FORMAT_R8_SINT: return CV_8SC1;
135     case DXGI_FORMAT_A8_UNORM: return CV_8UC1;
136     //case DXGI_FORMAT_R1_UNORM:
137     //case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
138     //case DXGI_FORMAT_R8G8_B8G8_UNORM:
139     //case DXGI_FORMAT_G8R8_G8B8_UNORM:
140     //case DXGI_FORMAT_BC1_TYPELESS:
141     //case DXGI_FORMAT_BC1_UNORM:
142     //case DXGI_FORMAT_BC1_UNORM_SRGB:
143     //case DXGI_FORMAT_BC2_TYPELESS:
144     //case DXGI_FORMAT_BC2_UNORM:
145     //case DXGI_FORMAT_BC2_UNORM_SRGB:
146     //case DXGI_FORMAT_BC3_TYPELESS:
147     //case DXGI_FORMAT_BC3_UNORM:
148     //case DXGI_FORMAT_BC3_UNORM_SRGB:
149     //case DXGI_FORMAT_BC4_TYPELESS:
150     //case DXGI_FORMAT_BC4_UNORM:
151     //case DXGI_FORMAT_BC4_SNORM:
152     //case DXGI_FORMAT_BC5_TYPELESS:
153     //case DXGI_FORMAT_BC5_UNORM:
154     //case DXGI_FORMAT_BC5_SNORM:
155     //case DXGI_FORMAT_B5G6R5_UNORM:
156     //case DXGI_FORMAT_B5G5R5A1_UNORM:
157     case DXGI_FORMAT_B8G8R8A8_UNORM:
158     case DXGI_FORMAT_B8G8R8X8_UNORM: return CV_8UC4;
159     //case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
160     //case DXGI_FORMAT_B8G8R8A8_TYPELESS:
161     case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return CV_8UC4;
162     //case DXGI_FORMAT_B8G8R8X8_TYPELESS:
163     case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return CV_8UC4;
164     //case DXGI_FORMAT_BC6H_TYPELESS:
165     //case DXGI_FORMAT_BC6H_UF16:
166     //case DXGI_FORMAT_BC6H_SF16:
167     //case DXGI_FORMAT_BC7_TYPELESS:
168     //case DXGI_FORMAT_BC7_UNORM:
169     //case DXGI_FORMAT_BC7_UNORM_SRGB:
170     default: break;
171     }
172     return errorType;
173 #endif
174 }
175 
getTypeFromD3DFORMAT(const int iD3DFORMAT)176 int getTypeFromD3DFORMAT(const int iD3DFORMAT)
177 {
178     (void)iD3DFORMAT;
179 #if !defined(HAVE_DIRECTX)
180     NO_DIRECTX_SUPPORT_ERROR;
181 #else
182     const int errorType = -1;
183     switch ((enum _D3DFORMAT)iD3DFORMAT)
184     {
185     //case D3DFMT_UNKNOWN:
186     case D3DFMT_R8G8B8: return CV_8UC3;
187     case D3DFMT_A8R8G8B8:
188     case D3DFMT_X8R8G8B8: return CV_8UC4;
189     //case D3DFMT_R5G6B5:
190     //case D3DFMT_X1R5G5B5:
191     //case D3DFMT_A1R5G5B5:
192     //case D3DFMT_A4R4G4B4:
193     //case D3DFMT_R3G3B2:
194     case D3DFMT_A8: return CV_8UC1;
195     //case D3DFMT_A8R3G3B2:
196     //case D3DFMT_X4R4G4B4:
197     //case D3DFMT_A2B10G10R10:
198     case D3DFMT_A8B8G8R8:
199     case D3DFMT_X8B8G8R8: return CV_8UC4;
200     //case D3DFMT_G16R16:
201     //case D3DFMT_A2R10G10B10:
202     //case D3DFMT_A16B16G16R16:
203 
204     case D3DFMT_A8P8: return CV_8UC2;
205     case D3DFMT_P8: return CV_8UC1;
206 
207     case D3DFMT_L8: return CV_8UC1;
208     case D3DFMT_A8L8: return CV_8UC2;
209     //case D3DFMT_A4L4:
210 
211     case D3DFMT_V8U8: return CV_8UC2;
212     //case D3DFMT_L6V5U5:
213     case D3DFMT_X8L8V8U8:
214     case D3DFMT_Q8W8V8U8: return CV_8UC4;
215     case D3DFMT_V16U16: return CV_16UC4; // TODO 16SC4 ?
216     //case D3DFMT_A2W10V10U10:
217 
218     case D3DFMT_D16_LOCKABLE: return CV_16UC1;
219     case D3DFMT_D32: return CV_32SC1;
220     //case D3DFMT_D15S1:
221     //case D3DFMT_D24S8:
222     //case D3DFMT_D24X8:
223     //case D3DFMT_D24X4S4:
224     case D3DFMT_D16: return CV_16UC1;
225 
226     case D3DFMT_D32F_LOCKABLE: return CV_32FC1;
227     default: break;
228     }
229     return errorType;
230 #endif
231 }
232 
233 namespace ocl {
234 
235 #if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
236 static bool g_isDirect3DDevice9Ex = false; // Direct3DDevice9Ex or Direct3DDevice9 was used
237 #endif
238 
initializeContextFromD3D11Device(ID3D11Device * pD3D11Device)239 Context& initializeContextFromD3D11Device(ID3D11Device* pD3D11Device)
240 {
241     (void)pD3D11Device;
242 #if !defined(HAVE_DIRECTX)
243     NO_DIRECTX_SUPPORT_ERROR;
244 #elif !defined(HAVE_OPENCL)
245     NO_OPENCL_SUPPORT_ERROR;
246 #else
247     cl_uint numPlatforms;
248     cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
249     if (status != CL_SUCCESS)
250         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
251     if (numPlatforms == 0)
252         CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
253 
254     std::vector<cl_platform_id> platforms(numPlatforms);
255     status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
256     if (status != CL_SUCCESS)
257         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
258 
259     // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
260 
261     int found = -1;
262     cl_device_id device = NULL;
263     cl_uint numDevices = 0;
264     cl_context context = NULL;
265 
266     // try with CL_PREFERRED_DEVICES_FOR_D3D11_KHR
267     for (int i = 0; i < (int)numPlatforms; i++)
268     {
269         clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
270                 clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
271         if (!clGetDeviceIDsFromD3D11KHR)
272             continue;
273 
274         device = NULL;
275         numDevices = 0;
276         status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
277                 CL_PREFERRED_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
278         if (status != CL_SUCCESS)
279             continue;
280         if (numDevices > 0)
281         {
282             cl_context_properties properties[] = {
283                     CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
284                     CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
285                     CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
286                     NULL, NULL
287             };
288             context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
289             if (status != CL_SUCCESS)
290             {
291                 clReleaseDevice(device);
292             }
293             else
294             {
295                 found = i;
296                 break;
297             }
298         }
299     }
300     if (found < 0)
301     {
302         // try with CL_ALL_DEVICES_FOR_D3D11_KHR
303         for (int i = 0; i < (int)numPlatforms; i++)
304         {
305             clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
306                     clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
307             if (!clGetDeviceIDsFromD3D11KHR)
308                 continue;
309 
310             device = NULL;
311             numDevices = 0;
312             status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
313                     CL_ALL_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
314             if (status != CL_SUCCESS)
315                 continue;
316             if (numDevices > 0)
317             {
318                 cl_context_properties properties[] = {
319                         CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
320                         CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
321                         CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
322                         NULL, NULL
323                 };
324                 context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
325                 if (status != CL_SUCCESS)
326                 {
327                     clReleaseDevice(device);
328                 }
329                 else
330                 {
331                     found = i;
332                     break;
333                 }
334             }
335         }
336         if (found < 0)
337             CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
338     }
339 
340 
341     Context& ctx = Context::getDefault(false);
342     initializeContextFromHandle(ctx, platforms[found], context, device);
343     return ctx;
344 #endif
345 }
346 
initializeContextFromD3D10Device(ID3D10Device * pD3D10Device)347 Context& initializeContextFromD3D10Device(ID3D10Device* pD3D10Device)
348 {
349     (void)pD3D10Device;
350 #if !defined(HAVE_DIRECTX)
351     NO_DIRECTX_SUPPORT_ERROR;
352 #elif !defined(HAVE_OPENCL)
353     NO_OPENCL_SUPPORT_ERROR;
354 #else
355     cl_uint numPlatforms;
356     cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
357     if (status != CL_SUCCESS)
358         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
359     if (numPlatforms == 0)
360         CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
361 
362     std::vector<cl_platform_id> platforms(numPlatforms);
363     status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
364     if (status != CL_SUCCESS)
365         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
366 
367     // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
368 
369     int found = -1;
370     cl_device_id device = NULL;
371     cl_uint numDevices = 0;
372     cl_context context = NULL;
373 
374     // try with CL_PREFERRED_DEVICES_FOR_D3D10_KHR
375     for (int i = 0; i < (int)numPlatforms; i++)
376     {
377         clGetDeviceIDsFromD3D10KHR_fn clGetDeviceIDsFromD3D10KHR = (clGetDeviceIDsFromD3D10KHR_fn)
378                 clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D10KHR");
379         if (!clGetDeviceIDsFromD3D10KHR)
380             continue;
381 
382         device = NULL;
383         numDevices = 0;
384         status = clGetDeviceIDsFromD3D10KHR(platforms[i], CL_D3D10_DEVICE_KHR, pD3D10Device,
385                 CL_PREFERRED_DEVICES_FOR_D3D10_KHR, 1, &device, &numDevices);
386         if (status != CL_SUCCESS)
387             continue;
388         if (numDevices > 0)
389         {
390             cl_context_properties properties[] = {
391                     CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
392                     CL_CONTEXT_D3D10_DEVICE_KHR, (cl_context_properties)(pD3D10Device),
393                     CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
394                     NULL, NULL
395             };
396             context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
397             if (status != CL_SUCCESS)
398             {
399                 clReleaseDevice(device);
400             }
401             else
402             {
403                 found = i;
404                 break;
405             }
406         }
407     }
408     if (found < 0)
409     {
410         // try with CL_ALL_DEVICES_FOR_D3D10_KHR
411         for (int i = 0; i < (int)numPlatforms; i++)
412         {
413             clGetDeviceIDsFromD3D10KHR_fn clGetDeviceIDsFromD3D10KHR = (clGetDeviceIDsFromD3D10KHR_fn)
414                     clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D10KHR");
415             if (!clGetDeviceIDsFromD3D10KHR)
416                 continue;
417 
418             device = NULL;
419             numDevices = 0;
420             status = clGetDeviceIDsFromD3D10KHR(platforms[i], CL_D3D10_DEVICE_KHR, pD3D10Device,
421                     CL_ALL_DEVICES_FOR_D3D10_KHR, 1, &device, &numDevices);
422             if (status != CL_SUCCESS)
423                 continue;
424             if (numDevices > 0)
425             {
426                 cl_context_properties properties[] = {
427                         CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
428                         CL_CONTEXT_D3D10_DEVICE_KHR, (cl_context_properties)(pD3D10Device),
429                         CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
430                         NULL, NULL
431                 };
432                 context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
433                 if (status != CL_SUCCESS)
434                 {
435                     clReleaseDevice(device);
436                 }
437                 else
438                 {
439                     found = i;
440                     break;
441                 }
442             }
443         }
444         if (found < 0)
445             CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
446     }
447 
448 
449     Context& ctx = Context::getDefault(false);
450     initializeContextFromHandle(ctx, platforms[found], context, device);
451     return ctx;
452 #endif
453 }
454 
initializeContextFromDirect3DDevice9Ex(IDirect3DDevice9Ex * pDirect3DDevice9Ex)455 Context& initializeContextFromDirect3DDevice9Ex(IDirect3DDevice9Ex* pDirect3DDevice9Ex)
456 {
457     (void)pDirect3DDevice9Ex;
458 #if !defined(HAVE_DIRECTX)
459     NO_DIRECTX_SUPPORT_ERROR;
460 #elif !defined(HAVE_OPENCL)
461     NO_OPENCL_SUPPORT_ERROR;
462 #else
463     cl_uint numPlatforms;
464     cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
465     if (status != CL_SUCCESS)
466         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
467     if (numPlatforms == 0)
468         CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
469 
470     std::vector<cl_platform_id> platforms(numPlatforms);
471     status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
472     if (status != CL_SUCCESS)
473         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
474 
475     // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
476 
477     int found = -1;
478     cl_device_id device = NULL;
479     cl_uint numDevices = 0;
480     cl_context context = NULL;
481 
482     // try with CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
483     for (int i = 0; i < (int)numPlatforms; i++)
484     {
485         clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
486                 clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
487         if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
488             continue;
489 
490         device = NULL;
491         numDevices = 0;
492         cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9EX_KHR;
493         status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9Ex,
494                 CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
495         if (status != CL_SUCCESS)
496             continue;
497         if (numDevices > 0)
498         {
499             cl_context_properties properties[] = {
500                     CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
501                     CL_CONTEXT_ADAPTER_D3D9EX_KHR, (cl_context_properties)(pDirect3DDevice9Ex),
502                     CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
503                     NULL, NULL
504             };
505             context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
506             if (status != CL_SUCCESS)
507             {
508                 clReleaseDevice(device);
509             }
510             else
511             {
512                 found = i;
513                 break;
514             }
515         }
516     }
517     if (found < 0)
518     {
519         // try with CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
520         for (int i = 0; i < (int)numPlatforms; i++)
521         {
522             clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
523                     clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
524             if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
525                 continue;
526 
527             device = NULL;
528             numDevices = 0;
529             cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9EX_KHR;
530             status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9Ex,
531                     CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
532             if (status != CL_SUCCESS)
533                 continue;
534             if (numDevices > 0)
535             {
536                 cl_context_properties properties[] = {
537                         CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
538                         CL_CONTEXT_ADAPTER_D3D9EX_KHR, (cl_context_properties)(pDirect3DDevice9Ex),
539                         CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
540                         NULL, NULL
541                 };
542                 context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
543                 if (status != CL_SUCCESS)
544                 {
545                     clReleaseDevice(device);
546                 }
547                 else
548                 {
549                     found = i;
550                     break;
551                 }
552             }
553         }
554         if (found < 0)
555             CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
556     }
557 
558     Context& ctx = Context::getDefault(false);
559     initializeContextFromHandle(ctx, platforms[found], context, device);
560     g_isDirect3DDevice9Ex = true;
561     return ctx;
562 #endif
563 }
564 
initializeContextFromDirect3DDevice9(IDirect3DDevice9 * pDirect3DDevice9)565 Context& initializeContextFromDirect3DDevice9(IDirect3DDevice9* pDirect3DDevice9)
566 {
567     (void)pDirect3DDevice9;
568 #if !defined(HAVE_DIRECTX)
569     NO_DIRECTX_SUPPORT_ERROR;
570 #elif !defined(HAVE_OPENCL)
571     NO_OPENCL_SUPPORT_ERROR;
572 #else
573     cl_uint numPlatforms;
574     cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
575     if (status != CL_SUCCESS)
576         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
577     if (numPlatforms == 0)
578         CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
579 
580     std::vector<cl_platform_id> platforms(numPlatforms);
581     status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
582     if (status != CL_SUCCESS)
583         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
584 
585     // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
586 
587     int found = -1;
588     cl_device_id device = NULL;
589     cl_uint numDevices = 0;
590     cl_context context = NULL;
591 
592     // try with CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
593     for (int i = 0; i < (int)numPlatforms; i++)
594     {
595         clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
596                 clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
597         if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
598             continue;
599 
600         device = NULL;
601         numDevices = 0;
602         cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9_KHR;
603         status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9,
604                 CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
605         if (status != CL_SUCCESS)
606             continue;
607         if (numDevices > 0)
608         {
609             cl_context_properties properties[] = {
610                     CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
611                     CL_CONTEXT_ADAPTER_D3D9_KHR, (cl_context_properties)(pDirect3DDevice9),
612                     CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
613                     NULL, NULL
614             };
615             context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
616             if (status != CL_SUCCESS)
617             {
618                 clReleaseDevice(device);
619             }
620             else
621             {
622                 found = i;
623                 break;
624             }
625         }
626     }
627     if (found < 0)
628     {
629         // try with CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
630         for (int i = 0; i < (int)numPlatforms; i++)
631         {
632             clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
633                     clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
634             if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
635                 continue;
636 
637             device = NULL;
638             numDevices = 0;
639             cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9_KHR;
640             status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9,
641                     CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
642             if (status != CL_SUCCESS)
643                 continue;
644             if (numDevices > 0)
645             {
646                 cl_context_properties properties[] = {
647                         CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
648                         CL_CONTEXT_ADAPTER_D3D9_KHR, (cl_context_properties)(pDirect3DDevice9),
649                         CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
650                         NULL, NULL
651                 };
652                 context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
653                 if (status != CL_SUCCESS)
654                 {
655                     clReleaseDevice(device);
656                 }
657                 else
658                 {
659                     found = i;
660                     break;
661                 }
662             }
663         }
664         if (found < 0)
665             CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
666     }
667 
668     Context& ctx = Context::getDefault(false);
669     initializeContextFromHandle(ctx, platforms[found], context, device);
670     g_isDirect3DDevice9Ex = false;
671     return ctx;
672 #endif
673 }
674 
675 } // namespace cv::ocl
676 
677 #if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
678 clCreateFromD3D11Texture2DKHR_fn clCreateFromD3D11Texture2DKHR = NULL;
679 clEnqueueAcquireD3D11ObjectsKHR_fn clEnqueueAcquireD3D11ObjectsKHR = NULL;
680 clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11ObjectsKHR = NULL;
681 
__OpenCLinitializeD3D11()682 static void __OpenCLinitializeD3D11()
683 {
684     using namespace cv::ocl;
685     static cl_platform_id initializedPlatform = NULL;
686     cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
687     if (initializedPlatform != platform)
688     {
689         clCreateFromD3D11Texture2DKHR = (clCreateFromD3D11Texture2DKHR_fn)
690                 clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D11Texture2DKHR");
691         clEnqueueAcquireD3D11ObjectsKHR = (clEnqueueAcquireD3D11ObjectsKHR_fn)
692                 clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D11ObjectsKHR");
693         clEnqueueReleaseD3D11ObjectsKHR = (clEnqueueReleaseD3D11ObjectsKHR_fn)
694                 clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D11ObjectsKHR");
695         initializedPlatform = platform;
696     }
697     if (!clCreateFromD3D11Texture2DKHR || !clEnqueueAcquireD3D11ObjectsKHR || !clEnqueueReleaseD3D11ObjectsKHR)
698     {
699         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D11");
700     }
701 }
702 #endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
703 
convertToD3D11Texture2D(InputArray src,ID3D11Texture2D * pD3D11Texture2D)704 void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
705 {
706     (void)src; (void)pD3D11Texture2D;
707 #if !defined(HAVE_DIRECTX)
708     NO_DIRECTX_SUPPORT_ERROR;
709 #elif defined(HAVE_OPENCL)
710     __OpenCLinitializeD3D11();
711 
712     D3D11_TEXTURE2D_DESC desc = { 0 };
713     pD3D11Texture2D->GetDesc(&desc);
714 
715     int srcType = src.type();
716     int textureType = getTypeFromDXGI_FORMAT(desc.Format);
717     CV_Assert(textureType == srcType);
718 
719     Size srcSize = src.size();
720     CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
721 
722     using namespace cv::ocl;
723     Context& ctx = Context::getDefault();
724     cl_context context = (cl_context)ctx.ptr();
725 
726     UMat u = src.getUMat();
727 
728     // TODO Add support for roi
729     CV_Assert(u.offset == 0);
730     CV_Assert(u.isContinuous());
731 
732     cl_int status = 0;
733     cl_mem clImage = clCreateFromD3D11Texture2DKHR(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 0, &status);
734     if (status != CL_SUCCESS)
735         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed");
736 
737     cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
738 
739     cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
740     status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
741     if (status != CL_SUCCESS)
742         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed");
743     size_t offset = 0; // TODO
744     size_t dst_origin[3] = {0, 0, 0};
745     size_t region[3] = {u.cols, u.rows, 1};
746     status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
747     if (status != CL_SUCCESS)
748         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
749     status = clEnqueueReleaseD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
750     if (status != CL_SUCCESS)
751         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsKHR failed");
752 
753     status = clFinish(q); // TODO Use events
754     if (status != CL_SUCCESS)
755         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
756 
757     status = clReleaseMemObject(clImage); // TODO RAII
758     if (status != CL_SUCCESS)
759         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
760 #else
761     // TODO memcpy
762     NO_OPENCL_SUPPORT_ERROR;
763 #endif
764 }
convertFromD3D11Texture2D(ID3D11Texture2D * pD3D11Texture2D,OutputArray dst)765 void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
766 {
767     (void)pD3D11Texture2D; (void)dst;
768 #if !defined(HAVE_DIRECTX)
769     NO_DIRECTX_SUPPORT_ERROR;
770 #elif defined(HAVE_OPENCL)
771     __OpenCLinitializeD3D11();
772 
773     D3D11_TEXTURE2D_DESC desc = { 0 };
774     pD3D11Texture2D->GetDesc(&desc);
775 
776     int textureType = getTypeFromDXGI_FORMAT(desc.Format);
777     CV_Assert(textureType >= 0);
778 
779     using namespace cv::ocl;
780     Context& ctx = Context::getDefault();
781     cl_context context = (cl_context)ctx.ptr();
782 
783     // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
784     dst.create(Size(desc.Width, desc.Height), textureType);
785     UMat u = dst.getUMat();
786 
787     // TODO Add support for roi
788     CV_Assert(u.offset == 0);
789     CV_Assert(u.isContinuous());
790 
791     cl_int status = 0;
792     cl_mem clImage = clCreateFromD3D11Texture2DKHR(context, CL_MEM_READ_ONLY, pD3D11Texture2D, 0, &status);
793     if (status != CL_SUCCESS)
794         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed");
795 
796     cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
797 
798     cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
799     status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
800     if (status != CL_SUCCESS)
801         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed");
802     size_t offset = 0; // TODO
803     size_t src_origin[3] = {0, 0, 0};
804     size_t region[3] = {u.cols, u.rows, 1};
805     status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
806     if (status != CL_SUCCESS)
807         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
808     status = clEnqueueReleaseD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
809     if (status != CL_SUCCESS)
810         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsKHR failed");
811 
812     status = clFinish(q); // TODO Use events
813     if (status != CL_SUCCESS)
814         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
815 
816     status = clReleaseMemObject(clImage); // TODO RAII
817     if (status != CL_SUCCESS)
818         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
819 #else
820     // TODO memcpy
821     NO_OPENCL_SUPPORT_ERROR;
822 #endif
823 }
824 
825 #if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
826 clCreateFromD3D10Texture2DKHR_fn clCreateFromD3D10Texture2DKHR = NULL;
827 clEnqueueAcquireD3D10ObjectsKHR_fn clEnqueueAcquireD3D10ObjectsKHR = NULL;
828 clEnqueueReleaseD3D10ObjectsKHR_fn clEnqueueReleaseD3D10ObjectsKHR = NULL;
829 
__OpenCLinitializeD3D10()830 static void __OpenCLinitializeD3D10()
831 {
832     using namespace cv::ocl;
833     static cl_platform_id initializedPlatform = NULL;
834     cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
835     if (initializedPlatform != platform)
836     {
837         clCreateFromD3D10Texture2DKHR = (clCreateFromD3D10Texture2DKHR_fn)
838                 clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D10Texture2DKHR");
839         clEnqueueAcquireD3D10ObjectsKHR = (clEnqueueAcquireD3D10ObjectsKHR_fn)
840                 clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D10ObjectsKHR");
841         clEnqueueReleaseD3D10ObjectsKHR = (clEnqueueReleaseD3D10ObjectsKHR_fn)
842                 clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D10ObjectsKHR");
843         initializedPlatform = platform;
844     }
845     if (!clCreateFromD3D10Texture2DKHR || !clEnqueueAcquireD3D10ObjectsKHR || !clEnqueueReleaseD3D10ObjectsKHR)
846     {
847         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D10");
848     }
849 }
850 #endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
851 
convertToD3D10Texture2D(InputArray src,ID3D10Texture2D * pD3D10Texture2D)852 void convertToD3D10Texture2D(InputArray src, ID3D10Texture2D* pD3D10Texture2D)
853 {
854     (void)src; (void)pD3D10Texture2D;
855 #if !defined(HAVE_DIRECTX)
856     NO_DIRECTX_SUPPORT_ERROR;
857 #elif defined(HAVE_OPENCL)
858     __OpenCLinitializeD3D10();
859 
860     D3D10_TEXTURE2D_DESC desc = { 0 };
861     pD3D10Texture2D->GetDesc(&desc);
862 
863     int srcType = src.type();
864     int textureType = getTypeFromDXGI_FORMAT(desc.Format);
865     CV_Assert(textureType == srcType);
866 
867     Size srcSize = src.size();
868     CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
869 
870     using namespace cv::ocl;
871     Context& ctx = Context::getDefault();
872     cl_context context = (cl_context)ctx.ptr();
873 
874     UMat u = src.getUMat();
875 
876     // TODO Add support for roi
877     CV_Assert(u.offset == 0);
878     CV_Assert(u.isContinuous());
879 
880     cl_int status = 0;
881     cl_mem clImage = clCreateFromD3D10Texture2DKHR(context, CL_MEM_WRITE_ONLY, pD3D10Texture2D, 0, &status);
882     if (status != CL_SUCCESS)
883         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D10Texture2DKHR failed");
884 
885     cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
886 
887     cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
888     status = clEnqueueAcquireD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
889     if (status != CL_SUCCESS)
890         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed");
891     size_t offset = 0; // TODO
892     size_t dst_origin[3] = {0, 0, 0};
893     size_t region[3] = {u.cols, u.rows, 1};
894     status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
895     if (status != CL_SUCCESS)
896         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
897     status = clEnqueueReleaseD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
898     if (status != CL_SUCCESS)
899         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D10ObjectsKHR failed");
900 
901     status = clFinish(q); // TODO Use events
902     if (status != CL_SUCCESS)
903         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
904 
905     status = clReleaseMemObject(clImage); // TODO RAII
906     if (status != CL_SUCCESS)
907         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
908 #else
909     // TODO memcpy
910     NO_OPENCL_SUPPORT_ERROR;
911 #endif
912 }
convertFromD3D10Texture2D(ID3D10Texture2D * pD3D10Texture2D,OutputArray dst)913 void convertFromD3D10Texture2D(ID3D10Texture2D* pD3D10Texture2D, OutputArray dst)
914 {
915     (void)pD3D10Texture2D; (void)dst;
916 #if !defined(HAVE_DIRECTX)
917     NO_DIRECTX_SUPPORT_ERROR;
918 #elif defined(HAVE_OPENCL)
919     __OpenCLinitializeD3D10();
920 
921     D3D10_TEXTURE2D_DESC desc = { 0 };
922     pD3D10Texture2D->GetDesc(&desc);
923 
924     int textureType = getTypeFromDXGI_FORMAT(desc.Format);
925     CV_Assert(textureType >= 0);
926 
927     using namespace cv::ocl;
928     Context& ctx = Context::getDefault();
929     cl_context context = (cl_context)ctx.ptr();
930 
931     // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
932     dst.create(Size(desc.Width, desc.Height), textureType);
933     UMat u = dst.getUMat();
934 
935     // TODO Add support for roi
936     CV_Assert(u.offset == 0);
937     CV_Assert(u.isContinuous());
938 
939     cl_int status = 0;
940     cl_mem clImage = clCreateFromD3D10Texture2DKHR(context, CL_MEM_READ_ONLY, pD3D10Texture2D, 0, &status);
941     if (status != CL_SUCCESS)
942         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D10Texture2DKHR failed");
943 
944     cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
945 
946     cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
947     status = clEnqueueAcquireD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
948     if (status != CL_SUCCESS)
949         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed");
950     size_t offset = 0; // TODO
951     size_t src_origin[3] = {0, 0, 0};
952     size_t region[3] = {u.cols, u.rows, 1};
953     status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
954     if (status != CL_SUCCESS)
955         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
956     status = clEnqueueReleaseD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
957     if (status != CL_SUCCESS)
958         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D10ObjectsKHR failed");
959 
960     status = clFinish(q); // TODO Use events
961     if (status != CL_SUCCESS)
962         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
963 
964     status = clReleaseMemObject(clImage); // TODO RAII
965     if (status != CL_SUCCESS)
966         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
967 #else
968     // TODO memcpy
969     NO_OPENCL_SUPPORT_ERROR;
970 #endif
971 }
972 
973 #if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
974 clCreateFromDX9MediaSurfaceKHR_fn clCreateFromDX9MediaSurfaceKHR = NULL;
975 clEnqueueAcquireDX9MediaSurfacesKHR_fn clEnqueueAcquireDX9MediaSurfacesKHR = NULL;
976 clEnqueueReleaseDX9MediaSurfacesKHR_fn clEnqueueReleaseDX9MediaSurfacesKHR = NULL;
977 
__OpenCLinitializeD3D9()978 static void __OpenCLinitializeD3D9()
979 {
980     using namespace cv::ocl;
981     static cl_platform_id initializedPlatform = NULL;
982     cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
983     if (initializedPlatform != platform)
984     {
985         clCreateFromDX9MediaSurfaceKHR = (clCreateFromDX9MediaSurfaceKHR_fn)
986                 clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromDX9MediaSurfaceKHR");
987         clEnqueueAcquireDX9MediaSurfacesKHR = (clEnqueueAcquireDX9MediaSurfacesKHR_fn)
988                 clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireDX9MediaSurfacesKHR");
989         clEnqueueReleaseDX9MediaSurfacesKHR = (clEnqueueReleaseDX9MediaSurfacesKHR_fn)
990                 clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseDX9MediaSurfacesKHR");
991         initializedPlatform = platform;
992     }
993     if (!clCreateFromDX9MediaSurfaceKHR || !clEnqueueAcquireDX9MediaSurfacesKHR || !clEnqueueReleaseDX9MediaSurfacesKHR)
994     {
995         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D9");
996     }
997 }
998 #endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
999 
convertToDirect3DSurface9(InputArray src,IDirect3DSurface9 * pDirect3DSurface9,void * surfaceSharedHandle)1000 void convertToDirect3DSurface9(InputArray src, IDirect3DSurface9* pDirect3DSurface9, void* surfaceSharedHandle)
1001 {
1002     (void)src; (void)pDirect3DSurface9; (void)surfaceSharedHandle;
1003 #if !defined(HAVE_DIRECTX)
1004     NO_DIRECTX_SUPPORT_ERROR;
1005 #elif defined(HAVE_OPENCL)
1006     __OpenCLinitializeD3D9();
1007 
1008     D3DSURFACE_DESC desc;
1009     if (FAILED(pDirect3DSurface9->GetDesc(&desc)))
1010     {
1011         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: Can't get D3D surface description");
1012     }
1013 
1014     int srcType = src.type();
1015     int surfaceType = getTypeFromD3DFORMAT(desc.Format);
1016     CV_Assert(surfaceType == srcType);
1017 
1018     Size srcSize = src.size();
1019     CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
1020 
1021     using namespace cv::ocl;
1022     Context& ctx = Context::getDefault();
1023     cl_context context = (cl_context)ctx.ptr();
1024 
1025     UMat u = src.getUMat();
1026 
1027     // TODO Add support for roi
1028     CV_Assert(u.offset == 0);
1029     CV_Assert(u.isContinuous());
1030 
1031     cl_int status = 0;
1032     cl_dx9_surface_info_khr surfaceInfo = {pDirect3DSurface9, (HANDLE)surfaceSharedHandle};
1033     cl_mem clImage = clCreateFromDX9MediaSurfaceKHR(context, CL_MEM_WRITE_ONLY,
1034             ocl::g_isDirect3DDevice9Ex ? CL_ADAPTER_D3D9EX_KHR : CL_ADAPTER_D3D9_KHR,
1035             &surfaceInfo, 0, &status);
1036     if (status != CL_SUCCESS)
1037         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromDX9MediaSurfaceKHR failed");
1038 
1039     cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
1040 
1041     cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
1042     status = clEnqueueAcquireDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
1043     if (status != CL_SUCCESS)
1044         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed");
1045     size_t offset = 0; // TODO
1046     size_t dst_origin[3] = {0, 0, 0};
1047     size_t region[3] = {u.cols, u.rows, 1};
1048     status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
1049     if (status != CL_SUCCESS)
1050         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
1051     status = clEnqueueReleaseDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
1052     if (status != CL_SUCCESS)
1053         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseDX9MediaSurfacesKHR failed");
1054 
1055     status = clFinish(q); // TODO Use events
1056     if (status != CL_SUCCESS)
1057         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
1058 
1059     status = clReleaseMemObject(clImage); // TODO RAII
1060     if (status != CL_SUCCESS)
1061         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
1062 #else
1063     // TODO pDirect3DSurface9->LockRect() + memcpy + Unlock()
1064     NO_OPENCL_SUPPORT_ERROR;
1065 #endif
1066 }
1067 
convertFromDirect3DSurface9(IDirect3DSurface9 * pDirect3DSurface9,OutputArray dst,void * surfaceSharedHandle)1068 void convertFromDirect3DSurface9(IDirect3DSurface9* pDirect3DSurface9, OutputArray dst, void* surfaceSharedHandle)
1069 {
1070     (void)pDirect3DSurface9; (void)dst; (void)surfaceSharedHandle;
1071 #if !defined(HAVE_DIRECTX)
1072     NO_DIRECTX_SUPPORT_ERROR;
1073 #elif defined(HAVE_OPENCL)
1074     __OpenCLinitializeD3D9();
1075 
1076     D3DSURFACE_DESC desc;
1077     if (FAILED(pDirect3DSurface9->GetDesc(&desc)))
1078     {
1079         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: Can't get D3D surface description");
1080     }
1081 
1082     int surfaceType = getTypeFromD3DFORMAT(desc.Format);
1083     CV_Assert(surfaceType >= 0);
1084 
1085     using namespace cv::ocl;
1086     Context& ctx = Context::getDefault();
1087     cl_context context = (cl_context)ctx.ptr();
1088 
1089     // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
1090     dst.create(Size(desc.Width, desc.Height), surfaceType);
1091     UMat u = dst.getUMat();
1092 
1093     // TODO Add support for roi
1094     CV_Assert(u.offset == 0);
1095     CV_Assert(u.isContinuous());
1096 
1097     cl_int status = 0;
1098     cl_dx9_surface_info_khr surfaceInfo = {pDirect3DSurface9, (HANDLE)surfaceSharedHandle};
1099     cl_mem clImage = clCreateFromDX9MediaSurfaceKHR(context, CL_MEM_READ_ONLY,
1100             ocl::g_isDirect3DDevice9Ex ? CL_ADAPTER_D3D9EX_KHR : CL_ADAPTER_D3D9_KHR,
1101             &surfaceInfo, 0, &status);
1102     if (status != CL_SUCCESS)
1103         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromDX9MediaSurfaceKHR failed");
1104 
1105     cl_mem clBuffer = (cl_mem)u.handle(ACCESS_WRITE);
1106 
1107     cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
1108     status = clEnqueueAcquireDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
1109     if (status != CL_SUCCESS)
1110         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed");
1111     size_t offset = 0; // TODO
1112     size_t src_origin[3] = {0, 0, 0};
1113     size_t region[3] = {u.cols, u.rows, 1};
1114     status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
1115     if (status != CL_SUCCESS)
1116         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
1117     status = clEnqueueReleaseDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
1118     if (status != CL_SUCCESS)
1119         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseDX9MediaSurfacesKHR failed");
1120 
1121     status = clFinish(q); // TODO Use events
1122     if (status != CL_SUCCESS)
1123         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
1124 
1125     status = clReleaseMemObject(clImage); // TODO RAII
1126     if (status != CL_SUCCESS)
1127         CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
1128 #else
1129     // TODO pDirect3DSurface9->LockRect() + memcpy + Unlock()
1130     NO_OPENCL_SUPPORT_ERROR;
1131 #endif
1132 }
1133 
1134 } } // namespace cv::directx
1135