1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qsgsoftwarelayer_p.h" |
5 | |
6 | #include "qsgsoftwarecontext_p.h" |
7 | #include "qsgsoftwarepixmaprenderer_p.h" |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | QSGSoftwareLayer::QSGSoftwareLayer(QSGRenderContext *renderContext) |
12 | : QSGLayer(*(new QSGTexturePrivate(this))) |
13 | , m_item(nullptr) |
14 | , m_context(renderContext) |
15 | , m_renderer(nullptr) |
16 | , m_device_pixel_ratio(1) |
17 | , m_mirrorHorizontal(false) |
18 | , m_mirrorVertical(true) |
19 | , m_live(true) |
20 | , m_grab(true) |
21 | , m_recursive(false) |
22 | , m_dirtyTexture(true) |
23 | { |
24 | |
25 | } |
26 | |
27 | QSGSoftwareLayer::~QSGSoftwareLayer() |
28 | { |
29 | invalidated(); |
30 | } |
31 | |
32 | qint64 QSGSoftwareLayer::comparisonKey() const |
33 | { |
34 | return 0; |
35 | } |
36 | |
37 | QSize QSGSoftwareLayer::textureSize() const |
38 | { |
39 | return m_pixmap.size(); |
40 | } |
41 | |
42 | bool QSGSoftwareLayer::hasAlphaChannel() const |
43 | { |
44 | return m_pixmap.hasAlphaChannel(); |
45 | } |
46 | |
47 | bool QSGSoftwareLayer::hasMipmaps() const |
48 | { |
49 | return false; |
50 | } |
51 | |
52 | bool QSGSoftwareLayer::updateTexture() |
53 | { |
54 | bool doGrab = (m_live || m_grab) && m_dirtyTexture; |
55 | if (doGrab) |
56 | grab(); |
57 | if (m_grab) |
58 | emit scheduledUpdateCompleted(); |
59 | m_grab = false; |
60 | return doGrab; |
61 | } |
62 | |
63 | void QSGSoftwareLayer::setItem(QSGNode *item) |
64 | { |
65 | if (item == m_item) |
66 | return; |
67 | m_item = item; |
68 | |
69 | if (m_live && !m_item) |
70 | m_pixmap = QPixmap(); |
71 | |
72 | markDirtyTexture(); |
73 | } |
74 | |
75 | void QSGSoftwareLayer::setRect(const QRectF &rect) |
76 | { |
77 | if (rect == m_rect) |
78 | return; |
79 | m_rect = rect; |
80 | markDirtyTexture(); |
81 | } |
82 | |
83 | void QSGSoftwareLayer::setSize(const QSize &size) |
84 | { |
85 | if (size == m_size) |
86 | return; |
87 | m_size = size; |
88 | |
89 | if (m_live && m_size.isNull()) |
90 | m_pixmap = QPixmap(); |
91 | |
92 | markDirtyTexture(); |
93 | } |
94 | |
95 | void QSGSoftwareLayer::scheduleUpdate() |
96 | { |
97 | if (m_grab) |
98 | return; |
99 | m_grab = true; |
100 | if (m_dirtyTexture) { |
101 | emit updateRequested(); |
102 | } |
103 | } |
104 | |
105 | QImage QSGSoftwareLayer::toImage() const |
106 | { |
107 | return m_pixmap.toImage(); |
108 | } |
109 | |
110 | void QSGSoftwareLayer::setLive(bool live) |
111 | { |
112 | if (live == m_live) |
113 | return; |
114 | m_live = live; |
115 | |
116 | if (m_live && (!m_item || m_size.isNull())) |
117 | m_pixmap = QPixmap(); |
118 | |
119 | markDirtyTexture(); |
120 | } |
121 | |
122 | void QSGSoftwareLayer::setRecursive(bool recursive) |
123 | { |
124 | m_recursive = recursive; |
125 | } |
126 | |
127 | void QSGSoftwareLayer::setFormat(Format) |
128 | { |
129 | } |
130 | |
131 | void QSGSoftwareLayer::setHasMipmaps(bool) |
132 | { |
133 | } |
134 | |
135 | void QSGSoftwareLayer::setDevicePixelRatio(qreal ratio) |
136 | { |
137 | m_device_pixel_ratio = ratio; |
138 | } |
139 | |
140 | void QSGSoftwareLayer::setMirrorHorizontal(bool mirror) |
141 | { |
142 | if (m_mirrorHorizontal == mirror) |
143 | return; |
144 | m_mirrorHorizontal = mirror; |
145 | markDirtyTexture(); |
146 | } |
147 | |
148 | void QSGSoftwareLayer::setMirrorVertical(bool mirror) |
149 | { |
150 | if (m_mirrorVertical == mirror) |
151 | return; |
152 | m_mirrorVertical = mirror; |
153 | markDirtyTexture(); |
154 | } |
155 | |
156 | void QSGSoftwareLayer::markDirtyTexture() |
157 | { |
158 | m_dirtyTexture = true; |
159 | if (m_live || m_grab) { |
160 | emit updateRequested(); |
161 | } |
162 | } |
163 | |
164 | void QSGSoftwareLayer::invalidated() |
165 | { |
166 | delete m_renderer; |
167 | m_renderer = nullptr; |
168 | } |
169 | |
170 | void QSGSoftwareLayer::grab() |
171 | { |
172 | if (!m_item || m_size.isNull()) { |
173 | m_pixmap = QPixmap(); |
174 | m_dirtyTexture = false; |
175 | return; |
176 | } |
177 | QSGNode *root = m_item; |
178 | while (root->firstChild() && root->type() != QSGNode::RootNodeType) |
179 | root = root->firstChild(); |
180 | if (root->type() != QSGNode::RootNodeType) |
181 | return; |
182 | |
183 | if (!m_renderer) { |
184 | m_renderer = new QSGSoftwarePixmapRenderer(m_context); |
185 | connect(sender: m_renderer, SIGNAL(sceneGraphChanged()), receiver: this, SLOT(markDirtyTexture())); |
186 | } |
187 | m_renderer->setDevicePixelRatio(m_device_pixel_ratio); |
188 | m_renderer->setRootNode(static_cast<QSGRootNode *>(root)); |
189 | |
190 | if (m_pixmap.size() != m_size) { |
191 | m_pixmap = QPixmap(m_size); |
192 | m_pixmap.setDevicePixelRatio(m_device_pixel_ratio); |
193 | } |
194 | |
195 | // Render texture. |
196 | root->markDirty(bits: QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update. |
197 | m_renderer->nodeChanged(node: root, state: QSGNode::DirtyForceUpdate); // Force render list update. |
198 | |
199 | m_dirtyTexture = false; |
200 | |
201 | m_renderer->setDeviceRect(m_size); |
202 | m_renderer->setViewportRect(m_size); |
203 | QRect mirrored(m_mirrorHorizontal ? m_rect.right() * m_device_pixel_ratio : m_rect.left() * m_device_pixel_ratio, |
204 | m_mirrorVertical ? m_rect.bottom() * m_device_pixel_ratio : m_rect.top() * m_device_pixel_ratio, |
205 | m_mirrorHorizontal ? -m_rect.width() * m_device_pixel_ratio : m_rect.width() * m_device_pixel_ratio, |
206 | m_mirrorVertical ? -m_rect.height() * m_device_pixel_ratio : m_rect.height() * m_device_pixel_ratio); |
207 | m_renderer->setProjectionRect(mirrored); |
208 | m_renderer->setClearColor(Qt::transparent); |
209 | |
210 | m_renderer->renderScene(); |
211 | m_renderer->render(target: &m_pixmap); |
212 | |
213 | root->markDirty(bits: QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update. |
214 | |
215 | if (m_recursive) |
216 | markDirtyTexture(); // Continuously update if 'live' and 'recursive'. |
217 | } |
218 | |
219 | QT_END_NAMESPACE |
220 | |
221 | #include "moc_qsgsoftwarelayer_p.cpp" |
222 | |