mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -326,6 +326,13 @@ enum CpuFeatures {
|
||||
|
||||
#include "cv_cpu_dispatch.h"
|
||||
|
||||
#if !defined(CV_STRONG_ALIGNMENT) && defined(__arm__) && !(defined(__aarch64__) || defined(_M_ARM64))
|
||||
// int*, int64* should be propertly aligned pointers on ARMv7
|
||||
#define CV_STRONG_ALIGNMENT 1
|
||||
#endif
|
||||
#if !defined(CV_STRONG_ALIGNMENT)
|
||||
#define CV_STRONG_ALIGNMENT 0
|
||||
#endif
|
||||
|
||||
/* fundamental constants */
|
||||
#define CV_PI 3.1415926535897932384626433832795
|
||||
|
||||
@@ -1458,16 +1458,23 @@ template<typename _Tp, int n> inline void v_zip( const v_reg<_Tp, n>& a0, const
|
||||
@return register object
|
||||
|
||||
@note Returned type will be detected from passed pointer type, for example uchar ==> cv::v_uint8x16, int ==> cv::v_int32x4, etc.
|
||||
|
||||
@note Alignment requirement:
|
||||
if CV_STRONG_ALIGNMENT=1 then passed pointer must be aligned (`sizeof(lane type)` should be enough).
|
||||
Do not cast pointer types without runtime check for pointer alignment (like `uchar*` => `int*`).
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load(const _Tp* ptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
return v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128>(ptr);
|
||||
}
|
||||
|
||||
/** @brief Load register contents from memory (aligned)
|
||||
|
||||
similar to cv::v_load, but source memory block should be aligned (to 16-byte boundary)
|
||||
similar to cv::v_load, but source memory block should be aligned (to 16-byte boundary in case of SIMD128, 32-byte - SIMD256, etc)
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_aligned(const _Tp* ptr)
|
||||
@@ -1488,6 +1495,9 @@ v_int32x4 r = v_load_low(lo);
|
||||
template<typename _Tp>
|
||||
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_low(const _Tp* ptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
|
||||
for( int i = 0; i < c.nlanes/2; i++ )
|
||||
{
|
||||
@@ -1509,6 +1519,10 @@ v_int32x4 r = v_load_halves(lo, hi);
|
||||
template<typename _Tp>
|
||||
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_halves(const _Tp* loptr, const _Tp* hiptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(loptr));
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(hiptr));
|
||||
#endif
|
||||
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
|
||||
for( int i = 0; i < c.nlanes/2; i++ )
|
||||
{
|
||||
@@ -1531,6 +1545,9 @@ template<typename _Tp>
|
||||
inline v_reg<typename V_TypeTraits<_Tp>::w_type, V_TypeTraits<_Tp>::nlanes128 / 2>
|
||||
v_load_expand(const _Tp* ptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
typedef typename V_TypeTraits<_Tp>::w_type w_type;
|
||||
v_reg<w_type, V_TypeTraits<w_type>::nlanes128> c;
|
||||
for( int i = 0; i < c.nlanes; i++ )
|
||||
@@ -1552,6 +1569,9 @@ template<typename _Tp>
|
||||
inline v_reg<typename V_TypeTraits<_Tp>::q_type, V_TypeTraits<_Tp>::nlanes128 / 4>
|
||||
v_load_expand_q(const _Tp* ptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
typedef typename V_TypeTraits<_Tp>::q_type q_type;
|
||||
v_reg<q_type, V_TypeTraits<q_type>::nlanes128> c;
|
||||
for( int i = 0; i < c.nlanes; i++ )
|
||||
@@ -1572,6 +1592,9 @@ For all types except 64-bit. */
|
||||
template<typename _Tp, int n> inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a,
|
||||
v_reg<_Tp, n>& b)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i2;
|
||||
for( i = i2 = 0; i < n; i++, i2 += 2 )
|
||||
{
|
||||
@@ -1591,6 +1614,9 @@ For all types except 64-bit. */
|
||||
template<typename _Tp, int n> inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a,
|
||||
v_reg<_Tp, n>& b, v_reg<_Tp, n>& c)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i3;
|
||||
for( i = i3 = 0; i < n; i++, i3 += 3 )
|
||||
{
|
||||
@@ -1613,6 +1639,9 @@ inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a,
|
||||
v_reg<_Tp, n>& b, v_reg<_Tp, n>& c,
|
||||
v_reg<_Tp, n>& d)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i4;
|
||||
for( i = i4 = 0; i < n; i++, i4 += 4 )
|
||||
{
|
||||
@@ -1636,6 +1665,9 @@ inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a,
|
||||
const v_reg<_Tp, n>& b,
|
||||
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i2;
|
||||
for( i = i2 = 0; i < n; i++, i2 += 2 )
|
||||
{
|
||||
@@ -1657,6 +1689,9 @@ inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a,
|
||||
const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c,
|
||||
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i3;
|
||||
for( i = i3 = 0; i < n; i++, i3 += 3 )
|
||||
{
|
||||
@@ -1679,6 +1714,9 @@ template<typename _Tp, int n> inline void v_store_interleave( _Tp* ptr, const v_
|
||||
const v_reg<_Tp, n>& d,
|
||||
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i4;
|
||||
for( i = i4 = 0; i < n; i++, i4 += 4 )
|
||||
{
|
||||
@@ -1700,6 +1738,9 @@ Pointer can be unaligned. */
|
||||
template<typename _Tp, int n>
|
||||
inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
for( int i = 0; i < n; i++ )
|
||||
ptr[i] = a.s[i];
|
||||
}
|
||||
@@ -1707,6 +1748,9 @@ inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a)
|
||||
template<typename _Tp, int n>
|
||||
inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a, hal::StoreMode /*mode*/)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
v_store(ptr, a);
|
||||
}
|
||||
|
||||
@@ -1720,6 +1764,9 @@ Scheme:
|
||||
template<typename _Tp, int n>
|
||||
inline void v_store_low(_Tp* ptr, const v_reg<_Tp, n>& a)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
for( int i = 0; i < (n/2); i++ )
|
||||
ptr[i] = a.s[i];
|
||||
}
|
||||
@@ -1734,6 +1781,9 @@ Scheme:
|
||||
template<typename _Tp, int n>
|
||||
inline void v_store_high(_Tp* ptr, const v_reg<_Tp, n>& a)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
for( int i = 0; i < (n/2); i++ )
|
||||
ptr[i] = a.s[i+(n/2)];
|
||||
}
|
||||
|
||||
@@ -449,7 +449,7 @@ Returned value is a string containing space separated list of CPU features with
|
||||
|
||||
Example: `SSE SSE2 SSE3 *SSE4.1 *SSE4.2 *FP16 *AVX *AVX2 *AVX512-SKX?`
|
||||
*/
|
||||
CV_EXPORTS std::string getCPUFeaturesLine();
|
||||
CV_EXPORTS_W std::string getCPUFeaturesLine();
|
||||
|
||||
/** @brief Returns the number of logical CPUs available for the process.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#ifndef OPENCV_UTILS_BUFFER_AREA_HPP
|
||||
#define OPENCV_UTILS_BUFFER_AREA_HPP
|
||||
|
||||
#include <opencv2/core/base.hpp>
|
||||
#include <opencv2/core/private.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace cv { namespace utils {
|
||||
|
||||
//! @addtogroup core_utils
|
||||
//! @{
|
||||
|
||||
/** @brief Manages memory block shared by muliple buffers.
|
||||
|
||||
This class allows to allocate one large memory block and split it into several smaller
|
||||
non-overlapping buffers. In safe mode each buffer allocation will be performed independently,
|
||||
this mode allows dynamic memory access instrumentation using valgrind or memory sanitizer.
|
||||
|
||||
Safe mode can be explicitly switched ON in constructor. It will also be enabled when compiling with
|
||||
memory sanitizer support or in runtime with the environment variable `OPENCV_BUFFER_AREA_ALWAYS_SAFE`.
|
||||
|
||||
Example of usage:
|
||||
@code
|
||||
int * buf1 = 0;
|
||||
double * buf2 = 0;
|
||||
cv::util::BufferArea area;
|
||||
area.allocate(buf1, 200); // buf1 = new int[200];
|
||||
area.allocate(buf2, 1000, 64); // buf2 = new double[1000]; - aligned by 64
|
||||
area.commit();
|
||||
@endcode
|
||||
|
||||
@note This class is considered private and should be used only in OpenCV itself. API can be changed.
|
||||
*/
|
||||
class CV_EXPORTS BufferArea
|
||||
{
|
||||
public:
|
||||
/** @brief Class constructor.
|
||||
|
||||
@param safe Enable _safe_ operation mode, each allocation will be performed independently.
|
||||
*/
|
||||
BufferArea(bool safe = false);
|
||||
|
||||
/** @brief Class destructor
|
||||
|
||||
All allocated memory well be freed. Each bound pointer will be reset to NULL.
|
||||
*/
|
||||
~BufferArea();
|
||||
|
||||
/** @brief Bind a pointer to local area.
|
||||
|
||||
BufferArea will store reference to the pointer and allocation parameters effectively owning the
|
||||
pointer and allocated memory. This operation has the same parameters and does the same job
|
||||
as the operator `new`, except allocation can be performed later during the BufferArea::commit call.
|
||||
|
||||
@param ptr Reference to a pointer of type T. Must be NULL
|
||||
@param count Count of objects to be allocated, it has the same meaning as in the operator `new`.
|
||||
@param alignment Alignment of allocated memory. same meaning as in the operator `new` (C++17).
|
||||
Must be divisible by sizeof(T). Must be power of two.
|
||||
|
||||
@note In safe mode allocation will be performed immediatly.
|
||||
*/
|
||||
template <typename T>
|
||||
void allocate(T*&ptr, size_t count, ushort alignment = sizeof(T))
|
||||
{
|
||||
CV_Assert(ptr == NULL);
|
||||
CV_Assert(count > 0);
|
||||
CV_Assert(alignment > 0);
|
||||
CV_Assert(alignment % sizeof(T) == 0);
|
||||
CV_Assert((alignment & (alignment - 1)) == 0);
|
||||
allocate_((void**)(&ptr), static_cast<ushort>(sizeof(T)), count, alignment);
|
||||
}
|
||||
|
||||
/** @brief Allocate memory and initialize all bound pointers
|
||||
|
||||
Each pointer bound to the area with the BufferArea::allocate will be initialized and will be set
|
||||
to point to a memory block with requested size and alignment.
|
||||
|
||||
@note Does nothing in safe mode as all allocations will be performed by BufferArea::allocate
|
||||
*/
|
||||
void commit();
|
||||
|
||||
private:
|
||||
BufferArea(const BufferArea &); // = delete
|
||||
BufferArea &operator=(const BufferArea &); // = delete
|
||||
void allocate_(void **ptr, ushort type_size, size_t count, ushort alignment);
|
||||
|
||||
private:
|
||||
class Block;
|
||||
std::vector<Block> blocks;
|
||||
void * oneBuf;
|
||||
size_t totalSize;
|
||||
const bool safe;
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
}} // cv::utils::
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "opencv2/core/utils/buffer_area.private.hpp"
|
||||
#include "opencv2/core/utils/configuration.private.hpp"
|
||||
|
||||
#ifdef OPENCV_ENABLE_MEMORY_SANITIZER
|
||||
#define BUFFER_AREA_DEFAULT_MODE true
|
||||
#else
|
||||
#define BUFFER_AREA_DEFAULT_MODE false
|
||||
#endif
|
||||
|
||||
static bool CV_BUFFER_AREA_OVERRIDE_SAFE_MODE =
|
||||
cv::utils::getConfigurationParameterBool("OPENCV_BUFFER_AREA_ALWAYS_SAFE", BUFFER_AREA_DEFAULT_MODE);
|
||||
|
||||
namespace cv { namespace utils {
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
class BufferArea::Block
|
||||
{
|
||||
private:
|
||||
inline size_t reserve_count() const
|
||||
{
|
||||
return alignment / type_size - 1;
|
||||
}
|
||||
public:
|
||||
Block(void **ptr_, ushort type_size_, size_t count_, ushort alignment_)
|
||||
: ptr(ptr_), raw_mem(0), count(count_), type_size(type_size_), alignment(alignment_)
|
||||
{
|
||||
CV_Assert(ptr && *ptr == NULL);
|
||||
}
|
||||
void cleanup() const
|
||||
{
|
||||
CV_Assert(ptr && *ptr);
|
||||
*ptr = 0;
|
||||
if (raw_mem)
|
||||
fastFree(raw_mem);
|
||||
}
|
||||
size_t getByteCount() const
|
||||
{
|
||||
return type_size * (count + reserve_count());
|
||||
}
|
||||
void real_allocate()
|
||||
{
|
||||
CV_Assert(ptr && *ptr == NULL);
|
||||
const size_t allocated_count = count + reserve_count();
|
||||
raw_mem = fastMalloc(type_size * allocated_count);
|
||||
if (alignment != type_size)
|
||||
{
|
||||
*ptr = alignPtr(raw_mem, alignment);
|
||||
CV_Assert(reinterpret_cast<size_t>(*ptr) % alignment == 0);
|
||||
CV_Assert(static_cast<uchar*>(*ptr) + type_size * count <= static_cast<uchar*>(raw_mem) + type_size * allocated_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr = raw_mem;
|
||||
}
|
||||
}
|
||||
void * fast_allocate(void * buf) const
|
||||
{
|
||||
CV_Assert(ptr && *ptr == NULL);
|
||||
buf = alignPtr(buf, alignment);
|
||||
CV_Assert(reinterpret_cast<size_t>(buf) % alignment == 0);
|
||||
*ptr = buf;
|
||||
return static_cast<void*>(static_cast<uchar*>(*ptr) + type_size * count);
|
||||
}
|
||||
private:
|
||||
void **ptr;
|
||||
void * raw_mem;
|
||||
size_t count;
|
||||
ushort type_size;
|
||||
ushort alignment;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
BufferArea::BufferArea(bool safe_) :
|
||||
oneBuf(0),
|
||||
totalSize(0),
|
||||
safe(safe_ || CV_BUFFER_AREA_OVERRIDE_SAFE_MODE)
|
||||
{
|
||||
}
|
||||
|
||||
BufferArea::~BufferArea()
|
||||
{
|
||||
for(std::vector<Block>::const_iterator i = blocks.begin(); i != blocks.end(); ++i)
|
||||
i->cleanup();
|
||||
if (oneBuf)
|
||||
fastFree(oneBuf);
|
||||
}
|
||||
|
||||
void BufferArea::allocate_(void **ptr, ushort type_size, size_t count, ushort alignment)
|
||||
{
|
||||
blocks.push_back(Block(ptr, type_size, count, alignment));
|
||||
if (safe)
|
||||
blocks.back().real_allocate();
|
||||
else
|
||||
totalSize += blocks.back().getByteCount();
|
||||
}
|
||||
|
||||
void BufferArea::commit()
|
||||
{
|
||||
if (!safe)
|
||||
{
|
||||
CV_Assert(totalSize > 0);
|
||||
CV_Assert(oneBuf == NULL);
|
||||
CV_Assert(!blocks.empty());
|
||||
oneBuf = fastMalloc(totalSize);
|
||||
void * ptr = oneBuf;
|
||||
for(std::vector<Block>::const_iterator i = blocks.begin(); i != blocks.end(); ++i)
|
||||
{
|
||||
ptr = i->fast_allocate(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
}} // cv::utils::
|
||||
+10
-16
@@ -563,12 +563,6 @@ Mat& Mat::setTo(InputArray _value, InputArray _mask)
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if CV_NEON && !defined(__aarch64__)
|
||||
#define CV_CHECK_ALIGNMENT 1
|
||||
#else
|
||||
#define CV_CHECK_ALIGNMENT 0
|
||||
#endif
|
||||
|
||||
#if CV_SIMD128
|
||||
template<typename V> CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
@@ -578,7 +572,7 @@ template<typename V> CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, s
|
||||
int width_1 = width & -v_uint8x16::nlanes;
|
||||
int i, j;
|
||||
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(T)>(src, dst));
|
||||
#endif
|
||||
|
||||
@@ -630,7 +624,7 @@ template<typename T1, typename T2> CV_ALWAYS_INLINE void flipHoriz_double( const
|
||||
int end = (int)(size.width*esz);
|
||||
int width = (end + 1)/2;
|
||||
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(T1)>(src, dst));
|
||||
CV_Assert(isAligned<sizeof(T2)>(src, dst));
|
||||
#endif
|
||||
@@ -659,7 +653,7 @@ static void
|
||||
flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
#if CV_SIMD
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
size_t alignmentMark = ((size_t)src)|((size_t)dst)|sstep|dstep;
|
||||
#endif
|
||||
if (esz == 2 * v_uint8x16::nlanes)
|
||||
@@ -712,7 +706,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
}
|
||||
}
|
||||
else if (esz == 8
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(uint64)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
@@ -720,7 +714,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
flipHoriz_single<v_uint64x2>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 4
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(unsigned)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
@@ -728,7 +722,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
flipHoriz_single<v_uint32x4>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 2
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(ushort)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
@@ -740,7 +734,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
flipHoriz_single<v_uint8x16>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 24
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(uint64_t)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
@@ -766,7 +760,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !CV_CHECK_ALIGNMENT
|
||||
#if !CV_STRONG_ALIGNMENT
|
||||
else if (esz == 12)
|
||||
{
|
||||
flipHoriz_double<uint64_t,uint>(src, sstep, dst, dstep, size, esz);
|
||||
@@ -815,7 +809,7 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size,
|
||||
{
|
||||
int i = 0;
|
||||
#if CV_SIMD
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
|
||||
#endif
|
||||
{
|
||||
@@ -827,7 +821,7 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size,
|
||||
vx_store((int*)(dst1 + i), t0);
|
||||
}
|
||||
}
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
else
|
||||
{
|
||||
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/core/utils/logger.hpp"
|
||||
#include "opencv2/core/utils/buffer_area.private.hpp"
|
||||
|
||||
#include "test_utils_tls.impl.hpp"
|
||||
|
||||
@@ -303,4 +304,132 @@ TEST(Samples, findFile_missing)
|
||||
cv::utils::logging::setLogLevel(prev);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool buffers_overlap(T * first, size_t first_num, T * second, size_t second_num)
|
||||
{
|
||||
// cerr << "[" << (void*)first << " : " << (void*)(first + first_num) << ")";
|
||||
// cerr << " X ";
|
||||
// cerr << "[" << (void*)second << " : " << (void*)(second + second_num) << ")";
|
||||
// cerr << endl;
|
||||
bool res = false;
|
||||
res |= (second <= first) && (first < second + second_num);
|
||||
res |= (second < first + first_num) && (first + first_num < second + second_num);
|
||||
return res;
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<bool> BufferArea;
|
||||
|
||||
TEST_P(BufferArea, basic)
|
||||
{
|
||||
const bool safe = GetParam();
|
||||
const size_t SZ = 3;
|
||||
int * int_ptr = NULL;
|
||||
uchar * uchar_ptr = NULL;
|
||||
double * dbl_ptr = NULL;
|
||||
{
|
||||
cv::utils::BufferArea area(safe);
|
||||
area.allocate(int_ptr, SZ);
|
||||
area.allocate(uchar_ptr, SZ);
|
||||
area.allocate(dbl_ptr, SZ);
|
||||
area.commit();
|
||||
ASSERT_TRUE(int_ptr != NULL);
|
||||
ASSERT_TRUE(uchar_ptr != NULL);
|
||||
ASSERT_TRUE(dbl_ptr != NULL);
|
||||
EXPECT_EQ((size_t)0, (size_t)int_ptr % sizeof(int));
|
||||
EXPECT_EQ((size_t)0, (size_t)dbl_ptr % sizeof(double));
|
||||
}
|
||||
EXPECT_TRUE(int_ptr == NULL);
|
||||
EXPECT_TRUE(uchar_ptr == NULL);
|
||||
EXPECT_TRUE(dbl_ptr == NULL);
|
||||
}
|
||||
|
||||
TEST_P(BufferArea, align)
|
||||
{
|
||||
const bool safe = GetParam();
|
||||
const size_t SZ = 3;
|
||||
const size_t CNT = 5;
|
||||
typedef int T;
|
||||
T * buffers[CNT] = {0};
|
||||
{
|
||||
cv::utils::BufferArea area(safe);
|
||||
// allocate buffers with 3 elements with growing alignment (power of two)
|
||||
for (size_t i = 0; i < CNT; ++i)
|
||||
{
|
||||
const ushort ALIGN = static_cast<ushort>(sizeof(T) << i);
|
||||
EXPECT_TRUE(buffers[i] == NULL);
|
||||
area.allocate(buffers[i], SZ, ALIGN);
|
||||
}
|
||||
area.commit();
|
||||
for (size_t i = 0; i < CNT; ++i)
|
||||
{
|
||||
const ushort ALIGN = static_cast<ushort>(sizeof(T) << i);
|
||||
EXPECT_TRUE(buffers[i] != NULL);
|
||||
EXPECT_EQ((size_t)0, reinterpret_cast<size_t>(buffers[i]) % ALIGN);
|
||||
if (i < CNT - 1)
|
||||
{
|
||||
SCOPED_TRACE(i);
|
||||
EXPECT_FALSE(buffers_overlap(buffers[i], SZ, buffers[i + 1], SZ))
|
||||
<< "Buffers overlap: "
|
||||
<< buffers[i] << " (" << SZ << " elems)"
|
||||
<< " and "
|
||||
<< buffers[i + 1] << " (" << SZ << " elems)"
|
||||
<< " (element size: " << sizeof(T) << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < CNT; ++i)
|
||||
{
|
||||
EXPECT_TRUE(buffers[i] == NULL);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(BufferArea, default_align)
|
||||
{
|
||||
const bool safe = GetParam();
|
||||
const size_t CNT = 100;
|
||||
const ushort ALIGN = 64;
|
||||
typedef int T;
|
||||
T * buffers[CNT] = {0};
|
||||
{
|
||||
cv::utils::BufferArea area(safe);
|
||||
// allocate buffers with 1-99 elements with default alignment
|
||||
for (size_t i = 0; i < CNT; ++ i)
|
||||
{
|
||||
EXPECT_TRUE(buffers[i] == NULL);
|
||||
area.allocate(buffers[i], i + 1, ALIGN);
|
||||
}
|
||||
area.commit();
|
||||
for (size_t i = 0; i < CNT; ++i)
|
||||
{
|
||||
EXPECT_TRUE(buffers[i] != NULL);
|
||||
EXPECT_EQ((size_t)0, reinterpret_cast<size_t>(buffers[i]) % ALIGN);
|
||||
if (i < CNT - 1)
|
||||
{
|
||||
SCOPED_TRACE(i);
|
||||
EXPECT_FALSE(buffers_overlap(buffers[i], i + 1, buffers[i + 1], i + 2))
|
||||
<< "Buffers overlap: "
|
||||
<< buffers[i] << " (" << i + 1 << " elems)"
|
||||
<< " and "
|
||||
<< buffers[i + 1] << " (" << i + 2 << " elems)"
|
||||
<< " (element size: " << sizeof(T) << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(BufferArea, bad)
|
||||
{
|
||||
const bool safe = GetParam();
|
||||
int * ptr = 0;
|
||||
cv::utils::BufferArea area(safe);
|
||||
EXPECT_ANY_THROW(area.allocate(ptr, 0)); // bad size
|
||||
EXPECT_ANY_THROW(area.allocate(ptr, 1, 0)); // bad alignment
|
||||
EXPECT_ANY_THROW(area.allocate(ptr, 1, 3)); // bad alignment
|
||||
ptr = (int*)1;
|
||||
EXPECT_ANY_THROW(area.allocate(ptr, 1)); // non-zero pointer
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, BufferArea, testing::Values(true, false));
|
||||
|
||||
|
||||
}} // namespace
|
||||
|
||||
Reference in New Issue
Block a user