make each context have its own framebuffer which has its own offscreen window

pull/3471/head
kallaballa 2 years ago
parent a5fb870c96
commit 991543a394
  1. 34
      modules/v4d/include/opencv2/v4d/v4d.hpp
  2. 101
      modules/v4d/src/detail/framebuffercontext.cpp
  3. 37
      modules/v4d/src/detail/framebuffercontext.hpp
  4. 61
      modules/v4d/src/detail/nanovgcontext.cpp
  5. 9
      modules/v4d/src/detail/nanovgcontext.hpp
  6. 164
      modules/v4d/src/v4d.cpp

@ -130,16 +130,9 @@ class CV_EXPORTS V4D {
cv::Rect viewport_;
float scale_;
cv::Vec2f mousePos_;
bool offscreen_;
bool stretch_;
string title_;
int major_;
int minor_;
bool compat_;
int samples_;
bool debug_;
GLFWwindow* glfwWindow_ = nullptr;
FrameBufferContext* clglContext_ = nullptr;
bool offscreen_;
FrameBufferContext* mainFramebufferContext_ = nullptr;
CLVAContext* clvaContext_ = nullptr;
NanoVGContext* nvgContext_ = nullptr;
cv::VideoCapture* capture_ = nullptr;
@ -192,17 +185,6 @@ public:
* Default destructor
*/
CV_EXPORTS virtual ~V4D();
/*!
* In case several V4D objects are in use all objects not in use have to
* call #makeNoneCurrent() and only the one to be active call #makeCurrent().
*/
CV_EXPORTS void makeCurrent();
/*!
* To make it possible for other V4D objects to become current all other
* V4D instances have to become non-current.
*/
CV_EXPORTS void makeNoneCurrent();
/*!
* The internal framebuffer exposed as OpenGL Texture2D.
* @return The texture object.
@ -359,16 +341,6 @@ public:
* @return The framebuffer size of the native window.
*/
CV_EXPORTS cv::Size getNativeFrameBufferSize();
/*!
* Get the pixel ratio of the display x-axis.
* @return The pixel ratio of the display x-axis.
*/
CV_EXPORTS float getXPixelRatio();
/*!
* Get the pixel ratio of the display y-axis.
* @return The pixel ratio of the display y-axis.
*/
CV_EXPORTS float getYPixelRatio();
/*!
* Determine if the window is in fullscreen mode.
* @return true if in fullscreen mode.
@ -451,7 +423,7 @@ private:
void setDefaultKeyboardEventCallback();
void setKeyboardEventCallback(
std::function<bool(int key, int scancode, int action, int modifiers)> fn);
bool initializeWindowing();
bool initializeGUI();
void setMouseDrag(bool d);
bool isMouseDrag();
cv::Vec2f getMousePosition();

@ -12,9 +12,69 @@ namespace cv {
namespace viz {
namespace detail {
//FIXME use cv::ogl
FrameBufferContext::FrameBufferContext(const cv::Size& frameBufferSize) :
frameBufferSize_(frameBufferSize) {
FrameBufferContext::FrameBufferContext(const FrameBufferContext& other) : FrameBufferContext(other.frameBufferSize_, true, other.title_, other.major_, other.minor_, other.compat_, other.samples_, other.debug_) {
}
FrameBufferContext::FrameBufferContext(const cv::Size& frameBufferSize, bool offscreen,
const string& title, int major, int minor, bool compat, int samples, bool debug) :
frameBufferSize_(frameBufferSize), offscreen_(offscreen), title_(title), major_(major), minor_(
minor), compat_(compat), samples_(samples), debug_(debug) {
if (glfwInit() != GLFW_TRUE)
assert(false);
glfwSetErrorCallback(cv::viz::glfw_error_callback);
if (debug_)
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
if (offscreen_)
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwSetTime(0);
#ifdef __APPLE__
glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#elif defined(OPENCV_V4D_USE_ES3)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major_);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor_);
glfwWindowHint(GLFW_OPENGL_PROFILE, compat_ ? GLFW_OPENGL_COMPAT_PROFILE : GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API) ;
#endif
glfwWindowHint(GLFW_SAMPLES, samples_);
glfwWindowHint(GLFW_RED_BITS, 8);
glfwWindowHint(GLFW_GREEN_BITS, 8);
glfwWindowHint(GLFW_BLUE_BITS, 8);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
glfwWindowHint(GLFW_STENCIL_BITS, 8);
glfwWindowHint(GLFW_DEPTH_BITS, 24);
#ifndef __EMSCRIPTEN__
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
#else
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
#endif
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
/* I figure we don't need double buffering because the FBO (and the bound texture) is our backbuffer that
* we blit to the front on every iteration.
* On X11, wayland and in WASM it works and boosts performance a bit.
*/
glfwWindowHint(GLFW_DOUBLEBUFFER, GL_FALSE);
glfwWindow_ = glfwCreateWindow(frameBufferSize.width, frameBufferSize.height, title_.c_str(), nullptr,
nullptr);
if (glfwWindow_ == NULL) {
assert(false);
}
glfwMakeContextCurrent(glfwWindow_);
#ifndef OPENCV_V4D_USE_ES3
glewExperimental = true;
glewInit();
@ -160,6 +220,10 @@ cv::ogl::Texture2D& FrameBufferContext::getTexture2D() {
return *texture_;
}
GLFWwindow* FrameBufferContext::getGLFWWindow() {
return glfwWindow_;
}
#ifndef __EMSCRIPTEN__
CLExecContext_t& FrameBufferContext::getCLExecContext() {
return context_;
@ -176,6 +240,7 @@ void FrameBufferContext::blitFrameBufferToScreen(const cv::Rect& viewport,
}
void FrameBufferContext::begin() {
glfwMakeContextCurrent(getGLFWWindow());
GL_CHECK(glGetIntegerv( GL_VIEWPORT, viewport_ ));
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID_));
GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, renderBufferID_));
@ -193,6 +258,7 @@ void FrameBufferContext::end() {
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
GL_CHECK(glFlush());
GL_CHECK(glFinish());
glfwMakeContextCurrent(nullptr);
}
void FrameBufferContext::download(cv::UMat& m) {
@ -238,6 +304,35 @@ void FrameBufferContext::releaseToGL(cv::UMat& m) {
GL_CHECK(glFinish());
}
}
float FrameBufferContext::getXPixelRatio() {
makeCurrent();
#ifdef __EMSCRIPTEN__
return emscripten_get_device_pixel_ratio();
#else
float xscale, yscale;
glfwGetWindowContentScale(getGLFWWindow(), &xscale, &yscale);
return xscale;
#endif
}
float FrameBufferContext::getYPixelRatio() {
makeCurrent();
#ifdef __EMSCRIPTEN__
return emscripten_get_device_pixel_ratio();
#else
float xscale, yscale;
glfwGetWindowContentScale(getGLFWWindow(), &xscale, &yscale);
return yscale;
#endif
}
void FrameBufferContext::makeCurrent() {
glfwMakeContextCurrent(getGLFWWindow());
}
void FrameBufferContext::makeNoneCurrent() {
glfwMakeContextCurrent(nullptr);
}
}
}
}

