2 Copyright (c) 2012, Brice Videau <brice.videau@imag.fr>
3 Copyright (c) 2012, Vincent Danjean <Vincent.Danjean@ens-lyon.org>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice, this
10 list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/types.h>
40 #pragma GCC diagnostic push
41 # pragma GCC diagnostic ignored "-Wcpp"
42 # define CL_USE_DEPRECATED_OPENCL_1_1_APIS
43 # include <CL/opencl.h>
44 #pragma GCC diagnostic pop
46 #pragma GCC visibility push(hidden)
48 #include "ocl_icd_loader.h"
49 #define DEBUG_OCL_ICD_PROVIDE_DUMP_FIELD
50 #include "ocl_icd_debug.h"
52 #define ETC_OPENCL_VENDORS "/etc/OpenCL/vendors"
54 int debug_ocl_icd_mask=0;
56 typedef __typeof__(clGetPlatformInfo) *clGetPlatformInfo_fn;
58 inline void dump_vendor_icd(const char* info, const struct vendor_icd *v) {
59 debug(D_DUMP, "%s %p={ num=%i, first=%i, handle=%p, f=%p}\n", info,
60 v, v->num_platforms, v->first_platform, v->dl_handle, v->ext_fn_ptr);
63 struct vendor_icd *_icds=NULL;
64 struct platform_icd *_picds=NULL;
65 static cl_uint _num_icds = 0;
66 cl_uint _num_picds = 0;
69 # define _clS(x) [-x] = #x
70 # define MAX_CL_ERRORS (-CL_INVALID_DEVICE_PARTITION_COUNT)
71 static char const * const clErrorStr[MAX_CL_ERRORS+1] = {
73 _clS(CL_DEVICE_NOT_FOUND),
74 _clS(CL_DEVICE_NOT_AVAILABLE),
75 _clS(CL_COMPILER_NOT_AVAILABLE),
76 _clS(CL_MEM_OBJECT_ALLOCATION_FAILURE),
77 _clS(CL_OUT_OF_RESOURCES),
78 _clS(CL_OUT_OF_HOST_MEMORY),
79 _clS(CL_PROFILING_INFO_NOT_AVAILABLE),
80 _clS(CL_MEM_COPY_OVERLAP),
81 _clS(CL_IMAGE_FORMAT_MISMATCH),
82 _clS(CL_IMAGE_FORMAT_NOT_SUPPORTED),
83 _clS(CL_BUILD_PROGRAM_FAILURE),
85 _clS(CL_MISALIGNED_SUB_BUFFER_OFFSET),
86 _clS(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST),
87 _clS(CL_COMPILE_PROGRAM_FAILURE),
88 _clS(CL_LINKER_NOT_AVAILABLE),
89 _clS(CL_LINK_PROGRAM_FAILURE),
90 _clS(CL_DEVICE_PARTITION_FAILED),
91 _clS(CL_KERNEL_ARG_INFO_NOT_AVAILABLE),
92 _clS(CL_INVALID_VALUE),
93 _clS(CL_INVALID_DEVICE_TYPE),
94 _clS(CL_INVALID_PLATFORM),
95 _clS(CL_INVALID_DEVICE),
96 _clS(CL_INVALID_CONTEXT),
97 _clS(CL_INVALID_QUEUE_PROPERTIES),
98 _clS(CL_INVALID_COMMAND_QUEUE),
99 _clS(CL_INVALID_HOST_PTR),
100 _clS(CL_INVALID_MEM_OBJECT),
101 _clS(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR),
102 _clS(CL_INVALID_IMAGE_SIZE),
103 _clS(CL_INVALID_SAMPLER),
104 _clS(CL_INVALID_BINARY),
105 _clS(CL_INVALID_BUILD_OPTIONS),
106 _clS(CL_INVALID_PROGRAM),
107 _clS(CL_INVALID_PROGRAM_EXECUTABLE),
108 _clS(CL_INVALID_KERNEL_NAME),
109 _clS(CL_INVALID_KERNEL_DEFINITION),
110 _clS(CL_INVALID_KERNEL),
111 _clS(CL_INVALID_ARG_INDEX),
112 _clS(CL_INVALID_ARG_VALUE),
113 _clS(CL_INVALID_ARG_SIZE),
114 _clS(CL_INVALID_KERNEL_ARGS),
115 _clS(CL_INVALID_WORK_DIMENSION),
116 _clS(CL_INVALID_WORK_GROUP_SIZE),
117 _clS(CL_INVALID_WORK_ITEM_SIZE),
118 _clS(CL_INVALID_GLOBAL_OFFSET),
119 _clS(CL_INVALID_EVENT_WAIT_LIST),
120 _clS(CL_INVALID_EVENT),
121 _clS(CL_INVALID_OPERATION),
122 _clS(CL_INVALID_GL_OBJECT),
123 _clS(CL_INVALID_BUFFER_SIZE),
124 _clS(CL_INVALID_MIP_LEVEL),
125 _clS(CL_INVALID_GLOBAL_WORK_SIZE),
126 _clS(CL_INVALID_PROPERTY),
127 _clS(CL_INVALID_IMAGE_DESCRIPTOR),
128 _clS(CL_INVALID_COMPILER_OPTIONS),
129 _clS(CL_INVALID_LINKER_OPTIONS),
130 _clS(CL_INVALID_DEVICE_PARTITION_COUNT)
135 static char* _clerror2string (cl_int error) __attribute__((unused));
136 static char* _clerror2string (cl_int error) {
138 if (-error > MAX_CL_ERRORS || error > 0) {
139 debug(D_WARN, "Unknown error code %d", error);
140 RETURN_STR("OpenCL Error");
142 const char *ret=clErrorStr[-error];
144 debug(D_WARN, "Unknown error code %d", error);
145 RETURN_STR("OpenCL Error");
149 static char number[15];
151 RETURN_STR("CL_SUCCESS");
153 snprintf(number, 15, "%i", error);
158 static inline int _string_end_with_icd(const char* str) {
159 size_t len = strlen(str);
160 if( len<5 || strcmp(str + len - 4, ".icd" ) != 0 ) {
166 static inline int _string_with_slash(const char* str) {
167 return strchr(str, '/') != NULL;
170 static inline unsigned int _find_num_icds(DIR *dir) {
171 unsigned int num_icds = 0;
173 while( (ent=readdir(dir)) != NULL ){
174 if (_string_end_with_icd(ent->d_name)) {
182 static inline unsigned int _load_icd(int num_icds, const char* lib_path) {
184 debug(D_LOG, "Loading ICD '%s'", lib_path);
186 _icds[num_icds].dl_handle = dlopen(lib_path, RTLD_LAZY|RTLD_LOCAL);//|RTLD_DEEPBIND);
187 if(_icds[num_icds].dl_handle != NULL) {
188 debug(D_LOG, "ICD[%i] loaded", num_icds);
191 debug(D_WARN, "error while dlopening the IDL: '%s',\n => skipping ICD", dlerror());
196 static inline unsigned int _open_driver(unsigned int num_icds,
197 const char*dir_path, const char*file_path) {
200 unsigned int lib_path_length;
201 if (dir_path != NULL) {
202 lib_path_length = strlen(dir_path) + strlen(file_path) + 2;
203 lib_path = malloc(lib_path_length*sizeof(char));
204 sprintf(lib_path,"%s/%s", dir_path, file_path);
206 lib_path_length = strlen(file_path) + 1;
207 lib_path = malloc(lib_path_length*sizeof(char));
208 sprintf(lib_path,"%s", file_path);
210 debug(D_LOG, "Considering file '%s'", lib_path);
211 FILE *f = fopen(lib_path,"r");
217 fseek(f, 0, SEEK_END);
218 lib_path_length = ftell(f)+1;
219 fseek(f, 0, SEEK_SET);
220 if(lib_path_length == 1) {
221 debug(D_WARN, "File contents too short, skipping ICD");
225 lib_path = malloc(lib_path_length*sizeof(char));
226 err = fgets(lib_path, lib_path_length, f);
230 debug(D_WARN, "Error while loading file contents, skipping ICD");
234 lib_path_length = strnlen(lib_path, lib_path_length);
236 if( lib_path[lib_path_length-1] == '\n' )
237 lib_path[lib_path_length-1] = '\0';
239 num_icds += _load_icd(num_icds, lib_path);
245 static inline unsigned int _open_drivers(DIR *dir, const char* dir_path) {
246 unsigned int num_icds = 0;
248 while( (ent=readdir(dir)) != NULL ){
249 if(! _string_end_with_icd(ent->d_name)) {
252 num_icds = _open_driver(num_icds, dir_path, ent->d_name);
258 static void* _get_function_addr(void* dlh, clGetExtensionFunctionAddress_fn fn, const char*name) {
260 debug(D_LOG,"Looking for function %s",name);
261 addr1=dlsym(dlh, name);
263 debug(D_WARN, "Missing global symbol '%s' in ICD, should be skipped", name);
269 debug(D_WARN, "Missing function '%s' in ICD, should be skipped", name);
272 if (addr1 && addr2 && addr1!=addr2) {
273 debug(D_WARN, "Function and symbol '%s' have different addresses!", name);
277 if (!addr2) addr2=addr1;
281 static int _allocate_platforms(int req) {
282 static cl_uint allocated=0;
283 debug(D_LOG,"Requesting allocation for %d platforms",req);
284 if (allocated - _num_picds < req) {
286 _picds=(struct platform_icd*)malloc(req*sizeof(struct platform_icd));
288 req = req - (allocated - _num_picds);
289 _picds=(struct platform_icd*)realloc(_picds, (allocated+req)*sizeof(struct platform_icd));
293 RETURN(allocated - _num_picds);
296 static char* _malloc_clGetPlatformInfo(clGetPlatformInfo_fn plt_info_ptr,
297 cl_platform_id pid, cl_platform_info cname, char* sname) {
299 size_t param_value_size_ret;
300 error = plt_info_ptr(pid, cname, 0, NULL, ¶m_value_size_ret);
301 if (error != CL_SUCCESS) {
302 debug(D_WARN, "Error %s while requesting %s in platform %p",
303 _clerror2string(error), sname, pid);
306 char *param_value = (char *)malloc(sizeof(char)*param_value_size_ret);
307 if (param_value == NULL) {
308 debug(D_WARN, "Error in malloc while requesting %s in platform %p",
312 error = plt_info_ptr(pid, cname, param_value_size_ret, param_value, NULL);
313 if (error != CL_SUCCESS){
315 debug(D_WARN, "Error %s while requesting %s in platform %p",
316 _clerror2string(error), sname, pid);
319 RETURN_STR(param_value);
322 static inline void _find_and_check_platforms(cl_uint num_icds) {
325 for( i=0; i<num_icds; i++){
326 debug(D_LOG, "Checking ICD %i/%i", i, num_icds);
327 dump_vendor_icd("before looking for platforms", &_icds[i]);
328 struct vendor_icd *picd = &_icds[i];
329 void* dlh = _icds[i].dl_handle;
330 picd->ext_fn_ptr = _get_function_addr(dlh, NULL, "clGetExtensionFunctionAddress");
331 clIcdGetPlatformIDsKHR_fn plt_fn_ptr =
332 _get_function_addr(dlh, picd->ext_fn_ptr, "clIcdGetPlatformIDsKHR");
333 clGetPlatformInfo_fn plt_info_ptr =
334 _get_function_addr(dlh, picd->ext_fn_ptr, "clGetPlatformInfo");
335 if( picd->ext_fn_ptr == NULL
336 || plt_fn_ptr == NULL
337 || plt_info_ptr == NULL) {
338 debug(D_WARN, "Missing symbols in ICD, skipping it");
341 cl_uint num_platforms=0;
343 error = (*plt_fn_ptr)(0, NULL, &num_platforms);
344 if( error != CL_SUCCESS || num_platforms == 0) {
345 debug(D_LOG, "No platform in ICD, skipping it");
348 cl_platform_id *platforms = (cl_platform_id *) malloc( sizeof(cl_platform_id) * num_platforms);
349 error = (*plt_fn_ptr)(num_platforms, platforms, NULL);
350 if( error != CL_SUCCESS ){
352 debug(D_WARN, "Error in loading ICD platforms, skipping ICD");
355 cl_uint num_valid_platforms=0;
357 debug(D_LOG, "Try to load %d plateforms", num_platforms);
358 if (_allocate_platforms(num_platforms) < num_platforms) {
360 debug(D_WARN, "Not enought platform allocated. Skipping ICD");
363 for(j=0; j<num_platforms; j++) {
364 debug(D_LOG, "Checking platform %i", j);
365 struct platform_icd *p=&_picds[_num_picds];
366 char *param_value=NULL;
367 p->extension_suffix=NULL;
371 if (debug_ocl_icd_mask & D_DUMP) {
372 int log=debug_ocl_icd_mask & D_TRACE;
373 debug_ocl_icd_mask &= ~D_TRACE;
374 dump_platform(p->vicd->ext_fn_ptr, p->pid);
375 debug_ocl_icd_mask |= log;
379 /* Allow to workaround a bug in the Intel ICD used
380 * with optirun (search for NVidia Optimus for more info)
382 const char* str=getenv("OCL_ICD_ASSUME_ICD_EXTENSION");
383 if (! str || str[0]==0) {
384 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_EXTENSIONS, "extensions");
385 if (param_value == NULL){
386 debug(D_WARN, "Skipping platform %i", j);
389 debug(D_DUMP, "Supported extensions: %s", param_value);
390 if( strstr(param_value, "cl_khr_icd") == NULL){
392 debug(D_WARN, "Missing khr extension in platform %i, skipping it", j);
398 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_ICD_SUFFIX_KHR, "suffix");
399 if (param_value == NULL){
400 debug(D_WARN, "Skipping platform %i", j);
403 p->extension_suffix = param_value;
404 debug(D_DUMP|D_LOG, "Extension suffix: %s", param_value);
406 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_PROFILE, "profile");
407 if (param_value != NULL){
408 debug(D_DUMP, "Profile: %s", param_value);
411 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VERSION, "version");
412 p->version = param_value;
413 if (param_value != NULL){
414 debug(D_DUMP, "Version: %s", param_value);
417 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_NAME, "name");
418 if (param_value != NULL){
419 debug(D_DUMP, "Name: %s", param_value);
422 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VENDOR, "vendor");
423 if (param_value != NULL){
424 debug(D_DUMP, "Vendor: %s", param_value);
428 num_valid_platforms++;
431 if( num_valid_platforms != 0 ) {
432 if ( _num_icds != i ) {
433 picd->dl_handle = dlh;
435 dump_vendor_icd("after looking for platforms", &_icds[_num_icds]);
437 picd->num_platforms = num_valid_platforms;
438 _icds[i].first_platform = _num_picds - num_valid_platforms;
446 static void __initClIcd( void ) {
448 cl_uint num_icds = 0;
451 const char* dir_path=getenv("OCL_ICD_VENDORS");
452 if (! dir_path || dir_path[0]==0) {
453 debug(D_DUMP, "OCL_ICD_VENDORS empty or not defined, using %s", ETC_OPENCL_VENDORS);
454 dir_path=ETC_OPENCL_VENDORS;
459 int ret=stat(dir_path, &buf);
460 if (ret != 0 && errno != ENOENT) {
461 debug(D_WARN, "Cannot stat '%s'. Aborting", dir_path);
463 if (ret == 0 && S_ISDIR(buf.st_mode)) {
469 debug(D_LOG,"Only loading '%s' as an ICD", dir_path);
473 debug(D_LOG,"Reading icd list from '%s'", dir_path);
474 dir = opendir(dir_path);
476 if (errno == ENOTDIR) {
477 debug(D_DUMP, "%s is not a directory, trying to use it as a ICD libname",
483 num_icds = _find_num_icds(dir);
489 _icds = (struct vendor_icd*)malloc(num_icds * sizeof(struct vendor_icd));
495 if (_string_end_with_icd(dir_path)) {
497 if (! _string_with_slash(dir_path)) {
498 num_icds = _open_driver(0, ETC_OPENCL_VENDORS, dir_path);
501 num_icds = _open_driver(0, NULL, dir_path);
504 num_icds = _load_icd(0, dir_path);
507 num_icds = _open_drivers(dir, dir_path);
513 _find_and_check_platforms(num_icds);
518 if (_num_icds < num_icds) {
519 _icds = (struct vendor_icd*)realloc(_icds, _num_icds * sizeof(struct vendor_icd));
521 debug(D_WARN, "%d valid vendor(s)!", _num_icds);
540 static pthread_once_t once_init = PTHREAD_ONCE_INIT;
544 volatile static __thread int in_init = 0;
545 volatile static cl_uint _initialized = 0;
547 static void _initClIcd_real( void ) {
550 /* probably reentrency, in_init is a __thread variable */
551 debug(D_WARN, "Executing init while already in init!");
554 __sync_synchronize();
555 pthread_once(&once_init, &__initClIcd);
556 __sync_synchronize();
560 if (__sync_bool_compare_and_swap(&gard, 0, 1)) {
562 __sync_synchronize();
564 __sync_synchronize();
568 /* probably reentrency (could also be preemptive user-level threads). */
570 /* someone else started __initClIcd(). We wait until it ends. */
571 debug(D_WARN, "Waiting end of init");
572 while (!_initialized) {
573 __sync_synchronize();
575 debug(D_WARN, "Wait done");
582 static inline void _initClIcd( void ) {
583 if( __builtin_expect (_initialized, 1) )
588 cl_platform_id __attribute__((visibility("internal")))
589 getDefaultPlatformID() {
590 static cl_platform_id defaultPlatformID=NULL;
591 static int defaultSet=0;
595 if(_num_picds == 0) {
598 const char *default_platform = getenv("OPENCL_ICD_DEFAULT_PLATFORM");
599 int num_default_platform;
601 if (! default_platform) {
602 num_default_platform = 0;
604 num_default_platform = strtol(default_platform, &end_scan, 10);
605 if (*default_platform == '\0' || *end_scan != '\0') {
609 if (num_default_platform < 0 || num_default_platform >= _num_picds) {
612 defaultPlatformID=_picds[num_default_platform].pid;
616 return defaultPlatformID;
619 #pragma GCC visibility pop
620 #define hidden_alias(name) \
621 typeof(name) name##_hid __attribute__ ((alias (#name), visibility("hidden")))
624 CL_ICDL_OCL_VERSION=1,
630 static cl_int clGetICDLoaderInfoOCLICD(
631 cl_icdl_info param_name,
632 size_t param_value_size,
634 size_t * param_value_size_ret)
636 char cl_icdl_ocl_version[] = "OpenCL 1.2";
637 char cl_icdl_version[] = PACKAGE_VERSION;
638 char cl_icdl_name[] = PACKAGE_NAME;
639 char cl_icdl_vendor[] = "OCL Icd free software";
643 #define oclcase(name, NAME) \
644 case CL_ICDL_##NAME: \
645 string_p = cl_icdl_##name; \
646 size_string = sizeof(cl_icdl_##name); \
649 switch ( param_name ) {
650 oclcase(ocl_version,OCL_VERSION);
651 oclcase(version,VERSION);
653 oclcase(vendor,VENDOR);
655 return CL_INVALID_VALUE;
659 if( param_value != NULL ) {
660 if( size_string > param_value_size )
661 return CL_INVALID_VALUE;
662 memcpy(param_value, string_p, size_string);
664 if( param_value_size_ret != NULL )
665 *param_value_size_ret = size_string;
669 CL_API_ENTRY void * CL_API_CALL
670 clGetExtensionFunctionAddress(const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
673 if( func_name == NULL )
675 cl_uint suffix_length;
677 void * return_value=NULL;
678 struct func_desc const * fn=&function_description[0];
679 int lenfn=strlen(func_name);
681 (strcmp(func_name+lenfn-3, "KHR")==0 || strcmp(func_name+lenfn-3, "EXT")==0)) {
682 while (fn->name != NULL) {
683 if (strcmp(func_name, fn->name)==0)
688 for(i=0; i<_num_picds; i++) {
689 suffix_length = strlen(_picds[i].extension_suffix);
690 if( suffix_length > strlen(func_name) )
692 if(strcmp(_picds[i].extension_suffix, &func_name[strlen(func_name)-suffix_length]) == 0)
693 RETURN((*_picds[i].vicd->ext_fn_ptr)(func_name));
695 if(strcmp(func_name, "clGetICDLoaderInfoOCLICD") == 0) {
696 return (void*)(void*(*)(void))(&clGetICDLoaderInfoOCLICD);
698 RETURN(return_value);
700 hidden_alias(clGetExtensionFunctionAddress);
702 CL_API_ENTRY cl_int CL_API_CALL
703 clGetPlatformIDs(cl_uint num_entries,
704 cl_platform_id * platforms,
705 cl_uint * num_platforms) CL_API_SUFFIX__VERSION_1_0 {
708 if( platforms == NULL && num_platforms == NULL )
709 RETURN(CL_INVALID_VALUE);
710 if( num_entries == 0 && platforms != NULL )
711 RETURN(CL_INVALID_VALUE);
712 if( _num_icds == 0 || _num_picds == 0 ) {
713 if ( num_platforms != NULL )
715 RETURN(CL_PLATFORM_NOT_FOUND_KHR);
719 if( num_platforms != NULL ){
720 *num_platforms = _num_picds;
722 if( platforms != NULL ) {
723 cl_uint n_platforms = _num_picds < num_entries ? _num_picds : num_entries;
724 for( i=0; i<n_platforms; i++) {
725 *(platforms++) = _picds[i].pid;
730 hidden_alias(clGetPlatformIDs);
732 #define RETURN_WITH_ERRCODE(errvar, errvalue, retvalue) \
740 #define CHECK_PLATFORM(__pid) \
742 cl_platform_id _pid=(__pid); \
745 for( j=0; j<_num_picds; j++) { \
746 if( _picds[j].pid == _pid) { \
754 CL_API_ENTRY cl_context CL_API_CALL
755 clCreateContext(const cl_context_properties * properties ,
756 cl_uint num_devices ,
757 const cl_device_id * devices ,
758 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
760 cl_int * errcode_ret ){
764 if( properties != NULL){
765 while( properties[i] != 0 ) {
766 if( properties[i] == CL_CONTEXT_PLATFORM ) {
767 if((struct _cl_platform_id *) properties[i+1] == NULL) {
769 *errcode_ret = CL_INVALID_PLATFORM;
773 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
774 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
777 RETURN(((struct _cl_platform_id *) properties[i+1])
778 ->dispatch->clCreateContext(properties, num_devices, devices,
779 pfn_notify, user_data, errcode_ret));
784 if(devices == NULL || num_devices == 0) {
785 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_VALUE, NULL);
787 if((struct _cl_device_id *)devices[0] == NULL) {
788 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_DEVICE, NULL);
790 RETURN(((struct _cl_device_id *)devices[0])
791 ->dispatch->clCreateContext(properties, num_devices, devices,
792 pfn_notify, user_data, errcode_ret));
794 hidden_alias(clCreateContext);
796 CL_API_ENTRY cl_context CL_API_CALL
797 clCreateContextFromType(const cl_context_properties * properties ,
798 cl_device_type device_type ,
799 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
801 cl_int * errcode_ret ){
804 if(_num_picds == 0) {
808 if( properties != NULL){
809 while( properties[i] != 0 ) {
810 if( properties[i] == CL_CONTEXT_PLATFORM ) {
811 if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
814 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
818 return ((struct _cl_platform_id *) properties[i+1])
819 ->dispatch->clCreateContextFromType(properties, device_type,
820 pfn_notify, user_data, errcode_ret);
825 const char *default_platform = getenv("OPENCL_ICD_DEFAULT_PLATFORM");
826 int num_default_platform;
828 if (! default_platform) {
829 num_default_platform = 0;
831 num_default_platform = strtol(default_platform, &end_scan, 10);
832 if (*default_platform == '\0' || *end_scan != '\0') {
836 if (num_default_platform < 0 || num_default_platform >= _num_picds) {
839 RETURN(_picds[num_default_platform].pid->dispatch->clCreateContextFromType
840 (properties, device_type, pfn_notify, user_data, errcode_ret));
843 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
845 hidden_alias(clCreateContextFromType);
847 CL_API_ENTRY cl_int CL_API_CALL
848 clGetGLContextInfoKHR(const cl_context_properties * properties ,
849 cl_gl_context_info param_name ,
850 size_t param_value_size ,
852 size_t * param_value_size_ret ){
856 if( properties != NULL){
857 while( properties[i] != 0 ) {
858 if( properties[i] == CL_CONTEXT_PLATFORM ) {
859 if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
860 RETURN(CL_INVALID_PLATFORM);
862 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
863 RETURN(CL_INVALID_PLATFORM);
866 RETURN(((struct _cl_platform_id *) properties[i+1])
867 ->dispatch->clGetGLContextInfoKHR(properties, param_name,
868 param_value_size, param_value, param_value_size_ret));
873 RETURN(CL_INVALID_PLATFORM);
875 hidden_alias(clGetGLContextInfoKHR);
877 CL_API_ENTRY cl_int CL_API_CALL
878 clWaitForEvents(cl_uint num_events ,
879 const cl_event * event_list ){
881 if( num_events == 0 || event_list == NULL )
882 RETURN(CL_INVALID_VALUE);
883 if( (struct _cl_event *)event_list[0] == NULL )
884 RETURN(CL_INVALID_EVENT);
885 RETURN(((struct _cl_event *)event_list[0])
886 ->dispatch->clWaitForEvents(num_events, event_list));
888 hidden_alias(clWaitForEvents);
890 CL_API_ENTRY cl_int CL_API_CALL
891 clUnloadCompiler( void ){
895 hidden_alias(clUnloadCompiler);