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