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