Merge pull request #11502 from berak:fix_knearest
[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 volatile bool useOptimizedFlag = true;
658
659 void setUseOptimized( bool flag )
660 {
661     useOptimizedFlag = flag;
662     currentFeatures = flag ? &featuresEnabled : &featuresDisabled;
663
664     ipp::setUseIPP(flag);
665 #ifdef HAVE_OPENCL
666     ocl::setUseOpenCL(flag);
667 #endif
668 #ifdef HAVE_TEGRA_OPTIMIZATION
669     ::tegra::setUseTegra(flag);
670 #endif
671 }
672
673 bool useOptimized(void)
674 {
675     return useOptimizedFlag;
676 }
677
678 int64 getTickCount(void)
679 {
680 #if defined _WIN32 || defined WINCE
681     LARGE_INTEGER counter;
682     QueryPerformanceCounter( &counter );
683     return (int64)counter.QuadPart;
684 #elif defined __linux || defined __linux__
685     struct timespec tp;
686     clock_gettime(CLOCK_MONOTONIC, &tp);
687     return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
688 #elif defined __MACH__ && defined __APPLE__
689     return (int64)mach_absolute_time();
690 #else
691     struct timeval tv;
692     struct timezone tz;
693     gettimeofday( &tv, &tz );
694     return (int64)tv.tv_sec*1000000 + tv.tv_usec;
695 #endif
696 }
697
698 double getTickFrequency(void)
699 {
700 #if defined _WIN32 || defined WINCE
701     LARGE_INTEGER freq;
702     QueryPerformanceFrequency(&freq);
703     return (double)freq.QuadPart;
704 #elif defined __linux || defined __linux__
705     return 1e9;
706 #elif defined __MACH__ && defined __APPLE__
707     static double freq = 0;
708     if( freq == 0 )
709     {
710         mach_timebase_info_data_t sTimebaseInfo;
711         mach_timebase_info(&sTimebaseInfo);
712         freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
713     }
714     return freq;
715 #else
716     return 1e6;
717 #endif
718 }
719
720 #if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
721 #if defined(__i386__)
722
723 int64 getCPUTickCount(void)
724 {
725     int64 x;
726     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
727     return x;
728 }
729 #elif defined(__x86_64__)
730
731 int64 getCPUTickCount(void)
732 {
733     unsigned hi, lo;
734     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
735     return (int64)lo | ((int64)hi << 32);
736 }
737
738 #elif defined(__ppc__)
739
740 int64 getCPUTickCount(void)
741 {
742     int64 result = 0;
743     unsigned upper, lower, tmp;
744     __asm__ volatile(
745                      "0:                  \n"
746                      "\tmftbu   %0           \n"
747                      "\tmftb    %1           \n"
748                      "\tmftbu   %2           \n"
749                      "\tcmpw    %2,%0        \n"
750                      "\tbne     0b         \n"
751                      : "=r"(upper),"=r"(lower),"=r"(tmp)
752                      );
753     return lower | ((int64)upper << 32);
754 }
755
756 #else
757
758 #error "RDTSC not defined"
759
760 #endif
761
762 #elif defined _MSC_VER && defined _WIN32 && defined _M_IX86
763
764 int64 getCPUTickCount(void)
765 {
766     __asm _emit 0x0f;
767     __asm _emit 0x31;
768 }
769
770 #else
771
772 //#ifdef HAVE_IPP
773 //int64 getCPUTickCount(void)
774 //{
775 //    return ippGetCpuClocks();
776 //}
777 //#else
778 int64 getCPUTickCount(void)
779 {
780     return getTickCount();
781 }
782 //#endif
783
784 #endif
785
786 const String& getBuildInformation()
787 {
788     static String build_info =
789 #include "version_string.inc"
790     ;
791     return build_info;
792 }
793
794 String getVersionString() { return String(CV_VERSION); }
795
796 int getVersionMajor() { return CV_VERSION_MAJOR; }
797
798 int getVersionMinor() { return CV_VERSION_MINOR; }
799
800 int getVersionRevision() { return CV_VERSION_REVISION; }
801
802 String format( const char* fmt, ... )
803 {
804     AutoBuffer<char, 1024> buf;
805
806     for ( ; ; )
807     {
808         va_list va;
809         va_start(va, fmt);
810         int bsize = static_cast<int>(buf.size());
811         int len = cv_vsnprintf((char *)buf, bsize, fmt, va);
812         va_end(va);
813
814         CV_Assert(len >= 0 && "Check format string for errors");
815         if (len >= bsize)
816         {
817             buf.resize(len + 1);
818             continue;
819         }
820         buf[bsize - 1] = 0;
821         return String((char *)buf, len);
822     }
823 }
824
825 String tempfile( const char* suffix )
826 {
827     String fname;
828 #ifndef WINRT
829     const char *temp_dir = getenv("OPENCV_TEMP_PATH");
830 #endif
831
832 #if defined _WIN32
833 #ifdef WINRT
834     RoInitialize(RO_INIT_MULTITHREADED);
835     std::wstring temp_dir = GetTempPathWinRT();
836
837     std::wstring temp_file = GetTempFileNameWinRT(L"ocv");
838     if (temp_file.empty())
839         return String();
840
841     temp_file = temp_dir.append(std::wstring(L"\\")).append(temp_file);
842     DeleteFileW(temp_file.c_str());
843
844     char aname[MAX_PATH];
845     size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH);
846     CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
847     fname = String(aname);
848     RoUninitialize();
849 #else
850     char temp_dir2[MAX_PATH] = { 0 };
851     char temp_file[MAX_PATH] = { 0 };
852
853     if (temp_dir == 0 || temp_dir[0] == 0)
854     {
855         ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
856         temp_dir = temp_dir2;
857     }
858     if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
859         return String();
860
861     DeleteFileA(temp_file);
862
863     fname = temp_file;
864 #endif
865 # else
866 #  ifdef __ANDROID__
867     //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
868     char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
869 #  else
870     char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
871 #  endif
872
873     if (temp_dir == 0 || temp_dir[0] == 0)
874         fname = defaultTemplate;
875     else
876     {
877         fname = temp_dir;
878         char ech = fname[fname.size() - 1];
879         if(ech != '/' && ech != '\\')
880             fname = fname + "/";
881         fname = fname + "__opencv_temp.XXXXXX";
882     }
883
884     const int fd = mkstemp((char*)fname.c_str());
885     if (fd == -1) return String();
886
887     close(fd);
888     remove(fname.c_str());
889 # endif
890
891     if (suffix)
892     {
893         if (suffix[0] != '.')
894             return fname + "." + suffix;
895         else
896             return fname + suffix;
897     }
898     return fname;
899 }
900
901 static ErrorCallback customErrorCallback = 0;
902 static void* customErrorCallbackData = 0;
903 static bool breakOnError = false;
904
905 bool setBreakOnError(bool value)
906 {
907     bool prevVal = breakOnError;
908     breakOnError = value;
909     return prevVal;
910 }
911
912 int cv_snprintf(char* buf, int len, const char* fmt, ...)
913 {
914     va_list va;
915     va_start(va, fmt);
916     int res = cv_vsnprintf(buf, len, fmt, va);
917     va_end(va);
918     return res;
919 }
920
921 int cv_vsnprintf(char* buf, int len, const char* fmt, va_list args)
922 {
923 #if defined _MSC_VER
924     if (len <= 0) return len == 0 ? 1024 : -1;
925     int res = _vsnprintf_s(buf, len, _TRUNCATE, fmt, args);
926     // ensure null terminating on VS
927     if (res >= 0 && res < len)
928     {
929         buf[res] = 0;
930         return res;
931     }
932     else
933     {
934         buf[len - 1] = 0; // truncate happened
935         return res >= len ? res : (len * 2);
936     }
937 #else
938     return vsnprintf(buf, len, fmt, args);
939 #endif
940 }
941
942 static void dumpException(const Exception& exc)
943 {
944     const char* errorStr = cvErrorStr(exc.code);
945     char buf[1 << 12];
946
947     cv_snprintf(buf, sizeof(buf),
948         "OpenCV(%s) Error: %s (%s) in %s, file %s, line %d",
949         CV_VERSION,
950         errorStr, exc.err.c_str(), exc.func.size() > 0 ?
951         exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line);
952 #ifdef __ANDROID__
953     __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
954 #else
955     fflush(stdout); fflush(stderr);
956     fprintf(stderr, "%s\n", buf);
957     fflush(stderr);
958 #endif
959 }
960
961 #ifdef CV_ERROR_SET_TERMINATE_HANDLER
962 static bool cv_terminate_handler_installed = false;
963 static std::terminate_handler cv_old_terminate_handler;
964 static cv::Exception cv_terminate_handler_exception;
965 static bool param_setupTerminateHandler = utils::getConfigurationParameterBool("OPENCV_SETUP_TERMINATE_HANDLER", true);
966 static void cv_terminate_handler() {
967     std::cerr << "OpenCV: terminate handler is called! The last OpenCV error is:\n";
968     dumpException(cv_terminate_handler_exception);
969     if (false /*cv_old_terminate_handler*/)  // buggy behavior is observed with doubled "abort/retry/ignore" windows
970         cv_old_terminate_handler();
971     abort();
972 }
973
974 #endif
975
976 void error( const Exception& exc )
977 {
978 #ifdef CV_ERROR_SET_TERMINATE_HANDLER
979     {
980         cv::AutoLock lock(getInitializationMutex());
981         if (!cv_terminate_handler_installed)
982         {
983             if (param_setupTerminateHandler)
984                 cv_old_terminate_handler = std::set_terminate(cv_terminate_handler);
985             cv_terminate_handler_installed = true;
986         }
987         cv_terminate_handler_exception = exc;
988     }
989 #endif
990
991     if (customErrorCallback != 0)
992         customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
993                             exc.file.c_str(), exc.line, customErrorCallbackData);
994     else if (param_dumpErrors)
995     {
996         dumpException(exc);
997     }
998
999     if(breakOnError)
1000     {
1001         static volatile int* p = 0;
1002         *p = 0;
1003     }
1004
1005     CV_THROW(exc);
1006 }
1007
1008 void error(int _code, const String& _err, const char* _func, const char* _file, int _line)
1009 {
1010     error(cv::Exception(_code, _err, _func, _file, _line));
1011 }
1012
1013
1014 ErrorCallback
1015 redirectError( ErrorCallback errCallback, void* userdata, void** prevUserdata)
1016 {
1017     if( prevUserdata )
1018         *prevUserdata = customErrorCallbackData;
1019
1020     ErrorCallback prevCallback = customErrorCallback;
1021
1022     customErrorCallback     = errCallback;
1023     customErrorCallbackData = userdata;
1024
1025     return prevCallback;
1026 }
1027
1028 }
1029
1030 CV_IMPL int cvCheckHardwareSupport(int feature)
1031 {
1032     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
1033     return cv::currentFeatures->have[feature];
1034 }
1035
1036 CV_IMPL int cvUseOptimized( int flag )
1037 {
1038     int prevMode = cv::useOptimizedFlag;
1039     cv::setUseOptimized( flag != 0 );
1040     return prevMode;
1041 }
1042
1043 CV_IMPL int64  cvGetTickCount(void)
1044 {
1045     return cv::getTickCount();
1046 }
1047
1048 CV_IMPL double cvGetTickFrequency(void)
1049 {
1050     return cv::getTickFrequency()*1e-6;
1051 }
1052
1053 CV_IMPL CvErrorCallback
1054 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
1055 {
1056     return cv::redirectError(errCallback, userdata, prevUserdata);
1057 }
1058
1059 CV_IMPL int cvNulDevReport( int, const char*, const char*,
1060                             const char*, int, void* )
1061 {
1062     return 0;
1063 }
1064
1065 CV_IMPL int cvStdErrReport( int, const char*, const char*,
1066                             const char*, int, void* )
1067 {
1068     return 0;
1069 }
1070
1071 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
1072                             const char*, int, void* )
1073 {
1074     return 0;
1075 }
1076
1077 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
1078 {
1079     return 0;
1080 }
1081
1082
1083 CV_IMPL const char* cvErrorStr( int status )
1084 {
1085     static char buf[256];
1086
1087     switch (status)
1088     {
1089     case CV_StsOk :                  return "No Error";
1090     case CV_StsBackTrace :           return "Backtrace";
1091     case CV_StsError :               return "Unspecified error";
1092     case CV_StsInternal :            return "Internal error";
1093     case CV_StsNoMem :               return "Insufficient memory";
1094     case CV_StsBadArg :              return "Bad argument";
1095     case CV_StsNoConv :              return "Iterations do not converge";
1096     case CV_StsAutoTrace :           return "Autotrace call";
1097     case CV_StsBadSize :             return "Incorrect size of input array";
1098     case CV_StsNullPtr :             return "Null pointer";
1099     case CV_StsDivByZero :           return "Division by zero occurred";
1100     case CV_BadStep :                return "Image step is wrong";
1101     case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
1102     case CV_StsObjectNotFound :      return "Requested object was not found";
1103     case CV_BadDepth :               return "Input image depth is not supported by function";
1104     case CV_StsUnmatchedFormats :    return "Formats of input arguments do not match";
1105     case CV_StsUnmatchedSizes :      return "Sizes of input arguments do not match";
1106     case CV_StsOutOfRange :          return "One of arguments\' values is out of range";
1107     case CV_StsUnsupportedFormat :   return "Unsupported format or combination of formats";
1108     case CV_BadCOI :                 return "Input COI is not supported";
1109     case CV_BadNumChannels :         return "Bad number of channels";
1110     case CV_StsBadFlag :             return "Bad flag (parameter or structure field)";
1111     case CV_StsBadPoint :            return "Bad parameter of type CvPoint";
1112     case CV_StsBadMask :             return "Bad type of mask argument";
1113     case CV_StsParseError :          return "Parsing error";
1114     case CV_StsNotImplemented :      return "The function/feature is not implemented";
1115     case CV_StsBadMemBlock :         return "Memory block has been corrupted";
1116     case CV_StsAssert :              return "Assertion failed";
1117     case CV_GpuNotSupported :        return "No CUDA support";
1118     case CV_GpuApiCallError :        return "Gpu API call";
1119     case CV_OpenGlNotSupported :     return "No OpenGL support";
1120     case CV_OpenGlApiCallError :     return "OpenGL API call";
1121     };
1122
1123     sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
1124     return buf;
1125 }
1126
1127 CV_IMPL int cvGetErrMode(void)
1128 {
1129     return 0;
1130 }
1131
1132 CV_IMPL int cvSetErrMode(int)
1133 {
1134     return 0;
1135 }
1136
1137 CV_IMPL int cvGetErrStatus(void)
1138 {
1139     return 0;
1140 }
1141
1142 CV_IMPL void cvSetErrStatus(int)
1143 {
1144 }
1145
1146
1147 CV_IMPL void cvError( int code, const char* func_name,
1148                       const char* err_msg,
1149                       const char* file_name, int line )
1150 {
1151     cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
1152 }
1153
1154 /* function, which converts int to int */
1155 CV_IMPL int
1156 cvErrorFromIppStatus( int status )
1157 {
1158     switch (status)
1159     {
1160     case CV_BADSIZE_ERR:               return CV_StsBadSize;
1161     case CV_BADMEMBLOCK_ERR:           return CV_StsBadMemBlock;
1162     case CV_NULLPTR_ERR:               return CV_StsNullPtr;
1163     case CV_DIV_BY_ZERO_ERR:           return CV_StsDivByZero;
1164     case CV_BADSTEP_ERR:               return CV_BadStep;
1165     case CV_OUTOFMEM_ERR:              return CV_StsNoMem;
1166     case CV_BADARG_ERR:                return CV_StsBadArg;
1167     case CV_NOTDEFINED_ERR:            return CV_StsError;
1168     case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
1169     case CV_NOTFOUND_ERR:              return CV_StsObjectNotFound;
1170     case CV_BADCONVERGENCE_ERR:        return CV_StsNoConv;
1171     case CV_BADDEPTH_ERR:              return CV_BadDepth;
1172     case CV_UNMATCHED_FORMATS_ERR:     return CV_StsUnmatchedFormats;
1173     case CV_UNSUPPORTED_COI_ERR:       return CV_BadCOI;
1174     case CV_UNSUPPORTED_CHANNELS_ERR:  return CV_BadNumChannels;
1175     case CV_BADFLAG_ERR:               return CV_StsBadFlag;
1176     case CV_BADRANGE_ERR:              return CV_StsBadArg;
1177     case CV_BADCOEF_ERR:               return CV_StsBadArg;
1178     case CV_BADFACTOR_ERR:             return CV_StsBadArg;
1179     case CV_BADPOINT_ERR:              return CV_StsBadPoint;
1180
1181     default:
1182       return CV_StsError;
1183     }
1184 }
1185
1186 namespace cv {
1187 bool __termination = false;
1188 }
1189
1190 namespace cv
1191 {
1192
1193 #if defined _WIN32 || defined WINCE
1194
1195 struct Mutex::Impl
1196 {
1197     Impl()
1198     {
1199 #if (_WIN32_WINNT >= 0x0600)
1200         ::InitializeCriticalSectionEx(&cs, 1000, 0);
1201 #else
1202         ::InitializeCriticalSection(&cs);
1203 #endif
1204         refcount = 1;
1205     }
1206     ~Impl() { DeleteCriticalSection(&cs); }
1207
1208     void lock() { EnterCriticalSection(&cs); }
1209     bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
1210     void unlock() { LeaveCriticalSection(&cs); }
1211
1212     CRITICAL_SECTION cs;
1213     int refcount;
1214 };
1215
1216 #else
1217
1218 struct Mutex::Impl
1219 {
1220     Impl()
1221     {
1222         pthread_mutexattr_t attr;
1223         pthread_mutexattr_init(&attr);
1224         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1225         pthread_mutex_init(&mt, &attr);
1226         pthread_mutexattr_destroy(&attr);
1227
1228         refcount = 1;
1229     }
1230     ~Impl() { pthread_mutex_destroy(&mt); }
1231
1232     void lock() { pthread_mutex_lock(&mt); }
1233     bool trylock() { return pthread_mutex_trylock(&mt) == 0; }
1234     void unlock() { pthread_mutex_unlock(&mt); }
1235
1236     pthread_mutex_t mt;
1237     int refcount;
1238 };
1239
1240 #endif
1241
1242 Mutex::Mutex()
1243 {
1244     impl = new Mutex::Impl;
1245 }
1246
1247 Mutex::~Mutex()
1248 {
1249     if( CV_XADD(&impl->refcount, -1) == 1 )
1250         delete impl;
1251     impl = 0;
1252 }
1253
1254 Mutex::Mutex(const Mutex& m)
1255 {
1256     impl = m.impl;
1257     CV_XADD(&impl->refcount, 1);
1258 }
1259
1260 Mutex& Mutex::operator = (const Mutex& m)
1261 {
1262     if (this != &m)
1263     {
1264         CV_XADD(&m.impl->refcount, 1);
1265         if( CV_XADD(&impl->refcount, -1) == 1 )
1266             delete impl;
1267         impl = m.impl;
1268     }
1269     return *this;
1270 }
1271
1272 void Mutex::lock() { impl->lock(); }
1273 void Mutex::unlock() { impl->unlock(); }
1274 bool Mutex::trylock() { return impl->trylock(); }
1275
1276
1277 //////////////////////////////// thread-local storage ////////////////////////////////
1278
1279 #ifdef _WIN32
1280 #ifdef _MSC_VER
1281 #pragma warning(disable:4505) // unreferenced local function has been removed
1282 #endif
1283 #ifndef TLS_OUT_OF_INDEXES
1284 #define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
1285 #endif
1286 #endif
1287
1288 // TLS platform abstraction layer
1289 class TlsAbstraction
1290 {
1291 public:
1292     TlsAbstraction();
1293     ~TlsAbstraction();
1294     void* GetData() const;
1295     void  SetData(void *pData);
1296
1297 private:
1298 #ifdef _WIN32
1299 #ifndef WINRT
1300     DWORD tlsKey;
1301 #endif
1302 #else // _WIN32
1303     pthread_key_t  tlsKey;
1304 #endif
1305 };
1306
1307 #ifdef _WIN32
1308 #ifdef WINRT
1309 static __declspec( thread ) void* tlsData = NULL; // using C++11 thread attribute for local thread data
1310 TlsAbstraction::TlsAbstraction() {}
1311 TlsAbstraction::~TlsAbstraction() {}
1312 void* TlsAbstraction::GetData() const
1313 {
1314     return tlsData;
1315 }
1316 void  TlsAbstraction::SetData(void *pData)
1317 {
1318     tlsData = pData;
1319 }
1320 #else //WINRT
1321 TlsAbstraction::TlsAbstraction()
1322 {
1323     tlsKey = TlsAlloc();
1324     CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
1325 }
1326 TlsAbstraction::~TlsAbstraction()
1327 {
1328     TlsFree(tlsKey);
1329 }
1330 void* TlsAbstraction::GetData() const
1331 {
1332     return TlsGetValue(tlsKey);
1333 }
1334 void  TlsAbstraction::SetData(void *pData)
1335 {
1336     CV_Assert(TlsSetValue(tlsKey, pData) == TRUE);
1337 }
1338 #endif
1339 #else // _WIN32
1340 TlsAbstraction::TlsAbstraction()
1341 {
1342     CV_Assert(pthread_key_create(&tlsKey, NULL) == 0);
1343 }
1344 TlsAbstraction::~TlsAbstraction()
1345 {
1346     CV_Assert(pthread_key_delete(tlsKey) == 0);
1347 }
1348 void* TlsAbstraction::GetData() const
1349 {
1350     return pthread_getspecific(tlsKey);
1351 }
1352 void  TlsAbstraction::SetData(void *pData)
1353 {
1354     CV_Assert(pthread_setspecific(tlsKey, pData) == 0);
1355 }
1356 #endif
1357
1358 // Per-thread data structure
1359 struct ThreadData
1360 {
1361     ThreadData()
1362     {
1363         idx = 0;
1364         slots.reserve(32);
1365     }
1366
1367     std::vector<void*> slots; // Data array for a thread
1368     size_t idx;               // Thread index in TLS storage. This is not OS thread ID!
1369 };
1370
1371 // Main TLS storage class
1372 class TlsStorage
1373 {
1374 public:
1375     TlsStorage() :
1376         tlsSlotsSize(0)
1377     {
1378         tlsSlots.reserve(32);
1379         threads.reserve(32);
1380     }
1381     ~TlsStorage()
1382     {
1383         for(size_t i = 0; i < threads.size(); i++)
1384         {
1385             if(threads[i])
1386             {
1387                 /* Current architecture doesn't allow proper global objects release, so this check can cause crashes
1388
1389                 // Check if all slots were properly cleared
1390                 for(size_t j = 0; j < threads[i]->slots.size(); j++)
1391                 {
1392                     CV_Assert(threads[i]->slots[j] == 0);
1393                 }
1394                 */
1395                 delete threads[i];
1396             }
1397         }
1398         threads.clear();
1399     }
1400
1401     void releaseThread()
1402     {
1403         AutoLock guard(mtxGlobalAccess);
1404         ThreadData *pTD = (ThreadData*)tls.GetData();
1405         for(size_t i = 0; i < threads.size(); i++)
1406         {
1407             if(pTD == threads[i])
1408             {
1409                 threads[i] = 0;
1410                 break;
1411             }
1412         }
1413         tls.SetData(0);
1414         delete pTD;
1415     }
1416
1417     // Reserve TLS storage index
1418     size_t reserveSlot()
1419     {
1420         AutoLock guard(mtxGlobalAccess);
1421         CV_Assert(tlsSlotsSize == tlsSlots.size());
1422
1423         // Find unused slots
1424         for(size_t slot = 0; slot < tlsSlotsSize; slot++)
1425         {
1426             if(!tlsSlots[slot])
1427             {
1428                 tlsSlots[slot] = 1;
1429                 return slot;
1430             }
1431         }
1432
1433         // Create new slot
1434         tlsSlots.push_back(1); tlsSlotsSize++;
1435         return tlsSlotsSize - 1;
1436     }
1437
1438     // Release TLS storage index and pass associated data to caller
1439     void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec, bool keepSlot = false)
1440     {
1441         AutoLock guard(mtxGlobalAccess);
1442         CV_Assert(tlsSlotsSize == tlsSlots.size());
1443         CV_Assert(tlsSlotsSize > slotIdx);
1444
1445         for(size_t i = 0; i < threads.size(); i++)
1446         {
1447             if(threads[i])
1448             {
1449                 std::vector<void*>& thread_slots = threads[i]->slots;
1450                 if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
1451                 {
1452                     dataVec.push_back(thread_slots[slotIdx]);
1453                     thread_slots[slotIdx] = NULL;
1454                 }
1455             }
1456         }
1457
1458         if (!keepSlot)
1459             tlsSlots[slotIdx] = 0;
1460     }
1461
1462     // Get data by TLS storage index
1463     void* getData(size_t slotIdx) const
1464     {
1465 #ifndef CV_THREAD_SANITIZER
1466         CV_Assert(tlsSlotsSize > slotIdx);
1467 #endif
1468
1469         ThreadData* threadData = (ThreadData*)tls.GetData();
1470         if(threadData && threadData->slots.size() > slotIdx)
1471             return threadData->slots[slotIdx];
1472
1473         return NULL;
1474     }
1475
1476     // Gather data from threads by TLS storage index
1477     void gather(size_t slotIdx, std::vector<void*> &dataVec)
1478     {
1479         AutoLock guard(mtxGlobalAccess);
1480         CV_Assert(tlsSlotsSize == tlsSlots.size());
1481         CV_Assert(tlsSlotsSize > slotIdx);
1482
1483         for(size_t i = 0; i < threads.size(); i++)
1484         {
1485             if(threads[i])
1486             {
1487                 std::vector<void*>& thread_slots = threads[i]->slots;
1488                 if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
1489                     dataVec.push_back(thread_slots[slotIdx]);
1490             }
1491         }
1492     }
1493
1494     // Set data to storage index
1495     void setData(size_t slotIdx, void* pData)
1496     {
1497 #ifndef CV_THREAD_SANITIZER
1498         CV_Assert(tlsSlotsSize > slotIdx);
1499 #endif
1500
1501         ThreadData* threadData = (ThreadData*)tls.GetData();
1502         if(!threadData)
1503         {
1504             threadData = new ThreadData;
1505             tls.SetData((void*)threadData);
1506             {
1507                 AutoLock guard(mtxGlobalAccess);
1508                 threadData->idx = threads.size();
1509                 threads.push_back(threadData);
1510             }
1511         }
1512
1513         if(slotIdx >= threadData->slots.size())
1514         {
1515             AutoLock guard(mtxGlobalAccess); // keep synchronization with gather() calls
1516             threadData->slots.resize(slotIdx + 1, NULL);
1517         }
1518         threadData->slots[slotIdx] = pData;
1519     }
1520
1521 private:
1522     TlsAbstraction tls; // TLS abstraction layer instance
1523
1524     Mutex  mtxGlobalAccess;           // Shared objects operation guard
1525     size_t tlsSlotsSize;              // equal to tlsSlots.size() in synchronized sections
1526                                       // without synchronization this counter doesn't desrease - it is used for slotIdx sanity checks
1527     std::vector<int> tlsSlots;        // TLS keys state
1528     std::vector<ThreadData*> threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup
1529 };
1530
1531 // Create global TLS storage object
1532 static TlsStorage &getTlsStorage()
1533 {
1534     CV_SINGLETON_LAZY_INIT_REF(TlsStorage, new TlsStorage())
1535 }
1536
1537 TLSDataContainer::TLSDataContainer()
1538 {
1539     key_ = (int)getTlsStorage().reserveSlot(); // Reserve key from TLS storage
1540 }
1541
1542 TLSDataContainer::~TLSDataContainer()
1543 {
1544     CV_Assert(key_ == -1); // Key must be released in child object
1545 }
1546
1547 void TLSDataContainer::gatherData(std::vector<void*> &data) const
1548 {
1549     getTlsStorage().gather(key_, data);
1550 }
1551
1552 void TLSDataContainer::release()
1553 {
1554     std::vector<void*> data;
1555     data.reserve(32);
1556     getTlsStorage().releaseSlot(key_, data); // Release key and get stored data for proper destruction
1557     key_ = -1;
1558     for(size_t i = 0; i < data.size(); i++)  // Delete all associated data
1559         deleteDataInstance(data[i]);
1560 }
1561
1562 void TLSDataContainer::cleanup()
1563 {
1564     std::vector<void*> data;
1565     data.reserve(32);
1566     getTlsStorage().releaseSlot(key_, data, true); // Extract stored data with removal from TLS tables
1567     for(size_t i = 0; i < data.size(); i++)  // Delete all associated data
1568         deleteDataInstance(data[i]);
1569 }
1570
1571 void* TLSDataContainer::getData() const
1572 {
1573     CV_Assert(key_ != -1 && "Can't fetch data from terminated TLS container.");
1574     void* pData = getTlsStorage().getData(key_); // Check if data was already allocated
1575     if(!pData)
1576     {
1577         // Create new data instance and save it to TLS storage
1578         pData = createDataInstance();
1579         getTlsStorage().setData(key_, pData);
1580     }
1581     return pData;
1582 }
1583
1584 TLSData<CoreTLSData>& getCoreTlsData()
1585 {
1586     CV_SINGLETON_LAZY_INIT_REF(TLSData<CoreTLSData>, new TLSData<CoreTLSData>())
1587 }
1588
1589 #if defined CVAPI_EXPORTS && defined _WIN32 && !defined WINCE
1590 #ifdef WINRT
1591     #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
1592 #endif
1593
1594 extern "C"
1595 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved);
1596
1597 extern "C"
1598 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
1599 {
1600     if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
1601     {
1602         if (lpReserved != NULL) // called after ExitProcess() call
1603         {
1604             cv::__termination = true;
1605         }
1606         else
1607         {
1608             // Not allowed to free resources if lpReserved is non-null
1609             // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583.aspx
1610             cv::getTlsStorage().releaseThread();
1611         }
1612     }
1613     return TRUE;
1614 }
1615 #endif
1616
1617
1618 namespace {
1619 static int g_threadNum = 0;
1620 class ThreadID {
1621 public:
1622     const int id;
1623     ThreadID() :
1624         id(CV_XADD(&g_threadNum, 1))
1625     {
1626 #ifdef OPENCV_WITH_ITT
1627         __itt_thread_set_name(cv::format("OpenCVThread-%03d", id).c_str());
1628 #endif
1629     }
1630 };
1631
1632 static TLSData<ThreadID>& getThreadIDTLS()
1633 {
1634     CV_SINGLETON_LAZY_INIT_REF(TLSData<ThreadID>, new TLSData<ThreadID>());
1635 }
1636
1637 } // namespace
1638 int utils::getThreadID() { return getThreadIDTLS().get()->id; }
1639
1640 bool utils::getConfigurationParameterBool(const char* name, bool defaultValue)
1641 {
1642 #ifdef NO_GETENV
1643     const char* envValue = NULL;
1644 #else
1645     const char* envValue = getenv(name);
1646 #endif
1647     if (envValue == NULL)
1648     {
1649         return defaultValue;
1650     }
1651     cv::String value = envValue;
1652     if (value == "1" || value == "True" || value == "true" || value == "TRUE")
1653     {
1654         return true;
1655     }
1656     if (value == "0" || value == "False" || value == "false" || value == "FALSE")
1657     {
1658         return false;
1659     }
1660     CV_Error(cv::Error::StsBadArg, cv::format("Invalid value for %s parameter: %s", name, value.c_str()));
1661 }
1662
1663
1664 size_t utils::getConfigurationParameterSizeT(const char* name, size_t defaultValue)
1665 {
1666 #ifdef NO_GETENV
1667     const char* envValue = NULL;
1668 #else
1669     const char* envValue = getenv(name);
1670 #endif
1671     if (envValue == NULL)
1672     {
1673         return defaultValue;
1674     }
1675     cv::String value = envValue;
1676     size_t pos = 0;
1677     for (; pos < value.size(); pos++)
1678     {
1679         if (!isdigit(value[pos]))
1680             break;
1681     }
1682     cv::String valueStr = value.substr(0, pos);
1683     cv::String suffixStr = value.substr(pos, value.length() - pos);
1684     int v = atoi(valueStr.c_str());
1685     if (suffixStr.length() == 0)
1686         return v;
1687     else if (suffixStr == "MB" || suffixStr == "Mb" || suffixStr == "mb")
1688         return v * 1024 * 1024;
1689     else if (suffixStr == "KB" || suffixStr == "Kb" || suffixStr == "kb")
1690         return v * 1024;
1691     CV_Error(cv::Error::StsBadArg, cv::format("Invalid value for %s parameter: %s", name, value.c_str()));
1692 }
1693
1694 cv::String utils::getConfigurationParameterString(const char* name, const char* defaultValue)
1695 {
1696 #ifdef NO_GETENV
1697     const char* envValue = NULL;
1698 #else
1699     const char* envValue = getenv(name);
1700 #endif
1701     if (envValue == NULL)
1702     {
1703         return defaultValue;
1704     }
1705     cv::String value = envValue;
1706     return value;
1707 }
1708
1709
1710 #ifdef CV_COLLECT_IMPL_DATA
1711 ImplCollector& getImplData()
1712 {
1713     CV_SINGLETON_LAZY_INIT_REF(ImplCollector, new ImplCollector())
1714 }
1715
1716 void setImpl(int flags)
1717 {
1718     cv::AutoLock lock(getImplData().mutex);
1719
1720     getImplData().implFlags = flags;
1721     getImplData().implCode.clear();
1722     getImplData().implFun.clear();
1723 }
1724
1725 void addImpl(int flag, const char* func)
1726 {
1727     cv::AutoLock lock(getImplData().mutex);
1728
1729     getImplData().implFlags |= flag;
1730     if(func) // use lazy collection if name was not specified
1731     {
1732         size_t index = getImplData().implCode.size();
1733         if(!index || (getImplData().implCode[index-1] != flag || getImplData().implFun[index-1].compare(func))) // avoid duplicates
1734         {
1735             getImplData().implCode.push_back(flag);
1736             getImplData().implFun.push_back(func);
1737         }
1738     }
1739 }
1740
1741 int getImpl(std::vector<int> &impl, std::vector<String> &funName)
1742 {
1743     cv::AutoLock lock(getImplData().mutex);
1744
1745     impl    = getImplData().implCode;
1746     funName = getImplData().implFun;
1747     return getImplData().implFlags; // return actual flags for lazy collection
1748 }
1749
1750 bool useCollection()
1751 {
1752     return getImplData().useCollection;
1753 }
1754
1755 void setUseCollection(bool flag)
1756 {
1757     cv::AutoLock lock(getImplData().mutex);
1758
1759     getImplData().useCollection = flag;
1760 }
1761 #endif
1762
1763 namespace instr
1764 {
1765 bool useInstrumentation()
1766 {
1767 #ifdef ENABLE_INSTRUMENTATION
1768     return getInstrumentStruct().useInstr;
1769 #else
1770     return false;
1771 #endif
1772 }
1773
1774 void setUseInstrumentation(bool flag)
1775 {
1776 #ifdef ENABLE_INSTRUMENTATION
1777     getInstrumentStruct().useInstr = flag;
1778 #else
1779     CV_UNUSED(flag);
1780 #endif
1781 }
1782
1783 InstrNode* getTrace()
1784 {
1785 #ifdef ENABLE_INSTRUMENTATION
1786     return &getInstrumentStruct().rootNode;
1787 #else
1788     return NULL;
1789 #endif
1790 }
1791
1792 void resetTrace()
1793 {
1794 #ifdef ENABLE_INSTRUMENTATION
1795     getInstrumentStruct().rootNode.removeChilds();
1796     getInstrumentTLSStruct().pCurrentNode = &getInstrumentStruct().rootNode;
1797 #endif
1798 }
1799
1800 void setFlags(FLAGS modeFlags)
1801 {
1802 #ifdef ENABLE_INSTRUMENTATION
1803     getInstrumentStruct().flags = modeFlags;
1804 #else
1805     CV_UNUSED(modeFlags);
1806 #endif
1807 }
1808 FLAGS getFlags()
1809 {
1810 #ifdef ENABLE_INSTRUMENTATION
1811     return (FLAGS)getInstrumentStruct().flags;
1812 #else
1813     return (FLAGS)0;
1814 #endif
1815 }
1816
1817 NodeData::NodeData(const char* funName, const char* fileName, int lineNum, void* retAddress, bool alwaysExpand, cv::instr::TYPE instrType, cv::instr::IMPL implType)
1818 {
1819     m_funName       = funName;
1820     m_instrType     = instrType;
1821     m_implType      = implType;
1822     m_fileName      = fileName;
1823     m_lineNum       = lineNum;
1824     m_retAddress    = retAddress;
1825     m_alwaysExpand  = alwaysExpand;
1826
1827     m_threads    = 1;
1828     m_counter    = 0;
1829     m_ticksTotal = 0;
1830
1831     m_funError  = false;
1832 }
1833 NodeData::NodeData(NodeData &ref)
1834 {
1835     *this = ref;
1836 }
1837 NodeData& NodeData::operator=(const NodeData &right)
1838 {
1839     this->m_funName      = right.m_funName;
1840     this->m_instrType    = right.m_instrType;
1841     this->m_implType     = right.m_implType;
1842     this->m_fileName     = right.m_fileName;
1843     this->m_lineNum      = right.m_lineNum;
1844     this->m_retAddress   = right.m_retAddress;
1845     this->m_alwaysExpand = right.m_alwaysExpand;
1846
1847     this->m_threads     = right.m_threads;
1848     this->m_counter     = right.m_counter;
1849     this->m_ticksTotal  = right.m_ticksTotal;
1850
1851     this->m_funError    = right.m_funError;
1852
1853     return *this;
1854 }
1855 NodeData::~NodeData()
1856 {
1857 }
1858 bool operator==(const NodeData& left, const NodeData& right)
1859 {
1860     if(left.m_lineNum == right.m_lineNum && left.m_funName == right.m_funName && left.m_fileName == right.m_fileName)
1861     {
1862         if(left.m_retAddress == right.m_retAddress || !(cv::instr::getFlags()&cv::instr::FLAGS_EXPAND_SAME_NAMES || left.m_alwaysExpand))
1863             return true;
1864     }
1865     return false;
1866 }
1867
1868 #ifdef ENABLE_INSTRUMENTATION
1869 InstrStruct& getInstrumentStruct()
1870 {
1871     static InstrStruct instr;
1872     return instr;
1873 }
1874
1875 InstrTLSStruct& getInstrumentTLSStruct()
1876 {
1877     return *getInstrumentStruct().tlsStruct.get();
1878 }
1879
1880 InstrNode* getCurrentNode()
1881 {
1882     return getInstrumentTLSStruct().pCurrentNode;
1883 }
1884
1885 IntrumentationRegion::IntrumentationRegion(const char* funName, const char* fileName, int lineNum, void *retAddress, bool alwaysExpand, TYPE instrType, IMPL implType)
1886 {
1887     m_disabled    = false;
1888     m_regionTicks = 0;
1889
1890     InstrStruct *pStruct = &getInstrumentStruct();
1891     if(pStruct->useInstr)
1892     {
1893         InstrTLSStruct *pTLS = &getInstrumentTLSStruct();
1894
1895         // Disable in case of failure
1896         if(!pTLS->pCurrentNode)
1897         {
1898             m_disabled = true;
1899             return;
1900         }
1901
1902         int depth = pTLS->pCurrentNode->getDepth();
1903         if(pStruct->maxDepth && pStruct->maxDepth <= depth)
1904         {
1905             m_disabled = true;
1906             return;
1907         }
1908
1909         NodeData payload(funName, fileName, lineNum, retAddress, alwaysExpand, instrType, implType);
1910         Node<NodeData>* pChild = NULL;
1911
1912         if(pStruct->flags&FLAGS_MAPPING)
1913         {
1914             // Critical section
1915             cv::AutoLock guard(pStruct->mutexCreate); // Guard from concurrent child creation
1916             pChild = pTLS->pCurrentNode->findChild(payload);
1917             if(!pChild)
1918             {
1919                 pChild = new Node<NodeData>(payload);
1920                 pTLS->pCurrentNode->addChild(pChild);
1921             }
1922         }
1923         else
1924         {
1925             pChild = pTLS->pCurrentNode->findChild(payload);
1926             if(!pChild)
1927             {
1928                 m_disabled = true;
1929                 return;
1930             }
1931         }
1932         pTLS->pCurrentNode = pChild;
1933
1934         m_regionTicks = getTickCount();
1935     }
1936 }
1937
1938 IntrumentationRegion::~IntrumentationRegion()
1939 {
1940     InstrStruct *pStruct = &getInstrumentStruct();
1941     if(pStruct->useInstr)
1942     {
1943         if(!m_disabled)
1944         {
1945             InstrTLSStruct *pTLS = &getInstrumentTLSStruct();
1946
1947             if (pTLS->pCurrentNode->m_payload.m_implType == cv::instr::IMPL_OPENCL &&
1948                 (pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_FUN ||
1949                     pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_WRAPPER))
1950             {
1951                 cv::ocl::finish(); // TODO Support "async" OpenCL instrumentation
1952             }
1953
1954             uint64 ticks = (getTickCount() - m_regionTicks);
1955             {
1956                 cv::AutoLock guard(pStruct->mutexCount); // Concurrent ticks accumulation
1957                 pTLS->pCurrentNode->m_payload.m_counter++;
1958                 pTLS->pCurrentNode->m_payload.m_ticksTotal += ticks;
1959                 pTLS->pCurrentNode->m_payload.m_tls.get()->m_ticksTotal += ticks;
1960             }
1961
1962             pTLS->pCurrentNode = pTLS->pCurrentNode->m_pParent;
1963         }
1964     }
1965 }
1966 #endif
1967 }
1968
1969 namespace ipp
1970 {
1971
1972 #ifdef HAVE_IPP
1973 struct IPPInitSingleton
1974 {
1975 public:
1976     IPPInitSingleton()
1977     {
1978         useIPP         = true;
1979         useIPP_NE      = false;
1980         ippStatus      = 0;
1981         funcname       = NULL;
1982         filename       = NULL;
1983         linen          = 0;
1984         cpuFeatures    = 0;
1985         ippFeatures    = 0;
1986         ippTopFeatures = 0;
1987         pIppLibInfo    = NULL;
1988
1989         ippStatus = ippGetCpuFeatures(&cpuFeatures, NULL);
1990         if(ippStatus < 0)
1991         {
1992             std::cerr << "ERROR: IPP cannot detect CPU features, IPP was disabled " << std::endl;
1993             useIPP = false;
1994             return;
1995         }
1996         ippFeatures = cpuFeatures;
1997
1998         const char* pIppEnv = getenv("OPENCV_IPP");
1999         cv::String env = pIppEnv;
2000         if(env.size())
2001         {
2002 #if IPP_VERSION_X100 >= 201703
2003             const Ipp64u minorFeatures = ippCPUID_MOVBE|ippCPUID_AES|ippCPUID_CLMUL|ippCPUID_ABR|ippCPUID_RDRAND|ippCPUID_F16C|
2004                 ippCPUID_ADCOX|ippCPUID_RDSEED|ippCPUID_PREFETCHW|ippCPUID_SHA|ippCPUID_MPX|ippCPUID_AVX512CD|ippCPUID_AVX512ER|
2005                 ippCPUID_AVX512PF|ippCPUID_AVX512BW|ippCPUID_AVX512DQ|ippCPUID_AVX512VL|ippCPUID_AVX512VBMI;
2006 #elif IPP_VERSION_X100 >= 201700
2007             const Ipp64u minorFeatures = ippCPUID_MOVBE|ippCPUID_AES|ippCPUID_CLMUL|ippCPUID_ABR|ippCPUID_RDRAND|ippCPUID_F16C|
2008                 ippCPUID_ADCOX|ippCPUID_RDSEED|ippCPUID_PREFETCHW|ippCPUID_SHA|ippCPUID_AVX512CD|ippCPUID_AVX512ER|
2009                 ippCPUID_AVX512PF|ippCPUID_AVX512BW|ippCPUID_AVX512DQ|ippCPUID_AVX512VL|ippCPUID_AVX512VBMI;
2010 #else
2011             const Ipp64u minorFeatures = 0;
2012 #endif
2013
2014             env = env.toLowerCase();
2015             if(env.substr(0, 2) == "ne")
2016             {
2017                 useIPP_NE = true;
2018                 env = env.substr(3, env.size());
2019             }
2020
2021             if(env == "disabled")
2022             {
2023                 std::cerr << "WARNING: IPP was disabled by OPENCV_IPP environment variable" << std::endl;
2024                 useIPP = false;
2025             }
2026             else if(env == "sse42")
2027                 ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42;
2028             else if(env == "avx2")
2029                 ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42|ippCPUID_AVX|ippCPUID_AVX2;
2030 #if IPP_VERSION_X100 >= 201700
2031 #if defined (_M_AMD64) || defined (__x86_64__)
2032             else if(env == "avx512")
2033                 ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42|ippCPUID_AVX|ippCPUID_AVX2|ippCPUID_AVX512F;
2034 #endif
2035 #endif
2036             else
2037                 std::cerr << "ERROR: Improper value of OPENCV_IPP: " << env.c_str() << ". Correct values are: disabled, sse42, avx2, avx512 (Intel64 only)" << std::endl;
2038
2039             // Trim unsupported features
2040             ippFeatures &= cpuFeatures;
2041         }
2042
2043         // Disable AVX1 since we don't track regressions for it. SSE42 will be used instead
2044         if(cpuFeatures&ippCPUID_AVX && !(cpuFeatures&ippCPUID_AVX2))
2045             ippFeatures &= ~((Ipp64u)ippCPUID_AVX);
2046
2047         // IPP integrations in OpenCV support only SSE4.2, AVX2 and AVX-512 optimizations.
2048         if(!(
2049 #if IPP_VERSION_X100 >= 201700
2050             cpuFeatures&ippCPUID_AVX512F ||
2051 #endif
2052             cpuFeatures&ippCPUID_AVX2 ||
2053             cpuFeatures&ippCPUID_SSE42
2054             ))
2055         {
2056             useIPP = false;
2057             return;
2058         }
2059
2060         if(ippFeatures == cpuFeatures)
2061             IPP_INITIALIZER(0)
2062         else
2063             IPP_INITIALIZER(ippFeatures)
2064         ippFeatures = ippGetEnabledCpuFeatures();
2065
2066         // Detect top level optimizations to make comparison easier for optimizations dependent conditions
2067 #if IPP_VERSION_X100 >= 201700
2068         if(ippFeatures&ippCPUID_AVX512F)
2069         {
2070             if((ippFeatures&ippCPUID_AVX512_SKX) == ippCPUID_AVX512_SKX)
2071                 ippTopFeatures = ippCPUID_AVX512_SKX;
2072             else if((ippFeatures&ippCPUID_AVX512_KNL) == ippCPUID_AVX512_KNL)
2073                 ippTopFeatures = ippCPUID_AVX512_KNL;
2074             else
2075                 ippTopFeatures = ippCPUID_AVX512F; // Unknown AVX512 configuration
2076         }
2077         else
2078 #endif
2079         if(ippFeatures&ippCPUID_AVX2)
2080             ippTopFeatures = ippCPUID_AVX2;
2081         else if(ippFeatures&ippCPUID_SSE42)
2082             ippTopFeatures = ippCPUID_SSE42;
2083
2084         pIppLibInfo = ippiGetLibVersion();
2085     }
2086
2087 public:
2088     bool        useIPP;
2089     bool        useIPP_NE;
2090
2091     int         ippStatus;  // 0 - all is ok, -1 - IPP functions failed
2092     const char *funcname;
2093     const char *filename;
2094     int         linen;
2095     Ipp64u      ippFeatures;
2096     Ipp64u      cpuFeatures;
2097     Ipp64u      ippTopFeatures;
2098     const IppLibraryVersion *pIppLibInfo;
2099 };
2100
2101 static IPPInitSingleton& getIPPSingleton()
2102 {
2103     CV_SINGLETON_LAZY_INIT_REF(IPPInitSingleton, new IPPInitSingleton())
2104 }
2105 #endif
2106
2107 #if OPENCV_ABI_COMPATIBILITY > 300
2108 unsigned long long getIppFeatures()
2109 #else
2110 int getIppFeatures()
2111 #endif
2112 {
2113 #ifdef HAVE_IPP
2114 #if OPENCV_ABI_COMPATIBILITY > 300
2115     return getIPPSingleton().ippFeatures;
2116 #else
2117     return (int)getIPPSingleton().ippFeatures;
2118 #endif
2119 #else
2120     return 0;
2121 #endif
2122 }
2123
2124 unsigned long long getIppTopFeatures();
2125
2126 unsigned long long getIppTopFeatures()
2127 {
2128 #ifdef HAVE_IPP
2129     return getIPPSingleton().ippTopFeatures;
2130 #else
2131     return 0;
2132 #endif
2133 }
2134
2135 void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line)
2136 {
2137 #ifdef HAVE_IPP
2138     getIPPSingleton().ippStatus = status;
2139     getIPPSingleton().funcname = _funcname;
2140     getIPPSingleton().filename = _filename;
2141     getIPPSingleton().linen = _line;
2142 #else
2143     CV_UNUSED(status); CV_UNUSED(_funcname); CV_UNUSED(_filename); CV_UNUSED(_line);
2144 #endif
2145 }
2146
2147 int getIppStatus()
2148 {
2149 #ifdef HAVE_IPP
2150     return getIPPSingleton().ippStatus;
2151 #else
2152     return 0;
2153 #endif
2154 }
2155
2156 String getIppErrorLocation()
2157 {
2158 #ifdef HAVE_IPP
2159     return format("%s:%d %s", getIPPSingleton().filename ? getIPPSingleton().filename : "", getIPPSingleton().linen, getIPPSingleton().funcname ? getIPPSingleton().funcname : "");
2160 #else
2161     return String();
2162 #endif
2163 }
2164
2165 String getIppVersion()
2166 {
2167 #ifdef HAVE_IPP
2168     const IppLibraryVersion *pInfo = getIPPSingleton().pIppLibInfo;
2169     if(pInfo)
2170         return format("%s %s %s", pInfo->Name, pInfo->Version, pInfo->BuildDate);
2171     else
2172         return String("error");
2173 #else
2174     return String("disabled");
2175 #endif
2176 }
2177
2178 bool useIPP()
2179 {
2180 #ifdef HAVE_IPP
2181     CoreTLSData* data = getCoreTlsData().get();
2182     if(data->useIPP < 0)
2183     {
2184         data->useIPP = getIPPSingleton().useIPP;
2185     }
2186     return (data->useIPP > 0);
2187 #else
2188     return false;
2189 #endif
2190 }
2191
2192 void setUseIPP(bool flag)
2193 {
2194     CoreTLSData* data = getCoreTlsData().get();
2195 #ifdef HAVE_IPP
2196     data->useIPP = (getIPPSingleton().useIPP)?flag:false;
2197 #else
2198     (void)flag;
2199     data->useIPP = false;
2200 #endif
2201 }
2202
2203 bool useIPP_NE()
2204 {
2205 #ifdef HAVE_IPP
2206     CoreTLSData* data = getCoreTlsData().get();
2207     if(data->useIPP_NE < 0)
2208     {
2209         data->useIPP_NE = getIPPSingleton().useIPP_NE;
2210     }
2211     return (data->useIPP_NE > 0);
2212 #else
2213     return false;
2214 #endif
2215 }
2216
2217 void setUseIPP_NE(bool flag)
2218 {
2219     CoreTLSData* data = getCoreTlsData().get();
2220 #ifdef HAVE_IPP
2221     data->useIPP_NE = (getIPPSingleton().useIPP_NE)?flag:false;
2222 #else
2223     (void)flag;
2224     data->useIPP_NE = false;
2225 #endif
2226 }
2227
2228 } // namespace ipp
2229
2230 } // namespace cv
2231
2232 #ifdef HAVE_TEGRA_OPTIMIZATION
2233
2234 namespace tegra {
2235
2236 bool useTegra()
2237 {
2238     cv::CoreTLSData* data = cv::getCoreTlsData().get();
2239
2240     if (data->useTegra < 0)
2241     {
2242         const char* pTegraEnv = getenv("OPENCV_TEGRA");
2243         if (pTegraEnv && (cv::String(pTegraEnv) == "disabled"))
2244             data->useTegra = false;
2245         else
2246             data->useTegra = true;
2247     }
2248
2249     return (data->useTegra > 0);
2250 }
2251
2252 void setUseTegra(bool flag)
2253 {
2254     cv::CoreTLSData* data = cv::getCoreTlsData().get();
2255     data->useTegra = flag;
2256 }
2257
2258 } // namespace tegra
2259
2260 #endif
2261
2262 /* End of file. */