1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include "setup.h"
17 #include "testBase.h"
18 #include "harness/errorHelpers.h"
19 #include <assert.h>
20 
21 #include <CL/cl.h>
22 #include <CL/cl_ext.h>
23 
24 #define EGLERR() \
25     assert(eglGetError() == EGL_SUCCESS); \
26 
27 #define MAX_DEVICES 10
28 
29 class EGLGLEnvironment : public GLEnvironment
30 {
31 private:
32     cl_platform_id _platform;
33     EGLDisplay     _display;
34     EGLContext     _context;
35     EGLSurface     _surface;
36 
37 public:
EGLGLEnvironment()38     EGLGLEnvironment()
39         :_platform(NULL)
40         ,_display(EGL_NO_DISPLAY)
41         ,_context(NULL)
42         ,_surface(EGL_NO_SURFACE)
43     {
44     }
45 
Init(int * argc,char ** argv,int use_opengl_32)46     virtual int Init( int *argc, char **argv, int use_opengl_32 )
47     {
48         EGLint ConfigAttribs[] =
49         {
50             EGL_RED_SIZE,        8,
51             EGL_GREEN_SIZE,     8,
52             EGL_BLUE_SIZE,        8,
53             EGL_ALPHA_SIZE,     8,
54             EGL_DEPTH_SIZE,     16,
55             EGL_SURFACE_TYPE,    EGL_PBUFFER_BIT,
56 //            EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE,
57             EGL_NONE
58         };
59 
60         static const EGLint ContextAttribs[] =
61         {
62             EGL_CONTEXT_CLIENT_VERSION, 2,
63             EGL_NONE
64         };
65 
66         EGLint conf_list[] = {
67                      EGL_WIDTH,  512,
68                      EGL_HEIGHT, 512,
69                      EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
70                      EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
71                      EGL_NONE};
72 
73         EGLint        majorVersion;
74         EGLint        minorVersion;
75         EGLConfig    config;
76         EGLint      numConfigs;
77 
78         EGLERR();
79         _display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
80         EGLERR();
81 
82         eglInitialize(_display, &majorVersion, &minorVersion);
83         EGLERR();
84 
85         eglBindAPI(EGL_OPENGL_ES_API);
86         EGLERR();
87 
88         eglChooseConfig(_display, ConfigAttribs, &config, 1, &numConfigs);
89         EGLERR();
90 
91         _context = eglCreateContext(_display, config, NULL, ContextAttribs);
92         EGLERR();
93 
94         _surface = eglCreatePbufferSurface(_display, config, conf_list);
95         EGLERR();
96 
97         eglMakeCurrent(_display, _surface, _surface, _context);
98         EGLERR();
99 
100         return 0;
101     }
102 
CreateCLContext(void)103     virtual cl_context CreateCLContext( void )
104     {
105         cl_context_properties properties[] = {
106             CL_CONTEXT_PLATFORM, (cl_context_properties) _platform,
107             CL_GL_CONTEXT_KHR,   (cl_context_properties) _context,
108             CL_EGL_DISPLAY_KHR,  (cl_context_properties) _display,
109             0
110         };
111         cl_device_id devices[MAX_DEVICES];
112         size_t dev_size;
113         cl_int status;
114 
115         clGetGLContextInfoKHR_fn GetGLContextInfo =
116             (clGetGLContextInfoKHR_fn)clGetExtensionFunctionAddressForPlatform(
117                 _platform, "clGetGLContextInfoKHR");
118         if (GetGLContextInfo == NULL)
119         {
120             print_error(status, "clGetGLContextInfoKHR failed");
121             return NULL;
122         }
123 
124         status = GetGLContextInfo(properties, CL_DEVICES_FOR_GL_CONTEXT_KHR,
125                                   sizeof(devices), devices, &dev_size);
126         if (status != CL_SUCCESS) {
127             print_error(status, "clGetGLContextInfoKHR failed");
128             return NULL;
129         }
130         dev_size /= sizeof(cl_device_id);
131         log_info("GL _context supports %d compute devices\n", dev_size);
132 
133         status =
134             GetGLContextInfo(properties, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
135                              sizeof(devices), devices, &dev_size);
136         if (status != CL_SUCCESS) {
137             print_error(status, "clGetGLContextInfoKHR failed");
138             return NULL;
139         }
140 
141         if (!dev_size)
142         {
143             log_info("GL _context current device is not a CL device.\n");
144             return NULL;
145         }
146 
147         return clCreateContext(properties, 1, &devices[0], NULL, NULL, &status);
148     }
149 
SupportsCLGLInterop(cl_device_type device_type)150     virtual int SupportsCLGLInterop( cl_device_type device_type )
151     {
152         cl_device_id devices[MAX_DEVICES];
153         cl_uint num_of_devices;
154         int interop_devices = 0;
155         int error;
156 
157         error = clGetPlatformIDs(1, &_platform, NULL);
158         if (error) {
159             print_error(error, "clGetPlatformIDs failed");
160             return -1;
161         }
162 
163         error = clGetDeviceIDs(_platform, device_type, MAX_DEVICES, devices, &num_of_devices);
164         if (error) {
165             print_error(error, "clGetDeviceIDs failed");
166             return -1;
167         }
168 
169         // Check all devices, search for one that supports cl_khr_gl_sharing
170         for (int i=0; i<(int)num_of_devices; i++) {
171             if (!is_extension_available(devices[i], "cl_khr_gl_sharing"))
172             {
173                 log_info("Device %d of %d does not support required extension cl_khr_gl_sharing.\n", i+1, num_of_devices);
174             }
175             else
176             {
177                 log_info("Device %d of %d supports required extension cl_khr_gl_sharing.\n", i+1, num_of_devices);
178                 interop_devices++;
179             }
180         }
181         return interop_devices > 0;
182     }
183 
184     // Change to cleanup egl environment properly when the test exit.
185     // This change does not affect any functionality of the test it self
terminate_egl_display()186     virtual void terminate_egl_display()
187     {
188         if(_display != EGL_NO_DISPLAY)
189         {
190             eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
191             EGLERR();
192 
193             eglDestroyContext(_display, _context);
194             EGLERR();
195             _context = EGL_NO_CONTEXT;
196 
197             eglDestroySurface(_display, _surface);
198             EGLERR();
199             _surface = EGL_NO_SURFACE;
200 
201             eglTerminate(_display);
202             EGLERR();
203             _display = EGL_NO_DISPLAY;
204         }
205     }
206 
~EGLGLEnvironment()207     virtual ~EGLGLEnvironment()
208     {
209     }
210 };
211 
Instance(void)212 GLEnvironment * GLEnvironment::Instance( void )
213 {
214     return new EGLGLEnvironment();
215 }
216