1 /***************************************************************************
2 * Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
3 * 2014 by Jean-Nicolas Artaud (jeannicolasartaud@gmail.com) *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
19 ***************************************************************************/
24 #include <OpenGL/glu.h>
28 #include "widgets/videoglwidget.h"
30 GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
32 #include <mlt++/Mlt.h>
34 #ifndef GL_TEXTURE_RECTANGLE_EXT
35 #define GL_TEXTURE_RECTANGLE_EXT GL_TEXTURE_RECTANGLE_NV
38 VideoGLWidget::VideoGLWidget(QWidget *parent, QGLWidget *share)
39 : QGLWidget(parent, share)
49 , m_display_ratio(4.0 / 3.0)
50 , m_backgroundColor(Qt::gray)
52 setAttribute(Qt::WA_PaintOnScreen);
53 setAttribute(Qt::WA_OpaquePaintEvent);
56 VideoGLWidget::~VideoGLWidget()
60 glDeleteTextures(1, &m_texture);
61 // m_frame will be cleaned up when the profile is closed by Render.
64 QSize VideoGLWidget::minimumSizeHint() const
69 QSize VideoGLWidget::sizeHint() const
71 return QSize(400, 300);
74 void VideoGLWidget::setImageAspectRatio(double ratio)
76 m_display_ratio = ratio;
77 resizeGL(width(), height());
80 void VideoGLWidget::initializeGL()
82 qglClearColor(m_backgroundColor);
83 glShadeModel(GL_FLAT);
84 glDisable(GL_DEPTH_TEST);
85 glDisable(GL_CULL_FACE);
86 glDisable(GL_LIGHTING);
89 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
92 void VideoGLWidget::resizeEvent(QResizeEvent* event)
94 resizeGL(event->size().width(),event->size().height());
97 void VideoGLWidget::resizeGL(int width, int height)
99 double this_aspect = (double) width / height;
101 // Special case optimisation to negate odd effect of sample aspect ratio
102 // not corresponding exactly with image resolution.
103 if ((int)(this_aspect * 1000) == (int)(m_display_ratio * 1000)) {
107 // Use OpenGL to normalise sample aspect ratio
108 else if (height * m_display_ratio > width) {
110 h = width / m_display_ratio;
112 w = height * m_display_ratio;
116 y = (height - h) / 2;
118 glViewport(0, 0, width, height);
119 glMatrixMode(GL_PROJECTION);
121 gluOrtho2D(0, width, height, 0);
122 glMatrixMode(GL_MODELVIEW);
123 glClear(GL_COLOR_BUFFER_BIT);
126 void VideoGLWidget::activateMonitor()
129 glViewport(0, 0, width(), height());
130 glMatrixMode(GL_PROJECTION);
132 gluOrtho2D(0, width(), height(), 0);
133 glMatrixMode(GL_MODELVIEW);
134 glClear(GL_COLOR_BUFFER_BIT);
137 void VideoGLWidget::paintGL()
141 glClear(GL_COLOR_BUFFER_BIT);
143 glEnable(GL_TEXTURE_RECTANGLE_EXT);
147 glTexCoord2i(m_image_width, 0);
148 glVertex2i(x + w, y);
149 glTexCoord2i(m_image_width, m_image_height);
150 glVertex2i(x + w, y + h);
151 glTexCoord2i(0, m_image_height);
152 glVertex2i(x, y + h);
154 glDisable(GL_TEXTURE_RECTANGLE_EXT);
156 if (m_frame_texture) {
158 glClear(GL_COLOR_BUFFER_BIT);
160 glEnable(GL_TEXTURE_2D);
161 glBindTexture(GL_TEXTURE_2D, m_frame_texture);
166 glVertex2i(x + w, y);
168 glVertex2i(x + w, y + h);
170 glVertex2i(x, y + h);
172 glDisable(GL_TEXTURE_2D);
176 void VideoGLWidget::showImage(const QImage &image)
178 m_image_width = image.width();
179 m_image_height = image.height();
182 glDeleteTextures(1, &m_texture);
187 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image_width);
188 glGenTextures(1, &m_texture);
189 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, m_texture);
190 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
191 glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
192 glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA8, m_image_width, m_image_height, 0, GL_RGB,
193 GL_UNSIGNED_BYTE, image.bits());
197 void VideoGLWidget::showImage(Mlt::Frame* frame, GLuint texnum)
199 static bool first = true;
200 static timespec start, now;
201 static int frameno = 0;
204 clock_gettime(CLOCK_MONOTONIC, &start);
210 clock_gettime(CLOCK_MONOTONIC, &now);
211 double elapsed = now.tv_sec - start.tv_sec +
212 1e-9 * (now.tv_nsec - start.tv_nsec);
213 printf("%d frames in %.3f seconds = %.1f fps (%.1f ms/frame)\n",
214 frameno, elapsed, frameno / elapsed,
215 1e3 * elapsed / frameno);
217 // Reset every 100 frames, so that local variations in frame times
218 // (especially for the first few frames, when the shaders are
219 // compiled etc.) don't make it hard to measure for the entire
220 // remaining duration of the program.
221 if (frameno == 100) {
227 GLsync sync = (GLsync) frame->get("movit.convert.fence");
228 glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
230 glDeleteTextures(1, &m_texture);
235 m_frame_texture = texnum;
240 void VideoGLWidget::mouseDoubleClickEvent(QMouseEvent * event)
242 // TODO: disable screensaver?
243 Qt::WindowFlags flags = windowFlags();
244 if (!isFullScreen()) {
245 // Check if we ahave a multiple monitor setup
246 #if QT_VERSION >= 0x040600
247 int monitors = QApplication::desktop()->screenCount();
249 int monitors = QApplication::desktop()->numScreens();
253 // Move monitor widget to the second screen (one screen for Kdenlive, the other one for the Monitor widget
254 int currentScreen = QApplication::desktop()->screenNumber(this);
255 if (currentScreen < monitors - 1)
256 screenres = QApplication::desktop()->screenGeometry(currentScreen + 1);
258 screenres = QApplication::desktop()->screenGeometry(currentScreen - 1);
259 move(QPoint(screenres.x(), screenres.y()));
260 resize(screenres.width(), screenres.height());
263 m_baseFlags = flags & (Qt::Window | Qt::SubWindow);
265 flags ^= Qt::SubWindow;
266 setWindowFlags(flags);
268 // This works around a bug with Compiz
269 // as the window must be visible before we can set the state
272 setWindowState(windowState() | Qt::WindowFullScreen); // set
274 setWindowState(windowState() | Qt::WindowFullScreen); // set
278 flags ^= (Qt::Window | Qt::SubWindow); //clear the flags...
279 flags |= m_baseFlags; //then we reset the flags (window and subwindow)
280 setWindowFlags(flags);
281 setWindowState(windowState() ^ Qt::WindowFullScreen); // reset
288 #include "videoglwidget.moc"