opencv/modules/core/src/opengl.cpp

1582 lines
38 KiB
C++
Raw Normal View History

2012-10-17 15:12:04 +08:00
/*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"
2012-12-13 17:49:32 +08:00
#ifdef HAVE_OPENGL
# include "gl_core_3_1.hpp"
# ifdef HAVE_CUDA
# include <cuda_gl_interop.h>
# endif
2012-10-17 15:12:04 +08:00
#endif
using namespace cv;
2013-08-28 19:45:13 +08:00
using namespace cv::cuda;
namespace
{
#ifndef HAVE_OPENGL
2013-04-15 18:17:18 +08:00
inline void throw_no_ogl() { CV_Error(cv::Error::OpenGlNotSupported, "The library is compiled without OpenGL support"); }
#else
2013-04-15 18:17:18 +08:00
inline void throw_no_ogl() { CV_Error(cv::Error::OpenGlApiCallError, "OpenGL context doesn't exist"); }
#endif
2013-04-15 18:17:18 +08:00
bool checkError(const char* file, const int line, const char* func = 0)
2012-10-17 15:12:04 +08:00
{
2013-04-15 18:17:18 +08:00
#ifndef HAVE_OPENGL
(void) file;
(void) line;
(void) func;
return true;
#else
GLenum err = gl::GetError();
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
if (err != gl::NO_ERROR_)
{
2013-04-15 18:17:18 +08:00
const char* msg;
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
switch (err)
{
case gl::INVALID_ENUM:
msg = "An unacceptable value is specified for an enumerated argument";
break;
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
case gl::INVALID_VALUE:
msg = "A numeric argument is out of range";
break;
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
case gl::INVALID_OPERATION:
msg = "The specified operation is not allowed in the current state";
break;
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
case gl::OUT_OF_MEMORY:
msg = "There is not enough memory left to execute the command";
break;
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
default:
msg = "Unknown error";
};
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
cvError(CV_OpenGlApiCallError, func, msg, file, line);
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
return false;
}
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
return true;
#endif
}
#define CV_CheckGlError() CV_DbgAssert( (checkError(__FILE__, __LINE__, CV_Func)) )
} // namespace
#ifdef HAVE_OPENGL
namespace
2012-10-17 15:12:04 +08:00
{
const GLenum gl_types[] = { gl::UNSIGNED_BYTE, gl::BYTE, gl::UNSIGNED_SHORT, gl::SHORT, gl::INT, gl::FLOAT, gl::DOUBLE };
2012-10-17 15:12:04 +08:00
}
#endif
2012-10-17 15:12:04 +08:00
////////////////////////////////////////////////////////////////////////
// setGlDevice
2012-10-17 15:12:04 +08:00
2013-08-28 19:45:13 +08:00
void cv::cuda::setGlDevice(int device)
2012-10-17 15:12:04 +08:00
{
2012-12-13 17:49:32 +08:00
#ifndef HAVE_OPENGL
(void) device;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
2013-04-15 18:17:18 +08:00
#ifndef HAVE_CUDA
2012-12-13 17:49:32 +08:00
(void) device;
throw_no_cuda();
2012-12-13 17:49:32 +08:00
#else
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaGLSetGLDevice(device) );
2012-12-13 17:49:32 +08:00
#endif
2012-10-17 15:12:04 +08:00
#endif
}
////////////////////////////////////////////////////////////////////////
// CudaResource
2013-04-15 18:17:18 +08:00
#if defined(HAVE_OPENGL) && defined(HAVE_CUDA)
2012-10-17 15:12:04 +08:00
namespace
{
class CudaResource
2012-10-17 15:12:04 +08:00
{
public:
CudaResource();
~CudaResource();
2012-10-17 15:12:04 +08:00
void registerBuffer(GLuint buffer);
void release();
2012-10-17 15:12:04 +08:00
void copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream = 0);
void copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream = 0);
2012-10-17 15:12:04 +08:00
void* map(cudaStream_t stream = 0);
2012-10-17 15:12:04 +08:00
void unmap(cudaStream_t stream = 0);
private:
cudaGraphicsResource_t resource_;
GLuint buffer_;
class GraphicsMapHolder;
2012-10-17 15:12:04 +08:00
};
CudaResource::CudaResource() : resource_(0), buffer_(0)
2012-10-17 15:12:04 +08:00
{
}
CudaResource::~CudaResource()
2012-10-17 15:12:04 +08:00
{
release();
2012-10-17 15:12:04 +08:00
}
void CudaResource::registerBuffer(GLuint buffer)
2012-10-17 15:12:04 +08:00
{
CV_DbgAssert( buffer != 0 );
if (buffer_ == buffer)
return;
2012-10-17 15:12:04 +08:00
cudaGraphicsResource_t resource;
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaGraphicsGLRegisterBuffer(&resource, buffer, cudaGraphicsMapFlagsNone) );
2012-10-17 15:12:04 +08:00
release();
2012-10-17 15:12:04 +08:00
resource_ = resource;
buffer_ = buffer;
}
void CudaResource::release()
{
if (resource_)
cudaGraphicsUnregisterResource(resource_);
resource_ = 0;
buffer_ = 0;
}
class CudaResource::GraphicsMapHolder
{
public:
GraphicsMapHolder(cudaGraphicsResource_t* resource, cudaStream_t stream);
~GraphicsMapHolder();
void reset();
private:
cudaGraphicsResource_t* resource_;
cudaStream_t stream_;
};
CudaResource::GraphicsMapHolder::GraphicsMapHolder(cudaGraphicsResource_t* resource, cudaStream_t stream) : resource_(resource), stream_(stream)
{
if (resource_)
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaGraphicsMapResources(1, resource_, stream_) );
}
CudaResource::GraphicsMapHolder::~GraphicsMapHolder()
{
if (resource_)
cudaGraphicsUnmapResources(1, resource_, stream_);
2012-10-17 15:12:04 +08:00
}
void CudaResource::GraphicsMapHolder::reset()
2012-10-17 15:12:04 +08:00
{
resource_ = 0;
}
2012-10-17 15:12:04 +08:00
void CudaResource::copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream)
{
CV_DbgAssert( resource_ != 0 );
2012-10-17 15:12:04 +08:00
GraphicsMapHolder h(&resource_, stream);
(void) h;
2012-10-17 15:12:04 +08:00
void* dst;
size_t size;
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&dst, &size, resource_) );
2012-10-17 15:12:04 +08:00
CV_DbgAssert( width * height == size );
2012-10-17 15:12:04 +08:00
if (stream == 0)
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaMemcpy2D(dst, width, src, spitch, width, height, cudaMemcpyDeviceToDevice) );
2012-10-17 15:12:04 +08:00
else
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaMemcpy2DAsync(dst, width, src, spitch, width, height, cudaMemcpyDeviceToDevice, stream) );
}
2012-10-17 15:12:04 +08:00
void CudaResource::copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream)
{
CV_DbgAssert( resource_ != 0 );
GraphicsMapHolder h(&resource_, stream);
(void) h;
void* src;
size_t size;
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&src, &size, resource_) );
CV_DbgAssert( width * height == size );
if (stream == 0)
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaMemcpy2D(dst, dpitch, src, width, width, height, cudaMemcpyDeviceToDevice) );
else
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaMemcpy2DAsync(dst, dpitch, src, width, width, height, cudaMemcpyDeviceToDevice, stream) );
2012-10-17 15:12:04 +08:00
}
void* CudaResource::map(cudaStream_t stream)
2012-10-17 15:12:04 +08:00
{
CV_DbgAssert( resource_ != 0 );
2012-10-17 15:12:04 +08:00
GraphicsMapHolder h(&resource_, stream);
2012-10-17 15:12:04 +08:00
void* ptr;
size_t size;
2013-04-08 16:37:36 +08:00
cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&ptr, &size, resource_) );
2012-10-17 15:12:04 +08:00
h.reset();
2012-10-17 15:12:04 +08:00
return ptr;
2012-10-17 15:12:04 +08:00
}
void CudaResource::unmap(cudaStream_t stream)
2012-10-17 15:12:04 +08:00
{
CV_Assert( resource_ != 0 );
2012-10-17 15:12:04 +08:00
cudaGraphicsUnmapResources(1, &resource_, stream);
}
}
#endif
2012-10-17 15:12:04 +08:00
////////////////////////////////////////////////////////////////////////
// ogl::Buffer
2012-10-17 15:12:04 +08:00
#ifndef HAVE_OPENGL
class cv::ogl::Buffer::Impl
2012-10-17 15:12:04 +08:00
{
};
#else
class cv::ogl::Buffer::Impl
2012-10-17 15:12:04 +08:00
{
public:
static const Ptr<Impl>& empty();
Impl(GLuint bufId, bool autoRelease);
Impl(GLsizeiptr size, const GLvoid* data, GLenum target, bool autoRelease);
2012-10-17 15:12:04 +08:00
~Impl();
void bind(GLenum target) const;
2012-10-17 15:12:04 +08:00
void copyFrom(GLuint srcBuf, GLsizeiptr size);
2012-10-17 15:12:04 +08:00
void copyFrom(GLsizeiptr size, const GLvoid* data);
void copyTo(GLsizeiptr size, GLvoid* data) const;
2012-10-17 15:12:04 +08:00
void* mapHost(GLenum access);
void unmapHost();
2012-10-17 15:12:04 +08:00
#ifdef HAVE_CUDA
void copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream = 0);
void copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream = 0) const;
void* mapDevice(cudaStream_t stream = 0);
2012-10-17 15:12:04 +08:00
void unmapDevice(cudaStream_t stream = 0);
#endif
void setAutoRelease(bool flag) { autoRelease_ = flag; }
GLuint bufId() const { return bufId_; }
2012-10-17 15:12:04 +08:00
private:
Impl();
GLuint bufId_;
bool autoRelease_;
2012-10-17 15:12:04 +08:00
#ifdef HAVE_CUDA
mutable CudaResource cudaResource_;
2012-10-17 15:12:04 +08:00
#endif
};
const Ptr<cv::ogl::Buffer::Impl>& cv::ogl::Buffer::Impl::empty()
2012-10-17 15:12:04 +08:00
{
static Ptr<Impl> p(new Impl);
return p;
}
2013-04-15 18:17:18 +08:00
cv::ogl::Buffer::Impl::Impl() : bufId_(0), autoRelease_(false)
2012-10-17 15:12:04 +08:00
{
}
cv::ogl::Buffer::Impl::Impl(GLuint abufId, bool autoRelease) : bufId_(abufId), autoRelease_(autoRelease)
2012-10-17 15:12:04 +08:00
{
2013-04-15 18:17:18 +08:00
CV_Assert( gl::IsBuffer(abufId) == gl::TRUE_ );
2012-10-17 15:12:04 +08:00
}
cv::ogl::Buffer::Impl::Impl(GLsizeiptr size, const GLvoid* data, GLenum target, bool autoRelease) : bufId_(0), autoRelease_(autoRelease)
2012-10-17 15:12:04 +08:00
{
gl::GenBuffers(1, &bufId_);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
CV_Assert( bufId_ != 0 );
2012-10-17 15:12:04 +08:00
gl::BindBuffer(target, bufId_);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::BufferData(target, size, data, gl::DYNAMIC_DRAW);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::BindBuffer(target, 0);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
}
cv::ogl::Buffer::Impl::~Impl()
2012-10-17 15:12:04 +08:00
{
if (autoRelease_ && bufId_)
gl::DeleteBuffers(1, &bufId_);
2012-10-17 15:12:04 +08:00
}
void cv::ogl::Buffer::Impl::bind(GLenum target) const
2012-10-17 15:12:04 +08:00
{
gl::BindBuffer(target, bufId_);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
void cv::ogl::Buffer::Impl::copyFrom(GLuint srcBuf, GLsizeiptr size)
2012-10-17 15:12:04 +08:00
{
gl::BindBuffer(gl::COPY_WRITE_BUFFER, bufId_);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::BindBuffer(gl::COPY_READ_BUFFER, srcBuf);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::CopyBufferSubData(gl::COPY_READ_BUFFER, gl::COPY_WRITE_BUFFER, 0, 0, size);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
}
void cv::ogl::Buffer::Impl::copyFrom(GLsizeiptr size, const GLvoid* data)
2012-10-17 15:12:04 +08:00
{
gl::BindBuffer(gl::COPY_WRITE_BUFFER, bufId_);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::BufferSubData(gl::COPY_WRITE_BUFFER, 0, size, data);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
void cv::ogl::Buffer::Impl::copyTo(GLsizeiptr size, GLvoid* data) const
2012-10-17 15:12:04 +08:00
{
gl::BindBuffer(gl::COPY_READ_BUFFER, bufId_);
CV_CheckGlError();
gl::GetBufferSubData(gl::COPY_READ_BUFFER, 0, size, data);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
}
void* cv::ogl::Buffer::Impl::mapHost(GLenum access)
2012-10-17 15:12:04 +08:00
{
gl::BindBuffer(gl::COPY_READ_BUFFER, bufId_);
CV_CheckGlError();
GLvoid* data = gl::MapBuffer(gl::COPY_READ_BUFFER, access);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
return data;
2012-10-17 15:12:04 +08:00
}
void cv::ogl::Buffer::Impl::unmapHost()
2012-10-17 15:12:04 +08:00
{
gl::UnmapBuffer(gl::COPY_READ_BUFFER);
2012-10-17 15:12:04 +08:00
}
#ifdef HAVE_CUDA
2013-04-15 18:17:18 +08:00
void cv::ogl::Buffer::Impl::copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream)
{
cudaResource_.registerBuffer(bufId_);
cudaResource_.copyFrom(src, spitch, width, height, stream);
}
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
void cv::ogl::Buffer::Impl::copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream) const
{
cudaResource_.registerBuffer(bufId_);
cudaResource_.copyTo(dst, dpitch, width, height, stream);
}
2012-10-17 15:12:04 +08:00
2013-04-15 18:17:18 +08:00
void* cv::ogl::Buffer::Impl::mapDevice(cudaStream_t stream)
{
cudaResource_.registerBuffer(bufId_);
return cudaResource_.map(stream);
}
void cv::ogl::Buffer::Impl::unmapDevice(cudaStream_t stream)
{
cudaResource_.unmap(stream);
}
#endif // HAVE_CUDA
2012-10-17 15:12:04 +08:00
#endif // HAVE_OPENGL
cv::ogl::Buffer::Buffer() : rows_(0), cols_(0), type_(0)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
impl_ = Impl::empty();
#endif
}
cv::ogl::Buffer::Buffer(int arows, int acols, int atype, unsigned int abufId, bool autoRelease) : rows_(0), cols_(0), type_(0)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arows;
(void) acols;
(void) atype;
(void) abufId;
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(abufId, autoRelease));
rows_ = arows;
cols_ = acols;
type_ = atype;
2012-10-17 15:12:04 +08:00
#endif
}
cv::ogl::Buffer::Buffer(Size asize, int atype, unsigned int abufId, bool autoRelease) : rows_(0), cols_(0), type_(0)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) asize;
(void) atype;
(void) abufId;
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(abufId, autoRelease));
rows_ = asize.height;
cols_ = asize.width;
type_ = atype;
2012-10-17 15:12:04 +08:00
#endif
}
cv::ogl::Buffer::Buffer(InputArray arr, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arr;
(void) target;
2012-12-03 17:27:20 +08:00
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
const int kind = arr.kind();
2012-10-17 15:12:04 +08:00
switch (kind)
2012-10-17 15:12:04 +08:00
{
case _InputArray::OPENGL_BUFFER:
case _InputArray::GPU_MAT:
2013-04-15 18:17:18 +08:00
copyFrom(arr, target, autoRelease);
break;
default:
{
Mat mat = arr.getMat();
CV_Assert( mat.isContinuous() );
const GLsizeiptr asize = mat.rows * mat.cols * mat.elemSize();
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(asize, mat.data, target, autoRelease));
rows_ = mat.rows;
cols_ = mat.cols;
type_ = mat.type();
break;
}
}
2012-10-17 15:12:04 +08:00
#endif
}
void cv::ogl::Buffer::create(int arows, int acols, int atype, Target target, bool autoRelease)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arows;
(void) acols;
(void) atype;
(void) target;
2012-12-03 17:27:20 +08:00
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
if (rows_ != arows || cols_ != acols || type_ != atype)
2012-10-17 15:12:04 +08:00
{
const GLsizeiptr asize = arows * acols * CV_ELEM_SIZE(atype);
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(asize, 0, target, autoRelease));
rows_ = arows;
cols_ = acols;
type_ = atype;
2012-10-17 15:12:04 +08:00
}
#endif
}
void cv::ogl::Buffer::release()
2012-10-17 15:12:04 +08:00
{
#ifdef HAVE_OPENGL
if (impl_)
impl_->setAutoRelease(true);
impl_ = Impl::empty();
rows_ = 0;
cols_ = 0;
type_ = 0;
#endif
}
void cv::ogl::Buffer::setAutoRelease(bool flag)
{
2012-10-17 15:12:04 +08:00
#ifndef HAVE_OPENGL
(void) flag;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
impl_->setAutoRelease(flag);
2012-10-17 15:12:04 +08:00
#endif
}
void cv::ogl::Buffer::copyFrom(InputArray arr, Target target, bool autoRelease)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arr;
(void) target;
2012-12-03 17:27:20 +08:00
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
const int kind = arr.kind();
const Size asize = arr.size();
const int atype = arr.type();
create(asize, atype, target, autoRelease);
switch (kind)
{
case _InputArray::OPENGL_BUFFER:
{
ogl::Buffer buf = arr.getOGlBuffer();
impl_->copyFrom(buf.bufId(), asize.area() * CV_ELEM_SIZE(atype));
break;
}
2012-10-17 15:12:04 +08:00
case _InputArray::GPU_MAT:
{
2013-04-15 18:17:18 +08:00
#ifndef HAVE_CUDA
throw_no_cuda();
#else
GpuMat dmat = arr.getGpuMat();
impl_->copyFrom(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows);
#endif
break;
}
default:
{
Mat mat = arr.getMat();
CV_Assert( mat.isContinuous() );
impl_->copyFrom(asize.area() * CV_ELEM_SIZE(atype), mat.data);
}
}
#endif
}
2013-08-28 19:45:13 +08:00
void cv::ogl::Buffer::copyFrom(InputArray arr, cuda::Stream& stream, Target target, bool autoRelease)
{
#ifndef HAVE_OPENGL
(void) arr;
2013-04-15 18:17:18 +08:00
(void) stream;
(void) target;
(void) autoRelease;
throw_no_ogl();
2013-04-15 18:17:18 +08:00
#else
#ifndef HAVE_CUDA
(void) arr;
(void) stream;
(void) target;
(void) autoRelease;
throw_no_cuda();
#else
GpuMat dmat = arr.getGpuMat();
create(dmat.size(), dmat.type(), target, autoRelease);
2013-08-28 19:45:13 +08:00
impl_->copyFrom(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows, cuda::StreamAccessor::getStream(stream));
2013-04-15 18:17:18 +08:00
#endif
#endif
}
void cv::ogl::Buffer::copyTo(OutputArray arr) const
{
#ifndef HAVE_OPENGL
(void) arr;
throw_no_ogl();
#else
const int kind = arr.kind();
2012-10-17 15:12:04 +08:00
switch (kind)
{
case _InputArray::OPENGL_BUFFER:
{
2013-04-15 18:17:18 +08:00
arr.getOGlBufferRef().copyFrom(*this);
break;
}
2012-10-17 15:12:04 +08:00
case _InputArray::GPU_MAT:
{
2013-04-15 18:17:18 +08:00
#ifndef HAVE_CUDA
throw_no_cuda();
2012-10-17 15:12:04 +08:00
#else
GpuMat& dmat = arr.getGpuMatRef();
dmat.create(rows_, cols_, type_);
impl_->copyTo(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows);
2012-10-17 15:12:04 +08:00
#endif
break;
}
2012-10-17 15:12:04 +08:00
default:
{
arr.create(rows_, cols_, type_);
Mat mat = arr.getMat();
CV_Assert( mat.isContinuous() );
impl_->copyTo(mat.rows * mat.cols * mat.elemSize(), mat.data);
2012-10-17 15:12:04 +08:00
}
}
#endif
}
2013-08-28 19:45:13 +08:00
void cv::ogl::Buffer::copyTo(OutputArray arr, cuda::Stream& stream) const
2013-04-15 18:17:18 +08:00
{
#ifndef HAVE_OPENGL
(void) arr;
(void) stream;
throw_no_ogl();
#else
#ifndef HAVE_CUDA
(void) arr;
(void) stream;
throw_no_cuda();
#else
arr.create(rows_, cols_, type_);
GpuMat dmat = arr.getGpuMat();
2013-08-28 19:45:13 +08:00
impl_->copyTo(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows, cuda::StreamAccessor::getStream(stream));
2013-04-15 18:17:18 +08:00
#endif
#endif
}
cv::ogl::Buffer cv::ogl::Buffer::clone(Target target, bool autoRelease) const
{
#ifndef HAVE_OPENGL
(void) target;
(void) autoRelease;
throw_no_ogl();
return cv::ogl::Buffer();
#else
ogl::Buffer buf;
buf.copyFrom(*this, target, autoRelease);
return buf;
#endif
}
void cv::ogl::Buffer::bind(Target target) const
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) target;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
impl_->bind(target);
2012-10-17 15:12:04 +08:00
#endif
}
void cv::ogl::Buffer::unbind(Target target)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) target;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
gl::BindBuffer(target, 0);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
#endif
}
Mat cv::ogl::Buffer::mapHost(Access access)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) access;
throw_no_ogl();
return Mat();
2012-10-17 15:12:04 +08:00
#else
return Mat(rows_, cols_, type_, impl_->mapHost(access));
2012-10-17 15:12:04 +08:00
#endif
}
void cv::ogl::Buffer::unmapHost()
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
return impl_->unmapHost();
2012-10-17 15:12:04 +08:00
#endif
}
GpuMat cv::ogl::Buffer::mapDevice()
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
throw_no_ogl();
return GpuMat();
2012-10-17 15:12:04 +08:00
#else
2013-04-15 18:17:18 +08:00
#ifndef HAVE_CUDA
throw_no_cuda();
return GpuMat();
2012-10-17 15:12:04 +08:00
#else
return GpuMat(rows_, cols_, type_, impl_->mapDevice());
2012-10-17 15:12:04 +08:00
#endif
#endif
}
void cv::ogl::Buffer::unmapDevice()
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
2013-04-15 18:17:18 +08:00
#ifndef HAVE_CUDA
throw_no_cuda();
2012-10-17 15:12:04 +08:00
#else
impl_->unmapDevice();
#endif
#endif
}
2013-08-28 19:45:13 +08:00
cuda::GpuMat cv::ogl::Buffer::mapDevice(cuda::Stream& stream)
2013-04-15 18:17:18 +08:00
{
#ifndef HAVE_OPENGL
(void) stream;
throw_no_ogl();
return GpuMat();
#else
#ifndef HAVE_CUDA
(void) stream;
throw_no_cuda();
return GpuMat();
#else
2013-08-28 19:45:13 +08:00
return GpuMat(rows_, cols_, type_, impl_->mapDevice(cuda::StreamAccessor::getStream(stream)));
2013-04-15 18:17:18 +08:00
#endif
#endif
}
2013-08-28 19:45:13 +08:00
void cv::ogl::Buffer::unmapDevice(cuda::Stream& stream)
2013-04-15 18:17:18 +08:00
{
#ifndef HAVE_OPENGL
(void) stream;
throw_no_ogl();
#else
#ifndef HAVE_CUDA
(void) stream;
throw_no_cuda();
#else
2013-08-28 19:45:13 +08:00
impl_->unmapDevice(cuda::StreamAccessor::getStream(stream));
2013-04-15 18:17:18 +08:00
#endif
#endif
}
unsigned int cv::ogl::Buffer::bufId() const
{
#ifndef HAVE_OPENGL
throw_no_ogl();
return 0;
#else
return impl_->bufId();
#endif
}
2012-10-17 15:12:04 +08:00
//////////////////////////////////////////////////////////////////////////////////////////
// ogl::Texture
2012-10-17 15:12:04 +08:00
#ifndef HAVE_OPENGL
class cv::ogl::Texture2D::Impl
2012-10-17 15:12:04 +08:00
{
};
#else
class cv::ogl::Texture2D::Impl
2012-10-17 15:12:04 +08:00
{
public:
static const Ptr<Impl> empty();
Impl(GLuint texId, bool autoRelease);
Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels, bool autoRelease);
2012-10-17 15:12:04 +08:00
~Impl();
void copyFrom(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
void copyTo(GLenum format, GLenum type, GLvoid* pixels) const;
2012-10-17 15:12:04 +08:00
void bind() const;
void setAutoRelease(bool flag) { autoRelease_ = flag; }
GLuint texId() const { return texId_; }
2012-10-17 15:12:04 +08:00
private:
Impl();
GLuint texId_;
bool autoRelease_;
2012-10-17 15:12:04 +08:00
};
const Ptr<cv::ogl::Texture2D::Impl> cv::ogl::Texture2D::Impl::empty()
2012-10-17 15:12:04 +08:00
{
static Ptr<Impl> p(new Impl);
return p;
}
2013-04-15 18:17:18 +08:00
cv::ogl::Texture2D::Impl::Impl() : texId_(0), autoRelease_(false)
2012-10-17 15:12:04 +08:00
{
}
cv::ogl::Texture2D::Impl::Impl(GLuint atexId, bool autoRelease) : texId_(atexId), autoRelease_(autoRelease)
2012-10-17 15:12:04 +08:00
{
2013-04-15 18:17:18 +08:00
CV_Assert( gl::IsTexture(atexId) == gl::TRUE_ );
2012-10-17 15:12:04 +08:00
}
cv::ogl::Texture2D::Impl::Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels, bool autoRelease) : texId_(0), autoRelease_(autoRelease)
2012-10-17 15:12:04 +08:00
{
gl::GenTextures(1, &texId_);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
CV_Assert(texId_ != 0);
2012-10-17 15:12:04 +08:00
gl::BindTexture(gl::TEXTURE_2D, texId_);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::TexImage2D(gl::TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, pixels);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::GenerateMipmap(gl::TEXTURE_2D);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
cv::ogl::Texture2D::Impl::~Impl()
2012-10-17 15:12:04 +08:00
{
if (autoRelease_ && texId_)
gl::DeleteTextures(1, &texId_);
2012-10-17 15:12:04 +08:00
}
void cv::ogl::Texture2D::Impl::copyFrom(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
2012-10-17 15:12:04 +08:00
{
gl::BindTexture(gl::TEXTURE_2D, texId_);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::TexSubImage2D(gl::TEXTURE_2D, 0, 0, 0, width, height, format, type, pixels);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::GenerateMipmap(gl::TEXTURE_2D);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
void cv::ogl::Texture2D::Impl::copyTo(GLenum format, GLenum type, GLvoid* pixels) const
2012-10-17 15:12:04 +08:00
{
gl::BindTexture(gl::TEXTURE_2D, texId_);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::PixelStorei(gl::PACK_ALIGNMENT, 1);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::GetTexImage(gl::TEXTURE_2D, 0, format, type, pixels);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
void cv::ogl::Texture2D::Impl::bind() const
2012-10-17 15:12:04 +08:00
{
gl::BindTexture(gl::TEXTURE_2D, texId_);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
}
#endif // HAVE_OPENGL
cv::ogl::Texture2D::Texture2D() : rows_(0), cols_(0), format_(NONE)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
impl_ = Impl::empty();
#endif
}
cv::ogl::Texture2D::Texture2D(int arows, int acols, Format aformat, unsigned int atexId, bool autoRelease) : rows_(0), cols_(0), format_(NONE)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arows;
(void) acols;
(void) aformat;
(void) atexId;
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(atexId, autoRelease));
rows_ = arows;
cols_ = acols;
format_ = aformat;
2012-10-17 15:12:04 +08:00
#endif
}
cv::ogl::Texture2D::Texture2D(Size asize, Format aformat, unsigned int atexId, bool autoRelease) : rows_(0), cols_(0), format_(NONE)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) asize;
(void) aformat;
(void) atexId;
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(atexId, autoRelease));
rows_ = asize.height;
cols_ = asize.width;
format_ = aformat;
2012-10-17 15:12:04 +08:00
#endif
}
cv::ogl::Texture2D::Texture2D(InputArray arr, bool autoRelease) : rows_(0), cols_(0), format_(NONE)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arr;
2012-12-03 17:27:20 +08:00
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
const int kind = arr.kind();
const Size asize = arr.size();
const int atype = arr.type();
const int depth = CV_MAT_DEPTH(atype);
const int cn = CV_MAT_CN(atype);
CV_Assert( depth <= CV_32F );
CV_Assert( cn == 1 || cn == 3 || cn == 4 );
const Format internalFormats[] =
{
NONE, DEPTH_COMPONENT, NONE, RGB, RGBA
};
const GLenum srcFormats[] =
{
0, gl::DEPTH_COMPONENT, 0, gl::BGR, gl::BGRA
};
2012-10-17 15:12:04 +08:00
switch (kind)
{
case _InputArray::OPENGL_BUFFER:
{
ogl::Buffer buf = arr.getOGlBuffer();
buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease));
ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
2012-10-17 15:12:04 +08:00
break;
}
2012-10-17 15:12:04 +08:00
case _InputArray::GPU_MAT:
{
2013-04-15 18:17:18 +08:00
#ifndef HAVE_CUDA
throw_no_cuda();
2012-10-17 15:12:04 +08:00
#else
GpuMat dmat = arr.getGpuMat();
ogl::Buffer buf(dmat, ogl::Buffer::PIXEL_UNPACK_BUFFER);
2013-11-19 14:12:22 +08:00
buf.setAutoRelease(true);
buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease));
ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
2012-10-17 15:12:04 +08:00
#endif
break;
}
2012-10-17 15:12:04 +08:00
default:
{
Mat mat = arr.getMat();
CV_Assert( mat.isContinuous() );
ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data, autoRelease));
2012-10-17 15:12:04 +08:00
break;
}
}
rows_ = asize.height;
cols_ = asize.width;
format_ = internalFormats[cn];
2012-10-17 15:12:04 +08:00
#endif
}
void cv::ogl::Texture2D::create(int arows, int acols, Format aformat, bool autoRelease)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arows;
(void) acols;
(void) aformat;
2012-12-03 17:27:20 +08:00
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
if (rows_ != arows || cols_ != acols || format_ != aformat)
2012-10-17 15:12:04 +08:00
{
ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
2013-09-06 19:52:07 +08:00
impl_.reset(new Impl(aformat, acols, arows, aformat, gl::FLOAT, 0, autoRelease));
rows_ = arows;
cols_ = acols;
format_ = aformat;
2012-10-17 15:12:04 +08:00
}
#endif
}
void cv::ogl::Texture2D::release()
{
#ifdef HAVE_OPENGL
if (impl_)
impl_->setAutoRelease(true);
impl_ = Impl::empty();
rows_ = 0;
cols_ = 0;
format_ = NONE;
#endif
}
void cv::ogl::Texture2D::setAutoRelease(bool flag)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) flag;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
impl_->setAutoRelease(flag);
2012-10-17 15:12:04 +08:00
#endif
}
void cv::ogl::Texture2D::copyFrom(InputArray arr, bool autoRelease)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arr;
2012-12-03 17:27:20 +08:00
(void) autoRelease;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
const int kind = arr.kind();
const Size asize = arr.size();
const int atype = arr.type();
2012-10-17 15:12:04 +08:00
const int depth = CV_MAT_DEPTH(atype);
const int cn = CV_MAT_CN(atype);
CV_Assert( depth <= CV_32F );
CV_Assert( cn == 1 || cn == 3 || cn == 4 );
const Format internalFormats[] =
{
NONE, DEPTH_COMPONENT, NONE, RGB, RGBA
};
const GLenum srcFormats[] =
{
0, gl::DEPTH_COMPONENT, 0, gl::BGR, gl::BGRA
};
create(asize, internalFormats[cn], autoRelease);
2012-10-17 15:12:04 +08:00
switch(kind)
{
case _InputArray::OPENGL_BUFFER:
2012-10-17 15:12:04 +08:00
{
ogl::Buffer buf = arr.getOGlBuffer();
buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
impl_->copyFrom(asize.width, asize.height, srcFormats[cn], gl_types[depth], 0);
ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
2012-10-17 15:12:04 +08:00
break;
}
case _InputArray::GPU_MAT:
{
2013-04-15 18:17:18 +08:00
#ifndef HAVE_CUDA
throw_no_cuda();
#else
GpuMat dmat = arr.getGpuMat();
ogl::Buffer buf(dmat, ogl::Buffer::PIXEL_UNPACK_BUFFER);
2013-11-19 14:12:22 +08:00
buf.setAutoRelease(true);
buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
impl_->copyFrom(asize.width, asize.height, srcFormats[cn], gl_types[depth], 0);
ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
#endif
break;
}
default:
{
Mat mat = arr.getMat();
CV_Assert( mat.isContinuous() );
ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);
impl_->copyFrom(asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data);
}
}
#endif
}
void cv::ogl::Texture2D::copyTo(OutputArray arr, int ddepth, bool autoRelease) const
{
#ifndef HAVE_OPENGL
(void) arr;
(void) ddepth;
(void) autoRelease;
throw_no_ogl();
#else
const int kind = arr.kind();
const int cn = format_ == DEPTH_COMPONENT ? 1: format_ == RGB ? 3 : 4;
const GLenum dstFormat = format_ == DEPTH_COMPONENT ? gl::DEPTH_COMPONENT : format_ == RGB ? gl::BGR : gl::BGRA;
switch(kind)
{
2012-10-17 15:12:04 +08:00
case _InputArray::OPENGL_BUFFER:
{
ogl::Buffer& buf = arr.getOGlBufferRef();
buf.create(rows_, cols_, CV_MAKE_TYPE(ddepth, cn), ogl::Buffer::PIXEL_PACK_BUFFER, autoRelease);
buf.bind(ogl::Buffer::PIXEL_PACK_BUFFER);
impl_->copyTo(dstFormat, gl_types[ddepth], 0);
ogl::Buffer::unbind(ogl::Buffer::PIXEL_PACK_BUFFER);
2012-10-17 15:12:04 +08:00
break;
}
2012-10-17 15:12:04 +08:00
case _InputArray::GPU_MAT:
{
2013-04-15 18:17:18 +08:00
#ifndef HAVE_CUDA
throw_no_cuda();
2012-10-17 15:12:04 +08:00
#else
ogl::Buffer buf(rows_, cols_, CV_MAKE_TYPE(ddepth, cn), ogl::Buffer::PIXEL_PACK_BUFFER);
2013-11-19 14:12:22 +08:00
buf.setAutoRelease(true);
buf.bind(ogl::Buffer::PIXEL_PACK_BUFFER);
impl_->copyTo(dstFormat, gl_types[ddepth], 0);
ogl::Buffer::unbind(ogl::Buffer::PIXEL_PACK_BUFFER);
buf.copyTo(arr);
2012-10-17 15:12:04 +08:00
#endif
break;
}
2012-10-17 15:12:04 +08:00
default:
{
arr.create(rows_, cols_, CV_MAKE_TYPE(ddepth, cn));
Mat mat = arr.getMat();
CV_Assert( mat.isContinuous() );
ogl::Buffer::unbind(ogl::Buffer::PIXEL_PACK_BUFFER);
impl_->copyTo(dstFormat, gl_types[ddepth], mat.data);
2012-10-17 15:12:04 +08:00
}
}
#endif
}
void cv::ogl::Texture2D::bind() const
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
impl_->bind();
#endif
}
unsigned int cv::ogl::Texture2D::texId() const
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
throw_no_ogl();
return 0;
2012-10-17 15:12:04 +08:00
#else
return impl_->texId();
2012-10-17 15:12:04 +08:00
#endif
}
////////////////////////////////////////////////////////////////////////
// ogl::Arrays
2012-10-17 15:12:04 +08:00
void cv::ogl::Arrays::setVertexArray(InputArray vertex)
2012-10-17 15:12:04 +08:00
{
const int cn = vertex.channels();
const 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 );
2012-10-17 15:12:04 +08:00
if (vertex.kind() == _InputArray::OPENGL_BUFFER)
vertex_ = vertex.getOGlBuffer();
else
vertex_.copyFrom(vertex);
size_ = vertex_.size().area();
}
2012-10-17 15:12:04 +08:00
void cv::ogl::Arrays::resetVertexArray()
{
vertex_.release();
size_ = 0;
2012-10-17 15:12:04 +08:00
}
void cv::ogl::Arrays::setColorArray(InputArray color)
2012-10-17 15:12:04 +08:00
{
const int cn = color.channels();
CV_Assert( cn == 3 || cn == 4 );
2012-10-17 15:12:04 +08:00
if (color.kind() == _InputArray::OPENGL_BUFFER)
color_ = color.getOGlBuffer();
else
color_.copyFrom(color);
}
2012-10-17 15:12:04 +08:00
void cv::ogl::Arrays::resetColorArray()
{
color_.release();
2012-10-17 15:12:04 +08:00
}
void cv::ogl::Arrays::setNormalArray(InputArray normal)
2012-10-17 15:12:04 +08:00
{
const int cn = normal.channels();
const int depth = normal.depth();
2012-10-17 15:12:04 +08:00
CV_Assert( cn == 3 );
CV_Assert( depth == CV_8S || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F );
2012-10-17 15:12:04 +08:00
if (normal.kind() == _InputArray::OPENGL_BUFFER)
normal_ = normal.getOGlBuffer();
else
normal_.copyFrom(normal);
}
void cv::ogl::Arrays::resetNormalArray()
{
normal_.release();
2012-10-17 15:12:04 +08:00
}
void cv::ogl::Arrays::setTexCoordArray(InputArray texCoord)
2012-10-17 15:12:04 +08:00
{
const int cn = texCoord.channels();
const int depth = texCoord.depth();
2012-10-17 15:12:04 +08:00
CV_Assert( cn >= 1 && cn <= 4 );
CV_Assert( depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F );
2012-10-17 15:12:04 +08:00
if (texCoord.kind() == _InputArray::OPENGL_BUFFER)
texCoord_ = texCoord.getOGlBuffer();
else
texCoord_.copyFrom(texCoord);
}
void cv::ogl::Arrays::resetTexCoordArray()
{
texCoord_.release();
}
void cv::ogl::Arrays::release()
{
resetVertexArray();
resetColorArray();
resetNormalArray();
resetTexCoordArray();
}
void cv::ogl::Arrays::setAutoRelease(bool flag)
{
vertex_.setAutoRelease(flag);
color_.setAutoRelease(flag);
normal_.setAutoRelease(flag);
texCoord_.setAutoRelease(flag);
2012-10-17 15:12:04 +08:00
}
void cv::ogl::Arrays::bind() const
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
CV_Assert( texCoord_.empty() || texCoord_.size().area() == size_ );
CV_Assert( normal_.empty() || normal_.size().area() == size_ );
CV_Assert( color_.empty() || color_.size().area() == size_ );
2012-10-17 15:12:04 +08:00
if (texCoord_.empty())
2012-10-17 15:12:04 +08:00
{
gl::DisableClientState(gl::TEXTURE_COORD_ARRAY);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
else
2012-10-17 15:12:04 +08:00
{
gl::EnableClientState(gl::TEXTURE_COORD_ARRAY);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
texCoord_.bind(ogl::Buffer::ARRAY_BUFFER);
2012-10-17 15:12:04 +08:00
gl::TexCoordPointer(texCoord_.channels(), gl_types[texCoord_.depth()], 0, 0);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
if (normal_.empty())
2012-10-17 15:12:04 +08:00
{
gl::DisableClientState(gl::NORMAL_ARRAY);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
else
2012-10-17 15:12:04 +08:00
{
gl::EnableClientState(gl::NORMAL_ARRAY);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
normal_.bind(ogl::Buffer::ARRAY_BUFFER);
2012-10-17 15:12:04 +08:00
gl::NormalPointer(gl_types[normal_.depth()], 0, 0);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
if (color_.empty())
2012-10-17 15:12:04 +08:00
{
gl::DisableClientState(gl::COLOR_ARRAY);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
else
2012-10-17 15:12:04 +08:00
{
gl::EnableClientState(gl::COLOR_ARRAY);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
color_.bind(ogl::Buffer::ARRAY_BUFFER);
2012-10-17 15:12:04 +08:00
const int cn = color_.channels();
gl::ColorPointer(cn, gl_types[color_.depth()], 0, 0);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
if (vertex_.empty())
2012-10-17 15:12:04 +08:00
{
gl::DisableClientState(gl::VERTEX_ARRAY);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
}
else
2012-10-17 15:12:04 +08:00
{
gl::EnableClientState(gl::VERTEX_ARRAY);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
vertex_.bind(ogl::Buffer::ARRAY_BUFFER);
2012-10-17 15:12:04 +08:00
gl::VertexPointer(vertex_.channels(), gl_types[vertex_.depth()], 0, 0);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
}
ogl::Buffer::unbind(ogl::Buffer::ARRAY_BUFFER);
2012-10-17 15:12:04 +08:00
#endif
}
////////////////////////////////////////////////////////////////////////
// Rendering
void cv::ogl::render(const ogl::Texture2D& tex, Rect_<double> wndRect, Rect_<double> texRect)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) tex;
(void) wndRect;
(void) texRect;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
if (!tex.empty())
{
gl::MatrixMode(gl::PROJECTION);
gl::LoadIdentity();
gl::Ortho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0);
CV_CheckGlError();
gl::MatrixMode(gl::MODELVIEW);
gl::LoadIdentity();
CV_CheckGlError();
gl::Disable(gl::LIGHTING);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
tex.bind();
gl::Enable(gl::TEXTURE_2D);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::TexEnvi(gl::TEXTURE_ENV, gl::TEXTURE_ENV_MODE, gl::REPLACE);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
const float vertex[] =
{
wndRect.x, wndRect.y, 0.0f,
wndRect.x, (wndRect.y + wndRect.height), 0.0f,
wndRect.x + wndRect.width, (wndRect.y + wndRect.height), 0.0f,
wndRect.x + wndRect.width, wndRect.y, 0.0f
};
const float texCoords[] =
{
texRect.x, texRect.y,
texRect.x, texRect.y + texRect.height,
texRect.x + texRect.width, texRect.y + texRect.height,
texRect.x + texRect.width, texRect.y
};
2012-10-17 15:12:04 +08:00
ogl::Buffer::unbind(ogl::Buffer::ARRAY_BUFFER);
2012-10-17 15:12:04 +08:00
gl::EnableClientState(gl::TEXTURE_COORD_ARRAY);
2012-10-17 15:12:04 +08:00
CV_CheckGlError();
gl::TexCoordPointer(2, gl::FLOAT, 0, texCoords);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::DisableClientState(gl::NORMAL_ARRAY);
gl::DisableClientState(gl::COLOR_ARRAY);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::EnableClientState(gl::VERTEX_ARRAY);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::VertexPointer(3, gl::FLOAT, 0, vertex);
CV_CheckGlError();
2012-10-17 15:12:04 +08:00
gl::DrawArrays(gl::QUADS, 0, 4);
CV_CheckGlError();
}
2012-10-17 15:12:04 +08:00
#endif
}
void cv::ogl::render(const ogl::Arrays& arr, int mode, Scalar color)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arr;
(void) mode;
(void) color;
throw_no_ogl();
2012-10-17 15:12:04 +08:00
#else
if (!arr.empty())
{
gl::Color3d(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0);
2012-10-17 15:12:04 +08:00
arr.bind();
2012-10-17 15:12:04 +08:00
gl::DrawArrays(mode, 0, arr.size());
}
2012-10-17 15:12:04 +08:00
#endif
}
void cv::ogl::render(const ogl::Arrays& arr, InputArray indices, int mode, Scalar color)
2012-10-17 15:12:04 +08:00
{
#ifndef HAVE_OPENGL
(void) arr;
(void) indices;
(void) mode;
(void) color;
throw_no_ogl();
#else
if (!arr.empty() && !indices.empty())
{
gl::Color3d(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0);
2012-10-17 15:12:04 +08:00
arr.bind();
2012-10-17 15:12:04 +08:00
const int kind = indices.kind();
2012-10-17 15:12:04 +08:00
switch (kind)
{
case _InputArray::OPENGL_BUFFER :
{
ogl::Buffer buf = indices.getOGlBuffer();
2012-10-17 15:12:04 +08:00
const int depth = buf.depth();
2012-10-17 15:12:04 +08:00
CV_Assert( buf.channels() == 1 );
CV_Assert( depth <= CV_32S );
2012-10-17 15:12:04 +08:00
GLenum type;
if (depth < CV_16U)
type = gl::UNSIGNED_BYTE;
else if (depth < CV_32S)
type = gl::UNSIGNED_SHORT;
else
type = gl::UNSIGNED_INT;
2012-10-17 15:12:04 +08:00
buf.bind(ogl::Buffer::ELEMENT_ARRAY_BUFFER);
2012-10-17 15:12:04 +08:00
gl::DrawElements(mode, buf.size().area(), type, 0);
2012-10-17 15:12:04 +08:00
ogl::Buffer::unbind(ogl::Buffer::ELEMENT_ARRAY_BUFFER);
2012-10-17 15:12:04 +08:00
break;
}
2012-10-17 15:12:04 +08:00
default:
{
Mat mat = indices.getMat();
2012-10-17 15:12:04 +08:00
const int depth = mat.depth();
2012-10-17 15:12:04 +08:00
CV_Assert( mat.channels() == 1 );
CV_Assert( depth <= CV_32S );
CV_Assert( mat.isContinuous() );
2012-10-17 15:12:04 +08:00
GLenum type;
if (depth < CV_16U)
type = gl::UNSIGNED_BYTE;
else if (depth < CV_32S)
type = gl::UNSIGNED_SHORT;
else
type = gl::UNSIGNED_INT;
2012-10-17 15:12:04 +08:00
ogl::Buffer::unbind(ogl::Buffer::ELEMENT_ARRAY_BUFFER);
2012-10-17 15:12:04 +08:00
gl::DrawElements(mode, mat.size().area(), type, mat.data);
}
}
2012-10-17 15:12:04 +08:00
}
#endif
}