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

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