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