qopenglcompositor.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/platformsupport/platformcompositor/qopenglcompositor.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the plugins of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include <QtGui/QOpenGLContext>-
41#include <QtGui/QOpenGLFramebufferObject>-
42#include <QtGui/QWindow>-
43#include <QtGui/QMatrix4x4>-
44#include <qpa/qplatformbackingstore.h>-
45-
46#include "qopenglcompositor_p.h"-
47-
48QT_BEGIN_NAMESPACE-
49-
50/*!-
51 \class QOpenGLCompositor-
52 \brief A generic OpenGL-based compositor-
53 \since 5.4-
54 \internal-
55 \ingroup qpa-
56-
57 This class provides a lightweight compositor that maintains the-
58 basic stacking order of windows and composites them by drawing-
59 textured quads via OpenGL.-
60-
61 It it meant to be used by platform plugins that run without a-
62 windowing system.-
63-
64 It is up to the platform plugin to manage the lifetime of the-
65 compositor (instance(), destroy()), set the correct destination-
66 context and window as early as possible (setTarget()),-
67 register the composited windows as they are shown, activated,-
68 raised and lowered (addWindow(), moveToTop(), etc.), and to-
69 schedule repaints (update()).-
70-
71 \note To get support for QWidget-based windows, just use-
72 QOpenGLCompositorBackingStore. It will automatically create-
73 textures from the raster-rendered content and trigger the-
74 necessary repaints.-
75 */-
76-
77static QOpenGLCompositor *compositor = 0;-
78-
79QOpenGLCompositor::QOpenGLCompositor()-
80 : m_context(0),-
81 m_targetWindow(0)-
82{-
83 Q_ASSERT(!compositor);-
84 m_updateTimer.setSingleShot(true);-
85 m_updateTimer.setInterval(0);-
86 connect(&m_updateTimer, SIGNAL(timeout()), SLOT(handleRenderAllRequest()));-
87}
never executed: end of block
0
88-
89QOpenGLCompositor::~QOpenGLCompositor()-
90{-
91 Q_ASSERT(compositor == this);-
92 m_blitter.destroy();-
93 compositor = 0;-
94}
never executed: end of block
0
95-
96void QOpenGLCompositor::setTarget(QOpenGLContext *context, QWindow *targetWindow)-
97{-
98 m_context = context;-
99 m_targetWindow = targetWindow;-
100}
never executed: end of block
0
101-
102void QOpenGLCompositor::update()-
103{-
104 if (!m_updateTimer.isActive())
!m_updateTimer.isActive()Description
TRUEnever evaluated
FALSEnever evaluated
0
105 m_updateTimer.start();
never executed: m_updateTimer.start();
0
106}
never executed: end of block
0
107-
108QImage QOpenGLCompositor::grab()-
109{-
110 Q_ASSERT(m_context && m_targetWindow);-
111 m_context->makeCurrent(m_targetWindow);-
112 QScopedPointer<QOpenGLFramebufferObject> fbo(new QOpenGLFramebufferObject(m_targetWindow->geometry().size()));-
113 renderAll(fbo.data());-
114 return fbo->toImage();
never executed: return fbo->toImage();
0
115}-
116-
117void QOpenGLCompositor::handleRenderAllRequest()-
118{-
119 Q_ASSERT(m_context && m_targetWindow);-
120 m_context->makeCurrent(m_targetWindow);-
121 renderAll(0);-
122}
never executed: end of block
0
123-
124void QOpenGLCompositor::renderAll(QOpenGLFramebufferObject *fbo)-
125{-
126 if (fbo)
fboDescription
TRUEnever evaluated
FALSEnever evaluated
0
127 fbo->bind();
never executed: fbo->bind();
0
128-
129 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);-
130-
131 const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size());-
132 glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height());-
133-
134 if (!m_blitter.isCreated())
!m_blitter.isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
0
135 m_blitter.create();
never executed: m_blitter.create();
0
136-
137 m_blitter.bind();-
138-
139 for (int i = 0; i < m_windows.size(); ++i)
i < m_windows.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
140 m_windows.at(i)->beginCompositing();
never executed: m_windows.at(i)->beginCompositing();
0
141-
142 for (int i = 0; i < m_windows.size(); ++i)
i < m_windows.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
143 render(m_windows.at(i));
never executed: render(m_windows.at(i));
0
144-
145 m_blitter.release();-
146 if (!fbo)
!fboDescription
TRUEnever evaluated
FALSEnever evaluated
0
147 m_context->swapBuffers(m_targetWindow);
never executed: m_context->swapBuffers(m_targetWindow);
0
148 else-
149 fbo->release();
never executed: fbo->release();
0
150-
151 for (int i = 0; i < m_windows.size(); ++i)
i < m_windows.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
152 m_windows.at(i)->endCompositing();
never executed: m_windows.at(i)->endCompositing();
0
153}
never executed: end of block
0
154-
155struct BlendStateBinder-
156{-
157 BlendStateBinder() : m_blend(false) {-
158 glDisable(GL_BLEND);-
159 }
never executed: end of block
0
160 void set(bool blend) {-
161 if (blend != m_blend) {
blend != m_blendDescription
TRUEnever evaluated
FALSEnever evaluated
0
162 if (blend) {
blendDescription
TRUEnever evaluated
FALSEnever evaluated
0
163 glEnable(GL_BLEND);-
164 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);-
165 } else {
never executed: end of block
0
166 glDisable(GL_BLEND);-
167 }
never executed: end of block
0
168 m_blend = blend;-
169 }
never executed: end of block
0
170 }
never executed: end of block
0
171 ~BlendStateBinder() {-
172 if (m_blend)
m_blendDescription
TRUEnever evaluated
FALSEnever evaluated
0
173 glDisable(GL_BLEND);
never executed: glDisable(0x0BE2);
0
174 }
never executed: end of block
0
175 bool m_blend;-
176};-
177-
178static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)-
179{-
180 return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1,
never executed: return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1, topLeftRect.width(), topLeftRect.height());
0
181 topLeftRect.width(), topLeftRect.height());
never executed: return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1, topLeftRect.width(), topLeftRect.height());
0
182}-
183-
184static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect, QOpenGLTextureBlitter *blitter)-
185{-
186 const QRect clipRect = textures->clipRect(idx);-
187 if (clipRect.isEmpty())
clipRect.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
188 return;
never executed: return;
0
189-
190 const QRect rectInWindow = textures->geometry(idx);-
191 const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());-
192 const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());-
193-
194 const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(clippedRectInWindow, targetWindowRect);-
195 const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect, rectInWindow.size(),-
196 QOpenGLTextureBlitter::OriginBottomLeft);-
197-
198 blitter->blit(textures->textureId(idx), target, source);-
199}
never executed: end of block
0
200-
201void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)-
202{-
203 const QPlatformTextureList *textures = window->textures();-
204 if (!textures)
!texturesDescription
TRUEnever evaluated
FALSEnever evaluated
0
205 return;
never executed: return;
0
206-
207 const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size());-
208 float currentOpacity = 1.0f;-
209 BlendStateBinder blend;-
210-
211 for (int i = 0; i < textures->count(); ++i) {
i < textures->count()Description
TRUEnever evaluated
FALSEnever evaluated
0
212 uint textureId = textures->textureId(i);-
213 const float opacity = window->sourceWindow()->opacity();-
214 if (opacity != currentOpacity) {
opacity != currentOpacityDescription
TRUEnever evaluated
FALSEnever evaluated
0
215 currentOpacity = opacity;-
216 m_blitter.setOpacity(currentOpacity);-
217 }
never executed: end of block
0
218-
219 if (textures->count() > 1 && i == textures->count() - 1) {
textures->count() > 1Description
TRUEnever evaluated
FALSEnever evaluated
i == textures->count() - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
220 // Backingstore for a widget with QOpenGLWidget subwidgets-
221 blend.set(true);-
222 const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);-
223 m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);-
224 } else if (textures->count() == 1) {
never executed: end of block
textures->count() == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
225 // A regular QWidget window-
226 const bool translucent = window->sourceWindow()->requestedFormat().alphaBufferSize() > 0;-
227 blend.set(translucent);-
228 const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);-
229 m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);-
230 } else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
never executed: end of block
!textures->fla...::StacksOnTop)Description
TRUEnever evaluated
FALSEnever evaluated
0
231 // Texture from an FBO belonging to a QOpenGLWidget-
232 blend.set(false);-
233 clippedBlit(textures, i, targetWindowRect, &m_blitter);-
234 }
never executed: end of block
0
235 }
never executed: end of block
0
236-
237 for (int i = 0; i < textures->count(); ++i) {
i < textures->count()Description
TRUEnever evaluated
FALSEnever evaluated
0
238 if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
textures->flag...::StacksOnTop)Description
TRUEnever evaluated
FALSEnever evaluated
0
239 blend.set(true);-
240 clippedBlit(textures, i, targetWindowRect, &m_blitter);-
241 }
never executed: end of block
0
242 }
never executed: end of block
0
243-
244 m_blitter.setOpacity(1.0f);-
245}
never executed: end of block
0
246-
247QOpenGLCompositor *QOpenGLCompositor::instance()-
248{-
249 if (!compositor)
!compositorDescription
TRUEnever evaluated
FALSEnever evaluated
0
250 compositor = new QOpenGLCompositor;
never executed: compositor = new QOpenGLCompositor;
0
251 return compositor;
never executed: return compositor;
0
252}-
253-
254void QOpenGLCompositor::destroy()-
255{-
256 delete compositor;-
257 compositor = 0;-
258}
never executed: end of block
0
259-
260void QOpenGLCompositor::addWindow(QOpenGLCompositorWindow *window)-
261{-
262 if (!m_windows.contains(window)) {
!m_windows.contains(window)Description
TRUEnever evaluated
FALSEnever evaluated
0
263 m_windows.append(window);-
264 emit topWindowChanged(window);-
265 }
never executed: end of block
0
266}
never executed: end of block
0
267-
268void QOpenGLCompositor::removeWindow(QOpenGLCompositorWindow *window)-
269{-
270 m_windows.removeOne(window);-
271 if (!m_windows.isEmpty())
!m_windows.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
272 emit topWindowChanged(m_windows.last());
never executed: topWindowChanged(m_windows.last());
0
273}
never executed: end of block
0
274-
275void QOpenGLCompositor::moveToTop(QOpenGLCompositorWindow *window)-
276{-
277 m_windows.removeOne(window);-
278 m_windows.append(window);-
279 emit topWindowChanged(window);-
280}
never executed: end of block
0
281-
282void QOpenGLCompositor::changeWindowIndex(QOpenGLCompositorWindow *window, int newIdx)-
283{-
284 int idx = m_windows.indexOf(window);-
285 if (idx != -1 && idx != newIdx) {
idx != -1Description
TRUEnever evaluated
FALSEnever evaluated
idx != newIdxDescription
TRUEnever evaluated
FALSEnever evaluated
0
286 m_windows.move(idx, newIdx);-
287 if (newIdx == m_windows.size() - 1)
newIdx == m_windows.size() - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
288 emit topWindowChanged(m_windows.last());
never executed: topWindowChanged(m_windows.last());
0
289 }
never executed: end of block
0
290}
never executed: end of block
0
291-
292QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9