1 | // Copyright (C) 2024 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 | #ifndef QQUICKSHAPEGENERICRENDERER_P_H |
5 | #define QQUICKSHAPEGENERICRENDERER_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists for the convenience |
12 | // of a number of Qt sources files. This header file may change from |
13 | // version to version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QtQuickShapes/private/qquickshapesglobal_p.h> |
19 | #include <QtQuickShapes/private/qquickshape_p_p.h> |
20 | #include <QtQuick/private/qsggradientcache_p.h> |
21 | #include <qsgnode.h> |
22 | #include <qsggeometry.h> |
23 | #include <qsgmaterial.h> |
24 | #include <qsgrendererinterface.h> |
25 | #include <qsgtexture.h> |
26 | #include <QtCore/qrunnable.h> |
27 | |
28 | QT_BEGIN_NAMESPACE |
29 | |
30 | class QQuickShapeGenericNode; |
31 | class QQuickShapeGenericStrokeFillNode; |
32 | class QQuickShapeFillRunnable; |
33 | class QQuickShapeStrokeRunnable; |
34 | |
35 | class QQuickShapeGenericRenderer : public QQuickAbstractPathRenderer |
36 | { |
37 | public: |
38 | enum Dirty { |
39 | DirtyFillGeom = 0x01, |
40 | DirtyStrokeGeom = 0x02, |
41 | DirtyColor = 0x04, |
42 | DirtyFillGradient = 0x08, |
43 | DirtyFillTransform = 0x10, |
44 | DirtyFillTexture = 0x20, |
45 | DirtyList = 0x40 // only for accDirty |
46 | }; |
47 | |
48 | QQuickShapeGenericRenderer(QQuickItem *item) |
49 | : m_item(item), |
50 | m_api(QSGRendererInterface::Unknown), |
51 | m_rootNode(nullptr), |
52 | m_accDirty(0), |
53 | m_asyncCallback(nullptr), |
54 | m_asyncCallbackData(nullptr) |
55 | { } |
56 | ~QQuickShapeGenericRenderer(); |
57 | |
58 | void beginSync(int totalCount, bool *countChanged) override; |
59 | void setPath(int index, const QQuickPath *path) override; |
60 | void setPath(int index, const QPainterPath &path, QQuickShapePath::PathHints pathHints = {}) override; |
61 | void setStrokeColor(int index, const QColor &color) override; |
62 | void setStrokeWidth(int index, qreal w) override; |
63 | void setFillColor(int index, const QColor &color) override; |
64 | void setFillRule(int index, QQuickShapePath::FillRule fillRule) override; |
65 | void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override; |
66 | void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override; |
67 | void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle, |
68 | qreal dashOffset, const QVector<qreal> &dashPattern) override; |
69 | void setFillGradient(int index, QQuickShapeGradient *gradient) override; |
70 | void setFillTextureProvider(int index, QQuickItem *textureProviderItem) override; |
71 | void setFillTransform(int index, const QSGTransform &transform) override; |
72 | void setTriangulationScale(qreal scale) override; |
73 | void endSync(bool async) override; |
74 | void setAsyncCallback(void (*)(void *), void *) override; |
75 | Flags flags() const override { return SupportsAsync; } |
76 | void handleSceneChange(QQuickWindow *window) override; |
77 | |
78 | void updateNode() override; |
79 | |
80 | void setRootNode(QQuickShapeGenericNode *node); |
81 | |
82 | struct Color4ub { unsigned char r, g, b, a; }; |
83 | typedef QVector<QSGGeometry::ColoredPoint2D> VertexContainerType; |
84 | typedef QVector<QSGGeometry::TexturedPoint2D> TexturedVertexContainerType; |
85 | typedef QVector<quint32> IndexContainerType; |
86 | |
87 | static void triangulateFill(const QPainterPath &path, |
88 | const Color4ub &fillColor, |
89 | VertexContainerType *fillVertices, |
90 | IndexContainerType *fillIndices, |
91 | QSGGeometry::Type *indexType, |
92 | bool supportsElementIndexUint, |
93 | qreal triangulationScale); |
94 | static void triangulateStroke(const QPainterPath &path, |
95 | const QPen &pen, |
96 | const Color4ub &strokeColor, |
97 | VertexContainerType *strokeVertices, |
98 | const QSize &clipSize, |
99 | qreal triangulationScale); |
100 | |
101 | private: |
102 | void maybeUpdateAsyncItem(); |
103 | |
104 | struct ShapePathData { |
105 | float strokeWidth; |
106 | QPen pen; |
107 | Color4ub strokeColor = { .r: uchar(0), .g: uchar(0), .b: uchar(0), .a: uchar(0) }; |
108 | Color4ub fillColor = { .r: uchar(0), .g: uchar(0), .b: uchar(0), .a: uchar(0) }; |
109 | Qt::FillRule fillRule; |
110 | QPainterPath path; |
111 | FillGradientType fillGradientActive; |
112 | QSGGradientCache::GradientDesc fillGradient; |
113 | QQuickItem *fillTextureProviderItem = nullptr; |
114 | QSGTransform fillTransform; |
115 | VertexContainerType fillVertices; |
116 | IndexContainerType fillIndices; |
117 | QSGGeometry::Type indexType; |
118 | VertexContainerType strokeVertices; |
119 | int syncDirty; |
120 | int effectiveDirty = 0; |
121 | QQuickShapeFillRunnable *pendingFill = nullptr; |
122 | QQuickShapeStrokeRunnable *pendingStroke = nullptr; |
123 | }; |
124 | |
125 | void updateShadowDataInNode(ShapePathData *d, QQuickShapeGenericStrokeFillNode *n); |
126 | void updateFillNode(ShapePathData *d, QQuickShapeGenericNode *node); |
127 | void updateStrokeNode(ShapePathData *d, QQuickShapeGenericNode *node); |
128 | |
129 | QQuickItem *m_item; |
130 | QSGRendererInterface::GraphicsApi m_api; |
131 | QQuickShapeGenericNode *m_rootNode; |
132 | QVector<ShapePathData> m_sp; |
133 | int m_accDirty; |
134 | void (*m_asyncCallback)(void *); |
135 | void *m_asyncCallbackData; |
136 | float m_triangulationScale = 1.0; |
137 | }; |
138 | |
139 | class QQuickShapeFillRunnable : public QObject, public QRunnable |
140 | { |
141 | Q_OBJECT |
142 | |
143 | public: |
144 | void run() override; |
145 | |
146 | bool orphaned = false; |
147 | |
148 | // input |
149 | QPainterPath path; |
150 | QQuickShapeGenericRenderer::Color4ub fillColor; |
151 | bool supportsElementIndexUint; |
152 | qreal triangulationScale; |
153 | |
154 | // output |
155 | QQuickShapeGenericRenderer::VertexContainerType fillVertices; |
156 | QQuickShapeGenericRenderer::IndexContainerType fillIndices; |
157 | QSGGeometry::Type indexType; |
158 | |
159 | Q_SIGNALS: |
160 | void done(QQuickShapeFillRunnable *self); |
161 | }; |
162 | |
163 | class QQuickShapeStrokeRunnable : public QObject, public QRunnable |
164 | { |
165 | Q_OBJECT |
166 | |
167 | public: |
168 | void run() override; |
169 | |
170 | bool orphaned = false; |
171 | |
172 | // input |
173 | QPainterPath path; |
174 | QPen pen; |
175 | QQuickShapeGenericRenderer::Color4ub strokeColor; |
176 | QSize clipSize; |
177 | qreal triangulationScale; |
178 | |
179 | // output |
180 | QQuickShapeGenericRenderer::VertexContainerType strokeVertices; |
181 | |
182 | Q_SIGNALS: |
183 | void done(QQuickShapeStrokeRunnable *self); |
184 | }; |
185 | |
186 | class QQuickShapeGenericStrokeFillNode : public QObject, public QSGGeometryNode |
187 | { |
188 | Q_OBJECT |
189 | public: |
190 | QQuickShapeGenericStrokeFillNode(QQuickWindow *window); |
191 | |
192 | enum Material { |
193 | MatSolidColor, |
194 | MatLinearGradient, |
195 | MatRadialGradient, |
196 | MatConicalGradient, |
197 | MatTextureFill |
198 | }; |
199 | |
200 | void activateMaterial(QQuickWindow *window, Material m); |
201 | |
202 | // shadow data for custom materials |
203 | QSGGradientCache::GradientDesc m_fillGradient; |
204 | QSGTextureProvider *m_fillTextureProvider = nullptr; |
205 | QSGTransform m_fillTransform; |
206 | void preprocess() override; |
207 | |
208 | private Q_SLOTS: |
209 | void handleTextureChanged(); |
210 | void handleTextureProviderDestroyed(); |
211 | |
212 | private: |
213 | QScopedPointer<QSGMaterial> m_material; |
214 | |
215 | friend class QQuickShapeGenericRenderer; |
216 | }; |
217 | |
218 | class QQuickShapeGenericNode : public QSGNode |
219 | { |
220 | public: |
221 | QQuickShapeGenericStrokeFillNode *m_fillNode = nullptr; |
222 | QQuickShapeGenericStrokeFillNode *m_strokeNode = nullptr; |
223 | QQuickShapeGenericNode *m_next = nullptr; |
224 | }; |
225 | |
226 | class QQuickShapeGenericMaterialFactory |
227 | { |
228 | public: |
229 | static QSGMaterial *createVertexColor(QQuickWindow *window); |
230 | static QSGMaterial *createLinearGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node); |
231 | static QSGMaterial *createRadialGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node); |
232 | static QSGMaterial *createConicalGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node); |
233 | static QSGMaterial *createTextureFill(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node); |
234 | }; |
235 | |
236 | class QQuickShapeLinearGradientRhiShader : public QSGMaterialShader |
237 | { |
238 | public: |
239 | QQuickShapeLinearGradientRhiShader(int viewCount); |
240 | |
241 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, |
242 | QSGMaterial *oldMaterial) override; |
243 | void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, |
244 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
245 | |
246 | private: |
247 | QSGTransform m_fillTransform; |
248 | QVector2D m_gradA; |
249 | QVector2D m_gradB; |
250 | }; |
251 | |
252 | class QQuickShapeLinearGradientMaterial : public QSGMaterial |
253 | { |
254 | public: |
255 | QQuickShapeLinearGradientMaterial(QQuickShapeGenericStrokeFillNode *node) |
256 | : m_node(node) |
257 | { |
258 | // Passing RequiresFullMatrix is essential in order to prevent the |
259 | // batch renderer from baking in simple, translate-only transforms into |
260 | // the vertex data. The shader will rely on the fact that |
261 | // vertexCoord.xy is the Shape-space coordinate and so no modifications |
262 | // are welcome. |
263 | setFlag(flags: Blending | RequiresFullMatrix); |
264 | } |
265 | |
266 | QSGMaterialType *type() const override; |
267 | int compare(const QSGMaterial *other) const override; |
268 | QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override; |
269 | |
270 | QQuickShapeGenericStrokeFillNode *node() const { return m_node; } |
271 | |
272 | private: |
273 | QQuickShapeGenericStrokeFillNode *m_node; |
274 | }; |
275 | |
276 | class QQuickShapeRadialGradientRhiShader : public QSGMaterialShader |
277 | { |
278 | public: |
279 | QQuickShapeRadialGradientRhiShader(int viewCount); |
280 | |
281 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, |
282 | QSGMaterial *oldMaterial) override; |
283 | void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, |
284 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
285 | |
286 | private: |
287 | QSGTransform m_fillTransform; |
288 | QVector2D m_focalPoint; |
289 | QVector2D m_focalToCenter; |
290 | float m_centerRadius; |
291 | float m_focalRadius; |
292 | }; |
293 | |
294 | class QQuickShapeRadialGradientMaterial : public QSGMaterial |
295 | { |
296 | public: |
297 | QQuickShapeRadialGradientMaterial(QQuickShapeGenericStrokeFillNode *node) |
298 | : m_node(node) |
299 | { |
300 | setFlag(flags: Blending | RequiresFullMatrix); |
301 | } |
302 | |
303 | QSGMaterialType *type() const override; |
304 | int compare(const QSGMaterial *other) const override; |
305 | QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override; |
306 | |
307 | QQuickShapeGenericStrokeFillNode *node() const { return m_node; } |
308 | |
309 | private: |
310 | QQuickShapeGenericStrokeFillNode *m_node; |
311 | }; |
312 | |
313 | class QQuickShapeConicalGradientRhiShader : public QSGMaterialShader |
314 | { |
315 | public: |
316 | QQuickShapeConicalGradientRhiShader(int viewCount); |
317 | |
318 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, |
319 | QSGMaterial *oldMaterial) override; |
320 | void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, |
321 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
322 | |
323 | private: |
324 | QSGTransform m_fillTransform; |
325 | QVector2D m_centerPoint; |
326 | float m_angle; |
327 | }; |
328 | |
329 | class QQuickShapeConicalGradientMaterial : public QSGMaterial |
330 | { |
331 | public: |
332 | QQuickShapeConicalGradientMaterial(QQuickShapeGenericStrokeFillNode *node) |
333 | : m_node(node) |
334 | { |
335 | setFlag(flags: Blending | RequiresFullMatrix); |
336 | } |
337 | |
338 | QSGMaterialType *type() const override; |
339 | int compare(const QSGMaterial *other) const override; |
340 | QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override; |
341 | |
342 | QQuickShapeGenericStrokeFillNode *node() const { return m_node; } |
343 | |
344 | private: |
345 | QQuickShapeGenericStrokeFillNode *m_node; |
346 | }; |
347 | |
348 | class QQuickShapeTextureFillRhiShader : public QSGMaterialShader |
349 | { |
350 | public: |
351 | QQuickShapeTextureFillRhiShader(int viewCount); |
352 | |
353 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, |
354 | QSGMaterial *oldMaterial) override; |
355 | void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, |
356 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
357 | |
358 | private: |
359 | QSGTransform m_fillTransform; |
360 | QVector2D m_boundsOffset; |
361 | QVector2D m_boundsSize; |
362 | }; |
363 | |
364 | class QQuickShapeTextureFillMaterial : public QSGMaterial |
365 | { |
366 | public: |
367 | QQuickShapeTextureFillMaterial(QQuickShapeGenericStrokeFillNode *node) |
368 | : m_node(node) |
369 | { |
370 | setFlag(flags: Blending | RequiresFullMatrix); |
371 | } |
372 | ~QQuickShapeTextureFillMaterial() override; |
373 | |
374 | QSGMaterialType *type() const override; |
375 | int compare(const QSGMaterial *other) const override; |
376 | QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override; |
377 | |
378 | QQuickShapeGenericStrokeFillNode *node() const { return m_node; } |
379 | |
380 | QSGPlainTexture *dummyTexture() const |
381 | { |
382 | return m_dummyTexture; |
383 | } |
384 | |
385 | void setDummyTexture(QSGPlainTexture *texture) |
386 | { |
387 | m_dummyTexture = texture; |
388 | } |
389 | |
390 | private: |
391 | QQuickShapeGenericStrokeFillNode *m_node; |
392 | QSGPlainTexture *m_dummyTexture = nullptr; |
393 | }; |
394 | |
395 | QT_END_NAMESPACE |
396 | |
397 | #endif // QQUICKSHAPEGENERICRENDERER_P_H |
398 |
Definitions
- QQuickShapeGenericRenderer
- Dirty
- QQuickShapeGenericRenderer
- flags
- Color4ub
- ShapePathData
- QQuickShapeFillRunnable
- QQuickShapeStrokeRunnable
- QQuickShapeGenericStrokeFillNode
- Material
- QQuickShapeGenericNode
- QQuickShapeGenericMaterialFactory
- QQuickShapeLinearGradientRhiShader
- QQuickShapeLinearGradientMaterial
- QQuickShapeLinearGradientMaterial
- node
- QQuickShapeRadialGradientRhiShader
- QQuickShapeRadialGradientMaterial
- QQuickShapeRadialGradientMaterial
- node
- QQuickShapeConicalGradientRhiShader
- QQuickShapeConicalGradientMaterial
- QQuickShapeConicalGradientMaterial
- node
- QQuickShapeTextureFillRhiShader
- QQuickShapeTextureFillMaterial
- QQuickShapeTextureFillMaterial
- node
- dummyTexture
Learn to use CMake with our Intro Training
Find out more