c++ - QOpenGLWidget draw 2D texture in another thread -
i tried draw qopenglwidget
in thread , here code:
// widget.h class qglcanvas; class framerenderer: public qthread { q_object public: framerenderer(qglcanvas *parent); void run() q_decl_override; void stop(); void initialize(); void updateframe(std::shared_ptr<cv::mat> frame); qglcanvas *parent_; std::atomic<bool> thread_run_; bool initialize_; gluint texture_; std::shared_ptr<cv::mat> frame_; qmutex mutex_; }; class qglcanvas : public qopenglwidget, protected qopenglfunctions { q_object public: qglcanvas(qwidget* parent = null); virtual void initializegl(); virtual void paintgl(); virtual void resizegl(int width, int height); void showimage(std::shared_ptr<cv::mat> frame); // opengl rendering thread framerenderer* render_thread_; qtimer* render_timer_; private slots: void startrendering(); }; //widget.cpp #include "widget.h" framerenderer::framerenderer(qglcanvas* parent): qthread(), parent_(parent) { thread_run_ = true; initialize_ = false; frame_ = std::make_shared<cv::mat>(); cv::mat img = cv::imread("./res/no_image.jpg"); *frame_ = img; } void framerenderer::stop() { thread_run_ = false; } void framerenderer::initialize() { if(initialize_) return; glgentextures(1, &texture_); glbindtexture(gl_texture_2d, texture_); gltexparameteri(gl_texture_2d, gl_texture_mag_filter, gl_nearest); gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_nearest); glteximage2d(gl_texture_2d, 0, gl_rgb, frame_->cols, frame_->rows, 0, gl_rgb, gl_unsigned_byte, null); glbindtexture(gl_texture_2d, 0); initialize_ = true; } void framerenderer::run() { while(true) { qmutexlocker lock(&mutex_); if(!thread_run_) break; parent_->makecurrent(); if(!initialize_) initialize(); int width = parent_->width(), height = parent_->height(); glviewport(0, 0, width, height); glclearcolor(0, 0, 1, 1); gldisable(gl_depth_test); glenable(gl_texture_2d); glbindtexture(gl_texture_2d, texture_); gltexsubimage2d(gl_texture_2d, 0, 0, 0, frame_->cols, frame_->rows, gl_rgb, gl_unsigned_byte, frame_->data); glbegin(gl_quads); gltexcoord2f(0.0f, 1.0f); glvertex3f(0, 0, 0.0f); gltexcoord2f(1.0f, 1.0f); glvertex3f(width, 0.0f, 0.0f); gltexcoord2f(1.0f, 0.0f); glvertex3f(width, height, 0.0f); gltexcoord2f(0.0f, 0.0f); glvertex3f(0, height, 0.0f); glend(); gldisable(gl_texture_2d); parent_->donecurrent(); qmetaobject::invokemethod(parent_, "update"); msleep(40); } } void framerenderer::updateframe(std::shared_ptr<cv::mat> frame) { qmutexlocker lock(&mutex_); frame_ = frame; } qglcanvas::qglcanvas(qwidget* parent) : qopenglwidget(parent) { render_timer_ = new qtimer(this); qobject::connect(render_timer_, signal(timeout()), this, slot(startrendering())); render_timer_->start(1000); } void qglcanvas::initializegl() { } void qglcanvas::resizegl(int width, int height) { //stop qglwidget standard behavior } void qglcanvas::paintgl() { } void qglcanvas::startrendering() { donecurrent(); render_thread_ = new framerenderer(this); context()->movetothread(render_thread_); render_thread_->start(); } void qglcanvas::showimage(std::shared_ptr<cv::mat> frame) { if(render_thread_) render_thread_->updateframe(frame); } // main.cpp #include "widget.h" #include <qapplication> int main(int argc, char *argv[]) { qapplication app(argc, argv); // check threaded opengl supported. if (!qopenglcontext::supportsthreadedopengl()) { std::cerr << "threaded opengl not supported" << std::endl; return exit_failure; } // set wanted surface format. qsurfaceformat format; format.setdepthbuffersize(16); format.setversion(4, 4); format.setprofile(qsurfaceformat::coreprofile); qsurfaceformat::setdefaultformat(format); // calculate position of widget. widget should // located center @ center of desktop. const qdesktopwidget* desktop = qapplication::desktop(); const qsize size(720, 576); const qpoint position( desktop->width() / 2 - size.width() / 2, desktop->height() / 2 - size.height() / 2); // create opengl widget std::shared_ptr<qglcanvas> widget = std::make_shared<qglcanvas>(); widget->resize(size); widget->move(position); widget->show(); return app.exec(); }
the problem got error:
cannot make qopenglcontext current in thread.
i had similar code structure using qglwidget
. when changed qopenglwidget
, cannot work.
Comments
Post a Comment