From a3eee7be24126f5a3458d488f44cd61c66135e17 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 13 Mar 2014 19:54:10 +0100 Subject: [PATCH] Various changes for getting an OpenGL context (almost) everywhere it is needed. --- src/clipmanager.cpp | 12 +++++++++++- src/clipmanager.h | 4 +++- src/dvdwizardchapters.cpp | 2 +- src/kdenlivedoc.cpp | 4 ++-- src/kdenlivedoc.h | 3 ++- src/kthumb.cpp | 5 +++++ src/mainwindow.cpp | 19 +++++++++++++----- src/mainwindow.h | 3 +++ src/monitor.cpp | 10 +++++++--- src/monitor.h | 4 +++- src/projectlist.cpp | 8 +++++++- src/projectlist.h | 4 +++- src/renderer.cpp | 15 +++++++++++++-- src/renderer.h | 7 ++++++- src/widgets/videoglwidget.cpp | 36 +++++++++++++++++++++++++++++++++-- src/widgets/videoglwidget.h | 5 +++-- 16 files changed, 117 insertions(+), 24 deletions(-) diff --git a/src/clipmanager.cpp b/src/clipmanager.cpp index 584955a4..22fee755 100644 --- a/src/clipmanager.cpp +++ b/src/clipmanager.cpp @@ -45,12 +45,14 @@ #include #include +#include #include -ClipManager::ClipManager(KdenliveDoc *doc) : +ClipManager::ClipManager(KdenliveDoc *doc, QGLWidget *glContext) : QObject(), + m_mainGLContext(glContext), m_audioThumbsQueue(), m_doc(doc), m_abortThumb(false), @@ -165,6 +167,10 @@ void ClipManager::stopThumbs(const QString &id) void ClipManager::slotGetThumbs() { + // We are in a new thread, so we need a new OpenGL context for the remainder of the function. + QGLWidget ctx(0, m_mainGLContext); + ctx.makeCurrent(); + QMap::const_iterator i; int max; int done = 0; @@ -251,6 +257,10 @@ void ClipManager::askForAudioThumb(const QString &id) void ClipManager::slotGetAudioThumbs() { + // We are in a new thread, so we need a new OpenGL context for the remainder of the function. + QGLWidget ctx(0, m_mainGLContext); + ctx.makeCurrent(); + Mlt::Profile prof((char*) KdenliveSettings::current_profile().toUtf8().constData()); mlt_audio_format audioFormat = mlt_audio_s16; while (!m_abortAudioThumb && !m_audioThumbsQueue.isEmpty()) { diff --git a/src/clipmanager.h b/src/clipmanager.h index a33a96df..172d0d52 100644 --- a/src/clipmanager.h +++ b/src/clipmanager.h @@ -52,6 +52,7 @@ class KdenliveDoc; class DocClipBase; class AbstractGroupItem; +class QGLWidget; class SolidVolumeInfo @@ -76,7 +77,7 @@ class ClipManager: public QObject { Q_OBJECT public: - ClipManager(KdenliveDoc *doc); + ClipManager(KdenliveDoc *doc, QGLWidget *glContext); virtual ~ ClipManager(); void addClip(DocClipBase *clip); DocClipBase *getClipAt(int pos); @@ -147,6 +148,7 @@ private slots: void slotAddClip(KIO::Job *job, const KUrl &, const KUrl &dst); private: // Private attributes + QGLWidget *m_mainGLContext; /** the list of clips in the document */ QList m_clipList; /** the list of groups in the document */ diff --git a/src/dvdwizardchapters.cpp b/src/dvdwizardchapters.cpp index d997e15b..35aaf02e 100644 --- a/src/dvdwizardchapters.cpp +++ b/src/dvdwizardchapters.cpp @@ -154,7 +154,7 @@ void DvdWizardChapters::createMonitor(DVDFORMAT format) { QString profile = DvdWizardVob::getDvdProfile(format); if (m_monitor == NULL) { - m_monitor = new Monitor(Kdenlive::DvdMonitor, m_manager, profile, this); + m_monitor = new Monitor(Kdenlive::DvdMonitor, m_manager, NULL, profile, this); //m_monitor->start(); QVBoxLayout *vbox = new QVBoxLayout; vbox->addWidget(m_monitor); diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index 14611b42..127cd32c 100644 --- a/src/kdenlivedoc.cpp +++ b/src/kdenlivedoc.cpp @@ -61,7 +61,7 @@ const double DOCUMENTVERSION = 0.88; -KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QMap & properties, const QMap & metadata, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, MainWindow *parent, KProgressDialog *progressDialog) : +KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QMap & properties, const QMap & metadata, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, QGLWidget *glContext, MainWindow *parent, KProgressDialog *progressDialog) : QObject(parent), m_autosave(NULL), m_url(url), @@ -83,7 +83,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup m_profile.display_aspect_den = 0; m_profile.colorspace = 0; - m_clipManager = new ClipManager(this); + m_clipManager = new ClipManager(this, glContext); m_autoSaveTimer = new QTimer(this); m_autoSaveTimer->setSingleShot(true); connect(m_clipManager, SIGNAL(displayMessage(QString,int)), parent, SLOT(slotGotProgressInfo(QString,int))); diff --git a/src/kdenlivedoc.h b/src/kdenlivedoc.h index 448470d7..8acf6328 100644 --- a/src/kdenlivedoc.h +++ b/src/kdenlivedoc.h @@ -43,6 +43,7 @@ class TrackInfo; class KTextEdit; class KProgressDialog; +class QGLWidget; class QUndoGroup; class QTimer; class QUndoStack; @@ -52,7 +53,7 @@ class KdenliveDoc: public QObject Q_OBJECT public: - KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QMap & properties, const QMap & metadata, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, MainWindow *parent = 0, KProgressDialog *progressDialog = 0); + KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QMap & properties, const QMap & metadata, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, QGLWidget *glContext, MainWindow *parent = 0, KProgressDialog *progressDialog = 0); ~KdenliveDoc(); QDomNodeList producersList(); double fps() const; diff --git a/src/kthumb.cpp b/src/kthumb.cpp index 3bf19e28..5a81f548 100644 --- a/src/kthumb.cpp +++ b/src/kthumb.cpp @@ -40,6 +40,7 @@ #include #include #include +#include KThumb::KThumb(ClipManager *clipManager, const KUrl &url, const QString &id, const QString &hash, QObject * parent) : QObject(parent), @@ -376,6 +377,10 @@ void KThumb::queryIntraThumbs(const QList &missingFrames) void KThumb::slotGetIntraThumbs() { + // We are in a new thread, so we need a new OpenGL context for the remainder of the function. + QGLWidget ctx(0, m_clipManager->getMainContext()); + ctx.makeCurrent(); + const int theight = KdenliveSettings::trackheight(); const int frameWidth = (int)(theight * m_ratio + 0.5); const int displayWidth = (int)(theight * m_dar + 0.5); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 41b5a102..dd1d83c9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -114,6 +114,7 @@ #include #include #include +#include #include #include @@ -149,6 +150,7 @@ static bool sortByNames(const QPair &a, const QPairresize(0, 0); + m_commandStack = new QUndoGroup; setDockNestingEnabled(true); m_timelineArea = new KTabWidget(this); @@ -228,13 +236,13 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_projectListDock = new QDockWidget(i18n("Project Tree"), this); m_projectListDock->setObjectName("project_tree"); - m_projectList = new ProjectList(); + m_projectList = new ProjectList(m_glContext); m_projectListDock->setWidget(m_projectList); addDockWidget(Qt::TopDockWidgetArea, m_projectListDock); m_clipMonitorDock = new QDockWidget(i18n("Clip Monitor"), this); m_clipMonitorDock->setObjectName("clip_monitor"); - m_clipMonitor = new Monitor(Kdenlive::ClipMonitor, m_monitorManager, QString(), m_timelineArea); + m_clipMonitor = new Monitor(Kdenlive::ClipMonitor, m_monitorManager, m_glContext, QString(), m_timelineArea); m_clipMonitorDock->setWidget(m_clipMonitor); // Connect the project list @@ -252,7 +260,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this); m_projectMonitorDock->setObjectName("project_monitor"); - m_projectMonitor = new Monitor(Kdenlive::ProjectMonitor, m_monitorManager, QString()); + m_projectMonitor = new Monitor(Kdenlive::ProjectMonitor, m_monitorManager, m_glContext, QString()); m_projectMonitorDock->setWidget(m_projectMonitor); #ifndef Q_WS_MAC @@ -720,6 +728,7 @@ MainWindow::~MainWindow() delete m_monitorManager; delete m_scopeManager; Mlt::Factory::close(); + delete m_glContext; } //virtual @@ -1999,7 +2008,7 @@ void MainWindow::newFile(bool showProjectSettings, bool force) m_timelineArea->setEnabled(true); m_projectList->setEnabled(true); bool openBackup; - KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, documentProperties, documentMetadata, projectTracks, m_projectMonitor->render, m_notesWidget, &openBackup, this); + KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, documentProperties, documentMetadata, projectTracks, m_projectMonitor->render, m_notesWidget, &openBackup, m_glContext, this); doc->m_autosave = new KAutoSaveFile(KUrl(), doc); bool ok; TrackView *trackView = new TrackView(doc, m_tracksActionCollection->actions(), &ok, this); @@ -2283,7 +2292,7 @@ void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale) progressDialog.progressBar()->setValue(0); bool openBackup; - KdenliveDoc *doc = new KdenliveDoc(stale ? KUrl(stale->fileName()) : url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap (), QMap (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, &openBackup, this, &progressDialog); + KdenliveDoc *doc = new KdenliveDoc(stale ? KUrl(stale->fileName()) : url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap (), QMap (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, &openBackup, m_glContext, this, &progressDialog); progressDialog.progressBar()->setValue(1); progressDialog.progressBar()->setMaximum(4); diff --git a/src/mainwindow.h b/src/mainwindow.h index 17904251..8b631dab 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -78,6 +78,7 @@ class KActionCollection; class AudioSignal; class AudioSpectrum; class Spectrogram; +class QGLWidget; class MainWindow : public KXmlGuiWindow { @@ -141,6 +142,8 @@ protected: virtual void readProperties(const KConfigGroup &config); private: + QGLWidget* m_glContext; + KTabWidget* m_timelineArea; QProgressBar *m_statusProgressBar; diff --git a/src/monitor.cpp b/src/monitor.cpp index b2c43060..29a7a3d8 100644 --- a/src/monitor.cpp +++ b/src/monitor.cpp @@ -24,6 +24,8 @@ #include "abstractclipitem.h" #include "monitorscene.h" #include "widgets/monitoreditwidget.h" +#include "widgets/videosurface.h" +#include "widgets/videoglwidget.h" #include "kdenlivesettings.h" #include @@ -48,7 +50,7 @@ #define SEEK_INACTIVE (-1) -Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QString profile, QWidget *parent) : +Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QGLWidget *glContext, QString profile, QWidget *parent) : AbstractMonitor(id, manager, parent) , render(NULL) , m_currentClip(NULL) @@ -61,6 +63,7 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QString profil , m_effectWidget(NULL) , m_selectedClip(NULL) , m_loopClipTransition(true) + , m_parentGLContext(glContext) , m_glWidget(NULL) , m_editMarker(NULL) { @@ -209,8 +212,8 @@ QWidget *Monitor::container() void Monitor::createOpenGlWidget(QWidget *parent, const QString &profile) { - render = new Render(id(), 0, profile, this); - m_glWidget = new VideoGLWidget(parent); + m_glWidget = new VideoGLWidget(parent, m_parentGLContext); + render = new Render(id(), 0, profile, this, m_glWidget); if (m_glWidget == NULL) { // Creation failed, we are in trouble... QMessageBox::critical(this, i18n("Missing OpenGL support"), @@ -220,6 +223,7 @@ void Monitor::createOpenGlWidget(QWidget *parent, const QString &profile) m_glWidget->setImageAspectRatio(render->dar()); m_glWidget->setBackgroundColor(KdenliveSettings::window_background()); connect(render, SIGNAL(showImageSignal(QImage)), m_glWidget, SLOT(showImage(QImage))); + connect(render, SIGNAL(showImageSignal(GLuint)), m_glWidget, SLOT(showImage(GLuint))); } void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMenu *markerMenu, QAction *loopClip) diff --git a/src/monitor.h b/src/monitor.h index 604dd39a..d3f1ba93 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -67,7 +67,7 @@ class Monitor : public AbstractMonitor Q_OBJECT public: - Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QString profile = QString(), QWidget *parent = 0); + Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QGLWidget *glContext, QString profile = QString(), QWidget *parent = 0); ~Monitor(); Render *render; AbstractRender *abstractRender(); @@ -141,6 +141,8 @@ private: /** true if selected clip is transition, false = selected clip is clip. * Necessary because sometimes we get two signals, e.g. we get a clip and we get selected transition = NULL. */ bool m_loopClipTransition; + + QGLWidget *m_parentGLContext; VideoGLWidget *m_glWidget; void createOpenGlWidget(QWidget *parent, const QString &profile); diff --git a/src/projectlist.cpp b/src/projectlist.cpp index 8cca3fa3..fcbc8e56 100644 --- a/src/projectlist.cpp +++ b/src/projectlist.cpp @@ -86,6 +86,7 @@ #include #include #include +#include MyMessageWidget::MyMessageWidget(QWidget *parent) : KMessageWidget(parent) {} @@ -185,7 +186,7 @@ void SmallInfoLabel::slotSetJobCount(int jobCount) } -ProjectList::ProjectList(QWidget *parent) : +ProjectList::ProjectList(QGLWidget *glContext, QWidget *parent) : QWidget(parent) , m_render(NULL) , m_fps(-1) @@ -204,6 +205,7 @@ ProjectList::ProjectList(QWidget *parent) : , m_abortAllJobs(false) , m_closing(false) , m_invalidClipDialog(NULL) + , m_mainGLContext(glContext) { qRegisterMetaType ("stringMap"); QVBoxLayout *layout = new QVBoxLayout; @@ -1531,6 +1533,10 @@ void ProjectList::getCachedThumbnail(SubProjectItem *item) void ProjectList::updateAllClips(bool displayRatioChanged, bool fpsChanged, const QStringList &brokenClips) { + // We are in a new thread, so we need a new OpenGL context for the remainder of the function. + QGLWidget ctx(0, m_mainGLContext); + ctx.makeCurrent(); + if (!m_allClipsProcessed) m_listView->setEnabled(false); m_listView->setSortingEnabled(false); QTreeWidgetItemIterator it(m_listView); diff --git a/src/projectlist.h b/src/projectlist.h index 4cb49734..bd80c8b8 100644 --- a/src/projectlist.h +++ b/src/projectlist.h @@ -100,6 +100,7 @@ class KdenliveDoc; class DocClipBase; class AbstractClipJob; class ItemDelegate; +class QGLWidget; class SmallInfoLabel: public QPushButton { @@ -129,7 +130,7 @@ class ProjectList : public QWidget Q_OBJECT public: - ProjectList(QWidget *parent = 0); + ProjectList(QGLWidget *glContext, QWidget *parent = 0); virtual ~ProjectList(); QDomElement producersList(); @@ -280,6 +281,7 @@ private: /** @brief The action that will trigger the log dialog. */ QAction *m_logAction; #endif + QGLWidget *m_mainGLContext; void requestClipThumbnail(const QString &id); diff --git a/src/renderer.cpp b/src/renderer.cpp index b3142223..d141a4f6 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -111,7 +111,7 @@ void Render::consumer_gl_frame_show(mlt_consumer consumer, Render * self, mlt_fr emit self->mltFrameReceived(new Mlt::Frame(frame_ptr)); } -Render::Render(Kdenlive::MonitorId rendererName, int winid, QString profile, QWidget *parent) : +Render::Render(Kdenlive::MonitorId rendererName, int winid, QString profile, QWidget *parent, QGLWidget *mainGLContext) : AbstractRender(rendererName, parent), requestedSeekPosition(SEEK_INACTIVE), showFrameSemaphore(1), @@ -128,7 +128,9 @@ Render::Render(Kdenlive::MonitorId rendererName, int winid, QString profile, QWi m_blackClip(NULL), m_winid(winid), m_paused(true), - m_isActive(false) + m_isActive(false), + m_mainGLContext(mainGLContext), + m_GLContext(NULL) { qRegisterMetaType ("stringMap"); analyseAudio = KdenliveSettings::monitor_audio(); @@ -140,16 +142,21 @@ Render::Render(Kdenlive::MonitorId rendererName, int winid, QString profile, QWi m_mltProducer->set_speed(0.0); m_refreshTimer.setSingleShot(true); m_refreshTimer.setInterval(100); + m_glslManager = new Mlt::Filter(*m_mltProfile, "glsl.manager"); connect(&m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh())); connect(this, SIGNAL(multiStreamFound(QString,QList,QList,stringMap)), this, SLOT(slotMultiStreamProducerFound(QString,QList,QList,stringMap))); connect(this, SIGNAL(checkSeeking()), this, SLOT(slotCheckSeeking())); connect(this, SIGNAL(mltFrameReceived(Mlt::Frame*)), this, SLOT(showFrame(Mlt::Frame*)), Qt::UniqueConnection); + + m_GLContext = new QGLWidget(0, m_mainGLContext); + m_GLContext->resize(0, 0); } Render::~Render() { closeMlt(); delete m_mltProfile; + delete m_GLContext; } @@ -704,6 +711,10 @@ bool Render::isProcessing(const QString &id) void Render::processFileProperties() { + // We are in a new thread, so we need a new OpenGL context for the remainder of the function. + QGLWidget ctx(0, m_mainGLContext); + ctx.makeCurrent(); + requestClipInfo info; QLocale locale; while (!m_requestList.isEmpty()) { diff --git a/src/renderer.h b/src/renderer.h index cf36dae0..96e23dce 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -47,6 +47,7 @@ #include #include +class QGLWidget; class QPixmap; class KComboBox; @@ -109,7 +110,7 @@ class Render: public AbstractRender * @param rendererName A unique identifier for this renderer * @param winid The parent widget identifier (required for SDL display). Set to 0 for OpenGL rendering * @param profile The MLT profile used for the renderer (default one will be used if empty). */ - Render(Kdenlive::MonitorId rendererName, int winid, QString profile = QString(), QWidget *parent = 0); + Render(Kdenlive::MonitorId rendererName, int winid, QString profile = QString(), QWidget *parent = 0, QGLWidget *mainGLContext = 0); /** @brief Destroy the MLT Renderer. */ virtual ~Render(); @@ -399,6 +400,9 @@ private: bool m_paused; /** @brief True if this monitor is active. */ bool m_isActive; + QGLWidget *m_mainGLContext; + QGLWidget *m_GLContext; + Mlt::Filter* m_glslManager; void closeMlt(); void mltCheckLength(Mlt::Tractor *tractor); @@ -477,6 +481,7 @@ signals: * * Used in Mac OS X. */ void showImageSignal(QImage); + void showImageSignal(GLuint); void showAudioSignal(const QVector &); void addClip(const KUrl &, stringMap); void checkSeeking(); diff --git a/src/widgets/videoglwidget.cpp b/src/widgets/videoglwidget.cpp index 375f2d6b..a37d529d 100644 --- a/src/widgets/videoglwidget.cpp +++ b/src/widgets/videoglwidget.cpp @@ -31,8 +31,8 @@ #define GL_TEXTURE_RECTANGLE_EXT GL_TEXTURE_RECTANGLE_NV #endif -VideoGLWidget::VideoGLWidget(QWidget *parent) - : QGLWidget(parent) +VideoGLWidget::VideoGLWidget(QWidget *parent, QGLWidget *share) + : QGLWidget(parent, share) , x(0) , y(0) , w(width()) @@ -40,6 +40,7 @@ VideoGLWidget::VideoGLWidget(QWidget *parent) , m_image_width(0) , m_image_height(0) , m_texture(0) + , m_other_texture(0) , m_display_ratio(4.0 / 3.0) , m_backgroundColor(Qt::gray) { @@ -146,6 +147,24 @@ void VideoGLWidget::paintGL() glEnd(); glDisable(GL_TEXTURE_RECTANGLE_EXT); } + if (m_other_texture) { +#ifdef Q_WS_MAC + glClear(GL_COLOR_BUFFER_BIT); +#endif + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, m_other_texture); + glBegin(GL_QUADS); + glTexCoord2i(0, 0); + glVertex2i(x, y); + glTexCoord2i(1, 0); + glVertex2i(x + w, y); + glTexCoord2i(1, 1); + glVertex2i(x + w, y + h); + glTexCoord2i(0, 1); + glVertex2i(x, y + h); + glEnd(); + glDisable(GL_TEXTURE_2D); + } } void VideoGLWidget::showImage(const QImage &image) @@ -155,6 +174,7 @@ void VideoGLWidget::showImage(const QImage &image) makeCurrent(); if (m_texture) glDeleteTextures(1, &m_texture); + m_other_texture = 0; glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image_width); glGenTextures(1, &m_texture); @@ -166,6 +186,18 @@ void VideoGLWidget::showImage(const QImage &image) updateGL(); } +void VideoGLWidget::showImage(GLuint texnum) +{ + makeCurrent(); + if (m_texture) { + glDeleteTextures(1, &m_texture); + m_texture = 0; + } + m_other_texture = texnum; + + updateGL(); +} + void VideoGLWidget::mouseDoubleClickEvent(QMouseEvent * event) { // TODO: disable screensaver? diff --git a/src/widgets/videoglwidget.h b/src/widgets/videoglwidget.h index de2304f4..918cb117 100644 --- a/src/widgets/videoglwidget.h +++ b/src/widgets/videoglwidget.h @@ -28,7 +28,7 @@ class VideoGLWidget : public QGLWidget Q_OBJECT public: - explicit VideoGLWidget(QWidget *parent = 0); + explicit VideoGLWidget(QWidget *parent = 0, QGLWidget *share = 0); ~VideoGLWidget(); void activateMonitor(); QSize minimumSizeHint() const; @@ -40,6 +40,7 @@ public: public slots: void showImage(const QImage &image); + void showImage(GLuint); protected: void initializeGL(); @@ -51,7 +52,7 @@ protected: private: int x, y, w, h; int m_image_width, m_image_height; - GLuint m_texture; + GLuint m_texture, m_other_texture; double m_display_ratio; QColor m_backgroundColor; Qt::WindowFlags m_baseFlags; -- 2.39.2