42
42
43
43
#include " precomp.hpp"
44
44
45
+ #if defined (__APPLE__) || defined(MACOSX)
46
+ #define GL_SHARING_EXTENSION " cl_APPLE_gl_sharing"
47
+ #else
48
+ #define GL_SHARING_EXTENSION " cl_khr_gl_sharing"
49
+ #endif
50
+
45
51
#ifdef HAVE_OPENGL
46
52
# include " gl_core_3_1.hpp"
47
53
# ifdef HAVE_CUDA
@@ -1636,6 +1642,11 @@ Context& initializeContextFromGL()
1636
1642
NO_OPENCL_SHARING_ERROR;
1637
1643
#else
1638
1644
cl_uint numPlatforms;
1645
+ cl_device_id* devices = new cl_device_id[256 ];
1646
+ cl_uint devCnt;
1647
+ cl_uint devUsed;
1648
+ cl_context context;
1649
+
1639
1650
cl_int status = clGetPlatformIDs (0 , NULL , &numPlatforms);
1640
1651
if (status != CL_SUCCESS)
1641
1652
CV_Error_ (cv::Error::OpenCLInitError, (" OpenCL: Can't get number of platforms: %d" , status));
@@ -1645,84 +1656,112 @@ Context& initializeContextFromGL()
1645
1656
std::vector<cl_platform_id> platforms (numPlatforms);
1646
1657
status = clGetPlatformIDs (numPlatforms, &platforms[0 ], NULL );
1647
1658
if (status != CL_SUCCESS)
1648
- CV_Error_ (cv::Error::OpenCLInitError, (" OpenCL: Can't get number of platforms: %d" , status));
1659
+ CV_Error_ (cv::Error::OpenCLInitError, (" OpenCL: Can't get platforms: %d" , status));
1660
+
1649
1661
1650
1662
// TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
1663
+ bool sharingSupported = false ;
1651
1664
1652
- int found = -1 ;
1653
- cl_device_id device = NULL ;
1654
- cl_context context = NULL ;
1665
+ for (unsigned int i = 0 ; (!sharingSupported && (i < numPlatforms)); ++i) {
1666
+ status = clGetDeviceIDs (platforms[i], CL_DEVICE_TYPE_GPU, 0 , NULL , &devCnt);
1667
+ if (status != CL_SUCCESS)
1668
+ CV_Error_ (cv::Error::OpenCLInitError, (" OpenCL: No devices available: %d" , status));
1655
1669
1656
- for (int i = 0 ; i < (int )numPlatforms; i++)
1657
- {
1658
- // query platform extension: presence of "cl_khr_gl_sharing" extension is required
1659
- {
1660
- AutoBuffer<char > extensionStr;
1670
+ status = clGetDeviceIDs (platforms[i], CL_DEVICE_TYPE_GPU, devCnt, devices, NULL );
1671
+ if (status != CL_SUCCESS)
1672
+ CV_Error_ (cv::Error::OpenCLInitError, (" OpenCL: Can't get platform devices: %d" , status));
1661
1673
1674
+ for (unsigned int j = 0 ; (!sharingSupported && (j < devCnt)); ++j) {
1662
1675
size_t extensionSize;
1663
- status = clGetPlatformInfo (platforms[i], CL_PLATFORM_EXTENSIONS, 0 , NULL , &extensionSize);
1664
- if (status == CL_SUCCESS)
1665
- {
1666
- extensionStr.allocate (extensionSize+1 );
1667
- status = clGetPlatformInfo (platforms[i], CL_PLATFORM_EXTENSIONS, extensionSize, (char *)extensionStr.data (), NULL );
1668
- }
1676
+ status = clGetDeviceInfo (devices[j], CL_DEVICE_EXTENSIONS, 0 , NULL , &extensionSize );
1669
1677
if (status != CL_SUCCESS)
1670
- CV_Error_ (cv::Error::OpenCLInitError, (" OpenCL: Can't get platform extension string : %d" , status));
1678
+ CV_Error_ (cv::Error::OpenCLInitError, (" OpenCL: No devices available : %d" , status));
1671
1679
1672
- if (!strstr ((const char *)extensionStr.data (), " cl_khr_gl_sharing" ))
1673
- continue ;
1680
+ if (extensionSize > 0 )
1681
+ {
1682
+ char * extensions = (char *)malloc (extensionSize);
1683
+ status = clGetDeviceInfo (devices[j], CL_DEVICE_EXTENSIONS, extensionSize, extensions, &extensionSize);
1684
+ if (status != CL_SUCCESS)
1685
+ continue ;
1686
+
1687
+ std::string stdDevString (extensions);
1688
+ free (extensions);
1689
+
1690
+
1691
+ size_t szOldPos = 0 ;
1692
+ size_t szSpacePos = stdDevString.find (' ' , szOldPos); // extensions string is space delimited
1693
+ while (szSpacePos != stdDevString.npos ) {
1694
+ if (strcmp (GL_SHARING_EXTENSION,
1695
+ stdDevString.substr (szOldPos, szSpacePos - szOldPos).c_str ())
1696
+ == 0 ) {
1697
+ // Device supports context sharing with OpenGL
1698
+ devUsed = i;
1699
+ sharingSupported = true ;
1700
+ break ;
1701
+ }
1702
+ do {
1703
+ szOldPos = szSpacePos + 1 ;
1704
+ szSpacePos = stdDevString.find (' ' , szOldPos);
1705
+ } while (szSpacePos == szOldPos);
1706
+ }
1707
+ }
1674
1708
}
1675
1709
1676
- clGetGLContextInfoKHR_fn clGetGLContextInfoKHR = (clGetGLContextInfoKHR_fn)
1677
- clGetExtensionFunctionAddressForPlatform (platforms[i], " clGetGLContextInfoKHR" );
1678
- if (!clGetGLContextInfoKHR)
1679
- continue ;
1710
+ if (!sharingSupported)
1711
+ CV_Error_ (cv::Error::OpenCLInitError, (" OpenCL: OpenGL sharing not supported: %d" , status));
1680
1712
1681
- cl_context_properties properties[] =
1682
- {
1683
- #if defined(_WIN32)
1684
- CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1685
- CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext (),
1686
- CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC (),
1687
- #elif defined(__ANDROID__)
1688
- CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1689
- CL_GL_CONTEXT_KHR, (cl_context_properties)eglGetCurrentContext (),
1690
- CL_EGL_DISPLAY_KHR, (cl_context_properties)eglGetCurrentDisplay (),
1691
- #elif defined(__linux__)
1692
- CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1693
- CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext (),
1694
- CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay (),
1695
- #endif
1696
- 0
1697
- };
1698
1713
1699
- // query device
1700
- device = NULL ;
1701
- status = clGetGLContextInfoKHR (properties, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, sizeof (cl_device_id), (void *)&device, NULL );
1702
- if (status != CL_SUCCESS)
1703
- continue ;
1714
+ // Define OS-specific context properties and create the OpenCL context
1715
+ #if defined (__APPLE__)
1716
+ CGLContextObj kCGLContext = CGLGetCurrentContext ();
1717
+ CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup (kCGLContext );
1718
+ cl_context_properties props[] =
1719
+ {
1720
+ CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup ,
1721
+ 0
1722
+ };
1723
+ context = clCreateContext (props, 0 ,0 , NULL , NULL , &ciErrNum);
1724
+ #elif defined(__ANDROID__)
1725
+ cl_context_properties props[] =
1726
+ {
1727
+ CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext (),
1728
+ CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay (),
1729
+ CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1730
+ 0
1731
+ };
1732
+ context = clCreateContext (props, 1 , &devices[devUsed], NULL , NULL , &status);
1733
+ #elif defined(_WIN32)
1734
+ cl_context_properties props[] =
1735
+ {
1736
+ CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext (),
1737
+ CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC (),
1738
+ CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1739
+ 0
1740
+ };
1741
+ context = clCreateContext (props, 1 , &devices[devUsed], NULL , NULL , &status);
1742
+ #elif defined(__linux__)
1743
+ cl_context_properties props[] =
1744
+ {
1745
+ CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext (),
1746
+ CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay (),
1747
+ CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1748
+ 0
1749
+ };
1750
+ context = clCreateContext (props, 1 , &devices[devUsed], NULL , NULL , &status);
1751
+ #endif
1704
1752
1705
- // create context
1706
- context = clCreateContext (properties, 1 , &device, NULL , NULL , &status);
1707
1753
if (status != CL_SUCCESS)
1708
- {
1709
- clReleaseDevice (device);
1710
- }
1754
+ CV_Error_ (cv::Error::OpenCLInitError, (" OpenCL: Can't create context for OpenGL interop: %d" , status));
1711
1755
else
1712
- {
1713
- found = i;
1714
1756
break ;
1715
- }
1716
1757
}
1717
1758
1718
- if (found < 0 )
1719
- CV_Error (cv::Error::OpenCLInitError, " OpenCL: Can't create context for OpenGL interop" );
1720
1759
1721
- cl_platform_id platform = platforms[found ];
1760
+ cl_platform_id platform = platforms[devUsed ];
1722
1761
std::string platformName = PlatformInfo (&platform).name ();
1723
1762
1724
- OpenCLExecutionContext clExecCtx = OpenCLExecutionContext::create (platformName, platform, context, device );
1725
- clReleaseDevice (device );
1763
+ OpenCLExecutionContext clExecCtx = OpenCLExecutionContext::create (platformName, platform, context, devices[devUsed] );
1764
+ clReleaseDevice (devices[devUsed] );
1726
1765
clReleaseContext (context);
1727
1766
clExecCtx.bind ();
1728
1767
return const_cast <Context&>(clExecCtx.getContext ());
0 commit comments