From: Steinar H. Gunderson Date: Sun, 12 Jan 2014 13:00:50 +0000 (+0100) Subject: Fix jittering issues when sending GL textures cross-thread. X-Git-Url: https://git.sesse.net/?p=kdenlive;a=commitdiff_plain;h=234d7fe2828b8e82253548e32081576fc56cbb80 Fix jittering issues when sending GL textures cross-thread. When rendering into a texture on one thread and rendering _from_ it on another, we need to properly synchronize the client state. Hook onto the OpenGL fences that MLT set to properly wait for the rendering commands to be sent to the GPU, which fixes the jittering we'd otherwise see, due to rendering old frames still left in the textures because the new ones are not ready yet. --- diff --git a/src/monitor.cpp b/src/monitor.cpp index 29a7a3d8..5d562637 100644 --- a/src/monitor.cpp +++ b/src/monitor.cpp @@ -223,7 +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))); + connect(render, SIGNAL(showImageSignal(Mlt::Frame*, GLuint)), m_glWidget, SLOT(showImage(Mlt::Frame*, GLuint))); } void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMenu *markerMenu, QAction *loopClip) diff --git a/src/renderer.cpp b/src/renderer.cpp index 19067517..880a9653 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -22,7 +22,6 @@ * * ***************************************************************************/ - #include "renderer.h" #include "kdenlivesettings.h" #include "kthumb.h" @@ -1954,8 +1953,7 @@ void Render::showFrame(Mlt::Frame* frame) const uint8_t* image = frame->get_image(format, width, height); const GLuint* texnum = (GLuint *)image; if (format == mlt_image_glsl_texture) { - emit showImageSignal(*texnum); - delete frame; + emit showImageSignal(frame, *texnum); } else { QImage qimage(width, height, QImage::Format_ARGB32_Premultiplied); memcpy(qimage.scanLine(0), image, width * height * 4); diff --git a/src/renderer.h b/src/renderer.h index 43be7b8b..6910f427 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -33,6 +33,7 @@ #include "definitions.h" #include "widgets/abstractmonitor.h" +#include #include #include @@ -486,7 +487,7 @@ signals: * * Used in Mac OS X. */ void showImageSignal(QImage); - void showImageSignal(GLuint); + void showImageSignal(Mlt::Frame*, 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 a37d529d..3c62742e 100644 --- a/src/widgets/videoglwidget.cpp +++ b/src/widgets/videoglwidget.cpp @@ -26,6 +26,10 @@ #include #endif #include "widgets/videoglwidget.h" +extern "C" { +GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +} +#include #ifndef GL_TEXTURE_RECTANGLE_EXT #define GL_TEXTURE_RECTANGLE_EXT GL_TEXTURE_RECTANGLE_NV @@ -40,7 +44,8 @@ VideoGLWidget::VideoGLWidget(QWidget *parent, QGLWidget *share) , m_image_width(0) , m_image_height(0) , m_texture(0) - , m_other_texture(0) + , m_frame(NULL) + , m_frame_texture(0) , m_display_ratio(4.0 / 3.0) , m_backgroundColor(Qt::gray) { @@ -53,6 +58,7 @@ VideoGLWidget::~VideoGLWidget() makeCurrent(); if (m_texture) glDeleteTextures(1, &m_texture); + // m_frame will be cleaned up when the profile is closed by Render. } QSize VideoGLWidget::minimumSizeHint() const @@ -147,12 +153,12 @@ void VideoGLWidget::paintGL() glEnd(); glDisable(GL_TEXTURE_RECTANGLE_EXT); } - if (m_other_texture) { + if (m_frame_texture) { #ifdef Q_WS_MAC glClear(GL_COLOR_BUFFER_BIT); #endif glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, m_other_texture); + glBindTexture(GL_TEXTURE_2D, m_frame_texture); glBegin(GL_QUADS); glTexCoord2i(0, 0); glVertex2i(x, y); @@ -174,7 +180,9 @@ void VideoGLWidget::showImage(const QImage &image) makeCurrent(); if (m_texture) glDeleteTextures(1, &m_texture); - m_other_texture = 0; + delete m_frame; + m_frame = NULL; + m_frame_texture = 0; glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image_width); glGenTextures(1, &m_texture); @@ -186,14 +194,18 @@ void VideoGLWidget::showImage(const QImage &image) updateGL(); } -void VideoGLWidget::showImage(GLuint texnum) +void VideoGLWidget::showImage(Mlt::Frame* frame, GLuint texnum) { makeCurrent(); + GLsync sync = (GLsync) frame->get("movit.convert.fence"); + glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED); if (m_texture) { glDeleteTextures(1, &m_texture); m_texture = 0; } - m_other_texture = texnum; + delete m_frame; + m_frame = frame; + m_frame_texture = texnum; updateGL(); } diff --git a/src/widgets/videoglwidget.h b/src/widgets/videoglwidget.h index 918cb117..0598d133 100644 --- a/src/widgets/videoglwidget.h +++ b/src/widgets/videoglwidget.h @@ -23,6 +23,10 @@ #include +namespace Mlt { +class Frame; +} + class VideoGLWidget : public QGLWidget { Q_OBJECT @@ -40,7 +44,7 @@ public: public slots: void showImage(const QImage &image); - void showImage(GLuint); + void showImage(Mlt::Frame*, GLuint); protected: void initializeGL(); @@ -52,7 +56,9 @@ protected: private: int x, y, w, h; int m_image_width, m_image_height; - GLuint m_texture, m_other_texture; + GLuint m_texture; + Mlt::Frame *m_frame; + GLuint m_frame_texture; double m_display_ratio; QColor m_backgroundColor; Qt::WindowFlags m_baseFlags;