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 QtQuick module 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 "qsgsoftwarelayer_p.h"
41
42#include "qsgsoftwarecontext_p.h"
43#include "qsgsoftwarepixmaprenderer_p.h"
44
45QT_BEGIN_NAMESPACE
46
47QSGSoftwareLayer::QSGSoftwareLayer(QSGRenderContext *renderContext)
48 : QSGLayer(*(new QSGSoftwareLayerPrivate))
49 , m_item(nullptr)
50 , m_context(renderContext)
51 , m_renderer(nullptr)
52 , m_device_pixel_ratio(1)
53 , m_mirrorHorizontal(false)
54 , m_mirrorVertical(true)
55 , m_live(true)
56 , m_grab(true)
57 , m_recursive(false)
58 , m_dirtyTexture(true)
59{
60
61}
62
63QSGSoftwareLayer::~QSGSoftwareLayer()
64{
65 invalidated();
66}
67
68int QSGSoftwareLayer::textureId() const
69{
70 return 0;
71}
72
73int QSGSoftwareLayerPrivate::comparisonKey() const
74{
75 return 0;
76}
77
78QSize QSGSoftwareLayer::textureSize() const
79{
80 return m_pixmap.size();
81}
82
83bool QSGSoftwareLayer::hasAlphaChannel() const
84{
85 return m_pixmap.hasAlphaChannel();
86}
87
88bool QSGSoftwareLayer::hasMipmaps() const
89{
90 return false;
91}
92
93void QSGSoftwareLayer::bind()
94{
95}
96
97bool QSGSoftwareLayer::updateTexture()
98{
99 bool doGrab = (m_live || m_grab) && m_dirtyTexture;
100 if (doGrab)
101 grab();
102 if (m_grab)
103 emit scheduledUpdateCompleted();
104 m_grab = false;
105 return doGrab;
106}
107
108void QSGSoftwareLayer::setItem(QSGNode *item)
109{
110 if (item == m_item)
111 return;
112 m_item = item;
113
114 if (m_live && !m_item)
115 m_pixmap = QPixmap();
116
117 markDirtyTexture();
118}
119
120void QSGSoftwareLayer::setRect(const QRectF &rect)
121{
122 if (rect == m_rect)
123 return;
124 m_rect = rect;
125 markDirtyTexture();
126}
127
128void QSGSoftwareLayer::setSize(const QSize &size)
129{
130 if (size == m_size)
131 return;
132 m_size = size;
133
134 if (m_live && m_size.isNull())
135 m_pixmap = QPixmap();
136
137 markDirtyTexture();
138}
139
140void QSGSoftwareLayer::scheduleUpdate()
141{
142 if (m_grab)
143 return;
144 m_grab = true;
145 if (m_dirtyTexture) {
146 emit updateRequested();
147 }
148}
149
150QImage QSGSoftwareLayer::toImage() const
151{
152 return m_pixmap.toImage();
153}
154
155void QSGSoftwareLayer::setLive(bool live)
156{
157 if (live == m_live)
158 return;
159 m_live = live;
160
161 if (m_live && (!m_item || m_size.isNull()))
162 m_pixmap = QPixmap();
163
164 markDirtyTexture();
165}
166
167void QSGSoftwareLayer::setRecursive(bool recursive)
168{
169 m_recursive = recursive;
170}
171
172void QSGSoftwareLayer::setFormat(uint)
173{
174}
175
176void QSGSoftwareLayer::setHasMipmaps(bool)
177{
178}
179
180void QSGSoftwareLayer::setDevicePixelRatio(qreal ratio)
181{
182 m_device_pixel_ratio = ratio;
183}
184
185void QSGSoftwareLayer::setMirrorHorizontal(bool mirror)
186{
187 if (m_mirrorHorizontal == mirror)
188 return;
189 m_mirrorHorizontal = mirror;
190 markDirtyTexture();
191}
192
193void QSGSoftwareLayer::setMirrorVertical(bool mirror)
194{
195 if (m_mirrorVertical == mirror)
196 return;
197 m_mirrorVertical = mirror;
198 markDirtyTexture();
199}
200
201void QSGSoftwareLayer::markDirtyTexture()
202{
203 m_dirtyTexture = true;
204 if (m_live || m_grab) {
205 emit updateRequested();
206 }
207}
208
209void QSGSoftwareLayer::invalidated()
210{
211 delete m_renderer;
212 m_renderer = nullptr;
213}
214
215void QSGSoftwareLayer::grab()
216{
217 if (!m_item || m_size.isNull()) {
218 m_pixmap = QPixmap();
219 m_dirtyTexture = false;
220 return;
221 }
222 QSGNode *root = m_item;
223 while (root->firstChild() && root->type() != QSGNode::RootNodeType)
224 root = root->firstChild();
225 if (root->type() != QSGNode::RootNodeType)
226 return;
227
228 if (!m_renderer) {
229 m_renderer = new QSGSoftwarePixmapRenderer(m_context);
230 connect(sender: m_renderer, SIGNAL(sceneGraphChanged()), receiver: this, SLOT(markDirtyTexture()));
231 }
232 m_renderer->setDevicePixelRatio(m_device_pixel_ratio);
233 m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
234
235 if (m_pixmap.size() != m_size) {
236 m_pixmap = QPixmap(m_size);
237 m_pixmap.setDevicePixelRatio(m_device_pixel_ratio);
238 }
239
240 // Render texture.
241 root->markDirty(bits: QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
242 m_renderer->nodeChanged(node: root, state: QSGNode::DirtyForceUpdate); // Force render list update.
243
244 m_dirtyTexture = false;
245
246 m_renderer->setDeviceRect(m_size);
247 m_renderer->setViewportRect(m_size);
248 QRect mirrored(m_mirrorHorizontal ? m_rect.right() * m_device_pixel_ratio : m_rect.left() * m_device_pixel_ratio,
249 m_mirrorVertical ? m_rect.bottom() * m_device_pixel_ratio : m_rect.top() * m_device_pixel_ratio,
250 m_mirrorHorizontal ? -m_rect.width() * m_device_pixel_ratio : m_rect.width() * m_device_pixel_ratio,
251 m_mirrorVertical ? -m_rect.height() * m_device_pixel_ratio : m_rect.height() * m_device_pixel_ratio);
252 m_renderer->setProjectionRect(mirrored);
253 m_renderer->setClearColor(Qt::transparent);
254
255 m_renderer->renderScene();
256 m_renderer->render(target: &m_pixmap);
257
258 root->markDirty(bits: QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update.
259
260 if (m_recursive)
261 markDirtyTexture(); // Continuously update if 'live' and 'recursive'.
262}
263
264QT_END_NAMESPACE
265
266#include "moc_qsgsoftwarelayer_p.cpp"
267

source code of qtdeclarative/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp