system.cpp 64.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
I
Ilya Lavrenov 已提交
15
// Copyright (C) 2015, Itseez Inc., all rights reserved.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"
45
#include <iostream>
46

47
#include <opencv2/core/utils/configuration.private.hpp>
48 49
#include <opencv2/core/utils/trace.private.hpp>

50 51
#include <opencv2/core/utils/logger.hpp>

52 53 54 55 56 57 58 59 60 61 62 63
namespace cv {

static Mutex* __initialization_mutex = NULL;
Mutex& getInitializationMutex()
{
    if (__initialization_mutex == NULL)
        __initialization_mutex = new Mutex();
    return *__initialization_mutex;
}
// force initialization (single-threaded environment)
Mutex* __initialization_mutex_initializer = &getInitializationMutex();

A
Alexander Alekhin 已提交
64 65 66 67 68 69 70 71
static bool param_dumpErrors = utils::getConfigurationParameterBool("OPENCV_DUMP_ERRORS",
#if defined(_DEBUG) || defined(__ANDROID__) || (defined(__GNUC__) && !defined(__EXCEPTIONS))
    true
#else
    false
#endif
);

72 73
} // namespace cv

74 75 76 77 78 79 80 81 82
#ifndef CV_ERROR_SET_TERMINATE_HANDLER  // build config option
# if defined(_WIN32)
#   define CV_ERROR_SET_TERMINATE_HANDLER 1
# endif
#endif
#if CV_ERROR_SET_TERMINATE_HANDLER == 0
# undef CV_ERROR_SET_TERMINATE_HANDLER
#endif

83 84 85 86 87 88
#ifdef _MSC_VER
# if _MSC_VER >= 1700
#  pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
# endif
#endif

89 90 91 92 93
#ifdef CV_ERROR_SET_TERMINATE_HANDLER
#include <exception>      // std::set_terminate
#include <cstdlib>        // std::abort
#endif

Z
Zoltán Mizsei 已提交
94
#if defined __ANDROID__ || defined __linux__ || defined __FreeBSD__ || defined __HAIKU__
I
Ilya Lavrenov 已提交
95 96 97
#  include <unistd.h>
#  include <fcntl.h>
#  include <elf.h>
98
#if defined __ANDROID__ || defined __linux__
I
Ilya Lavrenov 已提交
99 100
#  include <linux/auxvec.h>
#endif
B
Bert 已提交
101
#endif
I
Ilya Lavrenov 已提交
102

103
#if defined __ANDROID__ && defined HAVE_CPUFEATURES
104 105 106
#  include <cpu-features.h>
#endif

S
Sayed Adel 已提交
107 108 109 110 111 112 113 114 115 116 117 118
#ifndef __VSX__
# if defined __PPC64__ && defined __linux__
#   include "sys/auxv.h"
#   ifndef AT_HWCAP2
#     define AT_HWCAP2 26
#   endif
#   ifndef PPC_FEATURE2_ARCH_2_07
#     define PPC_FEATURE2_ARCH_2_07 0x80000000
#   endif
# endif
#endif

119
#if defined _WIN32 || defined WINCE
120 121 122 123
#ifndef _WIN32_WINNT           // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?)
  #define _WIN32_WINNT 0x0400  // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx
#endif
#include <windows.h>
124
#if (_WIN32_WINNT >= 0x0602)
125
  #include <synchapi.h>
126
#endif
127 128 129 130
#undef small
#undef min
#undef max
#undef abs
131
#include <tchar.h>
132

133
#ifdef WINRT
134
#include <wrl/client.h>
G
GregoryMorse 已提交
135 136 137 138
#ifndef __cplusplus_winrt
#include <windows.storage.h>
#pragma comment(lib, "runtimeobject.lib")
#endif
139 140 141

std::wstring GetTempPathWinRT()
{
G
GregoryMorse 已提交
142
#ifdef __cplusplus_winrt
143
    return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data());
G
GregoryMorse 已提交
144 145 146 147 148 149 150 151 152 153 154
#else
    Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationDataStatics> appdataFactory;
    Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationData> appdataRef;
    Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFolder> storagefolderRef;
    Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageItem> storageitemRef;
    HSTRING str;
    HSTRING_HEADER hstrHead;
    std::wstring wstr;
    if (FAILED(WindowsCreateStringReference(RuntimeClass_Windows_Storage_ApplicationData,
                                            (UINT32)wcslen(RuntimeClass_Windows_Storage_ApplicationData), &hstrHead, &str)))
        return wstr;
G
GregoryMorse 已提交
155
    if (FAILED(RoGetActivationFactory(str, IID_PPV_ARGS(appdataFactory.ReleaseAndGetAddressOf()))))
G
GregoryMorse 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169
        return wstr;
    if (FAILED(appdataFactory->get_Current(appdataRef.ReleaseAndGetAddressOf())))
        return wstr;
    if (FAILED(appdataRef->get_TemporaryFolder(storagefolderRef.ReleaseAndGetAddressOf())))
        return wstr;
    if (FAILED(storagefolderRef.As(&storageitemRef)))
        return wstr;
    str = NULL;
    if (FAILED(storageitemRef->get_Path(&str)))
        return wstr;
    wstr = WindowsGetStringRawBuffer(str, NULL);
    WindowsDeleteString(str);
    return wstr;
#endif
170 171 172 173
}

