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