a bit more opengl refactoring:

* added Access parameter to GlBuffer::mapHost
* added autoRelease parameter to all create methods
* fixed indentation in gl_core_3_1
* minor improvments for opengl sample
pull/258/merge
Vladislav Vinogradov 12 years ago
parent 08fbf667f9
commit 05d842bcd8
  1. 33
      modules/core/include/opencv2/core/opengl_interop.hpp
  2. 5389
      modules/core/src/gl_core_3_1.cpp
  3. 2429
      modules/core/src/gl_core_3_1.hpp
  4. 74
      modules/core/src/opengl_interop.cpp
  5. 25
      modules/gpu/test/test_opengl.cpp
  6. 13
      samples/gpu/opengl.cpp

@ -71,6 +71,13 @@ public:
PIXEL_UNPACK_BUFFER = 0x88EC //!< The buffer will be used for writing to OpenGL textures PIXEL_UNPACK_BUFFER = 0x88EC //!< The buffer will be used for writing to OpenGL textures
}; };
enum Access
{
READ_ONLY = 0x88B8,
WRITE_ONLY = 0x88B9,
READ_WRITE = 0x88BA
};
//! create empty buffer //! create empty buffer
GlBuffer(); GlBuffer();
@ -79,15 +86,15 @@ public:
GlBuffer(Size asize, int atype, unsigned int abufId, bool autoRelease = false); GlBuffer(Size asize, int atype, unsigned int abufId, bool autoRelease = false);
//! create buffer //! create buffer
GlBuffer(int arows, int acols, int atype, Target target = ARRAY_BUFFER); GlBuffer(int arows, int acols, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false);
GlBuffer(Size asize, int atype, Target target = ARRAY_BUFFER); GlBuffer(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false);
//! copy from host/device memory //! copy from host/device memory
explicit GlBuffer(InputArray arr, Target target = ARRAY_BUFFER); explicit GlBuffer(InputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false);
//! create buffer //! create buffer
void create(int arows, int acols, int atype, Target target = ARRAY_BUFFER); void create(int arows, int acols, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false);
void create(Size asize, int atype, Target target = ARRAY_BUFFER) { create(asize.height, asize.width, atype, target); } void create(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false) { create(asize.height, asize.width, atype, target, autoRelease); }
//! release memory and delete buffer object //! release memory and delete buffer object
void release(); void release();
@ -96,7 +103,7 @@ public:
void setAutoRelease(bool flag); void setAutoRelease(bool flag);
//! copy from host/device memory //! copy from host/device memory
void copyFrom(InputArray arr, Target target = ARRAY_BUFFER); void copyFrom(InputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false);
//! copy to host/device memory //! copy to host/device memory
void copyTo(OutputArray arr, Target target = ARRAY_BUFFER) const; void copyTo(OutputArray arr, Target target = ARRAY_BUFFER) const;
@ -111,7 +118,7 @@ public:
static void unbind(Target target); static void unbind(Target target);
//! map to host memory //! map to host memory
Mat mapHost(); Mat mapHost(Access access);
void unmapHost(); void unmapHost();
//! map to device memory //! map to device memory
@ -162,15 +169,15 @@ public:
GlTexture2D(Size asize, Format aformat, unsigned int atexId, bool autoRelease = false); GlTexture2D(Size asize, Format aformat, unsigned int atexId, bool autoRelease = false);
//! create texture //! create texture
GlTexture2D(int arows, int acols, Format aformat); GlTexture2D(int arows, int acols, Format aformat, bool autoRelease = false);
GlTexture2D(Size asize, Format aformat); GlTexture2D(Size asize, Format aformat, bool autoRelease = false);
//! copy from host/device memory //! copy from host/device memory
explicit GlTexture2D(InputArray arr); explicit GlTexture2D(InputArray arr, bool autoRelease = false);
//! create texture //! create texture
void create(int arows, int acols, Format aformat); void create(int arows, int acols, Format aformat, bool autoRelease = false);
void create(Size asize, Format aformat) { create(asize.height, asize.width, aformat); } void create(Size asize, Format aformat, bool autoRelease = false) { create(asize.height, asize.width, aformat, autoRelease); }
//! release memory and delete texture object //! release memory and delete texture object
void release(); void release();
@ -179,7 +186,7 @@ public:
void setAutoRelease(bool flag); void setAutoRelease(bool flag);
//! copy from host/device memory //! copy from host/device memory
void copyFrom(InputArray arr); void copyFrom(InputArray arr, bool autoRelease = false);
//! copy to host/device memory //! copy to host/device memory
void copyTo(OutputArray arr, int ddepth = CV_32F) const; void copyTo(OutputArray arr, int ddepth = CV_32F) const;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -327,7 +327,7 @@ public:
static const Ptr<Impl>& empty(); static const Ptr<Impl>& empty();
Impl(GLuint bufId, bool autoRelease); Impl(GLuint bufId, bool autoRelease);
Impl(GLsizeiptr size, const GLvoid* data, GLenum target); Impl(GLsizeiptr size, const GLvoid* data, GLenum target, bool autoRelease);
~Impl(); ~Impl();
void bind(GLenum target) const; void bind(GLenum target) const;
@ -337,7 +337,7 @@ public:
void copyFrom(GLsizeiptr size, const GLvoid* data); void copyFrom(GLsizeiptr size, const GLvoid* data);
void copyTo(GLsizeiptr size, GLvoid* data) const; void copyTo(GLsizeiptr size, GLvoid* data) const;
void* mapHost(); void* mapHost(GLenum access);
void unmapHost(); void unmapHost();
#ifdef HAVE_CUDA #ifdef HAVE_CUDA
@ -377,7 +377,7 @@ cv::GlBuffer::Impl::Impl(GLuint abufId, bool autoRelease) : bufId_(abufId), auto
{ {
} }
cv::GlBuffer::Impl::Impl(GLsizeiptr size, const GLvoid* data, GLenum target) : bufId_(0), autoRelease_(true) cv::GlBuffer::Impl::Impl(GLsizeiptr size, const GLvoid* data, GLenum target, bool autoRelease) : bufId_(0), autoRelease_(autoRelease)
{ {
gl::GenBuffers(1, &bufId_); gl::GenBuffers(1, &bufId_);
CV_CheckGlError(); CV_CheckGlError();
@ -436,12 +436,12 @@ void cv::GlBuffer::Impl::copyTo(GLsizeiptr size, GLvoid* data) const
CV_CheckGlError(); CV_CheckGlError();
} }
void* cv::GlBuffer::Impl::mapHost() void* cv::GlBuffer::Impl::mapHost(GLenum access)
{ {
gl::BindBuffer(gl::COPY_READ_BUFFER, bufId_); gl::BindBuffer(gl::COPY_READ_BUFFER, bufId_);
CV_CheckGlError(); CV_CheckGlError();
GLvoid* data = gl::MapBuffer(gl::COPY_READ_BUFFER, gl::READ_WRITE); GLvoid* data = gl::MapBuffer(gl::COPY_READ_BUFFER, access);
CV_CheckGlError(); CV_CheckGlError();
return data; return data;
@ -521,17 +521,17 @@ cv::GlBuffer::GlBuffer(Size asize, int atype, unsigned int abufId, bool autoRele
#endif #endif
} }
cv::GlBuffer::GlBuffer(int arows, int acols, int atype, Target target) : rows_(0), cols_(0), type_(0) cv::GlBuffer::GlBuffer(int arows, int acols, int atype, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0)
{ {
create(arows, acols, atype, target); create(arows, acols, atype, target, autoRelease);
} }
cv::GlBuffer::GlBuffer(Size asize, int atype, Target target) : rows_(0), cols_(0), type_(0) cv::GlBuffer::GlBuffer(Size asize, int atype, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0)
{ {
create(asize, atype, target); create(asize, atype, target, autoRelease);
} }
cv::GlBuffer::GlBuffer(InputArray arr, Target target) : rows_(0), cols_(0), type_(0) cv::GlBuffer::GlBuffer(InputArray arr, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0)
{ {
#ifndef HAVE_OPENGL #ifndef HAVE_OPENGL
(void) arr; (void) arr;
@ -544,19 +544,19 @@ cv::GlBuffer::GlBuffer(InputArray arr, Target target) : rows_(0), cols_(0), type
{ {
case _InputArray::OPENGL_BUFFER: case _InputArray::OPENGL_BUFFER:
{ {
copyFrom(arr, target); copyFrom(arr, target, autoRelease);
break; break;
} }
case _InputArray::OPENGL_TEXTURE2D: case _InputArray::OPENGL_TEXTURE2D:
{ {
copyFrom(arr, target); copyFrom(arr, target, autoRelease);
break; break;
} }
case _InputArray::GPU_MAT: case _InputArray::GPU_MAT:
{ {
copyFrom(arr, target); copyFrom(arr, target, autoRelease);
break; break;
} }
@ -565,7 +565,7 @@ cv::GlBuffer::GlBuffer(InputArray arr, Target target) : rows_(0), cols_(0), type
Mat mat = arr.getMat(); Mat mat = arr.getMat();
CV_Assert( mat.isContinuous() ); CV_Assert( mat.isContinuous() );
const GLsizeiptr asize = mat.rows * mat.cols * mat.elemSize(); const GLsizeiptr asize = mat.rows * mat.cols * mat.elemSize();
impl_ = new Impl(asize, mat.data, target); impl_ = new Impl(asize, mat.data, target, autoRelease);
rows_ = mat.rows; rows_ = mat.rows;
cols_ = mat.cols; cols_ = mat.cols;
type_ = mat.type(); type_ = mat.type();
@ -575,7 +575,7 @@ cv::GlBuffer::GlBuffer(InputArray arr, Target target) : rows_(0), cols_(0), type
#endif #endif
} }
void cv::GlBuffer::create(int arows, int acols, int atype, Target target) void cv::GlBuffer::create(int arows, int acols, int atype, Target target, bool autoRelease)
{ {
#ifndef HAVE_OPENGL #ifndef HAVE_OPENGL
(void) arows; (void) arows;
@ -587,7 +587,7 @@ void cv::GlBuffer::create(int arows, int acols, int atype, Target target)
if (rows_ != arows || cols_ != acols || type_ != atype) if (rows_ != arows || cols_ != acols || type_ != atype)
{ {
const GLsizeiptr asize = arows * acols * CV_ELEM_SIZE(atype); const GLsizeiptr asize = arows * acols * CV_ELEM_SIZE(atype);
impl_ = new Impl(asize, 0, target); impl_ = new Impl(asize, 0, target, autoRelease);
rows_ = arows; rows_ = arows;
cols_ = acols; cols_ = acols;
type_ = atype; type_ = atype;
@ -598,6 +598,8 @@ void cv::GlBuffer::create(int arows, int acols, int atype, Target target)
void cv::GlBuffer::release() void cv::GlBuffer::release()
{ {
#ifdef HAVE_OPENGL #ifdef HAVE_OPENGL
if (*impl_.refcount == 1)
impl_->setAutoRelease(true);
impl_ = Impl::empty(); impl_ = Impl::empty();
rows_ = 0; rows_ = 0;
cols_ = 0; cols_ = 0;
@ -615,7 +617,7 @@ void cv::GlBuffer::setAutoRelease(bool flag)
#endif #endif
} }
void cv::GlBuffer::copyFrom(InputArray arr, Target target) void cv::GlBuffer::copyFrom(InputArray arr, Target target, bool autoRelease)
{ {
#ifndef HAVE_OPENGL #ifndef HAVE_OPENGL
(void) arr; (void) arr;
@ -628,12 +630,13 @@ void cv::GlBuffer::copyFrom(InputArray arr, Target target)
{ {
GlTexture2D tex = arr.getGlTexture2D(); GlTexture2D tex = arr.getGlTexture2D();
tex.copyTo(*this); tex.copyTo(*this);
setAutoRelease(autoRelease);
return; return;
} }
const Size asize = arr.size(); const Size asize = arr.size();
const int atype = arr.type(); const int atype = arr.type();
create(asize, atype, target); create(asize, atype, target, autoRelease);
switch (kind) switch (kind)
{ {
@ -747,13 +750,14 @@ void cv::GlBuffer::unbind(Target target)
#endif #endif
} }
Mat cv::GlBuffer::mapHost() Mat cv::GlBuffer::mapHost(Access access)
{ {
#ifndef HAVE_OPENGL #ifndef HAVE_OPENGL
(void) access;
throw_nogl(); throw_nogl();
return Mat(); return Mat();
#else #else
return Mat(rows_, cols_, type_, impl_->mapHost()); return Mat(rows_, cols_, type_, impl_->mapHost(access));
#endif #endif
} }
@ -826,7 +830,7 @@ public:
static const Ptr<Impl> empty(); static const Ptr<Impl> empty();
Impl(GLuint texId, bool autoRelease); Impl(GLuint texId, bool autoRelease);
Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels, bool autoRelease);
~Impl(); ~Impl();
void copyFrom(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); void copyFrom(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
@ -859,7 +863,7 @@ cv::GlTexture2D::Impl::Impl(GLuint atexId, bool autoRelease) : texId_(atexId), a
{ {
} }
cv::GlTexture2D::Impl::Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) : texId_(0), autoRelease_(true) cv::GlTexture2D::Impl::Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels, bool autoRelease) : texId_(0), autoRelease_(autoRelease)
{ {
gl::GenTextures(1, &texId_); gl::GenTextures(1, &texId_);
CV_CheckGlError(); CV_CheckGlError();
@ -962,17 +966,17 @@ cv::GlTexture2D::GlTexture2D(Size asize, Format aformat, unsigned int atexId, bo
#endif #endif
} }
cv::GlTexture2D::GlTexture2D(int arows, int acols, Format aformat) : rows_(0), cols_(0), format_(NONE) cv::GlTexture2D::GlTexture2D(int arows, int acols, Format aformat, bool autoRelease) : rows_(0), cols_(0), format_(NONE)
{ {
create(arows, acols, aformat); create(arows, acols, aformat, autoRelease);
} }
cv::GlTexture2D::GlTexture2D(Size asize, Format aformat) : rows_(0), cols_(0), format_(NONE) cv::GlTexture2D::GlTexture2D(Size asize, Format aformat, bool autoRelease) : rows_(0), cols_(0), format_(NONE)
{ {
create(asize, aformat); create(asize, aformat, autoRelease);
} }
cv::GlTexture2D::GlTexture2D(InputArray arr) : rows_(0), cols_(0), format_(NONE) cv::GlTexture2D::GlTexture2D(InputArray arr, bool autoRelease) : rows_(0), cols_(0), format_(NONE)
{ {
#ifndef HAVE_OPENGL #ifndef HAVE_OPENGL
(void) arr; (void) arr;
@ -1004,7 +1008,7 @@ cv::GlTexture2D::GlTexture2D(InputArray arr) : rows_(0), cols_(0), format_(NONE)
{ {
GlBuffer buf = arr.getGlBuffer(); GlBuffer buf = arr.getGlBuffer();
buf.bind(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); impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease);
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER); GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
break; break;
} }
@ -1017,7 +1021,7 @@ cv::GlTexture2D::GlTexture2D(InputArray arr) : rows_(0), cols_(0), format_(NONE)
GpuMat dmat = arr.getGpuMat(); GpuMat dmat = arr.getGpuMat();
GlBuffer buf(dmat, GlBuffer::PIXEL_UNPACK_BUFFER); GlBuffer buf(dmat, GlBuffer::PIXEL_UNPACK_BUFFER);
buf.bind(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); impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease);
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER); GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
#endif #endif
@ -1029,7 +1033,7 @@ cv::GlTexture2D::GlTexture2D(InputArray arr) : rows_(0), cols_(0), format_(NONE)
Mat mat = arr.getMat(); Mat mat = arr.getMat();
CV_Assert( mat.isContinuous() ); CV_Assert( mat.isContinuous() );
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER); GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data); impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data, autoRelease);
break; break;
} }
} }
@ -1040,7 +1044,7 @@ cv::GlTexture2D::GlTexture2D(InputArray arr) : rows_(0), cols_(0), format_(NONE)
#endif #endif
} }
void cv::GlTexture2D::create(int arows, int acols, Format aformat) void cv::GlTexture2D::create(int arows, int acols, Format aformat, bool autoRelease)
{ {
#ifndef HAVE_OPENGL #ifndef HAVE_OPENGL
(void) arows; (void) arows;
@ -1051,7 +1055,7 @@ void cv::GlTexture2D::create(int arows, int acols, Format aformat)
if (rows_ != arows || cols_ != acols || format_ != aformat) if (rows_ != arows || cols_ != acols || format_ != aformat)
{ {
GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER); GlBuffer::unbind(GlBuffer::PIXEL_UNPACK_BUFFER);
impl_ = new Impl(aformat, acols, arows, aformat, gl::FLOAT, 0); impl_ = new Impl(aformat, acols, arows, aformat, gl::FLOAT, 0, autoRelease);
rows_ = arows; rows_ = arows;
cols_ = acols; cols_ = acols;
format_ = aformat; format_ = aformat;
@ -1062,6 +1066,8 @@ void cv::GlTexture2D::create(int arows, int acols, Format aformat)
void cv::GlTexture2D::release() void cv::GlTexture2D::release()
{ {
#ifdef HAVE_OPENGL #ifdef HAVE_OPENGL
if (*impl_.refcount == 1)
impl_->setAutoRelease(true);
impl_ = Impl::empty(); impl_ = Impl::empty();
rows_ = 0; rows_ = 0;
cols_ = 0; cols_ = 0;
@ -1079,7 +1085,7 @@ void cv::GlTexture2D::setAutoRelease(bool flag)
#endif #endif
} }
void cv::GlTexture2D::copyFrom(InputArray arr) void cv::GlTexture2D::copyFrom(InputArray arr, bool autoRelease)
{ {
#ifndef HAVE_OPENGL #ifndef HAVE_OPENGL
(void) arr; (void) arr;
@ -1105,7 +1111,7 @@ void cv::GlTexture2D::copyFrom(InputArray arr)
0, gl::DEPTH_COMPONENT, 0, gl::BGR, gl::BGRA 0, gl::DEPTH_COMPONENT, 0, gl::BGR, gl::BGRA
}; };
create(asize, internalFormats[cn]); create(asize, internalFormats[cn], autoRelease);
switch(kind) switch(kind)
{ {

@ -351,14 +351,14 @@ TEST_P(GlBuffer, Clone)
cv::destroyAllWindows(); cv::destroyAllWindows();
} }
TEST_P(GlBuffer, MapHost) TEST_P(GlBuffer, MapHostRead)
{ {
cv::namedWindow("test", cv::WINDOW_OPENGL); cv::namedWindow("test", cv::WINDOW_OPENGL);
cv::Mat gold = randomMat(size, type); cv::Mat gold = randomMat(size, type);
cv::GlBuffer buf(gold); cv::GlBuffer buf(gold);
cv::Mat dst = buf.mapHost(); cv::Mat dst = buf.mapHost(cv::GlBuffer::READ_ONLY);
EXPECT_MAT_NEAR(gold, dst, 0); EXPECT_MAT_NEAR(gold, dst, 0);
@ -368,6 +368,27 @@ TEST_P(GlBuffer, MapHost)
cv::destroyAllWindows(); cv::destroyAllWindows();
} }
TEST_P(GlBuffer, MapHostWrite)
{
cv::namedWindow("test", cv::WINDOW_OPENGL);
cv::Mat gold = randomMat(size, type);
cv::GlBuffer buf(size, type);
cv::Mat dst = buf.mapHost(cv::GlBuffer::WRITE_ONLY);
gold.copyTo(dst);
buf.unmapHost();
dst.release();
cv::Mat bufData;
buf.copyTo(bufData);
EXPECT_MAT_NEAR(gold, bufData, 0);
buf.release();
cv::destroyAllWindows();
}
TEST_P(GlBuffer, MapDevice) TEST_P(GlBuffer, MapDevice)
{ {
cv::namedWindow("test", cv::WINDOW_OPENGL); cv::namedWindow("test", cv::WINDOW_OPENGL);

@ -56,14 +56,18 @@ void CV_CDECL draw(void* userdata)
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
gluLookAt(0, 0, 4, 0, 0, 0, 0, 1, 0); gluLookAt(0, 0, 3, 0, 0, 0, 0, 1, 0);
glRotated(angle, 0, 1, 0); glRotated(angle, 0, 1, 0);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
data->tex.bind(); data->tex.bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
render(data->arr, data->indices, RenderMode::TRIANGLES); render(data->arr, data->indices, RenderMode::TRIANGLES);
@ -101,13 +105,8 @@ int main(int argc, char* argv[])
data.arr.setVertexArray(vertex); data.arr.setVertexArray(vertex);
data.arr.setTexCoordArray(texCoords); data.arr.setTexCoordArray(texCoords);
data.arr.setAutoRelease(false);
data.indices.copyFrom(indices); data.indices.copyFrom(indices);
data.indices.setAutoRelease(false);
data.tex.copyFrom(img); data.tex.copyFrom(img);
data.tex.setAutoRelease(false);
setOpenGlDrawCallback("OpenGL", draw, &data); setOpenGlDrawCallback("OpenGL", draw, &data);

Loading…
Cancel
Save