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