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.
337 lines
9.3 KiB
337 lines
9.3 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> |
|
|
|
#ifndef SRC_OPENCV_FRAMEBUFFERCONTEXT_HPP_ |
|
#define SRC_OPENCV_FRAMEBUFFERCONTEXT_HPP_ |
|
|
|
#ifdef __EMSCRIPTEN__ |
|
# include <emscripten/threading.h> |
|
#endif |
|
|
|
//FIXME |
|
#include "opencv2/v4d/detail/cl.hpp" |
|
#include <opencv2/core.hpp> |
|
#include <opencv2/core/ocl.hpp> |
|
#include "opencv2/v4d/util.hpp" |
|
#include <iostream> |
|
#include <map> |
|
#include <vector> |
|
|
|
struct GLFWwindow; |
|
typedef unsigned int GLenum; |
|
#define GL_FRAMEBUFFER 0x8D40 |
|
|
|
namespace cv { |
|
namespace v4d { |
|
class V4D; |
|
|
|
namespace detail { |
|
typedef cv::ocl::OpenCLExecutionContext CLExecContext_t; |
|
class CLExecScope_t |
|
{ |
|
CLExecContext_t ctx_; |
|
public: |
|
inline CLExecScope_t(const CLExecContext_t& ctx) |
|
{ |
|
if(ctx.empty()) |
|
return; |
|
ctx_ = CLExecContext_t::getCurrentRef(); |
|
ctx.bind(); |
|
} |
|
|
|
inline ~CLExecScope_t() |
|
{ |
|
if (!ctx_.empty()) |
|
{ |
|
ctx_.bind(); |
|
} |
|
} |
|
}; |
|
/*! |
|
* The FrameBufferContext acquires the framebuffer from OpenGL (either by up-/download or by cl-gl sharing) |
|
*/ |
|
class CV_EXPORTS FrameBufferContext { |
|
typedef unsigned int GLuint; |
|
typedef signed int GLint; |
|
|
|
friend class CLVAContext; |
|
friend class GLContext; |
|
friend class NanoVGContext; |
|
friend class ImGuiContextImpl; |
|
friend class cv::v4d::V4D; |
|
|
|
V4D* v4d_ = nullptr; |
|
bool offscreen_; |
|
string title_; |
|
int major_; |
|
int minor_; |
|
int samples_; |
|
bool debug_; |
|
GLFWwindow* glfwWindow_ = nullptr; |
|
bool clglSharing_ = true; |
|
bool isVisible_; |
|
GLuint frameBufferID_ = 0; |
|
GLuint onscreenTextureID_ = 0; |
|
GLuint textureID_ = 0; |
|
GLuint renderBufferID_ = 0; |
|
GLuint pboID_ = 0; |
|
GLint viewport_[4]; |
|
#ifndef __EMSCRIPTEN__ |
|
cl_mem clImage_ = nullptr; |
|
CLExecContext_t context_; |
|
#endif |
|
cv::Size framebufferSize_; |
|
bool isShared_ = false; |
|
GLFWwindow* sharedWindow_; |
|
const FrameBufferContext* parent_; |
|
|
|
//data and handles for webgl copying |
|
std::map<size_t, GLint> texture_hdls_; |
|
std::map<size_t, GLint> resolution_hdls_; |
|
|
|
std::map<size_t, GLuint> shader_program_hdls_; |
|
|
|
//gl object maps |
|
std::map<size_t, GLuint> copyVaos, copyVbos, copyEbos; |
|
|
|
// vertex position, color |
|
const float copyVertices[12] = { |
|
// x y z |
|
-1.0f, -1.0f, -0.0f, |
|
1.0f, 1.0f, -0.0f, |
|
-1.0f, 1.0f, -0.0f, |
|
1.0f, -1.0f, -0.0f }; |
|
|
|
const unsigned int copyIndices[6] = { |
|
// 2---,1 |
|
// | .' | |
|
// 0'---3 |
|
0, 1, 2, 0, 3, 1 }; |
|
|
|
std::map<size_t, GLuint> copyFramebuffers_; |
|
std::map<size_t, GLuint> copyTextures_; |
|
int index_; |
|
|
|
void* currentSyncObject_ = 0; |
|
bool firstSync_ = true; |
|
public: |
|
/*! |
|
* Acquires and releases the framebuffer from and to OpenGL. |
|
*/ |
|
class CV_EXPORTS FrameBufferScope { |
|
FrameBufferContext& ctx_; |
|
cv::UMat& m_; |
|
#ifndef __EMSCRIPTEN__ |
|
std::shared_ptr<ocl::OpenCLExecutionContext> pExecCtx; |
|
#endif |
|
public: |
|
/*! |
|
* Aquires the framebuffer via cl-gl sharing. |
|
* @param ctx The corresponding #FrameBufferContext. |
|
* @param m The UMat to bind the OpenGL framebuffer to. |
|
*/ |
|
CV_EXPORTS FrameBufferScope(FrameBufferContext& ctx, cv::UMat& m) : |
|
ctx_(ctx), m_(m) |
|
#ifndef __EMSCRIPTEN__ |
|
, pExecCtx(std::static_pointer_cast<ocl::OpenCLExecutionContext>(m.u->allocatorContext)) |
|
#endif |
|
{ |
|
CV_Assert(!m.empty()); |
|
#ifndef __EMSCRIPTEN__ |
|
if(pExecCtx) { |
|
CLExecScope_t execScope(*pExecCtx.get()); |
|
ctx_.acquireFromGL(m_); |
|
} else |
|
#endif |
|
{ |
|
ctx_.acquireFromGL(m_); |
|
} |
|
} |
|
/*! |
|
* Releases the framebuffer via cl-gl sharing. |
|
*/ |
|
CV_EXPORTS ~FrameBufferScope() { |
|
#ifndef __EMSCRIPTEN__ |
|
|
|
if (pExecCtx) { |
|
CLExecScope_t execScope(*pExecCtx.get()); |
|
ctx_.releaseToGL(m_); |
|
} |
|
else |
|
#endif |
|
{ |
|
ctx_.releaseToGL(m_); |
|
} |
|
} |
|
}; |
|
|
|
/*! |
|
* Setups and tears-down OpenGL states. |
|
*/ |
|
class CV_EXPORTS GLScope { |
|
FrameBufferContext& ctx_; |
|
public: |
|
/*! |
|
* Setup OpenGL states. |
|
* @param ctx The corresponding #FrameBufferContext. |
|
*/ |
|
CV_EXPORTS GLScope(FrameBufferContext& ctx, GLenum framebufferTarget = GL_FRAMEBUFFER) : |
|
ctx_(ctx) { |
|
ctx_.begin(framebufferTarget); |
|
} |
|
/*! |
|
* Tear-down OpenGL states. |
|
*/ |
|
CV_EXPORTS ~GLScope() { |
|
ctx_.end(); |
|
} |
|
}; |
|
|
|
/*! |
|
* Create a FrameBufferContext with given size. |
|
* @param frameBufferSize The frame buffer size. |
|
*/ |
|
FrameBufferContext(V4D& v4d, const cv::Size& frameBufferSize, bool offscreen, |
|
const string& title, int major, int minor, int samples, bool debug, GLFWwindow* sharedWindow, const FrameBufferContext* parent); |
|
|
|
FrameBufferContext(V4D& v4d, const string& title, const FrameBufferContext& other); |
|
|
|
/*! |
|
* Default destructor. |
|
*/ |
|
virtual ~FrameBufferContext(); |
|
|
|
GLuint getFramebufferID(); |
|
GLuint getTextureID(); |
|
/*! |
|
* Get the framebuffer size. |
|
* @return The framebuffer size. |
|
*/ |
|
cv::Size size(); |
|
void copyTo(cv::UMat& dst); |
|
void copyFrom(const cv::UMat& src); |
|
|
|
/*! |
|
* Execute function object fn inside a framebuffer context. |
|
* The context acquires the framebuffer from OpenGL (either by up-/download or by cl-gl sharing) |
|
* and provides it to the functon object. This is a good place to use OpenCL |
|
* directly on the framebuffer. |
|
* @param fn A function object that is passed the framebuffer to be read/manipulated. |
|
*/ |
|
template <typename Tfn, typename ... Args> |
|
void execute(Tfn fn, Args& ... args) { |
|
run_sync_on_main<2>([this, fn, &args...](){ |
|
#ifndef __EMSCRIPTEN__ |
|
if(!getCLExecContext().empty()) { |
|
CLExecScope_t clExecScope(getCLExecContext()); |
|
FrameBufferContext::GLScope glScope(*this, GL_FRAMEBUFFER); |
|
FrameBufferContext::FrameBufferScope fbScope(*this, framebuffer_); |
|
fn(framebuffer_, args...); |
|
} else |
|
#endif |
|
{ |
|
FrameBufferContext::GLScope glScope(*this, GL_FRAMEBUFFER); |
|
FrameBufferContext::FrameBufferScope fbScope(*this, framebuffer_); |
|
fn(framebuffer_, args...); |
|
} |
|
}); |
|
} |
|
cv::Vec2f position(); |
|
float pixelRatioX(); |
|
float pixelRatioY(); |
|
void makeCurrent(); |
|
bool isResizable(); |
|
void setResizable(bool r); |
|
void setWindowSize(const cv::Size& sz); |
|
cv::Size getWindowSize(); |
|
bool isFullscreen(); |
|
void setFullscreen(bool f); |
|
cv::Size getNativeFrameBufferSize(); |
|
void setVisible(bool v); |
|
bool isVisible(); |
|
void close(); |
|
bool isClosed(); |
|
bool isShared(); |
|
void fence(); |
|
bool wait(const uint64_t& timeout = 0); |
|
/*! |
|
* Blit the framebuffer to the screen |
|
* @param viewport ROI to blit |
|
* @param windowSize The size of the window to blit to |
|
* @param stretch if true stretch the framebuffer to window size |
|
*/ |
|
void blitFrameBufferToFrameBuffer(const cv::Rect& srcViewport, const cv::Size& targetFbSize, |
|
GLuint targetFramebufferID = 0, bool stretch = true, bool flipY = false); |
|
protected: |
|
cv::Ptr<V4D> getV4D(); |
|
int getIndex(); |
|
void setup(const cv::Size& sz); |
|
void teardown(); |
|
void initWebGLCopy(const size_t& index); |
|
void doWebGLCopy(FrameBufferContext& other); |
|
/*! |
|
* The UMat used to copy or bind (depending on cl-gl interop capability) the OpenGL framebuffer. |
|
*/ |
|
/*! |
|
* The internal framebuffer exposed as OpenGL Texture2D. |
|
* @return The texture object. |
|
*/ |
|
cv::ogl::Texture2D& getTexture2D(); |
|
|
|
GLFWwindow* getGLFWWindow(); |
|
|
|
#ifndef __EMSCRIPTEN__ |
|
/*! |
|
* Get the current OpenCLExecutionContext |
|
* @return The current OpenCLExecutionContext |
|
*/ |
|
CLExecContext_t& getCLExecContext(); |
|
#endif |
|
private: |
|
void loadBuffers(const size_t& index); |
|
void loadShader(const size_t& index); |
|
void init(); |
|
/*! |
|
* Setup OpenGL states. |
|
*/ |
|
CV_EXPORTS void begin(GLenum framebufferTarget); |
|
/*! |
|
* Tear-down OpenGL states. |
|
*/ |
|
CV_EXPORTS void end(); |
|
/*! |
|
* Download the framebuffer to UMat m. |
|
* @param m The target UMat. |
|
*/ |
|
void download(cv::UMat& m); |
|
/*! |
|
* Uploat UMat m to the framebuffer. |
|
* @param m The UMat to upload. |
|
*/ |
|
void upload(const cv::UMat& m); |
|
/*! |
|
* Acquire the framebuffer using cl-gl sharing. |
|
* @param m The UMat the framebuffer will be bound to. |
|
*/ |
|
void acquireFromGL(cv::UMat& m); |
|
/*! |
|
* Release the framebuffer using cl-gl sharing. |
|
* @param m The UMat the framebuffer is bound to. |
|
*/ |
|
void releaseToGL(cv::UMat& m); |
|
void toGLTexture2D(cv::UMat& u, cv::ogl::Texture2D& texture); |
|
void fromGLTexture2D(const cv::ogl::Texture2D& texture, cv::UMat& u); |
|
|
|
cv::UMat framebuffer_; |
|
/*! |
|
* The texture bound to the OpenGL framebuffer. |
|
*/ |
|
cv::ogl::Texture2D* texture_ = nullptr; |
|
}; |
|
} |
|
} |
|
} |
|
|
|
#endif /* SRC_OPENCV_FRAMEBUFFERCONTEXT_HPP_ */
|
|
|