1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
8 //
9 //
10 // License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2014, Itseez Inc., all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
21 //
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
25 //
26 // * The name of the copyright holders may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "precomp.hpp"
43 #include "opencl_kernels_core.hpp"
44 #include "umatrix.hpp"
45
46 #include <opencv2/core/utils/tls.hpp>
47
48 ///////////////////////////////// UMat implementation ///////////////////////////////
49
50 namespace cv {
51
52 // forward decls, implementation is below in this file
53 void setSize(UMat& m, int _dims, const int* _sz, const size_t* _steps,
54 bool autoSteps = false);
55
56 void updateContinuityFlag(UMat& m);
57 void finalizeHdr(UMat& m);
58
59 // it should be a prime number for the best hash function
60 enum { UMAT_NLOCKS = 31 };
61 static Mutex umatLocks[UMAT_NLOCKS];
62
UMatData(const MatAllocator * allocator)63 UMatData::UMatData(const MatAllocator* allocator)
64 {
65 prevAllocator = currAllocator = allocator;
66 urefcount = refcount = mapcount = 0;
67 data = origdata = 0;
68 size = 0;
69 flags = static_cast<UMatData::MemoryFlag>(0);
70 handle = 0;
71 userdata = 0;
72 allocatorFlags_ = 0;
73 originalUMatData = NULL;
74 }
75
~UMatData()76 UMatData::~UMatData()
77 {
78 prevAllocator = currAllocator = 0;
79 urefcount = refcount = 0;
80 CV_Assert(mapcount == 0);
81 data = origdata = 0;
82 size = 0;
83 bool isAsyncCleanup = !!(flags & UMatData::ASYNC_CLEANUP);
84 flags = static_cast<UMatData::MemoryFlag>(0);
85 handle = 0;
86 userdata = 0;
87 allocatorFlags_ = 0;
88 if (originalUMatData)
89 {
90 bool showWarn = false;
91 UMatData* u = originalUMatData;
92 bool zero_Ref = CV_XADD(&(u->refcount), -1) == 1;
93 if (zero_Ref)
94 {
95 // simulate Mat::deallocate
96 if (u->mapcount != 0)
97 {
98 (u->currAllocator ? u->currAllocator : /* TODO allocator ? allocator :*/ Mat::getDefaultAllocator())->unmap(u);
99 }
100 else
101 {
102 // we don't do "map", so we can't do "unmap"
103 }
104 }
105 bool zero_URef = CV_XADD(&(u->urefcount), -1) == 1;
106 if (zero_Ref && !zero_URef)
107 showWarn = true;
108 if (zero_Ref && zero_URef) // oops, we need to free resources
109 {
110 showWarn = !isAsyncCleanup;
111 // simulate UMat::deallocate
112 u->currAllocator->deallocate(u);
113 }
114 #ifndef NDEBUG
115 if (showWarn)
116 {
117 static int warn_message_showed = 0;
118 if (warn_message_showed++ < 100)
119 {
120 fflush(stdout);
121 fprintf(stderr, "\n! OPENCV warning: getUMat()/getMat() call chain possible problem."
122 "\n! Base object is dead, while nested/derived object is still alive or processed."
123 "\n! Please check lifetime of UMat/Mat objects!\n");
124 fflush(stderr);
125 }
126 }
127 #else
128 CV_UNUSED(showWarn);
129 #endif
130 originalUMatData = NULL;
131 }
132 }
133
getUMatDataLockIndex(const UMatData * u)134 static size_t getUMatDataLockIndex(const UMatData* u)
135 {
136 size_t idx = ((size_t)(void*)u) % UMAT_NLOCKS;
137 return idx;
138 }
139
lock()140 void UMatData::lock()
141 {
142 size_t idx = getUMatDataLockIndex(this);
143 //printf("%d lock(%d)\n", cv::utils::getThreadID(), (int)idx);
144 umatLocks[idx].lock();
145 }
146
unlock()147 void UMatData::unlock()
148 {
149 size_t idx = getUMatDataLockIndex(this);
150 //printf("%d unlock(%d)\n", cv::utils::getThreadID(), (int)idx);
151 umatLocks[idx].unlock();
152 }
153
154
155 // Do not allow several lock() calls with different UMatData objects.
156 struct UMatDataAutoLocker
157 {
158 int usage_count;
159 UMatData* locked_objects[2];
UMatDataAutoLockercv::UMatDataAutoLocker160 UMatDataAutoLocker() : usage_count(0) { locked_objects[0] = NULL; locked_objects[1] = NULL; }
161
lockcv::UMatDataAutoLocker162 void lock(UMatData*& u1)
163 {
164 bool locked_1 = (u1 == locked_objects[0] || u1 == locked_objects[1]);
165 if (locked_1)
166 {
167 u1 = NULL;
168 return;
169 }
170 CV_Assert(usage_count == 0); // UMatDataAutoLock can't be used multiple times from the same thread
171 usage_count = 1;
172 locked_objects[0] = u1;
173 u1->lock();
174 }
lockcv::UMatDataAutoLocker175 void lock(UMatData*& u1, UMatData*& u2)
176 {
177 bool locked_1 = (u1 == locked_objects[0] || u1 == locked_objects[1]);
178 bool locked_2 = (u2 == locked_objects[0] || u2 == locked_objects[1]);
179 if (locked_1)
180 u1 = NULL;
181 if (locked_2)
182 u2 = NULL;
183 if (locked_1 && locked_2)
184 return;
185 CV_Assert(usage_count == 0); // UMatDataAutoLock can't be used multiple times from the same thread
186 usage_count = 1;
187 locked_objects[0] = u1;
188 locked_objects[1] = u2;
189 if (u1)
190 u1->lock();
191 if (u2)
192 u2->lock();
193 }
releasecv::UMatDataAutoLocker194 void release(UMatData* u1, UMatData* u2)
195 {
196 if (u1 == NULL && u2 == NULL)
197 return;
198 CV_Assert(usage_count == 1);
199 usage_count = 0;
200 if (u1)
201 u1->unlock();
202 if (u2)
203 u2->unlock();
204 locked_objects[0] = NULL; locked_objects[1] = NULL;
205 }
206 };
getUMatDataAutoLockerTLS()207 static TLSData<UMatDataAutoLocker>& getUMatDataAutoLockerTLS()
208 {
209 CV_SINGLETON_LAZY_INIT_REF(TLSData<UMatDataAutoLocker>, new TLSData<UMatDataAutoLocker>());
210 }
getUMatDataAutoLocker()211 static UMatDataAutoLocker& getUMatDataAutoLocker() { return getUMatDataAutoLockerTLS().getRef(); }
212
213
UMatDataAutoLock(UMatData * u)214 UMatDataAutoLock::UMatDataAutoLock(UMatData* u) : u1(u), u2(NULL)
215 {
216 getUMatDataAutoLocker().lock(u1);
217 }
UMatDataAutoLock(UMatData * u1_,UMatData * u2_)218 UMatDataAutoLock::UMatDataAutoLock(UMatData* u1_, UMatData* u2_) : u1(u1_), u2(u2_)
219 {
220 if (getUMatDataLockIndex(u1) > getUMatDataLockIndex(u2))
221 {
222 std::swap(u1, u2);
223 }
224 getUMatDataAutoLocker().lock(u1, u2);
225 }
~UMatDataAutoLock()226 UMatDataAutoLock::~UMatDataAutoLock()
227 {
228 getUMatDataAutoLocker().release(u1, u2);
229 }
230
231 //////////////////////////////// UMat ////////////////////////////////
232
UMat(UMatUsageFlags _usageFlags)233 UMat::UMat(UMatUsageFlags _usageFlags) CV_NOEXCEPT
234 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
235 {}
236
UMat(int _rows,int _cols,int _type,UMatUsageFlags _usageFlags)237 UMat::UMat(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags)
238 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
239 {
240 create(_rows, _cols, _type);
241 }
242
UMat(int _rows,int _cols,int _type,const Scalar & _s,UMatUsageFlags _usageFlags)243 UMat::UMat(int _rows, int _cols, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
244 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
245 {
246 create(_rows, _cols, _type);
247 *this = _s;
248 }
249
UMat(Size _sz,int _type,UMatUsageFlags _usageFlags)250 UMat::UMat(Size _sz, int _type, UMatUsageFlags _usageFlags)
251 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
252 {
253 create( _sz.height, _sz.width, _type );
254 }
255
UMat(Size _sz,int _type,const Scalar & _s,UMatUsageFlags _usageFlags)256 UMat::UMat(Size _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
257 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
258 {
259 create(_sz.height, _sz.width, _type);
260 *this = _s;
261 }
262
UMat(int _dims,const int * _sz,int _type,UMatUsageFlags _usageFlags)263 UMat::UMat(int _dims, const int* _sz, int _type, UMatUsageFlags _usageFlags)
264 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
265 {
266 create(_dims, _sz, _type);
267 }
268
UMat(int _dims,const int * _sz,int _type,const Scalar & _s,UMatUsageFlags _usageFlags)269 UMat::UMat(int _dims, const int* _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
270 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
271 {
272 create(_dims, _sz, _type);
273 *this = _s;
274 }
275
UMat(const UMat & m)276 UMat::UMat(const UMat& m)
277 : flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), allocator(m.allocator),
278 usageFlags(m.usageFlags), u(m.u), offset(m.offset), size(&rows)
279 {
280 addref();
281 if( m.dims <= 2 )
282 {
283 step[0] = m.step[0]; step[1] = m.step[1];
284 }
285 else
286 {
287 dims = 0;
288 copySize(m);
289 }
290 }
291
operator =(const UMat & m)292 UMat& UMat::operator=(const UMat& m)
293 {
294 if( this != &m )
295 {
296 const_cast<UMat&>(m).addref();
297 release();
298 flags = m.flags;
299 if( dims <= 2 && m.dims <= 2 )
300 {
301 dims = m.dims;
302 rows = m.rows;
303 cols = m.cols;
304 step[0] = m.step[0];
305 step[1] = m.step[1];
306 }
307 else
308 copySize(m);
309 allocator = m.allocator;
310 usageFlags = m.usageFlags;
311 u = m.u;
312 offset = m.offset;
313 }
314 return *this;
315 }
316
clone() const317 UMat UMat::clone() const
318 {
319 UMat m;
320 copyTo(m);
321 return m;
322 }
323
assignTo(UMat & m,int _type) const324 void UMat::assignTo(UMat& m, int _type) const
325 {
326 if( _type < 0 )
327 m = *this;
328 else
329 convertTo(m, _type);
330 }
331
create(int _rows,int _cols,int _type,UMatUsageFlags _usageFlags)332 void UMat::create(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags)
333 {
334 int sz[] = {_rows, _cols};
335 create(2, sz, _type, _usageFlags);
336 }
337
create(Size _sz,int _type,UMatUsageFlags _usageFlags)338 void UMat::create(Size _sz, int _type, UMatUsageFlags _usageFlags)
339 {
340 create(_sz.height, _sz.width, _type, _usageFlags);
341 }
342
addref()343 void UMat::addref()
344 {
345 if( u )
346 CV_XADD(&(u->urefcount), 1);
347 }
348
release()349 void UMat::release()
350 {
351 if( u && CV_XADD(&(u->urefcount), -1) == 1 )
352 deallocate();
353 for(int i = 0; i < dims; i++)
354 size.p[i] = 0;
355 u = 0;
356 }
357
empty() const358 bool UMat::empty() const
359 {
360 return u == 0 || total() == 0 || dims == 0;
361 }
362
total() const363 size_t UMat::total() const
364 {
365 if( dims <= 2 )
366 return (size_t)rows * cols;
367 size_t p = 1;
368 for( int i = 0; i < dims; i++ )
369 p *= size[i];
370 return p;
371 }
372
373
UMat(UMat && m)374 UMat::UMat(UMat&& m)
375 : flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), allocator(m.allocator),
376 usageFlags(m.usageFlags), u(m.u), offset(m.offset), size(&rows)
377 {
378 if (m.dims <= 2) // move new step/size info
379 {
380 step[0] = m.step[0];
381 step[1] = m.step[1];
382 }
383 else
384 {
385 CV_DbgAssert(m.step.p != m.step.buf);
386 step.p = m.step.p;
387 size.p = m.size.p;
388 m.step.p = m.step.buf;
389 m.size.p = &m.rows;
390 }
391 m.flags = MAGIC_VAL; m.dims = m.rows = m.cols = 0;
392 m.allocator = NULL;
393 m.u = NULL;
394 m.offset = 0;
395 }
396
operator =(UMat && m)397 UMat& UMat::operator=(UMat&& m)
398 {
399 if (this == &m)
400 return *this;
401 release();
402 flags = m.flags; dims = m.dims; rows = m.rows; cols = m.cols;
403 allocator = m.allocator; usageFlags = m.usageFlags;
404 u = m.u;
405 offset = m.offset;
406 if (step.p != step.buf) // release self step/size
407 {
408 fastFree(step.p);
409 step.p = step.buf;
410 size.p = &rows;
411 }
412 if (m.dims <= 2) // move new step/size info
413 {
414 step[0] = m.step[0];
415 step[1] = m.step[1];
416 }
417 else
418 {
419 CV_DbgAssert(m.step.p != m.step.buf);
420 step.p = m.step.p;
421 size.p = m.size.p;
422 m.step.p = m.step.buf;
423 m.size.p = &m.rows;
424 }
425 m.flags = MAGIC_VAL;
426 m.usageFlags = USAGE_DEFAULT;
427 m.dims = m.rows = m.cols = 0;
428 m.allocator = NULL;
429 m.u = NULL;
430 m.offset = 0;
431 return *this;
432 }
433
434
getStdAllocator()435 MatAllocator* UMat::getStdAllocator()
436 {
437 #ifdef HAVE_OPENCL
438 if (ocl::useOpenCL())
439 return ocl::getOpenCLAllocator();
440 #endif
441 return Mat::getDefaultAllocator();
442 }
443
swap(UMat & a,UMat & b)444 void swap( UMat& a, UMat& b )
445 {
446 std::swap(a.flags, b.flags);
447 std::swap(a.dims, b.dims);
448 std::swap(a.rows, b.rows);
449 std::swap(a.cols, b.cols);
450 std::swap(a.allocator, b.allocator);
451 std::swap(a.u, b.u);
452 std::swap(a.offset, b.offset);
453
454 std::swap(a.size.p, b.size.p);
455 std::swap(a.step.p, b.step.p);
456 std::swap(a.step.buf[0], b.step.buf[0]);
457 std::swap(a.step.buf[1], b.step.buf[1]);
458
459 if( a.step.p == b.step.buf )
460 {
461 a.step.p = a.step.buf;
462 a.size.p = &a.rows;
463 }
464
465 if( b.step.p == a.step.buf )
466 {
467 b.step.p = b.step.buf;
468 b.size.p = &b.rows;
469 }
470 }
471
472
setSize(UMat & m,int _dims,const int * _sz,const size_t * _steps,bool autoSteps)473 void setSize( UMat& m, int _dims, const int* _sz,
474 const size_t* _steps, bool autoSteps )
475 {
476 CV_Assert( 0 <= _dims && _dims <= CV_MAX_DIM );
477 if( m.dims != _dims )
478 {
479 if( m.step.p != m.step.buf )
480 {
481 fastFree(m.step.p);
482 m.step.p = m.step.buf;
483 m.size.p = &m.rows;
484 }
485 if( _dims > 2 )
486 {
487 m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0]));
488 m.size.p = (int*)(m.step.p + _dims) + 1;
489 m.size.p[-1] = _dims;
490 m.rows = m.cols = -1;
491 }
492 }
493
494 m.dims = _dims;
495 if( !_sz )
496 return;
497
498 size_t esz = CV_ELEM_SIZE(m.flags), total = esz;
499 int i;
500 for( i = _dims-1; i >= 0; i-- )
501 {
502 int s = _sz[i];
503 CV_Assert( s >= 0 );
504 m.size.p[i] = s;
505
506 if( _steps )
507 m.step.p[i] = i < _dims-1 ? _steps[i] : esz;
508 else if( autoSteps )
509 {
510 m.step.p[i] = total;
511 int64 total1 = (int64)total*s;
512 if( (uint64)total1 != (size_t)total1 )
513 CV_Error( CV_StsOutOfRange, "The total matrix size does not fit to \"size_t\" type" );
514 total = (size_t)total1;
515 }
516 }
517
518 if( _dims == 1 )
519 {
520 m.dims = 2;
521 m.cols = 1;
522 m.step[1] = esz;
523 }
524 }
525
526
updateContinuityFlag()527 void UMat::updateContinuityFlag()
528 {
529 flags = cv::updateContinuityFlag(flags, dims, size.p, step.p);
530 }
531
532
finalizeHdr(UMat & m)533 void finalizeHdr(UMat& m)
534 {
535 m.updateContinuityFlag();
536 int d = m.dims;
537 if( d > 2 )
538 m.rows = m.cols = -1;
539 }
540
541
getUMat(AccessFlag accessFlags,UMatUsageFlags usageFlags) const542 UMat Mat::getUMat(AccessFlag accessFlags, UMatUsageFlags usageFlags) const
543 {
544 UMat hdr;
545 if(!data)
546 return hdr;
547 if (data != datastart)
548 {
549 Size wholeSize;
550 Point ofs;
551 locateROI(wholeSize, ofs);
552 Size sz(cols, rows);
553 if (ofs.x != 0 || ofs.y != 0)
554 {
555 Mat src = *this;
556 int dtop = ofs.y;
557 int dbottom = wholeSize.height - src.rows - ofs.y;
558 int dleft = ofs.x;
559 int dright = wholeSize.width - src.cols - ofs.x;
560 src.adjustROI(dtop, dbottom, dleft, dright);
561 return src.getUMat(accessFlags, usageFlags)(cv::Rect(ofs.x, ofs.y, sz.width, sz.height));
562 }
563 }
564 CV_Assert(data == datastart);
565
566 accessFlags |= ACCESS_RW;
567 UMatData* new_u = NULL;
568 {
569 MatAllocator *a = allocator, *a0 = getDefaultAllocator();
570 if(!a)
571 a = a0;
572 new_u = a->allocate(dims, size.p, type(), data, step.p, accessFlags, usageFlags);
573 new_u->originalUMatData = u;
574 }
575 bool allocated = false;
576 try
577 {
578 allocated = UMat::getStdAllocator()->allocate(new_u, accessFlags, usageFlags);
579 }
580 catch (const cv::Exception& e)
581 {
582 fprintf(stderr, "Exception: %s\n", e.what());
583 }
584 if (!allocated)
585 {
586 allocated = getDefaultAllocator()->allocate(new_u, accessFlags, usageFlags);
587 CV_Assert(allocated);
588 }
589 if (u != NULL)
590 {
591 #ifdef HAVE_OPENCL
592 if (ocl::useOpenCL() && new_u->currAllocator == ocl::getOpenCLAllocator())
593 {
594 CV_Assert(new_u->tempUMat());
595 }
596 #endif
597 CV_XADD(&(u->refcount), 1);
598 CV_XADD(&(u->urefcount), 1);
599 }
600 hdr.flags = flags;
601 hdr.usageFlags = usageFlags;
602 setSize(hdr, dims, size.p, step.p);
603 finalizeHdr(hdr);
604 hdr.u = new_u;
605 hdr.offset = 0; //data - datastart;
606 hdr.addref();
607 return hdr;
608 }
609
create(int d,const int * _sizes,int _type,UMatUsageFlags _usageFlags)610 void UMat::create(int d, const int* _sizes, int _type, UMatUsageFlags _usageFlags)
611 {
612 int i;
613 CV_Assert(0 <= d && d <= CV_MAX_DIM && _sizes);
614 _type = CV_MAT_TYPE(_type);
615
616 // if param value is USAGE_DEFAULT by implicit default param value -or- explicit value
617 // ...then don't change the existing usageFlags
618 // it is not possible to change usage from non-default to USAGE_DEFAULT through create()
619 // ...instead must construct UMat()
620 if (_usageFlags == cv::USAGE_DEFAULT)
621 {
622 _usageFlags = usageFlags;
623 }
624
625 if( u && (d == dims || (d == 1 && dims <= 2)) && _type == type() && _usageFlags == usageFlags )
626 {
627 for( i = 0; i < d; i++ )
628 if( size[i] != _sizes[i] )
629 break;
630 if( i == d && (d > 1 || size[1] == 1))
631 return;
632 }
633
634 int _sizes_backup[CV_MAX_DIM]; // #5991
635 if (_sizes == (this->size.p))
636 {
637 for(i = 0; i < d; i++ )
638 _sizes_backup[i] = _sizes[i];
639 _sizes = _sizes_backup;
640 }
641
642 release();
643 usageFlags = _usageFlags;
644 if( d == 0 )
645 return;
646 flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL;
647 setSize(*this, d, _sizes, 0, true);
648 offset = 0;
649
650 if( total() > 0 )
651 {
652 MatAllocator *a = allocator, *a0 = getStdAllocator();
653 if (!a)
654 {
655 a = a0;
656 a0 = Mat::getDefaultAllocator();
657 }
658 try
659 {
660 u = a->allocate(dims, size, _type, 0, step.p, ACCESS_RW /* ignored */, usageFlags);
661 CV_Assert(u != 0);
662 }
663 catch(...)
664 {
665 if(a != a0)
666 u = a0->allocate(dims, size, _type, 0, step.p, ACCESS_RW /* ignored */, usageFlags);
667 CV_Assert(u != 0);
668 }
669 CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
670 }
671
672 finalizeHdr(*this);
673 addref();
674 }
675
create(const std::vector<int> & _sizes,int _type,UMatUsageFlags _usageFlags)676 void UMat::create(const std::vector<int>& _sizes, int _type, UMatUsageFlags _usageFlags)
677 {
678 create((int)_sizes.size(), _sizes.data(), _type, _usageFlags);
679 }
680
copySize(const UMat & m)681 void UMat::copySize(const UMat& m)
682 {
683 setSize(*this, m.dims, 0, 0);
684 for( int i = 0; i < dims; i++ )
685 {
686 size[i] = m.size[i];
687 step[i] = m.step[i];
688 }
689 }
690
691
~UMat()692 UMat::~UMat()
693 {
694 release();
695 if( step.p != step.buf )
696 fastFree(step.p);
697 }
698
deallocate()699 void UMat::deallocate()
700 {
701 UMatData* u_ = u;
702 u = NULL;
703 u_->currAllocator->deallocate(u_);
704 }
705
706
UMat(const UMat & m,const Range & _rowRange,const Range & _colRange)707 UMat::UMat(const UMat& m, const Range& _rowRange, const Range& _colRange)
708 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows)
709 {
710 CV_Assert( m.dims >= 2 );
711 if( m.dims > 2 )
712 {
713 AutoBuffer<Range> rs(m.dims);
714 rs[0] = _rowRange;
715 rs[1] = _colRange;
716 for( int i = 2; i < m.dims; i++ )
717 rs[i] = Range::all();
718 *this = m(rs.data());
719 return;
720 }
721
722 *this = m;
723 if( _rowRange != Range::all() && _rowRange != Range(0,rows) )
724 {
725 CV_Assert( 0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows );
726 rows = _rowRange.size();
727 offset += step*_rowRange.start;
728 flags |= SUBMATRIX_FLAG;
729 }
730
731 if( _colRange != Range::all() && _colRange != Range(0,cols) )
732 {
733 CV_Assert( 0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols );
734 cols = _colRange.size();
735 offset += _colRange.start*elemSize();
736 flags |= SUBMATRIX_FLAG;
737 }
738
739 updateContinuityFlag();
740
741 if( rows <= 0 || cols <= 0 )
742 {
743 release();
744 rows = cols = 0;
745 }
746 }
747
748
UMat(const UMat & m,const Rect & roi)749 UMat::UMat(const UMat& m, const Rect& roi)
750 : flags(m.flags), dims(2), rows(roi.height), cols(roi.width),
751 allocator(m.allocator), usageFlags(m.usageFlags), u(m.u), offset(m.offset + roi.y*m.step[0]), size(&rows)
752 {
753 CV_Assert( m.dims <= 2 );
754
755 size_t esz = CV_ELEM_SIZE(flags);
756 offset += roi.x*esz;
757 CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols &&
758 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows );
759 if( u )
760 CV_XADD(&(u->urefcount), 1);
761 if( roi.width < m.cols || roi.height < m.rows )
762 flags |= SUBMATRIX_FLAG;
763
764 step[0] = m.step[0]; step[1] = esz;
765 updateContinuityFlag();
766
767 if( rows <= 0 || cols <= 0 )
768 {
769 release();
770 rows = cols = 0;
771 }
772 }
773
774
UMat(const UMat & m,const Range * ranges)775 UMat::UMat(const UMat& m, const Range* ranges)
776 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows)
777 {
778 int i, d = m.dims;
779
780 CV_Assert(ranges);
781 for( i = 0; i < d; i++ )
782 {
783 Range r = ranges[i];
784 CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) );
785 }
786 *this = m;
787 for( i = 0; i < d; i++ )
788 {
789 Range r = ranges[i];
790 if( r != Range::all() && r != Range(0, size.p[i]))
791 {
792 size.p[i] = r.end - r.start;
793 offset += r.start*step.p[i];
794 flags |= SUBMATRIX_FLAG;
795 }
796 }
797 updateContinuityFlag();
798 }
799
UMat(const UMat & m,const std::vector<Range> & ranges)800 UMat::UMat(const UMat& m, const std::vector<Range>& ranges)
801 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows)
802 {
803 int i, d = m.dims;
804
805 CV_Assert((int)ranges.size() == d);
806 for (i = 0; i < d; i++)
807 {
808 Range r = ranges[i];
809 CV_Assert(r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]));
810 }
811 *this = m;
812 for (i = 0; i < d; i++)
813 {
814 Range r = ranges[i];
815 if (r != Range::all() && r != Range(0, size.p[i]))
816 {
817 size.p[i] = r.end - r.start;
818 offset += r.start*step.p[i];
819 flags |= SUBMATRIX_FLAG;
820 }
821 }
822 updateContinuityFlag();
823 }
824
diag(int d) const825 UMat UMat::diag(int d) const
826 {
827 CV_Assert( dims <= 2 );
828 UMat m = *this;
829 size_t esz = elemSize();
830 int len;
831
832 if( d >= 0 )
833 {
834 len = std::min(cols - d, rows);
835 m.offset += esz*d;
836 }
837 else
838 {
839 len = std::min(rows + d, cols);
840 m.offset -= step[0]*d;
841 }
842 CV_DbgAssert( len > 0 );
843
844 m.size[0] = m.rows = len;
845 m.size[1] = m.cols = 1;
846 m.step[0] += (len > 1 ? esz : 0);
847
848 m.updateContinuityFlag();
849
850 if( size() != Size(1,1) )
851 m.flags |= SUBMATRIX_FLAG;
852
853 return m;
854 }
855
locateROI(Size & wholeSize,Point & ofs) const856 void UMat::locateROI( Size& wholeSize, Point& ofs ) const
857 {
858 CV_Assert( dims <= 2 && step[0] > 0 );
859 size_t esz = elemSize(), minstep;
860 ptrdiff_t delta1 = (ptrdiff_t)offset, delta2 = (ptrdiff_t)u->size;
861
862 if( delta1 == 0 )
863 ofs.x = ofs.y = 0;
864 else
865 {
866 ofs.y = (int)(delta1/step[0]);
867 ofs.x = (int)((delta1 - step[0]*ofs.y)/esz);
868 CV_DbgAssert( offset == (size_t)(ofs.y*step[0] + ofs.x*esz) );
869 }
870 minstep = (ofs.x + cols)*esz;
871 wholeSize.height = (int)((delta2 - minstep)/step[0] + 1);
872 wholeSize.height = std::max(wholeSize.height, ofs.y + rows);
873 wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz);
874 wholeSize.width = std::max(wholeSize.width, ofs.x + cols);
875 }
876
877
adjustROI(int dtop,int dbottom,int dleft,int dright)878 UMat& UMat::adjustROI( int dtop, int dbottom, int dleft, int dright )
879 {
880 CV_Assert( dims <= 2 && step[0] > 0 );
881 Size wholeSize; Point ofs;
882 size_t esz = elemSize();
883 locateROI( wholeSize, ofs );
884 int row1 = std::min(std::max(ofs.y - dtop, 0), wholeSize.height), row2 = std::max(0, std::min(ofs.y + rows + dbottom, wholeSize.height));
885 int col1 = std::min(std::max(ofs.x - dleft, 0), wholeSize.width), col2 = std::max(0, std::min(ofs.x + cols + dright, wholeSize.width));
886 if(row1 > row2)
887 std::swap(row1, row2);
888 if(col1 > col2)
889 std::swap(col1, col2);
890
891 offset += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
892 rows = row2 - row1; cols = col2 - col1;
893 size.p[0] = rows; size.p[1] = cols;
894 updateContinuityFlag();
895 return *this;
896 }
897
898
reshape(int new_cn,int new_rows) const899 UMat UMat::reshape(int new_cn, int new_rows) const
900 {
901 int cn = channels();
902 UMat hdr = *this;
903
904 if( dims > 2 && new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 )
905 {
906 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
907 hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags);
908 hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn;
909 return hdr;
910 }
911
912 CV_Assert( dims <= 2 );
913
914 if( new_cn == 0 )
915 new_cn = cn;
916
917 int total_width = cols * cn;
918
919 if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )
920 new_rows = rows * total_width / new_cn;
921
922 if( new_rows != 0 && new_rows != rows )
923 {
924 int total_size = total_width * rows;
925 if( !isContinuous() )
926 CV_Error( CV_BadStep,
927 "The matrix is not continuous, thus its number of rows can not be changed" );
928
929 if( (unsigned)new_rows > (unsigned)total_size )
930 CV_Error( CV_StsOutOfRange, "Bad new number of rows" );
931
932 total_width = total_size / new_rows;
933
934 if( total_width * new_rows != total_size )
935 CV_Error( CV_StsBadArg, "The total number of matrix elements "
936 "is not divisible by the new number of rows" );
937
938 hdr.rows = new_rows;
939 hdr.step[0] = total_width * elemSize1();
940 }
941
942 int new_width = total_width / new_cn;
943
944 if( new_width * new_cn != total_width )
945 CV_Error( CV_BadNumChannels,
946 "The total width is not divisible by the new number of channels" );
947
948 hdr.cols = new_width;
949 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
950 hdr.step[1] = CV_ELEM_SIZE(hdr.flags);
951 return hdr;
952 }
953
diag(const UMat & d,UMatUsageFlags usageFlags)954 UMat UMat::diag(const UMat& d, UMatUsageFlags usageFlags)
955 {
956 CV_Assert( d.cols == 1 || d.rows == 1 );
957 int len = d.rows + d.cols - 1;
958 UMat m(len, len, d.type(), Scalar(0), usageFlags);
959 UMat md = m.diag();
960 if( d.cols == 1 )
961 d.copyTo(md);
962 else
963 transpose(d, md);
964 return m;
965 }
966
checkVector(int _elemChannels,int _depth,bool _requireContinuous) const967 int UMat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const
968 {
969 return (depth() == _depth || _depth <= 0) &&
970 (isContinuous() || !_requireContinuous) &&
971 ((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) ||
972 (cols == _elemChannels && channels() == 1))) ||
973 (dims == 3 && channels() == 1 && size.p[2] == _elemChannels && (size.p[0] == 1 || size.p[1] == 1) &&
974 (isContinuous() || step.p[1] == step.p[2]*size.p[2])))
975 ? (int)(total()*channels()/_elemChannels) : -1;
976 }
977
reshape(int _cn,int _newndims,const int * _newsz) const978 UMat UMat::reshape(int _cn, int _newndims, const int* _newsz) const
979 {
980 if(_newndims == dims)
981 {
982 if(_newsz == 0)
983 return reshape(_cn);
984 if(_newndims == 2)
985 return reshape(_cn, _newsz[0]);
986 }
987
988 if (isContinuous())
989 {
990 CV_Assert(_cn >= 0 && _newndims > 0 && _newndims <= CV_MAX_DIM && _newsz);
991
992 if (_cn == 0)
993 _cn = this->channels();
994 else
995 CV_Assert(_cn <= CV_CN_MAX);
996
997 size_t total_elem1_ref = this->total() * this->channels();
998 size_t total_elem1 = _cn;
999
1000 AutoBuffer<int, 4> newsz_buf( (size_t)_newndims );
1001
1002 for (int i = 0; i < _newndims; i++)
1003 {
1004 CV_Assert(_newsz[i] >= 0);
1005
1006 if (_newsz[i] > 0)
1007 newsz_buf[i] = _newsz[i];
1008 else if (i < dims)
1009 newsz_buf[i] = this->size[i];
1010 else
1011 CV_Error(CV_StsOutOfRange, "Copy dimension (which has zero size) is not present in source matrix");
1012
1013 total_elem1 *= (size_t)newsz_buf[i];
1014 }
1015
1016 if (total_elem1 != total_elem1_ref)
1017 CV_Error(CV_StsUnmatchedSizes, "Requested and source matrices have different count of elements");
1018
1019 UMat hdr = *this;
1020 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((_cn-1) << CV_CN_SHIFT);
1021 setSize(hdr, _newndims, newsz_buf.data(), NULL, true);
1022
1023 return hdr;
1024 }
1025
1026 CV_Error(CV_StsNotImplemented, "Reshaping of n-dimensional non-continuous matrices is not supported yet");
1027 }
1028
getMat(AccessFlag accessFlags) const1029 Mat UMat::getMat(AccessFlag accessFlags) const
1030 {
1031 if(!u)
1032 return Mat();
1033 // TODO Support ACCESS_READ (ACCESS_WRITE) without unnecessary data transfers
1034 accessFlags |= ACCESS_RW;
1035 UMatDataAutoLock autolock(u);
1036 if(CV_XADD(&u->refcount, 1) == 0)
1037 u->currAllocator->map(u, accessFlags);
1038 if (u->data != 0)
1039 {
1040 Mat hdr(dims, size.p, type(), u->data + offset, step.p);
1041 hdr.flags = flags;
1042 hdr.u = u;
1043 hdr.datastart = u->data;
1044 hdr.data = u->data + offset;
1045 hdr.datalimit = hdr.dataend = u->data + u->size;
1046 return hdr;
1047 }
1048 else
1049 {
1050 CV_XADD(&u->refcount, -1);
1051 CV_Assert(u->data != 0 && "Error mapping of UMat to host memory.");
1052 return Mat();
1053 }
1054 }
1055
handle(AccessFlag accessFlags) const1056 void* UMat::handle(AccessFlag accessFlags) const
1057 {
1058 if( !u )
1059 return 0;
1060
1061 CV_Assert(u->refcount == 0);
1062 CV_Assert(!u->deviceCopyObsolete() || u->copyOnMap());
1063 if (u->deviceCopyObsolete())
1064 {
1065 u->currAllocator->unmap(u);
1066 }
1067
1068 if (!!(accessFlags & ACCESS_WRITE))
1069 u->markHostCopyObsolete(true);
1070
1071 return u->handle;
1072 }
1073
ndoffset(size_t * ofs) const1074 void UMat::ndoffset(size_t* ofs) const
1075 {
1076 // offset = step[0]*ofs[0] + step[1]*ofs[1] + step[2]*ofs[2] + ...;
1077 size_t val = offset;
1078 for( int i = 0; i < dims; i++ )
1079 {
1080 size_t s = step.p[i];
1081 ofs[i] = val / s;
1082 val -= ofs[i]*s;
1083 }
1084 }
1085
copyTo(OutputArray _dst) const1086 void UMat::copyTo(OutputArray _dst) const
1087 {
1088 CV_INSTRUMENT_REGION();
1089
1090 #ifdef HAVE_CUDA
1091 if (_dst.isGpuMat())
1092 {
1093 _dst.getGpuMat().upload(*this);
1094 return;
1095 }
1096 #endif
1097
1098 int dtype = _dst.type();
1099 if( _dst.fixedType() && dtype != type() )
1100 {
1101 CV_Assert( channels() == CV_MAT_CN(dtype) );
1102 convertTo( _dst, dtype );
1103 return;
1104 }
1105
1106 if( empty() )
1107 {
1108 _dst.release();
1109 return;
1110 }
1111
1112 size_t i, sz[CV_MAX_DIM] = {0}, srcofs[CV_MAX_DIM], dstofs[CV_MAX_DIM], esz = elemSize();
1113 for( i = 0; i < (size_t)dims; i++ )
1114 sz[i] = size.p[i];
1115 sz[dims-1] *= esz;
1116 ndoffset(srcofs);
1117 srcofs[dims-1] *= esz;
1118
1119 _dst.create( dims, size.p, type() );
1120 if( _dst.isUMat() )
1121 {
1122 UMat dst = _dst.getUMat();
1123 CV_Assert(dst.u);
1124 if( u == dst.u && dst.offset == offset )
1125 return;
1126
1127 if (u->currAllocator == dst.u->currAllocator)
1128 {
1129 dst.ndoffset(dstofs);
1130 dstofs[dims-1] *= esz;
1131 u->currAllocator->copy(u, dst.u, dims, sz, srcofs, step.p, dstofs, dst.step.p, false);
1132 return;
1133 }
1134 }
1135
1136 Mat dst = _dst.getMat();
1137 u->currAllocator->download(u, dst.ptr(), dims, sz, srcofs, step.p, dst.step.p);
1138 }
1139
copyTo(OutputArray _dst,InputArray _mask) const1140 void UMat::copyTo(OutputArray _dst, InputArray _mask) const
1141 {
1142 CV_INSTRUMENT_REGION();
1143
1144 if( _mask.empty() )
1145 {
1146 copyTo(_dst);
1147 return;
1148 }
1149 #ifdef HAVE_OPENCL
1150 int cn = channels(), mtype = _mask.type(), mdepth = CV_MAT_DEPTH(mtype), mcn = CV_MAT_CN(mtype);
1151 CV_Assert( mdepth == CV_8U && (mcn == 1 || mcn == cn) );
1152
1153 if (ocl::useOpenCL() && _dst.isUMat() && dims <= 2)
1154 {
1155 UMatData * prevu = _dst.getUMat().u;
1156 _dst.create( dims, size, type() );
1157
1158 UMat dst = _dst.getUMat();
1159
1160 bool haveDstUninit = false;
1161 if( prevu != dst.u ) // do not leave dst uninitialized
1162 haveDstUninit = true;
1163
1164 String opts = format("-D COPY_TO_MASK -D T1=%s -D scn=%d -D mcn=%d%s",
1165 ocl::memopTypeToStr(depth()), cn, mcn,
1166 haveDstUninit ? " -D HAVE_DST_UNINIT" : "");
1167
1168 ocl::Kernel k("copyToMask", ocl::core::copyset_oclsrc, opts);
1169 if (!k.empty())
1170 {
1171 k.args(ocl::KernelArg::ReadOnlyNoSize(*this),
1172 ocl::KernelArg::ReadOnlyNoSize(_mask.getUMat()),
1173 haveDstUninit ? ocl::KernelArg::WriteOnly(dst) :
1174 ocl::KernelArg::ReadWrite(dst));
1175
1176 size_t globalsize[2] = { (size_t)cols, (size_t)rows };
1177 if (k.run(2, globalsize, NULL, false))
1178 {
1179 CV_IMPL_ADD(CV_IMPL_OCL);
1180 return;
1181 }
1182 }
1183 }
1184 #endif
1185 Mat src = getMat(ACCESS_READ);
1186 src.copyTo(_dst, _mask);
1187 }
1188
convertTo(OutputArray _dst,int _type,double alpha,double beta) const1189 void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const
1190 {
1191 CV_INSTRUMENT_REGION();
1192
1193 bool noScale = std::fabs(alpha - 1) < DBL_EPSILON && std::fabs(beta) < DBL_EPSILON;
1194 int stype = type(), cn = CV_MAT_CN(stype);
1195
1196 if( _type < 0 )
1197 _type = _dst.fixedType() ? _dst.type() : stype;
1198 else
1199 _type = CV_MAKETYPE(CV_MAT_DEPTH(_type), cn);
1200
1201 int sdepth = CV_MAT_DEPTH(stype), ddepth = CV_MAT_DEPTH(_type);
1202 if( sdepth == ddepth && noScale )
1203 {
1204 copyTo(_dst);
1205 return;
1206 }
1207 #ifdef HAVE_OPENCL
1208 bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
1209 bool needDouble = sdepth == CV_64F || ddepth == CV_64F;
1210 if( dims <= 2 && cn && _dst.isUMat() && ocl::useOpenCL() &&
1211 ((needDouble && doubleSupport) || !needDouble) )
1212 {
1213 int wdepth = std::max(CV_32F, sdepth), rowsPerWI = 4;
1214
1215 char cvt[2][40];
1216 ocl::Kernel k("convertTo", ocl::core::convert_oclsrc,
1217 format("-D srcT=%s -D WT=%s -D dstT=%s -D convertToWT=%s -D convertToDT=%s%s%s",
1218 ocl::typeToStr(sdepth), ocl::typeToStr(wdepth), ocl::typeToStr(ddepth),
1219 ocl::convertTypeStr(sdepth, wdepth, 1, cvt[0]),
1220 ocl::convertTypeStr(wdepth, ddepth, 1, cvt[1]),
1221 doubleSupport ? " -D DOUBLE_SUPPORT" : "", noScale ? " -D NO_SCALE" : ""));
1222 if (!k.empty())
1223 {
1224 UMat src = *this;
1225 _dst.create( size(), _type );
1226 UMat dst = _dst.getUMat();
1227
1228 float alphaf = (float)alpha, betaf = (float)beta;
1229 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
1230 dstarg = ocl::KernelArg::WriteOnly(dst, cn);
1231
1232 if (noScale)
1233 k.args(srcarg, dstarg, rowsPerWI);
1234 else if (wdepth == CV_32F)
1235 k.args(srcarg, dstarg, alphaf, betaf, rowsPerWI);
1236 else
1237 k.args(srcarg, dstarg, alpha, beta, rowsPerWI);
1238
1239 size_t globalsize[2] = { (size_t)dst.cols * cn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI };
1240 if (k.run(2, globalsize, NULL, false))
1241 {
1242 CV_IMPL_ADD(CV_IMPL_OCL);
1243 return;
1244 }
1245 }
1246 }
1247 #endif
1248 UMat src = *this; // Fake reference to itself.
1249 // Resolves issue 8693 in case of src == dst.
1250 Mat m = getMat(ACCESS_READ);
1251 m.convertTo(_dst, _type, alpha, beta);
1252 }
1253
setTo(InputArray _value,InputArray _mask)1254 UMat& UMat::setTo(InputArray _value, InputArray _mask)
1255 {
1256 CV_INSTRUMENT_REGION();
1257
1258 bool haveMask = !_mask.empty();
1259 #ifdef HAVE_OPENCL
1260 int tp = type(), cn = CV_MAT_CN(tp), d = CV_MAT_DEPTH(tp);
1261
1262 if( dims <= 2 && cn <= 4 && CV_MAT_DEPTH(tp) < CV_64F && ocl::useOpenCL() )
1263 {
1264 Mat value = _value.getMat();
1265 CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::UMAT) );
1266 int kercn = haveMask || cn == 3 ? cn : std::max(cn, ocl::predictOptimalVectorWidth(*this)),
1267 kertp = CV_MAKE_TYPE(d, kercn);
1268
1269 double buf[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
1270 0, 0, 0, 0, 0, 0, 0, 0 };
1271 convertAndUnrollScalar(value, tp, (uchar *)buf, kercn / cn);
1272
1273 int scalarcn = kercn == 3 ? 4 : kercn, rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1;
1274 String opts = format("-D dstT=%s -D rowsPerWI=%d -D dstST=%s -D dstT1=%s -D cn=%d",
1275 ocl::memopTypeToStr(kertp), rowsPerWI,
1276 ocl::memopTypeToStr(CV_MAKETYPE(d, scalarcn)),
1277 ocl::memopTypeToStr(d), kercn);
1278
1279 ocl::Kernel setK(haveMask ? "setMask" : "set", ocl::core::copyset_oclsrc, opts);
1280 if( !setK.empty() )
1281 {
1282 ocl::KernelArg scalararg(ocl::KernelArg::CONSTANT, 0, 0, 0, buf, CV_ELEM_SIZE(d) * scalarcn);
1283 UMat mask;
1284
1285 if( haveMask )
1286 {
1287 mask = _mask.getUMat();
1288 CV_Assert( mask.size() == size() && mask.type() == CV_8UC1 );
1289 ocl::KernelArg maskarg = ocl::KernelArg::ReadOnlyNoSize(mask),
1290 dstarg = ocl::KernelArg::ReadWrite(*this);
1291 setK.args(maskarg, dstarg, scalararg);
1292 }
1293 else
1294 {
1295 ocl::KernelArg dstarg = ocl::KernelArg::WriteOnly(*this, cn, kercn);
1296 setK.args(dstarg, scalararg);
1297 }
1298
1299 size_t globalsize[] = { (size_t)cols * cn / kercn, ((size_t)rows + rowsPerWI - 1) / rowsPerWI };
1300 if( setK.run(2, globalsize, NULL, false) )
1301 {
1302 CV_IMPL_ADD(CV_IMPL_OCL);
1303 return *this;
1304 }
1305 }
1306 }
1307 #endif
1308 Mat m = getMat(haveMask ? ACCESS_RW : ACCESS_WRITE);
1309 m.setTo(_value, _mask);
1310 return *this;
1311 }
1312
operator =(const Scalar & s)1313 UMat& UMat::operator = (const Scalar& s)
1314 {
1315 setTo(s);
1316 return *this;
1317 }
1318
t() const1319 UMat UMat::t() const
1320 {
1321 UMat m;
1322 transpose(*this, m);
1323 return m;
1324 }
1325
zeros(int rows,int cols,int type,UMatUsageFlags usageFlags)1326 UMat UMat::zeros(int rows, int cols, int type, UMatUsageFlags usageFlags)
1327 {
1328 return UMat(rows, cols, type, Scalar::all(0), usageFlags);
1329 }
1330
zeros(Size size,int type,UMatUsageFlags usageFlags)1331 UMat UMat::zeros(Size size, int type, UMatUsageFlags usageFlags)
1332 {
1333 return UMat(size, type, Scalar::all(0), usageFlags);
1334 }
1335
zeros(int ndims,const int * sz,int type,UMatUsageFlags usageFlags)1336 UMat UMat::zeros(int ndims, const int* sz, int type, UMatUsageFlags usageFlags)
1337 {
1338 return UMat(ndims, sz, type, Scalar::all(0), usageFlags);
1339 }
1340
ones(int rows,int cols,int type,UMatUsageFlags usageFlags)1341 UMat UMat::ones(int rows, int cols, int type, UMatUsageFlags usageFlags)
1342 {
1343 return UMat(rows, cols, type, Scalar(1), usageFlags);
1344 }
1345
ones(Size size,int type,UMatUsageFlags usageFlags)1346 UMat UMat::ones(Size size, int type, UMatUsageFlags usageFlags)
1347 {
1348 return UMat(size, type, Scalar(1), usageFlags);
1349 }
1350
ones(int ndims,const int * sz,int type,UMatUsageFlags usageFlags)1351 UMat UMat::ones(int ndims, const int* sz, int type, UMatUsageFlags usageFlags)
1352 {
1353 return UMat(ndims, sz, type, Scalar(1), usageFlags);
1354 }
1355
1356 }
1357
1358 /* End of file. */
1359