@@ -67,6 +67,7 @@ UMatData::UMatData(const MatAllocator* allocator)
67
67
handle = 0 ;
68
68
userdata = 0 ;
69
69
allocatorFlags_ = 0 ;
70
+ originalUMatData = NULL ;
70
71
}
71
72
72
73
UMatData::~UMatData ()
@@ -80,6 +81,50 @@ UMatData::~UMatData()
80
81
handle = 0 ;
81
82
userdata = 0 ;
82
83
allocatorFlags_ = 0 ;
84
+ if (originalUMatData)
85
+ {
86
+ UMatData* u = originalUMatData;
87
+ CV_XADD (&(u->urefcount ), -1 );
88
+ CV_XADD (&(u->refcount ), -1 );
89
+ bool showWarn = false ;
90
+ if (u->refcount == 0 )
91
+ {
92
+ if (u->urefcount > 0 )
93
+ showWarn = true ;
94
+ // simulate Mat::deallocate
95
+ if (u->mapcount != 0 )
96
+ {
97
+ (u->currAllocator ? u->currAllocator : /* TODO allocator ? allocator :*/ Mat::getStdAllocator ())->unmap (u);
98
+ }
99
+ else
100
+ {
101
+ // we don't do "map", so we can't do "unmap"
102
+ }
103
+ }
104
+ if (u->refcount == 0 && u->urefcount == 0 ) // oops, we need to free resources
105
+ {
106
+ showWarn = true ;
107
+ // simulate UMat::deallocate
108
+ u->currAllocator ->deallocate (u);
109
+ }
110
+ #ifndef NDEBUG
111
+ if (showWarn)
112
+ {
113
+ static int warn_message_showed = 0 ;
114
+ if (warn_message_showed++ < 100 )
115
+ {
116
+ fflush (stdout);
117
+ fprintf (stderr, " \n ! OPENCV warning: getUMat()/getMat() call chain possible problem."
118
+ " \n ! Base object is dead, while nested/derived object is still alive or processed."
119
+ " \n ! Please check lifetime of UMat/Mat objects!\n " );
120
+ fflush (stderr);
121
+ }
122
+ }
123
+ #else
124
+ (void )showWarn;
125
+ #endif
126
+ originalUMatData = NULL ;
127
+ }
83
128
}
84
129
85
130
void UMatData::lock ()
@@ -222,35 +267,61 @@ UMat Mat::getUMat(int accessFlags, UMatUsageFlags usageFlags) const
222
267
UMat hdr;
223
268
if (!data)
224
269
return hdr;
225
- CV_Assert ((!u || u->mapcount ==0 ) && " Don't get UMat from temp-Mat!" );
270
+ Size wholeSize;
271
+ Point ofs;
272
+ locateROI (wholeSize, ofs);
273
+ Size sz (cols, rows);
274
+ if (ofs.x != 0 || ofs.y != 0 )
275
+ {
276
+ Mat src = *this ;
277
+ int dtop = ofs.y ;
278
+ int dbottom = wholeSize.height - src.rows - ofs.y ;
279
+ int dleft = ofs.x ;
280
+ int dright = wholeSize.width - src.cols - ofs.x ;
281
+ src.adjustROI (dtop, dbottom, dleft, dright);
282
+ return src.getUMat (accessFlags, usageFlags)(cv::Rect (ofs.x , ofs.y , sz.width , sz.height ));
283
+ }
284
+ CV_Assert (data == datastart);
285
+
226
286
accessFlags |= ACCESS_RW;
227
- UMatData* temp_u = u;
228
- if (!temp_u)
287
+ UMatData* new_u = NULL ;
229
288
{
230
289
MatAllocator *a = allocator, *a0 = getStdAllocator ();
231
290
if (!a)
232
291
a = a0;
233
- temp_u = a->allocate (dims, size.p , type (), data, step.p , accessFlags, usageFlags);
292
+ new_u = a->allocate (dims, size.p , type (), data, step.p , accessFlags, usageFlags);
234
293
}
235
294
bool allocated = false ;
236
295
try
237
296
{
238
- allocated = UMat::getStdAllocator ()->allocate (temp_u , accessFlags, usageFlags);
297
+ allocated = UMat::getStdAllocator ()->allocate (new_u , accessFlags, usageFlags);
239
298
}
240
299
catch (const cv::Exception& e)
241
300
{
242
301
fprintf (stderr, " Exception: %s\n " , e.what ());
243
302
}
244
303
if (!allocated)
245
304
{
246
- allocated = getStdAllocator ()->allocate (temp_u , accessFlags, usageFlags);
305
+ allocated = getStdAllocator ()->allocate (new_u , accessFlags, usageFlags);
247
306
CV_Assert (allocated);
248
307
}
308
+ if (u != NULL )
309
+ {
310
+ #ifdef HAVE_OPENCL
311
+ if (ocl::useOpenCL () && new_u->currAllocator == ocl::getOpenCLAllocator ())
312
+ {
313
+ CV_Assert (new_u->tempUMat ());
314
+ }
315
+ #endif
316
+ new_u->originalUMatData = u;
317
+ CV_XADD (&(u->refcount ), 1 );
318
+ CV_XADD (&(u->urefcount ), 1 );
319
+ }
249
320
hdr.flags = flags;
250
321
setSize (hdr, dims, size.p , step.p );
251
322
finalizeHdr (hdr);
252
- hdr.u = temp_u ;
253
- hdr.offset = data - datastart;
323
+ hdr.u = new_u ;
324
+ hdr.offset = 0 ; // data - datastart;
254
325
hdr.addref ();
255
326
return hdr;
256
327
}
@@ -639,7 +710,6 @@ Mat UMat::getMat(int accessFlags) const
639
710
{
640
711
if (!u)
641
712
return Mat ();
642
- CV_Assert (!u->tempUMat () && " Don't get Mat from temp UMat! Use copyTo()." );
643
713
// TODO Support ACCESS_READ (ACCESS_WRITE) without unnecessary data transfers
644
714
accessFlags |= ACCESS_RW;
645
715
UMatDataAutoLock autolock (u);
@@ -668,10 +738,10 @@ void* UMat::handle(int accessFlags) const
668
738
if ( !u )
669
739
return 0 ;
670
740
671
- // check flags: if CPU copy is newer, copy it back to GPU.
672
- if ( u->deviceCopyObsolete () )
741
+ CV_Assert (u->refcount == 0 );
742
+ CV_Assert (!u->deviceCopyObsolete () || u->copyOnMap ());
743
+ if (u->deviceCopyObsolete ())
673
744
{
674
- CV_Assert (u->refcount == 0 || u->origdata );
675
745
u->currAllocator ->unmap (u);
676
746
}
677
747
0 commit comments