ts: test case list is printed after cmd line parsing, refactored
[platform/upstream/opencv.git] / modules / core / src / system.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 // Copyright (C) 2015, Itseez Inc., all rights reserved.
16 // Third party copyrights are property of their respective owners.
17 //
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
20 //
21 //   * Redistribution's of source code must retain the above copyright notice,
22 //     this list of conditions and the following disclaimer.
23 //
24 //   * Redistribution's in binary form must reproduce the above copyright notice,
25 //     this list of conditions and the following disclaimer in the documentation
26 //     and/or other materials provided with the distribution.
27 //
28 //   * The name of the copyright holders may not be used to endorse or promote products
29 //     derived from this software without specific prior written permission.
30 //
31 // This software is provided by the copyright holders and contributors "as is" and
32 // any express or implied warranties, including, but not limited to, the implied
33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
34 // In no event shall the Intel Corporation or contributors be liable for any direct,
35 // indirect, incidental, special, exemplary, or consequential damages
36 // (including, but not limited to, procurement of substitute goods or services;
37 // loss of use, data, or profits; or business interruption) however caused
38 // and on any theory of liability, whether in contract, strict liability,
39 // or tort (including negligence or otherwise) arising in any way out of
40 // the use of this software, even if advised of the possibility of such damage.
41 //
42 //M*/
43
44 #include "precomp.hpp"
45 #include <iostream>
46
47 #include <opencv2/core/utils/configuration.private.hpp>
48 #include <opencv2/core/utils/trace.private.hpp>
49
50 #include <opencv2/core/utils/logger.hpp>
51
52 namespace cv {
53
54 static Mutex* __initialization_mutex = NULL;
55 Mutex& getInitializationMutex()
56 {
57     if (__initialization_mutex == NULL)
58         __initialization_mutex = new Mutex();
59     return *__initialization_mutex;
60 }
61 // force initialization (single-threaded environment)
62 Mutex* __initialization_mutex_initializer = &getInitializationMutex();
63
64 static bool param_dumpErrors = utils::getConfigurationParameterBool("OPENCV_DUMP_ERRORS",
65 #if defined(_DEBUG) || defined(__ANDROID__) || (defined(__GNUC__) && !defined(__EXCEPTIONS))
66     true
67 #else
68     false
69 #endif
70 );
71
72 } // namespace cv
73
74 #ifndef CV_ERROR_SET_TERMINATE_HANDLER  // build config option
75 # if defined(_WIN32)
76 #   define CV_ERROR_SET_TERMINATE_HANDLER 1
77 # endif
78 #endif
79 #if defined(CV_ERROR_SET_TERMINATE_HANDLER) && !CV_ERROR_SET_TERMINATE_HANDLER
80 # undef CV_ERROR_SET_TERMINATE_HANDLER
81 #endif
82
83 #ifdef _MSC_VER
84 # if _MSC_VER >= 1700
85 #  pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
86 # endif
87 #endif
88
89 #ifdef CV_ERROR_SET_TERMINATE_HANDLER
90 #include <exception>      // std::set_terminate
91 #include <cstdlib>        // std::abort
92 #endif
93
94 #if defined __ANDROID__ || defined __linux__ || defined __FreeBSD__ || defined __HAIKU__
95 #  include <unistd.h>
96 #  include <fcntl.h>
97 #  include <elf.h>
98 #if defined __ANDROID__ || defined __linux__
99 #  include <linux/auxvec.h>
100 #endif
101 #endif
102
103 #if defined __ANDROID__ && defined HAVE_CPUFEATURES
104 #  include <cpu-features.h>
105 #endif
106
107 #ifndef __VSX__
108 # if defined __PPC64__ && defined __linux__
109 #   include "sys/auxv.h"
110 #   ifndef AT_HWCAP2
111 #     define AT_HWCAP2 26
112 #   endif
113 #   ifndef PPC_FEATURE2_ARCH_2_07
114 #     define PPC_FEATURE2_ARCH_2_07 0x80000000
115 #   endif
116 # endif
117 #endif
118
119 #if defined _WIN32 || defined WINCE
120 #ifndef _WIN32_WINNT           // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?)
121   #define _WIN32_WINNT 0x0400  // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx
122 #endif
123 #include <windows.h>
124 #if (_WIN32_WINNT >= 0x0602)
125   #include <synchapi.h>
126 #endif
127 #undef small
128 #undef min
129 #undef max
130 #undef abs
131 #include <tchar.h>
132
133 #ifdef WINRT
134 #include <wrl/client.h>
135 #ifndef __cplusplus_winrt
136 #include <windows.storage.h>
137 #pragma comment(lib, "runtimeobject.lib")
138 #endif
139
140 std::wstring GetTempPathWinRT()
141 {
142 #ifdef __cplusplus_winrt
143     return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data());
144 #else
145     Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationDataStatics> appdataFactory;
146     Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationData> appdataRef;
147     Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFolder> storagefolderRef;
148     Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageItem> storageitemRef;
149     HSTRING str;
150     HSTRING_HEADER hstrHead;
151     std::wstring wstr;
152     if (FAILED(WindowsCreateStringReference(RuntimeClass_Windows_Storage_ApplicationData,
153                                             (UINT32)wcslen(RuntimeClass_Windows_Storage_ApplicationData), &hstrHead, &str)))
154         return wstr;
155     if (FAILED(RoGetActivationFactory(str, IID_PPV_ARGS(appdataFactory.ReleaseAndGetAddressOf()))))
156         return wstr;
157     if (FAILED(appdataFactory->get_Current(appdataRef.ReleaseAndGetAddressOf())))
158         return wstr;
159     if (FAILED(appdataRef->get_TemporaryFolder(storagefolderRef.ReleaseAndGetAddressOf())))
160         return wstr;
161     if (FAILED(storagefolderRef.As(&storageitemRef)))
162         return wstr;
163     str = NULL;
164     if (FAILED(storageitemRef->get_Path(&str)))
165         return wstr;
166     wstr = WindowsGetStringRawBuffer(str, NULL);
167     WindowsDeleteString(str);
168     return wstr;
169 #endif
170 }
171
172 std::wstring GetTempFileNameWinRT(std::wstring prefix)
173 {
174     wchar_t guidStr[40];
175     GUID g;
176     CoCreateGuid(&g);
177     wchar_t* mask = L"%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x";
178     swprintf(&guidStr[0], sizeof(guidStr)/sizeof(wchar_t), mask,
179              g.Data1, g.Data2, g.Data3, UINT(g.Data4[0]), UINT(g.Data4[1]),
180              UINT(g.Data4[2]), UINT(g.Data4[3]), UINT(g.Data4[4]),
181              UINT(g.Data4[5]), UINT(g.Data4[6]), UINT(g.Data4[7]));
182
183     return prefix.append(std::wstring(guidStr));
184 }
185
186 #endif
187 #else
188 #include <pthread.h>
189 #include <sys/time.h>
190 #include <time.h>
191
192 #if defined __MACH__ && defined __APPLE__
193 #include <mach/mach.h>
194 #include <mach/mach_time.h>
195 #endif
196
197 #endif
198
199 #ifdef _OPENMP
200 #include "omp.h"
201 #endif
202
203 #if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__ || defined __FreeBSD__ || defined __GLIBC__ || defined __HAIKU__
204 #include <unistd.h>
205 #include <stdio.h>
206 #include <sys/types.h>
207 #if defined __ANDROID__
208 #include <sys/sysconf.h>
209 #endif
210 #endif
211
212 #ifdef __ANDROID__
213 # include <android/log.h>
214 #endif
215
216 #ifdef DECLARE_CV_CPUID_X86
217 DECLARE_CV_CPUID_X86
218 #endif
219 #ifndef CV_CPUID_X86
220   #if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
221     #if _MSC_VER >= 1400  // MSVS 2005
222       #include <intrin.h>  // __cpuidex()
223       #define CV_CPUID_X86 __cpuidex
224     #else
225       #error "Required MSVS 2005+"
226     #endif
227   #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
228     static void cv_cpuid(int* cpuid_data, int reg_eax, int reg_ecx)
229     {
230         int __eax = reg_eax, __ebx = 0, __ecx = reg_ecx, __edx = 0;
231 // tested with available compilers (-fPIC -O2 -m32/-m64): https://godbolt.org/
232 #if !defined(__PIC__) \
233     || defined(__x86_64__) || __GNUC__ >= 5 \
234     || defined(__clang__) || defined(__INTEL_COMPILER)
235         __asm__("cpuid\n\t"
236                 : "+a" (__eax), "=b" (__ebx), "+c" (__ecx), "=d" (__edx)
237         );
238 #elif defined(__i386__)  // ebx may be reserved as the PIC register
239         __asm__("xchg{l}\t{%%}ebx, %1\n\t"
240                 "cpuid\n\t"
241                 "xchg{l}\t{%%}ebx, %1\n\t"
242                 : "+a" (__eax), "=&r" (__ebx), "+c" (__ecx), "=d" (__edx)
243         );
244 #else
245 #error "Configuration error"
246 #endif
247         cpuid_data[0] = __eax; cpuid_data[1] = __ebx; cpuid_data[2] = __ecx; cpuid_data[3] = __edx;
248     }
249     #define CV_CPUID_X86 cv_cpuid
250   #endif
251 #endif
252
253
254 namespace cv
255 {
256
257 Exception::Exception() { code = 0; line = 0; }
258
259 Exception::Exception(int _code, const String& _err, const String& _func, const String& _file, int _line)
260 : code(_code), err(_err), func(_func), file(_file), line(_line)
261 {
262     formatMessage();
263 }
264
265 Exception::~Exception() throw() {}
266
267 /*!
268  \return the error description and the context as a text string.
269  */
270 const char* Exception::what() const throw() { return msg.c_str(); }
271
272 void Exception::formatMessage()
273 {
274     size_t pos = err.find('\n');
275     bool multiline = pos != cv::String::npos;
276     if (multiline)
277     {
278         std::stringstream ss;
279         size_t prev_pos = 0;
280         while (pos != cv::String::npos)
281         {
282            ss << "> " << err.substr(prev_pos, pos - prev_pos) << std::endl;
283            prev_pos = pos + 1;
284            pos = err.find('\n', prev_pos);
285         }
286         ss << "> " << err.substr(prev_pos);
287         if (err[err.size() - 1] != '\n')
288             ss << std::endl;
289         err = ss.str();
290     }
291     if (func.size() > 0)
292     {
293         if (multiline)
294             msg = format("OpenCV(%s) %s:%d: error: (%d:%s) in function '%s'\n%s", CV_VERSION, file.c_str(), line, code, cvErrorStr(code), func.c_str(), err.c_str());
295         else
296             msg = format("OpenCV(%s) %s:%d: error: (%d:%s) %s in function '%s'\n", CV_VERSION, file.c_str(), line, code, cvErrorStr(code), err.c_str(), func.c_str());
297     }
298     else
299     {
300         msg = format("OpenCV(%s) %s:%d: error: (%d:%s) %s%s", CV_VERSION, file.c_str(), line, code, cvErrorStr(code), err.c_str(), multiline ? "" : "\n");
301     }
302 }
303
304 static const char* g_hwFeatureNames[CV_HARDWARE_MAX_FEATURE] = { NULL };
305
306 static const char* getHWFeatureName(int id)
307 {
308     return (id < CV_HARDWARE_MAX_FEATURE) ? g_hwFeatureNames[id] : NULL;
309 }
310 static const char* getHWFeatureNameSafe(int id)
311 {
312     const char* name = getHWFeatureName(id);
313     return name ? name : "Unknown feature";
314 }
315
316 struct HWFeatures
317 {
318     enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE };
319
320     HWFeatures(bool run_initialize = false)
321     {
322         memset( have, 0, sizeof(have[0]) * MAX_FEATURE );
323         if (run_initialize)
324             initialize();
325     }
326
327     static void initializeNames()
328     {
329         for (int i = 0; i < CV_HARDWARE_MAX_FEATURE; i++)
330         {
331             g_hwFeatureNames[i] = 0;
332         }
333         g_hwFeatureNames[CPU_MMX] = "MMX";
334         g_hwFeatureNames[CPU_SSE] = "SSE";
335         g_hwFeatureNames[CPU_SSE2] = "SSE2";
336         g_hwFeatureNames[CPU_SSE3] = "SSE3";
337         g_hwFeatureNames[CPU_SSSE3] = "SSSE3";
338         g_hwFeatureNames[CPU_SSE4_1] = "SSE4.1";
339         g_hwFeatureNames[CPU_SSE4_2] = "SSE4.2";
340         g_hwFeatureNames[CPU_POPCNT] = "POPCNT";
341         g_hwFeatureNames[CPU_FP16] = "FP16";
342         g_hwFeatureNames[CPU_AVX] = "AVX";
343         g_hwFeatureNames[CPU_AVX2] = "AVX2";
344         g_hwFeatureNames[CPU_FMA3] = "FMA3";
345
346         g_hwFeatureNames[CPU_AVX_512F] = "AVX512F";
347         g_hwFeatureNames[CPU_AVX_512BW] = "AVX512BW";
348         g_hwFeatureNames[CPU_AVX_512CD] = "AVX512CD";
349         g_hwFeatureNames[CPU_AVX_512DQ] = "AVX512DQ";
350         g_hwFeatureNames[CPU_AVX_512ER] = "AVX512ER";
351         g_hwFeatureNames[CPU_AVX_512IFMA] = "AVX512IFMA";
352         g_hwFeatureNames[CPU_AVX_512PF] = "AVX512PF";
353         g_hwFeatureNames[CPU_AVX_512VBMI] = "AVX512VBMI";
354         g_hwFeatureNames[CPU_AVX_512VL] = "AVX512VL";
355
356         g_hwFeatureNames[CPU_NEON] = "NEON";
357
358         g_hwFeatureNames[CPU_VSX] = "VSX";
359
360         g_hwFeatureNames[CPU_AVX512_SKX] = "AVX512-SKX";
361     }
362
363     void initialize(void)
364     {
365 #ifndef WINRT
366         if (getenv("OPENCV_DUMP_CONFIG"))
367         {
368             fprintf(stderr, "\nOpenCV build configuration is:\n%s\n",
369                 cv::getBuildInformation().c_str());
370         }
371 #endif
372
373         initializeNames();
374
375     #ifdef CV_CPUID_X86
376         int cpuid_data[4] = { 0, 0, 0, 0 };
377         int cpuid_data_ex[4] = { 0, 0, 0, 0 };
378
379         CV_CPUID_X86(cpuid_data, 1, 0/*unused*/);
380
381         int x86_family = (cpuid_data[0] >> 8) & 15;
382         if( x86_family >= 6 )
383         {
384             have[CV_CPU_MMX]    = (cpuid_data[3] & (1<<23)) != 0;
385             have[CV_CPU_SSE]    = (cpuid_data[3] & (1<<25)) != 0;
386             have[CV_CPU_SSE2]   = (cpuid_data[3] & (1<<26)) != 0;
387             have[CV_CPU_SSE3]   = (cpuid_data[2] & (1<<0)) != 0;
388             have[CV_CPU_SSSE3]  = (cpuid_data[2] & (1<<9)) != 0;
389             have[CV_CPU_FMA3]   = (cpuid_data[2] & (1<<12)) != 0;
390             have[CV_CPU_SSE4_1] = (cpuid_data[2] & (1<<19)) != 0;
391             have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0;
392             have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0;
393             have[CV_CPU_AVX]    = (cpuid_data[2] & (1<<28)) != 0;
394             have[CV_CPU_FP16]   = (cpuid_data[2] & (1<<29)) != 0;
395
396             // make the second call to the cpuid command in order to get
397             // information about extended features like AVX2
398             CV_CPUID_X86(cpuid_data_ex, 7, 0);
399
400             have[CV_CPU_AVX2]   = (cpuid_data_ex[1] & (1<<5)) != 0;
401
402             have[CV_CPU_AVX_512F]       = (cpuid_data_ex[1] & (1<<16)) != 0;
403             have[CV_CPU_AVX_512DQ]      = (cpuid_data_ex[1] & (1<<17)) != 0;
404             have[CV_CPU_AVX_512IFMA512] = (cpuid_data_ex[1] & (1<<21)) != 0;
405             have[CV_CPU_AVX_512PF]      = (cpuid_data_ex[1] & (1<<26)) != 0;
406             have[CV_CPU_AVX_512ER]      = (cpuid_data_ex[1] & (1<<27)) != 0;
407             have[CV_CPU_AVX_512CD]      = (cpuid_data_ex[1] & (1<<28)) != 0;
408             have[CV_CPU_AVX_512BW]      = (cpuid_data_ex[1] & (1<<30)) != 0;
409             have[CV_CPU_AVX_512VL]      = (cpuid_data_ex[1] & (1<<31)) != 0;
410             have[CV_CPU_AVX_512VBMI]    = (cpuid_data_ex[2] & (1<<1)) != 0;
411
412             bool have_AVX_OS_support = true;
413             bool have_AVX512_OS_support = true;
414             if (!(cpuid_data[2] & (1<<27)))
415                 have_AVX_OS_support = false; // OS uses XSAVE_XRSTORE and CPU support AVX
416             else
417             {
418                 int xcr0 = 0;
419             #ifdef _XCR_XFEATURE_ENABLED_MASK // requires immintrin.h
420                 xcr0 = (int)_xgetbv(_XCR_XFEATURE_ENABLED_MASK);
421             #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
422                 __asm__ ("xgetbv\n\t" : "=a" (xcr0) : "c" (0) : "%edx" );
423             #endif
424                 if ((xcr0 & 0x6) != 0x6)
425                     have_AVX_OS_support = false; // YMM registers
426                 if ((xcr0 & 0xe6) != 0xe6)
427                     have_AVX512_OS_support = false; // ZMM registers
428             }
429
430             if (!have_AVX_OS_support)
431             {
432                 have[CV_CPU_AVX] = false;
433                 have[CV_CPU_FP16] = false;
434                 have[CV_CPU_AVX2] = false;
435                 have[CV_CPU_FMA3] = false;
436             }
437             if (!have_AVX_OS_support || !have_AVX512_OS_support)
438             {
439                 have[CV_CPU_AVX_512F] = false;
440                 have[CV_CPU_AVX_512BW] = false;
441                 have[CV_CPU_AVX_512CD] = false;
442                 have[CV_CPU_AVX_512DQ] = false;
443                 have[CV_CPU_AVX_512ER] = false;
444                 have[CV_CPU_AVX_512IFMA512] = false;
445                 have[CV_CPU_AVX_512PF] = false;
446                 have[CV_CPU_AVX_512VBMI] = false;
447                 have[CV_CPU_AVX_512VL] = false;
448             }
449
450             if (have[CV_CPU_AVX_512F])
451             {
452                 have[CV_CPU_AVX512_SKX] = have[CV_CPU_AVX_512F] & have[CV_CPU_AVX_512CD] & have[CV_CPU_AVX_512BW] & have[CV_CPU_AVX_512DQ] & have[CV_CPU_AVX_512VL];
453             }
454         }
455     #endif // CV_CPUID_X86
456
457     #if defined __ANDROID__ || defined __linux__
458     #ifdef __aarch64__
459         have[CV_CPU_NEON] = true;
460         have[CV_CPU_FP16] = true;
461     #elif defined __arm__ && defined __ANDROID__
462       #if defined HAVE_CPUFEATURES
463         CV_LOG_INFO(NULL, "calling android_getCpuFeatures() ...");
464         uint64_t features = android_getCpuFeatures();
465         CV_LOG_INFO(NULL, cv::format("calling android_getCpuFeatures() ... Done (%llx)", (long long)features));
466         have[CV_CPU_NEON] = (features & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
467         have[CV_CPU_FP16] = (features & ANDROID_CPU_ARM_FEATURE_VFP_FP16) != 0;
468       #else
469         CV_LOG_INFO(NULL, "cpufeatures library is not available for CPU detection");
470         #if CV_NEON
471         CV_LOG_INFO(NULL, "- NEON instructions is enabled via build flags");
472         have[CV_CPU_NEON] = true;
473         #else
474         CV_LOG_INFO(NULL, "- NEON instructions is NOT enabled via build flags");
475         #endif
476         #if CV_FP16
477         CV_LOG_INFO(NULL, "- FP16 instructions is enabled via build flags");
478         have[CV_CPU_FP16] = true;
479         #else
480         CV_LOG_INFO(NULL, "- FP16 instructions is NOT enabled via build flags");
481         #endif
482       #endif
483     #elif defined __arm__
484         int cpufile = open("/proc/self/auxv", O_RDONLY);
485
486         if (cpufile >= 0)
487         {
488             Elf32_auxv_t auxv;
489             const size_t size_auxv_t = sizeof(auxv);
490
491             while ((size_t)read(cpufile, &auxv, size_auxv_t) == size_auxv_t)
492             {
493                 if (auxv.a_type == AT_HWCAP)
494                 {
495                     have[CV_CPU_NEON] = (auxv.a_un.a_val & 4096) != 0;
496                     have[CV_CPU_FP16] = (auxv.a_un.a_val & 2) != 0;
497                     break;
498                 }
499             }
500
501             close(cpufile);
502         }
503     #endif
504     #elif (defined __clang__ || defined __APPLE__)
505     #if (defined __ARM_NEON__ || (defined __ARM_NEON && defined __aarch64__))
506         have[CV_CPU_NEON] = true;
507     #endif
508     #if (defined __ARM_FP  && (((__ARM_FP & 0x2) != 0) && defined __ARM_NEON__))
509         have[CV_CPU_FP16] = true;
510     #endif
511     #endif
512
513     #ifdef __VSX__
514         have[CV_CPU_VSX] = true;
515     #elif (defined __PPC64__ && defined __linux__)
516         uint64 hwcaps = getauxval(AT_HWCAP);
517         uint64 hwcap2 = getauxval(AT_HWCAP2);
518         have[CV_CPU_VSX] = (hwcaps & PPC_FEATURE_PPC_LE && hwcaps & PPC_FEATURE_HAS_VSX && hwcap2 & PPC_FEATURE2_ARCH_2_07);
519     #else
520         have[CV_CPU_VSX] = false;
521     #endif
522
523         int baseline_features[] = { CV_CPU_BASELINE_FEATURES };
524         if (!checkFeatures(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0])))
525         {
526             fprintf(stderr, "\n"
527                     "******************************************************************\n"
528                     "* FATAL ERROR:                                                   *\n"
529                     "* This OpenCV build doesn't support current CPU/HW configuration *\n"
530                     "*                                                                *\n"
531                     "* Use OPENCV_DUMP_CONFIG=1 environment variable for details      *\n"
532                     "******************************************************************\n");
533             fprintf(stderr, "\nRequired baseline features:\n");
534             checkFeatures(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0]), true);
535             CV_Error(cv::Error::StsAssert, "Missing support for required CPU baseline features. Check OpenCV build configuration and required CPU/HW setup.");
536         }
537
538         readSettings(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0]));
539     }
540
541     bool checkFeatures(const int* features, int count, bool dump = false)
542     {
543         bool result = true;
544         for (int i = 0; i < count; i++)
545         {
546             int feature = features[i];
547             if (feature)
548             {
549                 if (have[feature])
550                 {
551                     if (dump) fprintf(stderr, "%s - OK\n", getHWFeatureNameSafe(feature));
552                 }
553                 else
554                 {
555                     result = false;
556                     if (dump) fprintf(stderr, "%s - NOT AVAILABLE\n", getHWFeatureNameSafe(feature));
557                 }
558             }
559         }
560         return result;
561     }
562
563     static inline bool isSymbolSeparator(char c)
564     {
565         return c == ',' || c == ';';
566     }
567
568     void readSettings(const int* baseline_features, int baseline_count)
569     {
570         bool dump = true;
571         const char* disabled_features =
572 #ifndef WINRT
573                 getenv("OPENCV_CPU_DISABLE");
574 #else
575                 NULL;
576 #endif
577         if (disabled_features && disabled_features[0] != 0)
578         {
579             const char* start = disabled_features;
580             for (;;)
581             {
582                 while (start[0] != 0 && isSymbolSeparator(start[0]))
583                 {
584                     start++;
585                 }
586                 if (start[0] == 0)
587                     break;
588                 const char* end = start;
589                 while (end[0] != 0 && !isSymbolSeparator(end[0]))
590                 {
591                     end++;
592                 }
593                 if (end == start)
594                     continue;
595                 cv::String feature(start, end);
596                 start = end;
597
598                 CV_Assert(feature.size() > 0);
599
600                 bool found = false;
601                 for (int i = 0; i < CV_HARDWARE_MAX_FEATURE; i++)
602                 {
603                     if (!g_hwFeatureNames[i]) continue;
604                     size_t len = strlen(g_hwFeatureNames[i]);
605                     if (len != feature.size()) continue;
606                     if (feature.compare(g_hwFeatureNames[i]) == 0)
607                     {
608                         bool isBaseline = false;
609                         for (int k = 0; k < baseline_count; k++)
610                         {
611                             if (baseline_features[k] == i)
612                             {
613                                 isBaseline = true;
614                                 break;
615                             }
616                         }
617                         if (isBaseline)
618                         {
619                             if (dump) fprintf(stderr, "OPENCV: Trying to disable baseline CPU feature: '%s'. This has very limited effect, because code optimizations for this feature are executed unconditionally in the most cases.\n", getHWFeatureNameSafe(i));
620                         }
621                         if (!have[i])
622                         {
623                             if (dump) fprintf(stderr, "OPENCV: Trying to disable unavailable CPU feature on the current platform: '%s'.\n", getHWFeatureNameSafe(i));
624                         }
625                         have[i] = false;
626
627                         found = true;
628                         break;
629                     }
630                 }
631                 if (!found)
632                 {
633                     if (dump) fprintf(stderr, "OPENCV: Trying to disable unknown CPU feature: '%s'.\n", feature.c_str());
634                 }
635             }
636         }
637     }
638
639     bool have[MAX_FEATURE+1];
640 };
641
642 static HWFeatures  featuresEnabled(true), featuresDisabled = HWFeatures(false);
643 static HWFeatures* currentFeatures = &featuresEnabled;
644
645 bool checkHardwareSupport(int feature)
646 {
647     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
648     return currentFeatures->have[feature];
649 }
650
651 String getHardwareFeatureName(int feature)
652 {
653     const char* name = getHWFeatureName(feature);
654     return name ? String(name) : String();
655 }
656
657 std::string getCPUFeaturesLine()
658 {
659     const int features[] = { CV_CPU_BASELINE_FEATURES, CV_CPU_DISPATCH_FEATURES };
660     const int sz = sizeof(features) / sizeof(features[0]);
661     std::string result;
662     std::string prefix;
663     for (int i = 1; i < sz; ++i)
664     {
665         if (features[i] == 0)
666         {
667             prefix = "*";
668             continue;
669         }
670         if (i != 1) result.append(" ");
671         result.append(prefix);
672         result.append(getHWFeatureNameSafe(features[i]));
673         if (!checkHardwareSupport(features[i])) result.append("?");
674     }
675     return result;
676 }
677
678 volatile bool useOptimizedFlag = true;
679
680 void setUseOptimized( bool flag )
681 {
682     useOptimizedFlag = flag;
683     currentFeatures = flag ? &featuresEnabled : &featuresDisabled;
684
685     ipp::setUseIPP(flag);
686 #ifdef HAVE_OPENCL
687     ocl::setUseOpenCL(flag);
688 #endif
689 #ifdef HAVE_TEGRA_OPTIMIZATION
690     ::tegra::setUseTegra(flag);
691 #endif
692 }
693
694 bool useOptimized(void)
695 {
696     return useOptimizedFlag;
697 }
698
699 int64 getTickCount(void)
700 {
701 #if defined _WIN32 || defined WINCE
702     LARGE_INTEGER counter;
703     QueryPerformanceCounter( &counter );
704     return (int64)counter.QuadPart;
705 #elif defined __linux || defined __linux__
706     struct timespec tp;
707     clock_gettime(CLOCK_MONOTONIC, &tp);
708     return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
709 #elif defined __MACH__ && defined __APPLE__
710     return (int64)mach_absolute_time();
711 #else
712     struct timeval tv;
713     struct timezone tz;
714     gettimeofday( &tv, &tz );
715     return (int64)tv.tv_sec*1000000 + tv.tv_usec;
716 #endif
717 }
718
719 double getTickFrequency(void)
720 {
721 #if defined _WIN32 || defined WINCE
722     LARGE_INTEGER freq;
723     QueryPerformanceFrequency(&freq);
724     return (double)freq.QuadPart;
725 #elif defined __linux || defined __linux__
726     return 1e9;
727 #elif defined __MACH__ && defined __APPLE__
728     static double freq = 0;
729     if( freq == 0 )
730     {
731         mach_timebase_info_data_t sTimebaseInfo;
732         mach_timebase_info(&sTimebaseInfo);
733         freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
734     }
735     return freq;
736 #else
737     return 1e6;
738 #endif
739 }
740
741 #if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
742 #if defined(__i386__)
743
744 int64 getCPUTickCount(void)
745 {
746     int64 x;
747     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
748     return x;
749 }
750 #elif defined(__x86_64__)
751
752 int64 getCPUTickCount(void)
753 {
754     unsigned hi, lo;
755     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
756     return (int64)lo | ((int64)hi << 32);
757 }
758
759 #elif defined(__ppc__)
760
761 int64 getCPUTickCount(void)
762 {
763     unsigned upper, lower, tmp;
764     __asm__ volatile(
765                      "0:                  \n"
766                      "\tmftbu   %0           \n"
767                      "\tmftb    %1           \n"
768                      "\tmftbu   %2           \n"
769                      "\tcmpw    %2,%0        \n"
770                      "\tbne     0b         \n"
771                      : "=r"(upper),"=r"(lower),"=r"(tmp)
772                      );
773     return lower | ((int64)upper << 32);
774 }
775
776 #else
777
778 #error "RDTSC not defined"
779
780 #endif
781
782 #elif defined _MSC_VER && defined _WIN32 && defined _M_IX86
783
784 int64 getCPUTickCount(void)
785 {
786     __asm _emit 0x0f;
787     __asm _emit 0x31;
788 }
789
790 #else
791
792 //#ifdef HAVE_IPP
793 //int64 getCPUTickCount(void)
794 //{
795 //    return ippGetCpuClocks();
796 //}
797 //#else
798 int64 getCPUTickCount(void)
799 {
800     return getTickCount();
801 }
802 //#endif
803
804 #endif
805
806 const String& getBuildInformation()
807 {
808     static String build_info =
809 #include "version_string.inc"
810     ;
811     return build_info;
812 }
813
814 String getVersionString() { return String(CV_VERSION); }
815
816 int getVersionMajor() { return CV_VERSION_MAJOR; }
817
818 int getVersionMinor() { return CV_VERSION_MINOR; }
819
820 int getVersionRevision() { return CV_VERSION_REVISION; }
821
822 String format( const char* fmt, ... )
823 {
824     AutoBuffer<char, 1024> buf;
825
826     for ( ; ; )
827     {
828         va_list va;
829         va_start(va, fmt);
830         int bsize = static_cast<int>(buf.size());
831         int len = cv_vsnprintf(buf.data(), bsize, fmt, va);
832         va_end(va);
833
834         CV_Assert(len >= 0 && "Check format string for errors");
835         if (len >= bsize)
836         {
837             buf.resize(len + 1);
838             continue;
839         }
840         buf[bsize - 1] = 0;
841         return String(buf.data(), len);
842     }
843 }
844
845 String tempfile( const char* suffix )
846 {
847     String fname;
848 #ifndef WINRT
849     const char *temp_dir = getenv("OPENCV_TEMP_PATH");
850 #endif
851
852 #if defined _WIN32
853 #ifdef WINRT
854     RoInitialize(RO_INIT_MULTITHREADED);
855     std::wstring temp_dir = GetTempPathWinRT();
856
857     std::wstring temp_file = GetTempFileNameWinRT(L"ocv");
858     if (temp_file.empty())
859         return String();
860
861     temp_file = temp_dir.append(std::wstring(L"\\")).append(temp_file);
862     DeleteFileW(temp_file.c_str());
863
864     char aname[MAX_PATH];
865     size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH);
866     CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
867     fname = String(aname);
868     RoUninitialize();
869 #else
870     char temp_dir2[MAX_PATH] = { 0 };
871     char temp_file[MAX_PATH] = { 0 };
872
873     if (temp_dir == 0 || temp_dir[0] == 0)
874     {
875         ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
876         temp_dir = temp_dir2;
877     }
878     if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
879         return String();
880
881     DeleteFileA(temp_file);
882
883     fname = temp_file;
884 #endif
885 # else
886 #  ifdef __ANDROID__
887     //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
888     char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
889 #  else
890     char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
891 #  endif
892
893     if (temp_dir == 0 || temp_dir[0] == 0)
894         fname = defaultTemplate;
895     else
896     {
897         fname = temp_dir;
898         char ech = fname[fname.size() - 1];
899         if(ech != '/' && ech != '\\')
900             fname = fname + "/";
901         fname = fname + "__opencv_temp.XXXXXX";
902     }
903
904     const int fd = mkstemp((char*)fname.c_str());
905     if (fd == -1) return String();
906
907     close(fd);
908     remove(fname.c_str());
909 # endif
910
911     if (suffix)
912     {
913         if (suffix[0] != '.')
914             return fname + "." + suffix;
915         else
916             return fname + suffix;
917     }
918     return fname;
919 }
920
921 static ErrorCallback customErrorCallback = 0;
922 static void* customErrorCallbackData = 0;
923 static bool breakOnError = false;
924
925 bool setBreakOnError(bool value)
926 {
927     bool prevVal = breakOnError;
928     breakOnError = value;
929     return prevVal;
930 }
931
932 int cv_snprintf(char* buf, int len, const char* fmt, ...)
933 {
934     va_list va;
935     va_start(va, fmt);
936     int res = cv_vsnprintf(buf, len, fmt, va);
937     va_end(va);
938     return res;
939 }
940
941 int cv_vsnprintf(char* buf, int len, const char* fmt, va_list args)
942 {
943 #if defined _MSC_VER
944     if (len <= 0) return len == 0 ? 1024 : -1;
945     int res = _vsnprintf_s(buf, len, _TRUNCATE, fmt, args);
946     // ensure null terminating on VS
947     if (res >= 0 && res < len)
948     {
949         buf[res] = 0;
950         return res;
951     }
952     else
953     {
954         buf[len - 1] = 0; // truncate happened
955         return res >= len ? res : (len * 2);
956     }
957 #else
958     return vsnprintf(buf, len, fmt, args);
959 #endif
960 }
961
962 static void dumpException(const Exception& exc)
963 {
964     const char* errorStr = cvErrorStr(exc.code);
965     char buf[1 << 12];
966
967     cv_snprintf(buf, sizeof(buf),
968         "OpenCV(%s) Error: %s (%s) in %s, file %s, line %d",
969         CV_VERSION,
970         errorStr, exc.err.c_str(), exc.func.size() > 0 ?
971         exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line);
972 #ifdef __ANDROID__
973     __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
974 #else
975     fflush(stdout); fflush(stderr);
976     fprintf(stderr, "%s\n", buf);
977     fflush(stderr);
978 #endif
979 }
980
981 #ifdef CV_ERROR_SET_TERMINATE_HANDLER
982 static bool cv_terminate_handler_installed = false;
983 static std::terminate_handler cv_old_terminate_handler;
984 static cv::Exception cv_terminate_handler_exception;
985 static bool param_setupTerminateHandler = utils::getConfigurationParameterBool("OPENCV_SETUP_TERMINATE_HANDLER", true);
986 static void cv_terminate_handler() {
987     std::cerr << "OpenCV: terminate handler is called! The last OpenCV error is:\n";
988     dumpException(cv_terminate_handler_exception);
989     if (false /*cv_old_terminate_handler*/)  // buggy behavior is observed with doubled "abort/retry/ignore" windows
990         cv_old_terminate_handler();
991     abort();
992 }
993
994 #endif
995
996 void error( const Exception& exc )
997 {
998 #ifdef CV_ERROR_SET_TERMINATE_HANDLER
999     {
1000         cv::AutoLock lock(getInitializationMutex());
1001         if (!cv_terminate_handler_installed)
1002         {
1003             if (param_setupTerminateHandler)
1004                 cv_old_terminate_handler = std::set_terminate(cv_terminate_handler);
1005             cv_terminate_handler_installed = true;
1006         }
1007         cv_terminate_handler_exception = exc;
1008     }
1009 #endif
1010
1011     if (customErrorCallback != 0)
1012         customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
1013                             exc.file.c_str(), exc.line, customErrorCallbackData);
1014     else if (param_dumpErrors)
1015     {
1016         dumpException(exc);
1017     }
1018
1019     if(breakOnError)
1020     {
1021         static volatile int* p = 0;
1022         *p = 0;
1023     }
1024
1025     CV_THROW(exc);
1026 }
1027
1028 void error(int _code, const String& _err, const char* _func, const char* _file, int _line)
1029 {
1030     error(cv::Exception(_code, _err, _func, _file, _line));
1031 }
1032
1033
1034 ErrorCallback
1035 redirectError( ErrorCallback errCallback, void* userdata, void** prevUserdata)
1036 {
1037     if( prevUserdata )
1038         *prevUserdata = customErrorCallbackData;
1039
1040     ErrorCallback prevCallback = customErrorCallback;
1041
1042     customErrorCallback     = errCallback;
1043     customErrorCallbackData = userdata;
1044
1045     return prevCallback;
1046 }
1047
1048 }
1049
1050 CV_IMPL int cvCheckHardwareSupport(int feature)
1051 {
1052     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
1053     return cv::currentFeatures->have[feature];
1054 }
1055
1056 CV_IMPL int cvUseOptimized( int flag )
1057 {
1058     int prevMode = cv::useOptimizedFlag;
1059     cv::setUseOptimized( flag != 0 );
1060     return prevMode;
1061 }
1062
1063 CV_IMPL int64  cvGetTickCount(void)
1064 {
1065     return cv::getTickCount();
1066 }
1067
1068 CV_IMPL double cvGetTickFrequency(void)
1069 {
1070     return cv::getTickFrequency()*1e-6;
1071 }
1072
1073 CV_IMPL CvErrorCallback
1074 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
1075 {
1076     return cv::redirectError(errCallback, userdata, prevUserdata);
1077 }
1078
1079 CV_IMPL int cvNulDevReport( int, const char*, const char*,
1080                             const char*, int, void* )
1081 {
1082     return 0;
1083 }
1084
1085 CV_IMPL int cvStdErrReport( int, const char*, const char*,
1086                             const char*, int, void* )
1087 {
1088     return 0;
1089 }
1090
1091 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
1092                             const char*, int, void* )
1093 {
1094     return 0;
1095 }
1096
1097 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
1098 {
1099     return 0;
1100 }
1101
1102
1103 CV_IMPL const char* cvErrorStr( int status )
1104 {
1105     static char buf[256];
1106
1107     switch (status)
1108     {
1109     case CV_StsOk :                  return "No Error";
1110     case CV_StsBackTrace :           return "Backtrace";
1111     case CV_StsError :               return "Unspecified error";
1112     case CV_StsInternal :            return "Internal error";
1113     case CV_StsNoMem :               return "Insufficient memory";
1114     case CV_StsBadArg :              return "Bad argument";
1115     case CV_StsNoConv :              return "Iterations do not converge";
1116     case CV_StsAutoTrace :           return "Autotrace call";
1117     case CV_StsBadSize :             return "Incorrect size of input array";
1118     case CV_StsNullPtr :             return "Null pointer";
1119     case CV_StsDivByZero :           return "Division by zero occurred";
1120     case CV_BadStep :                return "Image step is wrong";
1121     case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
1122     case CV_StsObjectNotFound :      return "Requested object was not found";
1123     case CV_BadDepth :               return "Input image depth is not supported by function";
1124     case CV_StsUnmatchedFormats :    return "Formats of input arguments do not match";
1125     case CV_StsUnmatchedSizes :      return "Sizes of input arguments do not match";
1126     case CV_StsOutOfRange :          return "One of arguments\' values is out of range";
1127     case CV_StsUnsupportedFormat :   return "Unsupported format or combination of formats";
1128     case CV_BadCOI :                 return "Input COI is not supported";
1129     case CV_BadNumChannels :         return "Bad number of channels";
1130     case CV_StsBadFlag :             return "Bad flag (parameter or structure field)";
1131     case CV_StsBadPoint :            return "Bad parameter of type CvPoint";
1132     case CV_StsBadMask :             return "Bad type of mask argument";
1133     case CV_StsParseError :          return "Parsing error";
1134     case CV_StsNotImplemented :      return "The function/feature is not implemented";
1135     case CV_StsBadMemBlock :         return "Memory block has been corrupted";
1136     case CV_StsAssert :              return "Assertion failed";
1137     case CV_GpuNotSupported :        return "No CUDA support";
1138     case CV_GpuApiCallError :        return "Gpu API call";
1139     case CV_OpenGlNotSupported :     return "No OpenGL support";
1140     case CV_OpenGlApiCallError :     return "OpenGL API call";
1141     };
1142
1143     sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
1144     return buf;
1145 }
1146
1147 CV_IMPL int cvGetErrMode(void)
1148 {
1149     return 0;
1150 }
1151
1152 CV_IMPL int cvSetErrMode(int)
1153 {
1154     return 0;
1155 }
1156
1157 CV_IMPL int cvGetErrStatus(void)
1158 {
1159     return 0;
1160 }
1161
1162 CV_IMPL void cvSetErrStatus(int)
1163 {
1164 }
1165
1166
1167 CV_IMPL void cvError( int code, const char* func_name,
1168                       const char* err_msg,
1169                       const char* file_name, int line )
1170 {
1171     cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
1172 }
1173
1174 /* function, which converts int to int */
1175 CV_IMPL int
1176 cvErrorFromIppStatus( int status )
1177 {
1178     switch (status)
1179     {
1180     case CV_BADSIZE_ERR:               return CV_StsBadSize;
1181     case CV_BADMEMBLOCK_ERR:           return CV_StsBadMemBlock;
1182     case CV_NULLPTR_ERR:               return CV_StsNullPtr;
1183     case CV_DIV_BY_ZERO_ERR:           return CV_StsDivByZero;
1184     case CV_BADSTEP_ERR:               return CV_BadStep;
1185     case CV_OUTOFMEM_ERR:              return CV_StsNoMem;
1186     case CV_BADARG_ERR:                return CV_StsBadArg;
1187     case CV_NOTDEFINED_ERR:            return CV_StsError;
1188     case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
1189     case CV_NOTFOUND_ERR:              return CV_StsObjectNotFound;
1190     case CV_BADCONVERGENCE_ERR:        return CV_StsNoConv;
1191     case CV_BADDEPTH_ERR:              return CV_BadDepth;
1192     case CV_UNMATCHED_FORMATS_ERR:     return CV_StsUnmatchedFormats;
1193     case CV_UNSUPPORTED_COI_ERR:       return CV_BadCOI;
1194     case CV_UNSUPPORTED_CHANNELS_ERR:  return CV_BadNumChannels;
1195     case CV_BADFLAG_ERR:               return CV_StsBadFlag;
1196     case CV_BADRANGE_ERR:              return CV_StsBadArg;
1197     case CV_BADCOEF_ERR:               return CV_StsBadArg;
1198     case CV_BADFACTOR_ERR:             return CV_StsBadArg;
1199     case CV_BADPOINT_ERR:              return CV_StsBadPoint;
1200
1201     default:
1202       return CV_StsError;
1203     }
1204 }
1205
1206 namespace cv {
1207 bool __termination = false;
1208 }
1209
1210 namespace cv
1211 {
1212
1213 #if defined _WIN32 || defined WINCE
1214
1215 struct Mutex::Impl
1216 {
1217     Impl()
1218     {
1219 #if (_WIN32_WINNT >= 0x0600)
1220         ::InitializeCriticalSectionEx(&cs, 1000, 0);
1221 #else
1222         ::InitializeCriticalSection(&cs);
1223 #endif
1224         refcount = 1;
1225     }
1226     ~Impl() { DeleteCriticalSection(&cs); }
1227
1228     void lock() { EnterCriticalSection(&cs); }
1229     bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
1230     void unlock() { LeaveCriticalSection(&cs); }
1231
1232     CRITICAL_SECTION cs;
1233     int refcount;
1234 };
1235
1236 #else
1237
1238 struct Mutex::Impl
1239 {
1240     Impl()
1241     {
1242         pthread_mutexattr_t attr;
1243         pthread_mutexattr_init(&attr);
1244         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1245         pthread_mutex_init(&mt, &attr);
1246         pthread_mutexattr_destroy(&attr);
1247
1248         refcount = 1;
1249     }
1250     ~Impl() { pthread_mutex_destroy(&mt); }
1251
1252     void lock() { pthread_mutex_lock(&mt); }
1253     bool trylock() { return pthread_mutex_trylock(&mt) == 0; }
1254     void unlock() { pthread_mutex_unlock(&mt); }
1255
1256     pthread_mutex_t mt;
1257     int refcount;
1258 };
1259
1260 #endif
1261
1262 Mutex::Mutex()
1263 {
1264     impl = new Mutex::Impl;
1265 }
1266
1267 Mutex::~Mutex()
1268 {
1269     if( CV_XADD(&impl->refcount, -1) == 1 )
1270         delete impl;
1271     impl = 0;
1272 }
1273
1274 Mutex::Mutex(const Mutex& m)
1275 {
1276     impl = m.impl;
1277     CV_XADD(&impl->refcount, 1);
1278 }
1279
1280 Mutex& Mutex::operator = (const Mutex& m)
1281 {
1282     if (this != &m)
1283     {
1284         CV_XADD(&m.impl->refcount, 1);
1285         if( CV_XADD(&impl->refcount, -1) == 1 )
1286             delete impl;
1287         impl = m.impl;
1288     }
1289     return *this;
1290 }
1291
1292 void Mutex::lock() { impl->lock(); }
1293 void Mutex::unlock() { impl->unlock(); }
1294 bool Mutex::trylock() { return impl->trylock(); }
1295
1296
1297 //////////////////////////////// thread-local storage ////////////////////////////////
1298
1299 #ifdef _WIN32
1300 #ifdef _MSC_VER
1301 #pragma warning(disable:4505) // unreferenced local function has been removed
1302 #endif
1303 #ifndef TLS_OUT_OF_INDEXES
1304 #define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
1305 #endif
1306 #endif
1307
1308 // TLS platform abstraction layer
1309 class TlsAbstraction
1310 {
1311 public:
1312     TlsAbstraction();
1313     ~TlsAbstraction();
1314     void* GetData() const;
1315     void  SetData(void *pData);
1316
1317 private:
1318 #ifdef _WIN32
1319 #ifndef WINRT
1320     DWORD tlsKey;
1321 #endif
1322 #else // _WIN32
1323     pthread_key_t  tlsKey;
1324 #endif
1325 };
1326
1327 #ifdef _WIN32
1328 #ifdef WINRT
1329 static __declspec( thread ) void* tlsData = NULL; // using C++11 thread attribute for local thread data
1330 TlsAbstraction::TlsAbstraction() {}
1331 TlsAbstraction::~TlsAbstraction() {}
1332 void* TlsAbstraction::GetData() const
1333 {
1334     return tlsData;
1335 }
1336 void  TlsAbstraction::SetData(void *pData)
1337 {
1338     tlsData = pData;
1339 }
1340 #else //WINRT
1341 TlsAbstraction::TlsAbstraction()
1342 {
1343     tlsKey = TlsAlloc();
1344     CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
1345 }
1346 TlsAbstraction::~TlsAbstraction()
1347 {
1348     TlsFree(tlsKey);
1349 }
1350 void* TlsAbstraction::GetData() const
1351 {
1352     return TlsGetValue(tlsKey);
1353 }
1354 void  TlsAbstraction::SetData(void *pData)
1355 {
1356     CV_Assert(TlsSetValue(tlsKey, pData) == TRUE);
1357 }
1358 #endif
1359 #else // _WIN32
1360 TlsAbstraction::TlsAbstraction()
1361 {
1362     CV_Assert(pthread_key_create(&tlsKey, NULL) == 0);
1363 }
1364 TlsAbstraction::~TlsAbstraction()
1365 {
1366     CV_Assert(pthread_key_delete(tlsKey) == 0);
1367 }
1368 void* TlsAbstraction::GetData() const
1369 {
1370     return pthread_getspecific(tlsKey);
1371 }
1372 void  TlsAbstraction::SetData(void *pData)
1373 {
1374     CV_Assert(pthread_setspecific(tlsKey, pData) == 0);
1375 }
1376 #endif
1377
1378 // Per-thread data structure
1379 struct ThreadData
1380 {
1381     ThreadData()
1382     {
1383         idx = 0;
1384         slots.reserve(32);
1385     }
1386
1387     std::vector<void*> slots; // Data array for a thread
1388     size_t idx;               // Thread index in TLS storage. This is not OS thread ID!
1389 };
1390
1391 // Main TLS storage class
1392 class TlsStorage
1393 {
1394 public:
1395     TlsStorage() :
1396         tlsSlotsSize(0)
1397     {
1398         tlsSlots.reserve(32);
1399         threads.reserve(32);
1400     }
1401     ~TlsStorage()
1402     {
1403         for(size_t i = 0; i < threads.size(); i++)
1404         {
1405             if(threads[i])
1406             {
1407                 /* Current architecture doesn't allow proper global objects release, so this check can cause crashes
1408
1409                 // Check if all slots were properly cleared
1410                 for(size_t j = 0; j < threads[i]->slots.size(); j++)
1411                 {
1412                     CV_Assert(threads[i]->slots[j] == 0);
1413                 }
1414                 */
1415                 delete threads[i];
1416             }
1417         }
1418         threads.clear();
1419     }
1420
1421     void releaseThread()
1422     {
1423         AutoLock guard(mtxGlobalAccess);
1424         ThreadData *pTD = (ThreadData*)tls.GetData();
1425         for(size_t i = 0; i < threads.size(); i++)
1426         {
1427             if(pTD == threads[i])
1428             {
1429                 threads[i] = 0;
1430                 break;
1431             }
1432         }
1433         tls.SetData(0);
1434         delete pTD;
1435     }
1436
1437     // Reserve TLS storage index
1438     size_t reserveSlot()
1439     {
1440         AutoLock guard(mtxGlobalAccess);
1441         CV_Assert(tlsSlotsSize == tlsSlots.size());
1442
1443         // Find unused slots
1444         for(size_t slot = 0; slot < tlsSlotsSize; slot++)
1445         {
1446             if(!tlsSlots[slot])
1447             {
1448                 tlsSlots[slot] = 1;
1449                 return slot;
1450             }
1451         }
1452
1453         // Create new slot
1454         tlsSlots.push_back(1); tlsSlotsSize++;
1455         return tlsSlotsSize - 1;
1456     }
1457
1458     // Release TLS storage index and pass associated data to caller
1459     void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec, bool keepSlot = false)
1460     {
1461         AutoLock guard(mtxGlobalAccess);
1462         CV_Assert(tlsSlotsSize == tlsSlots.size());
1463         CV_Assert(tlsSlotsSize > slotIdx);
1464
1465         for(size_t i = 0; i < threads.size(); i++)
1466         {
1467             if(threads[i])
1468             {
1469                 std::vector<void*>& thread_slots = threads[i]->slots;
1470                 if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
1471                 {
1472                     dataVec.push_back(thread_slots[slotIdx]);
1473                     thread_slots[slotIdx] = NULL;
1474                 }
1475             }
1476         }
1477
1478         if (!keepSlot)
1479             tlsSlots[slotIdx] = 0;
1480     }
1481
1482     // Get data by TLS storage index
1483     void* getData(size_t slotIdx) const
1484     {
1485 #ifndef CV_THREAD_SANITIZER
1486         CV_Assert(tlsSlotsSize > slotIdx);
1487 #endif
1488
1489         ThreadData* threadData = (ThreadData*)tls.GetData();
1490         if(threadData && threadData->slots.size() > slotIdx)
1491             return threadData->slots[slotIdx];
1492
1493         return NULL;
1494     }
1495
1496     // Gather data from threads by TLS storage index
1497     void gather(size_t slotIdx, std::vector<void*> &dataVec)
1498     {
1499         AutoLock guard(mtxGlobalAccess);
1500         CV_Assert(tlsSlotsSize == tlsSlots.size());
1501         CV_Assert(tlsSlotsSize > slotIdx);
1502
1503         for(size_t i = 0; i < threads.size(); i++)
1504         {
1505             if(threads[i])
1506             {
1507                 std::vector<void*>& thread_slots = threads[i]->slots;
1508                 if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
1509                     dataVec.push_back(thread_slots[slotIdx]);
1510             }
1511         }
1512     }
1513
1514     // Set data to storage index
1515     void setData(size_t slotIdx, void* pData)
1516     {
1517 #ifndef CV_THREAD_SANITIZER
1518         CV_Assert(tlsSlotsSize > slotIdx);
1519 #endif
1520
1521         ThreadData* threadData = (ThreadData*)tls.GetData();
1522         if(!threadData)
1523         {
1524             threadData = new ThreadData;
1525             tls.SetData((void*)threadData);
1526             {
1527                 AutoLock guard(mtxGlobalAccess);
1528                 threadData->idx = threads.size();
1529                 threads.push_back(threadData);
1530             }
1531         }
1532
1533         if(slotIdx >= threadData->slots.size())
1534         {
1535             AutoLock guard(mtxGlobalAccess); // keep synchronization with gather() calls
1536             threadData->slots.resize(slotIdx + 1, NULL);
1537         }
1538         threadData->slots[slotIdx] = pData;
1539     }
1540
1541 private:
1542     TlsAbstraction tls; // TLS abstraction layer instance
1543
1544     Mutex  mtxGlobalAccess;           // Shared objects operation guard
1545     size_t tlsSlotsSize;              // equal to tlsSlots.size() in synchronized sections
1546                                       // without synchronization this counter doesn't desrease - it is used for slotIdx sanity checks
1547     std::vector<int> tlsSlots;        // TLS keys state
1548     std::vector<ThreadData*> threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup
1549 };
1550
1551 // Create global TLS storage object
1552 static TlsStorage &getTlsStorage()
1553 {
1554     CV_SINGLETON_LAZY_INIT_REF(TlsStorage, new TlsStorage())
1555 }
1556
1557 TLSDataContainer::TLSDataContainer()
1558 {
1559     key_ = (int)getTlsStorage().reserveSlot(); // Reserve key from TLS storage
1560 }
1561
1562 TLSDataContainer::~TLSDataContainer()
1563 {
1564     CV_Assert(key_ == -1); // Key must be released in child object
1565 }
1566
1567 void TLSDataContainer::gatherData(std::vector<void*> &data) const
1568 {
1569     getTlsStorage().gather(key_, data);
1570 }
1571
1572 void TLSDataContainer::release()
1573 {
1574     std::vector<void*> data;
1575     data.reserve(32);
1576     getTlsStorage().releaseSlot(key_, data); // Release key and get stored data for proper destruction
1577     key_ = -1;
1578     for(size_t i = 0; i < data.size(); i++)  // Delete all associated data
1579         deleteDataInstance(data[i]);
1580 }
1581
1582 void TLSDataContainer::cleanup()
1583 {
1584     std::vector<void*> data;
1585     data.reserve(32);
1586     getTlsStorage().releaseSlot(key_, data, true); // Extract stored data with removal from TLS tables
1587     for(size_t i = 0; i < data.size(); i++)  // Delete all associated data
1588         deleteDataInstance(data[i]);
1589 }
1590
1591 void* TLSDataContainer::getData() const
1592 {
1593     CV_Assert(key_ != -1 && "Can't fetch data from terminated TLS container.");
1594     void* pData = getTlsStorage().getData(key_); // Check if data was already allocated
1595     if(!pData)
1596     {
1597         // Create new data instance and save it to TLS storage
1598         pData = createDataInstance();
1599         getTlsStorage().setData(key_, pData);
1600     }
1601     return pData;
1602 }
1603
1604 TLSData<CoreTLSData>& getCoreTlsData()
1605 {
1606     CV_SINGLETON_LAZY_INIT_REF(TLSData<CoreTLSData>, new TLSData<CoreTLSData>())
1607 }
1608
1609 #if defined CVAPI_EXPORTS && defined _WIN32 && !defined WINCE
1610 #ifdef WINRT
1611     #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
1612 #endif
1613
1614 extern "C"
1615 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved);
1616
1617 extern "C"
1618 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
1619 {
1620     if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
1621     {
1622         if (lpReserved != NULL) // called after ExitProcess() call
1623         {
1624             cv::__termination = true;
1625         }
1626         else
1627         {
1628             // Not allowed to free resources if lpReserved is non-null
1629             // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583.aspx
1630             cv::getTlsStorage().releaseThread();
1631         }
1632     }
1633     return TRUE;
1634 }
1635 #endif
1636
1637
1638 namespace {
1639 static int g_threadNum = 0;
1640 class ThreadID {
1641 public:
1642     const int id;
1643     ThreadID() :
1644         id(CV_XADD(&g_threadNum, 1))
1645     {
1646 #ifdef OPENCV_WITH_ITT
1647         __itt_thread_set_name(cv::format("OpenCVThread-%03d", id).c_str());
1648 #endif
1649     }
1650 };
1651
1652 static TLSData<ThreadID>& getThreadIDTLS()
1653 {
1654     CV_SINGLETON_LAZY_INIT_REF(TLSData<ThreadID>, new TLSData<ThreadID>());
1655 }
1656
1657 } // namespace
1658 int utils::getThreadID() { return getThreadIDTLS().get()->id; }
1659
1660 bool utils::getConfigurationParameterBool(const char* name, bool defaultValue)
1661 {
1662 #ifdef NO_GETENV
1663     const char* envValue = NULL;
1664 #else
1665     const char* envValue = getenv(name);
1666 #endif
1667     if (envValue == NULL)
1668     {
1669         return defaultValue;
1670     }
1671     cv::String value = envValue;
1672     if (value == "1" || value == "True" || value == "true" || value == "TRUE")
1673     {
1674         return true;
1675     }
1676     if (value == "0" || value == "False" || value == "false" || value == "FALSE")
1677     {
1678         return false;
1679     }
1680     CV_Error(cv::Error::StsBadArg, cv::format("Invalid value for %s parameter: %s", name, value.c_str()));
1681 }
1682
1683
1684 size_t utils::getConfigurationParameterSizeT(const char* name, size_t defaultValue)
1685 {
1686 #ifdef NO_GETENV
1687     const char* envValue = NULL;
1688 #else
1689     const char* envValue = getenv(name);
1690 #endif
1691     if (envValue == NULL)
1692     {
1693         return defaultValue;
1694     }
1695     cv::String value = envValue;
1696     size_t pos = 0;
1697     for (; pos < value.size(); pos++)
1698     {
1699         if (!isdigit(value[pos]))
1700             break;
1701     }
1702     cv::String valueStr = value.substr(0, pos);
1703     cv::String suffixStr = value.substr(pos, value.length() - pos);
1704     int v = atoi(valueStr.c_str());
1705     if (suffixStr.length() == 0)
1706         return v;
1707     else if (suffixStr == "MB" || suffixStr == "Mb" || suffixStr == "mb")
1708         return v * 1024 * 1024;
1709     else if (suffixStr == "KB" || suffixStr == "Kb" || suffixStr == "kb")
1710         return v * 1024;
1711     CV_Error(cv::Error::StsBadArg, cv::format("Invalid value for %s parameter: %s", name, value.c_str()));
1712 }
1713
1714 cv::String utils::getConfigurationParameterString(const char* name, const char* defaultValue)
1715 {
1716 #ifdef NO_GETENV
1717     const char* envValue = NULL;
1718 #else
1719     const char* envValue = getenv(name);
1720 #endif
1721     if (envValue == NULL)
1722     {
1723         return defaultValue;
1724     }
1725     cv::String value = envValue;
1726     return value;
1727 }
1728
1729
1730 #ifdef CV_COLLECT_IMPL_DATA
1731 ImplCollector& getImplData()
1732 {
1733     CV_SINGLETON_LAZY_INIT_REF(ImplCollector, new ImplCollector())
1734 }
1735
1736 void setImpl(int flags)
1737 {
1738     cv::AutoLock lock(getImplData().mutex);
1739
1740     getImplData().implFlags = flags;
1741     getImplData().implCode.clear();
1742     getImplData().implFun.clear();
1743 }
1744
1745 void addImpl(int flag, const char* func)
1746 {
1747     cv::AutoLock lock(getImplData().mutex);
1748
1749     getImplData().implFlags |= flag;
1750     if(func) // use lazy collection if name was not specified
1751     {
1752         size_t index = getImplData().implCode.size();
1753         if(!index || (getImplData().implCode[index-1] != flag || getImplData().implFun[index-1].compare(func))) // avoid duplicates
1754         {
1755             getImplData().implCode.push_back(flag);
1756             getImplData().implFun.push_back(func);
1757         }
1758     }
1759 }
1760
1761 int getImpl(std::vector<int> &impl, std::vector<String> &funName)
1762 {
1763     cv::AutoLock lock(getImplData().mutex);
1764
1765     impl    = getImplData().implCode;
1766     funName = getImplData().implFun;
1767     return getImplData().implFlags; // return actual flags for lazy collection
1768 }
1769
1770 bool useCollection()
1771 {
1772     return getImplData().useCollection;
1773 }
1774
1775 void setUseCollection(bool flag)
1776 {
1777     cv::AutoLock lock(getImplData().mutex);
1778
1779     getImplData().useCollection = flag;
1780 }
1781 #endif
1782
1783 namespace instr
1784 {
1785 bool useInstrumentation()
1786 {
1787 #ifdef ENABLE_INSTRUMENTATION
1788     return getInstrumentStruct().useInstr;
1789 #else
1790     return false;
1791 #endif
1792 }
1793
1794 void setUseInstrumentation(bool flag)
1795 {
1796 #ifdef ENABLE_INSTRUMENTATION
1797     getInstrumentStruct().useInstr = flag;
1798 #else
1799     CV_UNUSED(flag);
1800 #endif
1801 }
1802
1803 InstrNode* getTrace()
1804 {
1805 #ifdef ENABLE_INSTRUMENTATION
1806     return &getInstrumentStruct().rootNode;
1807 #else
1808     return NULL;
1809 #endif
1810 }
1811
1812 void resetTrace()
1813 {
1814 #ifdef ENABLE_INSTRUMENTATION
1815     getInstrumentStruct().rootNode.removeChilds();
1816     getInstrumentTLSStruct().pCurrentNode = &getInstrumentStruct().rootNode;
1817 #endif
1818 }
1819
1820 void setFlags(FLAGS modeFlags)
1821 {
1822 #ifdef ENABLE_INSTRUMENTATION
1823     getInstrumentStruct().flags = modeFlags;
1824 #else
1825     CV_UNUSED(modeFlags);
1826 #endif
1827 }
1828 FLAGS getFlags()
1829 {
1830 #ifdef ENABLE_INSTRUMENTATION
1831     return (FLAGS)getInstrumentStruct().flags;
1832 #else
1833     return (FLAGS)0;
1834 #endif
1835 }
1836
1837 NodeData::NodeData(const char* funName, const char* fileName, int lineNum, void* retAddress, bool alwaysExpand, cv::instr::TYPE instrType, cv::instr::IMPL implType)
1838 {
1839     m_funName       = funName;
1840     m_instrType     = instrType;
1841     m_implType      = implType;
1842     m_fileName      = fileName;
1843     m_lineNum       = lineNum;
1844     m_retAddress    = retAddress;
1845     m_alwaysExpand  = alwaysExpand;
1846
1847     m_threads    = 1;
1848     m_counter    = 0;
1849     m_ticksTotal = 0;
1850
1851     m_funError  = false;
1852 }
1853 NodeData::NodeData(NodeData &ref)
1854 {
1855     *this = ref;
1856 }
1857 NodeData& NodeData::operator=(const NodeData &right)
1858 {
1859     this->m_funName      = right.m_funName;
1860     this->m_instrType    = right.m_instrType;
1861     this->m_implType     = right.m_implType;
1862     this->m_fileName     = right.m_fileName;
1863     this->m_lineNum      = right.m_lineNum;
1864     this->m_retAddress   = right.m_retAddress;
1865     this->m_alwaysExpand = right.m_alwaysExpand;
1866
1867     this->m_threads     = right.m_threads;
1868     this->m_counter     = right.m_counter;
1869     this->m_ticksTotal  = right.m_ticksTotal;
1870
1871     this->m_funError    = right.m_funError;
1872
1873     return *this;
1874 }
1875 NodeData::~NodeData()
1876 {
1877 }
1878 bool operator==(const NodeData& left, const NodeData& right)
1879 {
1880     if(left.m_lineNum == right.m_lineNum && left.m_funName == right.m_funName && left.m_fileName == right.m_fileName)
1881     {
1882         if(left.m_retAddress == right.m_retAddress || !(cv::instr::getFlags()&cv::instr::FLAGS_EXPAND_SAME_NAMES || left.m_alwaysExpand))
1883             return true;
1884     }
1885     return false;
1886 }
1887
1888 #ifdef ENABLE_INSTRUMENTATION
1889 InstrStruct& getInstrumentStruct()
1890 {
1891     static InstrStruct instr;
1892     return instr;
1893 }
1894
1895 InstrTLSStruct& getInstrumentTLSStruct()
1896 {
1897     return *getInstrumentStruct().tlsStruct.get();
1898 }
1899
1900 InstrNode* getCurrentNode()
1901 {
1902     return getInstrumentTLSStruct().pCurrentNode;
1903 }
1904
1905 IntrumentationRegion::IntrumentationRegion(const char* funName, const char* fileName, int lineNum, void *retAddress, bool alwaysExpand, TYPE instrType, IMPL implType)
1906 {
1907     m_disabled    = false;
1908     m_regionTicks = 0;
1909
1910     InstrStruct *pStruct = &getInstrumentStruct();
1911     if(pStruct->useInstr)
1912     {
1913         InstrTLSStruct *pTLS = &getInstrumentTLSStruct();
1914
1915         // Disable in case of failure
1916         if(!pTLS->pCurrentNode)
1917         {
1918             m_disabled = true;
1919             return;
1920         }
1921
1922         int depth = pTLS->pCurrentNode->getDepth();
1923         if(pStruct->maxDepth && pStruct->maxDepth <= depth)
1924         {
1925             m_disabled = true;
1926             return;
1927         }
1928
1929         NodeData payload(funName, fileName, lineNum, retAddress, alwaysExpand, instrType, implType);
1930         Node<NodeData>* pChild = NULL;
1931
1932         if(pStruct->flags&FLAGS_MAPPING)
1933         {
1934             // Critical section
1935             cv::AutoLock guard(pStruct->mutexCreate); // Guard from concurrent child creation
1936             pChild = pTLS->pCurrentNode->findChild(payload);
1937             if(!pChild)
1938             {
1939                 pChild = new Node<NodeData>(payload);
1940                 pTLS->pCurrentNode->addChild(pChild);
1941             }
1942         }
1943         else
1944         {
1945             pChild = pTLS->pCurrentNode->findChild(payload);
1946             if(!pChild)
1947             {
1948                 m_disabled = true;
1949                 return;
1950             }
1951         }
1952         pTLS->pCurrentNode = pChild;
1953
1954         m_regionTicks = getTickCount();
1955     }
1956 }
1957
1958 IntrumentationRegion::~IntrumentationRegion()
1959 {
1960     InstrStruct *pStruct = &getInstrumentStruct();
1961     if(pStruct->useInstr)
1962     {
1963         if(!m_disabled)
1964         {
1965             InstrTLSStruct *pTLS = &getInstrumentTLSStruct();
1966
1967             if (pTLS->pCurrentNode->m_payload.m_implType == cv::instr::IMPL_OPENCL &&
1968                 (pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_FUN ||
1969                     pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_WRAPPER))
1970             {
1971                 cv::ocl::finish(); // TODO Support "async" OpenCL instrumentation
1972             }
1973
1974             uint64 ticks = (getTickCount() - m_regionTicks);
1975             {
1976                 cv::AutoLock guard(pStruct->mutexCount); // Concurrent ticks accumulation
1977                 pTLS->pCurrentNode->m_payload.m_counter++;
1978                 pTLS->pCurrentNode->m_payload.m_ticksTotal += ticks;
1979                 pTLS->pCurrentNode->m_payload.m_tls.get()->m_ticksTotal += ticks;
1980             }
1981
1982             pTLS->pCurrentNode = pTLS->pCurrentNode->m_pParent;
1983         }
1984     }
1985 }
1986 #endif
1987 }
1988
1989 namespace ipp
1990 {
1991
1992 #ifdef HAVE_IPP
1993 struct IPPInitSingleton
1994 {
1995 public:
1996     IPPInitSingleton()
1997     {
1998         useIPP         = true;
1999         useIPP_NE      = false;
2000         ippStatus      = 0;
2001         funcname       = NULL;
2002         filename       = NULL;
2003         linen          = 0;
2004         cpuFeatures    = 0;
2005         ippFeatures    = 0;
2006         ippTopFeatures = 0;
2007         pIppLibInfo    = NULL;
2008
2009         ippStatus = ippGetCpuFeatures(&cpuFeatures, NULL);
2010         if(ippStatus < 0)
2011         {
2012             std::cerr << "ERROR: IPP cannot detect CPU features, IPP was disabled " << std::endl;
2013             useIPP = false;
2014             return;
2015         }
2016         ippFeatures = cpuFeatures;
2017
2018         const char* pIppEnv = getenv("OPENCV_IPP");
2019         cv::String env = pIppEnv;
2020         if(env.size())
2021         {
2022 #if IPP_VERSION_X100 >= 201703
2023             const Ipp64u minorFeatures = ippCPUID_MOVBE|ippCPUID_AES|ippCPUID_CLMUL|ippCPUID_ABR|ippCPUID_RDRAND|ippCPUID_F16C|
2024                 ippCPUID_ADCOX|ippCPUID_RDSEED|ippCPUID_PREFETCHW|ippCPUID_SHA|ippCPUID_MPX|ippCPUID_AVX512CD|ippCPUID_AVX512ER|
2025                 ippCPUID_AVX512PF|ippCPUID_AVX512BW|ippCPUID_AVX512DQ|ippCPUID_AVX512VL|ippCPUID_AVX512VBMI;
2026 #elif IPP_VERSION_X100 >= 201700
2027             const Ipp64u minorFeatures = ippCPUID_MOVBE|ippCPUID_AES|ippCPUID_CLMUL|ippCPUID_ABR|ippCPUID_RDRAND|ippCPUID_F16C|
2028                 ippCPUID_ADCOX|ippCPUID_RDSEED|ippCPUID_PREFETCHW|ippCPUID_SHA|ippCPUID_AVX512CD|ippCPUID_AVX512ER|
2029                 ippCPUID_AVX512PF|ippCPUID_AVX512BW|ippCPUID_AVX512DQ|ippCPUID_AVX512VL|ippCPUID_AVX512VBMI;
2030 #else
2031             const Ipp64u minorFeatures = 0;
2032 #endif
2033
2034             env = env.toLowerCase();
2035             if(env.substr(0, 2) == "ne")
2036             {
2037                 useIPP_NE = true;
2038                 env = env.substr(3, env.size());
2039             }
2040
2041             if(env == "disabled")
2042             {
2043                 std::cerr << "WARNING: IPP was disabled by OPENCV_IPP environment variable" << std::endl;
2044                 useIPP = false;
2045             }
2046             else if(env == "sse42")
2047                 ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42;
2048             else if(env == "avx2")
2049                 ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42|ippCPUID_AVX|ippCPUID_AVX2;
2050 #if IPP_VERSION_X100 >= 201700
2051 #if defined (_M_AMD64) || defined (__x86_64__)
2052             else if(env == "avx512")
2053                 ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42|ippCPUID_AVX|ippCPUID_AVX2|ippCPUID_AVX512F;
2054 #endif
2055 #endif
2056             else
2057                 std::cerr << "ERROR: Improper value of OPENCV_IPP: " << env.c_str() << ". Correct values are: disabled, sse42, avx2, avx512 (Intel64 only)" << std::endl;
2058
2059             // Trim unsupported features
2060             ippFeatures &= cpuFeatures;
2061         }
2062
2063         // Disable AVX1 since we don't track regressions for it. SSE42 will be used instead
2064         if(cpuFeatures&ippCPUID_AVX && !(cpuFeatures&ippCPUID_AVX2))
2065             ippFeatures &= ~((Ipp64u)ippCPUID_AVX);
2066
2067         // IPP integrations in OpenCV support only SSE4.2, AVX2 and AVX-512 optimizations.
2068         if(!(
2069 #if IPP_VERSION_X100 >= 201700
2070             cpuFeatures&ippCPUID_AVX512F ||
2071 #endif
2072             cpuFeatures&ippCPUID_AVX2 ||
2073             cpuFeatures&ippCPUID_SSE42
2074             ))
2075         {
2076             useIPP = false;
2077             return;
2078         }
2079
2080         if(ippFeatures == cpuFeatures)
2081             IPP_INITIALIZER(0)
2082         else
2083             IPP_INITIALIZER(ippFeatures)
2084         ippFeatures = ippGetEnabledCpuFeatures();
2085
2086         // Detect top level optimizations to make comparison easier for optimizations dependent conditions
2087 #if IPP_VERSION_X100 >= 201700
2088         if(ippFeatures&ippCPUID_AVX512F)
2089         {
2090             if((ippFeatures&ippCPUID_AVX512_SKX) == ippCPUID_AVX512_SKX)
2091                 ippTopFeatures = ippCPUID_AVX512_SKX;
2092             else if((ippFeatures&ippCPUID_AVX512_KNL) == ippCPUID_AVX512_KNL)
2093                 ippTopFeatures = ippCPUID_AVX512_KNL;
2094             else
2095                 ippTopFeatures = ippCPUID_AVX512F; // Unknown AVX512 configuration
2096         }
2097         else
2098 #endif
2099         if(ippFeatures&ippCPUID_AVX2)
2100             ippTopFeatures = ippCPUID_AVX2;
2101         else if(ippFeatures&ippCPUID_SSE42)
2102             ippTopFeatures = ippCPUID_SSE42;
2103
2104         pIppLibInfo = ippiGetLibVersion();
2105     }
2106
2107 public:
2108     bool        useIPP;
2109     bool        useIPP_NE;
2110
2111     int         ippStatus;  // 0 - all is ok, -1 - IPP functions failed
2112     const char *funcname;
2113     const char *filename;
2114     int         linen;
2115     Ipp64u      ippFeatures;
2116     Ipp64u      cpuFeatures;
2117     Ipp64u      ippTopFeatures;
2118     const IppLibraryVersion *pIppLibInfo;
2119 };
2120
2121 static IPPInitSingleton& getIPPSingleton()
2122 {
2123     CV_SINGLETON_LAZY_INIT_REF(IPPInitSingleton, new IPPInitSingleton())
2124 }
2125 #endif
2126
2127 #if OPENCV_ABI_COMPATIBILITY > 300
2128 unsigned long long getIppFeatures()
2129 #else
2130 int getIppFeatures()
2131 #endif
2132 {
2133 #ifdef HAVE_IPP
2134 #if OPENCV_ABI_COMPATIBILITY > 300
2135     return getIPPSingleton().ippFeatures;
2136 #else
2137     return (int)getIPPSingleton().ippFeatures;
2138 #endif
2139 #else
2140     return 0;
2141 #endif
2142 }
2143
2144 unsigned long long getIppTopFeatures();
2145
2146 unsigned long long getIppTopFeatures()
2147 {
2148 #ifdef HAVE_IPP
2149     return getIPPSingleton().ippTopFeatures;
2150 #else
2151     return 0;
2152 #endif
2153 }
2154
2155 void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line)
2156 {
2157 #ifdef HAVE_IPP
2158     getIPPSingleton().ippStatus = status;
2159     getIPPSingleton().funcname = _funcname;
2160     getIPPSingleton().filename = _filename;
2161     getIPPSingleton().linen = _line;
2162 #else
2163     CV_UNUSED(status); CV_UNUSED(_funcname); CV_UNUSED(_filename); CV_UNUSED(_line);
2164 #endif
2165 }
2166
2167 int getIppStatus()
2168 {
2169 #ifdef HAVE_IPP
2170     return getIPPSingleton().ippStatus;
2171 #else
2172     return 0;
2173 #endif
2174 }
2175
2176 String getIppErrorLocation()
2177 {
2178 #ifdef HAVE_IPP
2179     return format("%s:%d %s", getIPPSingleton().filename ? getIPPSingleton().filename : "", getIPPSingleton().linen, getIPPSingleton().funcname ? getIPPSingleton().funcname : "");
2180 #else
2181     return String();
2182 #endif
2183 }
2184
2185 String getIppVersion()
2186 {
2187 #ifdef HAVE_IPP
2188     const IppLibraryVersion *pInfo = getIPPSingleton().pIppLibInfo;
2189     if(pInfo)
2190         return format("%s %s %s", pInfo->Name, pInfo->Version, pInfo->BuildDate);
2191     else
2192         return String("error");
2193 #else
2194     return String("disabled");
2195 #endif
2196 }
2197
2198 bool useIPP()
2199 {
2200 #ifdef HAVE_IPP
2201     CoreTLSData* data = getCoreTlsData().get();
2202     if(data->useIPP < 0)
2203     {
2204         data->useIPP = getIPPSingleton().useIPP;
2205     }
2206     return (data->useIPP > 0);
2207 #else
2208     return false;
2209 #endif
2210 }
2211
2212 void setUseIPP(bool flag)
2213 {
2214     CoreTLSData* data = getCoreTlsData().get();
2215 #ifdef HAVE_IPP
2216     data->useIPP = (getIPPSingleton().useIPP)?flag:false;
2217 #else
2218     (void)flag;
2219     data->useIPP = false;
2220 #endif
2221 }
2222
2223 bool useIPP_NE()
2224 {
2225 #ifdef HAVE_IPP
2226     CoreTLSData* data = getCoreTlsData().get();
2227     if(data->useIPP_NE < 0)
2228     {
2229         data->useIPP_NE = getIPPSingleton().useIPP_NE;
2230     }
2231     return (data->useIPP_NE > 0);
2232 #else
2233     return false;
2234 #endif
2235 }
2236
2237 void setUseIPP_NE(bool flag)
2238 {
2239     CoreTLSData* data = getCoreTlsData().get();
2240 #ifdef HAVE_IPP
2241     data->useIPP_NE = (getIPPSingleton().useIPP_NE)?flag:false;
2242 #else
2243     (void)flag;
2244     data->useIPP_NE = false;
2245 #endif
2246 }
2247
2248 } // namespace ipp
2249
2250 } // namespace cv
2251
2252 #ifdef HAVE_TEGRA_OPTIMIZATION
2253
2254 namespace tegra {
2255
2256 bool useTegra()
2257 {
2258     cv::CoreTLSData* data = cv::getCoreTlsData().get();
2259
2260     if (data->useTegra < 0)
2261     {
2262         const char* pTegraEnv = getenv("OPENCV_TEGRA");
2263         if (pTegraEnv && (cv::String(pTegraEnv) == "disabled"))
2264             data->useTegra = false;
2265         else
2266             data->useTegra = true;
2267     }
2268
2269     return (data->useTegra > 0);
2270 }
2271
2272 void setUseTegra(bool flag)
2273 {
2274     cv::CoreTLSData* data = cv::getCoreTlsData().get();
2275     data->useTegra = flag;
2276 }
2277
2278 } // namespace tegra
2279
2280 #endif
2281
2282 /* End of file. */