2010-05-12 01:44:00 +08:00
/*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.
2015-01-12 15:59:30 +08:00
// Copyright (C) 2015, Itseez Inc., all rights reserved.
2010-05-12 01:44:00 +08:00
// 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"
2015-09-25 23:00:53 +08:00
# include <iostream>
2010-05-12 01:44:00 +08:00
2017-05-25 23:59:01 +08:00
# include <opencv2/core/utils/trace.private.hpp>
2015-06-23 19:31:01 +08:00
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 ( ) ;
} // namespace cv
2013-08-21 18:38:20 +08:00
# ifdef _MSC_VER
# if _MSC_VER >= 1700
# pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
# endif
# endif
2017-07-10 17:43:59 +08:00
# if defined __ANDROID__ || defined __linux__ || defined __FreeBSD__
2014-12-30 21:53:19 +08:00
# include <unistd.h>
# include <fcntl.h>
# include <elf.h>
2017-07-10 17:43:59 +08:00
# if defined __ANDROID__ || defined __linux__
2014-12-30 21:53:19 +08:00
# include <linux / auxvec.h>
# endif
2015-11-13 16:03:34 +08:00
# endif
2014-12-30 21:53:19 +08:00
2017-07-10 17:43:59 +08:00
# if defined __ANDROID__ && defined HAVE_CPUFEATURES
2017-05-19 21:14:01 +08:00
# include <cpu-features.h>
# endif
2017-07-25 18:23:44 +08:00
# if defined _WIN32 || defined WINCE
2012-11-01 16:44:10 +08:00
# 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>
2013-07-19 17:43:05 +08:00
# if (_WIN32_WINNT >= 0x0602)
2013-07-23 21:44:57 +08:00
# include <synchapi.h>
2013-07-19 17:43:05 +08:00
# endif
2012-11-01 16:44:10 +08:00
# undef small
# undef min
# undef max
# undef abs
2010-05-12 01:44:00 +08:00
# include <tchar.h>
2015-12-15 20:55:43 +08:00
# if defined _MSC_VER
# if _MSC_VER >= 1400
# include <intrin.h>
# elif defined _M_IX86
static void __cpuid ( int * cpuid_data , int )
{
__asm
{
push ebx
push edi
mov edi , cpuid_data
mov eax , 1
cpuid
mov [ edi ] , eax
mov [ edi + 4 ] , ebx
mov [ edi + 8 ] , ecx
mov [ edi + 12 ] , edx
pop edi
pop ebx
}
}
static void __cpuidex ( int * cpuid_data , int , int )
{
__asm
{
push edi
mov edi , cpuid_data
mov eax , 7
mov ecx , 0
cpuid
mov [ edi ] , eax
mov [ edi + 4 ] , ebx
mov [ edi + 8 ] , ecx
mov [ edi + 12 ] , edx
pop edi
}
}
# endif
# endif
2013-07-19 17:43:05 +08:00
2015-02-21 00:47:45 +08:00
# ifdef WINRT
2013-07-19 17:43:05 +08:00
# include <wrl/client.h>
2013-11-18 20:25:50 +08:00
# ifndef __cplusplus_winrt
# include <windows.storage.h>
# pragma comment(lib, "runtimeobject.lib")
# endif
2013-07-19 17:43:05 +08:00
std : : wstring GetTempPathWinRT ( )
{
2013-11-18 20:25:50 +08:00
# ifdef __cplusplus_winrt
2013-07-19 17:43:05 +08:00
return std : : wstring ( Windows : : Storage : : ApplicationData : : Current - > TemporaryFolder - > Path - > Data ( ) ) ;
2013-11-18 20:25:50 +08:00
# 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 ;
2013-12-23 00:21:51 +08:00
if ( FAILED ( RoGetActivationFactory ( str , IID_PPV_ARGS ( appdataFactory . ReleaseAndGetAddressOf ( ) ) ) ) )
2013-11-18 20:25:50 +08:00
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
2013-07-19 17:43:05 +08:00
}
std : : wstring GetTempFileNameWinRT ( std : : wstring prefix )
{
2013-07-29 19:38:18 +08:00
wchar_t guidStr [ 40 ] ;
GUID g ;
CoCreateGuid ( & g ) ;
2013-07-19 17:43:05 +08:00
wchar_t * mask = L " %08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x " ;
2013-07-29 19:38:18 +08:00
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 ] ) ) ;
2013-07-19 17:43:05 +08:00
2015-02-21 00:47:45 +08:00
return prefix . append ( std : : wstring ( guidStr ) ) ;
2013-07-19 17:43:05 +08:00
}
# endif
2010-05-12 01:44:00 +08:00
# else
# include <pthread.h>
# include <sys/time.h>
# include <time.h>
2011-06-13 04:29:50 +08:00
# if defined __MACH__ && defined __APPLE__
2010-05-12 01:44:00 +08:00
# include <mach/mach.h>
# include <mach/mach_time.h>
# endif
# endif
# ifdef _OPENMP
# include "omp.h"
# endif
2016-08-22 21:17:06 +08:00
# if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__ || defined __FreeBSD__
2011-08-02 20:42:58 +08:00
# include <unistd.h>
# include <stdio.h>
2012-06-08 01:21:29 +08:00
# include <sys/types.h>
2017-07-10 17:43:59 +08:00
# if defined __ANDROID__
2011-08-02 22:56:51 +08:00
# include <sys/sysconf.h>
2011-08-02 20:42:58 +08:00
# endif
2011-08-02 22:56:51 +08:00
# endif
2011-08-02 20:42:58 +08:00
2017-07-10 17:43:59 +08:00
# ifdef __ANDROID__
2012-08-08 20:39:24 +08:00
# include <android / log.h>
# endif
2010-05-12 01:44:00 +08:00
namespace cv
{
2011-06-09 05:35:19 +08:00
Exception : : Exception ( ) { code = 0 ; line = 0 ; }
2013-03-23 00:37:49 +08:00
Exception : : Exception ( int _code , const String & _err , const String & _func , const String & _file , int _line )
2011-06-09 05:35:19 +08:00
: 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 .
2012-06-08 01:21:29 +08:00
*/
2011-06-09 05:35:19 +08:00
const char * Exception : : what ( ) const throw ( ) { return msg . c_str ( ) ; }
void Exception : : formatMessage ( )
{
if ( func . size ( ) > 0 )
msg = format ( " %s:%d: error: (%d) %s in function %s \n " , file . c_str ( ) , line , code , err . c_str ( ) , func . c_str ( ) ) ;
else
msg = format ( " %s:%d: error: (%d) %s \n " , file . c_str ( ) , line , code , err . c_str ( ) ) ;
}
2012-06-08 01:21:29 +08:00
2016-09-07 23:02:36 +08:00
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 " ;
}
2015-12-15 20:55:43 +08:00
struct HWFeatures
{
enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE } ;
2016-09-07 23:02:36 +08:00
HWFeatures ( bool run_initialize = false )
2015-12-15 20:55:43 +08:00
{
2016-09-07 23:02:36 +08:00
memset ( have , 0 , sizeof ( have [ 0 ] ) * MAX_FEATURE ) ;
if ( run_initialize )
initialize ( ) ;
2015-12-15 20:55:43 +08:00
}
2016-09-07 23:02:36 +08:00
static void initializeNames ( )
2015-12-15 20:55:43 +08:00
{
2016-09-07 23:02:36 +08:00
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 " ;
g_hwFeatureNames [ CPU_AVX_512IFMA512 ] = " AVX512IFMA " ;
g_hwFeatureNames [ CPU_AVX_512PF ] = " AVX512PF " ;
g_hwFeatureNames [ CPU_AVX_512VBMI ] = " AVX512VBMI " ;
g_hwFeatureNames [ CPU_AVX_512VL ] = " AVX512VL " ;
g_hwFeatureNames [ CPU_NEON ] = " NEON " ;
}
void initialize ( void )
{
# ifndef WINRT
if ( getenv ( " OPENCV_DUMP_CONFIG " ) )
{
fprintf ( stderr , " \n OpenCV build configuration is: \n %s \n " ,
cv : : getBuildInformation ( ) . c_str ( ) ) ;
}
# endif
initializeNames ( ) ;
2015-12-15 20:55:43 +08:00
int cpuid_data [ 4 ] = { 0 , 0 , 0 , 0 } ;
2016-09-07 23:02:36 +08:00
int cpuid_data_ex [ 4 ] = { 0 , 0 , 0 , 0 } ;
2015-12-15 20:55:43 +08:00
# if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
2016-09-07 23:02:36 +08:00
# define OPENCV_HAVE_X86_CPUID 1
2015-12-15 20:55:43 +08:00
__cpuid ( cpuid_data , 1 ) ;
# elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
2016-09-07 23:02:36 +08:00
# define OPENCV_HAVE_X86_CPUID 1
2015-12-15 20:55:43 +08:00
# ifdef __x86_64__
asm __volatile__
(
" movl $1, %%eax \n \t "
" cpuid \n \t "
: [ eax ] " =a " ( cpuid_data [ 0 ] ) , [ ebx ] " =b " ( cpuid_data [ 1 ] ) , [ ecx ] " =c " ( cpuid_data [ 2 ] ) , [ edx ] " =d " ( cpuid_data [ 3 ] )
:
: " cc "
) ;
# else
asm volatile
(
" pushl %%ebx \n \t "
" movl $1,%%eax \n \t "
" cpuid \n \t "
" popl %%ebx \n \t "
: " =a " ( cpuid_data [ 0 ] ) , " =c " ( cpuid_data [ 2 ] ) , " =d " ( cpuid_data [ 3 ] )
:
: " cc "
) ;
# endif
# endif
2016-09-07 23:02:36 +08:00
# ifdef OPENCV_HAVE_X86_CPUID
int x86_family = ( cpuid_data [ 0 ] > > 8 ) & 15 ;
if ( x86_family > = 6 )
2015-12-15 20:55:43 +08:00
{
2016-09-07 23:02:36 +08:00
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 ;
2015-12-15 20:55:43 +08:00
// make the second call to the cpuid command in order to get
// information about extended features like AVX2
# if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
2016-09-07 23:02:36 +08:00
# define OPENCV_HAVE_X86_CPUID_EX 1
__cpuidex ( cpuid_data_ex , 7 , 0 ) ;
2015-12-15 20:55:43 +08:00
# elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
2016-09-07 23:02:36 +08:00
# define OPENCV_HAVE_X86_CPUID_EX 1
2015-12-15 20:55:43 +08:00
# ifdef __x86_64__
asm __volatile__
(
" movl $7, %%eax \n \t "
" movl $0, %%ecx \n \t "
" cpuid \n \t "
2016-09-07 23:02:36 +08:00
: [ eax ] " =a " ( cpuid_data_ex [ 0 ] ) , [ ebx ] " =b " ( cpuid_data_ex [ 1 ] ) , [ ecx ] " =c " ( cpuid_data_ex [ 2 ] ) , [ edx ] " =d " ( cpuid_data_ex [ 3 ] )
2015-12-15 20:55:43 +08:00
:
: " cc "
) ;
# else
asm volatile
(
" pushl %%ebx \n \t "
" movl $7,%%eax \n \t "
" movl $0,%%ecx \n \t "
" cpuid \n \t "
" movl %%ebx, %0 \n \t "
" popl %%ebx \n \t "
2016-09-07 23:02:36 +08:00
: " =r " ( cpuid_data_ex [ 1 ] ) , " =c " ( cpuid_data_ex [ 2 ] )
2015-12-15 20:55:43 +08:00
:
: " cc "
) ;
# endif
# endif
2016-09-07 23:02:36 +08:00
# ifdef OPENCV_HAVE_X86_CPUID_EX
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 ;
# else
CV_UNUSED ( cpuid_data_ex ) ;
# endif
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__)
__asm__ ( " xgetbv " : " =a " ( xcr0 ) : " c " ( 0 ) : " %edx " ) ;
# 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 ;
}
2015-12-15 20:55:43 +08:00
}
2016-09-07 23:02:36 +08:00
# else
CV_UNUSED ( cpuid_data ) ;
CV_UNUSED ( cpuid_data_ex ) ;
# endif // OPENCV_HAVE_X86_CPUID
2015-12-15 20:55:43 +08:00
2017-06-09 23:24:14 +08:00
# if defined __ANDROID__ || defined __linux__
2015-12-15 20:55:43 +08:00
# ifdef __aarch64__
2016-09-07 23:02:36 +08:00
have [ CV_CPU_NEON ] = true ;
have [ CV_CPU_FP16 ] = true ;
2017-06-09 23:24:14 +08:00
# elif defined __arm__ && defined __ANDROID__
2017-06-13 00:10:13 +08:00
# if defined HAVE_CPUFEATURES
2017-06-09 23:24:14 +08:00
__android_log_print ( ANDROID_LOG_INFO , " OpenCV " , " calling android_getCpuFeatures() ... " ) ;
uint64_t features = android_getCpuFeatures ( ) ;
__android_log_print ( ANDROID_LOG_INFO , " OpenCV " , " calling android_getCpuFeatures() ... Done (%llx) " , features ) ;
have [ CV_CPU_NEON ] = ( features & ANDROID_CPU_ARM_FEATURE_NEON ) ! = 0 ;
have [ CV_CPU_FP16 ] = ( features & ANDROID_CPU_ARM_FEATURE_VFP_FP16 ) ! = 0 ;
2017-06-13 00:10:13 +08:00
# else
__android_log_print ( ANDROID_LOG_INFO , " OpenCV " , " cpufeatures library is not avaialble for CPU detection " ) ;
# if CV_NEON
__android_log_print ( ANDROID_LOG_INFO , " OpenCV " , " - NEON instructions is enabled via build flags " ) ;
have [ CV_CPU_NEON ] = true ;
# else
__android_log_print ( ANDROID_LOG_INFO , " OpenCV " , " - NEON instructions is NOT enabled via build flags " ) ;
# endif
# if CV_FP16
__android_log_print ( ANDROID_LOG_INFO , " OpenCV " , " - FP16 instructions is enabled via build flags " ) ;
have [ CV_CPU_FP16 ] = true ;
# else
__android_log_print ( ANDROID_LOG_INFO , " OpenCV " , " - FP16 instructions is NOT enabled via build flags " ) ;
# endif
# endif
2016-05-21 20:31:33 +08:00
# elif defined __arm__
2015-12-15 20:55:43 +08:00
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 )
{
2016-09-07 23:02:36 +08:00
have [ CV_CPU_NEON ] = ( auxv . a_un . a_val & 4096 ) ! = 0 ;
have [ CV_CPU_FP16 ] = ( auxv . a_un . a_val & 2 ) ! = 0 ;
2015-12-15 20:55:43 +08:00
break ;
}
}
close ( cpufile ) ;
}
# endif
2016-05-21 20:31:33 +08:00
# elif (defined __clang__ || defined __APPLE__)
# if (defined __ARM_NEON__ || (defined __ARM_NEON && defined __aarch64__))
2016-09-07 23:02:36 +08:00
have [ CV_CPU_NEON ] = true ;
2016-05-21 20:31:33 +08:00
# endif
# if (defined __ARM_FP && (((__ARM_FP & 0x2) != 0) && defined __ARM_NEON__))
2016-09-07 23:02:36 +08:00
have [ CV_CPU_FP16 ] = true ;
2016-05-21 20:31:33 +08:00
# endif
2015-12-15 20:55:43 +08:00
# endif
2016-09-07 23:02:36 +08:00
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 , " \n Required 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 )
{
return c = = ' , ' | | c = = ' ; ' | | c = = ' - ' ;
}
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 ( ) ) ;
}
}
}
2015-12-15 20:55:43 +08:00
}
bool have [ MAX_FEATURE + 1 ] ;
} ;
2016-09-07 23:02:36 +08:00
static HWFeatures featuresEnabled ( true ) , featuresDisabled = HWFeatures ( false ) ;
2015-12-15 20:55:43 +08:00
static HWFeatures * currentFeatures = & featuresEnabled ;
2010-05-12 01:44:00 +08:00
bool checkHardwareSupport ( int feature )
{
CV_DbgAssert ( 0 < = feature & & feature < = CV_HARDWARE_MAX_FEATURE ) ;
2015-12-15 20:55:43 +08:00
return currentFeatures - > have [ feature ] ;
2010-05-12 01:44:00 +08:00
}
2015-12-15 20:55:43 +08:00
volatile bool useOptimizedFlag = true ;
2010-05-12 01:44:00 +08:00
void setUseOptimized ( bool flag )
{
2015-12-15 20:55:43 +08:00
useOptimizedFlag = flag ;
currentFeatures = flag ? & featuresEnabled : & featuresDisabled ;
2015-02-27 19:24:51 +08:00
ipp : : setUseIPP ( flag ) ;
2015-06-20 01:52:14 +08:00
# ifdef HAVE_OPENCL
2015-02-27 19:24:51 +08:00
ocl : : setUseOpenCL ( flag ) ;
2015-06-20 01:52:14 +08:00
# endif
2015-02-27 19:24:51 +08:00
# ifdef HAVE_TEGRA_OPTIMIZATION
: : tegra : : setUseTegra ( flag ) ;
# endif
2010-05-12 01:44:00 +08:00
}
2010-12-24 07:00:04 +08:00
bool useOptimized ( void )
2010-05-12 01:44:00 +08:00
{
2015-12-15 20:55:43 +08:00
return useOptimizedFlag ;
2010-05-12 01:44:00 +08:00
}
2010-12-24 07:00:04 +08:00
int64 getTickCount ( void )
2010-05-12 01:44:00 +08:00
{
2017-07-25 18:23:44 +08:00
# if defined _WIN32 || defined WINCE
2010-05-12 01:44:00 +08:00
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 ;
2011-05-31 23:22:22 +08:00
# elif defined __MACH__ && defined __APPLE__
2010-05-12 01:44:00 +08:00
return ( int64 ) mach_absolute_time ( ) ;
2010-12-24 07:00:04 +08:00
# else
2010-05-12 01:44:00 +08:00
struct timeval tv ;
struct timezone tz ;
gettimeofday ( & tv , & tz ) ;
return ( int64 ) tv . tv_sec * 1000000 + tv . tv_usec ;
# endif
}
2010-12-24 07:00:04 +08:00
double getTickFrequency ( void )
2010-05-12 01:44:00 +08:00
{
2017-07-25 18:23:44 +08:00
# if defined _WIN32 || defined WINCE
2010-05-12 01:44:00 +08:00
LARGE_INTEGER freq ;
QueryPerformanceFrequency ( & freq ) ;
return ( double ) freq . QuadPart ;
# elif defined __linux || defined __linux__
return 1e9 ;
2011-05-31 23:22:22 +08:00
# elif defined __MACH__ && defined __APPLE__
2010-05-12 01:44:00 +08:00
static double freq = 0 ;
if ( freq = = 0 )
{
mach_timebase_info_data_t sTimebaseInfo ;
mach_timebase_info ( & sTimebaseInfo ) ;
freq = sTimebaseInfo . denom * 1e9 / sTimebaseInfo . numer ;
}
2010-12-24 07:00:04 +08:00
return freq ;
2010-05-12 01:44:00 +08:00
# else
return 1e6 ;
# endif
}
2010-12-24 07:00:04 +08:00
# if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
2010-05-12 01:44:00 +08:00
# 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 )
{
2010-12-24 07:00:04 +08:00
int64 result = 0 ;
2010-05-12 01:44:00 +08:00
unsigned upper , lower , tmp ;
__asm__ volatile (
" 0: \n "
" \t mftbu %0 \n "
" \t mftb %1 \n "
" \t mftbu %2 \n "
" \t cmpw %2,%0 \n "
" \t bne 0b \n "
: " =r " ( upper ) , " =r " ( lower ) , " =r " ( tmp )
) ;
return lower | ( ( int64 ) upper < < 32 ) ;
}
# else
# error "RDTSC not defined"
# endif
2017-07-25 18:23:44 +08:00
# elif defined _MSC_VER && defined _WIN32 && defined _M_IX86
2010-05-12 01:44:00 +08:00
int64 getCPUTickCount ( void )
{
__asm _emit 0x0f ;
__asm _emit 0x31 ;
}
# else
2014-03-21 19:27:56 +08:00
//#ifdef HAVE_IPP
//int64 getCPUTickCount(void)
//{
// return ippGetCpuClocks();
//}
//#else
2010-12-24 07:00:04 +08:00
int64 getCPUTickCount ( void )
2010-05-12 01:44:00 +08:00
{
return getTickCount ( ) ;
}
2014-03-21 19:27:56 +08:00
//#endif
2010-05-12 01:44:00 +08:00
# endif
2013-03-23 00:37:49 +08:00
const String & getBuildInformation ( )
2012-04-14 05:50:59 +08:00
{
2013-03-23 00:37:49 +08:00
static String build_info =
2012-04-14 05:50:59 +08:00
# include "version_string.inc"
;
return build_info ;
}
2013-03-23 00:37:49 +08:00
String format ( const char * fmt , . . . )
2010-05-12 01:44:00 +08:00
{
2014-03-25 03:07:00 +08:00
AutoBuffer < char , 1024 > buf ;
2013-03-26 15:54:04 +08:00
2014-03-25 03:07:00 +08:00
for ( ; ; )
2013-03-26 15:54:04 +08:00
{
2014-03-25 03:07:00 +08:00
va_list va ;
2013-03-26 15:54:04 +08:00
va_start ( va , fmt ) ;
2017-05-23 03:24:17 +08:00
int bsize = static_cast < int > ( buf . size ( ) ) ;
2017-06-09 03:53:16 +08:00
int len = cv_vsnprintf ( ( char * ) buf , bsize , fmt , va ) ;
2013-03-26 15:54:04 +08:00
va_end ( va ) ;
2017-06-09 03:53:16 +08:00
CV_Assert ( len > = 0 & & " Check format string for errors " ) ;
if ( len > = bsize )
2014-03-25 03:07:00 +08:00
{
2017-06-09 03:53:16 +08:00
buf . resize ( len + 1 ) ;
2014-03-25 03:07:00 +08:00
continue ;
}
2017-05-23 03:24:17 +08:00
buf [ bsize - 1 ] = 0 ;
2014-03-25 03:07:00 +08:00
return String ( ( char * ) buf , len ) ;
}
2010-05-12 01:44:00 +08:00
}
2013-03-23 00:37:49 +08:00
String tempfile ( const char * suffix )
2011-04-11 22:47:06 +08:00
{
2013-03-23 00:37:49 +08:00
String fname ;
2015-02-21 00:47:45 +08:00
# ifndef WINRT
2014-05-06 04:59:39 +08:00
const char * temp_dir = getenv ( " OPENCV_TEMP_PATH " ) ;
2013-07-19 17:43:05 +08:00
# endif
2012-12-08 19:43:23 +08:00
2017-07-25 18:23:44 +08:00
# if defined _WIN32
2015-02-21 00:47:45 +08:00
# ifdef WINRT
2013-07-19 17:43:05 +08:00
RoInitialize ( RO_INIT_MULTITHREADED ) ;
2015-03-04 15:35:06 +08:00
std : : wstring temp_dir = GetTempPathWinRT ( ) ;
2013-07-19 17:43:05 +08:00
2015-03-04 15:35:06 +08:00
std : : wstring temp_file = GetTempFileNameWinRT ( L " ocv " ) ;
2013-07-19 17:43:05 +08:00
if ( temp_file . empty ( ) )
2014-05-06 04:59:39 +08:00
return String ( ) ;
2013-07-19 17:43:05 +08:00
2015-02-21 00:47:45 +08:00
temp_file = temp_dir . append ( std : : wstring ( L " \\ " ) ) . append ( temp_file ) ;
2013-07-19 17:43:05 +08:00
DeleteFileW ( temp_file . c_str ( ) ) ;
2013-08-19 16:25:53 +08:00
char aname [ MAX_PATH ] ;
size_t copied = wcstombs ( aname , temp_file . c_str ( ) , MAX_PATH ) ;
CV_Assert ( ( copied ! = MAX_PATH ) & & ( copied ! = ( size_t ) - 1 ) ) ;
2014-05-06 04:59:39 +08:00
fname = String ( aname ) ;
2013-07-19 17:43:05 +08:00
RoUninitialize ( ) ;
# else
2013-08-19 16:25:53 +08:00
char temp_dir2 [ MAX_PATH ] = { 0 } ;
char temp_file [ MAX_PATH ] = { 0 } ;
2012-06-25 19:24:06 +08:00
2012-12-08 19:43:23 +08:00
if ( temp_dir = = 0 | | temp_dir [ 0 ] = = 0 )
{
: : GetTempPathA ( sizeof ( temp_dir2 ) , temp_dir2 ) ;
temp_dir = temp_dir2 ;
}
2012-07-02 20:23:57 +08:00
if ( 0 = = : : GetTempFileNameA ( temp_dir , " ocv " , 0 , temp_file ) )
2013-03-23 00:37:49 +08:00
return String ( ) ;
2012-06-25 19:24:06 +08:00
2012-10-04 13:44:29 +08:00
DeleteFileA ( temp_file ) ;
2012-12-08 19:43:23 +08:00
fname = temp_file ;
2013-07-19 17:43:05 +08:00
# endif
2012-06-25 19:24:06 +08:00
# else
2017-07-10 17:43:59 +08:00
# ifdef __ANDROID__
2012-06-25 19:24:06 +08:00
//char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
char defaultTemplate [ ] = " /data/local/tmp/__opencv_temp.XXXXXX " ;
# else
char defaultTemplate [ ] = " /tmp/__opencv_temp.XXXXXX " ;
# endif
2012-12-08 19:43:23 +08:00
if ( temp_dir = = 0 | | temp_dir [ 0 ] = = 0 )
2012-06-25 19:24:06 +08:00
fname = defaultTemplate ;
else
{
fname = temp_dir ;
char ech = fname [ fname . size ( ) - 1 ] ;
if ( ech ! = ' / ' & & ech ! = ' \\ ' )
2013-03-20 21:53:13 +08:00
fname = fname + " / " ;
fname = fname + " __opencv_temp.XXXXXX " ;
2012-06-25 19:24:06 +08:00
}
const int fd = mkstemp ( ( char * ) fname . c_str ( ) ) ;
2013-03-23 00:37:49 +08:00
if ( fd = = - 1 ) return String ( ) ;
2012-12-08 19:43:23 +08:00
2012-06-25 19:24:06 +08:00
close ( fd ) ;
remove ( fname . c_str ( ) ) ;
2012-12-08 19:43:23 +08:00
# endif
2012-06-25 19:24:06 +08:00
2012-12-08 19:43:23 +08:00
if ( suffix )
2012-06-25 19:24:06 +08:00
{
if ( suffix [ 0 ] ! = ' . ' )
2012-12-08 19:43:23 +08:00
return fname + " . " + suffix ;
2012-06-25 19:24:06 +08:00
else
2012-12-08 19:43:23 +08:00
return fname + suffix ;
2012-06-25 19:24:06 +08:00
}
return fname ;
2011-04-11 22:47:06 +08:00
}
2016-11-15 07:33:11 +08:00
static ErrorCallback customErrorCallback = 0 ;
2010-05-12 01:44:00 +08:00
static void * customErrorCallbackData = 0 ;
static bool breakOnError = false ;
bool setBreakOnError ( bool value )
{
bool prevVal = breakOnError ;
breakOnError = value ;
return prevVal ;
2010-12-24 07:00:04 +08:00
}
2010-05-12 01:44:00 +08:00
2017-06-09 03:53:16 +08:00
int cv_snprintf ( char * buf , int len , const char * fmt , . . . )
2017-05-23 03:24:17 +08:00
{
va_list va ;
va_start ( va , fmt ) ;
2017-06-09 03:53:16 +08:00
int res = cv_vsnprintf ( buf , len , fmt , va ) ;
2017-05-23 03:24:17 +08:00
va_end ( va ) ;
2017-06-09 03:53:16 +08:00
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 ) ;
}
2017-05-23 03:24:17 +08:00
# else
2017-06-09 03:53:16 +08:00
return vsnprintf ( buf , len , fmt , args ) ;
2017-05-23 03:24:17 +08:00
# endif
}
2010-05-12 01:44:00 +08:00
void error ( const Exception & exc )
{
2010-12-24 07:00:04 +08:00
if ( customErrorCallback ! = 0 )
2010-05-12 01:44:00 +08:00
customErrorCallback ( exc . code , exc . func . c_str ( ) , exc . err . c_str ( ) ,
exc . file . c_str ( ) , exc . line , customErrorCallbackData ) ;
else
{
const char * errorStr = cvErrorStr ( exc . code ) ;
2017-04-17 13:21:35 +08:00
char buf [ 1 < < 12 ] ;
2010-05-12 01:44:00 +08:00
2017-05-23 03:24:17 +08:00
cv_snprintf ( buf , sizeof ( buf ) ,
" OpenCV Error: %s (%s) in %s, file %s, line %d " ,
2010-05-12 01:44:00 +08:00
errorStr , exc . err . c_str ( ) , exc . func . size ( ) > 0 ?
2017-05-23 03:24:17 +08:00
exc . func . c_str ( ) : " unknown function " , exc . file . c_str ( ) , exc . line ) ;
2010-05-12 01:44:00 +08:00
fprintf ( stderr , " %s \n " , buf ) ;
fflush ( stderr ) ;
2013-01-23 16:27:30 +08:00
# ifdef __ANDROID__
2012-08-08 20:39:24 +08:00
__android_log_print ( ANDROID_LOG_ERROR , " cv::error() " , " %s " , buf ) ;
# endif
2010-05-12 01:44:00 +08:00
}
2010-12-24 07:00:04 +08:00
2010-05-12 01:44:00 +08:00
if ( breakOnError )
{
static volatile int * p = 0 ;
* p = 0 ;
}
2010-12-24 07:00:04 +08:00
2010-05-12 01:44:00 +08:00
throw exc ;
}
2010-12-24 07:00:04 +08:00
2013-03-27 22:43:06 +08:00
void error ( int _code , const String & _err , const char * _func , const char * _file , int _line )
{
error ( cv : : Exception ( _code , _err , _func , _file , _line ) ) ;
}
2017-05-23 03:24:17 +08:00
2016-11-15 07:33:11 +08:00
ErrorCallback
redirectError ( ErrorCallback errCallback , void * userdata , void * * prevUserdata )
2010-05-12 01:44:00 +08:00
{
if ( prevUserdata )
* prevUserdata = customErrorCallbackData ;
2010-12-24 07:00:04 +08:00
2016-11-15 07:33:11 +08:00
ErrorCallback prevCallback = customErrorCallback ;
2010-12-24 07:00:04 +08:00
customErrorCallback = errCallback ;
2010-05-12 01:44:00 +08:00
customErrorCallbackData = userdata ;
2010-12-24 07:00:04 +08:00
2010-05-12 01:44:00 +08:00
return prevCallback ;
}
2010-12-24 07:00:04 +08:00
2010-05-12 01:44:00 +08:00
}
CV_IMPL int cvCheckHardwareSupport ( int feature )
{
CV_DbgAssert ( 0 < = feature & & feature < = CV_HARDWARE_MAX_FEATURE ) ;
2015-12-15 20:55:43 +08:00
return cv : : currentFeatures - > have [ feature ] ;
2010-05-12 01:44:00 +08:00
}
CV_IMPL int cvUseOptimized ( int flag )
{
2015-12-15 20:55:43 +08:00
int prevMode = cv : : useOptimizedFlag ;
2010-05-12 01:44:00 +08:00
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 )
{
2010-12-24 07:00:04 +08:00
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 " ;
2017-02-21 17:48:15 +08:00
case CV_StsDivByZero : return " Division by zero occurred " ;
2010-12-24 07:00:04 +08:00
case CV_BadStep : return " Image step is wrong " ;
2010-05-12 01:44:00 +08:00
case CV_StsInplaceNotSupported : return " Inplace operation is not supported " ;
case CV_StsObjectNotFound : return " Requested object was not found " ;
2010-12-24 07:00:04 +08:00
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 " ;
2013-07-24 17:55:18 +08:00
case CV_GpuNotSupported : return " No CUDA support " ;
2011-11-21 19:58:52 +08:00
case CV_GpuApiCallError : return " Gpu API call " ;
case CV_OpenGlNotSupported : return " No OpenGL support " ;
case CV_OpenGlApiCallError : return " OpenGL API call " ;
2010-05-12 01:44:00 +08:00
} ;
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 ;
}
2010-12-24 07:00:04 +08:00
CV_IMPL int cvGetErrStatus ( void )
2010-05-12 01:44:00 +08:00
{
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 )
{
2010-12-24 07:00:04 +08:00
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 ;
2010-05-12 01:44:00 +08:00
case CV_INPLACE_NOT_SUPPORTED_ERR : return CV_StsInplaceNotSupported ;
2010-12-24 07:00:04 +08:00
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 ;
2010-05-12 01:44:00 +08:00
}
}
2013-12-11 04:31:34 +08:00
namespace cv {
bool __termination = false ;
}
2010-05-12 01:44:00 +08:00
2012-08-17 21:32:06 +08:00
namespace cv
{
2017-07-25 18:23:44 +08:00
# if defined _WIN32 || defined WINCE
2012-08-17 21:32:06 +08:00
struct Mutex : : Impl
{
2013-07-19 17:43:05 +08:00
Impl ( )
{
# if (_WIN32_WINNT >= 0x0600)
: : InitializeCriticalSectionEx ( & cs , 1000 , 0 ) ;
# else
: : InitializeCriticalSection ( & cs ) ;
# endif
refcount = 1 ;
}
2012-08-17 21:32:06 +08:00
~ Impl ( ) { DeleteCriticalSection ( & cs ) ; }
2012-08-17 22:28:50 +08:00
2012-08-17 21:32:06 +08:00
void lock ( ) { EnterCriticalSection ( & cs ) ; }
bool trylock ( ) { return TryEnterCriticalSection ( & cs ) ! = 0 ; }
void unlock ( ) { LeaveCriticalSection ( & cs ) ; }
2012-08-17 22:28:50 +08:00
2012-08-17 21:32:06 +08:00
CRITICAL_SECTION cs ;
int refcount ;
} ;
2012-10-17 07:18:30 +08:00
2012-08-17 21:32:06 +08:00
# else
struct Mutex : : Impl
{
2013-11-22 17:00:37 +08:00
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 ) ; }
2012-08-17 22:28:50 +08:00
2013-11-22 17:00:37 +08:00
void lock ( ) { pthread_mutex_lock ( & mt ) ; }
bool trylock ( ) { return pthread_mutex_trylock ( & mt ) = = 0 ; }
void unlock ( ) { pthread_mutex_unlock ( & mt ) ; }
2012-08-17 22:28:50 +08:00
2013-11-22 17:00:37 +08:00
pthread_mutex_t mt ;
2012-08-17 21:32:06 +08:00
int refcount ;
} ;
# endif
Mutex : : Mutex ( )
{
impl = new Mutex : : Impl ;
}
2012-08-17 22:28:50 +08:00
2012-08-17 21:32:06 +08:00
Mutex : : ~ Mutex ( )
{
if ( CV_XADD ( & impl - > refcount , - 1 ) = = 1 )
delete impl ;
impl = 0 ;
}
2012-08-17 22:28:50 +08:00
2012-08-17 21:32:06 +08:00
Mutex : : Mutex ( const Mutex & m )
{
impl = m . impl ;
CV_XADD ( & impl - > refcount , 1 ) ;
}
Mutex & Mutex : : operator = ( const Mutex & m )
{
2017-06-28 21:26:55 +08:00
if ( this ! = & m )
{
CV_XADD ( & m . impl - > refcount , 1 ) ;
if ( CV_XADD ( & impl - > refcount , - 1 ) = = 1 )
delete impl ;
impl = m . impl ;
}
2012-08-17 21:32:06 +08:00
return * this ;
}
2012-08-17 22:28:50 +08:00
2012-08-17 21:32:06 +08:00
void Mutex : : lock ( ) { impl - > lock ( ) ; }
void Mutex : : unlock ( ) { impl - > unlock ( ) ; }
2012-08-17 22:28:50 +08:00
bool Mutex : : trylock ( ) { return impl - > trylock ( ) ; }
2012-08-17 21:32:06 +08:00
2013-12-11 22:49:13 +08:00
//////////////////////////////// thread-local storage ////////////////////////////////
2017-07-25 18:23:44 +08:00
# ifdef _WIN32
2015-08-12 21:23:02 +08:00
# 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
2013-12-11 22:49:13 +08:00
{
public :
2015-08-12 21:23:02 +08:00
TlsAbstraction ( ) ;
~ TlsAbstraction ( ) ;
void * GetData ( ) const ;
void SetData ( void * pData ) ;
2013-12-11 22:49:13 +08:00
2015-08-12 21:23:02 +08:00
private :
2017-07-25 18:23:44 +08:00
# ifdef _WIN32
2015-08-12 21:23:02 +08:00
# ifndef WINRT
DWORD tlsKey ;
2013-12-30 16:31:00 +08:00
# endif
2017-07-25 18:23:44 +08:00
# else // _WIN32
2015-08-12 21:23:02 +08:00
pthread_key_t tlsKey ;
# endif
} ;
2013-12-11 22:49:13 +08:00
2017-07-25 18:23:44 +08:00
# ifdef _WIN32
2015-02-21 00:47:45 +08:00
# ifdef WINRT
2015-08-12 21:23:02 +08:00
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
2017-07-25 18:23:44 +08:00
# else // _WIN32
2015-08-12 21:23:02 +08:00
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
2013-12-11 22:49:13 +08:00
2015-08-12 21:23:02 +08:00
// Per-thread data structure
struct ThreadData
{
ThreadData ( )
2013-12-11 22:49:13 +08:00
{
2015-08-12 21:23:02 +08:00
idx = 0 ;
slots . reserve ( 32 ) ;
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
std : : vector < void * > slots ; // Data array for a thread
size_t idx ; // Thread index in TLS storage. This is not OS thread ID!
} ;
2013-12-11 22:49:13 +08:00
2015-08-12 21:23:02 +08:00
// Main TLS storage class
class TlsStorage
{
public :
2017-07-27 03:45:55 +08:00
TlsStorage ( ) :
tlsSlotsSize ( 0 )
2013-12-11 22:49:13 +08:00
{
2015-09-16 19:00:36 +08:00
tlsSlots . reserve ( 32 ) ;
2015-08-12 21:23:02 +08:00
threads . reserve ( 32 ) ;
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
~ TlsStorage ( )
2013-12-11 22:49:13 +08:00
{
2015-08-12 21:23:02 +08:00
for ( size_t i = 0 ; i < threads . size ( ) ; i + + )
2013-12-11 22:49:13 +08:00
{
2015-08-12 21:23:02 +08:00
if ( threads [ i ] )
{
2017-02-21 17:48:15 +08:00
/* Current architecture doesn't allow proper global objects release, so this check can cause crashes
2015-08-12 21:23:02 +08:00
// 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 ] ;
}
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
threads . clear ( ) ;
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
void releaseThread ( )
2013-12-11 22:49:13 +08:00
{
2015-08-12 21:23:02 +08:00
AutoLock guard ( mtxGlobalAccess ) ;
ThreadData * pTD = ( ThreadData * ) tls . GetData ( ) ;
for ( size_t i = 0 ; i < threads . size ( ) ; i + + )
2014-03-25 04:38:57 +08:00
{
2015-08-12 21:23:02 +08:00
if ( pTD = = threads [ i ] )
{
threads [ i ] = 0 ;
break ;
}
2014-03-25 04:38:57 +08:00
}
2015-08-12 21:23:02 +08:00
tls . SetData ( 0 ) ;
delete pTD ;
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
// Reserve TLS storage index
size_t reserveSlot ( )
2013-12-11 22:49:13 +08:00
{
2015-08-12 21:23:02 +08:00
AutoLock guard ( mtxGlobalAccess ) ;
2017-07-27 03:45:55 +08:00
CV_Assert ( tlsSlotsSize = = tlsSlots . size ( ) ) ;
2015-09-16 19:00:36 +08:00
// Find unused slots
2017-07-27 03:45:55 +08:00
for ( size_t slot = 0 ; slot < tlsSlotsSize ; slot + + )
2015-09-16 19:00:36 +08:00
{
if ( ! tlsSlots [ slot ] )
{
tlsSlots [ slot ] = 1 ;
return slot ;
}
}
// Create new slot
2017-07-27 03:45:55 +08:00
tlsSlots . push_back ( 1 ) ; tlsSlotsSize + + ;
return tlsSlotsSize - 1 ;
2013-12-11 22:49:13 +08:00
}
2017-02-21 17:48:15 +08:00
// Release TLS storage index and pass associated data to caller
2017-02-16 01:20:38 +08:00
void releaseSlot ( size_t slotIdx , std : : vector < void * > & dataVec , bool keepSlot = false )
2013-12-11 22:49:13 +08:00
{
2015-08-12 21:23:02 +08:00
AutoLock guard ( mtxGlobalAccess ) ;
2017-07-27 03:45:55 +08:00
CV_Assert ( tlsSlotsSize = = tlsSlots . size ( ) ) ;
CV_Assert ( tlsSlotsSize > slotIdx ) ;
2013-12-11 22:49:13 +08:00
2015-08-12 21:23:02 +08:00
for ( size_t i = 0 ; i < threads . size ( ) ; i + + )
2013-12-11 22:49:13 +08:00
{
2016-01-14 19:38:37 +08:00
if ( threads [ i ] )
2015-08-12 21:23:02 +08:00
{
2016-01-14 19:38:37 +08:00
std : : vector < void * > & thread_slots = threads [ i ] - > slots ;
if ( thread_slots . size ( ) > slotIdx & & thread_slots [ slotIdx ] )
{
dataVec . push_back ( thread_slots [ slotIdx ] ) ;
2017-02-16 01:20:38 +08:00
thread_slots [ slotIdx ] = NULL ;
2016-01-14 19:38:37 +08:00
}
2015-08-12 21:23:02 +08:00
}
2013-12-11 22:49:13 +08:00
}
2015-09-16 19:00:36 +08:00
2017-02-16 01:20:38 +08:00
if ( ! keepSlot )
tlsSlots [ slotIdx ] = 0 ;
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
// Get data by TLS storage index
void * getData ( size_t slotIdx ) const
2013-12-11 22:49:13 +08:00
{
2017-07-27 22:31:51 +08:00
# ifndef CV_THREAD_SANITIZER
2017-07-27 03:45:55 +08:00
CV_Assert ( tlsSlotsSize > slotIdx ) ;
2017-07-27 22:31:51 +08:00
# endif
2013-12-11 22:49:13 +08:00
2015-08-12 21:23:02 +08:00
ThreadData * threadData = ( ThreadData * ) tls . GetData ( ) ;
if ( threadData & & threadData - > slots . size ( ) > slotIdx )
return threadData - > slots [ slotIdx ] ;
return NULL ;
2013-12-11 22:49:13 +08:00
}
2015-09-16 19:00:36 +08:00
// Gather data from threads by TLS storage index
void gather ( size_t slotIdx , std : : vector < void * > & dataVec )
{
AutoLock guard ( mtxGlobalAccess ) ;
2017-07-27 03:45:55 +08:00
CV_Assert ( tlsSlotsSize = = tlsSlots . size ( ) ) ;
CV_Assert ( tlsSlotsSize > slotIdx ) ;
2015-09-16 19:00:36 +08:00
for ( size_t i = 0 ; i < threads . size ( ) ; i + + )
{
2016-01-14 19:38:37 +08:00
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 ] ) ;
}
2015-09-16 19:00:36 +08:00
}
}
2015-08-12 21:23:02 +08:00
// Set data to storage index
void setData ( size_t slotIdx , void * pData )
2013-12-11 22:49:13 +08:00
{
2017-07-27 22:31:51 +08:00
# ifndef CV_THREAD_SANITIZER
2017-07-27 03:45:55 +08:00
CV_Assert ( tlsSlotsSize > slotIdx ) ;
2017-07-27 22:31:51 +08:00
# endif
2015-08-12 21:23:02 +08:00
ThreadData * threadData = ( ThreadData * ) tls . GetData ( ) ;
if ( ! threadData )
2013-12-11 22:49:13 +08:00
{
2015-08-12 21:23:02 +08:00
threadData = new ThreadData ;
tls . SetData ( ( void * ) threadData ) ;
{
AutoLock guard ( mtxGlobalAccess ) ;
threadData - > idx = threads . size ( ) ;
threads . push_back ( threadData ) ;
}
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
if ( slotIdx > = threadData - > slots . size ( ) )
2015-09-16 19:00:36 +08:00
{
2017-07-27 03:45:55 +08:00
AutoLock guard ( mtxGlobalAccess ) ; // keep synchronization with gather() calls
threadData - > slots . resize ( slotIdx + 1 , NULL ) ;
2015-09-16 19:00:36 +08:00
}
2015-08-12 21:23:02 +08:00
threadData - > slots [ slotIdx ] = pData ;
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
private :
TlsAbstraction tls ; // TLS abstraction layer instance
Mutex mtxGlobalAccess ; // Shared objects operation guard
2017-07-27 03:45:55 +08:00
size_t tlsSlotsSize ; // equal to tlsSlots.size() in synchronized sections
// without synchronization this counter doesn't desrease - it is used for slotIdx sanity checks
2015-09-16 19:00:36 +08:00
std : : vector < int > tlsSlots ; // TLS keys state
2015-08-12 21:23:02 +08:00
std : : vector < ThreadData * > threads ; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup
2013-12-11 22:49:13 +08:00
} ;
2014-01-19 07:39:50 +08:00
2015-08-12 21:23:02 +08:00
// Create global TLS storage object
static TlsStorage & getTlsStorage ( )
2014-01-19 07:39:50 +08:00
{
2015-08-12 21:23:02 +08:00
CV_SINGLETON_LAZY_INIT_REF ( TlsStorage , new TlsStorage ( ) )
2014-01-19 07:39:50 +08:00
}
2013-12-11 22:49:13 +08:00
TLSDataContainer : : TLSDataContainer ( )
{
2015-08-12 21:23:02 +08:00
key_ = ( int ) getTlsStorage ( ) . reserveSlot ( ) ; // Reserve key from TLS storage
2012-08-17 21:32:06 +08:00
}
2013-12-11 22:49:13 +08:00
TLSDataContainer : : ~ TLSDataContainer ( )
{
2015-08-12 21:23:02 +08:00
CV_Assert ( key_ = = - 1 ) ; // Key must be released in child object
2013-12-11 22:49:13 +08:00
}
2015-09-16 19:00:36 +08:00
void TLSDataContainer : : gatherData ( std : : vector < void * > & data ) const
{
getTlsStorage ( ) . gather ( key_ , data ) ;
}
2015-08-12 21:23:02 +08:00
void TLSDataContainer : : release ( )
2013-12-11 22:49:13 +08:00
{
2015-08-12 21:23:02 +08:00
std : : vector < void * > data ;
data . reserve ( 32 ) ;
getTlsStorage ( ) . releaseSlot ( key_ , data ) ; // Release key and get stored data for proper destruction
2017-02-16 01:20:38 +08:00
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
2017-02-21 17:48:15 +08:00
for ( size_t i = 0 ; i < data . size ( ) ; i + + ) // Delete all associated data
2015-08-12 21:23:02 +08:00
deleteDataInstance ( data [ i ] ) ;
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
void * TLSDataContainer : : getData ( ) const
2013-12-11 22:49:13 +08:00
{
2017-05-25 23:59:01 +08:00
CV_Assert ( key_ ! = - 1 & & " Can't fetch data from terminated TLS container. " ) ;
2015-08-12 21:23:02 +08:00
void * pData = getTlsStorage ( ) . getData ( key_ ) ; // Check if data was already allocated
if ( ! pData )
2013-12-11 22:49:13 +08:00
{
2015-08-12 21:23:02 +08:00
// Create new data instance and save it to TLS storage
pData = createDataInstance ( ) ;
getTlsStorage ( ) . setData ( key_ , pData ) ;
2013-12-11 22:49:13 +08:00
}
2015-08-12 21:23:02 +08:00
return pData ;
2013-12-11 22:49:13 +08:00
}
2015-02-04 18:03:27 +08:00
TLSData < CoreTLSData > & getCoreTlsData ( )
{
2015-06-23 19:31:01 +08:00
CV_SINGLETON_LAZY_INIT_REF ( TLSData < CoreTLSData > , new TLSData < CoreTLSData > ( ) )
2015-02-04 18:03:27 +08:00
}
2017-07-25 18:23:44 +08:00
# if defined CVAPI_EXPORTS && defined _WIN32 && !defined WINCE
2015-08-12 21:23:02 +08:00
# ifdef WINRT
# pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
# endif
2015-09-01 05:59:08 +08:00
extern " C "
BOOL WINAPI DllMain ( HINSTANCE , DWORD fdwReason , LPVOID lpReserved ) ;
2015-08-12 21:23:02 +08:00
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
2015-02-04 18:03:27 +08:00
2017-05-25 23:59:01 +08:00
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 ;
}
2014-10-03 19:17:28 +08:00
# ifdef CV_COLLECT_IMPL_DATA
2015-03-12 22:58:03 +08:00
ImplCollector & getImplData ( )
{
2015-06-23 19:31:01 +08:00
CV_SINGLETON_LAZY_INIT_REF ( ImplCollector , new ImplCollector ( ) )
2015-03-12 22:58:03 +08:00
}
2014-10-03 19:17:28 +08:00
void setImpl ( int flags )
{
2015-03-12 22:58:03 +08:00
cv : : AutoLock lock ( getImplData ( ) . mutex ) ;
getImplData ( ) . implFlags = flags ;
getImplData ( ) . implCode . clear ( ) ;
getImplData ( ) . implFun . clear ( ) ;
2014-10-03 19:17:28 +08:00
}
void addImpl ( int flag , const char * func )
{
2015-03-12 22:58:03 +08:00
cv : : AutoLock lock ( getImplData ( ) . mutex ) ;
getImplData ( ) . implFlags | = flag ;
2014-10-03 19:17:28 +08:00
if ( func ) // use lazy collection if name was not specified
{
2015-03-12 22:58:03 +08:00
size_t index = getImplData ( ) . implCode . size ( ) ;
if ( ! index | | ( getImplData ( ) . implCode [ index - 1 ] ! = flag | | getImplData ( ) . implFun [ index - 1 ] . compare ( func ) ) ) // avoid duplicates
2014-10-03 19:17:28 +08:00
{
2015-03-12 22:58:03 +08:00
getImplData ( ) . implCode . push_back ( flag ) ;
getImplData ( ) . implFun . push_back ( func ) ;
2014-10-03 19:17:28 +08:00
}
}
}
int getImpl ( std : : vector < int > & impl , std : : vector < String > & funName )
{
2015-03-12 22:58:03 +08:00
cv : : AutoLock lock ( getImplData ( ) . mutex ) ;
impl = getImplData ( ) . implCode ;
funName = getImplData ( ) . implFun ;
return getImplData ( ) . implFlags ; // return actual flags for lazy collection
2014-10-03 19:17:28 +08:00
}
bool useCollection ( )
{
2015-03-12 22:58:03 +08:00
return getImplData ( ) . useCollection ;
2014-10-03 19:17:28 +08:00
}
void setUseCollection ( bool flag )
{
2015-03-12 22:58:03 +08:00
cv : : AutoLock lock ( getImplData ( ) . mutex ) ;
getImplData ( ) . useCollection = flag ;
2014-10-03 19:17:28 +08:00
}
# endif
2016-08-15 22:12:45 +08:00
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
}
2016-08-25 22:26:46 +08:00
void setFlags ( FLAGS modeFlags )
2016-08-15 22:12:45 +08:00
{
# ifdef ENABLE_INSTRUMENTATION
2016-11-07 17:15:51 +08:00
getInstrumentStruct ( ) . flags = modeFlags ;
2016-08-15 22:12:45 +08:00
# else
CV_UNUSED ( modeFlags ) ;
# endif
}
2016-08-25 22:26:46 +08:00
FLAGS getFlags ( )
2016-08-15 22:12:45 +08:00
{
# ifdef ENABLE_INSTRUMENTATION
2016-11-07 17:15:51 +08:00
return ( FLAGS ) getInstrumentStruct ( ) . flags ;
2016-08-15 22:12:45 +08:00
# else
2016-08-25 22:26:46 +08:00
return ( FLAGS ) 0 ;
2016-08-15 22:12:45 +08:00
# endif
}
2016-11-07 17:15:51 +08:00
NodeData : : NodeData ( const char * funName , const char * fileName , int lineNum , void * retAddress , bool alwaysExpand , cv : : instr : : TYPE instrType , cv : : instr : : IMPL implType )
2016-08-15 22:12:45 +08:00
{
2016-11-07 17:15:51 +08:00
m_funName = funName ;
m_instrType = instrType ;
m_implType = implType ;
m_fileName = fileName ;
m_lineNum = lineNum ;
m_retAddress = retAddress ;
m_alwaysExpand = alwaysExpand ;
2016-08-15 22:12:45 +08:00
2016-11-07 17:15:51 +08:00
m_threads = 1 ;
m_counter = 0 ;
2016-08-25 22:26:46 +08:00
m_ticksTotal = 0 ;
2016-11-07 17:15:51 +08:00
m_funError = false ;
2016-08-15 22:12:45 +08:00
}
NodeData : : NodeData ( NodeData & ref )
{
* this = ref ;
}
NodeData & NodeData : : operator = ( const NodeData & right )
{
2016-11-07 17:15:51 +08:00
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 ;
2016-08-25 22:26:46 +08:00
this - > m_counter = right . m_counter ;
this - > m_ticksTotal = right . m_ticksTotal ;
2016-11-07 17:15:51 +08:00
2016-08-25 22:26:46 +08:00
this - > m_funError = right . m_funError ;
2016-11-07 17:15:51 +08:00
2016-08-15 22:12:45 +08:00
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 )
2016-11-07 17:15:51 +08:00
{
if ( left . m_retAddress = = right . m_retAddress | | ! ( cv : : instr : : getFlags ( ) & cv : : instr : : FLAGS_EXPAND_SAME_NAMES | | left . m_alwaysExpand ) )
return true ;
}
2016-08-15 22:12:45 +08:00
return false ;
}
# ifdef ENABLE_INSTRUMENTATION
InstrStruct & getInstrumentStruct ( )
{
static InstrStruct instr ;
return instr ;
}
InstrTLSStruct & getInstrumentTLSStruct ( )
{
return * getInstrumentStruct ( ) . tlsStruct . get ( ) ;
}
InstrNode * getCurrentNode ( )
{
return getInstrumentTLSStruct ( ) . pCurrentNode ;
}
2016-11-07 17:15:51 +08:00
IntrumentationRegion : : IntrumentationRegion ( const char * funName , const char * fileName , int lineNum , void * retAddress , bool alwaysExpand , TYPE instrType , IMPL implType )
2016-08-15 22:12:45 +08:00
{
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 ;
}
2016-11-07 17:15:51 +08:00
int depth = pTLS - > pCurrentNode - > getDepth ( ) ;
if ( pStruct - > maxDepth & & pStruct - > maxDepth < = depth )
{
m_disabled = true ;
2016-08-15 22:12:45 +08:00
return ;
2016-11-07 17:15:51 +08:00
}
2016-08-15 22:12:45 +08:00
2016-11-07 17:15:51 +08:00
NodeData payload ( funName , fileName , lineNum , retAddress , alwaysExpand , instrType , implType ) ;
2016-08-15 22:12:45 +08:00
Node < NodeData > * pChild = NULL ;
2016-11-07 17:15:51 +08:00
if ( pStruct - > flags & FLAGS_MAPPING )
2016-08-15 22:12:45 +08:00
{
// 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 )
{
2016-11-07 17:15:51 +08:00
m_disabled = true ;
2016-08-15 22:12:45 +08:00
return ;
}
}
pTLS - > pCurrentNode = pChild ;
m_regionTicks = getTickCount ( ) ;
}
}
IntrumentationRegion : : ~ IntrumentationRegion ( )
{
InstrStruct * pStruct = & getInstrumentStruct ( ) ;
if ( pStruct - > useInstr )
{
if ( ! m_disabled )
{
InstrTLSStruct * pTLS = & getInstrumentTLSStruct ( ) ;
2016-11-07 17:15:51 +08:00
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 ) )
2016-08-15 22:12:45 +08:00
{
2016-11-07 17:15:51 +08:00
cv : : ocl : : finish ( ) ; // TODO Support "async" OpenCL instrumentation
2016-08-15 22:12:45 +08:00
}
2016-11-07 17:15:51 +08:00
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 ;
2016-08-15 22:12:45 +08:00
}
2016-11-07 17:15:51 +08:00
pTLS - > pCurrentNode = pTLS - > pCurrentNode - > m_pParent ;
2016-08-15 22:12:45 +08:00
}
}
}
# endif
}
2014-04-17 19:21:30 +08:00
namespace ipp
{
2017-04-13 20:50:23 +08:00
# ifdef HAVE_IPP
2016-08-12 14:50:42 +08:00
struct IPPInitSingleton
2015-09-25 23:00:53 +08:00
{
public :
2016-08-12 14:50:42 +08:00
IPPInitSingleton ( )
2015-09-25 23:00:53 +08:00
{
2017-04-13 20:50:23 +08:00
useIPP = true ;
ippStatus = 0 ;
funcname = NULL ;
filename = NULL ;
linen = 0 ;
ippFeatures = 0 ;
2015-09-25 23:00:53 +08:00
const char * pIppEnv = getenv ( " OPENCV_IPP " ) ;
cv : : String env = pIppEnv ;
if ( env . size ( ) )
{
if ( env = = " disabled " )
{
std : : cerr < < " WARNING: IPP was disabled by OPENCV_IPP environment variable " < < std : : endl ;
useIPP = false ;
}
# if IPP_VERSION_X100 >= 900
else if ( env = = " sse " )
ippFeatures = ippCPUID_SSE ;
else if ( env = = " sse2 " )
ippFeatures = ippCPUID_SSE2 ;
2015-10-12 15:51:28 +08:00
else if ( env = = " sse3 " )
ippFeatures = ippCPUID_SSE3 ;
else if ( env = = " ssse3 " )
ippFeatures = ippCPUID_SSSE3 ;
else if ( env = = " sse41 " )
ippFeatures = ippCPUID_SSE41 ;
2015-09-25 23:00:53 +08:00
else if ( env = = " sse42 " )
ippFeatures = ippCPUID_SSE42 ;
else if ( env = = " avx " )
ippFeatures = ippCPUID_AVX ;
else if ( env = = " avx2 " )
ippFeatures = ippCPUID_AVX2 ;
# endif
else
std : : cerr < < " ERROR: Improper value of OPENCV_IPP: " < < env . c_str ( ) < < std : : endl ;
}
IPP_INITIALIZER ( ippFeatures )
2017-04-13 20:50:23 +08:00
ippFeatures = ippGetEnabledCpuFeatures ( ) ;
2015-09-25 23:00:53 +08:00
}
bool useIPP ;
int ippStatus ; // 0 - all is ok, -1 - IPP functions failed
const char * funcname ;
const char * filename ;
int linen ;
2017-04-13 20:50:23 +08:00
Ipp64u ippFeatures ;
2015-09-25 23:00:53 +08:00
} ;
2016-08-12 14:50:42 +08:00
static IPPInitSingleton & getIPPSingleton ( )
2015-09-25 23:00:53 +08:00
{
2016-08-12 14:50:42 +08:00
CV_SINGLETON_LAZY_INIT_REF ( IPPInitSingleton , new IPPInitSingleton ( ) )
2015-09-25 23:00:53 +08:00
}
2017-04-13 20:50:23 +08:00
# endif
2015-09-25 23:00:53 +08:00
2017-04-13 20:50:23 +08:00
# if OPENCV_ABI_COMPATIBILITY > 300
unsigned long long getIppFeatures ( )
# else
2015-09-25 23:00:53 +08:00
int getIppFeatures ( )
2017-04-13 20:50:23 +08:00
# endif
2015-09-25 23:00:53 +08:00
{
# ifdef HAVE_IPP
2017-04-13 20:50:23 +08:00
# if OPENCV_ABI_COMPATIBILITY > 300
2016-08-12 14:50:42 +08:00
return getIPPSingleton ( ) . ippFeatures ;
2017-04-13 20:50:23 +08:00
# else
return ( int ) getIPPSingleton ( ) . ippFeatures ;
# endif
2015-09-25 23:00:53 +08:00
# else
return 0 ;
# endif
}
2014-04-16 22:50:23 +08:00
void setIppStatus ( int status , const char * const _funcname , const char * const _filename , int _line )
2014-04-16 19:34:18 +08:00
{
2017-04-13 20:50:23 +08:00
# ifdef HAVE_IPP
2016-08-12 14:50:42 +08:00
getIPPSingleton ( ) . ippStatus = status ;
getIPPSingleton ( ) . funcname = _funcname ;
getIPPSingleton ( ) . filename = _filename ;
getIPPSingleton ( ) . linen = _line ;
2017-04-13 20:50:23 +08:00
# else
CV_UNUSED ( status ) ; CV_UNUSED ( _funcname ) ; CV_UNUSED ( _filename ) ; CV_UNUSED ( _line ) ;
# endif
2014-04-16 19:34:18 +08:00
}
int getIppStatus ( )
{
2017-04-13 20:50:23 +08:00
# ifdef HAVE_IPP
2016-08-12 14:50:42 +08:00
return getIPPSingleton ( ) . ippStatus ;
2017-04-13 20:50:23 +08:00
# else
return 0 ;
# endif
2014-04-16 22:50:23 +08:00
}
String getIppErrorLocation ( )
{
2017-04-13 20:50:23 +08:00
# ifdef HAVE_IPP
2016-08-12 14:50:42 +08:00
return format ( " %s:%d %s " , getIPPSingleton ( ) . filename ? getIPPSingleton ( ) . filename : " " , getIPPSingleton ( ) . linen , getIPPSingleton ( ) . funcname ? getIPPSingleton ( ) . funcname : " " ) ;
2017-04-13 20:50:23 +08:00
# else
return String ( ) ;
# endif
2014-04-16 19:34:18 +08:00
}
2014-10-03 19:17:28 +08:00
bool useIPP ( )
{
# ifdef HAVE_IPP
2015-02-04 18:03:27 +08:00
CoreTLSData * data = getCoreTlsData ( ) . get ( ) ;
2014-10-03 19:17:28 +08:00
if ( data - > useIPP < 0 )
{
2016-08-12 14:50:42 +08:00
data - > useIPP = getIPPSingleton ( ) . useIPP ;
2014-10-03 19:17:28 +08:00
}
return ( data - > useIPP > 0 ) ;
# else
return false ;
# endif
}
void setUseIPP ( bool flag )
{
2015-02-04 18:03:27 +08:00
CoreTLSData * data = getCoreTlsData ( ) . get ( ) ;
2014-10-03 19:17:28 +08:00
# ifdef HAVE_IPP
2016-08-12 14:50:42 +08:00
data - > useIPP = ( getIPPSingleton ( ) . useIPP ) ? flag : false ;
2014-10-03 19:17:28 +08:00
# else
( void ) flag ;
data - > useIPP = false ;
# endif
}
2014-04-17 19:21:30 +08:00
} // namespace ipp
2015-02-27 17:52:11 +08:00
} // namespace cv
2015-02-27 00:34:20 +08:00
# ifdef HAVE_TEGRA_OPTIMIZATION
namespace tegra {
bool useTegra ( )
{
2015-02-27 17:52:11 +08:00
cv : : CoreTLSData * data = cv : : getCoreTlsData ( ) . get ( ) ;
2015-02-27 00:34:20 +08:00
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 )
{
2015-02-27 17:52:11 +08:00
cv : : CoreTLSData * data = cv : : getCoreTlsData ( ) . get ( ) ;
2015-02-27 00:34:20 +08:00
data - > useTegra = flag ;
}
} // namespace tegra
# endif
2013-07-10 21:43:46 +08:00
/* End of file. */