From bd4239be7b60eeaecb4151ca6a7e8117298a1c9b Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Wed, 30 Nov 2011 06:20:29 +0000 Subject: [PATCH] moved OpenGL wrappers to separate header added GlBuffer, GlTexture and GpuMat support to InputArray replaced addTextOpenGl function by render + GlFont --- modules/core/include/opencv2/core/core.hpp | 30 +- modules/core/include/opencv2/core/gpumat.hpp | 279 --- .../core/include/opencv2/core/internal.hpp | 32 + .../include/opencv2/core/opengl_interop.hpp | 327 ++++ modules/core/src/gpumat.cpp | 1436 +--------------- modules/core/src/matrix.cpp | 92 +- modules/core/src/opengl_interop.cpp | 1519 +++++++++++++++++ .../include/opencv2/highgui/highgui.hpp | 21 +- .../include/opencv2/highgui/highgui_c.h | 8 +- modules/highgui/src/window.cpp | 235 +-- modules/highgui/src/window_w32.cpp | 525 ++---- samples/cpp/point_cloud.cpp | 294 ++-- samples/gpu/highgui_gpu.cpp | 41 +- 13 files changed, 2418 insertions(+), 2421 deletions(-) create mode 100644 modules/core/include/opencv2/core/opengl_interop.hpp create mode 100644 modules/core/src/opengl_interop.cpp diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index d7d98d0b08..6e7801f076 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -90,6 +90,11 @@ class Mat; class SparseMat; typedef Mat MatND; +class GlBuffer; +class GlTexture; +class GlArrays; +class GlCamera; + namespace gpu { class GpuMat; } @@ -1273,10 +1278,19 @@ protected: class CV_EXPORTS _InputArray { public: - enum { KIND_SHIFT=16, NONE=0< _InputArray(const Matx<_Tp, m, n>& matx); _InputArray(const Scalar& s); _InputArray(const double& val); + _InputArray(const GlBuffer& buf); + _InputArray(const GlTexture& tex); + _InputArray(const gpu::GpuMat& d_mat); + virtual Mat getMat(int i=-1) const; virtual void getMatVector(vector& mv) const; + virtual GlBuffer getGlBuffer() const; + virtual GlTexture getGlTexture() const; + virtual gpu::GpuMat getGpuMat() const; + virtual int kind() const; virtual Size size(int i=-1) const; virtual size_t total(int i=-1) const; diff --git a/modules/core/include/opencv2/core/gpumat.hpp b/modules/core/include/opencv2/core/gpumat.hpp index 6682fff801..9e12f6729a 100644 --- a/modules/core/include/opencv2/core/gpumat.hpp +++ b/modules/core/include/opencv2/core/gpumat.hpp @@ -50,9 +50,6 @@ namespace cv { namespace gpu { - //////////////////////////////////////////////////////////////////////// - // GpuMat - //! Smart pointer for GPU memory with reference counting. Its interface is mostly similar with cv::Mat. class CV_EXPORTS GpuMat { @@ -217,286 +214,10 @@ namespace cv { namespace gpu CV_EXPORTS void ensureSizeIsEnough(int rows, int cols, int type, GpuMat& m); CV_EXPORTS void ensureSizeIsEnough(Size size, int type, GpuMat& m); - //////////////////////////////////////////////////////////////////////// - // OpenGL - - //! set a CUDA device to use OpenGL interoperability - CV_EXPORTS void setGlDevice(int device = 0); - - //! Smart pointer for OpenGL buffer memory with reference counting. - class CV_EXPORTS GlBuffer - { - public: - enum Usage - { - ARRAY_BUFFER = 0x8892, // buffer will use for OpenGL arrays (vertices, colors, normals, etc) - TEXTURE_BUFFER = 0x88EC // buffer will ise for OpenGL textures - }; - - //! create empty buffer - explicit GlBuffer(Usage usage); - - //! create buffer - GlBuffer(int rows, int cols, int type, Usage usage); - GlBuffer(Size size, int type, Usage usage); - - //! copy from host/device memory - GlBuffer(InputArray mat, Usage usage); - GlBuffer(const GpuMat& d_mat, Usage usage); - - GlBuffer(const GlBuffer& other); - - ~GlBuffer(); - - GlBuffer& operator =(const GlBuffer& other); - - void create(int rows, int cols, int type, Usage usage); - inline void create(Size size, int type, Usage usage) { create(size.height, size.width, type, usage); } - inline void create(int rows, int cols, int type) { create(rows, cols, type, usage()); } - inline void create(Size size, int type) { create(size.height, size.width, type, usage()); } - - void release(); - - //! copy from host/device memory - void copyFrom(InputArray mat); - void copyFrom(const GpuMat& d_mat); - - void bind() const; - void unbind() const; - - //! map to host memory - Mat mapHost(); - void unmapHost(); - - //! map to device memory - GpuMat mapDevice(); - void unmapDevice(); - - int rows; - int cols; - - inline Size size() const { return Size(cols, rows); } - inline bool empty() const { return rows == 0 || cols == 0; } - - inline int type() const { return type_; } - inline int depth() const { return CV_MAT_DEPTH(type_); } - inline int channels() const { return CV_MAT_CN(type_); } - inline int elemSize() const { return CV_ELEM_SIZE(type_); } - inline int elemSize1() const { return CV_ELEM_SIZE1(type_); } - - inline Usage usage() const { return usage_; } - - private: - int type_; - Usage usage_; - - class Impl; - Ptr impl_; - }; - - //! Smart pointer for OpenGL 2d texture memory with reference counting. - class CV_EXPORTS GlTexture - { - public: - //! create empty texture - GlTexture(); - - //! create texture - GlTexture(int rows, int cols, int type); - GlTexture(Size size, int type); - - //! copy from host/device memory - explicit GlTexture(InputArray mat, bool bgra = true); - explicit GlTexture(const GlBuffer& buf, bool bgra = true); - - GlTexture(const GlTexture& other); - - ~GlTexture(); - - GlTexture& operator =(const GlTexture& other); - - void create(int rows, int cols, int type); - inline void create(Size size, int type) { create(size.height, size.width, type); } - void release(); - - //! copy from host/device memory - void copyFrom(InputArray mat, bool bgra = true); - void copyFrom(const GlBuffer& buf, bool bgra = true); - - void bind() const; - void unbind() const; - - int rows; - int cols; - - inline Size size() const { return Size(cols, rows); } - inline bool empty() const { return rows == 0 || cols == 0; } - - inline int type() const { return type_; } - inline int depth() const { return CV_MAT_DEPTH(type_); } - inline int channels() const { return CV_MAT_CN(type_); } - inline int elemSize() const { return CV_ELEM_SIZE(type_); } - inline int elemSize1() const { return CV_ELEM_SIZE1(type_); } - - private: - int type_; - - class Impl; - Ptr impl_; - }; - - //! OpenGL Arrays - class CV_EXPORTS GlArrays - { - public: - inline GlArrays() - : vertex_(GlBuffer::ARRAY_BUFFER), color_(GlBuffer::ARRAY_BUFFER), bgra_(true), normal_(GlBuffer::ARRAY_BUFFER), texCoord_(GlBuffer::ARRAY_BUFFER) - { - } - - void setVertexArray(const GlBuffer& vertex); - void setVertexArray(const GpuMat& vertex); - void setVertexArray(InputArray vertex); - inline void resetVertexArray() { vertex_.release(); } - - void setColorArray(const GlBuffer& color, bool bgra = true); - void setColorArray(const GpuMat& color, bool bgra = true); - void setColorArray(InputArray color, bool bgra = true); - inline void resetColorArray() { color_.release(); } - - void setNormalArray(const GlBuffer& normal); - void setNormalArray(const GpuMat& normal); - void setNormalArray(InputArray normal); - inline void resetNormalArray() { normal_.release(); } - - void setTexCoordArray(const GlBuffer& texCoord); - void setTexCoordArray(const GpuMat& texCoord); - void setTexCoordArray(InputArray texCoord); - inline void resetTexCoordArray() { texCoord_.release(); } - - void bind() const; - void unbind() const; - - inline int rows() const { return vertex_.rows; } - inline int cols() const { return vertex_.cols; } - inline Size size() const { return vertex_.size(); } - inline bool empty() const { return vertex_.empty(); } - - private: - GlBuffer vertex_; - GlBuffer color_; - bool bgra_; - GlBuffer normal_; - GlBuffer texCoord_; - }; - - //! render functions - - //! render texture rectangle in window - CV_EXPORTS void render(const GlTexture& tex, - Rect_ wndRect = Rect_(0.0, 0.0, 1.0, 1.0), - Rect_ texRect = Rect_(0.0, 0.0, 1.0, 1.0)); - - //! render mode - namespace RenderMode { - enum { - POINTS = 0x0000, - LINES = 0x0001, - LINE_LOOP = 0x0002, - LINE_STRIP = 0x0003, - TRIANGLES = 0x0004, - TRIANGLE_STRIP = 0x0005, - TRIANGLE_FAN = 0x0006, - QUADS = 0x0007, - QUAD_STRIP = 0x0008, - POLYGON = 0x0009 - }; - } - - //! render OpenGL arrays - CV_EXPORTS void render(const GlArrays& arr, int mode = RenderMode::POINTS); - - //! OpenGL camera - class CV_EXPORTS GlCamera - { - public: - GlCamera(); - - void lookAt(Point3d eye, Point3d center, Point3d up); - void setCameraPos(Point3d pos, double yaw, double pitch, double roll); - - void setScale(Point3d scale); - - void setProjectionMatrix(const Mat& projectionMatrix, bool transpose = true); - void setPerspectiveProjection(double fov, double aspect, double zNear, double zFar); - void setOrthoProjection(double left, double right, double bottom, double top, double zNear, double zFar); - - void setupProjectionMatrix() const; - void setupModelViewMatrix() const; - - private: - Point3d eye_; - Point3d center_; - Point3d up_; - - Point3d pos_; - double yaw_; - double pitch_; - double roll_; - - bool useLookAtParams_; - - Point3d scale_; - - Mat projectionMatrix_; - - double fov_; - double aspect_; - - double left_; - double right_; - double bottom_; - double top_; - - double zNear_; - double zFar_; - - bool perspectiveProjection_; - }; - - //! OpenGL extension table - class CV_EXPORTS GlFuncTab - { - public: - virtual ~GlFuncTab(); - - virtual void genBuffers(int n, unsigned int* buffers) const = 0; - virtual void deleteBuffers(int n, const unsigned int* buffers) const = 0; - - virtual void bufferData(unsigned int target, ptrdiff_t size, const void* data, unsigned int usage) const = 0; - virtual void bufferSubData(unsigned int target, ptrdiff_t offset, ptrdiff_t size, const void* data) const = 0; - - virtual void bindBuffer(unsigned int target, unsigned int buffer) const = 0; - - virtual void* mapBuffer(unsigned int target, unsigned int access) const = 0; - virtual void unmapBuffer(unsigned int target) const = 0; - - virtual bool isGlContextInitialized() const = 0; - }; - - CV_EXPORTS void setGlFuncTab(const GlFuncTab* tab); - //////////////////////////////////////////////////////////////////////// // Error handling CV_EXPORTS void error(const char* error_string, const char* file, const int line, const char* func = ""); - CV_EXPORTS bool checkGlError(const char* file, const int line, const char* func = ""); - - #if defined(__GNUC__) - #define CV_CheckGlError() CV_DbgAssert( (cv::gpu::checkGlError(__FILE__, __LINE__, __func__)) ) - #else - #define CV_CheckGlError() CV_DbgAssert( (cv::gpu::checkGlError(__FILE__, __LINE__)) ) - #endif //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// diff --git a/modules/core/include/opencv2/core/internal.hpp b/modules/core/include/opencv2/core/internal.hpp index 7c9a900f7d..23bba05236 100644 --- a/modules/core/include/opencv2/core/internal.hpp +++ b/modules/core/include/opencv2/core/internal.hpp @@ -708,4 +708,36 @@ CvBigFuncTable; (tab).fn_2d[CV_32F] = (void*)FUNCNAME##_32f##FLAG; \ (tab).fn_2d[CV_64F] = (void*)FUNCNAME##_64f##FLAG +//! OpenGL extension table +class CV_EXPORTS CvOpenGlFuncTab +{ +public: + virtual ~CvOpenGlFuncTab(); + + virtual void genBuffers(int n, unsigned int* buffers) const = 0; + virtual void deleteBuffers(int n, const unsigned int* buffers) const = 0; + + virtual void bufferData(unsigned int target, ptrdiff_t size, const void* data, unsigned int usage) const = 0; + virtual void bufferSubData(unsigned int target, ptrdiff_t offset, ptrdiff_t size, const void* data) const = 0; + + virtual void bindBuffer(unsigned int target, unsigned int buffer) const = 0; + + virtual void* mapBuffer(unsigned int target, unsigned int access) const = 0; + virtual void unmapBuffer(unsigned int target) const = 0; + + virtual void generateBitmapFont(const std::string& family, int height, int weight, bool italic, bool underline, int start, int count, int base) const = 0; + + virtual bool isGlContextInitialized() const = 0; +}; + +CV_EXPORTS void icvSetOpenGlFuncTab(const CvOpenGlFuncTab* tab); + +CV_EXPORTS bool icvCheckGlError(const char* file, const int line, const char* func = ""); + +#if defined(__GNUC__) + #define CV_CheckGlError() CV_DbgAssert( (::icvCheckGlError(__FILE__, __LINE__, __func__)) ) +#else + #define CV_CheckGlError() CV_DbgAssert( (::icvCheckGlError(__FILE__, __LINE__)) ) +#endif + #endif diff --git a/modules/core/include/opencv2/core/opengl_interop.hpp b/modules/core/include/opencv2/core/opengl_interop.hpp new file mode 100644 index 0000000000..59fcbfcdad --- /dev/null +++ b/modules/core/include/opencv2/core/opengl_interop.hpp @@ -0,0 +1,327 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other GpuMaterials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_OPENGL_INTEROP_HPP__ +#define __OPENCV_OPENGL_INTEROP_HPP__ + +#ifdef __cplusplus + +#include "opencv2/core/core.hpp" + +namespace cv +{ + //! Smart pointer for OpenGL buffer memory with reference counting. + class CV_EXPORTS GlBuffer + { + public: + enum Usage + { + ARRAY_BUFFER = 0x8892, // buffer will use for OpenGL arrays (vertices, colors, normals, etc) + TEXTURE_BUFFER = 0x88EC // buffer will ise for OpenGL textures + }; + + //! create empty buffer + explicit GlBuffer(Usage usage); + + //! create buffer + GlBuffer(int rows, int cols, int type, Usage usage); + GlBuffer(Size size, int type, Usage usage); + + //! copy from host/device memory + GlBuffer(InputArray mat, Usage usage); + + void create(int rows, int cols, int type, Usage usage); + inline void create(Size size, int type, Usage usage) { create(size.height, size.width, type, usage); } + inline void create(int rows, int cols, int type) { create(rows, cols, type, usage()); } + inline void create(Size size, int type) { create(size.height, size.width, type, usage()); } + + void release(); + + //! copy from host/device memory + void copyFrom(InputArray mat); + + void bind() const; + void unbind() const; + + //! map to host memory + Mat mapHost(); + void unmapHost(); + + //! map to device memory + gpu::GpuMat mapDevice(); + void unmapDevice(); + + int rows; + int cols; + + inline Size size() const { return Size(cols, rows); } + inline bool empty() const { return rows == 0 || cols == 0; } + + inline int type() const { return type_; } + inline int depth() const { return CV_MAT_DEPTH(type_); } + inline int channels() const { return CV_MAT_CN(type_); } + inline int elemSize() const { return CV_ELEM_SIZE(type_); } + inline int elemSize1() const { return CV_ELEM_SIZE1(type_); } + + inline Usage usage() const { return usage_; } + + private: + int type_; + Usage usage_; + + class Impl; + Ptr impl_; + }; + + template <> CV_EXPORTS void Ptr::delete_obj(); + + //! Smart pointer for OpenGL 2d texture memory with reference counting. + class CV_EXPORTS GlTexture + { + public: + //! create empty texture + GlTexture(); + + //! create texture + GlTexture(int rows, int cols, int type); + GlTexture(Size size, int type); + + //! copy from host/device memory + explicit GlTexture(InputArray mat, bool bgra = true); + + void create(int rows, int cols, int type); + inline void create(Size size, int type) { create(size.height, size.width, type); } + void release(); + + //! copy from host/device memory + void copyFrom(InputArray mat, bool bgra = true); + + void bind() const; + void unbind() const; + + int rows; + int cols; + + inline Size size() const { return Size(cols, rows); } + inline bool empty() const { return rows == 0 || cols == 0; } + + inline int type() const { return type_; } + inline int depth() const { return CV_MAT_DEPTH(type_); } + inline int channels() const { return CV_MAT_CN(type_); } + inline int elemSize() const { return CV_ELEM_SIZE(type_); } + inline int elemSize1() const { return CV_ELEM_SIZE1(type_); } + + private: + int type_; + + class Impl; + Ptr impl_; + }; + + template <> CV_EXPORTS void Ptr::delete_obj(); + + //! OpenGL Arrays + class CV_EXPORTS GlArrays + { + public: + inline GlArrays() + : vertex_(GlBuffer::ARRAY_BUFFER), color_(GlBuffer::ARRAY_BUFFER), bgra_(true), normal_(GlBuffer::ARRAY_BUFFER), texCoord_(GlBuffer::ARRAY_BUFFER) + { + } + + void setVertexArray(InputArray vertex); + inline void resetVertexArray() { vertex_.release(); } + + void setColorArray(InputArray color, bool bgra = true); + inline void resetColorArray() { color_.release(); } + + void setNormalArray(InputArray normal); + inline void resetNormalArray() { normal_.release(); } + + void setTexCoordArray(InputArray texCoord); + inline void resetTexCoordArray() { texCoord_.release(); } + + void bind() const; + void unbind() const; + + inline int rows() const { return vertex_.rows; } + inline int cols() const { return vertex_.cols; } + inline Size size() const { return vertex_.size(); } + inline bool empty() const { return vertex_.empty(); } + + private: + GlBuffer vertex_; + GlBuffer color_; + bool bgra_; + GlBuffer normal_; + GlBuffer texCoord_; + }; + + //! OpenGL Font + class CV_EXPORTS GlFont + { + public: + enum Weight + { + WEIGHT_LIGHT = 300, + WEIGHT_NORMAL = 400, + WEIGHT_SEMIBOLD = 600, + WEIGHT_BOLD = 700, + WEIGHT_BLACK = 900 + }; + + enum Style + { + STYLE_NORMAL = 0, + STYLE_ITALIC = 1, + STYLE_UNDERLINE = 2 + }; + + static Ptr get(const std::string& family, int height = 12, Weight weight = WEIGHT_NORMAL, Style style = STYLE_NORMAL); + + void draw(const char* str, int len) const; + + inline const std::string& family() const { return family_; } + inline int height() const { return height_; } + inline Weight weight() const { return weight_; } + inline Style style() const { return style_; } + + private: + GlFont(const std::string& family, int height, Weight weight, Style style); + + std::string family_; + int height_; + Weight weight_; + Style style_; + + unsigned int base_; + + GlFont(const GlFont&); + GlFont& operator =(const GlFont&); + }; + + //! render functions + + //! render texture rectangle in window + CV_EXPORTS void render(const GlTexture& tex, + Rect_ wndRect = Rect_(0.0, 0.0, 1.0, 1.0), + Rect_ texRect = Rect_(0.0, 0.0, 1.0, 1.0)); + + //! render mode + namespace RenderMode { + enum { + POINTS = 0x0000, + LINES = 0x0001, + LINE_LOOP = 0x0002, + LINE_STRIP = 0x0003, + TRIANGLES = 0x0004, + TRIANGLE_STRIP = 0x0005, + TRIANGLE_FAN = 0x0006, + QUADS = 0x0007, + QUAD_STRIP = 0x0008, + POLYGON = 0x0009 + }; + } + + //! render OpenGL arrays + CV_EXPORTS void render(const GlArrays& arr, int mode = RenderMode::POINTS); + + CV_EXPORTS void render(const std::string& str, const Ptr& font, Scalar color, Point2d pos); + + //! OpenGL camera + class CV_EXPORTS GlCamera + { + public: + GlCamera(); + + void lookAt(Point3d eye, Point3d center, Point3d up); + void setCameraPos(Point3d pos, double yaw, double pitch, double roll); + + void setScale(Point3d scale); + + void setProjectionMatrix(const Mat& projectionMatrix, bool transpose = true); + void setPerspectiveProjection(double fov, double aspect, double zNear, double zFar); + void setOrthoProjection(double left, double right, double bottom, double top, double zNear, double zFar); + + void setupProjectionMatrix() const; + void setupModelViewMatrix() const; + + private: + Point3d eye_; + Point3d center_; + Point3d up_; + + Point3d pos_; + double yaw_; + double pitch_; + double roll_; + + bool useLookAtParams_; + + Point3d scale_; + + Mat projectionMatrix_; + + double fov_; + double aspect_; + + double left_; + double right_; + double bottom_; + double top_; + + double zNear_; + double zFar_; + + bool perspectiveProjection_; + }; + + namespace gpu + { + //! set a CUDA device to use OpenGL interoperability + CV_EXPORTS void setGlDevice(int device = 0); + } +} // namespace cv + +#endif // __cplusplus + +#endif // __OPENCV_OPENGL_INTEROP_HPP__ diff --git a/modules/core/src/gpumat.cpp b/modules/core/src/gpumat.cpp index f06772c305..c5910761f5 100644 --- a/modules/core/src/gpumat.cpp +++ b/modules/core/src/gpumat.cpp @@ -50,22 +50,10 @@ #include #endif -#ifdef HAVE_OPENGL - #include - #include - - #ifdef HAVE_CUDA - #include - #endif -#endif - using namespace std; using namespace cv; using namespace cv::gpu; -//////////////////////////////////////////////////////////////////////// -// GpuMat - cv::gpu::GpuMat::GpuMat(const GpuMat& m) : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data), refcount(m.refcount), datastart(m.datastart), dataend(m.dataend) { @@ -327,28 +315,25 @@ namespace #ifndef HAVE_CUDA +#define throw_nocuda CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support") + namespace { - void throw_nogpu() - { - CV_Error(CV_GpuNotSupported, "The library is compiled without GPU support"); - } - class EmptyFuncTable : public GpuFuncTable { public: - void copy(const Mat&, GpuMat&) const { throw_nogpu(); } - void copy(const GpuMat&, Mat&) const { throw_nogpu(); } - void copy(const GpuMat&, GpuMat&) const { throw_nogpu(); } + void copy(const Mat&, GpuMat&) const { throw_nocuda; } + void copy(const GpuMat&, Mat&) const { throw_nocuda; } + void copy(const GpuMat&, GpuMat&) const { throw_nocuda; } - void copyWithMask(const GpuMat&, GpuMat&, const GpuMat&) const { throw_nogpu(); } + void copyWithMask(const GpuMat&, GpuMat&, const GpuMat&) const { throw_nocuda; } - void convert(const GpuMat&, GpuMat&) const { throw_nogpu(); } - void convert(const GpuMat&, GpuMat&, double, double) const { throw_nogpu(); } + void convert(const GpuMat&, GpuMat&) const { throw_nocuda; } + void convert(const GpuMat&, GpuMat&, double, double) const { throw_nocuda; } - void setTo(GpuMat&, Scalar, const GpuMat&) const { throw_nogpu(); } + void setTo(GpuMat&, Scalar, const GpuMat&) const { throw_nocuda; } - void mallocPitch(void**, size_t*, size_t, size_t) const { throw_nogpu(); } + void mallocPitch(void**, size_t*, size_t, size_t) const { throw_nocuda; } void free(void*) const {} }; @@ -944,1405 +929,20 @@ void cv::gpu::GpuMat::release() } //////////////////////////////////////////////////////////////////////// -// OpenGL - -namespace -{ - void throw_nogl() - { - #ifndef HAVE_OPENGL - CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); - #else - CV_Error(CV_OpenGlNotSupported, "OpenGL context doesn't exist"); - #endif - } - - class EmptyGlFuncTab : public GlFuncTab - { - public: - void genBuffers(int, unsigned int*) const { throw_nogl(); } - void deleteBuffers(int, const unsigned int*) const { throw_nogl(); } - - void bufferData(unsigned int, ptrdiff_t, const void*, unsigned int) const { throw_nogl(); } - void bufferSubData(unsigned int, ptrdiff_t, ptrdiff_t, const void*) const { throw_nogl(); } - - void bindBuffer(unsigned int, unsigned int) const { throw_nogl(); } - - void* mapBuffer(unsigned int, unsigned int) const { throw_nogl(); return 0; } - void unmapBuffer(unsigned int) const { throw_nogl(); } - - bool isGlContextInitialized() const { return false; } - }; - - const GlFuncTab* g_glFuncTab = 0; - - const GlFuncTab* glFuncTab() - { - static EmptyGlFuncTab empty; - return g_glFuncTab ? g_glFuncTab : ∅ - } -} - -cv::gpu::GlFuncTab::~GlFuncTab() -{ - if (g_glFuncTab == this) - g_glFuncTab = 0; -} - -void cv::gpu::setGlFuncTab(const GlFuncTab* tab) -{ - g_glFuncTab = tab; -} - -#ifdef HAVE_OPENGL - #ifndef GL_DYNAMIC_DRAW - #define GL_DYNAMIC_DRAW 0x88E8 - #endif - - #ifndef GL_READ_WRITE - #define GL_READ_WRITE 0x88BA - #endif - - #ifndef GL_BGR - #define GL_BGR 0x80E0 - #endif - - #ifndef GL_BGRA - #define GL_BGRA 0x80E1 - #endif - - namespace - { - const GLenum gl_types[] = {GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE}; - - #ifdef HAVE_CUDA - bool g_isCudaGlDeviceInitialized = false; - #endif - } -#endif // HAVE_OPENGL - - - -void cv::gpu::setGlDevice(int device) -{ -#ifndef HAVE_CUDA - throw_nogpu(); -#else - #ifndef HAVE_OPENGL - throw_nogl(); - #else - if (!glFuncTab()->isGlContextInitialized()) - throw_nogl(); - - cudaSafeCall( cudaGLSetGLDevice(device) ); - - g_isCudaGlDeviceInitialized = true; - #endif -#endif -} - -//////////////////////////////////////////////////////////////////////// -// CudaGlInterop - -#if defined HAVE_CUDA && defined HAVE_OPENGL -namespace -{ - class CudaGlInterop - { - public: - CudaGlInterop(); - ~CudaGlInterop(); - - void registerBuffer(unsigned int buffer); - - void copyFrom(const GpuMat& mat, cudaStream_t stream = 0); - - GpuMat map(int rows, int cols, int type, cudaStream_t stream = 0); - void unmap(cudaStream_t stream = 0); - - private: - cudaGraphicsResource_t resource_; - }; - - inline CudaGlInterop::CudaGlInterop() : resource_(0) - { - } - - CudaGlInterop::~CudaGlInterop() - { - if (resource_) - { - cudaGraphicsUnregisterResource(resource_); - resource_ = 0; - } - } - - void CudaGlInterop::registerBuffer(unsigned int buffer) - { - if (!g_isCudaGlDeviceInitialized) - cvError(CV_GpuApiCallError, "registerBuffer", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__); - - cudaGraphicsResource_t resource; - cudaSafeCall( cudaGraphicsGLRegisterBuffer(&resource, buffer, cudaGraphicsMapFlagsNone) ); - - resource_ = resource; - } - - void CudaGlInterop::copyFrom(const GpuMat& mat, cudaStream_t stream) - { - CV_Assert(resource_ != 0); - - cudaSafeCall( cudaGraphicsMapResources(1, &resource_, stream) ); - - void* dst_ptr; - size_t num_bytes; - cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&dst_ptr, &num_bytes, resource_) ); - - const void* src_ptr = mat.ptr(); - size_t widthBytes = mat.cols * mat.elemSize(); - - CV_Assert(widthBytes * mat.rows <= num_bytes); - - if (stream == 0) - cudaSafeCall( cudaMemcpy2D(dst_ptr, widthBytes, src_ptr, mat.step, widthBytes, mat.rows, cudaMemcpyDeviceToDevice) ); - else - cudaSafeCall( cudaMemcpy2DAsync(dst_ptr, widthBytes, src_ptr, mat.step, widthBytes, mat.rows, cudaMemcpyDeviceToDevice, stream) ); - - cudaGraphicsUnmapResources(1, &resource_, stream); - } - - GpuMat CudaGlInterop::map(int rows, int cols, int type, cudaStream_t stream) - { - CV_Assert(resource_ != 0); - - cudaSafeCall( cudaGraphicsMapResources(1, &resource_, stream) ); - - void* ptr; - size_t num_bytes; - cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&ptr, &num_bytes, resource_) ); - - CV_Assert( static_cast(cols) * CV_ELEM_SIZE(type) * rows <= num_bytes ); - - return GpuMat(rows, cols, type, ptr); - } - - inline void CudaGlInterop::unmap(cudaStream_t stream) - { - cudaGraphicsUnmapResources(1, &resource_, stream); - } -} -#endif // HAVE_CUDA && HAVE_OPENGL - -//////////////////////////////////////////////////////////////////////// -// GlBuffer - -#ifndef HAVE_OPENGL - -class cv::gpu::GlBuffer::Impl -{ -}; - -#else - -class cv::gpu::GlBuffer::Impl -{ -public: - Impl(); - Impl(int rows, int cols, int type, unsigned int target); - Impl(const Mat& m, unsigned int target); - ~Impl(); - - void copyFrom(const Mat& m, unsigned int target); - -#ifdef HAVE_CUDA - void copyFrom(const GpuMat& mat, cudaStream_t stream = 0); -#endif - - void bind(unsigned int target) const; - void unbind(unsigned int target) const; - - Mat mapHost(int rows, int cols, int type, unsigned int target); - void unmapHost(unsigned int target); - -#ifdef HAVE_CUDA - GpuMat mapDevice(int rows, int cols, int type, cudaStream_t stream = 0); - void unmapDevice(cudaStream_t stream = 0); -#endif - -private: - unsigned int buffer_; - -#ifdef HAVE_CUDA - CudaGlInterop cudaGlInterop_; -#endif -}; - -inline cv::gpu::GlBuffer::Impl::Impl() : buffer_(0) -{ -} - -cv::gpu::GlBuffer::Impl::Impl(int rows, int cols, int type, unsigned int target) : buffer_(0) -{ - if (!glFuncTab()->isGlContextInitialized()) - throw_nogl(); - - CV_DbgAssert(rows > 0 && cols > 0); - CV_DbgAssert(CV_MAT_DEPTH(type) >= 0 && CV_MAT_DEPTH(type) <= CV_64F); - - glFuncTab()->genBuffers(1, &buffer_); - CV_CheckGlError(); - CV_Assert(buffer_ != 0); - - size_t size = rows * cols * CV_ELEM_SIZE(type); - - glFuncTab()->bindBuffer(target, buffer_); - CV_CheckGlError(); - - glFuncTab()->bufferData(target, size, 0, GL_DYNAMIC_DRAW); - CV_CheckGlError(); - - glFuncTab()->bindBuffer(target, 0); - -#ifdef HAVE_CUDA - if (g_isCudaGlDeviceInitialized) - cudaGlInterop_.registerBuffer(buffer_); -#endif -} +// Error handling -cv::gpu::GlBuffer::Impl::Impl(const Mat& m, unsigned int target) : buffer_(0) +void cv::gpu::error(const char *error_string, const char *file, const int line, const char *func) { - if (!glFuncTab()->isGlContextInitialized()) - throw_nogl(); - - CV_DbgAssert(m.rows > 0 && m.cols > 0); - CV_DbgAssert(m.depth() >= 0 && m.depth() <= CV_64F); - CV_Assert(m.isContinuous()); - - glFuncTab()->genBuffers(1, &buffer_); - CV_CheckGlError(); - CV_Assert(buffer_ != 0); - - size_t size = m.rows * m.cols * m.elemSize(); - - glFuncTab()->bindBuffer(target, buffer_); - CV_CheckGlError(); - - glFuncTab()->bufferData(target, size, m.data, GL_DYNAMIC_DRAW); - CV_CheckGlError(); - - glFuncTab()->bindBuffer(target, 0); - -#ifdef HAVE_CUDA - if (g_isCudaGlDeviceInitialized) - cudaGlInterop_.registerBuffer(buffer_); -#endif -} + int code = CV_GpuApiCallError; -cv::gpu::GlBuffer::Impl::~Impl() -{ - try - { - if (buffer_) - glFuncTab()->deleteBuffers(1, &buffer_); - } -#ifdef _DEBUG - catch(const exception& e) - { - cerr << e.what() << endl; - } -#endif - catch(...) + if (uncaught_exception()) { - } -} - -void cv::gpu::GlBuffer::Impl::copyFrom(const Mat& m, unsigned int target) -{ - CV_Assert(buffer_ != 0); - - CV_Assert(m.isContinuous()); - - bind(target); - - size_t size = m.rows * m.cols * m.elemSize(); - - glFuncTab()->bufferSubData(target, 0, size, m.data); - CV_CheckGlError(); - - unbind(target); -} - -#ifdef HAVE_CUDA - -void cv::gpu::GlBuffer::Impl::copyFrom(const GpuMat& mat, cudaStream_t stream) -{ - if (!g_isCudaGlDeviceInitialized) - cvError(CV_GpuApiCallError, "copyFrom", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__); - - CV_Assert(buffer_ != 0); - - cudaGlInterop_.copyFrom(mat, stream); -} - -#endif // HAVE_CUDA - -inline void cv::gpu::GlBuffer::Impl::bind(unsigned int target) const -{ - CV_Assert(buffer_ != 0); - - glFuncTab()->bindBuffer(target, buffer_); - CV_CheckGlError(); -} - -inline void cv::gpu::GlBuffer::Impl::unbind(unsigned int target) const -{ - glFuncTab()->bindBuffer(target, 0); -} - -inline Mat cv::gpu::GlBuffer::Impl::mapHost(int rows, int cols, int type, unsigned int target) -{ - void* ptr = glFuncTab()->mapBuffer(target, GL_READ_WRITE); - CV_CheckGlError(); - - return Mat(rows, cols, type, ptr); -} - -inline void cv::gpu::GlBuffer::Impl::unmapHost(unsigned int target) -{ - glFuncTab()->unmapBuffer(target); -} - -#ifdef HAVE_CUDA - -inline GpuMat cv::gpu::GlBuffer::Impl::mapDevice(int rows, int cols, int type, cudaStream_t stream) -{ - if (!g_isCudaGlDeviceInitialized) - cvError(CV_GpuApiCallError, "copyFrom", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__); - - CV_Assert(buffer_ != 0); - - return cudaGlInterop_.map(rows, cols, type, stream); -} - -inline void cv::gpu::GlBuffer::Impl::unmapDevice(cudaStream_t stream) -{ - if (!g_isCudaGlDeviceInitialized) - cvError(CV_GpuApiCallError, "copyFrom", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__); - - cudaGlInterop_.unmap(stream); -} - -#endif // HAVE_CUDA - -#endif // HAVE_OPENGL - -cv::gpu::GlBuffer::GlBuffer(Usage usage) : rows(0), cols(0), type_(0), usage_(usage) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_ = new Impl; -#endif -} - -cv::gpu::GlBuffer::GlBuffer(int rows_, int cols_, int type, Usage usage) : rows(0), cols(0), type_(0), usage_(usage) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_ = new Impl(rows_, cols_, type, usage); - rows = rows_; - cols = cols_; - type_ = type; -#endif -} - -cv::gpu::GlBuffer::GlBuffer(Size size, int type, Usage usage) : rows(0), cols(0), type_(0), usage_(usage) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_ = new Impl(size.height, size.width, type, usage); - rows = size.height; - cols = size.width; - type_ = type; -#endif -} - -cv::gpu::GlBuffer::GlBuffer(InputArray mat_, Usage usage) : rows(0), cols(0), type_(0), usage_(usage) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - Mat mat = mat_.getMat(); - impl_ = new Impl(mat, usage); - rows = mat.rows; - cols = mat.cols; - type_ = mat.type(); -#endif -} - -cv::gpu::GlBuffer::GlBuffer(const GpuMat& d_mat, Usage usage) : rows(0), cols(0), type_(0), usage_(usage) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - #ifndef HAVE_CUDA - throw_nogpu(); - #else - impl_ = new Impl(d_mat.rows, d_mat.cols, d_mat.type(), usage); - impl_->copyFrom(d_mat); - rows = d_mat.rows; - cols = d_mat.cols; - type_ = d_mat.type(); - #endif -#endif -} - -cv::gpu::GlBuffer::GlBuffer(const GlBuffer& other) - : rows(other.rows), cols(other.cols), type_(other.type_), usage_(other.usage_), impl_(other.impl_) -{ -} - -cv::gpu::GlBuffer::~GlBuffer() -{ -} - -GlBuffer& cv::gpu::GlBuffer::operator =(const GlBuffer& other) -{ - rows = other.rows; - cols = other.cols; - type_ = other.type_; - usage_ = other.usage_; - impl_ = other.impl_; - return *this; -} + const char* errorStr = cvErrorStr(code); + const char* function = func ? func : "unknown function"; -void cv::gpu::GlBuffer::create(int rows_, int cols_, int type, Usage usage) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - if (rows_ != rows || cols_ != cols || type_ != type || usage_ != usage) - { - impl_ = new Impl(rows_, cols_, type, usage); - rows = rows_; - cols = cols_; - type_ = type; - usage_ = usage; - } -#endif -} - -void cv::gpu::GlBuffer::release() -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_ = new Impl; -#endif -} - -void cv::gpu::GlBuffer::copyFrom(InputArray mat_) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - Mat mat = mat_.getMat(); - create(mat.rows, mat.cols, mat.type()); - impl_->copyFrom(mat, usage_); -#endif -} - -void cv::gpu::GlBuffer::copyFrom(const GpuMat& d_mat) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - #ifndef HAVE_CUDA - throw_nogpu(); - #else - create(d_mat.rows, d_mat.cols, d_mat.type()); - impl_->copyFrom(d_mat); - #endif -#endif -} - -void cv::gpu::GlBuffer::bind() const -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_->bind(usage_); -#endif -} - -void cv::gpu::GlBuffer::unbind() const -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_->unbind(usage_); -#endif -} - -Mat cv::gpu::GlBuffer::mapHost() -{ -#ifndef HAVE_OPENGL - throw_nogl(); - return Mat(); -#else - return impl_->mapHost(rows, cols, type_, usage_); -#endif -} - -void cv::gpu::GlBuffer::unmapHost() -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_->unmapHost(usage_); -#endif -} - -GpuMat cv::gpu::GlBuffer::mapDevice() -{ -#ifndef HAVE_OPENGL - throw_nogl(); - return GpuMat(); -#else - #ifndef HAVE_CUDA - throw_nogpu(); - return GpuMat(); - #else - return impl_->mapDevice(rows, cols, type_); - #endif -#endif -} - -void cv::gpu::GlBuffer::unmapDevice() -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - #ifndef HAVE_CUDA - throw_nogpu(); - #else - impl_->unmapDevice(); - #endif -#endif -} - -////////////////////////////////////////////////////////////////////////////////////////// -// GlTexture - -#ifndef HAVE_OPENGL - -class cv::gpu::GlTexture::Impl -{ -}; - -#else - -class cv::gpu::GlTexture::Impl -{ -public: - Impl(); - - Impl(int rows, int cols, int type); - - Impl(const Mat& mat, bool bgra); - Impl(const GlBuffer& buf, bool bgra); - - ~Impl(); - - void copyFrom(const Mat& mat, bool bgra); - void copyFrom(const GlBuffer& buf, bool bgra); - - void bind() const; - void unbind() const; - -private: - GLuint tex_; -}; - -inline cv::gpu::GlTexture::Impl::Impl() : tex_(0) -{ -} - -cv::gpu::GlTexture::Impl::Impl(int rows, int cols, int type) : tex_(0) -{ - if (!glFuncTab()->isGlContextInitialized()) - throw_nogl(); - - int depth = CV_MAT_DEPTH(type); - int cn = CV_MAT_CN(type); - - CV_DbgAssert(rows > 0 && cols > 0); - CV_Assert(cn == 1 || cn == 3 || cn == 4); - CV_Assert(depth >= 0 && depth <= CV_32F); - - glGenTextures(1, &tex_); - CV_CheckGlError(); - CV_Assert(tex_ != 0); - - glBindTexture(GL_TEXTURE_2D, tex_); - CV_CheckGlError(); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - CV_CheckGlError(); - - GLenum format = cn == 1 ? GL_LUMINANCE : cn == 3 ? GL_BGR : GL_BGRA; - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - CV_CheckGlError(); - - glTexImage2D(GL_TEXTURE_2D, 0, cn, cols, rows, 0, format, gl_types[depth], 0); - CV_CheckGlError(); -} - -cv::gpu::GlTexture::Impl::Impl(const Mat& mat, bool bgra) : tex_(0) -{ - if (!glFuncTab()->isGlContextInitialized()) - throw_nogl(); - - int depth = mat.depth(); - int cn = mat.channels(); - - CV_DbgAssert(mat.rows > 0 && mat.cols > 0); - CV_Assert(cn == 1 || cn == 3 || cn == 4); - CV_Assert(depth >= 0 && depth <= CV_32F); - CV_Assert(mat.isContinuous()); - - glGenTextures(1, &tex_); - CV_CheckGlError(); - CV_Assert(tex_ != 0); - - glBindTexture(GL_TEXTURE_2D, tex_); - CV_CheckGlError(); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - CV_CheckGlError(); - - GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA)); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - CV_CheckGlError(); - - glTexImage2D(GL_TEXTURE_2D, 0, cn, mat.cols, mat.rows, 0, format, gl_types[depth], mat.data); - CV_CheckGlError(); -} - -cv::gpu::GlTexture::Impl::Impl(const GlBuffer& buf, bool bgra) : tex_(0) -{ - if (!glFuncTab()->isGlContextInitialized()) - throw_nogl(); - - int depth = buf.depth(); - int cn = buf.channels(); - - CV_DbgAssert(buf.rows > 0 && buf.cols > 0); - CV_Assert(cn == 1 || cn == 3 || cn == 4); - CV_Assert(depth >= 0 && depth <= CV_32F); - CV_Assert(buf.usage() == GlBuffer::TEXTURE_BUFFER); - - glGenTextures(1, &tex_); - CV_CheckGlError(); - CV_Assert(tex_ != 0); - - glBindTexture(GL_TEXTURE_2D, tex_); - CV_CheckGlError(); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - CV_CheckGlError(); - - GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA)); - - buf.bind(); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - CV_CheckGlError(); - - glTexImage2D(GL_TEXTURE_2D, 0, cn, buf.cols, buf.rows, 0, format, gl_types[depth], 0); - CV_CheckGlError(); - - buf.unbind(); -} - -inline cv::gpu::GlTexture::Impl::~Impl() -{ - if (tex_) - glDeleteTextures(1, &tex_); -} - -void cv::gpu::GlTexture::Impl::copyFrom(const Mat& mat, bool bgra) -{ - CV_Assert(tex_ != 0); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - CV_CheckGlError(); - - int cn = mat.channels(); - GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA)); - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mat.cols, mat.rows, format, gl_types[mat.depth()], mat.data); - CV_CheckGlError(); -} - -void cv::gpu::GlTexture::Impl::copyFrom(const GlBuffer& buf, bool bgra) -{ - CV_Assert(tex_ != 0); - CV_Assert(buf.usage() == GlBuffer::TEXTURE_BUFFER); - - buf.bind(); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - CV_CheckGlError(); - - int cn = buf.channels(); - GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA)); - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, buf.cols, buf.rows, format, gl_types[buf.depth()], 0); - CV_CheckGlError(); - - buf.unbind(); -} - -inline void cv::gpu::GlTexture::Impl::bind() const -{ - CV_Assert(tex_ != 0); - - glEnable(GL_TEXTURE_2D); - CV_CheckGlError(); - - glBindTexture(GL_TEXTURE_2D, tex_); - CV_CheckGlError(); -} - -inline void cv::gpu::GlTexture::Impl::unbind() const -{ - glBindTexture(GL_TEXTURE_2D, 0); - - glDisable(GL_TEXTURE_2D); -} - -#endif // HAVE_OPENGL - -cv::gpu::GlTexture::GlTexture() : rows(0), cols(0), type_(0) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_ = new Impl; -#endif -} - -cv::gpu::GlTexture::GlTexture(int rows_, int cols_, int type) : rows(0), cols(0), type_(0) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_ = new Impl(rows_, cols_, type); - rows = rows_; - cols = cols_; - type_ = type; -#endif -} - -cv::gpu::GlTexture::GlTexture(Size size, int type) : rows(0), cols(0), type_(0) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_ = new Impl(size.height, size.width, type); - rows = size.height; - cols = size.width; - type_ = type; -#endif -} - -cv::gpu::GlTexture::GlTexture(InputArray mat_, bool bgra) : rows(0), cols(0), type_(0) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - Mat mat = mat_.getMat(); - impl_ = new Impl(mat, bgra); - rows = mat.rows; - cols = mat.cols; - type_ = mat.type(); -#endif -} - -cv::gpu::GlTexture::GlTexture(const GlBuffer& buf, bool bgra) : rows(0), cols(0), type_(0) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_ = new Impl(buf, bgra); - rows = buf.rows; - cols = buf.cols; - type_ = buf.type(); -#endif -} - -cv::gpu::GlTexture::GlTexture(const GlTexture& other) - : rows(other.rows), cols(other.cols), type_(other.type_), impl_(other.impl_) -{ -} - -cv::gpu::GlTexture::~GlTexture() -{ -} - -GlTexture& cv::gpu::GlTexture::operator =(const GlTexture& other) -{ - rows = other.rows; - cols = other.cols; - type_ = other.type_; - impl_ = other.impl_; - return *this; -} - -void cv::gpu::GlTexture::create(int rows_, int cols_, int type) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - if (rows_ != rows || cols_ != cols || type_ != type) - { - impl_ = new Impl(rows_, cols_, type); - rows = rows_; - cols = cols_; - type_ = type; - } -#endif -} - -void cv::gpu::GlTexture::release() -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_ = new Impl; -#endif -} - -void cv::gpu::GlTexture::copyFrom(InputArray mat_, bool bgra) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - Mat mat = mat_.getMat(); - create(mat.rows, mat.cols, mat.type()); - impl_->copyFrom(mat, bgra); -#endif -} - -void cv::gpu::GlTexture::copyFrom(const GlBuffer& buf, bool bgra) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - create(buf.rows, buf.cols, buf.type()); - impl_->copyFrom(buf, bgra); -#endif -} - -void cv::gpu::GlTexture::bind() const -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_->bind(); -#endif -} - -void cv::gpu::GlTexture::unbind() const -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - impl_->unbind(); -#endif -} - -//////////////////////////////////////////////////////////////////////// -// GlArrays - -void cv::gpu::GlArrays::setVertexArray(const GlBuffer& vertex) -{ - CV_Assert(vertex.usage() == GlBuffer::ARRAY_BUFFER); - - int cn = vertex.channels(); - int depth = vertex.depth(); - - CV_Assert(cn == 2 || cn == 3 || cn == 4); - CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); - - vertex_ = vertex; -} - -void cv::gpu::GlArrays::setVertexArray(const GpuMat& vertex) -{ - int cn = vertex.channels(); - int depth = vertex.depth(); - - CV_Assert(cn == 2 || cn == 3 || cn == 4); - CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); - - vertex_.copyFrom(vertex); -} - -void cv::gpu::GlArrays::setVertexArray(InputArray vertex) -{ - int cn = vertex.channels(); - int depth = vertex.depth(); - - CV_Assert(cn == 2 || cn == 3 || cn == 4); - CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); - - vertex_.copyFrom(vertex); -} - -void cv::gpu::GlArrays::setColorArray(const GlBuffer& color, bool bgra) -{ - CV_Assert(color.usage() == GlBuffer::ARRAY_BUFFER); - - int cn = color.channels(); - - CV_Assert((cn == 3 && !bgra) || cn == 4); - - color_ = color; - bgra_ = bgra; -} - -void cv::gpu::GlArrays::setColorArray(const GpuMat& color, bool bgra) -{ - int cn = color.channels(); - - CV_Assert((cn == 3 && !bgra) || cn == 4); - - color_.copyFrom(color); - bgra_ = bgra; -} - -void cv::gpu::GlArrays::setColorArray(InputArray color, bool bgra) -{ - int cn = color.channels(); - - CV_Assert((cn == 3 && !bgra) || cn == 4); - - color_.copyFrom(color); - bgra_ = bgra; -} - -void cv::gpu::GlArrays::setNormalArray(const GlBuffer& normal) -{ - CV_Assert(normal.usage() == GlBuffer::ARRAY_BUFFER); - - int cn = normal.channels(); - int depth = normal.depth(); - - CV_Assert(cn == 3); - CV_Assert(depth == CV_8S || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); - - normal_ = normal; -} - -void cv::gpu::GlArrays::setNormalArray(const GpuMat& normal) -{ - int cn = normal.channels(); - int depth = normal.depth(); - - CV_Assert(cn == 3); - CV_Assert(depth == CV_8S || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); - - normal_.copyFrom(normal); -} - -void cv::gpu::GlArrays::setNormalArray(InputArray normal) -{ - int cn = normal.channels(); - int depth = normal.depth(); - - CV_Assert(cn == 3); - CV_Assert(depth == CV_8S || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); - - normal_.copyFrom(normal); -} - -void cv::gpu::GlArrays::setTexCoordArray(const GlBuffer& texCoord) -{ - CV_Assert(texCoord.usage() == GlBuffer::ARRAY_BUFFER); - - int cn = texCoord.channels(); - int depth = texCoord.depth(); - - CV_Assert(cn >= 1 && cn <= 4); - CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); - - texCoord_ = texCoord; -} - -void cv::gpu::GlArrays::setTexCoordArray(const GpuMat& texCoord) -{ - int cn = texCoord.channels(); - int depth = texCoord.depth(); - - CV_Assert(cn >= 1 && cn <= 4); - CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); - - texCoord_.copyFrom(texCoord); -} - -void cv::gpu::GlArrays::setTexCoordArray(InputArray texCoord) -{ - int cn = texCoord.channels(); - int depth = texCoord.depth(); - - CV_Assert(cn >= 1 && cn <= 4); - CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); - - texCoord_.copyFrom(texCoord); -} - -void cv::gpu::GlArrays::bind() const -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - CV_DbgAssert(texCoord_.empty() || texCoord_.size().area() == vertex_.size().area()); - CV_DbgAssert(normal_.empty() || normal_.size().area() == vertex_.size().area()); - CV_DbgAssert(color_.empty() || color_.size().area() == vertex_.size().area()); - - if (!texCoord_.empty()) - { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - CV_CheckGlError(); - - texCoord_.bind(); - - glTexCoordPointer(texCoord_.channels(), gl_types[texCoord_.depth()], 0, 0); - CV_CheckGlError(); - - texCoord_.unbind(); - } - - if (!normal_.empty()) - { - glEnableClientState(GL_NORMAL_ARRAY); - CV_CheckGlError(); - - normal_.bind(); - - glNormalPointer(gl_types[normal_.depth()], 0, 0); - CV_CheckGlError(); - - normal_.unbind(); - } - - if (!color_.empty()) - { - glEnableClientState(GL_COLOR_ARRAY); - CV_CheckGlError(); - - color_.bind(); - - int cn = color_.channels(); - int format = cn == 3 ? cn : (bgra_ ? GL_BGRA : 4); - - glColorPointer(format, gl_types[color_.depth()], 0, 0); - CV_CheckGlError(); - - color_.unbind(); - } - - if (!vertex_.empty()) - { - glEnableClientState(GL_VERTEX_ARRAY); - CV_CheckGlError(); - - vertex_.bind(); - - glVertexPointer(vertex_.channels(), gl_types[vertex_.depth()], 0, 0); - CV_CheckGlError(); - - vertex_.unbind(); - } -#endif -} - -void cv::gpu::GlArrays::unbind() const -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - if (!texCoord_.empty()) - { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - CV_CheckGlError(); - } - - if (!normal_.empty()) - { - glDisableClientState(GL_NORMAL_ARRAY); - CV_CheckGlError(); - } - - if (!color_.empty()) - { - glDisableClientState(GL_COLOR_ARRAY); - CV_CheckGlError(); - } - - if (!vertex_.empty()) - { - glDisableClientState(GL_VERTEX_ARRAY); - CV_CheckGlError(); - } -#endif -} - -//////////////////////////////////////////////////////////////////////// -// Rendering - -void cv::gpu::render(const GlTexture& tex, Rect_ wndRect, Rect_ texRect) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - if (!tex.empty()) - { - tex.bind(); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - glBegin(GL_QUADS); - glTexCoord2d(texRect.x, texRect.y); - glVertex2d(wndRect.x, wndRect.y); - - glTexCoord2d(texRect.x, texRect.y + texRect.height); - glVertex2d(wndRect.x, (wndRect.y + wndRect.height)); - - glTexCoord2d(texRect.x + texRect.width, texRect.y + texRect.height); - glVertex2d(wndRect.x + wndRect.width, (wndRect.y + wndRect.height)); - - glTexCoord2d(texRect.x + texRect.width, texRect.y); - glVertex2d(wndRect.x + wndRect.width, wndRect.y); - glEnd(); - - CV_CheckGlError(); - - tex.unbind(); - } -#endif -} - -void cv::gpu::render(const GlArrays& arr, int mode) -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - arr.bind(); - - glDrawArrays(mode, 0, arr.size().area()); - - arr.unbind(); -#endif -} - -//////////////////////////////////////////////////////////////////////// -// GlCamera - -cv::gpu::GlCamera::GlCamera() : - eye_(0.0, 0.0, -5.0), center_(0.0, 0.0, 0.0), up_(0.0, 1.0, 0.0), - pos_(0.0, 0.0, -5.0), yaw_(0.0), pitch_(0.0), roll_(0.0), - useLookAtParams_(false), - - scale_(1.0, 1.0, 1.0), - - projectionMatrix_(), - fov_(45.0), aspect_(0.0), - left_(0.0), right_(1.0), bottom_(1.0), top_(0.0), - zNear_(-1.0), zFar_(1.0), - perspectiveProjection_(false) -{ -} - -void cv::gpu::GlCamera::lookAt(Point3d eye, Point3d center, Point3d up) -{ - eye_ = eye; - center_ = center; - up_ = up; - useLookAtParams_ = true; -} - -void cv::gpu::GlCamera::setCameraPos(Point3d pos, double yaw, double pitch, double roll) -{ - pos_ = pos; - yaw_ = yaw; - pitch_ = pitch; - roll_ = roll; - useLookAtParams_ = false; -} - -void cv::gpu::GlCamera::setScale(Point3d scale) -{ - scale_ = scale; -} - -void cv::gpu::GlCamera::setProjectionMatrix(const Mat& projectionMatrix, bool transpose) -{ - CV_Assert(projectionMatrix.type() == CV_32F || projectionMatrix.type() == CV_64F); - CV_Assert(projectionMatrix.cols == 4 && projectionMatrix.rows == 4); - - projectionMatrix_ = transpose ? projectionMatrix.t() : projectionMatrix; -} - -void cv::gpu::GlCamera::setPerspectiveProjection(double fov, double aspect, double zNear, double zFar) -{ - fov_ = fov; - aspect_ = aspect; - zNear_ = zNear; - zFar_ = zFar; - - projectionMatrix_.release(); - perspectiveProjection_ = true; -} - -void cv::gpu::GlCamera::setOrthoProjection(double left, double right, double bottom, double top, double zNear, double zFar) -{ - left_ = left; - right_ = right; - bottom_ = bottom; - top_ = top; - zNear_ = zNear; - zFar_ = zFar; - - projectionMatrix_.release(); - perspectiveProjection_ = false; -} - -void cv::gpu::GlCamera::setupProjectionMatrix() const -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - if (projectionMatrix_.empty()) - { - if (perspectiveProjection_) - gluPerspective(fov_, aspect_, zNear_, zFar_); - else - glOrtho(left_, right_, bottom_, top_, zNear_, zFar_); - } - else - { - if (projectionMatrix_.type() == CV_32F) - glLoadMatrixf(projectionMatrix_.ptr()); - else - glLoadMatrixd(projectionMatrix_.ptr()); - } - - CV_CheckGlError(); -#endif -} - -void cv::gpu::GlCamera::setupModelViewMatrix() const -{ -#ifndef HAVE_OPENGL - throw_nogl(); -#else - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - if (useLookAtParams_) - gluLookAt(eye_.x, eye_.y, eye_.z, center_.x, center_.y, center_.z, up_.x, up_.y, up_.z); - else - { - glRotated(-yaw_, 0.0, 1.0, 0.0); - glRotated(-pitch_, 1.0, 0.0, 0.0); - glRotated(-roll_, 0.0, 0.0, 1.0); - glTranslated(-pos_.x, -pos_.y, -pos_.z); - } - - glScaled(scale_.x, scale_.y, scale_.z); - - CV_CheckGlError(); -#endif -} - -//////////////////////////////////////////////////////////////////////// -// Error handling - -void cv::gpu::error(const char *error_string, const char *file, const int line, const char *func) -{ - int code = CV_GpuApiCallError; - - if (uncaught_exception()) - { - const char* errorStr = cvErrorStr(code); - const char* function = func ? func : "unknown function"; - - cerr << "OpenCV Error: " << errorStr << "(" << error_string << ") in " << function << ", file " << file << ", line " << line; - cerr.flush(); + cerr << "OpenCV Error: " << errorStr << "(" << error_string << ") in " << function << ", file " << file << ", line " << line; + cerr.flush(); } else cv::error( cv::Exception(code, error_string, func, file, line) ); } - -bool cv::gpu::checkGlError(const char* file, const int line, const char* func) -{ -#ifndef HAVE_OPENGL - return true; -#else - GLenum err = glGetError(); - - if (err != GL_NO_ERROR) - { - const char* msg; - - switch (err) - { - case GL_INVALID_ENUM: - msg = "An unacceptable value is specified for an enumerated argument"; - break; - case GL_INVALID_VALUE: - msg = "A numeric argument is out of range"; - break; - case GL_INVALID_OPERATION: - msg = "The specified operation is not allowed in the current state"; - break; - case GL_STACK_OVERFLOW: - msg = "This command would cause a stack overflow"; - break; - case GL_STACK_UNDERFLOW: - msg = "This command would cause a stack underflow"; - break; - case GL_OUT_OF_MEMORY: - msg = "There is not enough memory left to execute the command"; - break; - default: - msg = "Unknown error"; - }; - - cvError(CV_OpenGlApiCallError, func, msg, file, line); - - return false; - } - - return true; -#endif -} diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 83357af3fd..8188c1bd66 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -41,6 +41,8 @@ //M*/ #include "precomp.hpp" +#include "opencv2/core/gpumat.hpp" +#include "opencv2/core/opengl_interop.hpp" /****************************************************************************************\ * [scaled] Identity matrix initialization * @@ -873,6 +875,9 @@ _InputArray::_InputArray(const Mat& m) : flags(MAT), obj((void*)&m) {} _InputArray::_InputArray(const vector& vec) : flags(STD_VECTOR_MAT), obj((void*)&vec) {} _InputArray::_InputArray(const double& val) : flags(MATX+CV_64F), obj((void*)&val), sz(Size(1,1)) {} _InputArray::_InputArray(const MatExpr& expr) : flags(EXPR), obj((void*)&expr) {} +_InputArray::_InputArray(const GlBuffer& buf) : flags(OPENGL_BUFFER), obj((void*)&buf) {} +_InputArray::_InputArray(const GlTexture& tex) : flags(OPENGL_TEXTURE), obj((void*)&tex) {} +_InputArray::_InputArray(const gpu::GpuMat& d_mat) : flags(GPU_MAT), obj((void*)&d_mat) {} Mat _InputArray::getMat(int i) const { @@ -1011,6 +1016,42 @@ void _InputArray::getMatVector(vector& mv) const return; } } + +GlBuffer _InputArray::getGlBuffer() const +{ + int k = kind(); + + CV_Assert(k == OPENGL_BUFFER); + //if( k == OPENGL_BUFFER ) + { + const GlBuffer* buf = (const GlBuffer*)obj; + return *buf; + } +} + +GlTexture _InputArray::getGlTexture() const +{ + int k = kind(); + + CV_Assert(k == OPENGL_TEXTURE); + //if( k == OPENGL_TEXTURE ) + { + const GlTexture* tex = (const GlTexture*)obj; + return *tex; + } +} + +gpu::GpuMat _InputArray::getGpuMat() const +{ + int k = kind(); + + CV_Assert(k == GPU_MAT); + //if( k == GPU_MAT ) + { + const gpu::GpuMat* d_mat = (const gpu::GpuMat*)obj; + return *d_mat; + } +} int _InputArray::kind() const { @@ -1063,8 +1104,7 @@ Size _InputArray::size(int i) const return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1); } - CV_Assert( k == STD_VECTOR_MAT ); - //if( k == STD_VECTOR_MAT ) + if( k == STD_VECTOR_MAT ) { const vector& vv = *(const vector*)obj; if( i < 0 ) @@ -1073,6 +1113,28 @@ Size _InputArray::size(int i) const return vv[i].size(); } + + if( k == OPENGL_BUFFER ) + { + CV_Assert( i < 0 ); + const GlBuffer* buf = (const GlBuffer*)obj; + return buf->size(); + } + + if( k == OPENGL_TEXTURE ) + { + CV_Assert( i < 0 ); + const GlTexture* tex = (const GlTexture*)obj; + return tex->size(); + } + + CV_Assert( k == GPU_MAT ); + //if( k == GPU_MAT ) + { + CV_Assert( i < 0 ); + const gpu::GpuMat* d_mat = (const gpu::GpuMat*)obj; + return d_mat->size(); + } } size_t _InputArray::total(int i) const @@ -1096,14 +1158,23 @@ int _InputArray::type(int i) const if( k == NONE ) return -1; - CV_Assert( k == STD_VECTOR_MAT ); - //if( k == STD_VECTOR_MAT ) + if( k == STD_VECTOR_MAT ) { const vector& vv = *(const vector*)obj; CV_Assert( i < (int)vv.size() ); return vv[i >= 0 ? i : 0].type(); } + + if( k == OPENGL_BUFFER ) + return ((const GlBuffer*)obj)->type(); + + if( k == OPENGL_TEXTURE ) + return ((const GlTexture*)obj)->type(); + + CV_Assert( k == GPU_MAT ); + //if( k == GPU_MAT ) + return ((const gpu::GpuMat*)obj)->type(); } int _InputArray::depth(int i) const @@ -1144,12 +1215,21 @@ bool _InputArray::empty() const return vv.empty(); } - CV_Assert( k == STD_VECTOR_MAT ); - //if( k == STD_VECTOR_MAT ) + if( k == STD_VECTOR_MAT ) { const vector& vv = *(const vector*)obj; return vv.empty(); } + + if( k == OPENGL_BUFFER ) + return ((const GlBuffer*)obj)->empty(); + + if( k == OPENGL_TEXTURE ) + return ((const GlTexture*)obj)->empty(); + + CV_Assert( k == GPU_MAT ); + //if( k == GPU_MAT ) + return ((const gpu::GpuMat*)obj)->empty(); } diff --git a/modules/core/src/opengl_interop.cpp b/modules/core/src/opengl_interop.cpp new file mode 100644 index 0000000000..e6bbddc8c1 --- /dev/null +++ b/modules/core/src/opengl_interop.cpp @@ -0,0 +1,1519 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "precomp.hpp" +#include +#include "opencv2/core/opengl_interop.hpp" +#include "opencv2/core/gpumat.hpp" + +#ifdef HAVE_OPENGL + #ifdef __APPLE__ + #include + #include + #else + #include + #include + #endif + + #ifdef HAVE_CUDA + #include + #include + #endif +#endif + +using namespace std; +using namespace cv; +using namespace cv::gpu; + +#ifndef HAVE_OPENGL + #define throw_nogl CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support") + #define throw_nocuda CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support") +#else + #define throw_nogl CV_Error(CV_OpenGlNotSupported, "OpenGL context doesn't exist") + + #ifndef HAVE_CUDA + #define throw_nocuda CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support") + #else + #if defined(__GNUC__) + #define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__, __func__) + #else /* defined(__CUDACC__) || defined(__MSVC__) */ + #define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__) + #endif + + namespace + { + inline void ___cudaSafeCall(cudaError_t err, const char *file, const int line, const char *func = "") + { + if (cudaSuccess != err) + cv::gpu::error(cudaGetErrorString(err), file, line, func); + } + } + #endif // HAVE_CUDA +#endif + +namespace +{ + class EmptyGlFuncTab : public CvOpenGlFuncTab + { + public: + void genBuffers(int, unsigned int*) const { throw_nogl; } + void deleteBuffers(int, const unsigned int*) const { throw_nogl; } + + void bufferData(unsigned int, ptrdiff_t, const void*, unsigned int) const { throw_nogl; } + void bufferSubData(unsigned int, ptrdiff_t, ptrdiff_t, const void*) const { throw_nogl; } + + void bindBuffer(unsigned int, unsigned int) const { throw_nogl; } + + void* mapBuffer(unsigned int, unsigned int) const { throw_nogl; return 0; } + void unmapBuffer(unsigned int) const { throw_nogl; } + + void generateBitmapFont(const std::string&, int, int, bool, bool, int, int, int) const { throw_nogl; } + + bool isGlContextInitialized() const { return false; } + }; + + const CvOpenGlFuncTab* g_glFuncTab = 0; + + const CvOpenGlFuncTab* glFuncTab() + { + static EmptyGlFuncTab empty; + return g_glFuncTab ? g_glFuncTab : ∅ + } +} + +CvOpenGlFuncTab::~CvOpenGlFuncTab() +{ + if (g_glFuncTab == this) + g_glFuncTab = 0; +} + +void icvSetOpenGlFuncTab(const CvOpenGlFuncTab* tab) +{ + g_glFuncTab = tab; +} + +#ifdef HAVE_OPENGL + #ifndef GL_DYNAMIC_DRAW + #define GL_DYNAMIC_DRAW 0x88E8 + #endif + + #ifndef GL_READ_WRITE + #define GL_READ_WRITE 0x88BA + #endif + + #ifndef GL_BGR + #define GL_BGR 0x80E0 + #endif + + #ifndef GL_BGRA + #define GL_BGRA 0x80E1 + #endif + + namespace + { + const GLenum gl_types[] = {GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE}; + + #ifdef HAVE_CUDA + bool g_isCudaGlDeviceInitialized = false; + #endif + } +#endif // HAVE_OPENGL + +void cv::gpu::setGlDevice(int device) +{ +#ifndef HAVE_CUDA + throw_nocuda; +#else + #ifndef HAVE_OPENGL + throw_nogl; + #else + if (!glFuncTab()->isGlContextInitialized()) + throw_nogl; + + cudaSafeCall( cudaGLSetGLDevice(device) ); + + g_isCudaGlDeviceInitialized = true; + #endif +#endif +} + +//////////////////////////////////////////////////////////////////////// +// CudaGlInterop + +#if defined HAVE_CUDA && defined HAVE_OPENGL +namespace +{ + class CudaGlInterop + { + public: + CudaGlInterop(); + ~CudaGlInterop(); + + void registerBuffer(unsigned int buffer); + + void copyFrom(const GpuMat& mat, cudaStream_t stream = 0); + + GpuMat map(int rows, int cols, int type, cudaStream_t stream = 0); + void unmap(cudaStream_t stream = 0); + + private: + cudaGraphicsResource_t resource_; + }; + + inline CudaGlInterop::CudaGlInterop() : resource_(0) + { + } + + CudaGlInterop::~CudaGlInterop() + { + if (resource_) + { + cudaGraphicsUnregisterResource(resource_); + resource_ = 0; + } + } + + void CudaGlInterop::registerBuffer(unsigned int buffer) + { + if (!g_isCudaGlDeviceInitialized) + cvError(CV_GpuApiCallError, "registerBuffer", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__); + + cudaGraphicsResource_t resource; + cudaSafeCall( cudaGraphicsGLRegisterBuffer(&resource, buffer, cudaGraphicsMapFlagsNone) ); + + resource_ = resource; + } + + void CudaGlInterop::copyFrom(const GpuMat& mat, cudaStream_t stream) + { + CV_Assert(resource_ != 0); + + cudaSafeCall( cudaGraphicsMapResources(1, &resource_, stream) ); + + void* dst_ptr; + size_t num_bytes; + cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&dst_ptr, &num_bytes, resource_) ); + + const void* src_ptr = mat.ptr(); + size_t widthBytes = mat.cols * mat.elemSize(); + + CV_Assert(widthBytes * mat.rows <= num_bytes); + + if (stream == 0) + cudaSafeCall( cudaMemcpy2D(dst_ptr, widthBytes, src_ptr, mat.step, widthBytes, mat.rows, cudaMemcpyDeviceToDevice) ); + else + cudaSafeCall( cudaMemcpy2DAsync(dst_ptr, widthBytes, src_ptr, mat.step, widthBytes, mat.rows, cudaMemcpyDeviceToDevice, stream) ); + + cudaGraphicsUnmapResources(1, &resource_, stream); + } + + GpuMat CudaGlInterop::map(int rows, int cols, int type, cudaStream_t stream) + { + CV_Assert(resource_ != 0); + + cudaSafeCall( cudaGraphicsMapResources(1, &resource_, stream) ); + + void* ptr; + size_t num_bytes; + cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&ptr, &num_bytes, resource_) ); + + CV_Assert( static_cast(cols) * CV_ELEM_SIZE(type) * rows <= num_bytes ); + + return GpuMat(rows, cols, type, ptr); + } + + inline void CudaGlInterop::unmap(cudaStream_t stream) + { + cudaGraphicsUnmapResources(1, &resource_, stream); + } +} +#endif // HAVE_CUDA && HAVE_OPENGL + +//////////////////////////////////////////////////////////////////////// +// GlBuffer + +#ifndef HAVE_OPENGL + +class cv::GlBuffer::Impl +{ +}; + +#else + +class cv::GlBuffer::Impl +{ +public: + Impl(); + Impl(int rows, int cols, int type, unsigned int target); + Impl(const Mat& m, unsigned int target); + ~Impl(); + + void copyFrom(const Mat& m, unsigned int target); + +#ifdef HAVE_CUDA + void copyFrom(const GpuMat& mat, cudaStream_t stream = 0); +#endif + + void bind(unsigned int target) const; + void unbind(unsigned int target) const; + + Mat mapHost(int rows, int cols, int type, unsigned int target); + void unmapHost(unsigned int target); + +#ifdef HAVE_CUDA + GpuMat mapDevice(int rows, int cols, int type, cudaStream_t stream = 0); + void unmapDevice(cudaStream_t stream = 0); +#endif + +private: + unsigned int buffer_; + +#ifdef HAVE_CUDA + CudaGlInterop cudaGlInterop_; +#endif +}; + +inline cv::GlBuffer::Impl::Impl() : buffer_(0) +{ +} + +cv::GlBuffer::Impl::Impl(int rows, int cols, int type, unsigned int target) : buffer_(0) +{ + if (!glFuncTab()->isGlContextInitialized()) + throw_nogl; + + CV_DbgAssert(rows > 0 && cols > 0); + CV_DbgAssert(CV_MAT_DEPTH(type) >= 0 && CV_MAT_DEPTH(type) <= CV_64F); + + glFuncTab()->genBuffers(1, &buffer_); + CV_CheckGlError(); + CV_Assert(buffer_ != 0); + + size_t size = rows * cols * CV_ELEM_SIZE(type); + + glFuncTab()->bindBuffer(target, buffer_); + CV_CheckGlError(); + + glFuncTab()->bufferData(target, size, 0, GL_DYNAMIC_DRAW); + CV_CheckGlError(); + + glFuncTab()->bindBuffer(target, 0); + +#ifdef HAVE_CUDA + if (g_isCudaGlDeviceInitialized) + cudaGlInterop_.registerBuffer(buffer_); +#endif +} + +cv::GlBuffer::Impl::Impl(const Mat& m, unsigned int target) : buffer_(0) +{ + if (!glFuncTab()->isGlContextInitialized()) + throw_nogl; + + CV_DbgAssert(m.rows > 0 && m.cols > 0); + CV_DbgAssert(m.depth() >= 0 && m.depth() <= CV_64F); + CV_Assert(m.isContinuous()); + + glFuncTab()->genBuffers(1, &buffer_); + CV_CheckGlError(); + CV_Assert(buffer_ != 0); + + size_t size = m.rows * m.cols * m.elemSize(); + + glFuncTab()->bindBuffer(target, buffer_); + CV_CheckGlError(); + + glFuncTab()->bufferData(target, size, m.data, GL_DYNAMIC_DRAW); + CV_CheckGlError(); + + glFuncTab()->bindBuffer(target, 0); + +#ifdef HAVE_CUDA + if (g_isCudaGlDeviceInitialized) + cudaGlInterop_.registerBuffer(buffer_); +#endif +} + +cv::GlBuffer::Impl::~Impl() +{ + try + { + if (buffer_) + glFuncTab()->deleteBuffers(1, &buffer_); + } +#ifdef _DEBUG + catch(const exception& e) + { + cerr << e.what() << endl; + } +#endif + catch(...) + { + } +} + +void cv::GlBuffer::Impl::copyFrom(const Mat& m, unsigned int target) +{ + CV_Assert(buffer_ != 0); + + CV_Assert(m.isContinuous()); + + bind(target); + + size_t size = m.rows * m.cols * m.elemSize(); + + glFuncTab()->bufferSubData(target, 0, size, m.data); + CV_CheckGlError(); + + unbind(target); +} + +#ifdef HAVE_CUDA + +void cv::GlBuffer::Impl::copyFrom(const GpuMat& mat, cudaStream_t stream) +{ + if (!g_isCudaGlDeviceInitialized) + cvError(CV_GpuApiCallError, "copyFrom", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__); + + CV_Assert(buffer_ != 0); + + cudaGlInterop_.copyFrom(mat, stream); +} + +#endif // HAVE_CUDA + +inline void cv::GlBuffer::Impl::bind(unsigned int target) const +{ + CV_Assert(buffer_ != 0); + + glFuncTab()->bindBuffer(target, buffer_); + CV_CheckGlError(); +} + +inline void cv::GlBuffer::Impl::unbind(unsigned int target) const +{ + glFuncTab()->bindBuffer(target, 0); +} + +inline Mat cv::GlBuffer::Impl::mapHost(int rows, int cols, int type, unsigned int target) +{ + void* ptr = glFuncTab()->mapBuffer(target, GL_READ_WRITE); + CV_CheckGlError(); + + return Mat(rows, cols, type, ptr); +} + +inline void cv::GlBuffer::Impl::unmapHost(unsigned int target) +{ + glFuncTab()->unmapBuffer(target); +} + +#ifdef HAVE_CUDA + +inline GpuMat cv::GlBuffer::Impl::mapDevice(int rows, int cols, int type, cudaStream_t stream) +{ + if (!g_isCudaGlDeviceInitialized) + cvError(CV_GpuApiCallError, "copyFrom", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__); + + CV_Assert(buffer_ != 0); + + return cudaGlInterop_.map(rows, cols, type, stream); +} + +inline void cv::GlBuffer::Impl::unmapDevice(cudaStream_t stream) +{ + if (!g_isCudaGlDeviceInitialized) + cvError(CV_GpuApiCallError, "copyFrom", "cuda GL device wasn't initialized, call setGlDevice", __FILE__, __LINE__); + + cudaGlInterop_.unmap(stream); +} + +#endif // HAVE_CUDA + +#endif // HAVE_OPENGL + +cv::GlBuffer::GlBuffer(Usage usage) : rows(0), cols(0), type_(0), usage_(usage) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_ = new Impl; +#endif +} + +cv::GlBuffer::GlBuffer(int rows_, int cols_, int type, Usage usage) : rows(0), cols(0), type_(0), usage_(usage) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_ = new Impl(rows_, cols_, type, usage); + rows = rows_; + cols = cols_; + type_ = type; +#endif +} + +cv::GlBuffer::GlBuffer(Size size, int type, Usage usage) : rows(0), cols(0), type_(0), usage_(usage) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_ = new Impl(size.height, size.width, type, usage); + rows = size.height; + cols = size.width; + type_ = type; +#endif +} + +cv::GlBuffer::GlBuffer(InputArray mat_, Usage usage) : rows(0), cols(0), type_(0), usage_(usage) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + int kind = mat_.kind(); + Size size = mat_.size(); + int type = mat_.type(); + + if (kind == _InputArray::GPU_MAT) + { + #ifndef HAVE_CUDA + throw_nocuda; + #else + GpuMat d_mat = mat_.getGpuMat(); + impl_ = new Impl(d_mat.rows, d_mat.cols, d_mat.type(), usage); + impl_->copyFrom(d_mat); + #endif + } + else + { + Mat mat = mat_.getMat(); + impl_ = new Impl(mat, usage); + } + + rows = size.height; + cols = size.width; + type_ = type; +#endif +} + +void cv::GlBuffer::create(int rows_, int cols_, int type, Usage usage) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + if (rows_ != rows || cols_ != cols || type_ != type || usage_ != usage) + { + impl_ = new Impl(rows_, cols_, type, usage); + rows = rows_; + cols = cols_; + type_ = type; + usage_ = usage; + } +#endif +} + +void cv::GlBuffer::release() +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_ = new Impl; +#endif +} + +void cv::GlBuffer::copyFrom(InputArray mat_) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + int kind = mat_.kind(); + Size size = mat_.size(); + int type = mat_.type(); + + create(size, type); + + switch (kind) + { + case _InputArray::OPENGL_BUFFER: + { + GlBuffer buf = mat_.getGlBuffer(); + *this = buf; + break; + } + case _InputArray::GPU_MAT: + { + #ifndef HAVE_CUDA + throw_nocuda; + #else + GpuMat d_mat = mat_.getGpuMat(); + impl_->copyFrom(d_mat); + #endif + + break; + } + default: + { + Mat mat = mat_.getMat(); + impl_->copyFrom(mat, usage_); + } + } +#endif +} + +void cv::GlBuffer::bind() const +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_->bind(usage_); +#endif +} + +void cv::GlBuffer::unbind() const +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_->unbind(usage_); +#endif +} + +Mat cv::GlBuffer::mapHost() +{ +#ifndef HAVE_OPENGL + throw_nogl; + return Mat(); +#else + return impl_->mapHost(rows, cols, type_, usage_); +#endif +} + +void cv::GlBuffer::unmapHost() +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_->unmapHost(usage_); +#endif +} + +GpuMat cv::GlBuffer::mapDevice() +{ +#ifndef HAVE_OPENGL + throw_nogl; + return GpuMat(); +#else + #ifndef HAVE_CUDA + throw_nocuda; + return GpuMat(); + #else + return impl_->mapDevice(rows, cols, type_); + #endif +#endif +} + +void cv::GlBuffer::unmapDevice() +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + #ifndef HAVE_CUDA + throw_nocuda; + #else + impl_->unmapDevice(); + #endif +#endif +} + +template <> void cv::Ptr::delete_obj() +{ + if (obj) delete obj; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// GlTexture + +#ifndef HAVE_OPENGL + +class cv::GlTexture::Impl +{ +}; + +#else + +class cv::GlTexture::Impl +{ +public: + Impl(); + + Impl(int rows, int cols, int type); + + Impl(const Mat& mat, bool bgra); + Impl(const GlBuffer& buf, bool bgra); + + ~Impl(); + + void copyFrom(const Mat& mat, bool bgra); + void copyFrom(const GlBuffer& buf, bool bgra); + + void bind() const; + void unbind() const; + +private: + GLuint tex_; +}; + +inline cv::GlTexture::Impl::Impl() : tex_(0) +{ +} + +cv::GlTexture::Impl::Impl(int rows, int cols, int type) : tex_(0) +{ + if (!glFuncTab()->isGlContextInitialized()) + throw_nogl; + + int depth = CV_MAT_DEPTH(type); + int cn = CV_MAT_CN(type); + + CV_DbgAssert(rows > 0 && cols > 0); + CV_Assert(cn == 1 || cn == 3 || cn == 4); + CV_Assert(depth >= 0 && depth <= CV_32F); + + glGenTextures(1, &tex_); + CV_CheckGlError(); + CV_Assert(tex_ != 0); + + glBindTexture(GL_TEXTURE_2D, tex_); + CV_CheckGlError(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + CV_CheckGlError(); + + GLenum format = cn == 1 ? GL_LUMINANCE : cn == 3 ? GL_BGR : GL_BGRA; + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + CV_CheckGlError(); + + glTexImage2D(GL_TEXTURE_2D, 0, cn, cols, rows, 0, format, gl_types[depth], 0); + CV_CheckGlError(); +} + +cv::GlTexture::Impl::Impl(const Mat& mat, bool bgra) : tex_(0) +{ + if (!glFuncTab()->isGlContextInitialized()) + throw_nogl; + + int depth = mat.depth(); + int cn = mat.channels(); + + CV_DbgAssert(mat.rows > 0 && mat.cols > 0); + CV_Assert(cn == 1 || cn == 3 || cn == 4); + CV_Assert(depth >= 0 && depth <= CV_32F); + CV_Assert(mat.isContinuous()); + + glGenTextures(1, &tex_); + CV_CheckGlError(); + CV_Assert(tex_ != 0); + + glBindTexture(GL_TEXTURE_2D, tex_); + CV_CheckGlError(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + CV_CheckGlError(); + + GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA)); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + CV_CheckGlError(); + + glTexImage2D(GL_TEXTURE_2D, 0, cn, mat.cols, mat.rows, 0, format, gl_types[depth], mat.data); + CV_CheckGlError(); +} + +cv::GlTexture::Impl::Impl(const GlBuffer& buf, bool bgra) : tex_(0) +{ + if (!glFuncTab()->isGlContextInitialized()) + throw_nogl; + + int depth = buf.depth(); + int cn = buf.channels(); + + CV_DbgAssert(buf.rows > 0 && buf.cols > 0); + CV_Assert(cn == 1 || cn == 3 || cn == 4); + CV_Assert(depth >= 0 && depth <= CV_32F); + CV_Assert(buf.usage() == GlBuffer::TEXTURE_BUFFER); + + glGenTextures(1, &tex_); + CV_CheckGlError(); + CV_Assert(tex_ != 0); + + glBindTexture(GL_TEXTURE_2D, tex_); + CV_CheckGlError(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + CV_CheckGlError(); + + GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA)); + + buf.bind(); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + CV_CheckGlError(); + + glTexImage2D(GL_TEXTURE_2D, 0, cn, buf.cols, buf.rows, 0, format, gl_types[depth], 0); + CV_CheckGlError(); + + buf.unbind(); +} + +inline cv::GlTexture::Impl::~Impl() +{ + if (tex_) + glDeleteTextures(1, &tex_); +} + +void cv::GlTexture::Impl::copyFrom(const Mat& mat, bool bgra) +{ + CV_Assert(tex_ != 0); + + bind(); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + CV_CheckGlError(); + + int cn = mat.channels(); + GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA)); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mat.cols, mat.rows, format, gl_types[mat.depth()], mat.data); + CV_CheckGlError(); + + unbind(); +} + +void cv::GlTexture::Impl::copyFrom(const GlBuffer& buf, bool bgra) +{ + CV_Assert(tex_ != 0); + CV_Assert(buf.usage() == GlBuffer::TEXTURE_BUFFER); + + bind(); + + buf.bind(); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + CV_CheckGlError(); + + int cn = buf.channels(); + GLenum format = cn == 1 ? GL_LUMINANCE : (cn == 3 ? (bgra ? GL_BGR : GL_RGB) : (bgra ? GL_BGRA : GL_RGBA)); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, buf.cols, buf.rows, format, gl_types[buf.depth()], 0); + CV_CheckGlError(); + + buf.unbind(); + + unbind(); +} + +inline void cv::GlTexture::Impl::bind() const +{ + CV_Assert(tex_ != 0); + + glEnable(GL_TEXTURE_2D); + CV_CheckGlError(); + + glBindTexture(GL_TEXTURE_2D, tex_); + CV_CheckGlError(); +} + +inline void cv::GlTexture::Impl::unbind() const +{ + glBindTexture(GL_TEXTURE_2D, 0); + + glDisable(GL_TEXTURE_2D); +} + +#endif // HAVE_OPENGL + +cv::GlTexture::GlTexture() : rows(0), cols(0), type_(0) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_ = new Impl; +#endif +} + +cv::GlTexture::GlTexture(int rows_, int cols_, int type) : rows(0), cols(0), type_(0) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_ = new Impl(rows_, cols_, type); + rows = rows_; + cols = cols_; + type_ = type; +#endif +} + +cv::GlTexture::GlTexture(Size size, int type) : rows(0), cols(0), type_(0) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_ = new Impl(size.height, size.width, type); + rows = size.height; + cols = size.width; + type_ = type; +#endif +} + +cv::GlTexture::GlTexture(InputArray mat_, bool bgra) : rows(0), cols(0), type_(0) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + int kind = mat_.kind(); + Size size = mat_.size(); + int type = mat_.type(); + + switch (kind) + { + case _InputArray::OPENGL_BUFFER: + { + GlBuffer buf = mat_.getGlBuffer(); + impl_ = new Impl(buf, bgra); + break; + } + case _InputArray::GPU_MAT: + { + #ifndef HAVE_CUDA + throw_nocuda; + #else + GpuMat d_mat = mat_.getGpuMat(); + GlBuffer buf(d_mat, GlBuffer::TEXTURE_BUFFER); + impl_ = new Impl(buf, bgra); + #endif + + break; + } + default: + { + Mat mat = mat_.getMat(); + impl_ = new Impl(mat, bgra); + break; + } + } + + rows = size.height; + cols = size.width; + type_ = type; +#endif +} + +void cv::GlTexture::create(int rows_, int cols_, int type) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + if (rows_ != rows || cols_ != cols || type_ != type) + { + impl_ = new Impl(rows_, cols_, type); + rows = rows_; + cols = cols_; + type_ = type; + } +#endif +} + +void cv::GlTexture::release() +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_ = new Impl; +#endif +} + +void cv::GlTexture::copyFrom(InputArray mat_, bool bgra) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + int kind = mat_.kind(); + Size size = mat_.size(); + int type = mat_.type(); + + create(size, type); + + switch(kind) + { + case _InputArray::OPENGL_TEXTURE: + { + GlTexture tex = mat_.getGlTexture(); + *this = tex; + break; + } + case _InputArray::OPENGL_BUFFER: + { + GlBuffer buf = mat_.getGlBuffer(); + impl_->copyFrom(buf, bgra); + break; + } + case _InputArray::GPU_MAT: + { + #ifndef HAVE_CUDA + throw_nocuda; + #else + GpuMat d_mat = mat_.getGpuMat(); + GlBuffer buf(d_mat, GlBuffer::TEXTURE_BUFFER); + impl_->copyFrom(buf, bgra); + #endif + + break; + } + default: + { + Mat mat = mat_.getMat(); + impl_->copyFrom(mat, bgra); + } + } +#endif +} + +void cv::GlTexture::bind() const +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_->bind(); +#endif +} + +void cv::GlTexture::unbind() const +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + impl_->unbind(); +#endif +} + +template <> void cv::Ptr::delete_obj() +{ + if (obj) delete obj; +} + +//////////////////////////////////////////////////////////////////////// +// GlArrays + +void cv::GlArrays::setVertexArray(InputArray vertex) +{ + int cn = vertex.channels(); + int depth = vertex.depth(); + + CV_Assert(cn == 2 || cn == 3 || cn == 4); + CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); + + vertex_.copyFrom(vertex); +} + +void cv::GlArrays::setColorArray(InputArray color, bool bgra) +{ + int cn = color.channels(); + + CV_Assert((cn == 3 && !bgra) || cn == 4); + + color_.copyFrom(color); + bgra_ = bgra; +} + +void cv::GlArrays::setNormalArray(InputArray normal) +{ + int cn = normal.channels(); + int depth = normal.depth(); + + CV_Assert(cn == 3); + CV_Assert(depth == CV_8S || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); + + normal_.copyFrom(normal); +} + +void cv::GlArrays::setTexCoordArray(InputArray texCoord) +{ + int cn = texCoord.channels(); + int depth = texCoord.depth(); + + CV_Assert(cn >= 1 && cn <= 4); + CV_Assert(depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F); + + texCoord_.copyFrom(texCoord); +} + +void cv::GlArrays::bind() const +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + CV_DbgAssert(texCoord_.empty() || texCoord_.size().area() == vertex_.size().area()); + CV_DbgAssert(normal_.empty() || normal_.size().area() == vertex_.size().area()); + CV_DbgAssert(color_.empty() || color_.size().area() == vertex_.size().area()); + + if (!texCoord_.empty()) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + CV_CheckGlError(); + + texCoord_.bind(); + + glTexCoordPointer(texCoord_.channels(), gl_types[texCoord_.depth()], 0, 0); + CV_CheckGlError(); + + texCoord_.unbind(); + } + + if (!normal_.empty()) + { + glEnableClientState(GL_NORMAL_ARRAY); + CV_CheckGlError(); + + normal_.bind(); + + glNormalPointer(gl_types[normal_.depth()], 0, 0); + CV_CheckGlError(); + + normal_.unbind(); + } + + if (!color_.empty()) + { + glEnableClientState(GL_COLOR_ARRAY); + CV_CheckGlError(); + + color_.bind(); + + int cn = color_.channels(); + int format = cn == 3 ? cn : (bgra_ ? GL_BGRA : 4); + + glColorPointer(format, gl_types[color_.depth()], 0, 0); + CV_CheckGlError(); + + color_.unbind(); + } + + if (!vertex_.empty()) + { + glEnableClientState(GL_VERTEX_ARRAY); + CV_CheckGlError(); + + vertex_.bind(); + + glVertexPointer(vertex_.channels(), gl_types[vertex_.depth()], 0, 0); + CV_CheckGlError(); + + vertex_.unbind(); + } +#endif +} + +void cv::GlArrays::unbind() const +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + if (!texCoord_.empty()) + { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + CV_CheckGlError(); + } + + if (!normal_.empty()) + { + glDisableClientState(GL_NORMAL_ARRAY); + CV_CheckGlError(); + } + + if (!color_.empty()) + { + glDisableClientState(GL_COLOR_ARRAY); + CV_CheckGlError(); + } + + if (!vertex_.empty()) + { + glDisableClientState(GL_VERTEX_ARRAY); + CV_CheckGlError(); + } +#endif +} + +//////////////////////////////////////////////////////////////////////// +// GlFont + +cv::GlFont::GlFont(const string& family, int height, Weight weight, Style style) + : family_(family), height_(height), weight_(weight), style_(style), base_(0) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + base_ = glGenLists(256); + CV_CheckGlError(); + + glFuncTab()->generateBitmapFont(family, height, weight, style & STYLE_ITALIC, style & STYLE_UNDERLINE, 0, 256, base_); +#endif +} + +void cv::GlFont::draw(const char* str, int len) const +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + if (base_ && len > 0) + { + glPushAttrib(GL_LIST_BIT); + glListBase(base_); + + glCallLists(len, GL_UNSIGNED_BYTE, str); + + glPopAttrib(); + + CV_CheckGlError(); + } +#endif +} + +namespace +{ + class FontCompare : public unary_function, bool> + { + public: + inline FontCompare(const string& family, int height, GlFont::Weight weight, GlFont::Style style) + : family_(family), height_(height), weight_(weight), style_(style) + { + } + + bool operator ()(const cv::Ptr& font) + { + return font->family() == family_ && font->height() == height_ && font->weight() == weight_ && font->style() == style_; + } + + private: + string family_; + int height_; + GlFont::Weight weight_; + GlFont::Style style_; + }; +} + +Ptr cv::GlFont::get(const std::string& family, int height, Weight weight, Style style) +{ +#ifndef HAVE_OPENGL + throw_nogl; + return Ptr(); +#else + static vector< Ptr > fonts; + fonts.reserve(10); + + vector< Ptr >::iterator fontIt = find_if(fonts.begin(), fonts.end(), FontCompare(family, height, weight, style)); + + if (fontIt == fonts.end()) + { + fonts.push_back(new GlFont(family, height, weight, style)); + + fontIt = fonts.end() - 1; + } + + return *fontIt; +#endif +} + +//////////////////////////////////////////////////////////////////////// +// Rendering + +void cv::render(const GlTexture& tex, Rect_ wndRect, Rect_ texRect) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + if (!tex.empty()) + { + tex.bind(); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glBegin(GL_QUADS); + glTexCoord2d(texRect.x, texRect.y); + glVertex2d(wndRect.x, wndRect.y); + + glTexCoord2d(texRect.x, texRect.y + texRect.height); + glVertex2d(wndRect.x, (wndRect.y + wndRect.height)); + + glTexCoord2d(texRect.x + texRect.width, texRect.y + texRect.height); + glVertex2d(wndRect.x + wndRect.width, (wndRect.y + wndRect.height)); + + glTexCoord2d(texRect.x + texRect.width, texRect.y); + glVertex2d(wndRect.x + wndRect.width, wndRect.y); + glEnd(); + + CV_CheckGlError(); + + tex.unbind(); + } +#endif +} + +void cv::render(const GlArrays& arr, int mode) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + arr.bind(); + + glDrawArrays(mode, 0, arr.size().area()); + + arr.unbind(); +#endif +} + +void cv::render(const string& str, const Ptr& font, Scalar color, Point2d pos) +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + glPushAttrib(GL_DEPTH_BUFFER_BIT); + + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + + glDisable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glRasterPos2d(2.0 * (viewport[0] + pos.x) / viewport[2] - 1.0, 1.0 - 2.0 * (viewport[1] + pos.y + font->height()) / viewport[3]); + + glColor4dv(color.val); + font->draw(str.c_str(), str.length()); + + glPopAttrib(); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// GlCamera + +cv::GlCamera::GlCamera() : + eye_(0.0, 0.0, -5.0), center_(0.0, 0.0, 0.0), up_(0.0, 1.0, 0.0), + pos_(0.0, 0.0, -5.0), yaw_(0.0), pitch_(0.0), roll_(0.0), + useLookAtParams_(false), + + scale_(1.0, 1.0, 1.0), + + projectionMatrix_(), + fov_(45.0), aspect_(0.0), + left_(0.0), right_(1.0), bottom_(1.0), top_(0.0), + zNear_(-1.0), zFar_(1.0), + perspectiveProjection_(false) +{ +} + +void cv::GlCamera::lookAt(Point3d eye, Point3d center, Point3d up) +{ + eye_ = eye; + center_ = center; + up_ = up; + useLookAtParams_ = true; +} + +void cv::GlCamera::setCameraPos(Point3d pos, double yaw, double pitch, double roll) +{ + pos_ = pos; + yaw_ = yaw; + pitch_ = pitch; + roll_ = roll; + useLookAtParams_ = false; +} + +void cv::GlCamera::setScale(Point3d scale) +{ + scale_ = scale; +} + +void cv::GlCamera::setProjectionMatrix(const Mat& projectionMatrix, bool transpose) +{ + CV_Assert(projectionMatrix.type() == CV_32F || projectionMatrix.type() == CV_64F); + CV_Assert(projectionMatrix.cols == 4 && projectionMatrix.rows == 4); + + projectionMatrix_ = transpose ? projectionMatrix.t() : projectionMatrix; +} + +void cv::GlCamera::setPerspectiveProjection(double fov, double aspect, double zNear, double zFar) +{ + fov_ = fov; + aspect_ = aspect; + zNear_ = zNear; + zFar_ = zFar; + + projectionMatrix_.release(); + perspectiveProjection_ = true; +} + +void cv::GlCamera::setOrthoProjection(double left, double right, double bottom, double top, double zNear, double zFar) +{ + left_ = left; + right_ = right; + bottom_ = bottom; + top_ = top; + zNear_ = zNear; + zFar_ = zFar; + + projectionMatrix_.release(); + perspectiveProjection_ = false; +} + +void cv::GlCamera::setupProjectionMatrix() const +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + if (projectionMatrix_.empty()) + { + if (perspectiveProjection_) + gluPerspective(fov_, aspect_, zNear_, zFar_); + else + glOrtho(left_, right_, bottom_, top_, zNear_, zFar_); + } + else + { + if (projectionMatrix_.type() == CV_32F) + glLoadMatrixf(projectionMatrix_.ptr()); + else + glLoadMatrixd(projectionMatrix_.ptr()); + } + + CV_CheckGlError(); +#endif +} + +void cv::GlCamera::setupModelViewMatrix() const +{ +#ifndef HAVE_OPENGL + throw_nogl; +#else + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (useLookAtParams_) + gluLookAt(eye_.x, eye_.y, eye_.z, center_.x, center_.y, center_.z, up_.x, up_.y, up_.z); + else + { + glRotated(-yaw_, 0.0, 1.0, 0.0); + glRotated(-pitch_, 1.0, 0.0, 0.0); + glRotated(-roll_, 0.0, 0.0, 1.0); + glTranslated(-pos_.x, -pos_.y, -pos_.z); + } + + glScaled(scale_.x, scale_.y, scale_.z); + + CV_CheckGlError(); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// Error handling + +bool icvCheckGlError(const char* file, const int line, const char* func) +{ +#ifndef HAVE_OPENGL + return true; +#else + GLenum err = glGetError(); + + if (err != GL_NO_ERROR) + { + const char* msg; + + switch (err) + { + case GL_INVALID_ENUM: + msg = "An unacceptable value is specified for an enumerated argument"; + break; + case GL_INVALID_VALUE: + msg = "A numeric argument is out of range"; + break; + case GL_INVALID_OPERATION: + msg = "The specified operation is not allowed in the current state"; + break; + case GL_STACK_OVERFLOW: + msg = "This command would cause a stack overflow"; + break; + case GL_STACK_UNDERFLOW: + msg = "This command would cause a stack underflow"; + break; + case GL_OUT_OF_MEMORY: + msg = "There is not enough memory left to execute the command"; + break; + default: + msg = "Unknown error"; + }; + + cvError(CV_OpenGlApiCallError, func, msg, file, line); + + return false; + } + + return true; +#endif +} diff --git a/modules/highgui/include/opencv2/highgui/highgui.hpp b/modules/highgui/include/opencv2/highgui/highgui.hpp index a770f86fe1..9e3d4d4bc4 100644 --- a/modules/highgui/include/opencv2/highgui/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui/highgui.hpp @@ -44,7 +44,6 @@ #define __OPENCV_HIGHGUI_HPP__ #include "opencv2/core/core.hpp" -#include "opencv2/core/gpumat.hpp" #include "opencv2/highgui/highgui_c.h" #ifdef __cplusplus @@ -129,7 +128,7 @@ CV_EXPORTS_W void setTrackbarPos(const string& trackbarname, const string& winna typedef void (CV_CDECL *OpenGLCallback)(void* userdata); CV_EXPORTS void createOpenGLCallback(const string& winname, OpenGLCallback onOpenGlDraw, void* userdata = 0); -typedef void (CV_CDECL *OpenGlDrawCallback)(void* userdata); +typedef void (*OpenGlDrawCallback)(void* userdata); static inline void setOpenGlDrawCallback(const string& winname, OpenGlDrawCallback onOpenGlDraw, void* userdata = 0) { createOpenGLCallback(winname, onOpenGlDraw, userdata); @@ -139,22 +138,8 @@ CV_EXPORTS void setOpenGlContext(const string& winname); CV_EXPORTS void updateWindow(const string& winname); -CV_EXPORTS void imshow(const string& winname, const gpu::GlTexture& tex); -CV_EXPORTS void imshow(const string& winname, const gpu::GlBuffer& buf); -CV_EXPORTS void imshow(const string& winname, const gpu::GpuMat& d_mat); - -CV_EXPORTS void pointCloudShow(const string& winname, const gpu::GlCamera& camera, const gpu::GlArrays& arr); -CV_EXPORTS void pointCloudShow(const string& winname, const gpu::GlCamera& camera, const gpu::GlBuffer& points, - const gpu::GlBuffer& colors = gpu::GlBuffer(gpu::GlBuffer::ARRAY_BUFFER)); -CV_EXPORTS void pointCloudShow(const string& winname, const gpu::GlCamera& camera, const gpu::GpuMat& points, - const gpu::GpuMat& colors = gpu::GpuMat()); -CV_EXPORTS void pointCloudShow(const string& winname, const gpu::GlCamera& camera, InputArray points, - InputArray colors = noArray()); - -CV_EXPORTS void addTextOpenGl(const string& winname, const string& text, Point org, Scalar color = Scalar::all(255), - const string& fontName = "Courier New", int fontHeight = 12, - int fontWeight = CV_FONT_NORMAL, int fontStyle = CV_STYLE_NORMAL); -CV_EXPORTS void clearTextOpenGl(const string& winname); +CV_EXPORTS void pointCloudShow(const string& winname, const GlCamera& camera, const GlArrays& arr); +CV_EXPORTS void pointCloudShow(const string& winname, const GlCamera& camera, InputArray points, InputArray colors = noArray()); //Only for Qt diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 6f6cc0dc5f..4513c07303 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -63,8 +63,7 @@ enum { CV_FONT_LIGHT = 25,//QFont::Light, enum { CV_STYLE_NORMAL = 0,//QFont::StyleNormal, CV_STYLE_ITALIC = 1,//QFont::StyleItalic, - CV_STYLE_OBLIQUE = 2,//QFont::StyleOblique - CV_STYLE_UNDERLINE = 4 + CV_STYLE_OBLIQUE = 2 //QFont::StyleOblique }; /* ---------*/ @@ -258,11 +257,6 @@ CVAPI(void) cvCreateOpenGLCallback( const char* window_name, CvOpenGLCallback ca CVAPI(void) cvSetOpenGlContext(const char* window_name); CVAPI(void) cvUpdateWindow(const char* window_name); -CVAPI(void) cvAddTextOpenGl(const char* winname, const char* text, CvPoint org, CvScalar color CV_DEFAULT(cvScalar(255.0, 255.0, 255.0, 255.0)), - const char* fontName CV_DEFAULT("Courier New"), int fontHeight CV_DEFAULT(12), - int fontWeight CV_DEFAULT(CV_FONT_NORMAL), int fontStyle CV_DEFAULT(CV_STYLE_NORMAL)); - -CVAPI(void) cvClearTextOpenGl(const char* winname); /****************************************************************************************\ * Working with Video Files and Cameras * diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 2ee6d3f969..7e49c37f1e 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -40,6 +40,7 @@ //M*/ #include "precomp.hpp" +#include "opencv2/core/opengl_interop.hpp" // in later times, use this file as a dispatcher to implementations like cvcap.cpp @@ -284,7 +285,7 @@ namespace struct GlObjTex : GlObjBase { - cv::gpu::GlTexture tex; + cv::GlTexture tex; }; void CV_CDECL glDrawTextureCallback(void* userdata) @@ -293,17 +294,17 @@ namespace CV_DbgAssert(texObj->flag == CV_TEXTURE_MAGIC_VAL); - static cv::gpu::GlCamera glCamera; + static cv::GlCamera glCamera; glCamera.setupProjectionMatrix(); - cv::gpu::render(texObj->tex); + cv::render(texObj->tex); } struct GlObjPointCloud : GlObjBase { - cv::gpu::GlArrays arr; - cv::gpu::GlCamera camera; + cv::GlArrays arr; + cv::GlCamera camera; }; void CV_CDECL glDrawPointCloudCallback(void* userdata) @@ -315,7 +316,7 @@ namespace pointCloudObj->camera.setupProjectionMatrix(); pointCloudObj->camera.setupModelViewMatrix(); - cv::gpu::render(pointCloudObj->arr); + cv::render(pointCloudObj->arr); } void CV_CDECL glCleanCallback(void* userdata) @@ -327,20 +328,31 @@ namespace } #endif // HAVE_OPENGL -#ifdef HAVE_OPENGL - -namespace +void cv::imshow( const string& winname, InputArray _img ) { - template void imshowImpl(const std::string& winname, const T& img) +#ifndef HAVE_OPENGL + Mat img = _img.getMat(); + CvMat c_img = img; + cvShowImage(winname.c_str(), &c_img); +#else + double useGl = getWindowProperty(winname, WND_PROP_OPENGL); + if (useGl <= 0) + { + Mat img = _img.getMat(); + CvMat c_img = img; + cvShowImage(winname.c_str(), &c_img); + } + else { - using namespace cv; - namedWindow(winname, WINDOW_OPENGL | WINDOW_AUTOSIZE); double autoSize = getWindowProperty(winname, WND_PROP_AUTOSIZE); if (autoSize > 0) - resizeWindow(winname, img.cols, img.rows); + { + Size size = _img.size(); + resizeWindow(winname, size.width, size.height); + } setOpenGlContext(winname); @@ -355,12 +367,12 @@ namespace if (glObj) { GlObjTex* texObj = static_cast(glObj); - texObj->tex.copyFrom(img); + texObj->tex.copyFrom(_img); } else { GlObjTex* texObj = new GlObjTex; - texObj->tex.copyFrom(img); + texObj->tex.copyFrom(_img); glObj = texObj; glObj->flag = CV_TEXTURE_MAGIC_VAL; @@ -375,68 +387,21 @@ namespace updateWindow(winname); } -} - -#endif // HAVE_OPENGL - -void cv::imshow( const string& winname, InputArray _img ) -{ - Mat img = _img.getMat(); - -#ifndef HAVE_OPENGL - CvMat c_img = img; - cvShowImage(winname.c_str(), &c_img); -#else - double useGl = getWindowProperty(winname, WND_PROP_OPENGL); - if (useGl <= 0) - { - CvMat c_img = img; - cvShowImage(winname.c_str(), &c_img); - } - else - { - imshowImpl(winname, img); - } -#endif -} - -void cv::imshow(const string& winname, const gpu::GlBuffer& buf) -{ -#ifndef HAVE_OPENGL - CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); -#else - imshowImpl(winname, buf); #endif } -void cv::imshow(const string& winname, const gpu::GpuMat& d_mat) +void cv::pointCloudShow(const string& winname, const GlCamera& camera, const GlArrays& arr) { #ifndef HAVE_OPENGL CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); #else - setOpenGlContext(winname); - gpu::GlBuffer buf(d_mat, gpu::GlBuffer::TEXTURE_BUFFER); - imshow(winname, buf); -#endif -} - -void cv::imshow(const string& winname, const gpu::GlTexture& tex) -{ -#ifndef HAVE_OPENGL - CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); -#else - namedWindow(winname, WINDOW_OPENGL | WINDOW_AUTOSIZE); - - double autoSize = getWindowProperty(winname, WND_PROP_AUTOSIZE); - - if (autoSize > 0) - resizeWindow(winname, tex.cols, tex.rows); + namedWindow(winname, WINDOW_OPENGL); setOpenGlContext(winname); GlObjBase* glObj = findGlObjByName(winname); - if (glObj && glObj->flag != CV_TEXTURE_MAGIC_VAL) + if (glObj && glObj->flag != CV_POINT_CLOUD_MAGIC_VAL) { icvSetOpenGlCleanCallback(winname.c_str(), 0, 0); glObj = 0; @@ -444,16 +409,18 @@ void cv::imshow(const string& winname, const gpu::GlTexture& tex) if (glObj) { - GlObjTex* texObj = static_cast(glObj); - texObj->tex = tex; + GlObjPointCloud* pointCloudObj = static_cast(glObj); + pointCloudObj->arr = arr; + pointCloudObj->camera = camera; } else { - GlObjTex* texObj = new GlObjTex; - texObj->tex = tex; + GlObjPointCloud* pointCloudObj = new GlObjPointCloud; + pointCloudObj->arr = arr; + pointCloudObj->camera = camera; - glObj = texObj; - glObj->flag = CV_TEXTURE_MAGIC_VAL; + glObj = pointCloudObj; + glObj->flag = CV_POINT_CLOUD_MAGIC_VAL; glObj->winname = winname; addGlObj(glObj); @@ -461,13 +428,13 @@ void cv::imshow(const string& winname, const gpu::GlTexture& tex) icvSetOpenGlCleanCallback(winname.c_str(), glCleanCallback, glObj); } - setOpenGlDrawCallback(winname, glDrawTextureCallback, glObj); + setOpenGlDrawCallback(winname, glDrawPointCloudCallback, glObj); updateWindow(winname); #endif } -void cv::pointCloudShow(const string& winname, const gpu::GlCamera& camera, const gpu::GlArrays& arr) +void cv::pointCloudShow(const std::string& winname, const cv::GlCamera& camera, InputArray points, InputArray colors) { #ifndef HAVE_OPENGL CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); @@ -487,13 +454,23 @@ void cv::pointCloudShow(const string& winname, const gpu::GlCamera& camera, cons if (glObj) { GlObjPointCloud* pointCloudObj = static_cast(glObj); - pointCloudObj->arr = arr; + + pointCloudObj->arr.setVertexArray(points); + if (colors.empty()) + pointCloudObj->arr.resetColorArray(); + else + pointCloudObj->arr.setColorArray(colors); + pointCloudObj->camera = camera; } else { GlObjPointCloud* pointCloudObj = new GlObjPointCloud; - pointCloudObj->arr = arr; + + pointCloudObj->arr.setVertexArray(points); + if (!colors.empty()) + pointCloudObj->arr.setColorArray(colors); + pointCloudObj->camera = camera; glObj = pointCloudObj; @@ -511,104 +488,6 @@ void cv::pointCloudShow(const string& winname, const gpu::GlCamera& camera, cons #endif } -#ifdef HAVE_OPENGL - -namespace -{ - template void pointCloudShowImpl(const std::string& winname, const cv::gpu::GlCamera& camera, const T& points, const T& colors) - { - using namespace cv; - - namedWindow(winname, WINDOW_OPENGL); - - setOpenGlContext(winname); - - GlObjBase* glObj = findGlObjByName(winname); - - if (glObj && glObj->flag != CV_POINT_CLOUD_MAGIC_VAL) - { - icvSetOpenGlCleanCallback(winname.c_str(), 0, 0); - glObj = 0; - } - - if (glObj) - { - GlObjPointCloud* pointCloudObj = static_cast(glObj); - - pointCloudObj->arr.setVertexArray(points); - if (colors.empty()) - pointCloudObj->arr.resetColorArray(); - else - pointCloudObj->arr.setColorArray(colors); - - pointCloudObj->camera = camera; - } - else - { - GlObjPointCloud* pointCloudObj = new GlObjPointCloud; - - pointCloudObj->arr.setVertexArray(points); - if (!colors.empty()) - pointCloudObj->arr.setColorArray(colors); - - pointCloudObj->camera = camera; - - glObj = pointCloudObj; - glObj->flag = CV_POINT_CLOUD_MAGIC_VAL; - glObj->winname = winname; - - addGlObj(glObj); - - icvSetOpenGlCleanCallback(winname.c_str(), glCleanCallback, glObj); - } - - setOpenGlDrawCallback(winname, glDrawPointCloudCallback, glObj); - - updateWindow(winname); - } -} - -#endif // HAVE_OPENGL - -void cv::pointCloudShow(const string& winname, const gpu::GlCamera& camera, const gpu::GlBuffer& points, const gpu::GlBuffer& colors) -{ -#ifndef HAVE_OPENGL - CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); -#else - pointCloudShowImpl(winname, camera, points, colors); -#endif -} - -void cv::pointCloudShow(const string& winname, const gpu::GlCamera& camera, const gpu::GpuMat& points, const gpu::GpuMat& colors) -{ -#ifndef HAVE_OPENGL - CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); -#else - pointCloudShowImpl(winname, camera, points, colors); -#endif -} - -void cv::pointCloudShow(const string& winname, const gpu::GlCamera& camera, InputArray points, InputArray colors) -{ -#ifndef HAVE_OPENGL - CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); -#else - pointCloudShowImpl(winname, camera, points, colors); -#endif -} - -// OpenGL text - -void cv::addTextOpenGl(const string& winname, const string& text, Point org, Scalar color, const string& fontName, int fontHeight, int fontWeight, int fontStyle) -{ - cvAddTextOpenGl(winname.c_str(), text.c_str(), org, color, fontName.c_str(), fontHeight, fontWeight, fontStyle); -} - -void cv::clearTextOpenGl(const string& winname) -{ - cvClearTextOpenGl(winname.c_str()); -} - // Without OpenGL #ifndef HAVE_OPENGL @@ -630,16 +509,6 @@ CV_IMPL void cvUpdateWindow(const char*) CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); } -CV_IMPL void cvAddTextOpenGl(const char*, const char*, CvPoint, CvScalar, const char*, int, int, int) -{ - CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); -} - -CV_IMPL void cvClearTextOpenGl(const char*) -{ - CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); -} - void icvSetOpenGlCleanCallback(const char*, CvOpenGlCleanCallback, void*) { CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 0572dc5cba..3bbed9e340 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -60,7 +60,6 @@ #include #include #include "opencv2/highgui/highgui.hpp" -#include "opencv2/core/gpumat.hpp" #include #endif @@ -137,216 +136,6 @@ typedef struct CvTrackbar } CvTrackbar; -// OpenGL support - -#ifdef HAVE_OPENGL - -namespace -{ - class OpenGlFont - { - public: - OpenGlFont(HDC hDC, const std::string& fontName, int fontHeight, int fontWeight, int fontStyle); - ~OpenGlFont(); - - void draw(const char* str, int len, CvPoint org, CvScalar color, int width, int height) const; - - inline const std::string& fontName() const { return fontName_; } - inline int fontHeight() const { return fontHeight_; } - inline int fontWeight() const { return fontWeight_; } - inline int fontStyle() const { return fontStyle_; } - - private: - std::string fontName_; - int fontHeight_; - int fontWeight_; - int fontStyle_; - - GLuint base_; - - OpenGlFont(const OpenGlFont&); - OpenGlFont& operator =(const OpenGlFont&); - }; - - int getFontWidthW32(int fontWeight) - { - int weight = 0; - - switch(fontWeight) - { - case CV_FONT_LIGHT: - weight = 200; - break; - case CV_FONT_NORMAL: - weight = FW_NORMAL; - break; - case CV_FONT_DEMIBOLD: - weight = 550; - break; - case CV_FONT_BOLD: - weight = FW_BOLD; - break; - case CV_FONT_BLACK: - weight = FW_BLACK; - break; - default: - cvError(CV_StsBadArg, "getFontWidthW32", "Unsopported font width", __FILE__, __LINE__); - }; - - return weight; - } - - OpenGlFont::OpenGlFont(HDC hDC, const std::string& fontName, int fontHeight, int fontWeight, int fontStyle) - : fontName_(), fontHeight_(0), fontWeight_(0), fontStyle_(0), base_(0) - { - base_ = glGenLists(96); - - HFONT font = CreateFont - ( - -fontHeight, // height - 0, // cell width - 0, // Angle of Escapement - 0, // Orientation Angle - getFontWidthW32(fontWeight), // font weight - fontStyle & CV_STYLE_ITALIC ? TRUE : FALSE, // Italic - fontStyle & CV_STYLE_UNDERLINE ? TRUE : FALSE, // Underline - FALSE, // StrikeOut - ANSI_CHARSET, // CharSet - OUT_TT_PRECIS, // OutPrecision - CLIP_DEFAULT_PRECIS, // ClipPrecision - ANTIALIASED_QUALITY, // Quality - FF_DONTCARE | DEFAULT_PITCH, // PitchAndFamily - fontName.c_str() // FaceName - ); - - SelectObject(hDC, font); - - if (!wglUseFontBitmaps(hDC, 32, 96, base_)) - cvError(CV_OpenGlApiCallError, "OpenGlFont", "Can't create font", __FILE__, __LINE__); - - fontName_ = fontName; - fontHeight_ = fontHeight; - fontWeight_ = fontWeight; - fontStyle_ = fontStyle; - } - - OpenGlFont::~OpenGlFont() - { - if (base_) - glDeleteLists(base_, 96); - } - - void OpenGlFont::draw(const char* str, int len, CvPoint org, CvScalar color, int width, int height) const - { - if (base_) - { - glPushAttrib(GL_LIST_BIT); - glListBase(base_ - 32); - - glColor4dv(color.val); - glRasterPos2f(static_cast(org.x) / width, static_cast((org.y + fontHeight_)) / height); - glCallLists(len, GL_UNSIGNED_BYTE, str); - - glPopAttrib(); - - CV_CheckGlError(); - } - } - - class OpenGlText - { - public: - OpenGlText(HDC hDC); - - void add(const std::string& text, CvPoint org, CvScalar color, const std::string& fontName, int fontHeight, int fontWeight, int fontStyle); - inline void clear() { text_.clear(); } - - void draw(int width, int height) const; - - private: - struct Text - { - std::string str; - - CvPoint org; - CvScalar color; - - cv::Ptr font; - }; - - HDC hDC_; - - std::vector< cv::Ptr > fonts_; - - std::vector text_; - }; - - OpenGlText::OpenGlText(HDC hDC) : hDC_(hDC) - { - fonts_.reserve(5); - text_.reserve(5); - } - - class FontCompare : public std::unary_function, bool> - { - public: - inline FontCompare(const std::string& fontName, int fontHeight, int fontWeight, int fontStyle) - : fontName_(fontName), fontHeight_(fontHeight), fontWeight_(fontWeight), fontStyle_(fontStyle) - { - } - - bool operator ()(const cv::Ptr& font) - { - return font->fontName() == fontName_ && font->fontHeight() == fontHeight_ && font->fontWeight() == fontWeight_ && font->fontStyle() == fontStyle_; - } - - private: - std::string fontName_; - int fontHeight_; - int fontWeight_; - int fontStyle_; - }; - - void OpenGlText::add(const std::string& str, CvPoint org, CvScalar color, const std::string& fontName, int fontHeight, int fontWeight, int fontStyle) - { - std::vector< cv::Ptr >::iterator fontIt = - std::find_if(fonts_.begin(), fonts_.end(), FontCompare(fontName, fontHeight, fontWeight, fontStyle)); - - if (fontIt == fonts_.end()) - { - fonts_.push_back(new OpenGlFont(hDC_, fontName, fontHeight, fontWeight, fontStyle)); - fontIt = fonts_.end() - 1; - } - - Text text; - text.str = str; - text.org = org; - text.color = color; - text.font = *fontIt; - - text_.push_back(text); - } - - void OpenGlText::draw(int width, int height) const - { - glDisable(GL_DEPTH_TEST); - - static cv::gpu::GlCamera glCamera; - glCamera.setupProjectionMatrix(); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - for (size_t i = 0, size = text_.size(); i < size; ++i) - { - const Text& text = text_[i]; - text.font->draw(text.str.c_str(), text.str.length(), text.org, text.color, width, height); - } - } -} - -#endif // HAVE_OPENGL - typedef struct CvWindow { @@ -391,9 +180,7 @@ typedef struct CvWindow CvOpenGlCleanCallback glCleanCallback; void* glCleanData; - cv::gpu::GlFuncTab* glFuncTab; - - OpenGlText* glText; + CvOpenGlFuncTab* glFuncTab; #endif } CvWindow; @@ -809,9 +596,26 @@ namespace typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); - class GlFuncTab_W32 : public cv::gpu::GlFuncTab + class GlFuncTab_W32 : public CvOpenGlFuncTab { public: + GlFuncTab_W32(HDC hDC); + + void genBuffers(int n, unsigned int* buffers) const; + void deleteBuffers(int n, const unsigned int* buffers) const; + + void bufferData(unsigned int target, ptrdiff_t size, const void* data, unsigned int usage) const; + void bufferSubData(unsigned int target, ptrdiff_t offset, ptrdiff_t size, const void* data) const; + + void bindBuffer(unsigned int target, unsigned int buffer) const; + + void* mapBuffer(unsigned int target, unsigned int access) const; + void unmapBuffer(unsigned int target) const; + + void generateBitmapFont(const std::string& family, int height, int weight, bool italic, bool underline, int start, int count, int base) const; + + bool isGlContextInitialized() const; + PFNGLGENBUFFERSPROC glGenBuffersExt; PFNGLDELETEBUFFERSPROC glDeleteBuffersExt; @@ -825,142 +629,180 @@ namespace bool initialized; - GlFuncTab_W32() - { - glGenBuffersExt = 0; - glDeleteBuffersExt = 0; + HDC hDC; + }; - glBufferDataExt = 0; - glBufferSubDataExt = 0; + GlFuncTab_W32::GlFuncTab_W32(HDC hDC_) + { + glGenBuffersExt = 0; + glDeleteBuffersExt = 0; - glBindBufferExt = 0; + glBufferDataExt = 0; + glBufferSubDataExt = 0; - glMapBufferExt = 0; - glUnmapBufferExt = 0; + glBindBufferExt = 0; - initialized = false; - } + glMapBufferExt = 0; + glUnmapBufferExt = 0; - void genBuffers(int n, unsigned int* buffers) const - { - CV_FUNCNAME( "genBuffers" ); + initialized = false; - __BEGIN__; + hDC = hDC_; + } - if (!glGenBuffersExt) - CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); + void GlFuncTab_W32::genBuffers(int n, unsigned int* buffers) const + { + CV_FUNCNAME( "GlFuncTab_W32::genBuffers" ); - glGenBuffersExt(n, buffers); - CV_CheckGlError(); + __BEGIN__; - __END__; - } + if (!glGenBuffersExt) + CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); - void deleteBuffers(int n, const unsigned int* buffers) const - { - CV_FUNCNAME( "deleteBuffers" ); + glGenBuffersExt(n, buffers); + CV_CheckGlError(); - __BEGIN__; + __END__; + } - if (!glDeleteBuffersExt) - CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); + void GlFuncTab_W32::deleteBuffers(int n, const unsigned int* buffers) const + { + CV_FUNCNAME( "GlFuncTab_W32::deleteBuffers" ); - glDeleteBuffersExt(n, buffers); - CV_CheckGlError(); + __BEGIN__; - __END__; - } + if (!glDeleteBuffersExt) + CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); - void bufferData(unsigned int target, ptrdiff_t size, const void* data, unsigned int usage) const - { - CV_FUNCNAME( "bufferData" ); + glDeleteBuffersExt(n, buffers); + CV_CheckGlError(); - __BEGIN__; + __END__; + } - if (!glBufferDataExt) - CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); + void GlFuncTab_W32::bufferData(unsigned int target, ptrdiff_t size, const void* data, unsigned int usage) const + { + CV_FUNCNAME( "GlFuncTab_W32::bufferData" ); - glBufferDataExt(target, size, data, usage); - CV_CheckGlError(); + __BEGIN__; - __END__; - } + if (!glBufferDataExt) + CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); - void bufferSubData(unsigned int target, ptrdiff_t offset, ptrdiff_t size, const void* data) const - { - CV_FUNCNAME( "bufferSubData" ); + glBufferDataExt(target, size, data, usage); + CV_CheckGlError(); - __BEGIN__; + __END__; + } - if (!glBufferSubDataExt) - CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); + void GlFuncTab_W32::bufferSubData(unsigned int target, ptrdiff_t offset, ptrdiff_t size, const void* data) const + { + CV_FUNCNAME( "GlFuncTab_W32::bufferSubData" ); - glBufferSubDataExt(target, offset, size, data); - CV_CheckGlError(); + __BEGIN__; - __END__; - } + if (!glBufferSubDataExt) + CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); - void bindBuffer(unsigned int target, unsigned int buffer) const - { - CV_FUNCNAME( "bindBuffer" ); + glBufferSubDataExt(target, offset, size, data); + CV_CheckGlError(); - __BEGIN__; + __END__; + } - if (!glBindBufferExt) - CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); + void GlFuncTab_W32::bindBuffer(unsigned int target, unsigned int buffer) const + { + CV_FUNCNAME( "GlFuncTab_W32::bindBuffer" ); - glBindBufferExt(target, buffer); - CV_CheckGlError(); + __BEGIN__; - __END__; - } + if (!glBindBufferExt) + CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); - void* mapBuffer(unsigned int target, unsigned int access) const - { - CV_FUNCNAME( "mapBuffer" ); + glBindBufferExt(target, buffer); + CV_CheckGlError(); - void* res = 0; + __END__; + } - __BEGIN__; + void* GlFuncTab_W32::mapBuffer(unsigned int target, unsigned int access) const + { + CV_FUNCNAME( "GlFuncTab_W32::mapBuffer" ); - if (!glMapBufferExt) - CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); + void* res = 0; - res = glMapBufferExt(target, access); - CV_CheckGlError(); + __BEGIN__; - __END__; + if (!glMapBufferExt) + CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); - return res; - } + res = glMapBufferExt(target, access); + CV_CheckGlError(); - void unmapBuffer(unsigned int target) const - { - CV_FUNCNAME( "unmapBuffer" ); + __END__; - __BEGIN__; + return res; + } - if (!glUnmapBufferExt) - CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); + void GlFuncTab_W32::unmapBuffer(unsigned int target) const + { + CV_FUNCNAME( "GlFuncTab_W32::unmapBuffer" ); - glUnmapBufferExt(target); - CV_CheckGlError(); + __BEGIN__; - __END__; - } + if (!glUnmapBufferExt) + CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension"); - bool isGlContextInitialized() const - { - return initialized; - } - }; + glUnmapBufferExt(target); + CV_CheckGlError(); + + __END__; + } + + void GlFuncTab_W32::generateBitmapFont(const std::string& family, int height, int weight, bool italic, bool underline, int start, int count, int base) const + { + HFONT font; + + CV_FUNCNAME( "GlFuncTab_W32::generateBitmapFont" ); + + __BEGIN__; + + font = CreateFont + ( + -height, // height + 0, // cell width + 0, // Angle of Escapement + 0, // Orientation Angle + weight, // font weight + italic ? TRUE : FALSE, // Italic + underline ? TRUE : FALSE, // Underline + FALSE, // StrikeOut + ANSI_CHARSET, // CharSet + OUT_TT_PRECIS, // OutPrecision + CLIP_DEFAULT_PRECIS, // ClipPrecision + ANTIALIASED_QUALITY, // Quality + FF_DONTCARE | DEFAULT_PITCH, // PitchAndFamily + family.c_str() // FaceName + ); + + SelectObject(hDC, font); + + if (!wglUseFontBitmaps(hDC, start, count, base)) + CV_ERROR(CV_OpenGlApiCallError, "Can't create font"); + + __END__; + } + + bool GlFuncTab_W32::isGlContextInitialized() const + { + return initialized; + } void initGl(CvWindow* window) { glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - std::auto_ptr glFuncTab(new GlFuncTab_W32); + std::auto_ptr glFuncTab(new GlFuncTab_W32(window->dc)); // Load extensions PROC func; @@ -990,7 +832,7 @@ namespace window->glFuncTab = glFuncTab.release(); - cv::gpu::setGlFuncTab(window->glFuncTab); + icvSetOpenGlFuncTab(window->glFuncTab); } void createGlContext(HWND hWnd, HDC& hGLDC, HGLRC& hGLRC, bool& useGl) @@ -1089,11 +931,6 @@ namespace CV_CheckGlError(); - if (window->glText) - window->glText->draw(window->width, window->height); - - CV_CheckGlError(); - if (!SwapBuffers(window->dc)) CV_ERROR( CV_OpenGlApiCallError, "Can't swap OpenGL buffers" ); @@ -1209,8 +1046,6 @@ CV_IMPL int cvNamedWindow( const char* name, int flags ) window->glCleanCallback = 0; window->glCleanData = 0; - - window->glText = 0; #endif window->last_key = 0; @@ -1261,68 +1096,7 @@ CV_IMPL void cvSetOpenGlContext(const char* name) if (!wglMakeCurrent(window->dc, window->hGLRC)) CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" ); - cv::gpu::setGlFuncTab(window->glFuncTab); - - __END__; -} - -CV_IMPL void cvAddTextOpenGl(const char* name, const char* text, CvPoint org, CvScalar color, const char* fontName, int fontHeight, int fontWeight, int fontStyle) -{ - CV_FUNCNAME( "cvAddTextOpenGl" ); - - __BEGIN__; - - CvWindow* window; - - if(!name) - CV_ERROR( CV_StsNullPtr, "NULL name string" ); - - window = icvFindWindowByName( name ); - if (!window) - CV_ERROR( CV_StsNullPtr, "NULL window" ); - - if (!window->useGl) - CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" ); - - if (!wglMakeCurrent(window->dc, window->hGLRC)) - CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" ); - - if (!window->glText) - window->glText = new OpenGlText(window->dc); - - window->glText->add(text, org, color, fontName, fontHeight, fontWeight, fontStyle); - - InvalidateRect(window->hwnd, 0, 0); - - __END__; -} - -CV_IMPL void cvClearTextOpenGl(const char* name) -{ - CV_FUNCNAME( "cvClearTextOpenGl" ); - - __BEGIN__; - - CvWindow* window; - - if(!name) - CV_ERROR( CV_StsNullPtr, "NULL name string" ); - - window = icvFindWindowByName( name ); - if (!window) - CV_ERROR( CV_StsNullPtr, "NULL window" ); - - if (!window->useGl) - CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" ); - - if (!wglMakeCurrent(window->dc, window->hGLRC)) - CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" ); - - if (window->glText) - { - window->glText->clear(); - InvalidateRect(window->hwnd, 0, 0); - } + icvSetOpenGlFuncTab(window->glFuncTab); __END__; } @@ -1406,9 +1180,6 @@ static void icvRemoveWindow( CvWindow* window ) if (window->useGl) { wglMakeCurrent(window->dc, window->hGLRC); - - if (window->glText) - delete window->glText; if (window->glCleanCallback) { diff --git a/samples/cpp/point_cloud.cpp b/samples/cpp/point_cloud.cpp index d668da6187..e1fddf1ab4 100644 --- a/samples/cpp/point_cloud.cpp +++ b/samples/cpp/point_cloud.cpp @@ -3,7 +3,7 @@ #include #include #include "opencv2/core/core.hpp" -#include "opencv2/core/gpumat.hpp" +#include "opencv2/core/opengl_interop.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/calib3d/calib3d.hpp" @@ -13,56 +13,52 @@ using namespace std; using namespace cv; using namespace cv::gpu; -void mouseCallback(int event, int x, int y, int flags, void* userdata) +class PointCloudRenderer { - int* dx = static_cast(userdata); - int* dy = dx + 1; - - static int oldx = x; - static int oldy = y; - static bool moving = false; +public: + PointCloudRenderer(const Mat& points, const Mat& img, double scale); + + void onMouseEvent(int event, int x, int y, int flags); + void draw(); + void update(int key, double aspect); + + int fov_; + +private: + int mouse_dx_; + int mouse_dy_; + + double yaw_; + double pitch_; + Point3d pos_; + + TickMeter tm_; + static const int step_; + int frame_; + + GlCamera camera_; + GlArrays pointCloud_; + string fps_; +}; + +bool stop = false; - if (event == EVENT_LBUTTONDOWN) - { - oldx = x; - oldy = y; - moving = true; - } - else if (event == EVENT_LBUTTONUP) - { - moving = false; - } - - if (moving) - { - *dx = oldx - x; - *dy = oldy - y; - } - else - { - *dx = 0; - *dy = 0; - } -} - -inline int clamp(int val, int minVal, int maxVal) +void mouseCallback(int event, int x, int y, int flags, void* userdata) { - return max(min(val, maxVal), minVal); + if (stop) + return; + + PointCloudRenderer* renderer = static_cast(userdata); + renderer->onMouseEvent(event, x, y, flags); } -Point3d rotate(Point3d v, double yaw, double pitch) +void openGlDrawCallback(void* userdata) { - Point3d t1; - t1.x = v.x * cos(-yaw / 180.0 * CV_PI) - v.z * sin(-yaw / 180.0 * CV_PI); - t1.y = v.y; - t1.z = v.x * sin(-yaw / 180.0 * CV_PI) + v.z * cos(-yaw / 180.0 * CV_PI); + if (stop) + return; - Point3d t2; - t2.x = t1.x; - t2.y = t1.y * cos(pitch / 180.0 * CV_PI) - t1.z * sin(pitch / 180.0 * CV_PI); - t2.z = t1.y * sin(pitch / 180.0 * CV_PI) + t1.z * cos(pitch / 180.0 * CV_PI); - - return t2; + PointCloudRenderer* renderer = static_cast(userdata); + renderer->draw(); } int main(int argc, const char* argv[]) @@ -192,96 +188,168 @@ int main(int argc, const char* argv[]) const string windowName = "OpenGL Sample"; namedWindow(windowName, WINDOW_OPENGL); + resizeWindow(windowName, 400, 400); + + PointCloudRenderer renderer(points, imgLeftColor, scale); - int fov = 0; - createTrackbar("Fov", windowName, &fov, 100); + createTrackbar("Fov", windowName, &renderer.fov_, 100); + setMouseCallback(windowName, mouseCallback, &renderer); + setOpenGlDrawCallback(windowName, openGlDrawCallback, &renderer); - int mouse[2] = {0, 0}; - setMouseCallback(windowName, mouseCallback, mouse); + while (true) + { + int key = waitKey(1); - GlArrays pointCloud; + if (key >= 0) + key = key & 0xff; - pointCloud.setVertexArray(points); - pointCloud.setColorArray(imgLeftColor, false); + if (key == 27) + { + stop = true; + break; + } - GlCamera camera; - camera.setScale(Point3d(scale, scale, scale)); + double aspect = getWindowProperty(windowName, WND_PROP_ASPECT_RATIO); - double yaw = 0.0; - double pitch = 0.0; + key = tolower(key); - const Point3d dirVec(0.0, 0.0, -1.0); - const Point3d upVec(0.0, 1.0, 0.0); - const Point3d leftVec(-1.0, 0.0, 0.0); - Point3d pos; + renderer.update(key, aspect); + + updateWindow(windowName); + } - TickMeter tm; - const int step = 20; - int frame = 0; + return 0; +} - while (true) +const int PointCloudRenderer::step_ = 20; + +PointCloudRenderer::PointCloudRenderer(const Mat& points, const Mat& img, double scale) +{ + mouse_dx_ = 0; + mouse_dy_ = 0; + + fov_ = 0; + yaw_ = 0.0; + pitch_ = 0.0; + + frame_ = 0; + + camera_.setScale(Point3d(scale, scale, scale)); + + pointCloud_.setVertexArray(points); + pointCloud_.setColorArray(img, false); + + tm_.start(); +} + +inline int clamp(int val, int minVal, int maxVal) +{ + return max(min(val, maxVal), minVal); +} + +void PointCloudRenderer::onMouseEvent(int event, int x, int y, int flags) +{ + static int oldx = x; + static int oldy = y; + static bool moving = false; + + if (event == EVENT_LBUTTONDOWN) { - tm.start(); + oldx = x; + oldy = y; + moving = true; + } + else if (event == EVENT_LBUTTONUP) + { + moving = false; + } - int key = waitKey(1); - if (key >= 0) - key = key & 0xff; + if (moving) + { + mouse_dx_ = oldx - x; + mouse_dy_ = oldy - y; + } + else + { + mouse_dx_ = 0; + mouse_dy_ = 0; + } - if (key == 27) - break; + const int mouseClamp = 300; + mouse_dx_ = clamp(mouse_dx_, -mouseClamp, mouseClamp); + mouse_dy_ = clamp(mouse_dy_, -mouseClamp, mouseClamp); +} - double aspect = getWindowProperty(windowName, WND_PROP_ASPECT_RATIO); +Point3d rotate(Point3d v, double yaw, double pitch) +{ + Point3d t1; + t1.x = v.x * cos(-yaw / 180.0 * CV_PI) - v.z * sin(-yaw / 180.0 * CV_PI); + t1.y = v.y; + t1.z = v.x * sin(-yaw / 180.0 * CV_PI) + v.z * cos(-yaw / 180.0 * CV_PI); - const double posStep = 0.1; - - #ifdef _WIN32 + Point3d t2; + t2.x = t1.x; + t2.y = t1.y * cos(pitch / 180.0 * CV_PI) - t1.z * sin(pitch / 180.0 * CV_PI); + t2.z = t1.y * sin(pitch / 180.0 * CV_PI) + t1.z * cos(pitch / 180.0 * CV_PI); + + return t2; +} + +void PointCloudRenderer::update(int key, double aspect) +{ + const Point3d dirVec(0.0, 0.0, -1.0); + const Point3d upVec(0.0, 1.0, 0.0); + const Point3d leftVec(-1.0, 0.0, 0.0); + + const double posStep = 0.1; + + #ifdef _WIN32 const double mouseStep = 0.001; - #else + #else const double mouseStep = 0.000001; - #endif + #endif - const int mouseClamp = 300; + camera_.setPerspectiveProjection(30.0 + fov_ / 100.0 * 40.0, aspect, 0.1, 1000.0); - camera.setPerspectiveProjection(30.0 + fov / 100.0 * 40.0, aspect, 0.1, 1000.0); + yaw_ += mouse_dx_ * mouseStep; + pitch_ += mouse_dy_ * mouseStep; - int mouse_dx = clamp(mouse[0], -mouseClamp, mouseClamp); - int mouse_dy = clamp(mouse[1], -mouseClamp, mouseClamp); + if (key == 'w') + pos_ += posStep * rotate(dirVec, yaw_, pitch_); + else if (key == 's') + pos_ -= posStep * rotate(dirVec, yaw_, pitch_); + else if (key == 'a') + pos_ += posStep * rotate(leftVec, yaw_, pitch_); + else if (key == 'd') + pos_ -= posStep * rotate(leftVec, yaw_, pitch_); + else if (key == 'q') + pos_ += posStep * rotate(upVec, yaw_, pitch_); + else if (key == 'e') + pos_ -= posStep * rotate(upVec, yaw_, pitch_); - yaw += mouse_dx * mouseStep; - pitch += mouse_dy * mouseStep; + camera_.setCameraPos(pos_, yaw_, pitch_, 0.0); - key = tolower(key); - if (key == 'w') - pos += posStep * rotate(dirVec, yaw, pitch); - else if (key == 's') - pos -= posStep * rotate(dirVec, yaw, pitch); - else if (key == 'a') - pos += posStep * rotate(leftVec, yaw, pitch); - else if (key == 'd') - pos -= posStep * rotate(leftVec, yaw, pitch); - else if (key == 'q') - pos += posStep * rotate(upVec, yaw, pitch); - else if (key == 'e') - pos -= posStep * rotate(upVec, yaw, pitch); - - camera.setCameraPos(pos, yaw, pitch, 0.0); - - pointCloudShow(windowName, camera, pointCloud); - - tm.stop(); - - if (frame++ >= step) - { - ostringstream fps; - fps << "FPS: " << step / tm.getTimeSec(); - - clearTextOpenGl(windowName); - addTextOpenGl(windowName, fps.str(), Point(0, 0), Scalar::all(255), "Courier New", 16); - - frame = 0; - tm.reset(); - } + tm_.stop(); + + if (frame_++ >= step_) + { + ostringstream ostr; + ostr << "FPS: " << step_ / tm_.getTimeSec(); + fps_ = ostr.str(); + + frame_ = 0; + tm_.reset(); } - return 0; + tm_.start(); +} + +void PointCloudRenderer::draw() +{ + camera_.setupProjectionMatrix(); + camera_.setupModelViewMatrix(); + + render(pointCloud_); + + render(fps_, GlFont::get("Courier New", 16), Scalar::all(255), Point2d(3.0, 0.0)); } diff --git a/samples/gpu/highgui_gpu.cpp b/samples/gpu/highgui_gpu.cpp index bf0074316d..821c70fd32 100644 --- a/samples/gpu/highgui_gpu.cpp +++ b/samples/gpu/highgui_gpu.cpp @@ -3,6 +3,7 @@ #include "opencv2/core/core.hpp" #include "opencv2/core/gpumat.hpp" +#include "opencv2/core/opengl_interop.hpp" #include "opencv2/gpu/gpu.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/contrib/contrib.hpp" @@ -43,11 +44,17 @@ int main(int argc, char* argv[]) { bool haveCuda = getCudaEnabledDeviceCount() > 0; - namedWindow("OpenGL Mat", WINDOW_OPENGL | WINDOW_AUTOSIZE); - namedWindow("OpenGL GlBuffer", WINDOW_OPENGL | WINDOW_AUTOSIZE); - namedWindow("OpenGL GlTexture", WINDOW_OPENGL | WINDOW_AUTOSIZE); + const string openGlMatWnd = "OpenGL Mat"; + const string openGlBufferWnd = "OpenGL GlBuffer"; + const string openGlTextureWnd = "OpenGL GlTexture"; + const string openGlGpuMatWnd = "OpenGL GpuMat"; + const string matWnd = "Mat"; + + namedWindow(openGlMatWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE); + namedWindow(openGlBufferWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE); + namedWindow(openGlTextureWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE); if (haveCuda) - namedWindow("OpenGL GpuMat", WINDOW_OPENGL | WINDOW_AUTOSIZE); + namedWindow(openGlGpuMatWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE); namedWindow("Mat", WINDOW_AUTOSIZE); Mat img = imread(argv[1]); @@ -55,10 +62,10 @@ int main(int argc, char* argv[]) if (haveCuda) setGlDevice(); - setOpenGlContext("OpenGL GlBuffer"); + setOpenGlContext(openGlBufferWnd); GlBuffer buf(img, GlBuffer::TEXTURE_BUFFER); - setOpenGlContext("OpenGL GlTexture"); + setOpenGlContext(openGlTextureWnd); GlTexture tex(img); GpuMat d_img; @@ -69,48 +76,50 @@ int main(int argc, char* argv[]) { Timer t("OpenGL Mat "); - imshow("OpenGL Mat", img); + imshow(openGlMatWnd, img); } { Timer t("OpenGL GlBuffer "); - imshow("OpenGL GlBuffer", buf); + imshow(openGlBufferWnd, buf); } { Timer t("OpenGL GlTexture"); - imshow("OpenGL GlTexture", tex); + imshow(openGlTextureWnd, tex); } if (haveCuda) { Timer t("OpenGL GpuMat "); - imshow("OpenGL GpuMat", d_img); + imshow(openGlGpuMatWnd, d_img); } { Timer t("Mat "); - imshow("Mat", img); + imshow(matWnd, img); } + waitKey(); + cout << "\n=== Second call\n\n"; { Timer t("OpenGL Mat "); - imshow("OpenGL Mat", img); + imshow(openGlMatWnd, img); } { Timer t("OpenGL GlBuffer "); - imshow("OpenGL GlBuffer", buf); + imshow(openGlBufferWnd, buf); } { Timer t("OpenGL GlTexture"); - imshow("OpenGL GlTexture", tex); + imshow(openGlTextureWnd, tex); } if (haveCuda) { Timer t("OpenGL GpuMat "); - imshow("OpenGL GpuMat", d_img); + imshow(openGlGpuMatWnd, d_img); } { Timer t("Mat "); - imshow("Mat", img); + imshow(matWnd, img); } cout << "\n"; -- GitLab