std::wstring GetTempFileNameWinRT(std::wstring prefix)
{
174 175 176
    wchar_t guidStr[40];
    GUID g;
    CoCreateGuid(&g);
177
    wchar_t* mask = L"%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x";
178 179 180 181
    swprintf(&guidStr[0], sizeof(guidStr)/sizeof(wchar_t), mask,
             g.Data1, g.Data2, g.Data3, UINT(g.Data4[0]), UINT(g.Data4[1]),
             UINT(g.Data4[2]), UINT(g.Data4[3]), UINT(g.Data4[4]),
             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 188 189 190 191
#else
#include <pthread.h>
#include <sys/time.h>
#include <time.h>

192
#if defined __MACH__ && defined __APPLE__
193 194 195 196 197 198 199 200 201 202
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif

#endif

#ifdef _OPENMP
#include "omp.h"
#endif

203
#if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__ || defined __FreeBSD__ || defined __GLIBC__ || defined __HAIKU__
204 205
#include <unistd.h>
#include <stdio.h>
206
#include <sys/types.h>
207
#if defined __ANDROID__
A
Andrey Kamaev 已提交
208
#include <sys/sysconf.h>
209
#endif
A
Andrey Kamaev 已提交
210
#endif
211

212
#ifdef __ANDROID__
213 214 215
# include <android/log.h>
#endif

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
#ifdef DECLARE_CV_CPUID_X86
DECLARE_CV_CPUID_X86
#endif
#ifndef CV_CPUID_X86
  #if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
    #if _MSC_VER >= 1400  // MSVS 2005
      #include <intrin.h>  // __cpuidex()
      #define CV_CPUID_X86 __cpuidex
    #else
      #error "Required MSVS 2005+"
    #endif
  #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
    static void cv_cpuid(int* cpuid_data, int reg_eax, int reg_ecx)
    {
        int __eax = reg_eax, __ebx = 0, __ecx = reg_ecx, __edx = 0;
// tested with available compilers (-fPIC -O2 -m32/-m64): https://godbolt.org/
#if !defined(__PIC__) \
    || defined(__x86_64__) || __GNUC__ >= 5 \
    || defined(__clang__) || defined(__INTEL_COMPILER)
        __asm__("cpuid\n\t"
                : "+a" (__eax), "=b" (__ebx), "+c" (__ecx), "=d" (__edx)
        );
#elif defined(__i386__)  // ebx may be reserved as the PIC register
        __asm__("xchg{l}\t{%%}ebx, %1\n\t"
                "cpuid\n\t"
                "xchg{l}\t{%%}ebx, %1\n\t"
                : "+a" (__eax), "=&r" (__ebx), "+c" (__ecx), "=d" (__edx)
        );
#else
#error "Configuration error"
#endif
        cpuid_data[0] = __eax; cpuid_data[1] = __ebx; cpuid_data[2] = __ecx; cpuid_data[3] = __edx;
    }
    #define CV_CPUID_X86 cv_cpuid
  #endif
#endif


254 255 256
namespace cv
{

257 258
Exception::Exception() { code = 0; line = 0; }

259
Exception::Exception(int _code, const String& _err, const String& _func, const String& _file, int _line)
260 261 262 263 264 265 266 267 268
: code(_code), err(_err), func(_func), file(_file), line(_line)
{
    formatMessage();
}

Exception::~Exception() throw() {}

/*!
 \return the error description and the context as a text string.
269
 */
270 271 272 273
const char* Exception::what() const throw() { return msg.c_str(); }

void Exception::formatMessage()
{
A
Alexander Alekhin 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
    size_t pos = err.find('\n');
    bool multiline = pos != cv::String::npos;
    if (multiline)
    {
        std::stringstream ss;
        size_t prev_pos = 0;
        while (pos != cv::String::npos)
        {
           ss << "> " << err.substr(prev_pos, pos - prev_pos) << std::endl;
           prev_pos = pos + 1;
           pos = err.find('\n', prev_pos);
        }
        ss << "> " << err.substr(prev_pos);
        if (err[err.size() - 1] != '\n')
            ss << std::endl;
        err = ss.str();
    }
    if (func.size() > 0)
    {
        if (multiline)
            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());
        else
            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());
    }
298
    else
A
Alexander Alekhin 已提交
299 300 301
    {
        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");
    }
302
}
303

304 305 306 307 308 309 310 311 312 313 314 315
static const char* g_hwFeatureNames[CV_HARDWARE_MAX_FEATURE] = { NULL };

static const char* getHWFeatureName(int id)
{
    return (id < CV_HARDWARE_MAX_FEATURE) ? g_hwFeatureNames[id] : NULL;
}
static const char* getHWFeatureNameSafe(int id)
{
    const char* name = getHWFeatureName(id);
    return name ? name : "Unknown feature";
}

M
Maksim Shabunin 已提交
316 317 318 319
struct HWFeatures
{
    enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE };

320
    HWFeatures(bool run_initialize = false)
M
Maksim Shabunin 已提交
321
    {
322 323 324
        memset( have, 0, sizeof(have[0]) * MAX_FEATURE );
        if (run_initialize)
            initialize();
M
Maksim Shabunin 已提交
325 326
    }

327
    static void initializeNames()
M
Maksim Shabunin 已提交
328
    {
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
        for (int i = 0; i < CV_HARDWARE_MAX_FEATURE; i++)
        {
            g_hwFeatureNames[i] = 0;
        }
        g_hwFeatureNames[CPU_MMX] = "MMX";
        g_hwFeatureNames[CPU_SSE] = "SSE";
        g_hwFeatureNames[CPU_SSE2] = "SSE2";
        g_hwFeatureNames[CPU_SSE3] = "SSE3";
        g_hwFeatureNames[CPU_SSSE3] = "SSSE3";
        g_hwFeatureNames[CPU_SSE4_1] = "SSE4.1";
        g_hwFeatureNames[CPU_SSE4_2] = "SSE4.2";
        g_hwFeatureNames[CPU_POPCNT] = "POPCNT";
        g_hwFeatureNames[CPU_FP16] = "FP16";
        g_hwFeatureNames[CPU_AVX] = "AVX";
        g_hwFeatureNames[CPU_AVX2] = "AVX2";
        g_hwFeatureNames[CPU_FMA3] = "FMA3";

        g_hwFeatureNames[CPU_AVX_512F] = "AVX512F";
        g_hwFeatureNames[CPU_AVX_512BW] = "AVX512BW";
        g_hwFeatureNames[CPU_AVX_512CD] = "AVX512CD";
        g_hwFeatureNames[CPU_AVX_512DQ] = "AVX512DQ";
        g_hwFeatureNames[CPU_AVX_512ER] = "AVX512ER";
A
Alexander Alekhin 已提交
351
        g_hwFeatureNames[CPU_AVX_512IFMA] = "AVX512IFMA";
352 353 354 355 356
        g_hwFeatureNames[CPU_AVX_512PF] = "AVX512PF";
        g_hwFeatureNames[CPU_AVX_512VBMI] = "AVX512VBMI";
        g_hwFeatureNames[CPU_AVX_512VL] = "AVX512VL";

        g_hwFeatureNames[CPU_NEON] = "NEON";
S
Sayed Adel 已提交
357 358

        g_hwFeatureNames[CPU_VSX] = "VSX";
A
Alexander Alekhin 已提交
359 360

        g_hwFeatureNames[CPU_AVX512_SKX] = "AVX512-SKX";
361 362 363 364 365 366 367 368 369 370 371 372 373 374
    }

    void initialize(void)
    {
#ifndef WINRT
        if (getenv("OPENCV_DUMP_CONFIG"))
        {
            fprintf(stderr, "\nOpenCV build configuration is:\n%s\n",
                cv::getBuildInformation().c_str());
        }
#endif

        initializeNames();

375
    #ifdef CV_CPUID_X86
M
Maksim Shabunin 已提交
376
        int cpuid_data[4] = { 0, 0, 0, 0 };
377
        int cpuid_data_ex[4] = { 0, 0, 0, 0 };
M
Maksim Shabunin 已提交
378

379
        CV_CPUID_X86(cpuid_data, 1, 0/*unused*/);
M
Maksim Shabunin 已提交
380

381 382
        int x86_family = (cpuid_data[0] >> 8) & 15;
        if( x86_family >= 6 )
M
Maksim Shabunin 已提交
383
        {
384 385 386 387 388 389 390 391 392 393 394
            have[CV_CPU_MMX]    = (cpuid_data[3] & (1<<23)) != 0;
            have[CV_CPU_SSE]    = (cpuid_data[3] & (1<<25)) != 0;
            have[CV_CPU_SSE2]   = (cpuid_data[3] & (1<<26)) != 0;
            have[CV_CPU_SSE3]   = (cpuid_data[2] & (1<<0)) != 0;
            have[CV_CPU_SSSE3]  = (cpuid_data[2] & (1<<9)) != 0;
            have[CV_CPU_FMA3]   = (cpuid_data[2] & (1<<12)) != 0;
            have[CV_CPU_SSE4_1] = (cpuid_data[2] & (1<<19)) != 0;
            have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0;
            have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0;
            have[CV_CPU_AVX]    = (cpuid_data[2] & (1<<28)) != 0;
            have[CV_CPU_FP16]   = (cpuid_data[2] & (1<<29)) != 0;
M
Maksim Shabunin 已提交
395 396 397

            // make the second call to the cpuid command in order to get
            // information about extended features like AVX2
398
            CV_CPUID_X86(cpuid_data_ex, 7, 0);
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421

            have[CV_CPU_AVX2]   = (cpuid_data_ex[1] & (1<<5)) != 0;

            have[CV_CPU_AVX_512F]       = (cpuid_data_ex[1] & (1<<16)) != 0;
            have[CV_CPU_AVX_512DQ]      = (cpuid_data_ex[1] & (1<<17)) != 0;
            have[CV_CPU_AVX_512IFMA512] = (cpuid_data_ex[1] & (1<<21)) != 0;
            have[CV_CPU_AVX_512PF]      = (cpuid_data_ex[1] & (1<<26)) != 0;
            have[CV_CPU_AVX_512ER]      = (cpuid_data_ex[1] & (1<<27)) != 0;
            have[CV_CPU_AVX_512CD]      = (cpuid_data_ex[1] & (1<<28)) != 0;
            have[CV_CPU_AVX_512BW]      = (cpuid_data_ex[1] & (1<<30)) != 0;
            have[CV_CPU_AVX_512VL]      = (cpuid_data_ex[1] & (1<<31)) != 0;
            have[CV_CPU_AVX_512VBMI]    = (cpuid_data_ex[2] & (1<<1)) != 0;

            bool have_AVX_OS_support = true;
            bool have_AVX512_OS_support = true;
            if (!(cpuid_data[2] & (1<<27)))
                have_AVX_OS_support = false; // OS uses XSAVE_XRSTORE and CPU support AVX
            else
            {
                int xcr0 = 0;
            #ifdef _XCR_XFEATURE_ENABLED_MASK // requires immintrin.h
                xcr0 = (int)_xgetbv(_XCR_XFEATURE_ENABLED_MASK);
            #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
422
                __asm__ ("xgetbv\n\t" : "=a" (xcr0) : "c" (0) : "%edx" );
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
            #endif
                if ((xcr0 & 0x6) != 0x6)
                    have_AVX_OS_support = false; // YMM registers
                if ((xcr0 & 0xe6) != 0xe6)
                    have_AVX512_OS_support = false; // ZMM registers
            }

            if (!have_AVX_OS_support)
            {
                have[CV_CPU_AVX] = false;
                have[CV_CPU_FP16] = false;
                have[CV_CPU_AVX2] = false;
                have[CV_CPU_FMA3] = false;
            }
            if (!have_AVX_OS_support || !have_AVX512_OS_support)
            {
                have[CV_CPU_AVX_512F] = false;
                have[CV_CPU_AVX_512BW] = false;
                have[CV_CPU_AVX_512CD] = false;
                have[CV_CPU_AVX_512DQ] = false;
                have[CV_CPU_AVX_512ER] = false;
                have[CV_CPU_AVX_512IFMA512] = false;
                have[CV_CPU_AVX_512PF] = false;
                have[CV_CPU_AVX_512VBMI] = false;
                have[CV_CPU_AVX_512VL] = false;
            }
A
Alexander Alekhin 已提交
449 450 451 452 453

            if (have[CV_CPU_AVX_512F])
            {
                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];
            }
M
Maksim Shabunin 已提交
454
        }
455
    #endif // CV_CPUID_X86
M
Maksim Shabunin 已提交
456

457
    #if defined __ANDROID__ || defined __linux__
M
Maksim Shabunin 已提交
458
    #ifdef __aarch64__
459 460
        have[CV_CPU_NEON] = true;
        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 467
        have[CV_CPU_NEON] = (features & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
        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 473
        have[CV_CPU_NEON] = true;
        #else
474
        CV_LOG_INFO(NULL, "- NEON instructions is NOT enabled via build flags");
475 476
        #endif
        #if CV_FP16
477
        CV_LOG_INFO(NULL, "- FP16 instructions is enabled via build flags");
478 479
        have[CV_CPU_FP16] = true;
        #else
480
        CV_LOG_INFO(NULL, "- FP16 instructions is NOT enabled via build flags");
481 482
        #endif
      #endif
483
    #elif defined __arm__
M
Maksim Shabunin 已提交
484 485 486 487 488 489 490 491 492 493 494
        int cpufile = open("/proc/self/auxv", O_RDONLY);

        if (cpufile >= 0)
        {
            Elf32_auxv_t auxv;
            const size_t size_auxv_t = sizeof(auxv);

            while ((size_t)read(cpufile, &auxv, size_auxv_t) == size_auxv_t)
            {
                if (auxv.a_type == AT_HWCAP)
                {
495 496
                    have[CV_CPU_NEON] = (auxv.a_un.a_val & 4096) != 0;
                    have[CV_CPU_FP16] = (auxv.a_un.a_val & 2) != 0;
M
Maksim Shabunin 已提交
497 498 499 500 501 502 503
                    break;
                }
            }

            close(cpufile);
        }
    #endif
504 505
    #elif (defined __clang__ || defined __APPLE__)
    #if (defined __ARM_NEON__ || (defined __ARM_NEON && defined __aarch64__))
506
        have[CV_CPU_NEON] = true;
507 508
    #endif
    #if (defined __ARM_FP  && (((__ARM_FP & 0x2) != 0) && defined __ARM_NEON__))
509
        have[CV_CPU_FP16] = true;
510
    #endif
M
Maksim Shabunin 已提交
511 512
    #endif

S
Sayed Adel 已提交
513 514 515 516 517 518 519 520 521 522
    #ifdef __VSX__
        have[CV_CPU_VSX] = true;
    #elif (defined __PPC64__ && defined __linux__)
        uint64 hwcaps = getauxval(AT_HWCAP);
        uint64 hwcap2 = getauxval(AT_HWCAP2);
        have[CV_CPU_VSX] = (hwcaps & PPC_FEATURE_PPC_LE && hwcaps & PPC_FEATURE_HAS_VSX && hwcap2 & PPC_FEATURE2_ARCH_2_07);
    #else
        have[CV_CPU_VSX] = false;
    #endif

523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
        int baseline_features[] = { CV_CPU_BASELINE_FEATURES };
        if (!checkFeatures(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0])))
        {
            fprintf(stderr, "\n"
                    "******************************************************************\n"
                    "* FATAL ERROR:                                                   *\n"
                    "* This OpenCV build doesn't support current CPU/HW configuration *\n"
                    "*                                                                *\n"
                    "* Use OPENCV_DUMP_CONFIG=1 environment variable for details      *\n"
                    "******************************************************************\n");
            fprintf(stderr, "\nRequired baseline features:\n");
            checkFeatures(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0]), true);
            CV_ErrorNoReturn(cv::Error::StsAssert, "Missing support for required CPU baseline features. Check OpenCV build configuration and required CPU/HW setup.");
        }

        readSettings(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0]));
    }

    bool checkFeatures(const int* features, int count, bool dump = false)
    {
        bool result = true;
        for (int i = 0; i < count; i++)
        {
            int feature = features[i];
            if (feature)
            {
                if (have[feature])
                {
                    if (dump) fprintf(stderr, "%s - OK\n", getHWFeatureNameSafe(feature));
                }
                else
                {
                    result = false;
                    if (dump) fprintf(stderr, "%s - NOT AVAILABLE\n", getHWFeatureNameSafe(feature));
                }
            }
        }
        return result;
    }

    static inline bool isSymbolSeparator(char c)
    {
565
        return c == ',' || c == ';';
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
    }

    void readSettings(const int* baseline_features, int baseline_count)
    {
        bool dump = true;
        const char* disabled_features =
#ifndef WINRT
                getenv("OPENCV_CPU_DISABLE");
#else
                NULL;
#endif
        if (disabled_features && disabled_features[0] != 0)
        {
            const char* start = disabled_features;
            for (;;)
            {
                while (start[0] != 0 && isSymbolSeparator(start[0]))
                {
                    start++;
                }
                if (start[0] == 0)
                    break;
                const char* end = start;
                while (end[0] != 0 && !isSymbolSeparator(end[0]))
                {
                    end++;
                }
                if (end == start)
                    continue;
                cv::String feature(start, end);
                start = end;

                CV_Assert(feature.size() > 0);

                bool found = false;
                for (int i = 0; i < CV_HARDWARE_MAX_FEATURE; i++)
                {
                    if (!g_hwFeatureNames[i]) continue;
                    size_t len = strlen(g_hwFeatureNames[i]);
                    if (len != feature.size()) continue;
                    if (feature.compare(g_hwFeatureNames[i]) == 0)
                    {
                        bool isBaseline = false;
                        for (int k = 0; k < baseline_count; k++)
                        {
                            if (baseline_features[k] == i)
                            {
                                isBaseline = true;
                                break;
                            }
                        }
                        if (isBaseline)
                        {
                            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));
                        }
                        if (!have[i])
                        {
                            if (dump) fprintf(stderr, "OPENCV: Trying to disable unavailable CPU feature on the current platform: '%s'.\n", getHWFeatureNameSafe(i));
                        }
                        have[i] = false;

                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    if (dump) fprintf(stderr, "OPENCV: Trying to disable unknown CPU feature: '%s'.\n", feature.c_str());
                }
            }
        }
