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) 2000-2008, Intel Corporation, all rights reserved. 14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved. 15 // Copyright (C) 2013, OpenCV Foundation, all rights reserved. 16 // Third party copyrights are property of their respective owners. 17 // 18 // Redistribution and use in source and binary forms, with or without modification, 19 // are permitted provided that the following conditions are met: 20 // 21 // * Redistribution's of source code must retain the above copyright notice, 22 // this list of conditions and the following disclaimer. 23 // 24 // * Redistribution's in binary form must reproduce the above copyright notice, 25 // this list of conditions and the following disclaimer in the documentation 26 // and/or other materials provided with the distribution. 27 // 28 // * The name of the copyright holders may not be used to endorse or promote products 29 // derived from this software without specific prior written permission. 30 // 31 // This software is provided by the copyright holders and contributors "as is" and 32 // any express or implied warranties, including, but not limited to, the implied 33 // warranties of merchantability and fitness for a particular purpose are disclaimed. 34 // In no event shall the Intel Corporation or contributors be liable for any direct, 35 // indirect, incidental, special, exemplary, or consequential damages 36 // (including, but not limited to, procurement of substitute goods or services; 37 // loss of use, data, or profits; or business interruption) however caused 38 // and on any theory of liability, whether in contract, strict liability, 39 // or tort (including negligence or otherwise) arising in any way out of 40 // the use of this software, even if advised of the possibility of such damage. 41 // 42 //M*/ 43 44 #include "precomp.hpp" 45 46 using namespace cv; 47 using namespace cv::cuda; 48 49 cv::cuda::GpuMat::GpuMat(int rows_, int cols_, int type_, void* data_, size_t step_) : 50 flags(Mat::MAGIC_VAL + (type_ & Mat::TYPE_MASK)), rows(rows_), cols(cols_), 51 step(step_), data((uchar*)data_), refcount(0), 52 datastart((uchar*)data_), dataend((const uchar*)data_), 53 allocator(defaultAllocator()) 54 { 55 size_t minstep = cols * elemSize(); 56 57 if (step == Mat::AUTO_STEP) 58 { 59 step = minstep; 60 flags |= Mat::CONTINUOUS_FLAG; 61 } 62 else 63 { 64 if (rows == 1) 65 step = minstep; 66 67 CV_DbgAssert( step >= minstep ); 68 69 flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0; 70 } 71 72 dataend += step * (rows - 1) + minstep; 73 } 74 75 cv::cuda::GpuMat::GpuMat(Size size_, int type_, void* data_, size_t step_) : 76 flags(Mat::MAGIC_VAL + (type_ & Mat::TYPE_MASK)), rows(size_.height), cols(size_.width), 77 step(step_), data((uchar*)data_), refcount(0), 78 datastart((uchar*)data_), dataend((const uchar*)data_), 79 allocator(defaultAllocator()) 80 { 81 size_t minstep = cols * elemSize(); 82 83 if (step == Mat::AUTO_STEP) 84 { 85 step = minstep; 86 flags |= Mat::CONTINUOUS_FLAG; 87 } 88 else 89 { 90 if (rows == 1) 91 step = minstep; 92 93 CV_DbgAssert( step >= minstep ); 94 95 flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0; 96 } 97 98 dataend += step * (rows - 1) + minstep; 99 } 100 101 cv::cuda::GpuMat::GpuMat(const GpuMat& m, Range rowRange_, Range colRange_) 102 { 103 flags = m.flags; 104 step = m.step; refcount = m.refcount; 105 data = m.data; datastart = m.datastart; dataend = m.dataend; 106 allocator = m.allocator; 107 108 if (rowRange_ == Range::all()) 109 { 110 rows = m.rows; 111 } 112 else 113 { 114 CV_Assert( 0 <= rowRange_.start && rowRange_.start <= rowRange_.end && rowRange_.end <= m.rows ); 115 116 rows = rowRange_.size(); 117 data += step*rowRange_.start; 118 } 119 120 if (colRange_ == Range::all()) 121 { 122 cols = m.cols; 123 } 124 else 125 { 126 CV_Assert( 0 <= colRange_.start && colRange_.start <= colRange_.end && colRange_.end <= m.cols ); 127 128 cols = colRange_.size(); 129 data += colRange_.start*elemSize(); 130 flags &= cols < m.cols ? ~Mat::CONTINUOUS_FLAG : -1; 131 } 132 133 if (rows == 1) 134 flags |= Mat::CONTINUOUS_FLAG; 135 136 if (refcount) 137 CV_XADD(refcount, 1); 138 139 if (rows <= 0 || cols <= 0) 140 rows = cols = 0; 141 } 142 143 cv::cuda::GpuMat::GpuMat(const GpuMat& m, Rect roi) : 144 flags(m.flags), rows(roi.height), cols(roi.width), 145 step(m.step), data(m.data + roi.y*step), refcount(m.refcount), 146 datastart(m.datastart), dataend(m.dataend), 147 allocator(m.allocator) 148 { 149 flags &= roi.width < m.cols ? ~Mat::CONTINUOUS_FLAG : -1; 150 data += roi.x * elemSize(); 151 152 CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows ); 153 154 if (refcount) 155 CV_XADD(refcount, 1); 156 157 if (rows <= 0 || cols <= 0) 158 rows = cols = 0; 159 } 160 161 GpuMat cv::cuda::GpuMat::reshape(int new_cn, int new_rows) const 162 { 163 GpuMat hdr = *this; 164 165 int cn = channels(); 166 if (new_cn == 0) 167 new_cn = cn; 168 169 int total_width = cols * cn; 170 171 if ((new_cn > total_width || total_width % new_cn != 0) && new_rows == 0) 172 new_rows = rows * total_width / new_cn; 173 174 if (new_rows != 0 && new_rows != rows) 175 { 176 int total_size = total_width * rows; 177 178 if (!isContinuous()) 179 CV_Error(cv::Error::BadStep, "The matrix is not continuous, thus its number of rows can not be changed"); 180 181 if ((unsigned)new_rows > (unsigned)total_size) 182 CV_Error(cv::Error::StsOutOfRange, "Bad new number of rows"); 183 184 total_width = total_size / new_rows; 185 186 if (total_width * new_rows != total_size) 187 CV_Error(cv::Error::StsBadArg, "The total number of matrix elements is not divisible by the new number of rows"); 188 189 hdr.rows = new_rows; 190 hdr.step = total_width * elemSize1(); 191 } 192 193 int new_width = total_width / new_cn; 194 195 if (new_width * new_cn != total_width) 196 CV_Error(cv::Error::BadNumChannels, "The total width is not divisible by the new number of channels"); 197 198 hdr.cols = new_width; 199 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn - 1) << CV_CN_SHIFT); 200 201 return hdr; 202 } 203 204 void cv::cuda::GpuMat::locateROI(Size& wholeSize, Point& ofs) const 205 { 206 CV_DbgAssert( step > 0 ); 207 208 size_t esz = elemSize(); 209 ptrdiff_t delta1 = data - datastart; 210 ptrdiff_t delta2 = dataend - datastart; 211 212 if (delta1 == 0) 213 { 214 ofs.x = ofs.y = 0; 215 } 216 else 217 { 218 ofs.y = static_cast<int>(delta1 / step); 219 ofs.x = static_cast<int>((delta1 - step * ofs.y) / esz); 220 221 CV_DbgAssert( data == datastart + ofs.y * step + ofs.x * esz ); 222 } 223 224 size_t minstep = (ofs.x + cols) * esz; 225 226 wholeSize.height = std::max(static_cast<int>((delta2 - minstep) / step + 1), ofs.y + rows); 227 wholeSize.width = std::max(static_cast<int>((delta2 - step * (wholeSize.height - 1)) / esz), ofs.x + cols); 228 } 229 230 GpuMat& cv::cuda::GpuMat::adjustROI(int dtop, int dbottom, int dleft, int dright) 231 { 232 Size wholeSize; 233 Point ofs; 234 locateROI(wholeSize, ofs); 235 236 size_t esz = elemSize(); 237 238 int row1 = std::max(ofs.y - dtop, 0); 239 int row2 = std::min(ofs.y + rows + dbottom, wholeSize.height); 240 241 int col1 = std::max(ofs.x - dleft, 0); 242 int col2 = std::min(ofs.x + cols + dright, wholeSize.width); 243 244 data += (row1 - ofs.y) * step + (col1 - ofs.x) * esz; 245 rows = row2 - row1; 246 cols = col2 - col1; 247 248 if (esz * cols == step || rows == 1) 249 flags |= Mat::CONTINUOUS_FLAG; 250 else 251 flags &= ~Mat::CONTINUOUS_FLAG; 252 253 return *this; 254 } 255 256 namespace 257 { 258 template <class ObjType> 259 void createContinuousImpl(int rows, int cols, int type, ObjType& obj) 260 { 261 const int area = rows * cols; 262 263 if (obj.empty() || obj.type() != type || !obj.isContinuous() || obj.size().area() < area) 264 obj.create(1, area, type); 265 266 obj = obj.reshape(obj.channels(), rows); 267 } 268 } 269 270 void cv::cuda::createContinuous(int rows, int cols, int type, OutputArray arr) 271 { 272 switch (arr.kind()) 273 { 274 case _InputArray::MAT: 275 ::createContinuousImpl(rows, cols, type, arr.getMatRef()); 276 break; 277 278 case _InputArray::CUDA_GPU_MAT: 279 ::createContinuousImpl(rows, cols, type, arr.getGpuMatRef()); 280 break; 281 282 case _InputArray::CUDA_HOST_MEM: 283 ::createContinuousImpl(rows, cols, type, arr.getHostMemRef()); 284 break; 285 286 default: 287 arr.create(rows, cols, type); 288 } 289 } 290 291 namespace 292 { 293 template <class ObjType> 294 void ensureSizeIsEnoughImpl(int rows, int cols, int type, ObjType& obj) 295 { 296 if (obj.empty() || obj.type() != type || obj.data != obj.datastart) 297 { 298 obj.create(rows, cols, type); 299 } 300 else 301 { 302 const size_t esz = obj.elemSize(); 303 const ptrdiff_t delta2 = obj.dataend - obj.datastart; 304 305 const size_t minstep = obj.cols * esz; 306 307 Size wholeSize; 308 wholeSize.height = std::max(static_cast<int>((delta2 - minstep) / static_cast<size_t>(obj.step) + 1), obj.rows); 309 wholeSize.width = std::max(static_cast<int>((delta2 - static_cast<size_t>(obj.step) * (wholeSize.height - 1)) / esz), obj.cols); 310 311 if (wholeSize.height < rows || wholeSize.width < cols) 312 { 313 obj.create(rows, cols, type); 314 } 315 else 316 { 317 obj.cols = cols; 318 obj.rows = rows; 319 } 320 } 321 } 322 } 323 324 void cv::cuda::ensureSizeIsEnough(int rows, int cols, int type, OutputArray arr) 325 { 326 switch (arr.kind()) 327 { 328 case _InputArray::MAT: 329 ::ensureSizeIsEnoughImpl(rows, cols, type, arr.getMatRef()); 330 break; 331 332 case _InputArray::CUDA_GPU_MAT: 333 ::ensureSizeIsEnoughImpl(rows, cols, type, arr.getGpuMatRef()); 334 break; 335 336 case _InputArray::CUDA_HOST_MEM: 337 ::ensureSizeIsEnoughImpl(rows, cols, type, arr.getHostMemRef()); 338 break; 339 340 default: 341 arr.create(rows, cols, type); 342 } 343 } 344 345 GpuMat cv::cuda::getInputMat(InputArray _src, Stream& stream) 346 { 347 GpuMat src; 348 349 #ifndef HAVE_CUDA 350 (void) _src; 351 (void) stream; 352 throw_no_cuda(); 353 #else 354 if (_src.kind() == _InputArray::CUDA_GPU_MAT) 355 { 356 src = _src.getGpuMat(); 357 } 358 else if (!_src.empty()) 359 { 360 BufferPool pool(stream); 361 src = pool.getBuffer(_src.size(), _src.type()); 362 src.upload(_src, stream); 363 } 364 #endif 365 366 return src; 367 } 368 369 GpuMat cv::cuda::getOutputMat(OutputArray _dst, int rows, int cols, int type, Stream& stream) 370 { 371 GpuMat dst; 372 373 #ifndef HAVE_CUDA 374 (void) _dst; 375 (void) rows; 376 (void) cols; 377 (void) type; 378 (void) stream; 379 throw_no_cuda(); 380 #else 381 if (_dst.kind() == _InputArray::CUDA_GPU_MAT) 382 { 383 _dst.create(rows, cols, type); 384 dst = _dst.getGpuMat(); 385 } 386 else 387 { 388 BufferPool pool(stream); 389 dst = pool.getBuffer(rows, cols, type); 390 } 391 #endif 392 393 return dst; 394 } 395 396 void cv::cuda::syncOutput(const GpuMat& dst, OutputArray _dst, Stream& stream) 397 { 398 #ifndef HAVE_CUDA 399 (void) dst; 400 (void) _dst; 401 (void) stream; 402 throw_no_cuda(); 403 #else 404 if (_dst.kind() != _InputArray::CUDA_GPU_MAT) 405 { 406 if (stream) 407 dst.download(_dst, stream); 408 else 409 dst.download(_dst); 410 } 411 #endif 412 } 413 414 #ifndef HAVE_CUDA 415 416 GpuMat::Allocator* cv::cuda::GpuMat::defaultAllocator() 417 { 418 return 0; 419 } 420 421 void cv::cuda::GpuMat::setDefaultAllocator(Allocator* allocator) 422 { 423 (void) allocator; 424 throw_no_cuda(); 425 } 426 427 void cv::cuda::GpuMat::create(int _rows, int _cols, int _type) 428 { 429 (void) _rows; 430 (void) _cols; 431 (void) _type; 432 throw_no_cuda(); 433 } 434 435 void cv::cuda::GpuMat::release() 436 { 437 } 438 439 void cv::cuda::GpuMat::upload(InputArray arr) 440 { 441 (void) arr; 442 throw_no_cuda(); 443 } 444 445 void cv::cuda::GpuMat::upload(InputArray arr, Stream& _stream) 446 { 447 (void) arr; 448 (void) _stream; 449 throw_no_cuda(); 450 } 451 452 void cv::cuda::GpuMat::download(OutputArray _dst) const 453 { 454 (void) _dst; 455 throw_no_cuda(); 456 } 457 458 void cv::cuda::GpuMat::download(OutputArray _dst, Stream& _stream) const 459 { 460 (void) _dst; 461 (void) _stream; 462 throw_no_cuda(); 463 } 464 465 void cv::cuda::GpuMat::copyTo(OutputArray _dst) const 466 { 467 (void) _dst; 468 throw_no_cuda(); 469 } 470 471 void cv::cuda::GpuMat::copyTo(OutputArray _dst, Stream& _stream) const 472 { 473 (void) _dst; 474 (void) _stream; 475 throw_no_cuda(); 476 } 477 478 void cv::cuda::GpuMat::copyTo(OutputArray _dst, InputArray _mask, Stream& _stream) const 479 { 480 (void) _dst; 481 (void) _mask; 482 (void) _stream; 483 throw_no_cuda(); 484 } 485 486 GpuMat& cv::cuda::GpuMat::setTo(Scalar s, Stream& _stream) 487 { 488 (void) s; 489 (void) _stream; 490 throw_no_cuda(); 491 return *this; 492 } 493 494 GpuMat& cv::cuda::GpuMat::setTo(Scalar s, InputArray _mask, Stream& _stream) 495 { 496 (void) s; 497 (void) _mask; 498 (void) _stream; 499 throw_no_cuda(); 500 return *this; 501 } 502 503 void cv::cuda::GpuMat::convertTo(OutputArray _dst, int rtype, Stream& _stream) const 504 { 505 (void) _dst; 506 (void) rtype; 507 (void) _stream; 508 throw_no_cuda(); 509 } 510 511 void cv::cuda::GpuMat::convertTo(OutputArray _dst, int rtype, double alpha, double beta, Stream& _stream) const 512 { 513 (void) _dst; 514 (void) rtype; 515 (void) alpha; 516 (void) beta; 517 (void) _stream; 518 throw_no_cuda(); 519 } 520 521 #endif 522