@ -46,6 +46,14 @@ class FrameBufferContext {
friend class CLVAContext;
friend class NanoVGContext;
friend class cv::viz::V4D;
bool offscreen_;
string title_;
int major_;
int minor_;
bool compat_;
int samples_;
bool debug_;
GLFWwindow* glfwWindow_ = nullptr;
bool clglSharing_ = true;
GLuint frameBufferID_ = 0;
GLuint textureID_ = 0;
@ -61,6 +69,8 @@ class FrameBufferContext {
* @return The texture object.
*/
cv::ogl::Texture2D& getTexture2D();
GLFWwindow* getGLFWWindow();
#ifndef __EMSCRIPTEN__
/*!
* Get the current OpenCLExecutionContext
@ -130,7 +140,11 @@ public:
* Create a FrameBufferContext with given size.
* @param frameBufferSize The frame buffer size.
*/
FrameBufferContext(const cv::Size& frameBufferSize);
FrameBufferContext(const cv::Size& frameBufferSize, bool offscreen,
const string& title, int major, int minor, bool compat, int samples, bool debug);
FrameBufferContext(const FrameBufferContext& other);
/*!
* Default destructor.
*/
@ -148,6 +162,27 @@ public:
* @param fn A function object that is passed the framebuffer to be read/manipulated.
*/
void execute(std::function<void(cv::UMat&)> fn);
/*!
* Get the pixel ratio of the display x-axis.
* @return The pixel ratio of the display x-axis.
*/
CV_EXPORTS float getXPixelRatio();
/*!
* Get the pixel ratio of the display y-axis.
* @return The pixel ratio of the display y-axis.
*/
CV_EXPORTS float getYPixelRatio();
/*!
* In case several V4D objects are in use all objects not in use have to
* call #makeNoneCurrent() and only the one to be active call #makeCurrent().
*/
CV_EXPORTS void makeCurrent();
/*!
* To make it possible for other V4D objects to become current all other
* V4D instances have to become non-current.
*/
CV_EXPORTS void makeNoneCurrent();
protected:
/*!
* Setup OpenGL states.

@ -5,32 +5,64 @@
#include "nanovgcontext.hpp"
#include "opencv2/v4d/v4d.hpp"
namespace cv {
namespace viz {
namespace detail {
NanoVGContext::NanoVGContext(V4D& v4d, NVGcontext* context, FrameBufferContext& fbContext) :
v4d_(v4d), context_(context), clglContext_(fbContext) {
NanoVGContext::NanoVGContext(NVGcontext* context, FrameBufferContext& fbContext) :
context_(context), mainFbContext_(fbContext), nvgFbContext_(fbContext) {
//FIXME workaround for first frame color glitch
cv::UMat tmp;
FrameBufferContext::FrameBufferScope fbScope(clglContext_, tmp);
FrameBufferContext::GLScope glScope(mainFbContext_);
FrameBufferContext::FrameBufferScope fbScope(mainFbContext_, fb_);
}
void NanoVGContext::render(std::function<void(const cv::Size&)> fn) {
{
#ifndef __EMSCRIPTEN__
CLExecScope_t scope(mainFbContext_.getCLExecContext());
#endif
FrameBufferContext::GLScope mainGlScope(mainFbContext_);
FrameBufferContext::FrameBufferScope fbScope(mainFbContext_, fb_);
fb_.copyTo(preFB_);
}
{
#ifndef __EMSCRIPTEN__
CLExecScope_t scope(nvgFbContext_.getCLExecContext());
#endif
FrameBufferContext::GLScope nvgGlScope(nvgFbContext_);
FrameBufferContext::FrameBufferScope fbScope(nvgFbContext_, fb_);
preFB_.copyTo(fb_);
}
{
#ifndef __EMSCRIPTEN__
CLExecScope_t scope(nvgFbContext_.getCLExecContext());
#endif
FrameBufferContext::GLScope nvgGlScope(nvgFbContext_);
NanoVGContext::Scope nvgScope(*this);
cv::viz::nvg::detail::NVG::initializeContext(context_);
fn(nvgFbContext_.getSize());
}
{
#ifndef __EMSCRIPTEN__
CLExecScope_t scope(nvgFbContext_.getCLExecContext());
#endif
FrameBufferContext::GLScope nvgGlScope(nvgFbContext_);
FrameBufferContext::FrameBufferScope fbScope(nvgFbContext_, fb_);
fb_.copyTo(postFB_);
}
{
#ifndef __EMSCRIPTEN__
CLExecScope_t scope(clglContext_.getCLExecContext());
CLExecScope_t scope(mainFbContext_.getCLExecContext());
#endif
FrameBufferContext::GLScope glScope(clglContext_);
NanoVGContext::Scope nvgScope(*this);
cv::viz::nvg::detail::NVG::initializeContext(context_), fn(clglContext_.getSize());
FrameBufferContext::GLScope mainGlScope(mainFbContext_);
FrameBufferContext::FrameBufferScope fbScope(mainFbContext_, fb_);
postFB_.copyTo(fb_);
}
}
void NanoVGContext::begin() {
// push();
float w = v4d_.getFrameBufferSize().width;
float h = v4d_.getFrameBufferSize().height;
float r = v4d_.getXPixelRatio();
float w = mainFbContext_.getSize().width;
float h = mainFbContext_.getSize().height;
float r = mainFbContext_.getXPixelRatio();
nvgSave(context_);
nvgBeginFrame(context_, w, h, r);
@ -44,7 +76,6 @@ void NanoVGContext::end() {
//FIXME make nvgCancelFrame possible
nvgEndFrame(context_);
nvgRestore(context_);
// pop();
}
}
}

@ -31,9 +31,12 @@ namespace detail {
* Used to setup a nanovg context
*/
class NanoVGContext {
V4D& v4d_;
NVGcontext* context_;
FrameBufferContext& clglContext_;
FrameBufferContext& mainFbContext_;
FrameBufferContext& nvgFbContext_;
cv::UMat preFB_;
cv::UMat fb_;
cv::UMat postFB_;
public:
/*!
* Makes sure #NanoVGContext::begin and #NanoVGContext::end are both called
@ -62,7 +65,7 @@ public:
* @param context The native NVGContext
* @param fbContext The framebuffer context
*/
NanoVGContext(V4D& v4d, NVGcontext* context, FrameBufferContext& fbContext);
NanoVGContext(NVGcontext* context, FrameBufferContext& fbContext);
/*!
* Execute function object fn inside a nanovg context.
* The context takes care of setting up opengl and nanovg states.

@ -59,25 +59,23 @@ cv::Ptr<V4D> V4D::make(const cv::Size& size, const string& title, bool debug) {
cv::Ptr<V4D> V4D::make(const cv::Size& initialSize, const cv::Size& frameBufferSize,
bool offscreen, const string& title, int major, int minor, bool compat, int samples, bool debug) {
cerr << "make" << endl;
return new V4D(initialSize, frameBufferSize, offscreen, title, major, minor, compat, samples, debug);
}
V4D::V4D(const cv::Size& size, const cv::Size& frameBufferSize, bool offscreen,
const string& title, int major, int minor, bool compat, int samples, bool debug) :
initialSize_(size), frameBufferSize_(frameBufferSize), viewport_(0, 0,
frameBufferSize.width, frameBufferSize.height), scale_(1), mousePos_(0, 0), offscreen_(
offscreen), stretch_(false), title_(title), major_(major), minor_(minor), compat_(compat), samples_(
samples), debug_(debug) {
frameBufferSize.width, frameBufferSize.height), scale_(1), mousePos_(0, 0), stretch_(false), offscreen_(offscreen) {
assert(
frameBufferSize_.width >= initialSize_.width
&& frameBufferSize_.height >= initialSize_.height);
cerr << "init:" << initializeWindowing() << endl;
mainFramebufferContext_ = new detail::FrameBufferContext(this->getFrameBufferSize(), offscreen, title, major, minor, compat, samples, debug);
if(!initializeGUI())
assert(false);
}
V4D::~V4D() {
cerr << "destroy" << endl;
//don't delete form_. it is autmatically cleaned up by the base class (nanogui::Screen)
if (screen_)
delete screen_;
@ -89,66 +87,12 @@ V4D::~V4D() {
delete nvgContext_;
if (clvaContext_)
delete clvaContext_;
if (clglContext_)
delete clglContext_;
if (mainFramebufferContext_)
delete mainFramebufferContext_;
}
bool V4D::initializeWindowing() {
bool V4D::initializeGUI() {
try {
if (glfwInit() != GLFW_TRUE)
return false;
glfwSetErrorCallback(cv::viz::glfw_error_callback);
if (debug_)
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
if (offscreen_)
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwSetTime(0);
#ifdef __APPLE__
glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#elif defined(OPENCV_V4D_USE_ES3)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major_);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor_);
glfwWindowHint(GLFW_OPENGL_PROFILE, compat_ ? GLFW_OPENGL_COMPAT_PROFILE : GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API) ;
#endif
glfwWindowHint(GLFW_SAMPLES, samples_);
glfwWindowHint(GLFW_RED_BITS, 8);
glfwWindowHint(GLFW_GREEN_BITS, 8);
glfwWindowHint(GLFW_BLUE_BITS, 8);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
glfwWindowHint(GLFW_STENCIL_BITS, 8);
glfwWindowHint(GLFW_DEPTH_BITS, 24);
#ifndef __EMSCRIPTEN__
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
#else
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
#endif
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
/* I figure we don't need double buffering because the FBO (and the bound texture) is our backbuffer that
* we blit to the front on every iteration.
* On X11, wayland and in WASM it works and boosts performance a bit.
*/
glfwWindowHint(GLFW_DOUBLEBUFFER, GL_FALSE);
glfwWindow_ = glfwCreateWindow(initialSize_.width, initialSize_.height, title_.c_str(), nullptr,
nullptr);
if (glfwWindow_ == NULL) {
return false;
}
glfwMakeContextCurrent(getGLFWWindow());
screen_ = new nanogui::Screen();
@ -201,7 +145,7 @@ bool V4D::initializeWindowing() {
std::vector<nanogui::Widget*> widgets;
find_widgets(&v4d->screen(), widgets);
for (auto* w : widgets) {
auto mousePos = nanogui::Vector2i(v4d->getMousePosition()[0] / v4d->getXPixelRatio(), v4d->getMousePosition()[1] / v4d->getYPixelRatio());
auto mousePos = nanogui::Vector2i(v4d->getMousePosition()[0] / v4d->fb().getXPixelRatio(), v4d->getMousePosition()[1] / v4d->fb().getYPixelRatio());
if(contains_absolute(w, mousePos)) {
v4d->screen().scroll_callback_event(x, y);
return;
@ -223,10 +167,8 @@ bool V4D::initializeWindowing() {
v4d->screen().resize_callback_event(width, height);
});
clglContext_ = new detail::FrameBufferContext(this->getFrameBufferSize());
clvaContext_ = new detail::CLVAContext(*clglContext_);
nvgContext_ = new detail::NanoVGContext(*this, getNVGcontext(), *clglContext_);
cerr << "end init" << endl;
clvaContext_ = new detail::CLVAContext(*mainFramebufferContext_);
nvgContext_ = new detail::NanoVGContext(getNVGcontext(), *mainFramebufferContext_);
} catch(std::exception& ex) {
cerr << "V4D initialization failed: " << ex.what() << endl;
return false;
@ -235,7 +177,7 @@ bool V4D::initializeWindowing() {
}
cv::ogl::Texture2D& V4D::texture() {
return clglContext_->getTexture2D();
return mainFramebufferContext_->getTexture2D();
}
FormHelper& V4D::form() {
@ -255,9 +197,9 @@ bool V4D::keyboard_event(int key, int scancode, int action, int modifiers) {
}
FrameBufferContext& V4D::fb() {
assert(clglContext_ != nullptr);
makeCurrent();
return *clglContext_;
assert(mainFramebufferContext_ != nullptr);
mainFramebufferContext_->makeCurrent();
return *mainFramebufferContext_;
}
CLVAContext& V4D::clva() {
@ -267,13 +209,13 @@ CLVAContext& V4D::clva() {
NanoVGContext& V4D::nvg() {
assert(nvgContext_ != nullptr);
makeCurrent();
fb().makeCurrent();
return *nvgContext_;
}
nanogui::Screen& V4D::screen() {
assert(screen_ != nullptr);
makeCurrent();
fb().makeCurrent();
return *screen_;
}
@ -354,8 +296,8 @@ bool V4D::capture(std::function<void(cv::UMat&)> fn) {
currentReaderFrame_ = nextReaderFrame_;
{
FrameBufferContext::GLScope glScope(*clglContext_);
FrameBufferContext::FrameBufferScope fbScope(*clglContext_, readerFrameBuffer_);
FrameBufferContext::GLScope glScope(*mainFramebufferContext_);
FrameBufferContext::FrameBufferScope fbScope(*mainFramebufferContext_, readerFrameBuffer_);
currentReaderFrame_.copyTo(readerFrameBuffer_);
}
@ -388,8 +330,8 @@ void V4D::write(std::function<void(const cv::UMat&)> fn) {
futureWriter_.get();
{
FrameBufferContext::GLScope glScope(*clglContext_);
FrameBufferContext::FrameBufferScope fbScope(*clglContext_, writerFrameBuffer_);
FrameBufferContext::GLScope glScope(*mainFramebufferContext_);
FrameBufferContext::FrameBufferScope fbScope(*mainFramebufferContext_, writerFrameBuffer_);
writerFrameBuffer_.copyTo(currentWriterFrame_);
}
@ -402,14 +344,6 @@ bool V4D::isSinkReady() {
return sink_.isReady();
}
void V4D::makeCurrent() {
glfwMakeContextCurrent(getGLFWWindow());
}
void V4D::makeNoneCurrent() {
glfwMakeContextCurrent(nullptr);
}
void V4D::clear(const cv::Scalar& bgra) {
const float& b = bgra[0] / 255.0f;
const float& g = bgra[1] / 255.0f;
@ -505,7 +439,7 @@ void V4D::zoom(float factor) {
}
cv::Vec2f V4D::getPosition() {
makeCurrent();
fb().makeCurrent();
int x, y;
glfwGetWindowPos(getGLFWWindow(), &x, &y);
return {float(x), float(y)};
@ -528,7 +462,7 @@ cv::Rect V4D::getViewport() {
}
cv::Size V4D::getNativeFrameBufferSize() {
makeCurrent();
fb().makeCurrent();
int w, h;
glfwGetFramebufferSize(getGLFWWindow(), &w, &h);
return {w, h};
@ -539,7 +473,7 @@ cv::Size V4D::getFrameBufferSize() {
}
cv::Size V4D::getWindowSize() {
makeCurrent();
fb().makeCurrent();
int w, h;
glfwGetWindowSize(getGLFWWindow(), &w, &h);
return {w, h};
@ -549,40 +483,18 @@ cv::Size V4D::getInitialSize() {
return initialSize_;
}
float V4D::getXPixelRatio() {
makeCurrent();
#ifdef __EMSCRIPTEN__
return emscripten_get_device_pixel_ratio();
#else
float xscale, yscale;
glfwGetWindowContentScale(getGLFWWindow(), &xscale, &yscale);
return xscale;
#endif
}
float V4D::getYPixelRatio() {
makeCurrent();
#ifdef __EMSCRIPTEN__
return emscripten_get_device_pixel_ratio();
#else
float xscale, yscale;
glfwGetWindowContentScale(getGLFWWindow(), &xscale, &yscale);
return yscale;
#endif
}
void V4D::setWindowSize(const cv::Size& sz) {
makeCurrent();
screen().set_size(nanogui::Vector2i(sz.width / getXPixelRatio(), sz.height / getYPixelRatio()));
fb().makeCurrent();
screen().set_size(nanogui::Vector2i(sz.width / fb().getXPixelRatio(), sz.height / fb().getYPixelRatio()));
}
bool V4D::isFullscreen() {
makeCurrent();
fb().makeCurrent();
return glfwGetWindowMonitor(getGLFWWindow()) != nullptr;
}
void V4D::setFullscreen(bool f) {
makeCurrent();
fb().makeCurrent();
auto monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
if (f) {
@ -597,22 +509,22 @@ void V4D::setFullscreen(bool f) {
}
bool V4D::isResizable() {
makeCurrent();
fb().makeCurrent();
return glfwGetWindowAttrib(getGLFWWindow(), GLFW_RESIZABLE) == GLFW_TRUE;
}
void V4D::setResizable(bool r) {
makeCurrent();
fb().makeCurrent();
glfwWindowHint(GLFW_RESIZABLE, r ? GLFW_TRUE : GLFW_FALSE);
}
bool V4D::isVisible() {
makeCurrent();
fb().makeCurrent();
return glfwGetWindowAttrib(getGLFWWindow(), GLFW_VISIBLE) == GLFW_TRUE;
}
void V4D::setVisible(bool v) {
makeCurrent();
fb().makeCurrent();
glfwWindowHint(GLFW_VISIBLE, v ? GLFW_TRUE : GLFW_FALSE);
screen().set_visible(v);
screen().perform_layout();
@ -655,17 +567,17 @@ void V4D::setDefaultKeyboardEventCallback() {
bool V4D::display() {
bool result = true;
if (!offscreen_) {
makeCurrent();
fb().makeCurrent();
screen().draw_contents();
#ifndef __EMSCRIPTEN__
clglContext_->blitFrameBufferToScreen(getViewport(), getWindowSize(), isStretching());
mainFramebufferContext_->blitFrameBufferToScreen(getViewport(), getWindowSize(), isStretching());
#else
clglContext_->blitFrameBufferToScreen(getViewport(), getInitialSize(), isStretching());
mainFramebufferContext_->blitFrameBufferToScreen(getViewport(), getInitialSize(), isStretching());
#endif
screen().draw_widgets();
glfwSwapBuffers(glfwWindow_);
glfwSwapBuffers(getGLFWWindow());
glfwPollEvents();
result = !glfwWindowShouldClose(glfwWindow_);
result = !glfwWindowShouldClose(getGLFWWindow());
}
return result;
@ -681,7 +593,7 @@ void V4D::close() {
}
GLFWwindow* V4D::getGLFWWindow() {
return glfwWindow_;
return mainFramebufferContext_->getGLFWWindow();
}
NVGcontext* V4D::getNVGcontext() {

Loading…
Cancel
Save