fixed input event loss with multiple contexts

pull/3471/head
kallaballa 2 years ago
parent 442ab09c56
commit df33e5e3a7
  1. 3
      modules/v4d/include/opencv2/v4d/v4d.hpp
  2. 4
      modules/v4d/src/detail/clvacontext.cpp
  3. 82
      modules/v4d/src/detail/framebuffercontext.cpp
  4. 4
      modules/v4d/src/detail/framebuffercontext.hpp
  5. 7
      modules/v4d/src/detail/glcontext.cpp
  6. 2
      modules/v4d/src/detail/glcontext.hpp
  7. 4
      modules/v4d/src/detail/nanovgcontext.cpp
  8. 2
      modules/v4d/src/detail/nanovgcontext.hpp
  9. 121
      modules/v4d/src/v4d.cpp

@ -116,7 +116,8 @@ using namespace cv::v4d::detail;
class NVG;
class CV_EXPORTS V4D {
friend class NanoVGContext;
friend class detail::NanoVGContext;
friend class detail::FrameBufferContext;
const cv::Size initialSize_;
cv::Rect viewport_;
float scale_;

@ -11,8 +11,8 @@ namespace cv {
namespace v4d {
namespace detail {
CLVAContext::CLVAContext(FrameBufferContext& clglContext) :
mainFbContext_(clglContext) {
CLVAContext::CLVAContext(FrameBufferContext& mainFbContext) :
mainFbContext_(mainFbContext) {
}
cv::Size CLVAContext::getVideoFrameSize() {

@ -7,15 +7,17 @@
#include "opencv2/v4d/util.hpp"
#include "opencv2/v4d/v4d.hpp"
#include "glcontext.hpp"
#include "nanovgcontext.hpp"
namespace cv {
namespace v4d {
namespace detail {
FrameBufferContext::FrameBufferContext(const FrameBufferContext& other) : FrameBufferContext(other.frameBufferSize_, true, other.title_, other.major_, other.minor_, other.compat_, other.samples_, other.debug_, other.glfwWindow_, &other) {
FrameBufferContext::FrameBufferContext(V4D& v4d, const FrameBufferContext& other) : FrameBufferContext(v4d, other.frameBufferSize_, true, other.title_, other.major_, other.minor_, other.compat_, other.samples_, other.debug_, other.glfwWindow_, &other) {
}
FrameBufferContext::FrameBufferContext(const cv::Size& frameBufferSize, bool offscreen,
FrameBufferContext::FrameBufferContext(V4D& v4d, const cv::Size& frameBufferSize, bool offscreen,
const string& title, int major, int minor, bool compat, int samples, bool debug, GLFWwindow* sharedWindow, const FrameBufferContext* parent) :
offscreen_(offscreen), title_(title), major_(major), minor_(
minor), compat_(compat), samples_(samples), debug_(debug), frameBufferSize_(frameBufferSize), isShared_(sharedWindow != nullptr), parent_(parent) {
@ -94,6 +96,80 @@ FrameBufferContext::FrameBufferContext(const cv::Size& frameBufferSize, bool off
#ifndef __EMSCRIPTEN__
context_ = CLExecContext_t::getCurrent();
#endif
glfwSetWindowUserPointer(getGLFWWindow(), &v4d);
glfwSetCursorPosCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, double x, double y) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().cursor_pos_callback_event(x, y);
auto cursor = v4d->getMousePosition();
auto diff = cursor - cv::Vec2f(x, y);
if (v4d->isMouseDrag()) {
v4d->pan(diff[0], -diff[1]);
}
v4d->setMousePosition(x, y);
}
);
glfwSetMouseButtonCallback(getGLFWWindow(),
[](GLFWwindow* glfwWin, int button, int action, int modifiers) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().mouse_button_callback_event(button, action, modifiers);
if (button == GLFW_MOUSE_BUTTON_RIGHT) {
v4d->setMouseDrag(action == GLFW_PRESS);
}
}
);
glfwSetKeyCallback(getGLFWWindow(),
[](GLFWwindow* glfwWin, int key, int scancode, int action, int mods) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().key_callback_event(key, scancode, action, mods);
}
);
glfwSetCharCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, unsigned int codepoint) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().char_callback_event(codepoint);
}
);
glfwSetDropCallback(getGLFWWindow(),
[](GLFWwindow* glfwWin, int count, const char** filenames) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().drop_callback_event(count, filenames);
}
);
glfwSetScrollCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, double x, double y) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
std::vector<nanogui::Widget*> widgets;
find_widgets(&v4d->screen(), widgets);
for (auto* w : widgets) {
auto mousePos = nanogui::Vector2i(v4d->getMousePosition()[0] / v4d->fbCtx().getXPixelRatio(), v4d->getMousePosition()[1] / v4d->fbCtx().getYPixelRatio());
if(contains_absolute(w, mousePos)) {
v4d->screen().scroll_callback_event(x, y);
return;
}
}
v4d->zoom(y < 0 ? 1.1 : 0.9);
}
);
glfwSetFramebufferSizeCallback(getGLFWWindow(),
[](GLFWwindow* glfwWin, int width, int height) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().resize_callback_event(width, height);
cv::Rect& vp = v4d->viewport();
vp.x = 0;
vp.y = 0;
vp.width = width;
vp.height = height;
#ifndef __EMSCRIPTEN__
v4d->nvgCtx().fbCtx().teardown();
v4d->glCtx().fbCtx().teardown();
v4d->fbCtx().teardown();
v4d->fbCtx().setup(cv::Size(width, height));
v4d->glCtx().fbCtx().setup(cv::Size(width, height));
v4d->nvgCtx().fbCtx().setup(cv::Size(width, height));
#endif
});
}
FrameBufferContext::~FrameBufferContext() {
@ -380,6 +456,8 @@ void FrameBufferContext::releaseToGL(cv::UMat& m) {
if (clglSharing_) {
GL_CHECK(toGLTexture2D(m, getTexture2D()));
} else {
if(m.empty())
m.create(getSize(), CV_8UC4);
upload(m);
GL_CHECK(glFlush());
GL_CHECK(glFinish());

@ -143,10 +143,10 @@ public:
* Create a FrameBufferContext with given size.
* @param frameBufferSize The frame buffer size.
*/
FrameBufferContext(const cv::Size& frameBufferSize, bool offscreen,
FrameBufferContext(V4D& v4d, const cv::Size& frameBufferSize, bool offscreen,
const string& title, int major, int minor, bool compat, int samples, bool debug, GLFWwindow* sharedWindow, const FrameBufferContext* parent);
FrameBufferContext(const FrameBufferContext& other);
FrameBufferContext(V4D& v4d, const FrameBufferContext& other);
/*!
* Default destructor.

@ -8,12 +8,15 @@
namespace cv {
namespace v4d {
namespace detail {
GLContext::GLContext(FrameBufferContext& fbContext) :
mainFbContext_(fbContext), glFbContext_(fbContext) {
GLContext::GLContext(V4D& v4d, FrameBufferContext& fbContext) :
mainFbContext_(fbContext), glFbContext_(v4d, fbContext) {
}
void GLContext::render(std::function<void(const cv::Size&)> fn) {
#ifdef __EMSCRIPTEN__
fb_.create(mainFbContext_.getSize(), CV_8UC4);
preFB_.create(mainFbContext_.getSize(), CV_8UC4);
postFB_.create(mainFbContext_.getSize(), CV_8UC4);
{
FrameBufferContext::GLScope mainGlScope(mainFbContext_);
FrameBufferContext::FrameBufferScope fbScope(mainFbContext_, fb_);

@ -41,7 +41,7 @@ public:
* Creates a OpenGL Context
* @param fbContext The framebuffer context
*/
GLContext(FrameBufferContext& fbContext);
GLContext(V4D& v4d, FrameBufferContext& fbContext);
/*!
* Execute function object fn inside a gl context.
* The context takes care of setting up opengl states.

@ -8,8 +8,8 @@
namespace cv {
namespace v4d {
namespace detail {
NanoVGContext::NanoVGContext(FrameBufferContext& fbContext) :
mainFbContext_(fbContext), nvgFbContext_(fbContext) {
NanoVGContext::NanoVGContext(V4D& v4d, FrameBufferContext& fbContext) :
mainFbContext_(fbContext), nvgFbContext_(v4d, fbContext) {
screen_ = new nanogui::Screen();
screen_->initialize(nvgFbContext_.getGLFWWindow(), false);
context_ = screen_->nvg_context();

@ -65,7 +65,7 @@ public:
* @param context The native NVGContext
* @param fbContext The framebuffer context
*/
NanoVGContext(FrameBufferContext& fbContext);
NanoVGContext(V4D& v4d, FrameBufferContext& fbContext);
/*!
* Execute function object fn inside a nanovg context.
* The context takes care of setting up opengl and nanovg states.

@ -79,15 +79,19 @@ V4D::V4D(const cv::Size& size, bool offscreen, const string& title, int major, i
bool compat, int samples, bool debug) :
initialSize_(size), viewport_(0, 0, size.width, size.height), scale_(1), mousePos_(0, 0), stretch_(
false), offscreen_(offscreen) {
mainFbContext_ = new detail::FrameBufferContext(size, offscreen, title,
screen_ = new nanogui::Screen();
mainFbContext_ = new detail::FrameBufferContext(*this, size, offscreen, title,
major, minor, compat, samples, debug, nullptr, nullptr);
clvaContext_ = new detail::CLVAContext(*mainFbContext_);
glContext_ = new detail::GLContext(*mainFbContext_);
nvgContext_ = new detail::NanoVGContext(*mainFbContext_);
glContext_ = new detail::GLContext(*this, *mainFbContext_);
nvgContext_ = new detail::NanoVGContext(*this, *mainFbContext_);
if (!initializeGUI())
assert(false);
fbCtx().makeCurrent();
screen().initialize(getGLFWWindow(), false);
form_ = new FormHelper(&screen());
this->setWindowSize(initialSize_);
}
V4D::~V4D() {
@ -108,112 +112,6 @@ V4D::~V4D() {
delete mainFbContext_;
}
bool V4D::initializeGUI() {
try {
screen_ = new nanogui::Screen();
screen().initialize(getGLFWWindow(), false);
form_ = new FormHelper(&screen());
this->setWindowSize(initialSize_);
glfwSetWindowUserPointer(getGLFWWindow(), this);
glfwSetCursorPosCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, double x, double y) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().cursor_pos_callback_event(x, y);
auto cursor = v4d->getMousePosition();
auto diff = cursor - cv::Vec2f(x, y);
if (v4d->isMouseDrag()) {
v4d->pan(diff[0], -diff[1]);
}
v4d->setMousePosition(x, y);
}
);
glfwSetMouseButtonCallback(getGLFWWindow(),
[](GLFWwindow* glfwWin, int button, int action, int modifiers) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().mouse_button_callback_event(button, action, modifiers);
if (button == GLFW_MOUSE_BUTTON_RIGHT) {
v4d->setMouseDrag(action == GLFW_PRESS);
}
}
);
glfwSetKeyCallback(getGLFWWindow(),
[](GLFWwindow* glfwWin, int key, int scancode, int action, int mods) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().key_callback_event(key, scancode, action, mods);
}
);
glfwSetCharCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, unsigned int codepoint) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().char_callback_event(codepoint);
}
);
glfwSetDropCallback(getGLFWWindow(),
[](GLFWwindow* glfwWin, int count, const char** filenames) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().drop_callback_event(count, filenames);
}
);
glfwSetScrollCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, double x, double y) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
std::vector<nanogui::Widget*> widgets;
find_widgets(&v4d->screen(), widgets);
for (auto* w : widgets) {
auto mousePos = nanogui::Vector2i(v4d->getMousePosition()[0] / v4d->fbCtx().getXPixelRatio(), v4d->getMousePosition()[1] / v4d->fbCtx().getYPixelRatio());
if(contains_absolute(w, mousePos)) {
v4d->screen().scroll_callback_event(x, y);
return;
}
}
v4d->zoom(y < 0 ? 1.1 : 0.9);
}
);
// glfwSetWindowSizeCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, int width, int height) {
// V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
// GLFWmonitor* monitor = glfwGetPrimaryMonitor();
// const GLFWvidmode* mode = glfwGetVideoMode(monitor);
// int w = mode->width;
// int h = mode->height;
//
//// v4d->screen().resize_callback_event(width, height);
// if (width <= w && height <= h) {
// cerr << "winsize: " << width << ":" << height << endl;
// v4d->nvgCtx().fbCtx().teardown();
// v4d->glCtx().fbCtx().teardown();
// v4d->fbCtx().teardown();
// v4d->fbCtx().setup(cv::Size(width, height));
// v4d->glCtx().fbCtx().setup(cv::Size(width, height));
// v4d->nvgCtx().fbCtx().setup(cv::Size(width, height));
// }
// });
glfwSetFramebufferSizeCallback(getGLFWWindow(),
[](GLFWwindow* glfwWin, int width, int height) {
V4D* v4d = reinterpret_cast<V4D*>(glfwGetWindowUserPointer(glfwWin));
v4d->screen().resize_callback_event(width, height);
cv::Rect& vp = v4d->viewport();
vp.x = 0;
vp.y = 0;
vp.width = width;
vp.height = height;
#ifndef __EMSCRIPTEN__
v4d->nvgCtx().fbCtx().teardown();
v4d->glCtx().fbCtx().teardown();
v4d->fbCtx().teardown();
v4d->fbCtx().setup(cv::Size(width, height));
v4d->glCtx().fbCtx().setup(cv::Size(width, height));
v4d->nvgCtx().fbCtx().setup(cv::Size(width, height));
#endif
});
} catch (std::exception& ex) {
cerr << "V4D initialization failed: " << ex.what() << endl;
return false;
}
return true;
}
cv::ogl::Texture2D& V4D::texture() {
return mainFbContext_->getTexture2D();
}
@ -259,7 +157,6 @@ GLContext& V4D::glCtx() {
nanogui::Screen& V4D::screen() {
assert(screen_ != nullptr);
fbCtx().makeCurrent();
return *screen_;
}

Loading…
Cancel
Save