OpenCoverage

qopenglcompositorbackingstore.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.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/QWindow>-
42#include <QtGui/QPainter>-
43#include <QtGui/QOffscreenSurface>-
44#include <qpa/qplatformbackingstore.h>-
45#include <private/qwindow_p.h>-
46-
47#include "qopenglcompositorbackingstore_p.h"-
48#include "qopenglcompositor_p.h"-
49-
50#ifndef GL_UNPACK_ROW_LENGTH-
51#define GL_UNPACK_ROW_LENGTH 0x0CF2-
52#endif-
53-
54QT_BEGIN_NAMESPACE-
55-
56/*!-
57 \class QOpenGLCompositorBackingStore-
58 \brief A backing store implementation for OpenGL-
59 \since 5.4-
60 \internal-
61 \ingroup qpa-
62-
63 This implementation uploads raster-rendered widget windows into-
64 textures. It is meant to be used with QOpenGLCompositor that-
65 composites the textures onto a single native window using OpenGL.-
66 This means that multiple top-level widgets are supported without-
67 creating actual native windows for each of them.-
68-
69 \note It is important to call notifyComposited() from the-
70 corresponding platform window's endCompositing() callback-
71 (inherited from QOpenGLCompositorWindow).-
72-
73 \note When implementing QOpenGLCompositorWindow::textures() for-
74 windows of type RasterSurface or RasterGLSurface, simply return-
75 the list provided by this class' textures().-
76*/-
77-
78QOpenGLCompositorBackingStore::QOpenGLCompositorBackingStore(QWindow *window)-
79 : QPlatformBackingStore(window),-
80 m_window(window),-
81 m_bsTexture(0),-
82 m_bsTextureContext(0),-
83 m_textures(new QPlatformTextureList),-
84 m_lockedWidgetTextures(0)-
85{-
86}
never executed: end of block
0
87-
88QOpenGLCompositorBackingStore::~QOpenGLCompositorBackingStore()-
89{-
90 if (m_bsTexture) {
m_bsTextureDescription
TRUEnever evaluated
FALSEnever evaluated
0
91 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
92 // With render-to-texture-widgets QWidget makes sure the TLW's shareContext() is-
93 // made current before destroying backingstores. That is however not the case for-
94 // windows with regular widgets only.-
95 QScopedPointer<QOffscreenSurface> tempSurface;-
96 if (!ctx) {
!ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
97 ctx = QOpenGLCompositor::instance()->context();-
98 tempSurface.reset(new QOffscreenSurface);-
99 tempSurface->setFormat(ctx->format());-
100 tempSurface->create();-
101 ctx->makeCurrent(tempSurface.data());-
102 }
never executed: end of block
0
103-
104 if (ctx && m_bsTextureContext && ctx->shareGroup() == m_bsTextureContext->shareGroup())
ctxDescription
TRUEnever evaluated
FALSEnever evaluated
m_bsTextureContextDescription
TRUEnever evaluated
FALSEnever evaluated
ctx->shareGrou...->shareGroup()Description
TRUEnever evaluated
FALSEnever evaluated
0
105 glDeleteTextures(1, &m_bsTexture);
never executed: glDeleteTextures(1, &m_bsTexture);
0
106 else-
107 qWarning("QOpenGLCompositorBackingStore: Texture is not valid in the current context");
never executed: QMessageLogger(__FILE__, 107, __PRETTY_FUNCTION__).warning("QOpenGLCompositorBackingStore: Texture is not valid in the current context");
0
108-
109 if (tempSurface)
tempSurfaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
110 ctx->doneCurrent();
never executed: ctx->doneCurrent();
0
111 }
never executed: end of block
0
112-
113 delete m_textures; // this does not actually own any GL resources-
114}
never executed: end of block
0
115-
116QPaintDevice *QOpenGLCompositorBackingStore::paintDevice()-
117{-
118 return &m_image;
never executed: return &m_image;
0
119}-
120-
121void QOpenGLCompositorBackingStore::updateTexture()-
122{-
123 if (!m_bsTexture) {
!m_bsTextureDescription
TRUEnever evaluated
FALSEnever evaluated
0
124 m_bsTextureContext = QOpenGLContext::currentContext();-
125 Q_ASSERT(m_bsTextureContext);-
126 glGenTextures(1, &m_bsTexture);-
127 glBindTexture(GL_TEXTURE_2D, m_bsTexture);-
128 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);-
129 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);-
130 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);-
131 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);-
132 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);-
133 } else {
never executed: end of block
0
134 glBindTexture(GL_TEXTURE_2D, m_bsTexture);-
135 }
never executed: end of block
0
136-
137 if (!m_dirty.isNull()) {
!m_dirty.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
138 QRegion fixed;-
139 QRect imageRect = m_image.rect();-
140-
141 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
142 if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
!ctx->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
ctx->format()....Version() >= 3Description
TRUEnever evaluated
FALSEnever evaluated
0
143 foreach (const QRect &rect, m_dirty.rects()) {-
144 QRect r = imageRect & rect;-
145 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image.width());-
146 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), r.width(), r.height(), GL_RGBA, GL_UNSIGNED_BYTE,-
147 m_image.constScanLine(r.y()) + r.x() * 4);-
148 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);-
149 }
never executed: end of block
0
150 } else {
never executed: end of block
0
151 foreach (const QRect &rect, m_dirty.rects()) {-
152 // intersect with image rect to be sure-
153 QRect r = imageRect & rect;-
154-
155 // if the rect is wide enough it's cheaper to just-
156 // extend it instead of doing an image copy-
157 if (r.width() >= imageRect.width() / 2) {
r.width() >= i...ct.width() / 2Description
TRUEnever evaluated
FALSEnever evaluated
0
158 r.setX(0);-
159 r.setWidth(imageRect.width());-
160 }
never executed: end of block
0
161-
162 fixed |= r;-
163 }
never executed: end of block
0
164 foreach (const QRect &rect, fixed.rects()) {-
165 // if the sub-rect is full-width we can pass the image data directly to-
166 // OpenGL instead of copying, since there's no gap between scanlines-
167 if (rect.width() == imageRect.width()) {
rect.width() =...geRect.width()Description
TRUEnever evaluated
FALSEnever evaluated
0
168 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,-
169 m_image.constScanLine(rect.y()));-
170 } else {
never executed: end of block
0
171 glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,-
172 m_image.copy(rect).constBits());-
173 }
never executed: end of block
0
174 }-
175 }
never executed: end of block
0
176-
177 m_dirty = QRegion();-
178 }
never executed: end of block
0
179}
never executed: end of block
0
180-
181void QOpenGLCompositorBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)-
182{-
183 // Called for ordinary raster windows.-
184-
185 Q_UNUSED(region);-
186 Q_UNUSED(offset);-
187-
188 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();-
189 QOpenGLContext *dstCtx = compositor->context();-
190 Q_ASSERT(dstCtx);-
191-
192 QWindow *dstWin = compositor->targetWindow();-
193 if (!dstWin)
!dstWinDescription
TRUEnever evaluated
FALSEnever evaluated
0
194 return;
never executed: return;
0
195-
196 dstCtx->makeCurrent(dstWin);-
197 updateTexture();-
198 m_textures->clear();-
199 m_textures->appendTexture(Q_NULLPTR, m_bsTexture, window->geometry());-
200-
201 compositor->update();-
202}
never executed: end of block
0
203-
204void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,-
205 QPlatformTextureList *textures, QOpenGLContext *context,-
206 bool translucentBackground)-
207{-
208 // QOpenGLWidget/QQuickWidget content provided as textures. The raster content goes on top.-
209-
210 Q_UNUSED(region);-
211 Q_UNUSED(offset);-
212 Q_UNUSED(context);-
213 Q_UNUSED(translucentBackground);-
214-
215 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();-
216 QOpenGLContext *dstCtx = compositor->context();-
217 Q_ASSERT(dstCtx); // setTarget() must have been called before, e.g. from QEGLFSWindow-
218-
219 // The compositor's context and the context to which QOpenGLWidget/QQuickWidget-
220 // textures belong are not the same. They share resources, though.-
221 Q_ASSERT(context->shareGroup() == dstCtx->shareGroup());-
222-
223 QWindow *dstWin = compositor->targetWindow();-
224 if (!dstWin)
!dstWinDescription
TRUEnever evaluated
FALSEnever evaluated
0
225 return;
never executed: return;
0
226-
227 dstCtx->makeCurrent(dstWin);-
228-
229 QWindowPrivate::get(window)->lastComposeTime.start();-
230-
231 m_textures->clear();-
232 for (int i = 0; i < textures->count(); ++i)
i < textures->count()Description
TRUEnever evaluated
FALSEnever evaluated
0
233 m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i),
never executed: m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i), textures->clipRect(i), textures->flags(i));
0
234 textures->clipRect(i), textures->flags(i));
never executed: m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i), textures->clipRect(i), textures->flags(i));
0
235-
236 updateTexture();-
237 m_textures->appendTexture(Q_NULLPTR, m_bsTexture, window->geometry());-
238-
239 textures->lock(true);-
240 m_lockedWidgetTextures = textures;-
241-
242 compositor->update();-
243}
never executed: end of block
0
244-
245void QOpenGLCompositorBackingStore::notifyComposited()-
246{-
247 if (m_lockedWidgetTextures) {
m_lockedWidgetTexturesDescription
TRUEnever evaluated
FALSEnever evaluated
0
248 QPlatformTextureList *textureList = m_lockedWidgetTextures;-
249 m_lockedWidgetTextures = 0; // may reenter so null before unlocking-
250 textureList->lock(false);-
251 }
never executed: end of block
0
252}
never executed: end of block
0
253-
254void QOpenGLCompositorBackingStore::beginPaint(const QRegion &region)-
255{-
256 m_dirty |= region;-
257-
258 if (m_image.hasAlphaChannel()) {
m_image.hasAlphaChannel()Description
TRUEnever evaluated
FALSEnever evaluated
0
259 QPainter p(&m_image);-
260 p.setCompositionMode(QPainter::CompositionMode_Source);-
261 foreach (const QRect &r, region.rects())-
262 p.fillRect(r, Qt::transparent);
never executed: p.fillRect(r, Qt::transparent);
0
263 }
never executed: end of block
0
264}
never executed: end of block
0
265-
266void QOpenGLCompositorBackingStore::resize(const QSize &size, const QRegion &staticContents)-
267{-
268 Q_UNUSED(staticContents);-
269-
270 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();-
271 QOpenGLContext *dstCtx = compositor->context();-
272 QWindow *dstWin = compositor->targetWindow();-
273 if (!dstWin)
!dstWinDescription
TRUEnever evaluated
FALSEnever evaluated
0
274 return;
never executed: return;
0
275-
276 m_image = QImage(size, QImage::Format_RGBA8888);-
277-
278 m_window->create();-
279-
280 dstCtx->makeCurrent(dstWin);-
281 if (m_bsTexture) {
m_bsTextureDescription
TRUEnever evaluated
FALSEnever evaluated
0
282 glDeleteTextures(1, &m_bsTexture);-
283 m_bsTexture = 0;-
284 m_bsTextureContext = Q_NULLPTR;-
285 }
never executed: end of block
0
286}
never executed: end of block
0
287-
288QImage QOpenGLCompositorBackingStore::toImage() const-
289{-
290 return m_image;
never executed: return m_image;
0
291}-
292-
293QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

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