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