From: Steinar H. G. <sgu...@bi...> - 2014-03-13 21:24:08
|
Git commit 234d7fe2828b8e82253548e32081576fc56cbb80 by Steinar H. Gunderson. Committed on 12/01/2014 at 13:00. Pushed by sandsmark into branch 'master'. 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. M +1 -1 src/monitor.cpp M +1 -3 src/renderer.cpp M +2 -1 src/renderer.h M +18 -6 src/widgets/videoglwidget.cpp M +8 -2 src/widgets/videoglwidget.h http://commits.kde.org/kdenlive/234d7fe2828b8e82253548e32081576fc56cbb80 diff --git a/src/monitor.cpp b/src/monitor.cpp index 29a7a3d..5d56263 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 1906751..880a965 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 43be7b8..6910f42 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -33,6 +33,7 @@ #include "definitions.h" #include "widgets/abstractmonitor.h" +#include <GL/gl.h> #include <mlt/framework/mlt_types.h> #include <kurl.h> @@ -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<double> &); void addClip(const KUrl &, stringMap); void checkSeeking(); diff --git a/src/widgets/videoglwidget.cpp b/src/widgets/videoglwidget.cpp index a37d529..3c62742 100644 --- a/src/widgets/videoglwidget.cpp +++ b/src/widgets/videoglwidget.cpp @@ -26,6 +26,10 @@ #include <GL/glu.h> #endif #include "widgets/videoglwidget.h" +extern "C" { +GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +} +#include <mlt++/Mlt.h> #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 918cb11..0598d13 100644 --- a/src/widgets/videoglwidget.h +++ b/src/widgets/videoglwidget.h @@ -23,6 +23,10 @@ #include <QGLWidget> +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; |