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