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"
|
|
|
|
#include "opencv2/core/opengl_interop.hpp"
|
|
|
|
#include "opencv2/core/gpumat.hpp"
|
|
|
|
|
|
|
|
#ifdef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
#include "gl_core_3_1.hpp"
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
#ifdef HAVE_CUDA
|
|
|
|
#include <cuda_runtime.h>
|
|
|
|
#include <cuda_gl_interop.h>
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace cv;
|
|
|
|
using namespace cv::gpu;
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
#ifndef HAVE_CUDA
|
|
|
|
void throw_nocuda() { CV_Error(CV_GpuNotSupported, "The library is compiled without GPU support"); }
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
void throw_nocuda() { CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform"); }
|
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
#if defined(__GNUC__)
|
|
|
|
#define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__, __func__)
|
|
|
|
#else /* defined(__CUDACC__) || defined(__MSVC__) */
|
|
|
|
#define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__)
|
|
|
|
#endif
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void ___cudaSafeCall(cudaError_t err, const char* file, const int line, const char* func = "")
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
if (cudaSuccess != err)
|
|
|
|
cv::gpu::error(cudaGetErrorString(err), file, line, func);
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
#endif
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
#ifndef HAVE_OPENGL
|
|
|
|
void throw_nogl() { CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); }
|
|
|
|
#else
|
|
|
|
void throw_nogl() { CV_Error(CV_OpenGlApiCallError, "OpenGL context doesn't exist"); }
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cv::checkGlError(const char* file, const int line, const char* func)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
#ifndef HAVE_OPENGL
|
|
|
|
(void) file;
|
|
|
|
(void) line;
|
|
|
|
(void) func;
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
GLenum err = gl::GetError();
|
|
|
|
|
|
|
|
if (err != gl::NO_ERROR_)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
const char* msg;
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
case gl::INVALID_VALUE:
|
|
|
|
msg = "A numeric argument is out of range";
|
|
|
|
break;
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
default:
|
|
|
|
msg = "Unknown error";
|
|
|
|
};
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cvError(CV_OpenGlApiCallError, func, msg, file, line);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
return false;
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
return true;
|
|
|
|
#endif
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
#ifdef HAVE_OPENGL
|
|
|
|
namespace
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +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
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
#endif
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// setGlDevice
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
void cv::gpu::setGlDevice(int device)
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
#if !defined(HAVE_CUDA) || defined(CUDA_DISABLER)
|
|
|
|
(void) device;
|
|
|
|
throw_nocuda();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) device;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
|
|
|
cudaSafeCall( cudaGLSetGLDevice(device) );
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2012-11-30 21:35:28 +08:00
|
|
|
// CudaResource
|
|
|
|
|
|
|
|
#if defined(HAVE_OPENGL) && defined(HAVE_CUDA) && !defined(CUDA_DISABLER)
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
class CudaResource
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
public:
|
2012-11-30 21:35:28 +08:00
|
|
|
CudaResource();
|
|
|
|
~CudaResource();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void registerBuffer(GLuint buffer);
|
|
|
|
void release();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +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_;
|
2012-11-30 21:35:28 +08:00
|
|
|
GLuint buffer_;
|
|
|
|
|
|
|
|
class GraphicsMapHolder;
|
2012-10-17 15:12:04 +08:00
|
|
|
};
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
CudaResource::CudaResource() : resource_(0), buffer_(0)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
CudaResource::~CudaResource()
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
release();
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void CudaResource::registerBuffer(GLuint buffer)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
CV_DbgAssert( buffer != 0 );
|
|
|
|
|
|
|
|
if (buffer_ == buffer)
|
|
|
|
return;
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
cudaGraphicsResource_t resource;
|
|
|
|
cudaSafeCall( cudaGraphicsGLRegisterBuffer(&resource, buffer, cudaGraphicsMapFlagsNone) );
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
release();
|
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
resource_ = resource;
|
2012-11-30 21:35:28 +08:00
|
|
|
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_)
|
|
|
|
cudaSafeCall( cudaGraphicsMapResources(1, resource_, stream_) );
|
|
|
|
}
|
|
|
|
|
|
|
|
CudaResource::GraphicsMapHolder::~GraphicsMapHolder()
|
|
|
|
{
|
|
|
|
if (resource_)
|
|
|
|
cudaGraphicsUnmapResources(1, resource_, stream_);
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void CudaResource::GraphicsMapHolder::reset()
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
resource_ = 0;
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
GraphicsMapHolder h(&resource_, stream);
|
|
|
|
(void) h;
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void* dst;
|
|
|
|
size_t size;
|
|
|
|
cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&dst, &size, resource_) );
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
CV_DbgAssert( width * height == size );
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
if (stream == 0)
|
2012-11-30 21:35:28 +08:00
|
|
|
cudaSafeCall( cudaMemcpy2D(dst, width, src, spitch, width, height, cudaMemcpyDeviceToDevice) );
|
2012-10-17 15:12:04 +08:00
|
|
|
else
|
2012-11-30 21:35:28 +08:00
|
|
|
cudaSafeCall( cudaMemcpy2DAsync(dst, width, src, spitch, width, height, cudaMemcpyDeviceToDevice, stream) );
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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;
|
|
|
|
cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&src, &size, resource_) );
|
|
|
|
|
|
|
|
CV_DbgAssert( width * height == size );
|
|
|
|
|
|
|
|
if (stream == 0)
|
|
|
|
cudaSafeCall( cudaMemcpy2D(dst, dpitch, src, width, width, height, cudaMemcpyDeviceToDevice) );
|
|
|
|
else
|
|
|
|
cudaSafeCall( cudaMemcpy2DAsync(dst, dpitch, src, width, width, height, cudaMemcpyDeviceToDevice, stream) );
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void* CudaResource::map(cudaStream_t stream)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
CV_DbgAssert( resource_ != 0 );
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
GraphicsMapHolder h(&resource_, stream);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
void* ptr;
|
2012-11-30 21:35:28 +08:00
|
|
|
size_t size;
|
|
|
|
cudaSafeCall( cudaGraphicsResourceGetMappedPointer(&ptr, &size, resource_) );
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
h.reset();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
return ptr;
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void CudaResource::unmap(cudaStream_t stream)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
CV_Assert( resource_ != 0 );
|
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
cudaGraphicsUnmapResources(1, &resource_, stream);
|
|
|
|
}
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
|
|
|
|
#endif
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// GlBuffer
|
|
|
|
|
|
|
|
#ifndef HAVE_OPENGL
|
|
|
|
|
|
|
|
class cv::GlBuffer::Impl
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
class cv::GlBuffer::Impl
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const Ptr<Impl>& empty();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
Impl(GLuint bufId, bool autoRelease);
|
|
|
|
Impl(GLsizeiptr size, const GLvoid* data, GLenum target);
|
2012-10-17 15:12:04 +08:00
|
|
|
~Impl();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void bind(GLenum target) const;
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void copyFrom(GLuint srcBuf, GLsizeiptr size);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void copyFrom(GLsizeiptr size, const GLvoid* data);
|
|
|
|
void copyTo(GLsizeiptr size, GLvoid* data) const;
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void* mapHost();
|
|
|
|
void unmapHost();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
#ifdef HAVE_CUDA
|
2012-11-30 21:35:28 +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) const;
|
|
|
|
|
|
|
|
void* mapDevice(cudaStream_t stream = 0);
|
2012-10-17 15:12:04 +08:00
|
|
|
void unmapDevice(cudaStream_t stream = 0);
|
|
|
|
#endif
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void setAutoRelease(bool flag) { autoRelease_ = flag; }
|
|
|
|
|
|
|
|
GLuint bufId() const { return bufId_; }
|
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
private:
|
|
|
|
Impl();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
GLuint bufId_;
|
|
|
|
bool autoRelease_;
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
#ifdef HAVE_CUDA
|
2012-11-30 21:35:28 +08:00
|
|
|
mutable CudaResource cudaResource_;
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
const Ptr<cv::GlBuffer::Impl>& cv::GlBuffer::Impl::empty()
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
static Ptr<Impl> p(new Impl);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlBuffer::Impl::Impl() : bufId_(0), autoRelease_(true)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlBuffer::Impl::Impl(GLuint abufId, bool autoRelease) : bufId_(abufId), autoRelease_(autoRelease)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlBuffer::Impl::Impl(GLsizeiptr size, const GLvoid* data, GLenum target) : bufId_(0), autoRelease_(true)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::GenBuffers(1, &bufId_);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
CV_Assert( bufId_ != 0 );
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindBuffer(target, bufId_);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BufferData(target, size, data, gl::DYNAMIC_DRAW);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindBuffer(target, 0);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
cv::GlBuffer::Impl::~Impl()
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
if (autoRelease_ && bufId_)
|
|
|
|
gl::DeleteBuffers(1, &bufId_);
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::Impl::bind(GLenum target) const
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindBuffer(target, bufId_);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::Impl::copyFrom(GLuint srcBuf, GLsizeiptr size)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindBuffer(gl::COPY_WRITE_BUFFER, bufId_);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindBuffer(gl::COPY_READ_BUFFER, srcBuf);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::Impl::copyFrom(GLsizeiptr size, const GLvoid* data)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindBuffer(gl::COPY_WRITE_BUFFER, bufId_);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BufferSubData(gl::COPY_WRITE_BUFFER, 0, size, data);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::Impl::copyTo(GLsizeiptr size, GLvoid* data) const
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +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
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void* cv::GlBuffer::Impl::mapHost()
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindBuffer(gl::COPY_READ_BUFFER, bufId_);
|
|
|
|
CV_CheckGlError();
|
|
|
|
|
|
|
|
GLvoid* data = gl::MapBuffer(gl::COPY_READ_BUFFER, gl::READ_WRITE);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
return data;
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::Impl::unmapHost()
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::UnmapBuffer(gl::COPY_READ_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_CUDA
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void* cv::GlBuffer::Impl::mapDevice(cudaStream_t stream)
|
|
|
|
{
|
|
|
|
cudaResource_.registerBuffer(bufId_);
|
|
|
|
return cudaResource_.map(stream);
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::Impl::unmapDevice(cudaStream_t stream)
|
|
|
|
{
|
|
|
|
cudaResource_.unmap(stream);
|
|
|
|
}
|
|
|
|
#endif
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
#endif // HAVE_OPENGL
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlBuffer::GlBuffer() : rows_(0), cols_(0), type_(0)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
|
|
|
impl_ = Impl::empty();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlBuffer::GlBuffer(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
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) arows;
|
|
|
|
(void) acols;
|
|
|
|
(void) atype;
|
|
|
|
(void) abufId;
|
|
|
|
(void) autoRelease;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
impl_ = new Impl(abufId, autoRelease);
|
|
|
|
rows_ = arows;
|
|
|
|
cols_ = acols;
|
|
|
|
type_ = atype;
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlBuffer::GlBuffer(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
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) asize;
|
|
|
|
(void) atype;
|
|
|
|
(void) abufId;
|
|
|
|
(void) autoRelease;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
impl_ = new Impl(abufId, autoRelease);
|
|
|
|
rows_ = asize.height;
|
|
|
|
cols_ = asize.width;
|
|
|
|
type_ = atype;
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlBuffer::GlBuffer(int arows, int acols, int atype, Target target) : rows_(0), cols_(0), type_(0)
|
|
|
|
{
|
|
|
|
create(arows, acols, atype, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::GlBuffer::GlBuffer(Size asize, int atype, Target target) : rows_(0), cols_(0), type_(0)
|
|
|
|
{
|
|
|
|
create(asize, atype, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::GlBuffer::GlBuffer(InputArray arr, Target target) : rows_(0), cols_(0), type_(0)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) arr;
|
|
|
|
(void) target;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
const int kind = arr.kind();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
switch (kind)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
case _InputArray::OPENGL_BUFFER:
|
|
|
|
{
|
|
|
|
copyFrom(arr, target);
|
|
|
|
break;
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
case _InputArray::OPENGL_TEXTURE2D:
|
|
|
|
{
|
|
|
|
copyFrom(arr, target);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case _InputArray::GPU_MAT:
|
|
|
|
{
|
|
|
|
copyFrom(arr, target);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
Mat mat = arr.getMat();
|
|
|
|
CV_Assert( mat.isContinuous() );
|
|
|
|
const GLsizeiptr asize = mat.rows * mat.cols * mat.elemSize();
|
|
|
|
impl_ = new Impl(asize, mat.data, target);
|
|
|
|
rows_ = mat.rows;
|
|
|
|
cols_ = mat.cols;
|
|
|
|
type_ = mat.type();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::create(int arows, int acols, int atype, Target target)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) arows;
|
|
|
|
(void) acols;
|
|
|
|
(void) atype;
|
|
|
|
(void) target;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
if (rows_ != arows || cols_ != acols || type_ != atype)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
const GLsizeiptr asize = arows * acols * CV_ELEM_SIZE(atype);
|
|
|
|
impl_ = new Impl(asize, 0, target);
|
|
|
|
rows_ = arows;
|
|
|
|
cols_ = acols;
|
|
|
|
type_ = atype;
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlBuffer::release()
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
#ifdef HAVE_OPENGL
|
|
|
|
impl_ = Impl::empty();
|
|
|
|
rows_ = 0;
|
|
|
|
cols_ = 0;
|
|
|
|
type_ = 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlBuffer::setAutoRelease(bool flag)
|
|
|
|
{
|
2012-10-17 15:12:04 +08:00
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) flag;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
impl_->setAutoRelease(flag);
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::copyFrom(InputArray arr, Target target)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) arr;
|
|
|
|
(void) target;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
const int kind = arr.kind();
|
|
|
|
|
|
|
|
if (kind == _InputArray::OPENGL_TEXTURE2D)
|
|
|
|
{
|
|
|
|
GlTexture2D tex = arr.getGlTexture2D();
|
|
|
|
tex.copyTo(*this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Size asize = arr.size();
|
|
|
|
const int atype = arr.type();
|
|
|
|
create(asize, atype, target);
|
|
|
|
|
|
|
|
switch (kind)
|
|
|
|
{
|
|
|
|
case _InputArray::OPENGL_BUFFER:
|
|
|
|
{
|
|
|
|
GlBuffer buf = arr.getGlBuffer();
|
|
|
|
impl_->copyFrom(buf.bufId(), asize.area() * CV_ELEM_SIZE(atype));
|
|
|
|
break;
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
case _InputArray::GPU_MAT:
|
|
|
|
{
|
|
|
|
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
|
|
|
throw_nocuda();
|
|
|
|
#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
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlBuffer::copyTo(OutputArray arr, Target target) const
|
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
|
|
|
(void) arr;
|
|
|
|
(void) target;
|
|
|
|
throw_nogl();
|
|
|
|
#else
|
|
|
|
const int kind = arr.kind();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
switch (kind)
|
|
|
|
{
|
|
|
|
case _InputArray::OPENGL_BUFFER:
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
arr.getGlBufferRef().copyFrom(*this, target);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case _InputArray::OPENGL_TEXTURE2D:
|
|
|
|
{
|
|
|
|
arr.getGlTexture2DRef().copyFrom(*this);
|
2012-10-17 15:12:04 +08:00
|
|
|
break;
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
case _InputArray::GPU_MAT:
|
|
|
|
{
|
|
|
|
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nocuda();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
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-11-30 21:35:28 +08:00
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
default:
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer cv::GlBuffer::clone(Target target) const
|
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
|
|
|
(void) target;
|
|
|
|
throw_nogl();
|
|
|
|
return GlBuffer();
|
|
|
|
#else
|
|
|
|
GlBuffer buf;
|
|
|
|
buf.copyFrom(*this, target);
|
|
|
|
return buf;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlBuffer::bind(Target target) const
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) target;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
impl_->bind(target);
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlBuffer::unbind(Target target)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) target;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindBuffer(target, 0);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
Mat cv::GlBuffer::mapHost()
|
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
return Mat();
|
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
return Mat(rows_, cols_, type_, impl_->mapHost());
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlBuffer::unmapHost()
|
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
return impl_->unmapHost();
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
GpuMat cv::GlBuffer::mapDevice()
|
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
return GpuMat();
|
|
|
|
#else
|
|
|
|
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nocuda();
|
2012-10-17 15:12:04 +08:00
|
|
|
return GpuMat();
|
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
return GpuMat(rows_, cols_, type_, impl_->mapDevice());
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlBuffer::unmapDevice()
|
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
|
|
|
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nocuda();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
|
|
|
impl_->unmapDevice();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
unsigned int cv::GlBuffer::bufId() const
|
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
|
|
|
throw_nogl();
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
return impl_->bufId();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
template <> void cv::Ptr<cv::GlBuffer::Impl>::delete_obj()
|
|
|
|
{
|
|
|
|
if (obj) delete obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2012-11-30 21:35:28 +08:00
|
|
|
// GlTexture2D
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
#ifndef HAVE_OPENGL
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
class cv::GlTexture2D::Impl
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
class cv::GlTexture2D::Impl
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const Ptr<Impl> empty();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
Impl(GLuint texId, bool autoRelease);
|
|
|
|
Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
|
2012-10-17 15:12:04 +08:00
|
|
|
~Impl();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
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;
|
2012-11-30 21:35:28 +08:00
|
|
|
|
|
|
|
void setAutoRelease(bool flag) { autoRelease_ = flag; }
|
|
|
|
|
|
|
|
GLuint texId() const { return texId_; }
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
Impl();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
GLuint texId_;
|
|
|
|
bool autoRelease_;
|
2012-10-17 15:12:04 +08:00
|
|
|
};
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
const Ptr<cv::GlTexture2D::Impl> cv::GlTexture2D::Impl::empty()
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
static Ptr<Impl> p(new Impl);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlTexture2D::Impl::Impl() : texId_(0), autoRelease_(true)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlTexture2D::Impl::Impl(GLuint atexId, bool autoRelease) : texId_(atexId), autoRelease_(autoRelease)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlTexture2D::Impl::Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) : texId_(0), autoRelease_(true)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::GenTextures(1, &texId_);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
CV_Assert(texId_ != 0);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindTexture(gl::TEXTURE_2D, texId_);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::TexImage2D(gl::TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, pixels);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::GenerateMipmap(gl::TEXTURE_2D);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlTexture2D::Impl::~Impl()
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
if (autoRelease_ && texId_)
|
|
|
|
gl::DeleteTextures(1, &texId_);
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlTexture2D::Impl::copyFrom(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindTexture(gl::TEXTURE_2D, texId_);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::TexSubImage2D(gl::TEXTURE_2D, 0, 0, 0, width, height, format, type, pixels);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::GenerateMipmap(gl::TEXTURE_2D);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlTexture2D::Impl::copyTo(GLenum format, GLenum type, GLvoid* pixels) const
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindTexture(gl::TEXTURE_2D, texId_);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::PixelStorei(gl::PACK_ALIGNMENT, 1);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::GetTexImage(gl::TEXTURE_2D, 0, format, type, pixels);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlTexture2D::Impl::bind() const
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::BindTexture(gl::TEXTURE_2D, texId_);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // HAVE_OPENGL
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlTexture2D::GlTexture2D() : rows_(0), cols_(0), format_(NONE)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
|
|
|
impl_ = Impl::empty();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlTexture2D::GlTexture2D(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
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) arows;
|
|
|
|
(void) acols;
|
|
|
|
(void) aformat;
|
|
|
|
(void) atexId;
|
|
|
|
(void) autoRelease;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
impl_ = new Impl(atexId, autoRelease);
|
|
|
|
rows_ = arows;
|
|
|
|
cols_ = acols;
|
|
|
|
format_ = aformat;
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlTexture2D::GlTexture2D(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
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) asize;
|
|
|
|
(void) aformat;
|
|
|
|
(void) atexId;
|
|
|
|
(void) autoRelease;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
impl_ = new Impl(atexId, autoRelease);
|
|
|
|
rows_ = asize.height;
|
|
|
|
cols_ = asize.width;
|
|
|
|
format_ = aformat;
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlTexture2D::GlTexture2D(int arows, int acols, Format aformat) : rows_(0), cols_(0), format_(NONE)
|
|
|
|
{
|
|
|
|
create(arows, acols, aformat);
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::GlTexture2D::GlTexture2D(Size asize, Format aformat) : rows_(0), cols_(0), format_(NONE)
|
|
|
|
{
|
|
|
|
create(asize, aformat);
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::GlTexture2D::GlTexture2D(InputArray arr) : rows_(0), cols_(0), format_(NONE)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) arr;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
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:
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer buf = arr.getGlBuffer();
|
|
|
|
buf.bind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0);
|
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
break;
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
case _InputArray::GPU_MAT:
|
|
|
|
{
|
|
|
|
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nocuda();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
GpuMat dmat = arr.getGpuMat();
|
|
|
|
GlBuffer buf(dmat, GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
buf.bind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0);
|
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
default:
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
Mat mat = arr.getMat();
|
|
|
|
CV_Assert( mat.isContinuous() );
|
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data);
|
2012-10-17 15:12:04 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
rows_ = asize.height;
|
|
|
|
cols_ = asize.width;
|
|
|
|
format_ = internalFormats[cn];
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlTexture2D::create(int arows, int acols, Format aformat)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) arows;
|
|
|
|
(void) acols;
|
|
|
|
(void) aformat;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
if (rows_ != arows || cols_ != acols || format_ != aformat)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
impl_ = new Impl(aformat, acols, arows, aformat, gl::FLOAT, 0);
|
|
|
|
rows_ = arows;
|
|
|
|
cols_ = acols;
|
|
|
|
format_ = aformat;
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlTexture2D::release()
|
|
|
|
{
|
|
|
|
#ifdef HAVE_OPENGL
|
|
|
|
impl_ = Impl::empty();
|
|
|
|
rows_ = 0;
|
|
|
|
cols_ = 0;
|
|
|
|
format_ = NONE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlTexture2D::setAutoRelease(bool flag)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) flag;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
impl_->setAutoRelease(flag);
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlTexture2D::copyFrom(InputArray arr)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) arr;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
const int kind = arr.kind();
|
|
|
|
|
|
|
|
const Size asize = arr.size();
|
|
|
|
const int atype = arr.type();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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]);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
|
|
|
switch(kind)
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
case _InputArray::OPENGL_BUFFER:
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer buf = arr.getGlBuffer();
|
|
|
|
buf.bind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
impl_->copyFrom(asize.width, asize.height, srcFormats[cn], gl_types[depth], 0);
|
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
break;
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
|
|
|
|
case _InputArray::GPU_MAT:
|
|
|
|
{
|
|
|
|
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
|
|
|
throw_nocuda();
|
|
|
|
#else
|
|
|
|
GpuMat dmat = arr.getGpuMat();
|
|
|
|
GlBuffer buf(dmat, GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
buf.bind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
impl_->copyFrom(asize.width, asize.height, srcFormats[cn], gl_types[depth], 0);
|
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
Mat mat = arr.getMat();
|
|
|
|
CV_Assert( mat.isContinuous() );
|
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
|
|
|
|
impl_->copyFrom(asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlTexture2D::copyTo(OutputArray arr, int ddepth) const
|
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
|
|
|
(void) arr;
|
|
|
|
(void) ddepth;
|
|
|
|
throw_nogl();
|
|
|
|
#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:
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer& buf = arr.getGlBufferRef();
|
|
|
|
buf.create(rows_, cols_, CV_MAKE_TYPE(ddepth, cn), GlBuffer::PIXEL_PACK_BUFFER);
|
|
|
|
buf.bind(GlBuffer::PIXEL_PACK_BUFFER);
|
|
|
|
impl_->copyTo(dstFormat, gl_types[ddepth], 0);
|
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_PACK_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
break;
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
case _InputArray::GPU_MAT:
|
|
|
|
{
|
|
|
|
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nocuda();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer buf(rows_, cols_, CV_MAKE_TYPE(ddepth, cn), GlBuffer::PIXEL_PACK_BUFFER);
|
|
|
|
buf.bind(GlBuffer::PIXEL_PACK_BUFFER);
|
|
|
|
impl_->copyTo(dstFormat, gl_types[ddepth], 0);
|
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_PACK_BUFFER);
|
|
|
|
buf.copyTo(arr);
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
default:
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
arr.create(rows_, cols_, CV_MAKE_TYPE(ddepth, cn));
|
|
|
|
Mat mat = arr.getMat();
|
|
|
|
CV_Assert( mat.isContinuous() );
|
|
|
|
GlBuffer::unbind(GlBuffer::PIXEL_PACK_BUFFER);
|
|
|
|
impl_->copyTo(dstFormat, gl_types[ddepth], mat.data);
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlTexture2D::bind() const
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
|
|
|
impl_->bind();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
unsigned int cv::GlTexture2D::texId() const
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nogl();
|
|
|
|
return 0;
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
return impl_->texId();
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
template <> void cv::Ptr<cv::GlTexture2D::Impl>::delete_obj()
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
if (obj) delete obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// GlArrays
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
cv::GlArrays::GlArrays() : size_(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
void cv::GlArrays::setVertexArray(InputArray vertex)
|
|
|
|
{
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
if (vertex.kind() == _InputArray::OPENGL_BUFFER)
|
|
|
|
vertex_ = vertex.getGlBuffer();
|
|
|
|
else
|
|
|
|
vertex_.copyFrom(vertex);
|
|
|
|
|
|
|
|
size_ = vertex_.size().area();
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlArrays::resetVertexArray()
|
|
|
|
{
|
|
|
|
vertex_.release();
|
|
|
|
size_ = 0;
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlArrays::setColorArray(InputArray color)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
const int cn = color.channels();
|
|
|
|
|
|
|
|
CV_Assert( cn == 3 || cn == 4 );
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
if (color.kind() == _InputArray::OPENGL_BUFFER)
|
|
|
|
color_ = color.getGlBuffer();
|
|
|
|
else
|
|
|
|
color_.copyFrom(color);
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::GlArrays::resetColorArray()
|
|
|
|
{
|
|
|
|
color_.release();
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlArrays::setNormalArray(InputArray normal)
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
const int cn = normal.channels();
|
|
|
|
const int depth = normal.depth();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
if (normal.kind() == _InputArray::OPENGL_BUFFER)
|
|
|
|
normal_ = normal.getGlBuffer();
|
|
|
|
else
|
|
|
|
normal_.copyFrom(normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlArrays::resetNormalArray()
|
|
|
|
{
|
|
|
|
normal_.release();
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlArrays::setTexCoordArray(InputArray texCoord)
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
const int cn = texCoord.channels();
|
|
|
|
const int depth = texCoord.depth();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
if (texCoord.kind() == _InputArray::OPENGL_BUFFER)
|
|
|
|
texCoord_ = texCoord.getGlBuffer();
|
|
|
|
else
|
|
|
|
texCoord_.copyFrom(texCoord);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlArrays::resetTexCoordArray()
|
|
|
|
{
|
|
|
|
texCoord_.release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlArrays::release()
|
|
|
|
{
|
|
|
|
resetVertexArray();
|
|
|
|
resetColorArray();
|
|
|
|
resetNormalArray();
|
|
|
|
resetTexCoordArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cv::GlArrays::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::GlArrays::bind() const
|
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
if (texCoord_.empty())
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::DisableClientState(gl::TEXTURE_COORD_ARRAY);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
else
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::EnableClientState(gl::TEXTURE_COORD_ARRAY);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
texCoord_.bind(GlBuffer::ARRAY_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::TexCoordPointer(texCoord_.channels(), gl_types[texCoord_.depth()], 0, 0);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
if (normal_.empty())
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::DisableClientState(gl::NORMAL_ARRAY);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
else
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::EnableClientState(gl::NORMAL_ARRAY);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
normal_.bind(GlBuffer::ARRAY_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::NormalPointer(gl_types[normal_.depth()], 0, 0);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
if (color_.empty())
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::DisableClientState(gl::COLOR_ARRAY);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
else
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::EnableClientState(gl::COLOR_ARRAY);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
color_.bind(GlBuffer::ARRAY_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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();
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
if (vertex_.empty())
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::DisableClientState(gl::VERTEX_ARRAY);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
else
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::EnableClientState(gl::VERTEX_ARRAY);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
vertex_.bind(GlBuffer::ARRAY_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::VertexPointer(vertex_.channels(), gl_types[vertex_.depth()], 0, 0);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer::unbind(GlBuffer::ARRAY_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Rendering
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::render(const GlTexture2D& tex, Rect_<double> wndRect, Rect_<double> texRect)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) tex;
|
|
|
|
(void) wndRect;
|
|
|
|
(void) texRect;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
|
|
|
if (!tex.empty())
|
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
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();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::Enable(gl::TEXTURE_2D);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::TexEnvi(gl::TEXTURE_ENV, gl::TEXTURE_ENV_MODE, gl::REPLACE);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer::unbind(GlBuffer::ARRAY_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::EnableClientState(gl::TEXTURE_COORD_ARRAY);
|
2012-10-17 15:12:04 +08:00
|
|
|
CV_CheckGlError();
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::TexCoordPointer(2, gl::FLOAT, 0, texCoords);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::DisableClientState(gl::NORMAL_ARRAY);
|
|
|
|
gl::DisableClientState(gl::COLOR_ARRAY);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::EnableClientState(gl::VERTEX_ARRAY);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::VertexPointer(3, gl::FLOAT, 0, vertex);
|
|
|
|
CV_CheckGlError();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::DrawArrays(cv::RenderMode::QUADS, 0, 4);
|
|
|
|
CV_CheckGlError();
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::render(const GlArrays& arr, int mode, Scalar color)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
|
|
|
#ifndef HAVE_OPENGL
|
2012-11-30 21:35:28 +08:00
|
|
|
(void) arr;
|
|
|
|
(void) mode;
|
|
|
|
(void) color;
|
|
|
|
throw_nogl();
|
2012-10-17 15:12:04 +08:00
|
|
|
#else
|
2012-11-30 21:35:28 +08:00
|
|
|
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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
arr.bind();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::DrawArrays(mode, 0, arr.size());
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
void cv::render(const GlArrays& arr, InputArray indices, int mode, Scalar color)
|
2012-10-17 15:12:04 +08:00
|
|
|
{
|
2012-11-30 21:35:28 +08:00
|
|
|
#ifndef HAVE_OPENGL
|
|
|
|
(void) arr;
|
|
|
|
(void) indices;
|
|
|
|
(void) mode;
|
|
|
|
(void) color;
|
|
|
|
throw_nogl();
|
|
|
|
#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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
arr.bind();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
const int kind = indices.kind();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
switch (kind)
|
|
|
|
{
|
|
|
|
case _InputArray::OPENGL_BUFFER :
|
|
|
|
{
|
|
|
|
GlBuffer buf = indices.getGlBuffer();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
const int depth = buf.depth();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
CV_Assert( buf.channels() == 1 );
|
|
|
|
CV_Assert( depth <= CV_32S );
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
buf.bind(GlBuffer::ELEMENT_ARRAY_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::DrawElements(mode, buf.size().area(), type, 0);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer::unbind(GlBuffer::ELEMENT_ARRAY_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
break;
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
Mat mat = indices.getMat();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
const int depth = mat.depth();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
CV_Assert( mat.channels() == 1 );
|
|
|
|
CV_Assert( depth <= CV_32S );
|
|
|
|
CV_Assert( mat.isContinuous() );
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +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
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
GlBuffer::unbind(GlBuffer::ELEMENT_ARRAY_BUFFER);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
gl::DrawElements(mode, mat.size().area(), type, mat.data);
|
|
|
|
}
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|