M
Maksim Shabunin 已提交
637 638 639 640 641
    }

    bool have[MAX_FEATURE+1];
};

642
static HWFeatures  featuresEnabled(true), featuresDisabled = HWFeatures(false);
M
Maksim Shabunin 已提交
643 644
static HWFeatures* currentFeatures = &featuresEnabled;

645 646 647
bool checkHardwareSupport(int feature)
{
    CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
M
Maksim Shabunin 已提交
648
    return currentFeatures->have[feature];
649 650
}

651 652 653 654 655
String getHardwareFeatureName(int feature)
{
    const char* name = getHWFeatureName(feature);
    return name ? String(name) : String();
}
M
Maksim Shabunin 已提交
656 657 658

volatile bool useOptimizedFlag = true;

659 660
void setUseOptimized( bool flag )
{
M
Maksim Shabunin 已提交
661 662
    useOptimizedFlag = flag;
    currentFeatures = flag ? &featuresEnabled : &featuresDisabled;
663 664

    ipp::setUseIPP(flag);
665
#ifdef HAVE_OPENCL
666
    ocl::setUseOpenCL(flag);
667
#endif
668 669 670
#ifdef HAVE_TEGRA_OPTIMIZATION
    ::tegra::setUseTegra(flag);
#endif
671 672
}

673
bool useOptimized(void)
674
{
M
Maksim Shabunin 已提交
675
    return useOptimizedFlag;
676
}
677 678

int64 getTickCount(void)
679
{
680
#if defined _WIN32 || defined WINCE
681 682 683 684 685 686 687
    LARGE_INTEGER counter;
    QueryPerformanceCounter( &counter );
    return (int64)counter.QuadPart;
#elif defined __linux || defined __linux__
    struct timespec tp;
    clock_gettime(CLOCK_MONOTONIC, &tp);
    return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
688
#elif defined __MACH__ && defined __APPLE__
689
    return (int64)mach_absolute_time();
690
#else
691 692 693 694 695 696 697
    struct timeval tv;
    struct timezone tz;
    gettimeofday( &tv, &tz );
    return (int64)tv.tv_sec*1000000 + tv.tv_usec;
#endif
}

698
double getTickFrequency(void)
699
{
700
#if defined _WIN32 || defined WINCE
701 702 703 704 705
    LARGE_INTEGER freq;
    QueryPerformanceFrequency(&freq);
    return (double)freq.QuadPart;
#elif defined __linux || defined __linux__
    return 1e9;
706
#elif defined __MACH__ && defined __APPLE__
707 708 709 710 711 712 713
    static double freq = 0;
    if( freq == 0 )
    {
        mach_timebase_info_data_t sTimebaseInfo;
        mach_timebase_info(&sTimebaseInfo);
        freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
    }
714
    return freq;
715 716 717 718 719
#else
    return 1e6;
#endif
}

720
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
#if defined(__i386__)

int64 getCPUTickCount(void)
{
    int64 x;
    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
    return x;
}
#elif defined(__x86_64__)

int64 getCPUTickCount(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return (int64)lo | ((int64)hi << 32);
}

#elif defined(__ppc__)

int64 getCPUTickCount(void)
{
742
    int64 result = 0;
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
    unsigned upper, lower, tmp;
    __asm__ volatile(
                     "0:                  \n"
                     "\tmftbu   %0           \n"
                     "\tmftb    %1           \n"
                     "\tmftbu   %2           \n"
                     "\tcmpw    %2,%0        \n"
                     "\tbne     0b         \n"
                     : "=r"(upper),"=r"(lower),"=r"(tmp)
                     );
    return lower | ((int64)upper << 32);
}

#else

#error "RDTSC not defined"

#endif

762
#elif defined _MSC_VER && defined _WIN32 && defined _M_IX86
763 764 765 766 767 768 769 770 771

int64 getCPUTickCount(void)
{
    __asm _emit 0x0f;
    __asm _emit 0x31;
}

#else

V
vbystricky 已提交
772 773 774 775 776 777
//#ifdef HAVE_IPP
//int64 getCPUTickCount(void)
//{
//    return ippGetCpuClocks();
//}
//#else
778
int64 getCPUTickCount(void)
779 780 781
{
    return getTickCount();
}
V
vbystricky 已提交
782
//#endif
783 784 785

#endif

786
const String& getBuildInformation()
787
{
788
    static String build_info =
789 790 791 792 793
#include "version_string.inc"
    ;
    return build_info;
}

794 795 796 797 798 799 800 801
String getVersionString() { return String(CV_VERSION); }

int getVersionMajor() { return CV_VERSION_MAJOR; }

int getVersionMinor() { return CV_VERSION_MINOR; }

int getVersionRevision() { return CV_VERSION_REVISION; }

802
String format( const char* fmt, ... )
803
{
I
Ilya Lavrenov 已提交
804
    AutoBuffer<char, 1024> buf;
805

I
Ilya Lavrenov 已提交
806
    for ( ; ; )
807
    {
I
Ilya Lavrenov 已提交
808
        va_list va;
809
        va_start(va, fmt);
A
Alexander Alekhin 已提交
810
        int bsize = static_cast<int>(buf.size());
811
        int len = cv_vsnprintf((char *)buf, bsize, fmt, va);
812 813
        va_end(va);

814 815
        CV_Assert(len >= 0 && "Check format string for errors");
        if (len >= bsize)
I
Ilya Lavrenov 已提交
816
        {
817
            buf.resize(len + 1);
I
Ilya Lavrenov 已提交
818 819
            continue;
        }
A
Alexander Alekhin 已提交
820
        buf[bsize - 1] = 0;
I
Ilya Lavrenov 已提交
821 822
        return String((char *)buf, len);
    }
823 824
}

825
String tempfile( const char* suffix )
826
{
827
    String fname;
828
#ifndef WINRT
G
GregoryMorse 已提交
829
    const char *temp_dir = getenv("OPENCV_TEMP_PATH");
830
#endif
831

832
#if defined _WIN32
833
#ifdef WINRT
834
    RoInitialize(RO_INIT_MULTITHREADED);
835
    std::wstring temp_dir = GetTempPathWinRT();
836

837
    std::wstring temp_file = GetTempFileNameWinRT(L"ocv");
838
    if (temp_file.empty())
G
GregoryMorse 已提交
839
        return String();
840

841
    temp_file = temp_dir.append(std::wstring(L"\\")).append(temp_file);
842 843
    DeleteFileW(temp_file.c_str());

844 845 846
    char aname[MAX_PATH];
    size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH);
    CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
G
GregoryMorse 已提交
847
    fname = String(aname);
848 849
    RoUninitialize();
#else
850 851
    char temp_dir2[MAX_PATH] = { 0 };
    char temp_file[MAX_PATH] = { 0 };
852

853 854 855 856 857
    if (temp_dir == 0 || temp_dir[0] == 0)
    {
        ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
        temp_dir = temp_dir2;
    }
858
    if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
859
        return String();
860

R
Roy Reapor 已提交
861 862
    DeleteFileA(temp_file);

863
    fname = temp_file;
864
#endif
865
# else
866
#  ifdef __ANDROID__
867 868 869 870 871 872
    //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
    char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
#  else
    char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
#  endif

873
    if (temp_dir == 0 || temp_dir[0] == 0)
