Repository for OpenCV's extra modules
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
5.7 KiB

// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright Amir Hassan (kallaballa) <amir@viel-zu.org>
#include "framebuffercontext.hpp"
#include "opencv2/viz2d/util.hpp"
#include "opencv2/viz2d/viz2d.hpp"
#ifndef VIZ2D_USE_ES3
#include <GL/glew.h>
#endif
namespace cv {
namespace viz {
namespace detail {
//FIXME use cv::ogl
FrameBufferContext::FrameBufferContext(const cv::Size& frameBufferSize) :
frameBufferSize_(frameBufferSize) {
#ifndef VIZ2D_USE_ES3
glewExperimental = true;
glewInit();
try {
if (isClGlSharingSupported())
cv::ogl::ocl::initializeContextFromGL();
else
clglSharing_ = false;
} catch (...) {
cerr << "CL-GL sharing failed." << endl;
clglSharing_ = false;
}
#else
clglSharing_ = false;
#endif
frameBufferID_ = 0;
GL_CHECK(glGenFramebuffers(1, &frameBufferID_));
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID_));
GL_CHECK(glGenRenderbuffers(1, &renderBufferID_));
textureID_ = 0;
GL_CHECK(glGenTextures(1, &textureID_));
GL_CHECK(glBindTexture(GL_TEXTURE_2D, textureID_));
texture_ = new cv::ogl::Texture2D(frameBufferSize_, cv::ogl::Texture2D::RGBA, textureID_);
GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
GL_CHECK(
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frameBufferSize_.width, frameBufferSize_.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, renderBufferID_));
GL_CHECK(
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, frameBufferSize_.width, frameBufferSize_.height));
GL_CHECK(
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBufferID_));
GL_CHECK(
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID_, 0));
assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
#ifndef __EMSCRIPTEN__
context_ = CLExecContext_t::getCurrent();
#endif
}
FrameBufferContext::~FrameBufferContext() {
end();
glDeleteTextures(1, &textureID_);
glDeleteRenderbuffers(1, &renderBufferID_);
glDeleteFramebuffers(1, &frameBufferID_);
}
cv::Size FrameBufferContext::getSize() {
return frameBufferSize_;
}
void FrameBufferContext::execute(std::function<void(cv::UMat&)> fn) {
#ifndef __EMSCRIPTEN__
CLExecScope_t clExecScope(getCLExecContext());
#endif
FrameBufferContext::GLScope glScope(*this);
FrameBufferContext::FrameBufferScope fbScope(*this, frameBuffer_);
fn(frameBuffer_);
}
cv::ogl::Texture2D& FrameBufferContext::getTexture2D() {
return *texture_;
}
#ifndef __EMSCRIPTEN__
CLExecContext_t& FrameBufferContext::getCLExecContext() {
return context_;
}
#endif
void FrameBufferContext::blitFrameBufferToScreen(const cv::Rect& viewport,
const cv::Size& windowSize, bool stretch) {
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBufferID_));
GL_CHECK(glReadBuffer(GL_COLOR_ATTACHMENT0));
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
GL_CHECK(
glBlitFramebuffer( viewport.x, viewport.y, viewport.x + viewport.width, viewport.y + viewport.height, stretch ? 0 : windowSize.width - frameBufferSize_.width, stretch ? 0 : windowSize.height - frameBufferSize_.height, stretch ? windowSize.width : frameBufferSize_.width, stretch ? windowSize.height : frameBufferSize_.height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
}
void FrameBufferContext::begin() {
GL_CHECK(glGetIntegerv( GL_VIEWPORT, viewport_ ));
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID_));
GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, renderBufferID_));
GL_CHECK(
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBufferID_));
GL_CHECK(glBindTexture(GL_TEXTURE_2D, textureID_));
GL_CHECK(
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID_, 0));
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
}
void FrameBufferContext::end() {
GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0));
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
GL_CHECK(glFlush());
GL_CHECK(glFinish());
}
void FrameBufferContext::download(cv::UMat& m) {
cv::Mat tmp = m.getMat(cv::ACCESS_WRITE);
assert(tmp.data != nullptr);
//this should use a PBO for the pixel transfer, but i couldn't get it to work for both opengl and webgl at the same time
GL_CHECK(glReadPixels(0, 0, tmp.cols, tmp.rows, GL_RGBA, GL_UNSIGNED_BYTE, tmp.data));
tmp.release();
}
void FrameBufferContext::upload(const cv::UMat& m) {
cv::Mat tmp = m.getMat(cv::ACCESS_READ);
assert(tmp.data != nullptr);
GL_CHECK(
glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, tmp.cols, tmp.rows, GL_RGBA, GL_UNSIGNED_BYTE, tmp.data));
tmp.release();
}
void FrameBufferContext::acquireFromGL(cv::UMat& m) {
if (clglSharing_) {
GL_CHECK(cv::ogl::convertFromGLTexture2D(getTexture2D(), m));
} else {
if (m.empty())
m.create(getSize(), CV_8UC4);
download(m);
GL_CHECK(glFlush());
GL_CHECK(glFinish());
}
//FIXME
cv::flip(m, m, 0);
}
void FrameBufferContext::releaseToGL(cv::UMat& m) {
//FIXME
cv::flip(m, m, 0);
if (clglSharing_) {
GL_CHECK(cv::ogl::convertToGLTexture2D(m, getTexture2D()));
} else {
if (m.empty())
m.create(getSize(), CV_8UC4);
upload(m);
GL_CHECK(glFlush());
GL_CHECK(glFinish());
}
}
}
}
}