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 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
22 //
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
26 //
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #include "precomp.hpp"
44
45 #ifdef HAVE_OPENGL
46 # include "gl_core_3_1.hpp"
47 # ifdef HAVE_CUDA
48 # include <cuda_gl_interop.h>
49 # endif
50 #endif
51
52 using namespace cv;
53 using namespace cv::cuda;
54
55 namespace
56 {
57 #ifndef HAVE_OPENGL
throw_no_ogl()58 inline void throw_no_ogl() { CV_Error(cv::Error::OpenGlNotSupported, "The library is compiled without OpenGL support"); }
59 #else
60 inline void throw_no_ogl() { CV_Error(cv::Error::OpenGlApiCallError, "OpenGL context doesn't exist"); }
61
62 bool checkError(const char* file, const int line, const char* func = 0)
63 {
64 GLenum err = gl::GetError();
65
66 if (err != gl::NO_ERROR_)
67 {
68 const char* msg;
69
70 switch (err)
71 {
72 case gl::INVALID_ENUM:
73 msg = "An unacceptable value is specified for an enumerated argument";
74 break;
75
76 case gl::INVALID_VALUE:
77 msg = "A numeric argument is out of range";
78 break;
79
80 case gl::INVALID_OPERATION:
81 msg = "The specified operation is not allowed in the current state";
82 break;
83
84 case gl::OUT_OF_MEMORY:
85 msg = "There is not enough memory left to execute the command";
86 break;
87
88 default:
89 msg = "Unknown error";
90 };
91
92 cvError(CV_OpenGlApiCallError, func, msg, file, line);
93
94 return false;
95 }
96
97 return true;
98 }
99 #endif
100
101 #define CV_CheckGlError() CV_DbgAssert( (checkError(__FILE__, __LINE__, CV_Func)) )
102 } // namespace
103
104 #ifdef HAVE_OPENGL
105 namespace
106 {
107 const GLenum gl_types[] = { gl::UNSIGNED_BYTE, gl::BYTE, gl::UNSIGNED_SHORT, gl::SHORT, gl::INT, gl::FLOAT, gl::DOUBLE };
108 }
109 #endif
110
111 ////////////////////////////////////////////////////////////////////////
112 // setGlDevice
113
setGlDevice(int device)114 void cv::cuda::setGlDevice(int device)
115 {
116 #ifndef HAVE_OPENGL
117 (void) device;
118 throw_no_ogl();
119 #else
120 #ifndef HAVE_CUDA
121 (void) device;
122 throw_no_cuda();
123 #else
124 cudaSafeCall( cudaGLSetGLDevice(device) );
125 #endif
126 #endif
127 }
128
129 ////////////////////////////////////////////////////////////////////////
130 // CudaResource
131
132 #if defined(HAVE_OPENGL) && defined(HAVE_CUDA)
133
134 namespace
135 {
136 class CudaResource
137 {
138 public:
139 CudaResource();
140 ~CudaResource();
141
142 void registerBuffer(GLuint buffer);
143 void release();
144
145 void copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream = 0);
146 void copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream = 0);
147
148 void* map(cudaStream_t stream = 0);
149 void unmap(cudaStream_t stream = 0);
150
151 private:
152 cudaGraphicsResource_t resource_;
153 GLuint buffer_;
154
155 class GraphicsMapHolder;
156 };
157
CudaResource()158 CudaResource::CudaResource() : resource_(0), buffer_(0)
159 {
160 }
161
~CudaResource()162 CudaResource::~CudaResource()
163 {
164 release();
165 }
166
registerBuffer(GLuint buffer)167 void CudaResource::registerBuffer(GLuint buffer)
168 {
169 CV_DbgAssert( buffer != 0 );
170
171 if (buffer_ == buffer)
172 return;
173
174 cudaGraphicsResource_t resource;
175 cudaSafeCall( cudaGraphicsGLRegisterBuffer(&resource, buffer, cudaGraphicsMapFlagsNone) );
176
177 release();
178
179 resource_ = resource;
180 buffer_ = buffer;
181 }
182
release()183 void CudaResource::release()
184 {
185 if (resource_)
186 cudaGraphicsUnregisterResource(resource_);
187
188 resource_ = 0;
189 buffer_ = 0;
190 }
191
192 class CudaResource::GraphicsMapHolder
193 {
194 public:
195 GraphicsMapHolder(cudaGraphicsResource_t* resource, cudaStream_t stream);
196 ~GraphicsMapHolder();
197
198 void reset();
199
200 private:
201 cudaGraphicsResource_t* resource_;
202 cudaStream_t stream_;
203 };
204
GraphicsMapHolder(cudaGraphicsResource_t * resource,cudaStream_t stream)205 CudaResource::GraphicsMapHolder::GraphicsMapHolder(cudaGraphicsResource_t* resource, cudaStream_t stream) : resource_(resource), stream_(stream)
206 {
207 if (resource_)
208 cudaSafeCall( cudaGraphicsMapResources(1, resource_, stream_) );
209 }
210
~GraphicsMapHolder()211 CudaResource::GraphicsMapHolder::~GraphicsMapHolder()
212 {
213 if (resource_)
214 cudaGraphicsUnmapResources(1, resource_, stream_);
215 }
216
reset()217 void CudaResource::GraphicsMapHolder::reset()
218 {
219 resource_ = 0;
220 }
221
copyFrom(const void * src,size_t spitch,size_t width,size_t height,cudaStream_t stream)222 void CudaResource::copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream)
223 {
224 CV_DbgAssert( resource_ != 0 );
225
226 GraphicsMapHolder h(&resource_, stream);
227 (void) h;
228
229 void* dst;
230 size_t size;
231 cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&dst, &size, resource_) );
232
233 CV_DbgAssert( width * height == size );
234
235 if (stream == 0)
236 cudaSafeCall( cudaMemcpy2D(dst, width, src, spitch, width, height, cudaMemcpyDeviceToDevice) );
237 else
238 cudaSafeCall( cudaMemcpy2DAsync(dst, width, src, spitch, width, height, cudaMemcpyDeviceToDevice, stream) );
239 }
240
copyTo(void * dst,size_t dpitch,size_t width,size_t height,cudaStream_t stream)241 void CudaResource::copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream)
242 {
243 CV_DbgAssert( resource_ != 0 );
244
245 GraphicsMapHolder h(&resource_, stream);
246 (void) h;
247
248 void* src;
249 size_t size;
250 cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&src, &size, resource_) );
251
252 CV_DbgAssert( width * height == size );
253
254 if (stream == 0)
255 cudaSafeCall( cudaMemcpy2D(dst, dpitch, src, width, width, height, cudaMemcpyDeviceToDevice) );
256 else
257 cudaSafeCall( cudaMemcpy2DAsync(dst, dpitch, src, width, width, height, cudaMemcpyDeviceToDevice, stream) );
258 }
259
map(cudaStream_t stream)260 void* CudaResource::map(cudaStream_t stream)
261 {
262 CV_DbgAssert( resource_ != 0 );
263
264 GraphicsMapHolder h(&resource_, stream);
265
266 void* ptr;
267 size_t size;
268 cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&ptr, &size, resource_) );
269
270 h.reset();
271
272 return ptr;
273 }
274
unmap(cudaStream_t stream)275 void CudaResource::unmap(cudaStream_t stream)
276 {
277 CV_Assert( resource_ != 0 );
278
279 cudaGraphicsUnmapResources(1, &resource_, stream);
280 }
281 }
282
283 #endif
284
285 ////////////////////////////////////////////////////////////////////////
286 // ogl::Buffer
287
288 #ifndef HAVE_OPENGL
289
290 class cv::ogl::Buffer::Impl
291 {
292 };
293
294 #else
295
296 class cv::ogl::Buffer::Impl
297 {
298 public:
299 static const Ptr<Impl>& empty();
300
301 Impl(GLuint bufId, bool autoRelease);
302 Impl(GLsizeiptr size, const GLvoid* data, GLenum target, bool autoRelease);
303 ~Impl();
304
305 void bind(GLenum target) const;
306
307 void copyFrom(GLuint srcBuf, GLsizeiptr size);
308
309 void copyFrom(GLsizeiptr size, const GLvoid* data);
310 void copyTo(GLsizeiptr size, GLvoid* data) const;
311
312 void* mapHost(GLenum access);
313 void unmapHost();
314
315 #ifdef HAVE_CUDA
316 void copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream = 0);
317 void copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream = 0) const;
318
319 void* mapDevice(cudaStream_t stream = 0);
320 void unmapDevice(cudaStream_t stream = 0);
321 #endif
322
setAutoRelease(bool flag)323 void setAutoRelease(bool flag) { autoRelease_ = flag; }
324
bufId() const325 GLuint bufId() const { return bufId_; }
326
327 private:
328 Impl();
329
330 GLuint bufId_;
331 bool autoRelease_;
332
333 #ifdef HAVE_CUDA
334 mutable CudaResource cudaResource_;
335 #endif
336 };
337
empty()338 const Ptr<cv::ogl::Buffer::Impl>& cv::ogl::Buffer::Impl::empty()
339 {
340 static Ptr<Impl> p(new Impl);
341 return p;
342 }
343
Impl()344 cv::ogl::Buffer::Impl::Impl() : bufId_(0), autoRelease_(false)
345 {
346 }
347
Impl(GLuint abufId,bool autoRelease)348 cv::ogl::Buffer::Impl::Impl(GLuint abufId, bool autoRelease) : bufId_(abufId), autoRelease_(autoRelease)
349 {
350 CV_Assert( gl::IsBuffer(abufId) == gl::TRUE_ );
351 }
352
Impl(GLsizeiptr size,const GLvoid * data,GLenum target,bool autoRelease)353 cv::ogl::Buffer::Impl::Impl(GLsizeiptr size, const GLvoid* data, GLenum target, bool autoRelease) : bufId_(0), autoRelease_(autoRelease)
354 {
355 gl::GenBuffers(1, &bufId_);
356 CV_CheckGlError();
357
358 CV_Assert( bufId_ != 0 );
359
360 gl::BindBuffer(target, bufId_);
361 CV_CheckGlError();
362
363 gl::BufferData(target, size, data, gl::DYNAMIC_DRAW);
364 CV_CheckGlError();
365
366 gl::BindBuffer(target, 0);
367 CV_CheckGlError();
368 }
369
~Impl()370 cv::ogl::Buffer::Impl::~Impl()
371 {
372 if (autoRelease_ && bufId_)
373 gl::DeleteBuffers(1, &bufId_);
374 }
375
bind(GLenum target) const376 void cv::ogl::Buffer::Impl::bind(GLenum target) const
377 {
378 gl::BindBuffer(target, bufId_);
379 CV_CheckGlError();
380 }
381
copyFrom(GLuint srcBuf,GLsizeiptr size)382 void cv::ogl::Buffer::Impl::copyFrom(GLuint srcBuf, GLsizeiptr size)
383 {
384 gl::BindBuffer(gl::COPY_WRITE_BUFFER, bufId_);
385 CV_CheckGlError();
386
387 gl::BindBuffer(gl::COPY_READ_BUFFER, srcBuf);
388 CV_CheckGlError();
389
390 gl::CopyBufferSubData(gl::COPY_READ_BUFFER, gl::COPY_WRITE_BUFFER, 0, 0, size);
391 CV_CheckGlError();
392 }
393
copyFrom(GLsizeiptr size,const GLvoid * data)394 void cv::ogl::Buffer::Impl::copyFrom(GLsizeiptr size, const GLvoid* data)
395 {
396 gl::BindBuffer(gl::COPY_WRITE_BUFFER, bufId_);
397 CV_CheckGlError();
398
399 gl::BufferSubData(gl::COPY_WRITE_BUFFER, 0, size, data);
400 CV_CheckGlError();
401 }
402
copyTo(GLsizeiptr size,GLvoid * data) const403 void cv::ogl::Buffer::Impl::copyTo(GLsizeiptr size, GLvoid* data) const
404 {
405 gl::BindBuffer(gl::COPY_READ_BUFFER, bufId_);
406 CV_CheckGlError();
407
408 gl::GetBufferSubData(gl::COPY_READ_BUFFER, 0, size, data);
409 CV_CheckGlError();
410 }
411
mapHost(GLenum access)412 void* cv::ogl::Buffer::Impl::mapHost(GLenum access)
413 {
414 gl::BindBuffer(gl::COPY_READ_BUFFER, bufId_);
415 CV_CheckGlError();
416
417 GLvoid* data = gl::MapBuffer(gl::COPY_READ_BUFFER, access);
418 CV_CheckGlError();
419
420 return data;
421 }
422
unmapHost()423 void cv::ogl::Buffer::Impl::unmapHost()
424 {
425 gl::UnmapBuffer(gl::COPY_READ_BUFFER);
426 }
427
428 #ifdef HAVE_CUDA
429
copyFrom(const void * src,size_t spitch,size_t width,size_t height,cudaStream_t stream)430 void cv::ogl::Buffer::Impl::copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream)
431 {
432 cudaResource_.registerBuffer(bufId_);
433 cudaResource_.copyFrom(src, spitch, width, height, stream);
434 }
435
copyTo(void * dst,size_t dpitch,size_t width,size_t height,cudaStream_t stream) const436 void cv::ogl::Buffer::Impl::copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream) const
437 {
438 cudaResource_.registerBuffer(bufId_);
439 cudaResource_.copyTo(dst, dpitch, width, height, stream);
440 }
441
mapDevice(cudaStream_t stream)442 void* cv::ogl::Buffer::Impl::mapDevice(cudaStream_t stream)
443 {
444 cudaResource_.registerBuffer(bufId_);
445 return cudaResource_.map(stream);
446 }
447
unmapDevice(cudaStream_t stream)448 void cv::ogl::Buffer::Impl::unmapDevice(cudaStream_t stream)
449 {
450 cudaResource_.unmap(stream);
451 }
452
453 #endif // HAVE_CUDA
454
455 #endif // HAVE_OPENGL
456
Buffer()457 cv::ogl::Buffer::Buffer() : rows_(0), cols_(0), type_(0)
458 {
459 #ifndef HAVE_OPENGL
460 throw_no_ogl();
461 #else
462 impl_ = Impl::empty();
463 #endif
464 }
465
Buffer(int arows,int acols,int atype,unsigned int abufId,bool autoRelease)466 cv::ogl::Buffer::Buffer(int arows, int acols, int atype, unsigned int abufId, bool autoRelease) : rows_(0), cols_(0), type_(0)
467 {
468 #ifndef HAVE_OPENGL
469 (void) arows;
470 (void) acols;
471 (void) atype;
472 (void) abufId;
473 (void) autoRelease;
474 throw_no_ogl();
475 #else
476 impl_.reset(new Impl(abufId, autoRelease));
477 rows_ = arows;
478 cols_ = acols;
479 type_ = atype;
480 #endif
481 }
482
Buffer(Size asize,int atype,unsigned int abufId,bool autoRelease)483 cv::ogl::Buffer::Buffer(Size asize, int atype, unsigned int abufId, bool autoRelease) : rows_(0), cols_(0), type_(0)
484 {
485 #ifndef HAVE_OPENGL
486 (void) asize;
487 (void) atype;
488 (void) abufId;
489 (void) autoRelease;
490 throw_no_ogl();
491 #else
492 impl_.reset(new Impl(abufId, autoRelease));
493 rows_ = asize.height;
494 cols_ = asize.width;
495 type_ = atype;
496 #endif
497 }
498
Buffer(InputArray arr,Target target,bool autoRelease)499 cv::ogl::Buffer::Buffer(InputArray arr, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0)
500 {
501 #ifndef HAVE_OPENGL
502 (void) arr;
503 (void) target;
504 (void) autoRelease;
505 throw_no_ogl();
506 #else
507 const int kind = arr.kind();
508
509 switch (kind)
510 {
511 case _InputArray::OPENGL_BUFFER:
512 case _InputArray::CUDA_GPU_MAT:
513 copyFrom(arr, target, autoRelease);
514 break;
515
516 default:
517 {
518 Mat mat = arr.getMat();
519 CV_Assert( mat.isContinuous() );
520 const GLsizeiptr asize = mat.rows * mat.cols * mat.elemSize();
521 impl_.reset(new Impl(asize, mat.data, target, autoRelease));
522 rows_ = mat.rows;
523 cols_ = mat.cols;
524 type_ = mat.type();
525 break;
526 }
527 }
528 #endif
529 }
530
create(int arows,int acols,int atype,Target target,bool autoRelease)531 void cv::ogl::Buffer::create(int arows, int acols, int atype, Target target, bool autoRelease)
532 {
533 #ifndef HAVE_OPENGL
534 (void) arows;
535 (void) acols;
536 (void) atype;
537 (void) target;
538 (void) autoRelease;
539 throw_no_ogl();
540 #else
541 if (rows_ != arows || cols_ != acols || type_ != atype)
542 {
543 const GLsizeiptr asize = arows * acols * CV_ELEM_SIZE(atype);
544 impl_.reset(new Impl(asize, 0, target, autoRelease));
545 rows_ = arows;
546 cols_ = acols;
547 type_ = atype;
548 }
549 #endif
550 }
551
release()552 void cv::ogl::Buffer::release()
553 {
554 #ifdef HAVE_OPENGL
555 if (impl_)
556 impl_->setAutoRelease(true);
557 impl_ = Impl::empty();
558 rows_ = 0;
559 cols_ = 0;
560 type_ = 0;
561 #endif
562 }
563
setAutoRelease(bool flag)564 void cv::ogl::Buffer::setAutoRelease(bool flag)
565 {
566 #ifndef HAVE_OPENGL
567 (void) flag;
568 throw_no_ogl();
569 #else
570 impl_->setAutoRelease(flag);
571 #endif
572 }
573
copyFrom(InputArray arr,Target target,bool autoRelease)574 void cv::ogl::Buffer::copyFrom(InputArray arr, Target target, bool autoRelease)
575 {
576 #ifndef HAVE_OPENGL
577 (void) arr;
578 (void) target;
579 (void) autoRelease;
580 throw_no_ogl();
581 #else
582 const int kind = arr.kind();
583
584 const Size asize = arr.size();
585 const int atype = arr.type();
586 create(asize, atype, target, autoRelease);
587
588 switch (kind)
589 {
590 case _InputArray::OPENGL_BUFFER:
591 {
592 ogl::Buffer buf = arr.getOGlBuffer();
593 impl_->copyFrom(buf.bufId(), asize.area() * CV_ELEM_SIZE(atype));
594 break;
595 }
596
597 case _InputArray::CUDA_GPU_MAT:
598 {
599 #ifndef HAVE_CUDA
600 throw_no_cuda();
601 #else
602 GpuMat dmat = arr.getGpuMat();
603 impl_->copyFrom(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows);
604 #endif
605
606 break;
607 }
608
609 default:
610 {
611 Mat mat = arr.getMat();
612 CV_Assert( mat.isContinuous() );
613 impl_->copyFrom(asize.area() * CV_ELEM_SIZE(atype), mat.data);
614 }
615 }
616 #endif
617 }
618
copyFrom(InputArray arr,cuda::Stream & stream,Target target,bool autoRelease)619 void cv::ogl::Buffer::copyFrom(InputArray arr, cuda::Stream& stream, Target target, bool autoRelease)
620 {
621 #ifndef HAVE_OPENGL
622 (void) arr;
623 (void) stream;
624 (void) target;
625 (void) autoRelease;
626 throw_no_ogl();
627 #else
628 #ifndef HAVE_CUDA
629 (void) arr;
630 (void) stream;
631 (void) target;
632 (void) autoRelease;
633 throw_no_cuda();
634 #else
635 GpuMat dmat = arr.getGpuMat();
636
637 create(dmat.size(), dmat.type(), target, autoRelease);
638
639 impl_->copyFrom(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows, cuda::StreamAccessor::getStream(stream));
640 #endif
641 #endif
642 }
643
copyTo(OutputArray arr) const644 void cv::ogl::Buffer::copyTo(OutputArray arr) const
645 {
646 #ifndef HAVE_OPENGL
647 (void) arr;
648 throw_no_ogl();
649 #else
650 const int kind = arr.kind();
651
652 switch (kind)
653 {
654 case _InputArray::OPENGL_BUFFER:
655 {
656 arr.getOGlBufferRef().copyFrom(*this);
657 break;
658 }
659
660 case _InputArray::CUDA_GPU_MAT:
661 {
662 #ifndef HAVE_CUDA
663 throw_no_cuda();
664 #else
665 GpuMat& dmat = arr.getGpuMatRef();
666 dmat.create(rows_, cols_, type_);
667 impl_->copyTo(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows);
668 #endif
669
670 break;
671 }
672
673 default:
674 {
675 arr.create(rows_, cols_, type_);
676 Mat mat = arr.getMat();
677 CV_Assert( mat.isContinuous() );
678 impl_->copyTo(mat.rows * mat.cols * mat.elemSize(), mat.data);
679 }
680 }
681 #endif
682 }
683
copyTo(OutputArray arr,cuda::Stream & stream) const684 void cv::ogl::Buffer::copyTo(OutputArray arr, cuda::Stream& stream) const
685 {
686 #ifndef HAVE_OPENGL
687 (void) arr;
688 (void) stream;
689 throw_no_ogl();
690 #else
691 #ifndef HAVE_CUDA
692 (void) arr;
693 (void) stream;
694 throw_no_cuda();
695 #else
696 arr.create(rows_, cols_, type_);
697 GpuMat dmat = arr.getGpuMat();
698 impl_->copyTo(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows, cuda::StreamAccessor::getStream(stream));
699 #endif
700 #endif
701 }
702
clone(Target target,bool autoRelease) const703 cv::ogl::Buffer cv::ogl::Buffer::clone(Target target, bool autoRelease) const
704 {
705 #ifndef HAVE_OPENGL
706 (void) target;
707 (void) autoRelease;
708 throw_no_ogl();
709 return cv::ogl::Buffer();
710 #else
711 ogl::Buffer buf;
712 buf.copyFrom(*this, target, autoRelease);
713 return buf;
714 #endif
715 }
716
bind(Target target) const717 void cv::ogl::Buffer::bind(Target target) const
718 {
719 #ifndef HAVE_OPENGL
720 (void) target;
721 throw_no_ogl();
722 #else
723 impl_->bind(target);
724 #endif
725 }
726
unbind(Target target)727 void cv::ogl::Buffer::unbind(Target target)
728 {
729 #ifndef HAVE_OPENGL
730 (void) target;
731 throw_no_ogl();
732 #else
733 gl::BindBuffer(target, 0);
734 CV_CheckGlError();
735 #endif
736 }
737
mapHost(Access access)738 Mat cv::ogl::Buffer::mapHost(Access access)
739 {
740 #ifndef HAVE_OPENGL
741 (void) access;
742 throw_no_ogl();
743 return Mat();
744 #else
745 return Mat(rows_, cols_, type_, impl_->mapHost(access));
746 #endif
747 }
748
unmapHost()749 void cv::ogl::Buffer::unmapHost()
750 {
751 #ifndef HAVE_OPENGL
752 throw_no_ogl();
753 #else
754 return impl_->unmapHost();
755 #endif
756 }
757
mapDevice()758 GpuMat cv::ogl::Buffer::mapDevice()
759 {
760 #ifndef HAVE_OPENGL
761 throw_no_ogl();
762 return GpuMat();
763 #else
764 #ifndef HAVE_CUDA
765 throw_no_cuda();
766 return GpuMat();
767 #else
768 return GpuMat(rows_, cols_, type_, impl_->mapDevice());
769 #endif
770 #endif
771 }
772
unmapDevice()773 void cv::ogl::Buffer::unmapDevice()
774 {
775 #ifndef HAVE_OPENGL
776 throw_no_ogl();
777 #else
778 #ifndef HAVE_CUDA
779 throw_no_cuda();
780 #else
781 impl_->unmapDevice();
782 #endif
783 #endif
784 }
785
mapDevice(cuda::Stream & stream)786 cuda::GpuMat cv::ogl::Buffer::mapDevice(cuda::Stream& stream)
787 {
788 #ifndef HAVE_OPENGL
789 (void) stream;
790 throw_no_ogl();
791 return GpuMat();
792 #else
793 #ifndef HAVE_CUDA
794 (void) stream;
795 throw_no_cuda();
796 return GpuMat();
797 #else
798 return GpuMat(rows_, cols_, type_, impl_->mapDevice(cuda::StreamAccessor::getStream(stream)));
799 #endif
800 #endif
801 }
802
unmapDevice(cuda::Stream & stream)803 void cv::ogl::Buffer::unmapDevice(cuda::Stream& stream)
804 {
805 #ifndef HAVE_OPENGL
806 (void) stream;
807 throw_no_ogl();
808 #else
809 #ifndef HAVE_CUDA
810 (void) stream;
811 throw_no_cuda();
812 #else
813 impl_->unmapDevice(cuda::StreamAccessor::getStream(stream));
814 #endif
815 #endif
816 }
817
bufId() const818 unsigned int cv::ogl::Buffer::bufId() const
819 {
820 #ifndef HAVE_OPENGL
821 throw_no_ogl();
822 return 0;
823 #else
824 return impl_->bufId();
825 #endif
826 }
827
828
829 //////////////////////////////////////////////////////////////////////////////////////////
830 // ogl::Texture
831
832 #ifndef HAVE_OPENGL
833
834 class cv::ogl::Texture2D::Impl
835 {
836 };
837
838 #else
839
840 class cv::ogl::Texture2D::Impl
841 {
842 public:
843 static const Ptr<Impl> empty();
844
845 Impl(GLuint texId, bool autoRelease);
846 Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels, bool autoRelease);
847 ~Impl();
848
849 void copyFrom(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
850 void copyTo(GLenum format, GLenum type, GLvoid* pixels) const;
851
852 void bind() const;
853
setAutoRelease(bool flag)854 void setAutoRelease(bool flag) { autoRelease_ = flag; }
855
texId() const856 GLuint texId() const { return texId_; }
857
858 private:
859 Impl();
860
861 GLuint texId_;
862 bool autoRelease_;
863 };
864
empty()865 const Ptr<cv::ogl::Texture2D::Impl> cv::ogl::Texture2D::Impl::empty()
866 {
867 static Ptr<Impl> p(new Impl);
868 return p;
869 }
870
Impl()871 cv::ogl::Texture2D::Impl::Impl() : texId_(0), autoRelease_(false)
872 {
873 }
874
Impl(GLuint atexId,bool autoRelease)875 cv::ogl::Texture2D::Impl::Impl(GLuint atexId, bool autoRelease) : texId_(atexId), autoRelease_(autoRelease)
876 {
877 CV_Assert( gl::IsTexture(atexId) == gl::TRUE_ );
878 }
879
Impl(GLint internalFormat,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels,bool autoRelease)880 cv::ogl::Texture2D::Impl::Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels, bool autoRelease) : texId_(0), autoRelease_(autoRelease)
881 {
882 gl::GenTextures(1, &texId_);
883 CV_CheckGlError();
884
885 CV_Assert(texId_ != 0);
886
887 gl::BindTexture(gl::TEXTURE_2D, texId_);
888 CV_CheckGlError();
889
890 gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
891 CV_CheckGlError();
892
893 gl::TexImage2D(gl::TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, pixels);
894 CV_CheckGlError();
895
896 gl::GenerateMipmap(gl::TEXTURE_2D);
897 CV_CheckGlError();
898 }
899
~Impl()900 cv::ogl::Texture2D::Impl::~Impl()
901 {
902 if (autoRelease_ && texId_)
903 gl::DeleteTextures(1, &texId_);
904 }
905
copyFrom(GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)906 void cv::ogl::Texture2D::Impl::copyFrom(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
907 {
908 gl::BindTexture(gl::TEXTURE_2D, texId_);
909 CV_CheckGlError();
910
911 gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
912 CV_CheckGlError();
913
914 gl::TexSubImage2D(gl::TEXTURE_2D, 0, 0, 0, width, height, format, type, pixels);
915 CV_CheckGlError();
916
917 gl::GenerateMipmap(gl::TEXTURE_2D);
918 CV_CheckGlError();
919 }
920
copyTo(GLenum format,GLenum type,GLvoid * pixels) const921 void cv::ogl::Texture2D::Impl::copyTo(GLenum format, GLenum type, GLvoid* pixels) const
922 {
923 gl::BindTexture(gl::TEXTURE_2D, texId_);
924 CV_CheckGlError();
925
926 gl::PixelStorei(gl::PACK_ALIGNMENT, 1);
927 CV_CheckGlError();
928
929 gl::GetTexImage(gl::TEXTURE_2D, 0, format, type, pixels);
930 CV_CheckGlError();
931 }
932
bind() const933 void cv::ogl::Texture2D::Impl::bind() const
934 {
935 gl::BindTexture(gl::TEXTURE_2D, texId_);
936 CV_CheckGlError();
937 }
938
939 #endif // HAVE_OPENGL
940
Texture2D()941 cv::ogl::Texture2D::Texture2D() : rows_(0), cols_(0), format_(NONE)
942 {
943 #ifndef HAVE_OPENGL
944 throw_no_ogl();
945 #else
946 impl_ = Impl::empty();
947 #endif
948 }
949
Texture2D(int arows,int acols,Format aformat,unsigned int atexId,bool autoRelease)950 cv::ogl::Texture2D::Texture2D(int arows, int acols, Format aformat, unsigned int atexId, bool autoRelease) : rows_(0), cols_(0), format_(NONE)
951 {
952 #ifndef HAVE_OPENGL
953 (void) arows;
954 (void) acols;
955 (void) aformat;
956 (void) atexId;
957 (void) autoRelease;
958 throw_no_ogl();
959 #else
960 impl_.reset(new Impl(atexId, autoRelease));
961 rows_ = arows;
962 cols_ = acols;
963 format_ = aformat;
964 #endif
965 }
966
Texture2D(Size asize,Format aformat,unsigned int atexId,bool autoRelease)967 cv::ogl::Texture2D::Texture2D(Size asize, Format aformat, unsigned int atexId, bool autoRelease) : rows_(0), cols_(0), format_(NONE)
968 {
969 #ifndef HAVE_OPENGL
970 (void) asize;
971 (void) aformat;
972 (void) atexId;
973 (void) autoRelease;
974 throw_no_ogl();
975 #else
976 impl_.reset(new Impl(atexId, autoRelease));
977 rows_ = asize.height;
978 cols_ = asize.width;
979 format_ = aformat;
980 #endif
981 }
982
Texture2D(InputArray arr,bool autoRelease)983 cv::ogl::Texture2D::Texture2D(InputArray arr, bool autoRelease) : rows_(0), cols_(0), format_(NONE)
984 {
985 #ifndef HAVE_OPENGL
986 (void) arr;
987 (void) autoRelease;
988 throw_no_ogl();
989 #else
990 const int kind = arr.kind();
991
992 const Size asize = arr.size();
993 const int atype = arr.type();
994
995 const int depth = CV_MAT_DEPTH(atype);
996 const int cn = CV_MAT_CN(atype);
997
998 CV_Assert( depth <= CV_32F );
999 CV_Assert( cn == 1 || cn == 3 || cn == 4 );
1000
1001 const Format internalFormats[] =
1002 {
1003 NONE, DEPTH_COMPONENT, NONE, RGB, RGBA
1004 };
1005 const GLenum srcFormats[] =
1006 {
1007 0, gl::DEPTH_COMPONENT, 0, gl::BGR, gl::BGRA
1008 };
1009
1010 switch (kind)
1011 {
1012 case _InputArray::OPENGL_BUFFER:
1013 {
1014 ogl::Buffer buf = arr.getOGlBuffer();
1015 buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1016 impl_.reset(new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease));
1017 ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1018 break;
1019 }
1020
1021 case _InputArray::CUDA_GPU_MAT:
1022 {
1023 #ifndef HAVE_CUDA
1024 throw_no_cuda();
1025 #else
1026 GpuMat dmat = arr.getGpuMat();
1027 ogl::Buffer buf(dmat, ogl::Buffer::PIXEL_UNPACK_BUFFER);
1028 buf.setAutoRelease(true);
1029 buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1030 impl_.reset(new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease));
1031 ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1032 #endif
1033
1034 break;
1035 }
1036
1037 default:
1038 {
1039 Mat mat = arr.getMat();
1040 CV_Assert( mat.isContinuous() );
1041 ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1042 impl_.reset(new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data, autoRelease));
1043 break;
1044 }
1045 }
1046
1047 rows_ = asize.height;
1048 cols_ = asize.width;
1049 format_ = internalFormats[cn];
1050 #endif
1051 }
1052
create(int arows,int acols,Format aformat,bool autoRelease)1053 void cv::ogl::Texture2D::create(int arows, int acols, Format aformat, bool autoRelease)
1054 {
1055 #ifndef HAVE_OPENGL
1056 (void) arows;
1057 (void) acols;
1058 (void) aformat;
1059 (void) autoRelease;
1060 throw_no_ogl();
1061 #else
1062 if (rows_ != arows || cols_ != acols || format_ != aformat)
1063 {
1064 ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1065 impl_.reset(new Impl(aformat, acols, arows, aformat, gl::FLOAT, 0, autoRelease));
1066 rows_ = arows;
1067 cols_ = acols;
1068 format_ = aformat;
1069 }
1070 #endif
1071 }
1072
release()1073 void cv::ogl::Texture2D::release()
1074 {
1075 #ifdef HAVE_OPENGL
1076 if (impl_)
1077 impl_->setAutoRelease(true);
1078 impl_ = Impl::empty();
1079 rows_ = 0;
1080 cols_ = 0;
1081 format_ = NONE;
1082 #endif
1083 }
1084
setAutoRelease(bool flag)1085 void cv::ogl::Texture2D::setAutoRelease(bool flag)
1086 {
1087 #ifndef HAVE_OPENGL
1088 (void) flag;
1089 throw_no_ogl();
1090 #else
1091 impl_->setAutoRelease(flag);
1092 #endif
1093 }
1094
copyFrom(InputArray arr,bool autoRelease)1095 void cv::ogl::Texture2D::copyFrom(InputArray arr, bool autoRelease)
1096 {
1097 #ifndef HAVE_OPENGL
1098 (void) arr;
1099 (void) autoRelease;
1100 throw_no_ogl();
1101 #else
1102 const int kind = arr.kind();
1103
1104 const Size asize = arr.size();
1105 const int atype = arr.type();
1106
1107 const int depth = CV_MAT_DEPTH(atype);
1108 const int cn = CV_MAT_CN(atype);
1109
1110 CV_Assert( depth <= CV_32F );
1111 CV_Assert( cn == 1 || cn == 3 || cn == 4 );
1112
1113 const Format internalFormats[] =
1114 {
1115 NONE, DEPTH_COMPONENT, NONE, RGB, RGBA
1116 };
1117 const GLenum srcFormats[] =
1118 {
1119 0, gl::DEPTH_COMPONENT, 0, gl::BGR, gl::BGRA
1120 };
1121
1122 create(asize, internalFormats[cn], autoRelease);
1123
1124 switch(kind)
1125 {
1126 case _InputArray::OPENGL_BUFFER:
1127 {
1128 ogl::Buffer buf = arr.getOGlBuffer();
1129 buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1130 impl_->copyFrom(asize.width, asize.height, srcFormats[cn], gl_types[depth], 0);
1131 ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1132 break;
1133 }
1134
1135 case _InputArray::CUDA_GPU_MAT:
1136 {
1137 #ifndef HAVE_CUDA
1138 throw_no_cuda();
1139 #else
1140 GpuMat dmat = arr.getGpuMat();
1141 ogl::Buffer buf(dmat, ogl::Buffer::PIXEL_UNPACK_BUFFER);
1142 buf.setAutoRelease(true);
1143 buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1144 impl_->copyFrom(asize.width, asize.height, srcFormats[cn], gl_types[depth], 0);
1145 ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1146 #endif
1147
1148 break;
1149 }
1150
1151 default:
1152 {
1153 Mat mat = arr.getMat();
1154 CV_Assert( mat.isContinuous() );
1155 ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
1156 impl_->copyFrom(asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data);
1157 }
1158 }
1159 #endif
1160 }
1161
copyTo(OutputArray arr,int ddepth,bool autoRelease) const1162 void cv::ogl::Texture2D::copyTo(OutputArray arr, int ddepth, bool autoRelease) const
1163 {
1164 #ifndef HAVE_OPENGL
1165 (void) arr;
1166 (void) ddepth;
1167 (void) autoRelease;
1168 throw_no_ogl();
1169 #else
1170 const int kind = arr.kind();
1171
1172 const int cn = format_ == DEPTH_COMPONENT ? 1: format_ == RGB ? 3 : 4;
1173 const GLenum dstFormat = format_ == DEPTH_COMPONENT ? gl::DEPTH_COMPONENT : format_ == RGB ? gl::BGR : gl::BGRA;
1174
1175 switch(kind)
1176 {
1177 case _InputArray::OPENGL_BUFFER:
1178 {
1179 ogl::Buffer& buf = arr.getOGlBufferRef();
1180 buf.create(rows_, cols_, CV_MAKE_TYPE(ddepth, cn), ogl::Buffer::PIXEL_PACK_BUFFER, autoRelease);
1181 buf.bind(ogl::Buffer::PIXEL_PACK_BUFFER);
1182 impl_->copyTo(dstFormat, gl_types[ddepth], 0);
1183 ogl::Buffer::unbind(ogl::Buffer::PIXEL_PACK_BUFFER);
1184 break;
1185 }
1186
1187 case _InputArray::CUDA_GPU_MAT:
1188 {
1189 #ifndef HAVE_CUDA
1190 throw_no_cuda();
1191 #else
1192 ogl::Buffer buf(rows_, cols_, CV_MAKE_TYPE(ddepth, cn), ogl::Buffer::PIXEL_PACK_BUFFER);
1193 buf.setAutoRelease(true);
1194 buf.bind(ogl::Buffer::PIXEL_PACK_BUFFER);
1195 impl_->copyTo(dstFormat, gl_types[ddepth], 0);
1196 ogl::Buffer::unbind(ogl::Buffer::PIXEL_PACK_BUFFER);
1197 buf.copyTo(arr);
1198 #endif
1199
1200 break;
1201 }
1202
1203 default:
1204 {
1205 arr.create(rows_, cols_, CV_MAKE_TYPE(ddepth, cn));
1206 Mat mat = arr.getMat();
1207 CV_Assert( mat.isContinuous() );
1208 ogl::Buffer::unbind(ogl::Buffer::PIXEL_PACK_BUFFER);
1209 impl_->copyTo(dstFormat, gl_types[ddepth], mat.data);
1210 }
1211 }
1212 #endif
1213 }
1214
bind() const1215 void cv::ogl::Texture2D::bind() const
1216 {
1217 #ifndef HAVE_OPENGL
1218 throw_no_ogl();
1219 #else
1220 impl_->bind();
1221 #endif
1222 }
1223
texId() const1224 unsigned int cv::ogl::Texture2D::texId() const
1225 {
1226 #ifndef HAVE_OPENGL
1227 throw_no_ogl();
1228 return 0;
1229 #else
1230 return impl_->texId();
1231 #endif
1232 }
1233
1234
1235 ////////////////////////////////////////////////////////////////////////
1236 // ogl::Arrays
1237
setVertexArray(InputArray vertex)1238 void cv::ogl::Arrays::setVertexArray(InputArray vertex)
1239 {
1240 const int cn = vertex.channels();
1241 const int depth = vertex.depth();
1242
1243 CV_Assert( cn == 2 || cn == 3 || cn == 4 );
1244 CV_Assert( depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F );
1245
1246 if (vertex.kind() == _InputArray::OPENGL_BUFFER)
1247 vertex_ = vertex.getOGlBuffer();
1248 else
1249 vertex_.copyFrom(vertex);
1250
1251 size_ = vertex_.size().area();
1252 }
1253
resetVertexArray()1254 void cv::ogl::Arrays::resetVertexArray()
1255 {
1256 vertex_.release();
1257 size_ = 0;
1258 }
1259
setColorArray(InputArray color)1260 void cv::ogl::Arrays::setColorArray(InputArray color)
1261 {
1262 const int cn = color.channels();
1263
1264 CV_Assert( cn == 3 || cn == 4 );
1265
1266 if (color.kind() == _InputArray::OPENGL_BUFFER)
1267 color_ = color.getOGlBuffer();
1268 else
1269 color_.copyFrom(color);
1270 }
1271
resetColorArray()1272 void cv::ogl::Arrays::resetColorArray()
1273 {
1274 color_.release();
1275 }
1276
setNormalArray(InputArray normal)1277 void cv::ogl::Arrays::setNormalArray(InputArray normal)
1278 {
1279 const int cn = normal.channels();
1280 const int depth = normal.depth();
1281
1282 CV_Assert( cn == 3 );
1283 CV_Assert( depth == CV_8S || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F );
1284
1285 if (normal.kind() == _InputArray::OPENGL_BUFFER)
1286 normal_ = normal.getOGlBuffer();
1287 else
1288 normal_.copyFrom(normal);
1289 }
1290
resetNormalArray()1291 void cv::ogl::Arrays::resetNormalArray()
1292 {
1293 normal_.release();
1294 }
1295
setTexCoordArray(InputArray texCoord)1296 void cv::ogl::Arrays::setTexCoordArray(InputArray texCoord)
1297 {
1298 const int cn = texCoord.channels();
1299 const int depth = texCoord.depth();
1300
1301 CV_Assert( cn >= 1 && cn <= 4 );
1302 CV_Assert( depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F );
1303
1304 if (texCoord.kind() == _InputArray::OPENGL_BUFFER)
1305 texCoord_ = texCoord.getOGlBuffer();
1306 else
1307 texCoord_.copyFrom(texCoord);
1308 }
1309
resetTexCoordArray()1310 void cv::ogl::Arrays::resetTexCoordArray()
1311 {
1312 texCoord_.release();
1313 }
1314
release()1315 void cv::ogl::Arrays::release()
1316 {
1317 resetVertexArray();
1318 resetColorArray();
1319 resetNormalArray();
1320 resetTexCoordArray();
1321 }
1322
setAutoRelease(bool flag)1323 void cv::ogl::Arrays::setAutoRelease(bool flag)
1324 {
1325 vertex_.setAutoRelease(flag);
1326 color_.setAutoRelease(flag);
1327 normal_.setAutoRelease(flag);
1328 texCoord_.setAutoRelease(flag);
1329 }
1330
bind() const1331 void cv::ogl::Arrays::bind() const
1332 {
1333 #ifndef HAVE_OPENGL
1334 throw_no_ogl();
1335 #else
1336 CV_Assert( texCoord_.empty() || texCoord_.size().area() == size_ );
1337 CV_Assert( normal_.empty() || normal_.size().area() == size_ );
1338 CV_Assert( color_.empty() || color_.size().area() == size_ );
1339
1340 if (texCoord_.empty())
1341 {
1342 gl::DisableClientState(gl::TEXTURE_COORD_ARRAY);
1343 CV_CheckGlError();
1344 }
1345 else
1346 {
1347 gl::EnableClientState(gl::TEXTURE_COORD_ARRAY);
1348 CV_CheckGlError();
1349
1350 texCoord_.bind(ogl::Buffer::ARRAY_BUFFER);
1351
1352 gl::TexCoordPointer(texCoord_.channels(), gl_types[texCoord_.depth()], 0, 0);
1353 CV_CheckGlError();
1354 }
1355
1356 if (normal_.empty())
1357 {
1358 gl::DisableClientState(gl::NORMAL_ARRAY);
1359 CV_CheckGlError();
1360 }
1361 else
1362 {
1363 gl::EnableClientState(gl::NORMAL_ARRAY);
1364 CV_CheckGlError();
1365
1366 normal_.bind(ogl::Buffer::ARRAY_BUFFER);
1367
1368 gl::NormalPointer(gl_types[normal_.depth()], 0, 0);
1369 CV_CheckGlError();
1370 }
1371
1372 if (color_.empty())
1373 {
1374 gl::DisableClientState(gl::COLOR_ARRAY);
1375 CV_CheckGlError();
1376 }
1377 else
1378 {
1379 gl::EnableClientState(gl::COLOR_ARRAY);
1380 CV_CheckGlError();
1381
1382 color_.bind(ogl::Buffer::ARRAY_BUFFER);
1383
1384 const int cn = color_.channels();
1385
1386 gl::ColorPointer(cn, gl_types[color_.depth()], 0, 0);
1387 CV_CheckGlError();
1388 }
1389
1390 if (vertex_.empty())
1391 {
1392 gl::DisableClientState(gl::VERTEX_ARRAY);
1393 CV_CheckGlError();
1394 }
1395 else
1396 {
1397 gl::EnableClientState(gl::VERTEX_ARRAY);
1398 CV_CheckGlError();
1399
1400 vertex_.bind(ogl::Buffer::ARRAY_BUFFER);
1401
1402 gl::VertexPointer(vertex_.channels(), gl_types[vertex_.depth()], 0, 0);
1403 CV_CheckGlError();
1404 }
1405
1406 ogl::Buffer::unbind(ogl::Buffer::ARRAY_BUFFER);
1407 #endif
1408 }
1409
1410 ////////////////////////////////////////////////////////////////////////
1411 // Rendering
1412
render(const ogl::Texture2D & tex,Rect_<double> wndRect,Rect_<double> texRect)1413 void cv::ogl::render(const ogl::Texture2D& tex, Rect_<double> wndRect, Rect_<double> texRect)
1414 {
1415 #ifndef HAVE_OPENGL
1416 (void) tex;
1417 (void) wndRect;
1418 (void) texRect;
1419 throw_no_ogl();
1420 #else
1421 if (!tex.empty())
1422 {
1423 gl::MatrixMode(gl::PROJECTION);
1424 gl::LoadIdentity();
1425 gl::Ortho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0);
1426 CV_CheckGlError();
1427
1428 gl::MatrixMode(gl::MODELVIEW);
1429 gl::LoadIdentity();
1430 CV_CheckGlError();
1431
1432 gl::Disable(gl::LIGHTING);
1433 CV_CheckGlError();
1434
1435 tex.bind();
1436
1437 gl::Enable(gl::TEXTURE_2D);
1438 CV_CheckGlError();
1439
1440 gl::TexEnvi(gl::TEXTURE_ENV, gl::TEXTURE_ENV_MODE, gl::REPLACE);
1441 CV_CheckGlError();
1442
1443 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR);
1444 CV_CheckGlError();
1445
1446 const float vertex[] =
1447 {
1448 wndRect.x, wndRect.y, 0.0f,
1449 wndRect.x, (wndRect.y + wndRect.height), 0.0f,
1450 wndRect.x + wndRect.width, (wndRect.y + wndRect.height), 0.0f,
1451 wndRect.x + wndRect.width, wndRect.y, 0.0f
1452 };
1453 const float texCoords[] =
1454 {
1455 texRect.x, texRect.y,
1456 texRect.x, texRect.y + texRect.height,
1457 texRect.x + texRect.width, texRect.y + texRect.height,
1458 texRect.x + texRect.width, texRect.y
1459 };
1460
1461 ogl::Buffer::unbind(ogl::Buffer::ARRAY_BUFFER);
1462
1463 gl::EnableClientState(gl::TEXTURE_COORD_ARRAY);
1464 CV_CheckGlError();
1465
1466 gl::TexCoordPointer(2, gl::FLOAT, 0, texCoords);
1467 CV_CheckGlError();
1468
1469 gl::DisableClientState(gl::NORMAL_ARRAY);
1470 gl::DisableClientState(gl::COLOR_ARRAY);
1471 CV_CheckGlError();
1472
1473 gl::EnableClientState(gl::VERTEX_ARRAY);
1474 CV_CheckGlError();
1475
1476 gl::VertexPointer(3, gl::FLOAT, 0, vertex);
1477 CV_CheckGlError();
1478
1479 gl::DrawArrays(gl::QUADS, 0, 4);
1480 CV_CheckGlError();
1481 }
1482 #endif
1483 }
1484
render(const ogl::Arrays & arr,int mode,Scalar color)1485 void cv::ogl::render(const ogl::Arrays& arr, int mode, Scalar color)
1486 {
1487 #ifndef HAVE_OPENGL
1488 (void) arr;
1489 (void) mode;
1490 (void) color;
1491 throw_no_ogl();
1492 #else
1493 if (!arr.empty())
1494 {
1495 gl::Color3d(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0);
1496
1497 arr.bind();
1498
1499 gl::DrawArrays(mode, 0, arr.size());
1500 }
1501 #endif
1502 }
1503
render(const ogl::Arrays & arr,InputArray indices,int mode,Scalar color)1504 void cv::ogl::render(const ogl::Arrays& arr, InputArray indices, int mode, Scalar color)
1505 {
1506 #ifndef HAVE_OPENGL
1507 (void) arr;
1508 (void) indices;
1509 (void) mode;
1510 (void) color;
1511 throw_no_ogl();
1512 #else
1513 if (!arr.empty() && !indices.empty())
1514 {
1515 gl::Color3d(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0);
1516
1517 arr.bind();
1518
1519 const int kind = indices.kind();
1520
1521 switch (kind)
1522 {
1523 case _InputArray::OPENGL_BUFFER :
1524 {
1525 ogl::Buffer buf = indices.getOGlBuffer();
1526
1527 const int depth = buf.depth();
1528
1529 CV_Assert( buf.channels() == 1 );
1530 CV_Assert( depth <= CV_32S );
1531
1532 GLenum type;
1533 if (depth < CV_16U)
1534 type = gl::UNSIGNED_BYTE;
1535 else if (depth < CV_32S)
1536 type = gl::UNSIGNED_SHORT;
1537 else
1538 type = gl::UNSIGNED_INT;
1539
1540 buf.bind(ogl::Buffer::ELEMENT_ARRAY_BUFFER);
1541
1542 gl::DrawElements(mode, buf.size().area(), type, 0);
1543
1544 ogl::Buffer::unbind(ogl::Buffer::ELEMENT_ARRAY_BUFFER);
1545
1546 break;
1547 }
1548
1549 default:
1550 {
1551 Mat mat = indices.getMat();
1552
1553 const int depth = mat.depth();
1554
1555 CV_Assert( mat.channels() == 1 );
1556 CV_Assert( depth <= CV_32S );
1557 CV_Assert( mat.isContinuous() );
1558
1559 GLenum type;
1560 if (depth < CV_16U)
1561 type = gl::UNSIGNED_BYTE;
1562 else if (depth < CV_32S)
1563 type = gl::UNSIGNED_SHORT;
1564 else
1565 type = gl::UNSIGNED_INT;
1566
1567 ogl::Buffer::unbind(ogl::Buffer::ELEMENT_ARRAY_BUFFER);
1568
1569 gl::DrawElements(mode, mat.size().area(), type, mat.data);
1570 }
1571 }
1572 }
1573 #endif
1574 }
1575