874 875 876 877 878 879
        fname = defaultTemplate;
    else
    {
        fname = temp_dir;
        char ech = fname[fname.size() - 1];
        if(ech != '/' && ech != '\\')
880 881
            fname = fname + "/";
        fname = fname + "__opencv_temp.XXXXXX";
882 883 884
    }

    const int fd = mkstemp((char*)fname.c_str());
885
    if (fd == -1) return String();
886

887 888
    close(fd);
    remove(fname.c_str());
889
# endif
890

891
    if (suffix)
892 893
    {
        if (suffix[0] != '.')
894
            return fname + "." + suffix;
895
        else
896
            return fname + suffix;
897 898
    }
    return fname;
899 900
}

901
static ErrorCallback customErrorCallback = 0;
902 903 904 905 906 907 908 909
static void* customErrorCallbackData = 0;
static bool breakOnError = false;

bool setBreakOnError(bool value)
{
    bool prevVal = breakOnError;
    breakOnError = value;
    return prevVal;
910
}
911

912
int cv_snprintf(char* buf, int len, const char* fmt, ...)
A
Alexander Alekhin 已提交
913 914 915
{
    va_list va;
    va_start(va, fmt);
916
    int res = cv_vsnprintf(buf, len, fmt, va);
A
Alexander Alekhin 已提交
917
    va_end(va);
918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
    return res;
}

int cv_vsnprintf(char* buf, int len, const char* fmt, va_list args)
{
#if defined _MSC_VER
    if (len <= 0) return len == 0 ? 1024 : -1;
    int res = _vsnprintf_s(buf, len, _TRUNCATE, fmt, args);
    // ensure null terminating on VS
    if (res >= 0 && res < len)
    {
        buf[res] = 0;
        return res;
    }
    else
    {
        buf[len - 1] = 0; // truncate happened
        return res >= len ? res : (len * 2);
    }
A
Alexander Alekhin 已提交
937
#else
938
    return vsnprintf(buf, len, fmt, args);
A
Alexander Alekhin 已提交
939 940 941
#endif
}

942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
static void dumpException(const Exception& exc)
{
    const char* errorStr = cvErrorStr(exc.code);
    char buf[1 << 12];

    cv_snprintf(buf, sizeof(buf),
        "OpenCV(%s) Error: %s (%s) in %s, file %s, line %d",
        CV_VERSION,
        errorStr, exc.err.c_str(), exc.func.size() > 0 ?
        exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line);
#ifdef __ANDROID__
    __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
#else
    fflush(stdout); fflush(stderr);
    fprintf(stderr, "%s\n", buf);
    fflush(stderr);
#endif
}

#ifdef CV_ERROR_SET_TERMINATE_HANDLER
static bool cv_terminate_handler_installed = false;
static std::terminate_handler cv_old_terminate_handler;
static cv::Exception cv_terminate_handler_exception;
static bool param_setupTerminateHandler = utils::getConfigurationParameterBool("OPENCV_SETUP_TERMINATE_HANDLER", true);
static void cv_terminate_handler() {
    std::cerr << "OpenCV: terminate handler is called! The last OpenCV error is:\n";
    dumpException(cv_terminate_handler_exception);
    if (false /*cv_old_terminate_handler*/)  // buggy behavior is observed with doubled "abort/retry/ignore" windows
        cv_old_terminate_handler();
    abort();
}

#endif

976 977
void error( const Exception& exc )
{
978 979 980 981 982 983 984 985 986 987 988 989 990
#ifdef CV_ERROR_SET_TERMINATE_HANDLER
    {
        cv::AutoLock lock(getInitializationMutex());
        if (!cv_terminate_handler_installed)
        {
            if (param_setupTerminateHandler)
                cv_old_terminate_handler = std::set_terminate(cv_terminate_handler);
            cv_terminate_handler_installed = true;
        }
        cv_terminate_handler_exception = exc;
    }
#endif

991
    if (customErrorCallback != 0)
992 993
        customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
                            exc.file.c_str(), exc.line, customErrorCallbackData);
A
Alexander Alekhin 已提交
994
    else if (param_dumpErrors)
995
    {
996
        dumpException(exc);
997
    }
998

999 1000 1001 1002 1003
    if(breakOnError)
    {
        static volatile int* p = 0;
        *p = 0;
    }
1004

M
Maksim Shabunin 已提交
1005
    CV_THROW(exc);
1006
}
1007

1008 1009 1010 1011 1012
void error(int _code, const String& _err, const char* _func, const char* _file, int _line)
{
    error(cv::Exception(_code, _err, _func, _file, _line));
}

A
Alexander Alekhin 已提交
1013

1014 1015
ErrorCallback
redirectError( ErrorCallback errCallback, void* userdata, void** prevUserdata)
1016 1017 1018
{
    if( prevUserdata )
        *prevUserdata = customErrorCallbackData;
1019

1020
    ErrorCallback prevCallback = customErrorCallback;
1021 1022

    customErrorCallback     = errCallback;
1023
    customErrorCallbackData = userdata;
1024

1025 1026
    return prevCallback;
}
1027

1028 1029 1030 1031 1032
}

CV_IMPL int cvCheckHardwareSupport(int feature)
{
    CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
M
Maksim Shabunin 已提交
1033
    return cv::currentFeatures->have[feature];
1034 1035 1036 1037
}

CV_IMPL int cvUseOptimized( int flag )
{
M
Maksim Shabunin 已提交
1038
    int prevMode = cv::useOptimizedFlag;
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
    cv::setUseOptimized( flag != 0 );
    return prevMode;
}

CV_IMPL int64  cvGetTickCount(void)
{
    return cv::getTickCount();
}

CV_IMPL double cvGetTickFrequency(void)
{
    return cv::getTickFrequency()*1e-6;
}

CV_IMPL CvErrorCallback
cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
{
    return cv::redirectError(errCallback, userdata, prevUserdata);
}

CV_IMPL int cvNulDevReport( int, const char*, const char*,
                            const char*, int, void* )
{
    return 0;
}

CV_IMPL int cvStdErrReport( int, const char*, const char*,
                            const char*, int, void* )
{
    return 0;
}

CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
                            const char*, int, void* )
{
    return 0;
}

CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
{
    return 0;
}


CV_IMPL const char* cvErrorStr( int status )
{
    static char buf[256];

    switch (status)
    {
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
    case CV_StsOk :                  return "No Error";
    case CV_StsBackTrace :           return "Backtrace";
    case CV_StsError :               return "Unspecified error";
    case CV_StsInternal :            return "Internal error";
    case CV_StsNoMem :               return "Insufficient memory";
    case CV_StsBadArg :              return "Bad argument";
    case CV_StsNoConv :              return "Iterations do not converge";
    case CV_StsAutoTrace :           return "Autotrace call";
    case CV_StsBadSize :             return "Incorrect size of input array";
    case CV_StsNullPtr :             return "Null pointer";
1099
    case CV_StsDivByZero :           return "Division by zero occurred";
1100
    case CV_BadStep :                return "Image step is wrong";
1101 1102
    case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
    case CV_StsObjectNotFound :      return "Requested object was not found";
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
    case CV_BadDepth :               return "Input image depth is not supported by function";
    case CV_StsUnmatchedFormats :    return "Formats of input arguments do not match";
    case CV_StsUnmatchedSizes :      return "Sizes of input arguments do not match";
    case CV_StsOutOfRange :          return "One of arguments\' values is out of range";
    case CV_StsUnsupportedFormat :   return "Unsupported format or combination of formats";
    case CV_BadCOI :                 return "Input COI is not supported";
    case CV_BadNumChannels :         return "Bad number of channels";
    case CV_StsBadFlag :             return "Bad flag (parameter or structure field)";
    case CV_StsBadPoint :            return "Bad parameter of type CvPoint";
    case CV_StsBadMask :             return "Bad type of mask argument";
    case CV_StsParseError :          return "Parsing error";
    case CV_StsNotImplemented :      return "The function/feature is not implemented";
    case CV_StsBadMemBlock :         return "Memory block has been corrupted";
    case CV_StsAssert :              return "Assertion failed";
V
Vladislav Vinogradov 已提交
1117
    case CV_GpuNotSupported :        return "No CUDA support";
1118 1119 1120
    case CV_GpuApiCallError :        return "Gpu API call";
    case CV_OpenGlNotSupported :     return "No OpenGL support";
    case CV_OpenGlApiCallError :     return "OpenGL API call";
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
    };

    sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
    return buf;
}

CV_IMPL int cvGetErrMode(void)
{
    return 0;
}

CV_IMPL int cvSetErrMode(int)
{
    return 0;
}

1137
CV_IMPL int cvGetErrStatus(void)
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
{
    return 0;
}

CV_IMPL void cvSetErrStatus(int)
{
}


CV_IMPL void cvError( int code, const char* func_name,
                      const char* err_msg,
                      const char* file_name, int line )
{
    cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
}

/* function, which converts int to int */
CV_IMPL int
cvErrorFromIppStatus( int status )
{
    switch (status)
    {
1160 1161 1162 1163 1164 1165 1166 1167
    case CV_BADSIZE_ERR:               return CV_StsBadSize;
    case CV_BADMEMBLOCK_ERR:           return CV_StsBadMemBlock;
    case CV_NULLPTR_ERR:               return CV_StsNullPtr;
    case CV_DIV_BY_ZERO_ERR:           return CV_StsDivByZero;
    case CV_BADSTEP_ERR:               return CV_BadStep;
    case CV_OUTOFMEM_ERR:              return CV_StsNoMem;
    case CV_BADARG_ERR:                return CV_StsBadArg;
    case CV_NOTDEFINED_ERR:            return CV_StsError;
1168
    case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
    case CV_NOTFOUND_ERR:              return CV_StsObjectNotFound;
    case CV_BADCONVERGENCE_ERR:        return CV_StsNoConv;
    case CV_BADDEPTH_ERR:              return CV_BadDepth;
    case CV_UNMATCHED_FORMATS_ERR:     return CV_StsUnmatchedFormats;
    case CV_UNSUPPORTED_COI_ERR:       return CV_BadCOI;
    case CV_UNSUPPORTED_CHANNELS_ERR:  return CV_BadNumChannels;
    case CV_BADFLAG_ERR:               return CV_StsBadFlag;
    case CV_BADRANGE_ERR:              return CV_StsBadArg;
    case CV_BADCOEF_ERR:               return CV_StsBadArg;
    case CV_BADFACTOR_ERR:             return CV_StsBadArg;
    case CV_BADPOINT_ERR:              return CV_StsBadPoint;

    default:
      return CV_StsError;
1183 1184 1185
    }
}

