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__(clGetExtensionFunctionAddress) *clGetExtensionFunctionAddress_fn;
57 typedef __typeof__(clGetPlatformInfo) *clGetPlatformInfo_fn;
61 cl_uint num_platforms;
62 cl_uint first_platform;
64 clGetExtensionFunctionAddress_fn ext_fn_ptr;
67 inline void dump_vendor_icd(const char* info, const struct vendor_icd *v) {
68 debug(D_DUMP, "%s %p={ num=%i, first=%i, handle=%p, f=%p}\n", info,
69 v, v->num_platforms, v->first_platform, v->dl_handle, v->ext_fn_ptr);
73 char * extension_suffix;
75 struct vendor_icd *vicd;
79 struct vendor_icd *_icds=NULL;
80 struct platform_icd *_picds=NULL;
81 static cl_uint _num_icds = 0;
82 static cl_uint _num_picds = 0;
85 # define _clS(x) [-x] = #x
86 # define MAX_CL_ERRORS (-CL_INVALID_DEVICE_PARTITION_COUNT)
87 static char const * const clErrorStr[MAX_CL_ERRORS+1] = {
89 _clS(CL_DEVICE_NOT_FOUND),
90 _clS(CL_DEVICE_NOT_AVAILABLE),
91 _clS(CL_COMPILER_NOT_AVAILABLE),
92 _clS(CL_MEM_OBJECT_ALLOCATION_FAILURE),
93 _clS(CL_OUT_OF_RESOURCES),
94 _clS(CL_OUT_OF_HOST_MEMORY),
95 _clS(CL_PROFILING_INFO_NOT_AVAILABLE),
96 _clS(CL_MEM_COPY_OVERLAP),
97 _clS(CL_IMAGE_FORMAT_MISMATCH),
98 _clS(CL_IMAGE_FORMAT_NOT_SUPPORTED),
99 _clS(CL_BUILD_PROGRAM_FAILURE),
100 _clS(CL_MAP_FAILURE),
101 _clS(CL_MISALIGNED_SUB_BUFFER_OFFSET),
102 _clS(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST),
103 _clS(CL_COMPILE_PROGRAM_FAILURE),
104 _clS(CL_LINKER_NOT_AVAILABLE),
105 _clS(CL_LINK_PROGRAM_FAILURE),
106 _clS(CL_DEVICE_PARTITION_FAILED),
107 _clS(CL_KERNEL_ARG_INFO_NOT_AVAILABLE),
108 _clS(CL_INVALID_VALUE),
109 _clS(CL_INVALID_DEVICE_TYPE),
110 _clS(CL_INVALID_PLATFORM),
111 _clS(CL_INVALID_DEVICE),
112 _clS(CL_INVALID_CONTEXT),
113 _clS(CL_INVALID_QUEUE_PROPERTIES),
114 _clS(CL_INVALID_COMMAND_QUEUE),
115 _clS(CL_INVALID_HOST_PTR),
116 _clS(CL_INVALID_MEM_OBJECT),
117 _clS(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR),
118 _clS(CL_INVALID_IMAGE_SIZE),
119 _clS(CL_INVALID_SAMPLER),
120 _clS(CL_INVALID_BINARY),
121 _clS(CL_INVALID_BUILD_OPTIONS),
122 _clS(CL_INVALID_PROGRAM),
123 _clS(CL_INVALID_PROGRAM_EXECUTABLE),
124 _clS(CL_INVALID_KERNEL_NAME),
125 _clS(CL_INVALID_KERNEL_DEFINITION),
126 _clS(CL_INVALID_KERNEL),
127 _clS(CL_INVALID_ARG_INDEX),
128 _clS(CL_INVALID_ARG_VALUE),
129 _clS(CL_INVALID_ARG_SIZE),
130 _clS(CL_INVALID_KERNEL_ARGS),
131 _clS(CL_INVALID_WORK_DIMENSION),
132 _clS(CL_INVALID_WORK_GROUP_SIZE),
133 _clS(CL_INVALID_WORK_ITEM_SIZE),
134 _clS(CL_INVALID_GLOBAL_OFFSET),
135 _clS(CL_INVALID_EVENT_WAIT_LIST),
136 _clS(CL_INVALID_EVENT),
137 _clS(CL_INVALID_OPERATION),
138 _clS(CL_INVALID_GL_OBJECT),
139 _clS(CL_INVALID_BUFFER_SIZE),
140 _clS(CL_INVALID_MIP_LEVEL),
141 _clS(CL_INVALID_GLOBAL_WORK_SIZE),
142 _clS(CL_INVALID_PROPERTY),
143 _clS(CL_INVALID_IMAGE_DESCRIPTOR),
144 _clS(CL_INVALID_COMPILER_OPTIONS),
145 _clS(CL_INVALID_LINKER_OPTIONS),
146 _clS(CL_INVALID_DEVICE_PARTITION_COUNT)
151 static char* _clerror2string (cl_int error) __attribute__((unused));
152 static char* _clerror2string (cl_int error) {
154 if (-error > MAX_CL_ERRORS || error > 0) {
155 debug(D_WARN, "Unknown error code %d", error);
156 RETURN_STR("OpenCL Error");
158 const char *ret=clErrorStr[-error];
160 debug(D_WARN, "Unknown error code %d", error);
161 RETURN_STR("OpenCL Error");
165 static char number[15];
167 RETURN_STR("CL_SUCCESS");
169 snprintf(number, 15, "%i", error);
174 static inline int _string_end_with_icd(const char* str) {
175 size_t len = strlen(str);
176 if( len<5 || strcmp(str + len - 4, ".icd" ) != 0 ) {
182 static inline int _string_with_slash(const char* str) {
183 return strchr(str, '/') != NULL;
186 static inline unsigned int _find_num_icds(DIR *dir) {
187 unsigned int num_icds = 0;
189 while( (ent=readdir(dir)) != NULL ){
190 if (_string_end_with_icd(ent->d_name)) {
198 static inline unsigned int _load_icd(int num_icds, const char* lib_path) {
200 debug(D_LOG, "Loading ICD '%s'", lib_path);
202 _icds[num_icds].dl_handle = dlopen(lib_path, RTLD_LAZY|RTLD_LOCAL);//|RTLD_DEEPBIND);
203 if(_icds[num_icds].dl_handle != NULL) {
204 debug(D_LOG, "ICD[%i] loaded", num_icds);
207 debug(D_WARN, "error while dlopening the IDL: '%s',\n => skipping ICD", dlerror());
212 static inline unsigned int _open_driver(unsigned int num_icds,
213 const char*dir_path, const char*file_path) {
216 unsigned int lib_path_length;
217 if (dir_path != NULL) {
218 lib_path_length = strlen(dir_path) + strlen(file_path) + 2;
219 lib_path = malloc(lib_path_length*sizeof(char));
220 sprintf(lib_path,"%s/%s", dir_path, file_path);
222 lib_path_length = strlen(file_path) + 1;
223 lib_path = malloc(lib_path_length*sizeof(char));
224 sprintf(lib_path,"%s", file_path);
226 debug(D_LOG, "Considering file '%s'", lib_path);
227 FILE *f = fopen(lib_path,"r");
233 fseek(f, 0, SEEK_END);
234 lib_path_length = ftell(f)+1;
235 fseek(f, 0, SEEK_SET);
236 if(lib_path_length == 1) {
237 debug(D_WARN, "File contents too short, skipping ICD");
241 lib_path = malloc(lib_path_length*sizeof(char));
242 err = fgets(lib_path, lib_path_length, f);
246 debug(D_WARN, "Error while loading file contents, skipping ICD");
250 lib_path_length = strlen(lib_path);
252 if( lib_path[lib_path_length-1] == '\n' )
253 lib_path[lib_path_length-1] = '\0';
255 num_icds += _load_icd(num_icds, lib_path);
261 static inline unsigned int _open_drivers(DIR *dir, const char* dir_path) {
262 unsigned int num_icds = 0;
264 while( (ent=readdir(dir)) != NULL ){
265 if(! _string_end_with_icd(ent->d_name)) {
268 num_icds = _open_driver(num_icds, dir_path, ent->d_name);
274 static void* _get_function_addr(void* dlh, clGetExtensionFunctionAddress_fn fn, const char*name) {
276 debug(D_LOG,"Looking for function %s",name);
277 addr1=dlsym(dlh, name);
279 debug(D_WARN, "Missing global symbol '%s' in ICD, should be skipped", name);
285 debug(D_WARN, "Missing function '%s' in ICD, should be skipped", name);
288 if (addr1 && addr2 && addr1!=addr2) {
289 debug(D_WARN, "Function and symbol '%s' have different addresses!", name);
293 if (!addr2) addr2=addr1;
297 static int _allocate_platforms(int req) {
298 static cl_uint allocated=0;
299 debug(D_LOG,"Requesting allocation for %d platforms",req);
300 if (allocated - _num_picds < req) {
302 _picds=(struct platform_icd*)malloc(req*sizeof(struct platform_icd));
304 req = req - (allocated - _num_picds);
305 _picds=(struct platform_icd*)realloc(_picds, (allocated+req)*sizeof(struct platform_icd));
309 RETURN(allocated - _num_picds);
312 static char* _malloc_clGetPlatformInfo(clGetPlatformInfo_fn plt_info_ptr,
313 cl_platform_id pid, cl_platform_info cname, char* sname) {
315 size_t param_value_size_ret;
316 error = plt_info_ptr(pid, cname, 0, NULL, ¶m_value_size_ret);
317 if (error != CL_SUCCESS) {
318 debug(D_WARN, "Error %s while requesting %s in platform %p",
319 _clerror2string(error), sname, pid);
322 char *param_value = (char *)malloc(sizeof(char)*param_value_size_ret);
323 if (param_value == NULL) {
324 debug(D_WARN, "Error in malloc while requesting %s in platform %p",
328 error = plt_info_ptr(pid, cname, param_value_size_ret, param_value, NULL);
329 if (error != CL_SUCCESS){
331 debug(D_WARN, "Error %s while requesting %s in platform %p",
332 _clerror2string(error), sname, pid);
335 RETURN_STR(param_value);
338 static inline void _find_and_check_platforms(cl_uint num_icds) {
341 for( i=0; i<num_icds; i++){
342 debug(D_LOG, "Checking ICD %i/%i", i, num_icds);
343 dump_vendor_icd("before looking for platforms", &_icds[i]);
344 struct vendor_icd *picd = &_icds[i];
345 void* dlh = _icds[i].dl_handle;
346 picd->ext_fn_ptr = _get_function_addr(dlh, NULL, "clGetExtensionFunctionAddress");
347 clIcdGetPlatformIDsKHR_fn plt_fn_ptr =
348 _get_function_addr(dlh, picd->ext_fn_ptr, "clIcdGetPlatformIDsKHR");
349 clGetPlatformInfo_fn plt_info_ptr =
350 _get_function_addr(dlh, picd->ext_fn_ptr, "clGetPlatformInfo");
351 if( picd->ext_fn_ptr == NULL
352 || plt_fn_ptr == NULL
353 || plt_info_ptr == NULL) {
354 debug(D_WARN, "Missing symbols in ICD, skipping it");
357 cl_uint num_platforms=0;
359 error = (*plt_fn_ptr)(0, NULL, &num_platforms);
360 if( error != CL_SUCCESS || num_platforms == 0) {
361 debug(D_LOG, "No platform in ICD, skipping it");
364 cl_platform_id *platforms = (cl_platform_id *) malloc( sizeof(cl_platform_id) * num_platforms);
365 error = (*plt_fn_ptr)(num_platforms, platforms, NULL);
366 if( error != CL_SUCCESS ){
368 debug(D_WARN, "Error in loading ICD platforms, skipping ICD");
371 cl_uint num_valid_platforms=0;
373 debug(D_LOG, "Try to load %d plateforms", num_platforms);
374 if (_allocate_platforms(num_platforms) < num_platforms) {
376 debug(D_WARN, "Not enought platform allocated. Skipping ICD");
379 for(j=0; j<num_platforms; j++) {
380 debug(D_LOG, "Checking platform %i", j);
381 struct platform_icd *p=&_picds[_num_picds];
382 char *param_value=NULL;
383 p->extension_suffix=NULL;
387 if (debug_ocl_icd_mask & D_DUMP) {
388 int log=debug_ocl_icd_mask & D_TRACE;
389 debug_ocl_icd_mask &= ~D_TRACE;
390 dump_platform(p->vicd->ext_fn_ptr, p->pid);
391 debug_ocl_icd_mask |= log;
395 /* Allow to workaround a bug in the Intel ICD used
396 * with optirun (search for NVidia Optimus for more info)
398 const char* str=getenv("OCL_ICD_ASSUME_ICD_EXTENSION");
399 if (! str || str[0]==0) {
400 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_EXTENSIONS, "extensions");
401 if (param_value == NULL){
402 debug(D_WARN, "Skipping platform %i", j);
405 debug(D_DUMP, "Supported extensions: %s", param_value);
406 if( strstr(param_value, "cl_khr_icd") == NULL){
408 debug(D_WARN, "Missing khr extension in platform %i, skipping it", j);
414 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_ICD_SUFFIX_KHR, "suffix");
415 if (param_value == NULL){
416 debug(D_WARN, "Skipping platform %i", j);
419 p->extension_suffix = param_value;
420 debug(D_DUMP|D_LOG, "Extension suffix: %s", param_value);
422 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_PROFILE, "profile");
423 if (param_value != NULL){
424 debug(D_DUMP, "Profile: %s", param_value);
427 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VERSION, "version");
428 p->version = param_value;
429 if (param_value != NULL){
430 debug(D_DUMP, "Version: %s", param_value);
433 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_NAME, "name");
434 if (param_value != NULL){
435 debug(D_DUMP, "Name: %s", param_value);
438 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VENDOR, "vendor");
439 if (param_value != NULL){
440 debug(D_DUMP, "Vendor: %s", param_value);
444 num_valid_platforms++;
447 if( num_valid_platforms != 0 ) {
448 if ( _num_icds != i ) {
449 picd->dl_handle = dlh;
451 dump_vendor_icd("after looking for platforms", &_icds[_num_icds]);
453 picd->num_platforms = num_valid_platforms;
454 _icds[i].first_platform = _num_picds - num_valid_platforms;
462 static void __initClIcd( void ) {
464 cl_uint num_icds = 0;
467 const char* dir_path=getenv("OCL_ICD_VENDORS");
468 if (! dir_path || dir_path[0]==0) {
469 debug(D_DUMP, "OCL_ICD_VENDORS empty or not defined, using %s", ETC_OPENCL_VENDORS);
470 dir_path=ETC_OPENCL_VENDORS;
475 int ret=stat(dir_path, &buf);
476 if (ret != 0 && errno != ENOENT) {
477 debug(D_WARN, "Cannot stat '%s'. Aborting", dir_path);
479 if (ret == 0 && S_ISDIR(buf.st_mode)) {
485 debug(D_LOG,"Only loading '%s' as an ICD", dir_path);
489 debug(D_LOG,"Reading icd list from '%s'", dir_path);
490 dir = opendir(dir_path);
492 if (errno == ENOTDIR) {
493 debug(D_DUMP, "%s is not a directory, trying to use it as a ICD libname",
499 num_icds = _find_num_icds(dir);
505 _icds = (struct vendor_icd*)malloc(num_icds * sizeof(struct vendor_icd));
511 if (_string_end_with_icd(dir_path)) {
513 if (! _string_with_slash(dir_path)) {
514 num_icds = _open_driver(0, ETC_OPENCL_VENDORS, dir_path);
517 num_icds = _open_driver(0, NULL, dir_path);
520 num_icds = _load_icd(0, dir_path);
523 num_icds = _open_drivers(dir, dir_path);
529 _find_and_check_platforms(num_icds);
534 if (_num_icds < num_icds) {
535 _icds = (struct vendor_icd*)realloc(_icds, _num_icds * sizeof(struct vendor_icd));
537 debug(D_WARN, "%d valid vendor(s)!", _num_icds);
549 static pthread_once_t once_init = PTHREAD_ONCE_INIT;
553 volatile static __thread int in_init = 0;
554 volatile static cl_uint _initialized = 0;
556 static inline void __attribute__((constructor)) _initClIcd( void ) {
561 /* probably reentrency */
564 __sync_synchronize();
565 pthread_once(&once_init, &__initClIcd);
566 __sync_synchronize();
570 if (__sync_bool_compare_and_swap(&gard, 0, 1)) {
572 __sync_synchronize();
574 __sync_synchronize();
578 /* probably reentrency (could also be user threads). */
580 /* someone else started __initClIcd(). We wait until its end. */
581 debug(D_WARN, "Waiting end of init");
582 while (!_initialized) ;
583 debug(D_WARN, "Wait done");
590 #pragma GCC visibility pop
591 #define hidden_alias(name) \
592 typeof(name) name##_hid __attribute__ ((alias (#name), visibility("hidden")))
595 CL_ICDL_OCL_VERSION=1,
601 static cl_int clGetICDLoaderInfoOCLICD(
602 cl_icdl_info param_name,
603 size_t param_value_size,
605 size_t * param_value_size_ret)
607 char cl_icdl_ocl_version[] = "OpenCL 1.2";
608 char cl_icdl_version[] = PACKAGE_VERSION;
609 char cl_icdl_name[] = PACKAGE_NAME;
610 char cl_icdl_vendor[] = "OCL Icd free software";
614 #define oclcase(name, NAME) \
615 case CL_ICDL_##NAME: \
616 string_p = cl_icdl_##name; \
617 size_string = sizeof(cl_icdl_##name); \
620 switch ( param_name ) {
621 oclcase(ocl_version,OCL_VERSION);
622 oclcase(version,VERSION);
624 oclcase(vendor,VENDOR);
626 return CL_INVALID_VALUE;
630 if( param_value != NULL ) {
631 if( size_string > param_value_size )
632 return CL_INVALID_VALUE;
633 memcpy(param_value, string_p, size_string);
635 if( param_value_size_ret != NULL )
636 *param_value_size_ret = size_string;
640 CL_API_ENTRY void * CL_API_CALL
641 clGetExtensionFunctionAddress(const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
644 if( func_name == NULL )
646 cl_uint suffix_length;
648 void * return_value=NULL;
649 struct func_desc const * fn=&function_description[0];
650 int lenfn=strlen(func_name);
652 (strcmp(func_name+lenfn-3, "KHR")==0 || strcmp(func_name+lenfn-3, "EXT")==0)) {
653 while (fn->name != NULL) {
654 if (strcmp(func_name, fn->name)==0)
659 for(i=0; i<_num_picds; i++) {
660 suffix_length = strlen(_picds[i].extension_suffix);
661 if( suffix_length > strlen(func_name) )
663 if(strcmp(_picds[i].extension_suffix, &func_name[strlen(func_name)-suffix_length]) == 0)
664 RETURN((*_picds[i].vicd->ext_fn_ptr)(func_name));
666 if(strcmp(func_name, "clGetICDLoaderInfoOCLICD") == 0) {
667 return (void*)(void*(*)(void))(&clGetICDLoaderInfoOCLICD);
669 RETURN(return_value);
671 hidden_alias(clGetExtensionFunctionAddress);
673 CL_API_ENTRY cl_int CL_API_CALL
674 clGetPlatformIDs(cl_uint num_entries,
675 cl_platform_id * platforms,
676 cl_uint * num_platforms) CL_API_SUFFIX__VERSION_1_0 {
679 if( platforms == NULL && num_platforms == NULL )
680 RETURN(CL_INVALID_VALUE);
681 if( num_entries == 0 && platforms != NULL )
682 RETURN(CL_INVALID_VALUE);
683 if( _num_icds == 0 || _num_picds == 0 ) {
684 if ( num_platforms != NULL )
686 RETURN(CL_PLATFORM_NOT_FOUND_KHR);
690 if( num_platforms != NULL ){
691 *num_platforms = _num_picds;
693 if( platforms != NULL ) {
694 cl_uint n_platforms = _num_picds < num_entries ? _num_picds : num_entries;
695 for( i=0; i<n_platforms; i++) {
696 *(platforms++) = _picds[i].pid;
701 hidden_alias(clGetPlatformIDs);
703 CL_API_ENTRY cl_context CL_API_CALL
704 clCreateContext(const cl_context_properties * properties ,
705 cl_uint num_devices ,
706 const cl_device_id * devices ,
707 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
709 cl_int * errcode_ret ){
713 if( properties != NULL){
714 while( properties[i] != 0 ) {
715 if( properties[i] == CL_CONTEXT_PLATFORM )
716 RETURN(((struct _cl_platform_id *) properties[i+1])
717 ->dispatch->clCreateContext(properties, num_devices, devices,
718 pfn_notify, user_data, errcode_ret));
722 if(devices == NULL || num_devices == 0) {
724 *errcode_ret = CL_INVALID_VALUE;
728 RETURN(((struct _cl_device_id *)devices[0])
729 ->dispatch->clCreateContext(properties, num_devices, devices,
730 pfn_notify, user_data, errcode_ret));
732 hidden_alias(clCreateContext);
734 CL_API_ENTRY cl_context CL_API_CALL
735 clCreateContextFromType(const cl_context_properties * properties ,
736 cl_device_type device_type ,
737 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
739 cl_int * errcode_ret ){
743 if( properties != NULL){
744 while( properties[i] != 0 ) {
745 if( properties[i] == CL_CONTEXT_PLATFORM )
746 if (properties[i+1] == 0) {
749 return ((struct _cl_platform_id *) properties[i+1])
750 ->dispatch->clCreateContextFromType(properties, device_type,
751 pfn_notify, user_data, errcode_ret);
755 if(_num_picds == 0) {
757 *errcode_ret = CL_INVALID_VALUE;
761 const char *default_platform = getenv("OPENCL_ICD_DEFAULT_PLATFORM");
762 int num_default_platform;
764 if (! default_platform) {
765 num_default_platform = 0;
767 num_default_platform = strtol(default_platform, &end_scan, 10);
768 if (*default_platform == '\0' || *end_scan != '\0') {
772 if (num_default_platform < 0 || num_default_platform >= _num_picds) {
775 RETURN(_picds[num_default_platform].pid->dispatch->clCreateContextFromType
776 (properties, device_type, pfn_notify, user_data, errcode_ret));
780 *errcode_ret = CL_INVALID_PLATFORM;
784 hidden_alias(clCreateContextFromType);
786 CL_API_ENTRY cl_int CL_API_CALL
787 clGetGLContextInfoKHR(const cl_context_properties * properties ,
788 cl_gl_context_info param_name ,
789 size_t param_value_size ,
791 size_t * param_value_size_ret ){
795 if( properties != NULL){
796 while( properties[i] != 0 ) {
797 if( properties[i] == CL_CONTEXT_PLATFORM )
798 RETURN(((struct _cl_platform_id *) properties[i+1])
799 ->dispatch->clGetGLContextInfoKHR(properties, param_name,
800 param_value_size, param_value, param_value_size_ret));
804 RETURN(CL_INVALID_PLATFORM);
806 hidden_alias(clGetGLContextInfoKHR);
808 CL_API_ENTRY cl_int CL_API_CALL
809 clWaitForEvents(cl_uint num_events ,
810 const cl_event * event_list ){
812 if( num_events == 0 || event_list == NULL )
813 RETURN(CL_INVALID_VALUE);
814 RETURN(((struct _cl_event *)event_list[0])
815 ->dispatch->clWaitForEvents(num_events, event_list));
817 hidden_alias(clWaitForEvents);
819 CL_API_ENTRY cl_int CL_API_CALL
820 clUnloadCompiler( void ){
824 hidden_alias(clUnloadCompiler);