]> rtime.felk.cvut.cz Git - opencv.git/blob - opencv/src/cxcore/cxsystem.cpp
switch between SSE and non-SSE code dynamically => a single OpenCV binary can be...
[opencv.git] / opencv / src / cxcore / cxsystem.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
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.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #include "_cxcore.h"
44
45 #if defined WIN32 || defined WIN64 || defined _WIN64 || defined WINCE
46 #include <tchar.h>
47 #include <intrin.h>
48 #else
49 #include <pthread.h>
50 #include <sys/time.h>
51 #include <time.h>
52
53 #ifdef __MACH__
54 #include <mach/mach.h>
55 #include <mach/mach_time.h>
56 #endif
57
58 #endif
59
60 #ifdef _OPENMP
61 #include "omp.h"
62 #endif
63
64 #include <stdarg.h>
65
66 namespace cv
67 {
68
69 struct HWFeatures
70 {
71     enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE };
72     
73     HWFeatures()
74     {
75         memset( have, 0, sizeof(have) );
76         x86_family = 0;
77     }
78     
79     static HWFeatures initialize()
80     {
81         HWFeatures f;
82         
83         int cpuid_data[4]={0,0,0,0};
84     #if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
85         __cpuid(cpuid_data, 1);
86     #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
87         asm volatile
88         (
89          "movl $1,%%eax\n"
90          ".byte 0x0f; .byte 0xa2\n"
91          : "=a"(cpuid_data[0]), "=c" (cpuid_data[2]), "=d" (cpuid_data[3])
92          :
93          : "%ebx", "%esi", "%edi"
94          );
95     #endif
96         
97         f.x86_family = (cpuid_data[0] >> 8) & 15;
98         if( f.x86_family >= 6 )
99         {
100             f.have[CV_CPU_MMX] = (cpuid_data[3] & (1 << 23)) != 0;
101             f.have[CV_CPU_SSE] = (cpuid_data[3] & (1<<25)) != 0;
102             f.have[CV_CPU_SSE2] = (cpuid_data[3] & (1<<26)) != 0;
103             f.have[CV_CPU_SSE3] = (cpuid_data[2] & (1<<0)) != 0;
104             f.have[CV_CPU_SSSE3] = (cpuid_data[2] & (1<<9)) != 0;
105             f.have[CV_CPU_SSE4_1] = (cpuid_data[2] & (1<<19)) != 0;
106             f.have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0;
107             f.have[CV_CPU_AVX] = (cpuid_data[2] & (1<<28)) != 0;
108             
109             f.have[CV_CPU_SSE] = f.have[CV_CPU_SSE4_2] ? CV_CPU_SSE4_2 :
110                   f.have[CV_CPU_SSE4_1] ? CV_CPU_SSE4_1 :
111                   f.have[CV_CPU_SSSE3] ? CV_CPU_SSSE3 :
112                   f.have[CV_CPU_SSE3] ? CV_CPU_SSE3 :
113                   f.have[CV_CPU_SSE2] ? CV_CPU_SSE2 :
114                   f.have[CV_CPU_SSE] ? CV_CPU_SSE : 0;
115         }
116         
117         return f;
118     }
119     
120     int x86_family;
121     int have[MAX_FEATURE+1];
122 };
123     
124 static HWFeatures featuresEnabled = HWFeatures::initialize(), featuresDisabled = HWFeatures();
125     
126 #ifdef HAVE_IPP
127 volatile bool useOptimizedFlag = true;
128
129 struct IPPInitializer
130 {
131     IPPInitializer() { ippStaticInit(); }
132 };
133
134 IPPInitializer ippInitializer;
135 #else
136 volatile bool useOptimizedFlag = false;
137 #endif
138
139 void setUseOptimized( bool flag )
140 {
141     useOptimizedFlag = flag;
142     cvHardwareSupport = flag ? featuresEnabled.have : featuresDisabled.have;
143 }
144
145 bool useOptimized()
146 {
147     return useOptimizedFlag;
148 }
149     
150 int64 getTickCount()
151 {
152 #if defined WIN32 || defined WIN64 || defined _WIN64 || defined WINCE
153     LARGE_INTEGER counter;
154     QueryPerformanceCounter( &counter );
155     return (int64)counter.QuadPart;
156 #elif defined __linux || defined __linux__
157     struct timespec tp;
158     clock_gettime(CLOCK_MONOTONIC, &tp);
159     return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
160 #elif defined __MACH__
161     return (int64)mach_absolute_time();
162 #else    
163     struct timeval tv;
164     struct timezone tz;
165     gettimeofday( &tv, &tz );
166     return (int64)tv.tv_sec*1000000 + tv.tv_usec;
167 #endif
168 }
169
170 double getTickFrequency()
171 {
172 #if defined WIN32 || defined WIN64 || defined _WIN64 || defined WINCE
173     LARGE_INTEGER freq;
174     QueryPerformanceFrequency(&freq);
175     return (double)freq.QuadPart;
176 #elif defined __linux || defined __linux__
177     return 1e9;
178 #elif defined __MACH__
179     static double freq = 0;
180     if( freq == 0 )
181     {
182         mach_timebase_info_data_t sTimebaseInfo;
183         mach_timebase_info(&sTimebaseInfo);
184         freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
185     }
186     return freq; 
187 #else
188     return 1e6;
189 #endif
190 }
191
192 #if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__) 
193 #if defined(__i386__)
194
195 int64 getCPUTickCount(void)
196 {
197     int64 x;
198     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
199     return x;
200 }
201 #elif defined(__x86_64__)
202
203 int64 getCPUTickCount(void)
204 {
205     unsigned hi, lo;
206     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
207     return (int64)lo | ((int64)hi << 32);
208 }
209
210 #elif defined(__ppc__)
211
212 int64 getCPUTickCount(void)
213 {
214     int64 result=0;
215     unsigned upper, lower, tmp;
216     __asm__ volatile(
217                      "0:                  \n"
218                      "\tmftbu   %0           \n"
219                      "\tmftb    %1           \n"
220                      "\tmftbu   %2           \n"
221                      "\tcmpw    %2,%0        \n"
222                      "\tbne     0b         \n"
223                      : "=r"(upper),"=r"(lower),"=r"(tmp)
224                      );
225     return lower | ((int64)upper << 32);
226 }
227
228 #else
229
230 #error "RDTSC not defined"
231
232 #endif
233
234 #elif defined _MSC_VER && defined WIN32 && !defined _WIN64
235
236 int64 getCPUTickCount(void)
237 {
238     __asm _emit 0x0f;
239     __asm _emit 0x31;
240 }
241
242 #else
243
244 int64 getCPUTickCount()
245 {
246     return getTickCount();
247 }
248
249 #endif
250
251
252 static int numThreads = 0;
253 static int numProcs = 0;
254
255 int getNumThreads(void)
256 {
257     if( !numProcs )
258         setNumThreads(0);
259     return numThreads;
260 }
261
262 void setNumThreads( int
263 #ifdef _OPENMP
264                              threads
265 #endif
266                   )
267 {
268     if( !numProcs )
269     {
270 #ifdef _OPENMP
271         numProcs = omp_get_num_procs();
272 #else
273         numProcs = 1;
274 #endif
275     }
276
277 #ifdef _OPENMP
278     if( threads <= 0 )
279         threads = numProcs;
280     else
281         threads = MIN( threads, numProcs );
282
283     numThreads = threads;
284 #else
285     numThreads = 1;
286 #endif
287 }
288
289
290 int getThreadNum(void)
291 {
292 #ifdef _OPENMP
293     return omp_get_thread_num();
294 #else
295     return 0;
296 #endif
297 }
298     
299     
300 string format( const char* fmt, ... )
301 {
302     char buf[1 << 16];
303     va_list args;
304     va_start( args, fmt );
305     vsprintf( buf, fmt, args );
306     return string(buf);
307 }
308
309 static CvErrorCallback customErrorCallback = 0;
310 static void* customErrorCallbackData = 0;
311 static bool breakOnError = false;
312
313 bool setBreakOnError(bool value)
314 {
315     bool prevVal = breakOnError;
316     breakOnError = value;
317     return prevVal;
318 }        
319
320 void error( const Exception& exc )
321 {
322     if (customErrorCallback != 0) 
323         customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
324                             exc.file.c_str(), exc.line, customErrorCallbackData);
325     else
326     {
327         const char* errorStr = cvErrorStr(exc.code);
328         char buf[1 << 16];
329
330         sprintf( buf, "OpenCV Error: %s (%s) in %s, file %s, line %d",
331             errorStr, exc.err.c_str(), exc.func.size() > 0 ?
332             exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line );
333         fprintf( stderr, "%s\n", buf );
334         fflush( stderr );
335     }
336     if(breakOnError)
337     {
338         static volatile int* p = 0;
339         *p = 0;
340     }
341     throw exc;
342 }
343     
344 CvErrorCallback
345 redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
346 {
347     if( prevUserdata )
348         *prevUserdata = customErrorCallbackData;
349     CvErrorCallback prevCallback = customErrorCallback;
350     customErrorCallback = errCallback;
351     customErrorCallbackData = userdata;
352     
353     return prevCallback;
354 }
355     
356 }
357
358 /*CV_IMPL int
359 cvGuiBoxReport( int code, const char *func_name, const char *err_msg,
360                 const char *file, int line, void* )
361 {
362 #if (!defined WIN32 && !defined WIN64) || defined WINCE
363     return cvStdErrReport( code, func_name, err_msg, file, line, 0 );
364 #else
365     if( code != CV_StsBackTrace && code != CV_StsAutoTrace )
366     {
367         size_t msg_len = strlen(err_msg ? err_msg : "") + 1024;
368         char* message = (char*)alloca(msg_len);
369         char title[100];
370
371         wsprintf( message, "%s (%s)\nin function %s, %s(%d)\n\n"
372                   "Press \"Abort\" to terminate application.\n"
373                   "Press \"Retry\" to debug (if the app is running under debugger).\n"
374                   "Press \"Ignore\" to continue (this is not safe).\n",
375                   cvErrorStr(code), err_msg ? err_msg : "no description",
376                   func_name, file, line );
377
378         wsprintf( title, "OpenCV GUI Error Handler" );
379
380         int answer = MessageBox( NULL, message, title, MB_ICONERROR|MB_ABORTRETRYIGNORE|MB_SYSTEMMODAL );
381
382         if( answer == IDRETRY )
383         {
384             CV_DBG_BREAK();
385         }
386         return answer != IDIGNORE;
387     }
388     return 0;
389 #endif
390 }*/
391
392 const int* cvHardwareSupport = cv::featuresEnabled.have;
393
394 CV_IMPL int cvUseOptimized( int flag )
395 {
396     int prevMode = cv::useOptimizedFlag;
397     cv::setUseOptimized( flag != 0 );
398     return prevMode;
399 }
400
401 CV_IMPL int64  cvGetTickCount(void)
402 {
403     return cv::getTickCount();
404 }
405
406 CV_IMPL double cvGetTickFrequency(void)
407 {
408     return cv::getTickFrequency()*1e-6;
409 }
410
411 CV_IMPL void cvSetNumThreads(int nt)
412 {
413     cv::setNumThreads(nt);
414 }
415
416 CV_IMPL int cvGetNumThreads()
417 {
418     return cv::getNumThreads();
419 }
420
421 CV_IMPL int cvGetThreadNum()
422 {
423     return cv::getThreadNum();
424 }
425
426
427 CV_IMPL CvErrorCallback
428 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
429 {
430     return cv::redirectError(errCallback, userdata, prevUserdata);
431 }
432
433 CV_IMPL int cvNulDevReport( int, const char*, const char*,
434                             const char*, int, void* )
435 {
436     return 0;
437 }
438
439 CV_IMPL int cvStdErrReport( int, const char*, const char*,
440                             const char*, int, void* )
441 {
442     return 0;
443 }
444
445 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
446                             const char*, int, void* )
447 {
448     return 0;
449 }
450
451 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
452 {
453     return 0;
454 }
455
456
457 CV_IMPL const char* cvErrorStr( int status )
458 {
459     static char buf[256];
460
461     switch (status)
462     {
463     case CV_StsOk :        return "No Error";
464     case CV_StsBackTrace : return "Backtrace";
465     case CV_StsError :     return "Unspecified error";
466     case CV_StsInternal :  return "Internal error";
467     case CV_StsNoMem :     return "Insufficient memory";
468     case CV_StsBadArg :    return "Bad argument";
469     case CV_StsNoConv :    return "Iterations do not converge";
470     case CV_StsAutoTrace : return "Autotrace call";
471     case CV_StsBadSize :   return "Incorrect size of input array";
472     case CV_StsNullPtr :   return "Null pointer";
473     case CV_StsDivByZero : return "Division by zero occured";
474     case CV_BadStep :      return "Image step is wrong";
475     case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
476     case CV_StsObjectNotFound :      return "Requested object was not found";
477     case CV_BadDepth :     return "Input image depth is not supported by function";
478     case CV_StsUnmatchedFormats : return "Formats of input arguments do not match";
479     case CV_StsUnmatchedSizes :  return "Sizes of input arguments do not match";
480     case CV_StsOutOfRange : return "One of arguments\' values is out of range";
481     case CV_StsUnsupportedFormat : return "Unsupported format or combination of formats";
482     case CV_BadCOI :      return "Input COI is not supported";
483     case CV_BadNumChannels : return "Bad number of channels";
484     case CV_StsBadFlag :   return "Bad flag (parameter or structure field)";
485     case CV_StsBadPoint :  return "Bad parameter of type CvPoint";
486     case CV_StsBadMask : return "Bad type of mask argument";
487     case CV_StsParseError : return "Parsing error";
488     case CV_StsNotImplemented : return "The function/feature is not implemented";
489     case CV_StsBadMemBlock :  return "Memory block has been corrupted";
490     case CV_StsAssert :  return "Assertion failed";
491     };
492
493     sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
494     return buf;
495 }
496
497 CV_IMPL int cvGetErrMode(void)
498 {
499     return 0;
500 }
501
502 CV_IMPL int cvSetErrMode(int)
503 {
504     return 0;
505 }
506
507 CV_IMPL int cvGetErrStatus()
508 {
509     return 0;
510 }
511
512 CV_IMPL void cvSetErrStatus(int)
513 {
514 }
515
516
517 CV_IMPL void cvError( int code, const char* func_name,
518                       const char* err_msg,
519                       const char* file_name, int line )
520 {
521     cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
522 }
523
524 /* function, which converts int to int */
525 CV_IMPL int
526 cvErrorFromIppStatus( int status )
527 {
528     switch (status)
529     {
530     case CV_BADSIZE_ERR: return CV_StsBadSize;
531     case CV_BADMEMBLOCK_ERR: return CV_StsBadMemBlock;
532     case CV_NULLPTR_ERR: return CV_StsNullPtr;
533     case CV_DIV_BY_ZERO_ERR: return CV_StsDivByZero;
534     case CV_BADSTEP_ERR: return CV_BadStep ;
535     case CV_OUTOFMEM_ERR: return CV_StsNoMem;
536     case CV_BADARG_ERR: return CV_StsBadArg;
537     case CV_NOTDEFINED_ERR: return CV_StsError;
538     case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
539     case CV_NOTFOUND_ERR: return CV_StsObjectNotFound;
540     case CV_BADCONVERGENCE_ERR: return CV_StsNoConv;
541     case CV_BADDEPTH_ERR: return CV_BadDepth;
542     case CV_UNMATCHED_FORMATS_ERR: return CV_StsUnmatchedFormats;
543     case CV_UNSUPPORTED_COI_ERR: return CV_BadCOI;
544     case CV_UNSUPPORTED_CHANNELS_ERR: return CV_BadNumChannels;
545     case CV_BADFLAG_ERR: return CV_StsBadFlag;
546     case CV_BADRANGE_ERR: return CV_StsBadArg;
547     case CV_BADCOEF_ERR: return CV_StsBadArg;
548     case CV_BADFACTOR_ERR: return CV_StsBadArg;
549     case CV_BADPOINT_ERR: return CV_StsBadPoint;
550
551     default: return CV_StsError;
552     }
553 }
554
555 static CvModuleInfo cxcore_info = { 0, "cxcore", CV_VERSION, 0 };
556
557 CvModuleInfo *CvModule::first = 0, *CvModule::last = 0;
558
559 CvModule::CvModule( CvModuleInfo* _info )
560 {
561     cvRegisterModule( _info );
562     info = last;
563 }
564
565 CvModule::~CvModule()
566 {
567     if( info )
568     {
569         CvModuleInfo* p = first;
570         for( ; p != 0 && p->next != info; p = p->next )
571             ;
572         if( p )
573             p->next = info->next;
574         if( first == info )
575             first = info->next;
576         if( last == info )
577             last = p;
578         free( info );
579         info = 0;
580     }
581 }
582
583 CV_IMPL int
584 cvRegisterModule( const CvModuleInfo* module )
585 {
586     CV_Assert( module != 0 && module->name != 0 && module->version != 0 );
587
588     size_t name_len = strlen(module->name);
589     size_t version_len = strlen(module->version);
590
591     CvModuleInfo* module_copy = (CvModuleInfo*)malloc( sizeof(*module_copy) +
592                                 name_len + 1 + version_len + 1 );
593
594     *module_copy = *module;
595     module_copy->name = (char*)(module_copy + 1);
596     module_copy->version = (char*)(module_copy + 1) + name_len + 1;
597
598     memcpy( (void*)module_copy->name, module->name, name_len + 1 );
599     memcpy( (void*)module_copy->version, module->version, version_len + 1 );
600     module_copy->next = 0;
601
602     if( CvModule::first == 0 )
603         CvModule::first = module_copy;
604     else
605         CvModule::last->next = module_copy;
606     CvModule::last = module_copy;
607     return 0;
608 }
609
610 CvModule cxcore_module( &cxcore_info );
611
612 CV_IMPL void
613 cvGetModuleInfo( const char* name, const char **version, const char **plugin_list )
614 {
615     static char joint_verinfo[1024] = "";
616     static char plugin_list_buf[1024] = "";
617
618     if( version )
619         *version = 0;
620
621     if( plugin_list )
622         *plugin_list = 0;
623
624     CvModuleInfo* module;
625
626     if( version )
627     {
628         if( name )
629         {
630             size_t i, name_len = strlen(name);
631
632             for( module = CvModule::first; module != 0; module = module->next )
633             {
634                 if( strlen(module->name) == name_len )
635                 {
636                     for( i = 0; i < name_len; i++ )
637                     {
638                         int c0 = toupper(module->name[i]), c1 = toupper(name[i]);
639                         if( c0 != c1 )
640                             break;
641                     }
642                     if( i == name_len )
643                         break;
644                 }
645             }
646             if( !module )
647                 CV_Error( CV_StsObjectNotFound, "The module is not found" );
648
649             *version = module->version;
650         }
651         else
652         {
653             char* ptr = joint_verinfo;
654
655             for( module = CvModule::first; module != 0; module = module->next )
656             {
657                 sprintf( ptr, "%s: %s%s", module->name, module->version, module->next ? ", " : "" );
658                 ptr += strlen(ptr);
659             }
660
661             *version = joint_verinfo;
662         }
663     }
664
665     if( plugin_list )
666         *plugin_list = plugin_list_buf;
667 }
668
669 #if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
670 BOOL WINAPI DllMain( HINSTANCE, DWORD  fdwReason, LPVOID )
671 {
672     if( fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH )
673     {
674         cv::deleteThreadAllocData();
675         cv::deleteThreadRNGData();
676     }
677     return TRUE;
678 }
679 #endif
680
681 /* End of file. */