1186 1187 1188
namespace cv {
bool __termination = false;
}
1189

1190 1191 1192
namespace cv
{

1193
#if defined _WIN32 || defined WINCE
1194 1195 1196

struct Mutex::Impl
{
1197 1198 1199 1200 1201 1202 1203 1204 1205
    Impl()
    {
#if (_WIN32_WINNT >= 0x0600)
        ::InitializeCriticalSectionEx(&cs, 1000, 0);
#else
        ::InitializeCriticalSection(&cs);
#endif
        refcount = 1;
    }
1206
    ~Impl() { DeleteCriticalSection(&cs); }
1207

1208 1209 1210
    void lock() { EnterCriticalSection(&cs); }
    bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
    void unlock() { LeaveCriticalSection(&cs); }
1211

1212 1213 1214
    CRITICAL_SECTION cs;
    int refcount;
};
1215

1216 1217 1218 1219
#else

struct Mutex::Impl
{
I
Ilya Lavrenov 已提交
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
    Impl()
    {
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&mt, &attr);
        pthread_mutexattr_destroy(&attr);

        refcount = 1;
    }
    ~Impl() { pthread_mutex_destroy(&mt); }
1231

I
Ilya Lavrenov 已提交
1232 1233 1234
    void lock() { pthread_mutex_lock(&mt); }
    bool trylock() { return pthread_mutex_trylock(&mt) == 0; }
    void unlock() { pthread_mutex_unlock(&mt); }
1235

I
Ilya Lavrenov 已提交
1236
    pthread_mutex_t mt;
1237 1238 1239 1240 1241 1242 1243 1244 1245
    int refcount;
};

#endif

Mutex::Mutex()
{
    impl = new Mutex::Impl;
}
1246

1247 1248 1249 1250 1251 1252
Mutex::~Mutex()
{
    if( CV_XADD(&impl->refcount, -1) == 1 )
        delete impl;
    impl = 0;
}
1253

1254 1255 1256 1257 1258 1259 1260 1261
Mutex::Mutex(const Mutex& m)
{
    impl = m.impl;
    CV_XADD(&impl->refcount, 1);
}

Mutex& Mutex::operator = (const Mutex& m)
{
1262 1263 1264 1265 1266 1267 1268
    if (this != &m)
    {
        CV_XADD(&m.impl->refcount, 1);
        if( CV_XADD(&impl->refcount, -1) == 1 )
            delete impl;
        impl = m.impl;
    }
1269 1270
    return *this;
}
1271

1272 1273
void Mutex::lock() { impl->lock(); }
void Mutex::unlock() { impl->unlock(); }
1274
bool Mutex::trylock() { return impl->trylock(); }
1275

A
Alexander Alekhin 已提交
1276 1277 1278

//////////////////////////////// thread-local storage ////////////////////////////////

1279
#ifdef _WIN32
P
Pavel Vlasov 已提交
1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
#ifdef _MSC_VER
#pragma warning(disable:4505) // unreferenced local function has been removed
#endif
#ifndef TLS_OUT_OF_INDEXES
#define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
#endif
#endif

// TLS platform abstraction layer
class TlsAbstraction
A
Alexander Alekhin 已提交
1290 1291
{
public:
P
Pavel Vlasov 已提交
1292 1293 1294 1295
    TlsAbstraction();
    ~TlsAbstraction();
    void* GetData() const;
    void  SetData(void *pData);
A
Alexander Alekhin 已提交
1296

P
Pavel Vlasov 已提交
1297
private:
1298
#ifdef _WIN32
P
Pavel Vlasov 已提交
1299 1300
#ifndef WINRT
    DWORD tlsKey;
A
Alexander Alekhin 已提交
1301
#endif
1302
#else // _WIN32
P
Pavel Vlasov 已提交
1303 1304 1305
    pthread_key_t  tlsKey;
#endif
};
A
Alexander Alekhin 已提交
1306

1307
#ifdef _WIN32
1308
#ifdef WINRT
P
Pavel Vlasov 已提交
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
static __declspec( thread ) void* tlsData = NULL; // using C++11 thread attribute for local thread data
TlsAbstraction::TlsAbstraction() {}
TlsAbstraction::~TlsAbstraction() {}
void* TlsAbstraction::GetData() const
{
    return tlsData;
}
void  TlsAbstraction::SetData(void *pData)
{
    tlsData = pData;
}
#else //WINRT
TlsAbstraction::TlsAbstraction()
{
    tlsKey = TlsAlloc();
    CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
}
TlsAbstraction::~TlsAbstraction()
{
    TlsFree(tlsKey);
}
void* TlsAbstraction::GetData() const
{
    return TlsGetValue(tlsKey);
}
void  TlsAbstraction::SetData(void *pData)
{
    CV_Assert(TlsSetValue(tlsKey, pData) == TRUE);
}
#endif
1339
#else // _WIN32
P
Pavel Vlasov 已提交
1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
TlsAbstraction::TlsAbstraction()
{
    CV_Assert(pthread_key_create(&tlsKey, NULL) == 0);
}
TlsAbstraction::~TlsAbstraction()
{
    CV_Assert(pthread_key_delete(tlsKey) == 0);
}
void* TlsAbstraction::GetData() const
{
    return pthread_getspecific(tlsKey);
}
void  TlsAbstraction::SetData(void *pData)
{
    CV_Assert(pthread_setspecific(tlsKey, pData) == 0);
}
#endif
A
Alexander Alekhin 已提交
1357

P
Pavel Vlasov 已提交
1358 1359 1360 1361
// Per-thread data structure
struct ThreadData
{
    ThreadData()
A
Alexander Alekhin 已提交
1362
    {
P
Pavel Vlasov 已提交
1363 1364
        idx = 0;
        slots.reserve(32);
A
Alexander Alekhin 已提交
1365 1366
    }

P
Pavel Vlasov 已提交
1367 1368 1369
    std::vector<void*> slots; // Data array for a thread
    size_t idx;               // Thread index in TLS storage. This is not OS thread ID!
};
A
Alexander Alekhin 已提交
1370

P
Pavel Vlasov 已提交
1371 1372 1373 1374
// Main TLS storage class
class TlsStorage
{
public:
1375 1376
    TlsStorage() :
        tlsSlotsSize(0)
A
Alexander Alekhin 已提交
1377
    {
P
Pavel Vlasov 已提交
1378
        tlsSlots.reserve(32);
P
Pavel Vlasov 已提交
1379
        threads.reserve(32);
A
Alexander Alekhin 已提交
1380
    }
P
Pavel Vlasov 已提交
1381
    ~TlsStorage()
A
Alexander Alekhin 已提交
1382
    {
P
Pavel Vlasov 已提交
1383
        for(size_t i = 0; i < threads.size(); i++)
A
Alexander Alekhin 已提交
1384
        {
P
Pavel Vlasov 已提交
1385 1386
            if(threads[i])
            {
1387
                /* Current architecture doesn't allow proper global objects release, so this check can cause crashes
P
Pavel Vlasov 已提交
1388 1389 1390 1391 1392 1393 1394 1395 1396

                // Check if all slots were properly cleared
                for(size_t j = 0; j < threads[i]->slots.size(); j++)
                {
                    CV_Assert(threads[i]->slots[j] == 0);
                }
                */
                delete threads[i];
            }
A
Alexander Alekhin 已提交
1397
        }
P
Pavel Vlasov 已提交
1398
        threads.clear();
A
Alexander Alekhin 已提交
1399 1400
    }

P
Pavel Vlasov 已提交
1401
    void releaseThread()
A
Alexander Alekhin 已提交
1402
    {
P
Pavel Vlasov 已提交
1403 1404 1405
        AutoLock guard(mtxGlobalAccess);
        ThreadData *pTD = (ThreadData*)tls.GetData();
        for(size_t i = 0; i < threads.size(); i++)
1406
        {
P
Pavel Vlasov 已提交
1407 1408 1409 1410 1411
            if(pTD == threads[i])
            {
                threads[i] = 0;
                break;
            }
1412
        }
P
Pavel Vlasov 已提交
1413 1414
        tls.SetData(0);
        delete pTD;
A
Alexander Alekhin 已提交
1415 1416
    }

P
Pavel Vlasov 已提交
1417 1418
    // Reserve TLS storage index
    size_t reserveSlot()
A
Alexander Alekhin 已提交
1419
    {
P
Pavel Vlasov 已提交
1420
        AutoLock guard(mtxGlobalAccess);
1421
        CV_Assert(tlsSlotsSize == tlsSlots.size());
P
Pavel Vlasov 已提交
1422 1423

        // Find unused slots
1424
        for(size_t slot = 0; slot < tlsSlotsSize; slot++)
P
Pavel Vlasov 已提交
1425 1426 1427 1428 1429 1430 1431 1432 1433
        {
            if(!tlsSlots[slot])
            {
                tlsSlots[slot] = 1;
                return slot;
            }
        }

        // Create new slot
1434 1435
        tlsSlots.push_back(1); tlsSlotsSize++;
        return tlsSlotsSize - 1;
A
Alexander Alekhin 已提交
1436 1437
    }

1438
    // Release TLS storage index and pass associated data to caller
1439
    void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec, bool keepSlot = false)
A
Alexander Alekhin 已提交
1440
    {
P
Pavel Vlasov 已提交
1441
        AutoLock guard(mtxGlobalAccess);
1442 1443
        CV_Assert(tlsSlotsSize == tlsSlots.size());
        CV_Assert(tlsSlotsSize > slotIdx);
A
Alexander Alekhin 已提交
1444

P
Pavel Vlasov 已提交
1445
        for(size_t i = 0; i < threads.size(); i++)
A
Alexander Alekhin 已提交
1446
        {
1447
            if(threads[i])
P
Pavel Vlasov 已提交
1448
            {
1449 1450 1451 1452
                std::vector<void*>& thread_slots = threads[i]->slots;
                if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
                {
                    dataVec.push_back(thread_slots[slotIdx]);
1453
                    thread_slots[slotIdx] = NULL;
1454
                }
P
Pavel Vlasov 已提交
1455
            }
A
Alexander Alekhin 已提交
1456
        }
P
Pavel Vlasov 已提交
1457

1458 1459
        if (!keepSlot)
            tlsSlots[slotIdx] = 0;
A
Alexander Alekhin 已提交
1460 1461
    }

