summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteinar H. Gunderson <sgunderson@bigfoot.com>2014-01-12 13:00:50 (GMT)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>2014-03-13 21:16:54 (GMT)
commit234d7fe2828b8e82253548e32081576fc56cbb80 (patch)
tree82f9679ba842632d727d939c7900ba077ca11a50
parentaa95245a04e8dd94de03eabcbc72a7140f2283a4 (diff)
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.
-rw-r--r--src/monitor.cpp2
-rw-r--r--src/renderer.cpp4
-rw-r--r--src/renderer.h3
-rw-r--r--src/widgets/videoglwidget.cpp24
-rw-r--r--src/widgets/videoglwidget.h10
5 files changed, 30 insertions, 13 deletions
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;