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