P
Pavel Vlasov 已提交
1462 1463
    // Get data by TLS storage index
    void* getData(size_t slotIdx) const
A
Alexander Alekhin 已提交
1464
    {
1465
#ifndef CV_THREAD_SANITIZER
1466
        CV_Assert(tlsSlotsSize > slotIdx);
1467
#endif
A
Alexander Alekhin 已提交
1468

P
Pavel Vlasov 已提交
1469 1470 1471 1472 1473
        ThreadData* threadData = (ThreadData*)tls.GetData();
        if(threadData && threadData->slots.size() > slotIdx)
            return threadData->slots[slotIdx];

        return NULL;
A
Alexander Alekhin 已提交
1474 1475
    }

P
Pavel Vlasov 已提交
1476 1477 1478 1479
    // Gather data from threads by TLS storage index
    void gather(size_t slotIdx, std::vector<void*> &dataVec)
    {
        AutoLock guard(mtxGlobalAccess);
1480 1481
        CV_Assert(tlsSlotsSize == tlsSlots.size());
        CV_Assert(tlsSlotsSize > slotIdx);
P
Pavel Vlasov 已提交
1482 1483 1484

        for(size_t i = 0; i < threads.size(); i++)
        {
1485 1486 1487 1488 1489 1490
            if(threads[i])
            {
                std::vector<void*>& thread_slots = threads[i]->slots;
                if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
                    dataVec.push_back(thread_slots[slotIdx]);
            }
P
Pavel Vlasov 已提交
1491 1492 1493
        }
    }

P
Pavel Vlasov 已提交
1494 1495
    // Set data to storage index
    void setData(size_t slotIdx, void* pData)
A
Alexander Alekhin 已提交
1496
    {
1497
#ifndef CV_THREAD_SANITIZER
1498
        CV_Assert(tlsSlotsSize > slotIdx);
1499
#endif
P
Pavel Vlasov 已提交
1500 1501 1502

        ThreadData* threadData = (ThreadData*)tls.GetData();
        if(!threadData)
A
Alexander Alekhin 已提交
1503
        {
P
Pavel Vlasov 已提交
1504 1505 1506 1507 1508 1509 1510
            threadData = new ThreadData;
            tls.SetData((void*)threadData);
            {
                AutoLock guard(mtxGlobalAccess);
                threadData->idx = threads.size();
                threads.push_back(threadData);
            }
A
Alexander Alekhin 已提交
1511
        }
P
Pavel Vlasov 已提交
1512 1513

        if(slotIdx >= threadData->slots.size())
P
Pavel Vlasov 已提交
1514
        {
1515 1516
            AutoLock guard(mtxGlobalAccess); // keep synchronization with gather() calls
            threadData->slots.resize(slotIdx + 1, NULL);
P
Pavel Vlasov 已提交
1517
        }
P
Pavel Vlasov 已提交
1518
        threadData->slots[slotIdx] = pData;
A
Alexander Alekhin 已提交
1519
    }
P
Pavel Vlasov 已提交
1520 1521 1522 1523 1524

private:
    TlsAbstraction tls; // TLS abstraction layer instance

    Mutex  mtxGlobalAccess;           // Shared objects operation guard
1525 1526
    size_t tlsSlotsSize;              // equal to tlsSlots.size() in synchronized sections
                                      // without synchronization this counter doesn't desrease - it is used for slotIdx sanity checks
P
Pavel Vlasov 已提交
1527
    std::vector<int> tlsSlots;        // TLS keys state
P
Pavel Vlasov 已提交
1528
    std::vector<ThreadData*> threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup
A
Alexander Alekhin 已提交
1529
};
1530

P
Pavel Vlasov 已提交
1531 1532
// Create global TLS storage object
static TlsStorage &getTlsStorage()
1533
{
P
Pavel Vlasov 已提交
1534
    CV_SINGLETON_LAZY_INIT_REF(TlsStorage, new TlsStorage())
1535
}
A
Alexander Alekhin 已提交
1536 1537 1538

TLSDataContainer::TLSDataContainer()
{
P
Pavel Vlasov 已提交
1539
    key_ = (int)getTlsStorage().reserveSlot(); // Reserve key from TLS storage
1540 1541
}

A
Alexander Alekhin 已提交
1542 1543
TLSDataContainer::~TLSDataContainer()
{
P
Pavel Vlasov 已提交
1544
    CV_Assert(key_ == -1); // Key must be released in child object
A
Alexander Alekhin 已提交
1545 1546
}

P
Pavel Vlasov 已提交
1547 1548 1549 1550 1551
void TLSDataContainer::gatherData(std::vector<void*> &data) const
{
    getTlsStorage().gather(key_, data);
}

P
Pavel Vlasov 已提交
1552
void TLSDataContainer::release()
A
Alexander Alekhin 已提交
1553
{
P
Pavel Vlasov 已提交
1554 1555 1556
    std::vector<void*> data;
    data.reserve(32);
    getTlsStorage().releaseSlot(key_, data); // Release key and get stored data for proper destruction
1557 1558 1559 1560 1561 1562 1563 1564 1565 1566
    key_ = -1;
    for(size_t i = 0; i < data.size(); i++)  // Delete all associated data
        deleteDataInstance(data[i]);
}

void TLSDataContainer::cleanup()
{
    std::vector<void*> data;
    data.reserve(32);
    getTlsStorage().releaseSlot(key_, data, true); // Extract stored data with removal from TLS tables
1567
    for(size_t i = 0; i < data.size(); i++)  // Delete all associated data
P
Pavel Vlasov 已提交
1568
        deleteDataInstance(data[i]);
A
Alexander Alekhin 已提交
1569 1570
}

P
Pavel Vlasov 已提交
1571
void* TLSDataContainer::getData() const
A
Alexander Alekhin 已提交
1572
{
1573
    CV_Assert(key_ != -1 && "Can't fetch data from terminated TLS container.");
P
Pavel Vlasov 已提交
1574 1575
    void* pData = getTlsStorage().getData(key_); // Check if data was already allocated
    if(!pData)
A
Alexander Alekhin 已提交
1576
    {
P
Pavel Vlasov 已提交
1577 1578 1579
        // Create new data instance and save it to TLS storage
        pData = createDataInstance();
        getTlsStorage().setData(key_, pData);
A
Alexander Alekhin 已提交
1580
    }
P
Pavel Vlasov 已提交
1581
    return pData;
A
Alexander Alekhin 已提交
1582 1583
}

1584 1585
TLSData<CoreTLSData>& getCoreTlsData()
{
1586
    CV_SINGLETON_LAZY_INIT_REF(TLSData<CoreTLSData>, new TLSData<CoreTLSData>())
1587 1588
}

1589
#if defined CVAPI_EXPORTS && defined _WIN32 && !defined WINCE
P
Pavel Vlasov 已提交
1590 1591 1592 1593
#ifdef WINRT
    #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
#endif

1594 1595 1596
extern "C"
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved);

P
Pavel Vlasov 已提交
1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
extern "C"
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
{
    if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
    {
        if (lpReserved != NULL) // called after ExitProcess() call
        {
            cv::__termination = true;
        }
        else
        {
            // Not allowed to free resources if lpReserved is non-null
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583.aspx
            cv::getTlsStorage().releaseThread();
        }
    }
    return TRUE;
}
#endif
1616

1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709

namespace {
static int g_threadNum = 0;
class ThreadID {
public:
    const int id;
    ThreadID() :
        id(CV_XADD(&g_threadNum, 1))
    {
#ifdef OPENCV_WITH_ITT
        __itt_thread_set_name(cv::format("OpenCVThread-%03d", id).c_str());
#endif
    }
};

static TLSData<ThreadID>& getThreadIDTLS()
{
    CV_SINGLETON_LAZY_INIT_REF(TLSData<ThreadID>, new TLSData<ThreadID>());
}

} // namespace
int utils::getThreadID() { return getThreadIDTLS().get()->id; }

bool utils::getConfigurationParameterBool(const char* name, bool defaultValue)
{
#ifdef NO_GETENV
    const char* envValue = NULL;
#else
    const char* envValue = getenv(name);
#endif
    if (envValue == NULL)
    {
        return defaultValue;
    }
    cv::String value = envValue;
    if (value == "1" || value == "True" || value == "true" || value == "TRUE")
    {
        return true;
    }
    if (value == "0" || value == "False" || value == "false" || value == "FALSE")
    {
        return false;
    }
    CV_ErrorNoReturn(cv::Error::StsBadArg, cv::format("Invalid value for %s parameter: %s", name, value.c_str()));
}


size_t utils::getConfigurationParameterSizeT(const char* name, size_t defaultValue)
{
#ifdef NO_GETENV
    const char* envValue = NULL;
#else
    const char* envValue = getenv(name);
#endif
    if (envValue == NULL)
    {
        return defaultValue;
    }
    cv::String value = envValue;
    size_t pos = 0;
    for (; pos < value.size(); pos++)
    {
        if (!isdigit(value[pos]))
            break;
    }
    cv::String valueStr = value.substr(0, pos);
    cv::String suffixStr = value.substr(pos, value.length() - pos);
    int v = atoi(valueStr.c_str());
    if (suffixStr.length() == 0)
        return v;
    else if (suffixStr == "MB" || suffixStr == "Mb" || suffixStr == "mb")
        return v * 1024 * 1024;
    else if (suffixStr == "KB" || suffixStr == "Kb" || suffixStr == "kb")
        return v * 1024;
    CV_ErrorNoReturn(cv::Error::StsBadArg, cv::format("Invalid value for %s parameter: %s", name, value.c_str()));
}

cv::String utils::getConfigurationParameterString(const char* name, const char* defaultValue)
{
#ifdef NO_GETENV
    const char* envValue = NULL;
#else
    const char* envValue = getenv(name);
#endif
    if (envValue == NULL)
    {
        return defaultValue;
    }
    cv::String value = envValue;
    return value;
}


