1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
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 Intel Corporation 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.
43 /****************************************************************************************/
44 /* Dynamic detection and loading of IPP modules */
45 /****************************************************************************************/
49 #if defined _MSC_VER && _MSC_VER >= 1200
50 #pragma warning( disable: 4115 ) /* type definition in () */
53 #if defined _MSC_VER && defined WIN64 && !defined EM64T
54 #pragma optimize( "", off )
57 #if defined WIN32 || defined WIN64
68 #define CV_PROC_GENERIC 0
69 #define CV_PROC_SHIFT 10
70 #define CV_PROC_ARCH_MASK ((1 << CV_PROC_SHIFT) - 1)
71 #define CV_PROC_IA32_GENERIC 1
72 #define CV_PROC_IA32_WITH_MMX (CV_PROC_IA32_GENERIC|(2 << CV_PROC_SHIFT))
73 #define CV_PROC_IA32_WITH_SSE (CV_PROC_IA32_GENERIC|(3 << CV_PROC_SHIFT))
74 #define CV_PROC_IA32_WITH_SSE2 (CV_PROC_IA32_GENERIC|(4 << CV_PROC_SHIFT))
75 #define CV_PROC_IA64 2
76 #define CV_PROC_EM64T 3
77 #define CV_GET_PROC_ARCH(model) ((model) & CV_PROC_ARCH_MASK)
79 typedef struct CvProcessorInfo
83 double frequency; // clocks per microsecond
87 #undef MASM_INLINE_ASSEMBLY
89 #if defined WIN32 && !defined WIN64
92 #define MASM_INLINE_ASSEMBLY 1
93 #elif defined __BORLANDC__
95 #if __BORLANDC__ >= 0x560
96 #define MASM_INLINE_ASSEMBLY 1
104 determine processor type
107 icvInitProcessorInfo( CvProcessorInfo* cpu_info )
109 memset( cpu_info, 0, sizeof(*cpu_info) );
110 cpu_info->model = CV_PROC_GENERIC;
112 #if defined WIN32 || defined WIN64
114 #ifndef PROCESSOR_ARCHITECTURE_AMD64
115 #define PROCESSOR_ARCHITECTURE_AMD64 9
118 #ifndef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
119 #define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10
125 GetSystemInfo( &sys );
127 if( sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL &&
128 sys.dwProcessorType == PROCESSOR_INTEL_PENTIUM && sys.wProcessorLevel >= 6 )
130 int version = 0, features = 0, family = 0;
134 cpu_info->count = (int)sys.dwNumberOfProcessors;
135 unsigned long val = 0, sz = sizeof(val);
137 if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0\\",
138 0, KEY_QUERY_VALUE, &key ) >= 0 )
140 if( RegQueryValueEx( key, "~MHz", 0, 0, (uchar*)&val, &sz ) >= 0 )
141 cpu_info->frequency = (double)val;
145 #ifdef MASM_INLINE_ASSEMBLY
148 /* use CPUID to determine the features supported */
168 #elif defined WIN32 && __GNUC__ > 2
172 ".byte 0x0f; .byte 0xa2\n\t"
175 : "=r"(version), "=r" (features)
177 : "%ebx", "%esi", "%edi"
181 static const char cpuid_code[] =
182 "\x53\x56\x57\xb8\x01\x00\x00\x00\x0f\xa2\x5f\x5e\x5b\xc3";
183 typedef int64 (CV_CDECL * func_ptr)(void);
184 func_ptr cpuid = (func_ptr)(void*)cpuid_code;
185 int64 cpuid_val = cpuid();
186 version = (int)cpuid_val;
187 features = (int)(cpuid_val >> 32);
191 #define ICV_CPUID_M6 ((1<<15)|(1<<23)) /* cmov + MMX */
192 #define ICV_CPUID_A6 ((1<<25)|ICV_CPUID_M6) /* <all above> + SSE */
193 #define ICV_CPUID_W7 ((1<<26)|ICV_CPUID_A6) /* <all above> + SSE2 */
195 family = (version >> 8) & 15;
196 if( family >= 6 && (features & ICV_CPUID_M6) != 0 ) /* Pentium II or higher */
197 id = features & ICV_CPUID_W7;
199 cpu_info->model = id == ICV_CPUID_W7 ? CV_PROC_IA32_WITH_SSE2 :
200 id == ICV_CPUID_A6 ? CV_PROC_IA32_WITH_SSE :
201 id == ICV_CPUID_M6 ? CV_PROC_IA32_WITH_MMX :
202 CV_PROC_IA32_GENERIC;
207 if( sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 )
208 cpu_info->model = CV_PROC_EM64T;
210 if( sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 )
211 cpu_info->model = CV_PROC_IA64;
213 if( QueryPerformanceFrequency( &freq ) )
214 cpu_info->frequency = (double)freq.QuadPart;
217 cpu_info->frequency = 1;
220 cpu_info->model = CV_PROC_EM64T;
221 #elif defined __ia64__
222 cpu_info->model = CV_PROC_IA64;
223 #elif !defined __i386__
224 cpu_info->model = CV_PROC_GENERIC;
226 cpu_info->model = CV_PROC_IA32_GENERIC;
228 // reading /proc/cpuinfo file (proc file system must be supported)
229 FILE *file = fopen( "/proc/cpuinfo", "r" );
234 int max_size = sizeof(buffer)-1;
238 const char* ptr = fgets( buffer, max_size, file );
241 if( strncmp( buffer, "flags", 5 ) == 0 )
243 if( strstr( buffer, "mmx" ) && strstr( buffer, "cmov" ))
245 cpu_info->model = CV_PROC_IA32_WITH_MMX;
246 if( strstr( buffer, "xmm" ) || strstr( buffer, "sse" ))
248 cpu_info->model = CV_PROC_IA32_WITH_SSE;
249 if( strstr( buffer, "emm" ))
250 cpu_info->model = CV_PROC_IA32_WITH_SSE2;
254 else if( strncmp( buffer, "cpu MHz", 7 ) == 0 )
256 char* pos = strchr( buffer, ':' );
258 cpu_info->frequency = strtod( pos + 1, &pos );
263 if( CV_GET_PROC_ARCH(cpu_info->model) != CV_PROC_IA32_GENERIC )
264 cpu_info->frequency = 1;
266 assert( cpu_info->frequency > 1 );
273 CV_INLINE const CvProcessorInfo*
274 icvGetProcessorInfo()
276 static CvProcessorInfo cpu_info;
277 static int init_cpu_info = 0;
280 icvInitProcessorInfo( &cpu_info );
287 /****************************************************************************************/
288 /* Make functions descriptions */
289 /****************************************************************************************/
292 #define IPCVAPI_EX(type,func_name,names,modules,arg) \
293 { (void**)&func_name##_p, (void*)(size_t)-1, names, modules, 0 },
296 #define IPCVAPI_C_EX(type,func_name,names,modules,arg) \
297 { (void**)&func_name##_p, (void*)(size_t)-1, names, modules, 0 },
299 static CvPluginFuncInfo cxcore_ipp_tab[] =
301 #undef _CXCORE_IPP_H_
303 #undef _CXCORE_IPP_H_
309 determine processor type, load appropriate dll and
310 initialize all function pointers
312 #if defined WIN32 || defined WIN64
313 #define DLL_PREFIX ""
314 #define DLL_SUFFIX ".dll"
316 #define DLL_PREFIX "lib"
317 #define DLL_SUFFIX ".so"
318 #define LoadLibrary(name) dlopen(name, RTLD_LAZY)
319 #define FreeLibrary(name) dlclose(name)
320 #define GetProcAddress dlsym
321 typedef void* HMODULE;
325 #define DLL_DEBUG_FLAG "d"
327 #define DLL_DEBUG_FLAG ""
330 #define VERBOSE_LOADING 0
333 #define ICV_PRINTF(args) printf args; fflush(stdout)
335 #define ICV_PRINTF(args)
338 typedef struct CvPluginInfo
340 const char* basename;
346 static CvPluginInfo plugins[CV_PLUGIN_MAX];
347 static CvModuleInfo cxcore_info = { 0, "cxcore", CV_VERSION, cxcore_ipp_tab };
349 CvModuleInfo *CvModule::first = 0, *CvModule::last = 0;
351 CvModule::CvModule( CvModuleInfo* _info )
353 cvRegisterModule( _info );
357 CvModule::~CvModule()
361 CvModuleInfo* p = first;
362 for( ; p != 0 && p->next != info; p = p->next )
365 p->next = info->next;
376 icvUpdatePluginFuncTab( CvPluginFuncInfo* func_tab )
378 int i, loaded_functions = 0;
381 for( i = 0; func_tab[i].func_addr != 0; i++ )
383 if( func_tab[i].default_func_addr == (void*)(size_t)-1 )
384 func_tab[i].default_func_addr = *func_tab[i].func_addr;
386 *func_tab[i].func_addr = func_tab[i].default_func_addr;
387 func_tab[i].loaded_from = 0;
390 // ippopencv substitutes all the other IPP modules
391 if( plugins[CV_PLUGIN_OPTCV].handle != 0 )
393 for( i = 2; i < CV_PLUGIN_MKL; i++ )
395 assert( plugins[i].handle == 0 );
396 plugins[i].handle = plugins[CV_PLUGIN_OPTCV].handle;
400 // 2. try to find corresponding functions in ipp* and reassign pointers to them
401 for( i = 0; func_tab[i].func_addr != 0; i++ )
403 #if defined _MSC_VER && _MSC_VER >= 1200
404 #pragma warning( disable: 4054 4055 ) /* converting pointers to code<->data */
409 assert( func_tab[i].loaded_from == 0 );
411 if( func_tab[i].search_modules )
414 const char* name_ptr = func_tab[i].func_names;
416 for( ; j < 10 && name_ptr; j++ )
418 const char* name_start = name_ptr;
419 const char* name_end;
420 while( !isalpha(name_start[0]) && name_start[0] != '\0' )
424 name_end = name_start ? strchr( name_start, ',' ) : 0;
425 idx = (func_tab[i].search_modules / (1<<j*4)) % CV_PLUGIN_MAX;
427 if( plugins[idx].handle != 0 && name_start )
431 strncpy( name, name_start, name_end - name_start );
432 name[name_end - name_start] = '\0';
435 strcpy( name, name_start );
437 addr = (uchar*)GetProcAddress( plugins[idx].handle, name );
447 while( *addr == 0xE9 )
448 addr += 5 + *((int*)(addr + 1));
450 *func_tab[i].func_addr = addr;
451 func_tab[i].loaded_from = idx; // store index of the module
452 // that contain the loaded function
454 ICV_PRINTF(("%s: \t%s\n", name, plugins[idx].name ));
457 #if defined _MSC_VER && _MSC_VER >= 1200
458 #pragma warning( default: 4054 4055 )
466 ICV_PRINTF(("\nTotal loaded: %d\n\n", loaded_functions ));
467 printf( "***************************************************\nNot loaded ...\n\n" );
468 for( i = 0; func_tab[i].func_addr != 0; i++ )
469 if( !func_tab[i].loaded_from )
471 ICV_PRINTF(( "%s\n", func_tab[i].func_names ));
475 ICV_PRINTF(("\nTotal: %d\n", not_loaded ));
479 if( plugins[CV_PLUGIN_OPTCV].handle != 0 )
481 for( i = 2; i < CV_PLUGIN_MKL; i++ )
482 plugins[i].handle = 0;
485 return loaded_functions;
490 cvRegisterModule( const CvModuleInfo* module )
492 CvModuleInfo* module_copy = 0;
494 CV_FUNCNAME( "cvRegisterModule" );
498 size_t name_len, version_len;
500 CV_ASSERT( module != 0 && module->name != 0 && module->version != 0 );
502 name_len = strlen(module->name);
503 version_len = strlen(module->version);
505 CV_CALL( module_copy = (CvModuleInfo*)cvAlloc( sizeof(*module_copy) +
506 name_len + 1 + version_len + 1 ));
508 *module_copy = *module;
509 module_copy->name = (char*)(module_copy + 1);
510 module_copy->version = (char*)(module_copy + 1) + name_len + 1;
512 memcpy( (void*)module_copy->name, module->name, name_len + 1 );
513 memcpy( (void*)module_copy->version, module->version, version_len + 1 );
514 module_copy->next = 0;
516 if( CvModule::first == 0 )
517 CvModule::first = module_copy;
519 CvModule::last->next = module_copy;
520 CvModule::last = module_copy;
522 if( CvModule::first == CvModule::last )
524 CV_CALL( cvUseOptimized(1));
528 CV_CALL( icvUpdatePluginFuncTab( module_copy->func_tab ));
533 if( cvGetErrStatus() < 0 && module_copy )
534 cvFree( &module_copy );
536 return module_copy ? 0 : -1;
541 cvUseOptimized( int load_flag )
543 int i, loaded_modules = 0, loaded_functions = 0;
544 CvModuleInfo* module;
545 const CvProcessorInfo* cpu_info = icvGetProcessorInfo();
546 int arch = CV_GET_PROC_ARCH(cpu_info->model);
548 // TODO: implement some more elegant way
549 // to find the latest and the greatest IPP/MKL libraries
550 static const char* opencv_sfx[] = { "100", "099", "097", 0 };
551 static const char* ipp_sfx_ia32[] = { "-6.1", "-6.0", "-5.3", "-5.2", "-5.1", "", 0 };
552 static const char* ipp_sfx_ia64[] = { "64-6.1", "64-6.0", "64-5.3", "64-5.2", "64-5.1", "64", 0 };
553 static const char* ipp_sfx_em64t[] = { "em64t-6.1", "em64t-6.0", "em64t-5.3", "em64t-5.2", "em64t-5.1", "em64t", 0 };
554 static const char* mkl_sfx_ia32[] = { "p4", "p3", "def", 0 };
555 static const char* mkl_sfx_ia64[] = { "i2p", "itp", 0 };
556 static const char* mkl_sfx_em64t[] = { "def", 0 };
557 const char** ipp_suffix = arch == CV_PROC_IA64 ? ipp_sfx_ia64 :
558 arch == CV_PROC_EM64T ? ipp_sfx_em64t : ipp_sfx_ia32;
559 const char** mkl_suffix = arch == CV_PROC_IA64 ? mkl_sfx_ia64 :
560 arch == CV_PROC_EM64T ? mkl_sfx_em64t : mkl_sfx_ia32;
562 for( i = 0; i < CV_PLUGIN_MAX; i++ )
563 plugins[i].basename = 0;
564 plugins[CV_PLUGIN_NONE].basename = 0;
565 plugins[CV_PLUGIN_NONE].name[0] = '\0';
566 plugins[CV_PLUGIN_OPTCV].basename = "ippopencv";
567 plugins[CV_PLUGIN_IPPCV].basename = "ippcv";
568 plugins[CV_PLUGIN_IPPI].basename = "ippi";
569 plugins[CV_PLUGIN_IPPS].basename = "ipps";
570 plugins[CV_PLUGIN_IPPVM].basename = "ippvm";
571 plugins[CV_PLUGIN_IPPCC].basename = "ippcc";
572 plugins[CV_PLUGIN_MKL].basename = "mkl_";
574 // try to load optimized dlls
575 for( i = 1; i < CV_PLUGIN_MAX; i++ )
577 // unload previously loaded optimized modules
578 if( plugins[i].handle )
580 FreeLibrary( plugins[i].handle );
581 plugins[i].handle = 0;
584 // do not load regular IPP modules if the custom merged IPP module is already found.
585 if( i < CV_PLUGIN_MKL && load_flag && plugins[CV_PLUGIN_OPTCV].handle != 0 )
588 if( load_flag && plugins[i].basename &&
589 (arch == CV_PROC_IA32_GENERIC || arch == CV_PROC_IA64 || arch == CV_PROC_EM64T) )
591 const char** suffix = i == CV_PLUGIN_OPTCV ? opencv_sfx :
592 i < CV_PLUGIN_MKL ? ipp_suffix : mkl_suffix;
593 if( suffix == mkl_sfx_ia32 )
595 if( !(cpu_info->model & CV_PROC_IA32_WITH_SSE2) )
597 if( !(cpu_info->model & CV_PROC_IA32_WITH_SSE) )
601 for( ; *suffix != 0; suffix++ )
603 sprintf( plugins[i].name, DLL_PREFIX "%s%s" DLL_DEBUG_FLAG DLL_SUFFIX,
604 plugins[i].basename, *suffix );
606 ICV_PRINTF(("loading %s...\n", plugins[i].name ));
607 plugins[i].handle = LoadLibrary( plugins[i].name );
608 if( plugins[i].handle != 0 )
610 ICV_PRINTF(("%s loaded\n", plugins[i].name ));
615 // temporary workaround for MacOSX
616 sprintf( plugins[i].name, DLL_PREFIX "%s%s" DLL_DEBUG_FLAG ".dylib",
617 plugins[i].basename, *suffix );
619 ICV_PRINTF(("loading %s...\n", plugins[i].name ));
620 plugins[i].handle = LoadLibrary( plugins[i].name );
621 if( plugins[i].handle != 0 )
623 ICV_PRINTF(("%s loaded\n", plugins[i].name ));
632 for( module = CvModule::first; module != 0; module = module->next )
633 loaded_functions += icvUpdatePluginFuncTab( module->func_tab );
635 return loaded_functions;
638 CvModule cxcore_module( &cxcore_info );
641 cvGetModuleInfo( const char* name, const char **version, const char **plugin_list )
643 static char joint_verinfo[1024] = "";
644 static char plugin_list_buf[1024] = "";
646 CV_FUNCNAME( "cvGetLibraryInfo" );
656 CvModuleInfo* module;
662 size_t i, name_len = strlen(name);
664 for( module = CvModule::first; module != 0; module = module->next )
666 if( strlen(module->name) == name_len )
668 for( i = 0; i < name_len; i++ )
670 int c0 = toupper(module->name[i]), c1 = toupper(name[i]);
679 CV_ERROR( CV_StsObjectNotFound, "The module is not found" );
681 *version = module->version;
685 char* ptr = joint_verinfo;
687 for( module = CvModule::first; module != 0; module = module->next )
689 sprintf( ptr, "%s: %s%s", module->name, module->version, module->next ? ", " : "" );
693 *version = joint_verinfo;
699 char* ptr = plugin_list_buf;
702 for( i = 0; i < CV_PLUGIN_MAX; i++ )
703 if( plugins[i].handle != 0 )
705 sprintf( ptr, "%s, ", plugins[i].name );
709 if( ptr > plugin_list_buf )
712 *plugin_list = plugin_list_buf;
722 typedef int64 (CV_CDECL * rdtsc_func)(void);
724 /* helper functions for RNG initialization and accurate time measurement */
725 CV_IMPL int64 cvGetTickCount( void )
727 const CvProcessorInfo* cpu_info = icvGetProcessorInfo();
729 if( cpu_info->frequency > 1 &&
730 CV_GET_PROC_ARCH(cpu_info->model) == CV_PROC_IA32_GENERIC )
732 #ifdef MASM_INLINE_ASSEMBLY
740 #elif (defined __GNUC__ || defined CV_ICC) && defined __i386__
742 asm volatile (".byte 0xf; .byte 0x31" /* "rdtsc" */ : "=A" (t));
745 static const char code[] = "\x0f\x31\xc3";
746 rdtsc_func func = (rdtsc_func)(void*)code;
752 #if defined WIN32 || defined WIN64
753 LARGE_INTEGER counter;
754 QueryPerformanceCounter( &counter );
755 return (int64)counter.QuadPart;
759 gettimeofday( &tv, &tz );
760 return (int64)tv.tv_sec*1000000 + tv.tv_usec;
765 CV_IMPL double cvGetTickFrequency()
767 return icvGetProcessorInfo()->frequency;
771 static int icvNumThreads = 0;
772 static int icvNumProcs = 0;
774 CV_IMPL int cvGetNumThreads(void)
778 return icvNumThreads;
781 CV_IMPL void cvSetNumThreads( int threads )
786 icvNumProcs = omp_get_num_procs();
787 icvNumProcs = MIN( icvNumProcs, CV_MAX_THREADS );
795 threads = icvNumProcs;
797 // threads = MIN( threads, icvNumProcs );
799 icvNumThreads = threads;
806 CV_IMPL int cvGetThreadNum(void)
809 return omp_get_thread_num();