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