1710
#ifdef CV_COLLECT_IMPL_DATA
P
Pavel Vlasov 已提交
1711 1712
ImplCollector& getImplData()
{
1713
    CV_SINGLETON_LAZY_INIT_REF(ImplCollector, new ImplCollector())
P
Pavel Vlasov 已提交
1714 1715
}

1716 1717
void setImpl(int flags)
{
P
Pavel Vlasov 已提交
1718 1719 1720 1721 1722
    cv::AutoLock lock(getImplData().mutex);

    getImplData().implFlags = flags;
    getImplData().implCode.clear();
    getImplData().implFun.clear();
1723 1724 1725 1726
}

void addImpl(int flag, const char* func)
{
P
Pavel Vlasov 已提交
1727 1728 1729
    cv::AutoLock lock(getImplData().mutex);

    getImplData().implFlags |= flag;
1730 1731
    if(func) // use lazy collection if name was not specified
    {
P
Pavel Vlasov 已提交
1732 1733
        size_t index = getImplData().implCode.size();
        if(!index || (getImplData().implCode[index-1] != flag || getImplData().implFun[index-1].compare(func))) // avoid duplicates
1734
        {
P
Pavel Vlasov 已提交
1735 1736
            getImplData().implCode.push_back(flag);
            getImplData().implFun.push_back(func);
1737 1738 1739 1740 1741 1742
        }
    }
}

int getImpl(std::vector<int> &impl, std::vector<String> &funName)
{
P
Pavel Vlasov 已提交
1743 1744 1745 1746 1747
    cv::AutoLock lock(getImplData().mutex);

    impl    = getImplData().implCode;
    funName = getImplData().implFun;
    return getImplData().implFlags; // return actual flags for lazy collection
1748 1749 1750 1751
}

bool useCollection()
{
P
Pavel Vlasov 已提交
1752
    return getImplData().useCollection;
1753 1754 1755 1756
}

void setUseCollection(bool flag)
{
P
Pavel Vlasov 已提交
1757 1758 1759
    cv::AutoLock lock(getImplData().mutex);

    getImplData().useCollection = flag;
1760 1761 1762
}
#endif

1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799
namespace instr
{
bool useInstrumentation()
{
#ifdef ENABLE_INSTRUMENTATION
    return getInstrumentStruct().useInstr;
#else
    return false;
#endif
}

void setUseInstrumentation(bool flag)
{
#ifdef ENABLE_INSTRUMENTATION
    getInstrumentStruct().useInstr = flag;
#else
    CV_UNUSED(flag);
#endif
}

InstrNode* getTrace()
{
#ifdef ENABLE_INSTRUMENTATION
    return &getInstrumentStruct().rootNode;
#else
    return NULL;
#endif
}

void resetTrace()
{
#ifdef ENABLE_INSTRUMENTATION
    getInstrumentStruct().rootNode.removeChilds();
    getInstrumentTLSStruct().pCurrentNode = &getInstrumentStruct().rootNode;
#endif
}

1800
void setFlags(FLAGS modeFlags)
1801 1802
{
#ifdef ENABLE_INSTRUMENTATION
1803
    getInstrumentStruct().flags = modeFlags;
1804 1805 1806 1807
#else
    CV_UNUSED(modeFlags);
#endif
}
1808
FLAGS getFlags()
1809 1810
{
#ifdef ENABLE_INSTRUMENTATION
1811
    return (FLAGS)getInstrumentStruct().flags;
1812
#else
1813
    return (FLAGS)0;
1814 1815 1816
#endif
}

1817
NodeData::NodeData(const char* funName, const char* fileName, int lineNum, void* retAddress, bool alwaysExpand, cv::instr::TYPE instrType, cv::instr::IMPL implType)
1818
{
1819 1820 1821 1822 1823 1824 1825
    m_funName       = funName;
    m_instrType     = instrType;
    m_implType      = implType;
    m_fileName      = fileName;
    m_lineNum       = lineNum;
    m_retAddress    = retAddress;
    m_alwaysExpand  = alwaysExpand;
1826

1827 1828
    m_threads    = 1;
    m_counter    = 0;
1829 1830
    m_ticksTotal = 0;

1831
    m_funError  = false;
1832 1833 1834 1835 1836 1837 1838
}
NodeData::NodeData(NodeData &ref)
{
    *this = ref;
}
NodeData& NodeData::operator=(const NodeData &right)
{
1839 1840 1841 1842 1843 1844 1845 1846 1847
    this->m_funName      = right.m_funName;
    this->m_instrType    = right.m_instrType;
    this->m_implType     = right.m_implType;
    this->m_fileName     = right.m_fileName;
    this->m_lineNum      = right.m_lineNum;
    this->m_retAddress   = right.m_retAddress;
    this->m_alwaysExpand = right.m_alwaysExpand;

    this->m_threads     = right.m_threads;
1848 1849
    this->m_counter     = right.m_counter;
    this->m_ticksTotal  = right.m_ticksTotal;
1850

1851
    this->m_funError    = right.m_funError;
1852

1853 1854 1855 1856 1857 1858 1859 1860
    return *this;
}
NodeData::~NodeData()
{
}
bool operator==(const NodeData& left, const NodeData& right)
{
    if(left.m_lineNum == right.m_lineNum && left.m_funName == right.m_funName && left.m_fileName == right.m_fileName)
1861 1862 1863 1864
    {
        if(left.m_retAddress == right.m_retAddress || !(cv::instr::getFlags()&cv::instr::FLAGS_EXPAND_SAME_NAMES || left.m_alwaysExpand))
            return true;
    }
1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884
    return false;
}

#ifdef ENABLE_INSTRUMENTATION
InstrStruct& getInstrumentStruct()
{
    static InstrStruct instr;
    return instr;
}

InstrTLSStruct& getInstrumentTLSStruct()
{
    return *getInstrumentStruct().tlsStruct.get();
}

InstrNode* getCurrentNode()
{
    return getInstrumentTLSStruct().pCurrentNode;
}

1885
IntrumentationRegion::IntrumentationRegion(const char* funName, const char* fileName, int lineNum, void *retAddress, bool alwaysExpand, TYPE instrType, IMPL implType)
1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901
{
    m_disabled    = false;
    m_regionTicks = 0;

    InstrStruct *pStruct = &getInstrumentStruct();
    if(pStruct->useInstr)
    {
        InstrTLSStruct *pTLS = &getInstrumentTLSStruct();

        // Disable in case of failure
        if(!pTLS->pCurrentNode)
        {
            m_disabled = true;
            return;
        }

1902 1903 1904 1905
        int depth = pTLS->pCurrentNode->getDepth();
        if(pStruct->maxDepth && pStruct->maxDepth <= depth)
        {
            m_disabled = true;
1906
            return;
1907
        }
1908

1909
        NodeData payload(funName, fileName, lineNum, retAddress, alwaysExpand, instrType, implType);
1910 1911
        Node<NodeData>* pChild = NULL;

1912
        if(pStruct->flags&FLAGS_MAPPING)
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927
        {
            // Critical section
            cv::AutoLock guard(pStruct->mutexCreate); // Guard from concurrent child creation
            pChild = pTLS->pCurrentNode->findChild(payload);
            if(!pChild)
            {
                pChild = new Node<NodeData>(payload);
                pTLS->pCurrentNode->addChild(pChild);
            }
        }
        else
        {
            pChild = pTLS->pCurrentNode->findChild(payload);
            if(!pChild)
            {
1928
                m_disabled = true;
1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
                return;
            }
        }
        pTLS->pCurrentNode = pChild;

        m_regionTicks = getTickCount();
    }
}

IntrumentationRegion::~IntrumentationRegion()
{
    InstrStruct *pStruct = &getInstrumentStruct();
    if(pStruct->useInstr)
    {
        if(!m_disabled)
        {
            InstrTLSStruct *pTLS = &getInstrumentTLSStruct();
1946 1947 1948 1949

            if (pTLS->pCurrentNode->m_payload.m_implType == cv::instr::IMPL_OPENCL &&
                (pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_FUN ||
                    pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_WRAPPER))
1950
            {
1951
                cv::ocl::finish(); // TODO Support "async" OpenCL instrumentation
1952 1953
            }

1954 1955 1956 1957 1958 1959
            uint64 ticks = (getTickCount() - m_regionTicks);
            {
                cv::AutoLock guard(pStruct->mutexCount); // Concurrent ticks accumulation
                pTLS->pCurrentNode->m_payload.m_counter++;
                pTLS->pCurrentNode->m_payload.m_ticksTotal += ticks;
                pTLS->pCurrentNode->m_payload.m_tls.get()->m_ticksTotal += ticks;
1960
            }
1961 1962

            pTLS->pCurrentNode = pTLS->pCurrentNode->m_pParent;
1963 1964 1965 1966 1967 1968
        }
    }
}
#endif
}

