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