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
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()); |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|