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