1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
11 // For Open Source Computer Vision Library
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.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
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.
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.
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.
43 #include "precomp.hpp"
45 #include "opencv2/core/opengl_interop.hpp"
46 #include "opencv2/core/gpumat.hpp"
48 #if defined WIN32 || defined _WIN32 || defined WINCE
58 #include <OpenGL/gl.h>
59 #include <OpenGL/glu.h>
66 #include <cuda_runtime.h>
67 #include <cuda_gl_interop.h>
73 using namespace cv::gpu;
76 #define throw_nogl CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support")
77 #define throw_nocuda CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support")
79 #define throw_nogl CV_Error(CV_OpenGlNotSupported, "OpenGL context doesn't exist")
81 #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
82 #define throw_nocuda CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support")
85 #define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__, __func__)
86 #else /* defined(__CUDACC__) || defined(__MSVC__) */
87 #define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__)
92 inline void ___cudaSafeCall(cudaError_t err, const char *file, const int line, const char *func = "")
94 if (cudaSuccess != err)
95 cv::gpu::error(cudaGetErrorString(err), file, line, func);
103 class EmptyGlFuncTab : public CvOpenGlFuncTab
106 void genBuffers(int, unsigned int*) const { throw_nogl; }
107 void deleteBuffers(int, const unsigned int*) const { throw_nogl; }
109 void bufferData(unsigned int, ptrdiff_t, const void*, unsigned int) const { throw_nogl; }
110 void bufferSubData(unsigned int, ptrdiff_t, ptrdiff_t, const void*) const { throw_nogl; }
112 void bindBuffer(unsigned int, unsigned int) const { throw_nogl; }
114 void* mapBuffer(unsigned int, unsigned int) const { throw_nogl; return 0; }
115 void unmapBuffer(unsigned int) const { throw_nogl; }
117 void generateBitmapFont(const std::string&, int, int, bool, bool, int, int, int) const { throw_nogl; }
119 bool isGlContextInitialized() const { return false; }
122 const CvOpenGlFuncTab* g_glFuncTab = 0;
124 #if defined HAVE_CUDA || defined HAVE_OPENGL
125 const CvOpenGlFuncTab* glFuncTab()
127 static EmptyGlFuncTab empty;
128 return g_glFuncTab ? g_glFuncTab : ∅
133 CvOpenGlFuncTab::~CvOpenGlFuncTab()
135 if (g_glFuncTab == this)
139 void icvSetOpenGlFuncTab(const CvOpenGlFuncTab* tab)
145 #ifndef GL_DYNAMIC_DRAW
146 #define GL_DYNAMIC_DRAW 0x88E8
149 #ifndef GL_READ_WRITE
150 #define GL_READ_WRITE 0x88BA
154 #define GL_BGR 0x80E0
158 #define GL_BGRA 0x80E1
163 const GLenum gl_types[] = {GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE};
166 bool g_isCudaGlDeviceInitialized = false;
169 #endif // HAVE_OPENGL
171 void cv::gpu::setGlDevice(int device)
173 #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
181 if (!glFuncTab()->isGlContextInitialized())
184 cudaSafeCall( cudaGLSetGLDevice(device) );
186 g_isCudaGlDeviceInitialized = true;
191 ////////////////////////////////////////////////////////////////////////
194 #if defined HAVE_CUDA && defined HAVE_OPENGL
203 void registerBuffer(unsigned int buffer);
205 void copyFrom(const GpuMat& mat, cudaStream_t stream = 0);
207 GpuMat map(int rows, int cols, int type, cudaStream_t stream = 0);
208 void unmap(cudaStream_t stream = 0);
211 cudaGraphicsResource_t resource_;
214 inline CudaGlInterop::CudaGlInterop() : resource_(0)
218 CudaGlInterop::~CudaGlInterop()
222 cudaGraphicsUnregisterResource(resource_);
227 void CudaGlInterop::registerBuffer(unsigned int buffer)
229 if (!g_isCudaGlDeviceInitialized)
230 cvError(CV_GpuApiCallError, "registerBuffer", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__);
232 cudaGraphicsResource_t resource;
233 cudaSafeCall( cudaGraphicsGLRegisterBuffer(&resource, buffer, cudaGraphicsMapFlagsNone) );
235 resource_ = resource;
238 void CudaGlInterop::copyFrom(const GpuMat& mat, cudaStream_t stream)
240 CV_Assert(resource_ != 0);
242 cudaSafeCall( cudaGraphicsMapResources(1, &resource_, stream) );
246 cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&dst_ptr, &num_bytes, resource_) );
248 const void* src_ptr = mat.ptr();
249 size_t widthBytes = mat.cols * mat.elemSize();
251 CV_Assert(widthBytes * mat.rows <= num_bytes);
254 cudaSafeCall( cudaMemcpy2D(dst_ptr, widthBytes, src_ptr, mat.step, widthBytes, mat.rows, cudaMemcpyDeviceToDevice) );
256 cudaSafeCall( cudaMemcpy2DAsync(dst_ptr, widthBytes, src_ptr, mat.step, widthBytes, mat.rows, cudaMemcpyDeviceToDevice, stream) );
258 cudaGraphicsUnmapResources(1, &resource_, stream);
261 GpuMat CudaGlInterop::map(int rows, int cols, int type, cudaStream_t stream)
263 CV_Assert(resource_ != 0);
265 cudaSafeCall( cudaGraphicsMapResources(1, &resource_, stream) );
269 cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&ptr, &num_bytes, resource_) );
271 CV_Assert( static_cast<size_t>(cols) * CV_ELEM_SIZE(type) * rows <= num_bytes );
273 return GpuMat(rows, cols, type, ptr);
276 inline void CudaGlInterop::unmap(cudaStream_t stream)
278 cudaGraphicsUnmapResources(1, &resource_, stream);
281 #endif // HAVE_CUDA && HAVE_OPENGL
283 ////////////////////////////////////////////////////////////////////////
288 class cv::GlBuffer::Impl
294 class cv::GlBuffer::Impl
297 static const Ptr<Impl>& empty();
299 Impl(int rows, int cols, int type, unsigned int target);
300 Impl(const Mat& m, unsigned int target);
303 void copyFrom(const Mat& m, unsigned int target);
306 void copyFrom(const GpuMat& mat, cudaStream_t stream = 0);
309 void bind(unsigned int target) const;
310 void unbind(unsigned int target) const;
312 Mat mapHost(int rows, int cols, int type, unsigned int target);
313 void unmapHost(unsigned int target);
316 GpuMat mapDevice(int rows, int cols, int type, cudaStream_t stream = 0);
317 void unmapDevice(cudaStream_t stream = 0);
323 unsigned int buffer_;
326 CudaGlInterop cudaGlInterop_;
330 inline const Ptr<cv::GlBuffer::Impl>& cv::GlBuffer::Impl::empty()
332 static Ptr<Impl> p(new Impl);
336 inline cv::GlBuffer::Impl::Impl() : buffer_(0)
340 cv::GlBuffer::Impl::Impl(int rows, int cols, int type, unsigned int target) : buffer_(0)
342 if (!glFuncTab()->isGlContextInitialized())
345 CV_DbgAssert(rows > 0 && cols > 0);
346 CV_DbgAssert(CV_MAT_DEPTH(type) >= 0 && CV_MAT_DEPTH(type) <= CV_64F);
348 glFuncTab()->genBuffers(1, &buffer_);
350 CV_Assert(buffer_ != 0);
352 size_t size = rows * cols * CV_ELEM_SIZE(type);
354 glFuncTab()->bindBuffer(target, buffer_);
357 glFuncTab()->bufferData(target, size, 0, GL_DYNAMIC_DRAW);
360 glFuncTab()->bindBuffer(target, 0);
363 if (g_isCudaGlDeviceInitialized)
364 cudaGlInterop_.registerBuffer(buffer_);
368 cv::GlBuffer::Impl::Impl(const Mat& m, unsigned int target) : buffer_(0)
370 if (!glFuncTab()->isGlContextInitialized())
373 CV_DbgAssert(m.rows > 0 && m.cols > 0);
374 CV_DbgAssert(m.depth() >= 0 && m.depth() <= CV_64F);
375 CV_Assert(m.isContinuous());
377 glFuncTab()->genBuffers(1, &buffer_);
379 CV_Assert(buffer_ != 0);
381 size_t size = m.rows * m.cols * m.elemSize();
383 glFuncTab()->bindBuffer(target, buffer_);
386 glFuncTab()->bufferData(target, size, m.data, GL_DYNAMIC_DRAW);
389 glFuncTab()->bindBuffer(target, 0);
392 if (g_isCudaGlDeviceInitialized)
393 cudaGlInterop_.registerBuffer(buffer_);
397 cv::GlBuffer::Impl::~Impl()
402 glFuncTab()->deleteBuffers(1, &buffer_);
405 catch(const exception& e)
407 cerr << e.what() << endl;
415 void cv::GlBuffer::Impl::copyFrom(const Mat& m, unsigned int target)
417 CV_Assert(buffer_ != 0);
419 CV_Assert(m.isContinuous());
423 size_t size = m.rows * m.cols * m.elemSize();
425 glFuncTab()->bufferSubData(target, 0, size, m.data);
433 void cv::GlBuffer::Impl::copyFrom(const GpuMat& mat, cudaStream_t stream)
435 if (!g_isCudaGlDeviceInitialized)
436 cvError(CV_GpuApiCallError, "copyFrom", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__);
438 CV_Assert(buffer_ != 0);
440 cudaGlInterop_.copyFrom(mat, stream);
445 inline void cv::GlBuffer::Impl::bind(unsigned int target) const
447 CV_Assert(buffer_ != 0);
449 glFuncTab()->bindBuffer(target, buffer_);
453 inline void cv::GlBuffer::Impl::unbind(unsigned int target) const
455 glFuncTab()->bindBuffer(target, 0);
458 inline Mat cv::GlBuffer::Impl::mapHost(int rows, int cols, int type, unsigned int target)
460 void* ptr = glFuncTab()->mapBuffer(target, GL_READ_WRITE);
463 return Mat(rows, cols, type, ptr);
466 inline void cv::GlBuffer::Impl::unmapHost(unsigned int target)
468 glFuncTab()->unmapBuffer(target);
473 inline GpuMat cv::GlBuffer::Impl::mapDevice(int rows, int cols, int type, cudaStream_t stream)
475 if (!g_isCudaGlDeviceInitialized)
476 cvError(CV_GpuApiCallError, "copyFrom", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__);
478 CV_Assert(buffer_ != 0);
480 return cudaGlInterop_.map(rows, cols, type, stream);
483 inline void cv::GlBuffer::Impl::unmapDevice(cudaStream_t stream)
485 if (!g_isCudaGlDeviceInitialized)
486 cvError(CV_GpuApiCallError, "copyFrom", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__);
488 cudaGlInterop_.unmap(stream);
493 #endif // HAVE_OPENGL
495 cv::GlBuffer::GlBuffer(Usage _usage) : rows_(0), cols_(0), type_(0), usage_(_usage)
501 impl_ = Impl::empty();
505 cv::GlBuffer::GlBuffer(int _rows, int _cols, int _type, Usage _usage) : rows_(0), cols_(0), type_(0), usage_(_usage)
514 impl_ = new Impl(_rows, _cols, _type, _usage);
521 cv::GlBuffer::GlBuffer(Size _size, int _type, Usage _usage) : rows_(0), cols_(0), type_(0), usage_(_usage)
529 impl_ = new Impl(_size.height, _size.width, _type, _usage);
530 rows_ = _size.height;
536 cv::GlBuffer::GlBuffer(InputArray mat_, Usage _usage) : rows_(0), cols_(0), type_(0), usage_(_usage)
543 int kind = mat_.kind();
544 Size _size = mat_.size();
545 int _type = mat_.type();
547 if (kind == _InputArray::GPU_MAT)
549 #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
552 GpuMat d_mat = mat_.getGpuMat();
553 impl_ = new Impl(d_mat.rows, d_mat.cols, d_mat.type(), _usage);
554 impl_->copyFrom(d_mat);
559 Mat mat = mat_.getMat();
560 impl_ = new Impl(mat, _usage);
563 rows_ = _size.height;
569 void cv::GlBuffer::create(int _rows, int _cols, int _type, Usage _usage)
578 if (rows_ != _rows || cols_ != _cols || type_ != _type || usage_ != _usage)
580 impl_ = new Impl(_rows, _cols, _type, _usage);
589 void cv::GlBuffer::release()
594 impl_ = Impl::empty();
598 void cv::GlBuffer::copyFrom(InputArray mat_)
604 int kind = mat_.kind();
605 Size _size = mat_.size();
606 int _type = mat_.type();
608 create(_size, _type);
612 case _InputArray::OPENGL_BUFFER:
614 GlBuffer buf = mat_.getGlBuffer();
618 case _InputArray::GPU_MAT:
620 #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
623 GpuMat d_mat = mat_.getGpuMat();
624 impl_->copyFrom(d_mat);
631 Mat mat = mat_.getMat();
632 impl_->copyFrom(mat, usage_);
638 void cv::GlBuffer::bind() const
647 void cv::GlBuffer::unbind() const
652 impl_->unbind(usage_);
656 Mat cv::GlBuffer::mapHost()
662 return impl_->mapHost(rows_, cols_, type_, usage_);
666 void cv::GlBuffer::unmapHost()
671 impl_->unmapHost(usage_);
675 GpuMat cv::GlBuffer::mapDevice()
681 #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
685 return impl_->mapDevice(rows_, cols_, type_);
690 void cv::GlBuffer::unmapDevice()
695 #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
698 impl_->unmapDevice();
703 template <> void cv::Ptr<cv::GlBuffer::Impl>::delete_obj()
708 //////////////////////////////////////////////////////////////////////////////////////////
713 class cv::GlTexture::Impl
719 class cv::GlTexture::Impl
722 static const Ptr<Impl> empty();
724 Impl(int rows, int cols, int type);
726 Impl(const Mat& mat, bool bgra);
727 Impl(const GlBuffer& buf, bool bgra);
731 void copyFrom(const Mat& mat, bool bgra);
732 void copyFrom(const GlBuffer& buf, bool bgra);
743 inline const Ptr<cv::GlTexture::Impl> cv::GlTexture::Impl::empty()
745 static Ptr<Impl> p(new Impl);
749 inline cv::GlTexture::Impl::Impl() : tex_(0)
753 cv::GlTexture::Impl::Impl(int rows, int cols, int type) : tex_(0)
755 if (!glFuncTab()->isGlContextInitialized())
758 int depth = CV_MAT_DEPTH(type);
759 int cn = CV_MAT_CN(type);
761 CV_DbgAssert(rows > 0 && cols > 0);
762 CV_Assert(cn == 1 || cn == 3 || cn == 4);
763 CV_Assert(depth >= 0 && depth <= CV_32F);
765 glGenTextures(1, &tex_);
767 CV_Assert(tex_ != 0);
769 glBindTexture(GL_TEXTURE_2D, tex_);
772 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
773 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
774 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
775 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
778 GLenum format = cn == 1 ? GL_LUMINANCE : cn == 3 ? GL_BGR : GL_BGRA;
780 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
783 glTexImage2D(GL_TEXTURE_2D, 0, cn, cols, rows, 0, format, gl_types[depth], 0);
787 cv::GlTexture::Impl::Impl(const Mat& mat, bool bgra) : tex_(0)
789 if (!glFuncTab()->isGlContextInitialized())
792 int depth = mat.depth();
793 int cn = mat.channels();
795 CV_DbgAssert(mat.rows > 0 && mat.cols > 0);
796 CV_Assert(cn == 1 || cn == 3 || cn == 4);
797 CV_Assert(depth >= 0 && depth <= CV_32F);
798 CV_Assert(mat.isContinuous());
800 glGenTextures(1, &tex_);
802 CV_Assert(tex_ != 0);
804 glBindTexture(GL_TEXTURE_2D, tex_);
807 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
808 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
809 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
810 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
813 GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA));
815 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
818 glTexImage2D(GL_TEXTURE_2D, 0, cn, mat.cols, mat.rows, 0, format, gl_types[depth], mat.data);
822 cv::GlTexture::Impl::Impl(const GlBuffer& buf, bool bgra) : tex_(0)
824 if (!glFuncTab()->isGlContextInitialized())
827 int depth = buf.depth();
828 int cn = buf.channels();
830 CV_DbgAssert(buf.rows() > 0 && buf.cols() > 0);
831 CV_Assert(cn == 1 || cn == 3 || cn == 4);
832 CV_Assert(depth >= 0 && depth <= CV_32F);
833 CV_Assert(buf.usage() == GlBuffer::TEXTURE_BUFFER);
835 glGenTextures(1, &tex_);
837 CV_Assert(tex_ != 0);
839 glBindTexture(GL_TEXTURE_2D, tex_);
842 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
844 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
845 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
848 GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA));
852 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
855 glTexImage2D(GL_TEXTURE_2D, 0, cn, buf.cols(), buf.rows(), 0, format, gl_types[depth], 0);
861 inline cv::GlTexture::Impl::~Impl()
864 glDeleteTextures(1, &tex_);
867 void cv::GlTexture::Impl::copyFrom(const Mat& mat, bool bgra)
869 CV_Assert(tex_ != 0);
873 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
876 int cn = mat.channels();
877 GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA));
879 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mat.cols, mat.rows, format, gl_types[mat.depth()], mat.data);
885 void cv::GlTexture::Impl::copyFrom(const GlBuffer& buf, bool bgra)
887 CV_Assert(tex_ != 0);
888 CV_Assert(buf.usage() == GlBuffer::TEXTURE_BUFFER);
894 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
897 int cn = buf.channels();
898 GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA));
900 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, buf.cols(), buf.rows(), format, gl_types[buf.depth()], 0);
908 inline void cv::GlTexture::Impl::bind() const
910 CV_Assert(tex_ != 0);
912 glEnable(GL_TEXTURE_2D);
915 glBindTexture(GL_TEXTURE_2D, tex_);
919 inline void cv::GlTexture::Impl::unbind() const
921 glBindTexture(GL_TEXTURE_2D, 0);
923 glDisable(GL_TEXTURE_2D);
926 #endif // HAVE_OPENGL
928 cv::GlTexture::GlTexture() : rows_(0), cols_(0), type_(0), buf_(GlBuffer::TEXTURE_BUFFER)
933 impl_ = Impl::empty();
937 cv::GlTexture::GlTexture(int _rows, int _cols, int _type) : rows_(0), cols_(0), type_(0), buf_(GlBuffer::TEXTURE_BUFFER)
945 impl_ = new Impl(_rows, _cols, _type);
952 cv::GlTexture::GlTexture(Size _size, int _type) : rows_(0), cols_(0), type_(0), buf_(GlBuffer::TEXTURE_BUFFER)
959 impl_ = new Impl(_size.height, _size.width, _type);
960 rows_ = _size.height;
966 cv::GlTexture::GlTexture(InputArray mat_, bool bgra) : rows_(0), cols_(0), type_(0), buf_(GlBuffer::TEXTURE_BUFFER)
973 int kind = mat_.kind();
974 Size _size = mat_.size();
975 int _type = mat_.type();
979 case _InputArray::OPENGL_BUFFER:
981 GlBuffer buf = mat_.getGlBuffer();
982 impl_ = new Impl(buf, bgra);
985 case _InputArray::GPU_MAT:
987 #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
990 GpuMat d_mat = mat_.getGpuMat();
991 GlBuffer buf(d_mat, GlBuffer::TEXTURE_BUFFER);
992 impl_ = new Impl(buf, bgra);
999 Mat mat = mat_.getMat();
1000 impl_ = new Impl(mat, bgra);
1005 rows_ = _size.height;
1006 cols_ = _size.width;
1011 void cv::GlTexture::create(int _rows, int _cols, int _type)
1019 if (rows_ != _rows || cols_ != _cols || type_ != _type)
1021 impl_ = new Impl(_rows, _cols, _type);
1029 void cv::GlTexture::release()
1034 impl_ = Impl::empty();
1038 void cv::GlTexture::copyFrom(InputArray mat_, bool bgra)
1045 int kind = mat_.kind();
1046 Size _size = mat_.size();
1047 int _type = mat_.type();
1049 create(_size, _type);
1053 case _InputArray::OPENGL_TEXTURE:
1055 GlTexture tex = mat_.getGlTexture();
1059 case _InputArray::OPENGL_BUFFER:
1061 GlBuffer buf = mat_.getGlBuffer();
1062 impl_->copyFrom(buf, bgra);
1065 case _InputArray::GPU_MAT:
1067 #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
1070 GpuMat d_mat = mat_.getGpuMat();
1071 buf_.copyFrom(d_mat);
1072 impl_->copyFrom(buf_, bgra);
1079 Mat mat = mat_.getMat();
1080 impl_->copyFrom(mat, bgra);
1086 void cv::GlTexture::bind() const
1095 void cv::GlTexture::unbind() const
1104 template <> void cv::Ptr<cv::GlTexture::Impl>::delete_obj()
1106 if (obj) delete obj;
1109 ////////////////////////////////////////////////////////////////////////
1112 void cv::GlArrays::setVertexArray(InputArray vertex)
1114 int cn = vertex.channels();
1115 int depth = vertex.depth();
1117 CV_Assert(cn == 2 || cn == 3 || cn == 4);
1118 CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F);
1120 vertex_.copyFrom(vertex);
1123 void cv::GlArrays::setColorArray(InputArray color, bool bgra)
1125 int cn = color.channels();
1127 CV_Assert((cn == 3 && !bgra) || cn == 4);
1129 color_.copyFrom(color);
1133 void cv::GlArrays::setNormalArray(InputArray normal)
1135 int cn = normal.channels();
1136 int depth = normal.depth();
1139 CV_Assert(depth == CV_8S || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F);
1141 normal_.copyFrom(normal);
1144 void cv::GlArrays::setTexCoordArray(InputArray texCoord)
1146 int cn = texCoord.channels();
1147 int depth = texCoord.depth();
1149 CV_Assert(cn >= 1 && cn <= 4);
1150 CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F);
1152 texCoord_.copyFrom(texCoord);
1155 void cv::GlArrays::bind() const
1160 CV_DbgAssert(texCoord_.empty() || texCoord_.size().area() == vertex_.size().area());
1161 CV_DbgAssert(normal_.empty() || normal_.size().area() == vertex_.size().area());
1162 CV_DbgAssert(color_.empty() || color_.size().area() == vertex_.size().area());
1164 if (!texCoord_.empty())
1166 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1171 glTexCoordPointer(texCoord_.channels(), gl_types[texCoord_.depth()], 0, 0);
1177 if (!normal_.empty())
1179 glEnableClientState(GL_NORMAL_ARRAY);
1184 glNormalPointer(gl_types[normal_.depth()], 0, 0);
1190 if (!color_.empty())
1192 glEnableClientState(GL_COLOR_ARRAY);
1197 int cn = color_.channels();
1198 int format = cn == 3 ? cn : (bgra_ ? GL_BGRA : 4);
1200 glColorPointer(format, gl_types[color_.depth()], 0, 0);
1206 if (!vertex_.empty())
1208 glEnableClientState(GL_VERTEX_ARRAY);
1213 glVertexPointer(vertex_.channels(), gl_types[vertex_.depth()], 0, 0);
1221 void cv::GlArrays::unbind() const
1226 if (!texCoord_.empty())
1228 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1232 if (!normal_.empty())
1234 glDisableClientState(GL_NORMAL_ARRAY);
1238 if (!color_.empty())
1240 glDisableClientState(GL_COLOR_ARRAY);
1244 if (!vertex_.empty())
1246 glDisableClientState(GL_VERTEX_ARRAY);
1252 ////////////////////////////////////////////////////////////////////////
1255 cv::GlFont::GlFont(const string& _family, int _height, Weight _weight, Style _style)
1256 : family_(_family), height_(_height), weight_(_weight), style_(_style), base_(0)
1261 base_ = glGenLists(256);
1264 glFuncTab()->generateBitmapFont(family_, height_, weight_, (style_ & STYLE_ITALIC) != 0, (style_ & STYLE_UNDERLINE) != 0, 0, 256, base_);
1268 void cv::GlFont::draw(const char* str, int len) const
1275 if (base_ && len > 0)
1277 glPushAttrib(GL_LIST_BIT);
1280 glCallLists(static_cast<GLsizei>(len), GL_UNSIGNED_BYTE, str);
1291 class FontCompare : public unary_function<Ptr<GlFont>, bool>
1294 inline FontCompare(const string& family, int height, GlFont::Weight weight, GlFont::Style style)
1295 : family_(family), height_(height), weight_(weight), style_(style)
1299 bool operator ()(const cv::Ptr<GlFont>& font)
1301 return font->family() == family_ && font->height() == height_ && font->weight() == weight_ && font->style() == style_;
1307 GlFont::Weight weight_;
1308 GlFont::Style style_;
1312 Ptr<GlFont> cv::GlFont::get(const std::string& family, int height, Weight weight, Style style)
1320 return Ptr<GlFont>();
1322 static vector< Ptr<GlFont> > fonts;
1325 vector< Ptr<GlFont> >::iterator fontIt = find_if(fonts.begin(), fonts.end(), FontCompare(family, height, weight, style));
1327 if (fontIt == fonts.end())
1329 fonts.push_back(new GlFont(family, height, weight, style));
1331 fontIt = fonts.end() - 1;
1338 ////////////////////////////////////////////////////////////////////////
1341 void cv::render(const GlTexture& tex, Rect_<double> wndRect, Rect_<double> texRect)
1353 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1356 glTexCoord2d(texRect.x, texRect.y);
1357 glVertex2d(wndRect.x, wndRect.y);
1359 glTexCoord2d(texRect.x, texRect.y + texRect.height);
1360 glVertex2d(wndRect.x, (wndRect.y + wndRect.height));
1362 glTexCoord2d(texRect.x + texRect.width, texRect.y + texRect.height);
1363 glVertex2d(wndRect.x + wndRect.width, (wndRect.y + wndRect.height));
1365 glTexCoord2d(texRect.x + texRect.width, texRect.y);
1366 glVertex2d(wndRect.x + wndRect.width, wndRect.y);
1376 void cv::render(const GlArrays& arr, int mode, Scalar color)
1384 glColor3d(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0);
1388 glDrawArrays(mode, 0, arr.size().area());
1394 void cv::render(const string& str, const Ptr<GlFont>& font, Scalar color, Point2d pos)
1403 glPushAttrib(GL_DEPTH_BUFFER_BIT);
1406 glGetIntegerv(GL_VIEWPORT, viewport);
1408 glDisable(GL_DEPTH_TEST);
1410 glMatrixMode(GL_PROJECTION);
1413 glMatrixMode(GL_MODELVIEW);
1416 glColor3d(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0);
1418 glRasterPos2d(2.0 * (viewport[0] + pos.x) / viewport[2] - 1.0, 1.0 - 2.0 * (viewport[1] + pos.y + font->height()) / viewport[3]);
1420 font->draw(str.c_str(), (int)str.length());
1426 ////////////////////////////////////////////////////////////////////////
1429 cv::GlCamera::GlCamera() :
1430 eye_(0.0, 0.0, -5.0), center_(0.0, 0.0, 0.0), up_(0.0, 1.0, 0.0),
1431 pos_(0.0, 0.0, -5.0), yaw_(0.0), pitch_(0.0), roll_(0.0),
1432 useLookAtParams_(false),
1434 scale_(1.0, 1.0, 1.0),
1436 projectionMatrix_(),
1437 fov_(45.0), aspect_(0.0),
1438 left_(0.0), right_(1.0), bottom_(1.0), top_(0.0),
1439 zNear_(-1.0), zFar_(1.0),
1440 perspectiveProjection_(false)
1444 void cv::GlCamera::lookAt(Point3d eye, Point3d center, Point3d up)
1449 useLookAtParams_ = true;
1452 void cv::GlCamera::setCameraPos(Point3d pos, double yaw, double pitch, double roll)
1458 useLookAtParams_ = false;
1461 void cv::GlCamera::setScale(Point3d scale)
1466 void cv::GlCamera::setProjectionMatrix(const Mat& projectionMatrix, bool transpose)
1468 CV_Assert(projectionMatrix.type() == CV_32F || projectionMatrix.type() == CV_64F);
1469 CV_Assert(projectionMatrix.cols == 4 && projectionMatrix.rows == 4);
1471 projectionMatrix_ = transpose ? projectionMatrix.t() : projectionMatrix;
1474 void cv::GlCamera::setPerspectiveProjection(double fov, double aspect, double zNear, double zFar)
1481 projectionMatrix_.release();
1482 perspectiveProjection_ = true;
1485 void cv::GlCamera::setOrthoProjection(double left, double right, double bottom, double top, double zNear, double zFar)
1494 projectionMatrix_.release();
1495 perspectiveProjection_ = false;
1498 void cv::GlCamera::setupProjectionMatrix() const
1503 glMatrixMode(GL_PROJECTION);
1506 if (projectionMatrix_.empty())
1508 if (perspectiveProjection_)
1509 gluPerspective(fov_, aspect_, zNear_, zFar_);
1511 glOrtho(left_, right_, bottom_, top_, zNear_, zFar_);
1515 if (projectionMatrix_.type() == CV_32F)
1516 glLoadMatrixf(projectionMatrix_.ptr<float>());
1518 glLoadMatrixd(projectionMatrix_.ptr<double>());
1525 void cv::GlCamera::setupModelViewMatrix() const
1530 glMatrixMode(GL_MODELVIEW);
1533 if (useLookAtParams_)
1534 gluLookAt(eye_.x, eye_.y, eye_.z, center_.x, center_.y, center_.z, up_.x, up_.y, up_.z);
1537 glRotated(-yaw_, 0.0, 1.0, 0.0);
1538 glRotated(-pitch_, 1.0, 0.0, 0.0);
1539 glRotated(-roll_, 0.0, 0.0, 1.0);
1540 glTranslated(-pos_.x, -pos_.y, -pos_.z);
1543 glScaled(scale_.x, scale_.y, scale_.z);
1549 ////////////////////////////////////////////////////////////////////////
1552 bool icvCheckGlError(const char* file, const int line, const char* func)
1560 GLenum err = glGetError();
1562 if (err != GL_NO_ERROR)
1568 case GL_INVALID_ENUM:
1569 msg = "An unacceptable value is specified for an enumerated argument";
1571 case GL_INVALID_VALUE:
1572 msg = "A numeric argument is out of range";
1574 case GL_INVALID_OPERATION:
1575 msg = "The specified operation is not allowed in the current state";
1577 case GL_STACK_OVERFLOW:
1578 msg = "This command would cause a stack overflow";
1580 case GL_STACK_UNDERFLOW:
1581 msg = "This command would cause a stack underflow";
1583 case GL_OUT_OF_MEMORY:
1584 msg = "There is not enough memory left to execute the command";
1587 msg = "Unknown error";
1590 cvError(CV_OpenGlApiCallError, func, msg, file, line);