mirror of
https://github.com/opencv/opencv.git
synced 2024-11-24 03:00:14 +08:00
Merge pull request #25979 from asmorkalov:as/custom_allocator
Set and check allocator pointer for all cv::Mat instances
This commit is contained in:
commit
ab99f87b6a
@ -692,16 +692,13 @@ void Mat::create(int d, const int* _sizes, int _type)
|
||||
if( total() > 0 )
|
||||
{
|
||||
MatAllocator *a = allocator, *a0 = getDefaultAllocator();
|
||||
#ifdef HAVE_TGPU
|
||||
if( !a || a == tegra::getAllocator() )
|
||||
a = tegra::getAllocator(d, _sizes, _type);
|
||||
#endif
|
||||
if(!a)
|
||||
a = a0;
|
||||
try
|
||||
{
|
||||
u = a->allocate(dims, size, _type, 0, step.p, ACCESS_RW /* ignored */, USAGE_DEFAULT);
|
||||
CV_Assert(u != 0);
|
||||
allocator = a;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -709,6 +706,7 @@ void Mat::create(int d, const int* _sizes, int _type)
|
||||
throw;
|
||||
u = a0->allocate(dims, size, _type, 0, step.p, ACCESS_RW /* ignored */, USAGE_DEFAULT);
|
||||
CV_Assert(u != 0);
|
||||
allocator = a0;
|
||||
}
|
||||
CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
|
||||
}
|
||||
|
144
modules/core/test/test_allocator.cpp
Normal file
144
modules/core/test/test_allocator.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
// 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
// Dummy allocator implementation copied from the default OpenCV allocator with some simplifications
|
||||
struct DummyAllocator: public cv::MatAllocator
|
||||
{
|
||||
public:
|
||||
DummyAllocator() {};
|
||||
~DummyAllocator() {};
|
||||
|
||||
cv::UMatData* allocate(int dims, const int* sizes, int type,
|
||||
void* data0, size_t* step, cv::AccessFlag flags,
|
||||
cv::UMatUsageFlags usageFlags) const
|
||||
{
|
||||
CV_UNUSED(flags);
|
||||
CV_UNUSED(usageFlags);
|
||||
|
||||
size_t total = CV_ELEM_SIZE(type);
|
||||
for( int i = dims-1; i >= 0; i-- )
|
||||
{
|
||||
if( step )
|
||||
{
|
||||
if( data0 && step[i] != CV_AUTOSTEP )
|
||||
{
|
||||
CV_Assert(total <= step[i]);
|
||||
total = step[i];
|
||||
}
|
||||
else
|
||||
step[i] = total;
|
||||
}
|
||||
total *= sizes[i];
|
||||
}
|
||||
|
||||
uchar* data = nullptr;
|
||||
if (data0)
|
||||
{
|
||||
data = (uchar*)data0;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = new uchar[total];
|
||||
DummyAllocator::allocatedBytes += total;
|
||||
DummyAllocator::allocations++;
|
||||
}
|
||||
cv::UMatData* u = new cv::UMatData(this);
|
||||
u->data = u->origdata = data;
|
||||
u->size = total;
|
||||
if(data0)
|
||||
u->flags |= cv::UMatData::USER_ALLOCATED;
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
bool allocate(cv::UMatData* u, cv::AccessFlag accessFlags, cv::UMatUsageFlags usageFlags) const
|
||||
{
|
||||
CV_UNUSED(accessFlags);
|
||||
CV_UNUSED(usageFlags);
|
||||
|
||||
if(!u) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void deallocate(cv::UMatData* u) const
|
||||
{
|
||||
if(!u)
|
||||
return;
|
||||
|
||||
CV_Assert(u->urefcount == 0);
|
||||
CV_Assert(u->refcount == 0);
|
||||
if( !(u->flags & cv::UMatData::USER_ALLOCATED) )
|
||||
{
|
||||
delete[] u->origdata;
|
||||
DummyAllocator::deallocations++;
|
||||
u->origdata = 0;
|
||||
}
|
||||
delete u;
|
||||
}
|
||||
|
||||
static size_t allocatedBytes;
|
||||
static int allocations;
|
||||
static int deallocations;
|
||||
};
|
||||
|
||||
size_t DummyAllocator::allocatedBytes = 0;
|
||||
int DummyAllocator::allocations = 0;
|
||||
int DummyAllocator::deallocations = 0;
|
||||
|
||||
cv::MatAllocator* getDummyAllocator()
|
||||
{
|
||||
static cv::MatAllocator* allocator = new DummyAllocator;
|
||||
return allocator;
|
||||
}
|
||||
|
||||
struct AllocatorTest : public testing::Test {
|
||||
void SetUp() override {
|
||||
cv::MatAllocator* allocator = getDummyAllocator();
|
||||
EXPECT_TRUE(allocator != nullptr);
|
||||
cv::Mat::setDefaultAllocator(allocator);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
cv::Mat::setDefaultAllocator(cv::Mat::getStdAllocator());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(AllocatorTest, DummyAllocator)
|
||||
{
|
||||
cv::MatAllocator* dummy = getDummyAllocator();
|
||||
|
||||
DummyAllocator::allocatedBytes = 0;
|
||||
DummyAllocator::allocations = 0;
|
||||
DummyAllocator::deallocations = 0;
|
||||
|
||||
{
|
||||
cv::Mat src1 = cv::Mat::ones (16, 16, CV_8UC1);
|
||||
EXPECT_TRUE(!src1.empty());
|
||||
EXPECT_EQ(src1.allocator, dummy);
|
||||
|
||||
cv::Mat src1_roi = src1(cv::Rect(2,2,8,8));
|
||||
EXPECT_EQ(src1_roi.allocator, dummy);
|
||||
|
||||
cv::MatAllocator* standard = cv::Mat::getStdAllocator();
|
||||
cv::Mat::setDefaultAllocator(standard);
|
||||
cv::Mat src2 = cv::Mat::ones (16, 16, CV_8UC1);
|
||||
EXPECT_TRUE(!src2.empty());
|
||||
EXPECT_EQ(src2.allocator, standard);
|
||||
|
||||
src1.create(32, 32, CV_8UC1);
|
||||
EXPECT_EQ(src1.allocator, dummy);
|
||||
}
|
||||
|
||||
size_t expect_allocated = 16*16*sizeof(uchar) + 32*32*sizeof(uchar);
|
||||
EXPECT_EQ(expect_allocated, DummyAllocator::allocatedBytes);
|
||||
|
||||
// ROI should not trigger extra allocations
|
||||
EXPECT_EQ(2, DummyAllocator::allocations);
|
||||
EXPECT_EQ(2, DummyAllocator::deallocations);
|
||||
}
|
||||
|
||||
}} // namespace
|
Loading…
Reference in New Issue
Block a user