I
Ilya Lavrenov 已提交
1969 1970 1971
namespace ipp
{

1972
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
1973
struct IPPInitSingleton
1974 1975
{
public:
P
Pavel Vlasov 已提交
1976
    IPPInitSingleton()
1977
    {
P
Pavel Vlasov 已提交
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996
        useIPP         = true;
        useIPP_NE      = false;
        ippStatus      = 0;
        funcname       = NULL;
        filename       = NULL;
        linen          = 0;
        cpuFeatures    = 0;
        ippFeatures    = 0;
        ippTopFeatures = 0;
        pIppLibInfo    = NULL;

        ippStatus = ippGetCpuFeatures(&cpuFeatures, NULL);
        if(ippStatus < 0)
        {
            std::cerr << "ERROR: IPP cannot detect CPU features, IPP was disabled " << std::endl;
            useIPP = false;
            return;
        }
        ippFeatures = cpuFeatures;
1997 1998 1999 2000 2001

        const char* pIppEnv = getenv("OPENCV_IPP");
        cv::String env = pIppEnv;
        if(env.size())
        {
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
#if IPP_VERSION_X100 >= 201703
            const Ipp64u minorFeatures = ippCPUID_MOVBE|ippCPUID_AES|ippCPUID_CLMUL|ippCPUID_ABR|ippCPUID_RDRAND|ippCPUID_F16C|
                ippCPUID_ADCOX|ippCPUID_RDSEED|ippCPUID_PREFETCHW|ippCPUID_SHA|ippCPUID_MPX|ippCPUID_AVX512CD|ippCPUID_AVX512ER|
                ippCPUID_AVX512PF|ippCPUID_AVX512BW|ippCPUID_AVX512DQ|ippCPUID_AVX512VL|ippCPUID_AVX512VBMI;
#elif IPP_VERSION_X100 >= 201700
            const Ipp64u minorFeatures = ippCPUID_MOVBE|ippCPUID_AES|ippCPUID_CLMUL|ippCPUID_ABR|ippCPUID_RDRAND|ippCPUID_F16C|
                ippCPUID_ADCOX|ippCPUID_RDSEED|ippCPUID_PREFETCHW|ippCPUID_SHA|ippCPUID_AVX512CD|ippCPUID_AVX512ER|
                ippCPUID_AVX512PF|ippCPUID_AVX512BW|ippCPUID_AVX512DQ|ippCPUID_AVX512VL|ippCPUID_AVX512VBMI;
#else
            const Ipp64u minorFeatures = 0;
#endif

P
Pavel Vlasov 已提交
2014 2015 2016 2017 2018 2019 2020
            env = env.toLowerCase();
            if(env.substr(0, 2) == "ne")
            {
                useIPP_NE = true;
                env = env.substr(3, env.size());
            }

2021 2022 2023 2024 2025 2026
            if(env == "disabled")
            {
                std::cerr << "WARNING: IPP was disabled by OPENCV_IPP environment variable" << std::endl;
                useIPP = false;
            }
            else if(env == "sse42")
2027
                ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42;
2028
            else if(env == "avx2")
2029 2030
                ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42|ippCPUID_AVX|ippCPUID_AVX2;
#if IPP_VERSION_X100 >= 201700
P
Pavel Vlasov 已提交
2031 2032
#if defined (_M_AMD64) || defined (__x86_64__)
            else if(env == "avx512")
2033 2034
                ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42|ippCPUID_AVX|ippCPUID_AVX2|ippCPUID_AVX512F;
#endif
2035 2036
#endif
            else
P
Pavel Vlasov 已提交
2037 2038
                std::cerr << "ERROR: Improper value of OPENCV_IPP: " << env.c_str() << ". Correct values are: disabled, sse42, avx2, avx512 (Intel64 only)" << std::endl;

2039 2040
            // Trim unsupported features
            ippFeatures &= cpuFeatures;
P
Pavel Vlasov 已提交
2041 2042 2043 2044
        }

        // Disable AVX1 since we don't track regressions for it. SSE42 will be used instead
        if(cpuFeatures&ippCPUID_AVX && !(cpuFeatures&ippCPUID_AVX2))
2045
            ippFeatures &= ~((Ipp64u)ippCPUID_AVX);
P
Pavel Vlasov 已提交
2046 2047 2048

        // IPP integrations in OpenCV support only SSE4.2, AVX2 and AVX-512 optimizations.
        if(!(
2049
#if IPP_VERSION_X100 >= 201700
P
Pavel Vlasov 已提交
2050
            cpuFeatures&ippCPUID_AVX512F ||
2051
#endif
P
Pavel Vlasov 已提交
2052 2053 2054 2055 2056 2057
            cpuFeatures&ippCPUID_AVX2 ||
            cpuFeatures&ippCPUID_SSE42
            ))
        {
            useIPP = false;
            return;
2058 2059
        }

2060 2061 2062 2063
        if(ippFeatures == cpuFeatures)
            IPP_INITIALIZER(0)
        else
            IPP_INITIALIZER(ippFeatures)
2064
        ippFeatures = ippGetEnabledCpuFeatures();
P
Pavel Vlasov 已提交
2065 2066

        // Detect top level optimizations to make comparison easier for optimizations dependent conditions
2067
#if IPP_VERSION_X100 >= 201700
P
Pavel Vlasov 已提交
2068 2069 2070 2071 2072 2073 2074 2075 2076
        if(ippFeatures&ippCPUID_AVX512F)
        {
            if((ippFeatures&ippCPUID_AVX512_SKX) == ippCPUID_AVX512_SKX)
                ippTopFeatures = ippCPUID_AVX512_SKX;
            else if((ippFeatures&ippCPUID_AVX512_KNL) == ippCPUID_AVX512_KNL)
                ippTopFeatures = ippCPUID_AVX512_KNL;
            else
                ippTopFeatures = ippCPUID_AVX512F; // Unknown AVX512 configuration
        }
2077 2078 2079
        else
#endif
        if(ippFeatures&ippCPUID_AVX2)
P
Pavel Vlasov 已提交
2080 2081 2082 2083 2084
            ippTopFeatures = ippCPUID_AVX2;
        else if(ippFeatures&ippCPUID_SSE42)
            ippTopFeatures = ippCPUID_SSE42;

        pIppLibInfo = ippiGetLibVersion();
2085 2086
    }

P
Pavel Vlasov 已提交
2087 2088 2089
public:
    bool        useIPP;
    bool        useIPP_NE;
2090

P
Pavel Vlasov 已提交
2091
    int         ippStatus;  // 0 - all is ok, -1 - IPP functions failed
2092 2093 2094
    const char *funcname;
    const char *filename;
    int         linen;
2095
    Ipp64u      ippFeatures;
P
Pavel Vlasov 已提交
2096 2097 2098
    Ipp64u      cpuFeatures;
    Ipp64u      ippTopFeatures;
    const IppLibraryVersion *pIppLibInfo;
2099 2100
};

P
Pavel Vlasov 已提交
2101
static IPPInitSingleton& getIPPSingleton()
2102
{
P
Pavel Vlasov 已提交
2103
    CV_SINGLETON_LAZY_INIT_REF(IPPInitSingleton, new IPPInitSingleton())
2104
}
2105
#endif
2106

2107 2108 2109
#if OPENCV_ABI_COMPATIBILITY > 300
unsigned long long getIppFeatures()
#else
2110
int getIppFeatures()
2111
#endif
2112 2113
{
#ifdef HAVE_IPP
2114
#if OPENCV_ABI_COMPATIBILITY > 300
P
Pavel Vlasov 已提交
2115
    return getIPPSingleton().ippFeatures;
2116 2117 2118
#else
    return (int)getIPPSingleton().ippFeatures;
#endif
2119 2120 2121 2122
#else
    return 0;
#endif
}
I
Ilya Lavrenov 已提交
2123

P
Pavel Vlasov 已提交
2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134
unsigned long long getIppTopFeatures();

unsigned long long getIppTopFeatures()
{
#ifdef HAVE_IPP
    return getIPPSingleton().ippTopFeatures;
#else
    return 0;
#endif
}

I
Ilya Lavrenov 已提交
2135
void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line)
I
Ilya Lavrenov 已提交
2136
{
2137
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
2138 2139 2140 2141
    getIPPSingleton().ippStatus = status;
    getIPPSingleton().funcname = _funcname;
    getIPPSingleton().filename = _filename;
    getIPPSingleton().linen = _line;
2142 2143 2144
#else
    CV_UNUSED(status); CV_UNUSED(_funcname); CV_UNUSED(_filename); CV_UNUSED(_line);
#endif
I
Ilya Lavrenov 已提交
2145 2146 2147 2148
}

int getIppStatus()
{
2149
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
2150
    return getIPPSingleton().ippStatus;
2151 2152 2153
#else
    return 0;
#endif
I
Ilya Lavrenov 已提交
2154 2155 2156 2157
}

String getIppErrorLocation()
{
2158
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
2159
    return format("%s:%d %s", getIPPSingleton().filename ? getIPPSingleton().filename : "", getIPPSingleton().linen, getIPPSingleton().funcname ? getIPPSingleton().funcname : "");
2160 2161 2162
#else
    return String();
#endif
I
Ilya Lavrenov 已提交
2163 2164
}

P
Pavel Vlasov 已提交
2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177
String getIppVersion()
{
#ifdef HAVE_IPP
    const IppLibraryVersion *pInfo = getIPPSingleton().pIppLibInfo;
    if(pInfo)
        return format("%s %s %s", pInfo->Name, pInfo->Version, pInfo->BuildDate);
    else
        return String("error");
#else
    return String("disabled");
#endif
}

2178 2179 2180
bool useIPP()
{
#ifdef HAVE_IPP
2181
    CoreTLSData* data = getCoreTlsData().get();
2182 2183
    if(data->useIPP < 0)
    {
P
Pavel Vlasov 已提交
2184
        data->useIPP = getIPPSingleton().useIPP;
2185 2186 2187 2188 2189 2190 2191 2192 2193
    }
    return (data->useIPP > 0);
#else
    return false;
#endif
}

void setUseIPP(bool flag)
{
2194
    CoreTLSData* data = getCoreTlsData().get();
2195
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
2196
    data->useIPP = (getIPPSingleton().useIPP)?flag:false;
2197 2198 2199 2200 2201 2202
#else
    (void)flag;
    data->useIPP = false;
#endif
}

P
Pavel Vlasov 已提交
2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227
bool useIPP_NE()
{
#ifdef HAVE_IPP
    CoreTLSData* data = getCoreTlsData().get();
    if(data->useIPP_NE < 0)
    {
        data->useIPP_NE = getIPPSingleton().useIPP_NE;
    }
    return (data->useIPP_NE > 0);
#else
    return false;
#endif
}

void setUseIPP_NE(bool flag)
{
    CoreTLSData* data = getCoreTlsData().get();
#ifdef HAVE_IPP
    data->useIPP_NE = (getIPPSingleton().useIPP_NE)?flag:false;
#else
    (void)flag;
    data->useIPP_NE = false;
#endif
}

I
Ilya Lavrenov 已提交
2228 2229
} // namespace ipp

2230 2231
} // namespace cv

2232 2233 2234 2235 2236 2237
#ifdef HAVE_TEGRA_OPTIMIZATION

namespace tegra {

bool useTegra()
{
2238
    cv::CoreTLSData* data = cv::getCoreTlsData().get();
2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253

    if (data->useTegra < 0)
    {
        const char* pTegraEnv = getenv("OPENCV_TEGRA");
        if (pTegraEnv && (cv::String(pTegraEnv) == "disabled"))
            data->useTegra = false;
        else
            data->useTegra = true;
    }

    return (data->useTegra > 0);
}

void setUseTegra(bool flag)
{
2254
    cv::CoreTLSData* data = cv::getCoreTlsData().get();
2255 2256 2257 2258 2259 2260 2261
    data->useTegra = flag;
}

} // namespace tegra

#endif

2262
/* End of file. */