]> git.sesse.net Git - kdenlive/blob - src/widgets/videoglwidget.cpp
375f2d6b916a5a9b443ed3ab13fb8a9515219d33
[kdenlive] / src / widgets / videoglwidget.cpp
1 /***************************************************************************
2  *   Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
3  *               2014 by Jean-Nicolas Artaud (jeannicolasartaud@gmail.com) *
4  *                                                                         *
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.                                   *
9  *                                                                         *
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.                          *
14  *                                                                         *
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  ***************************************************************************/
20
21 #include <QtGui>
22 #include <QtOpenGL>
23 #ifdef Q_WS_MAC
24 #include <OpenGL/glu.h>
25 #else
26 #include <GL/glu.h>
27 #endif
28 #include "widgets/videoglwidget.h"
29
30 #ifndef GL_TEXTURE_RECTANGLE_EXT
31 #define GL_TEXTURE_RECTANGLE_EXT GL_TEXTURE_RECTANGLE_NV
32 #endif
33
34 VideoGLWidget::VideoGLWidget(QWidget *parent)
35     : QGLWidget(parent)
36     , x(0)
37     , y(0)
38     , w(width())
39     , h(height())
40     , m_image_width(0)
41     , m_image_height(0)
42     , m_texture(0)
43     , m_display_ratio(4.0 / 3.0)
44     , m_backgroundColor(Qt::gray)
45 {  
46     setAttribute(Qt::WA_PaintOnScreen);
47     setAttribute(Qt::WA_OpaquePaintEvent);
48 }
49
50 VideoGLWidget::~VideoGLWidget()
51 {
52     makeCurrent();
53     if (m_texture)
54         glDeleteTextures(1, &m_texture);
55 }
56
57 QSize VideoGLWidget::minimumSizeHint() const
58 {
59     return QSize(40, 30);
60 }
61
62 QSize VideoGLWidget::sizeHint() const
63 {
64     return QSize(400, 300);
65 }
66
67 void VideoGLWidget::setImageAspectRatio(double ratio)
68 {
69     m_display_ratio = ratio;
70     resizeGL(width(), height());
71 }
72
73 void VideoGLWidget::initializeGL()
74 {
75     qglClearColor(m_backgroundColor);
76     glShadeModel(GL_FLAT);
77     glDisable(GL_DEPTH_TEST);
78     glDisable(GL_CULL_FACE);
79     glDisable(GL_LIGHTING);
80     glDisable(GL_DITHER);
81     glDisable(GL_BLEND);
82     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
83 }
84
85 void VideoGLWidget::resizeEvent(QResizeEvent* event)
86 {
87     resizeGL(event->size().width(),event->size().height());
88 }
89
90 void VideoGLWidget::resizeGL(int width, int height)
91 {
92     double this_aspect = (double) width / height;
93
94     // Special case optimisation to negate odd effect of sample aspect ratio
95     // not corresponding exactly with image resolution.
96     if ((int)(this_aspect * 1000) == (int)(m_display_ratio * 1000)) {
97         w = width;
98         h = height;
99     }
100     // Use OpenGL to normalise sample aspect ratio
101     else if (height * m_display_ratio > width) {
102         w = width;
103         h = width / m_display_ratio;
104     } else {
105         w = height * m_display_ratio;
106         h = height;
107     }
108     x = (width - w) / 2;
109     y = (height - h) / 2;
110
111     glViewport(0, 0, width, height);
112     glMatrixMode(GL_PROJECTION);
113     glLoadIdentity();
114     gluOrtho2D(0, width, height, 0);
115     glMatrixMode(GL_MODELVIEW);
116     glClear(GL_COLOR_BUFFER_BIT);
117 }
118
119 void VideoGLWidget::activateMonitor()
120 {
121     makeCurrent();
122     glViewport(0, 0, width(), height());
123     glMatrixMode(GL_PROJECTION);
124     glLoadIdentity();
125     gluOrtho2D(0, width(), height(), 0);
126     glMatrixMode(GL_MODELVIEW);
127     glClear(GL_COLOR_BUFFER_BIT);
128 }
129
130 void VideoGLWidget::paintGL()
131 {
132     if (m_texture) {
133 #ifdef Q_WS_MAC
134                 glClear(GL_COLOR_BUFFER_BIT);
135 #endif
136         glEnable(GL_TEXTURE_RECTANGLE_EXT);
137         glBegin(GL_QUADS);
138         glTexCoord2i(0, 0);
139         glVertex2i(x, y);
140         glTexCoord2i(m_image_width, 0);
141         glVertex2i(x + w, y);
142         glTexCoord2i(m_image_width, m_image_height);
143         glVertex2i(x + w, y + h);
144         glTexCoord2i(0, m_image_height);
145         glVertex2i(x, y + h);
146         glEnd();
147         glDisable(GL_TEXTURE_RECTANGLE_EXT);
148     }
149 }
150
151 void VideoGLWidget::showImage(const QImage &image)
152 {
153     m_image_width = image.width();
154     m_image_height = image.height();
155     makeCurrent();
156     if (m_texture)
157         glDeleteTextures(1, &m_texture);
158
159     glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image_width);
160     glGenTextures(1, &m_texture);
161     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, m_texture);
162     glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
163     glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
164     glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA8, m_image_width, m_image_height, 0, GL_RGB,
165                  GL_UNSIGNED_BYTE, image.bits());
166     updateGL();
167 }
168
169 void VideoGLWidget::mouseDoubleClickEvent(QMouseEvent * event)
170 {
171     // TODO: disable screensaver?
172     Qt::WindowFlags flags = windowFlags();
173     if (!isFullScreen()) {
174         // Check if we ahave a multiple monitor setup
175 #if QT_VERSION >= 0x040600
176         int monitors = QApplication::desktop()->screenCount();
177 #else
178         int monitors = QApplication::desktop()->numScreens();
179 #endif
180         if (monitors > 1) {
181             QRect screenres;
182             // Move monitor widget to the second screen (one screen for Kdenlive, the other one for the Monitor widget
183             int currentScreen = QApplication::desktop()->screenNumber(this);
184             if (currentScreen < monitors - 1)
185                 screenres = QApplication::desktop()->screenGeometry(currentScreen + 1);
186             else
187                 screenres = QApplication::desktop()->screenGeometry(currentScreen - 1);
188             move(QPoint(screenres.x(), screenres.y()));
189             resize(screenres.width(), screenres.height());
190         }
191
192         m_baseFlags = flags & (Qt::Window | Qt::SubWindow);
193         flags |= Qt::Window;
194         flags ^= Qt::SubWindow;
195         setWindowFlags(flags);
196 #ifdef Q_WS_X11
197         // This works around a bug with Compiz
198         // as the window must be visible before we can set the state
199         show();
200         raise();
201         setWindowState(windowState() | Qt::WindowFullScreen);   // set
202 #else
203         setWindowState(windowState() | Qt::WindowFullScreen);   // set
204         show();
205 #endif
206     } else {
207         flags ^= (Qt::Window | Qt::SubWindow); //clear the flags...
208         flags |= m_baseFlags; //then we reset the flags (window and subwindow)
209         setWindowFlags(flags);
210         setWindowState(windowState()  ^ Qt::WindowFullScreen);   // reset
211         show();
212     }
213     event->accept();
214 }
215
216
217 #include "videoglwidget.moc"