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
28QT_BEGIN_NAMESPACE
29
30class QQuickShapeGenericNode;
31class QQuickShapeGenericStrokeFillNode;
32class QQuickShapeFillRunnable;
33class QQuickShapeStrokeRunnable;
34
35class QQuickShapeGenericRenderer : public QQuickAbstractPathRenderer
36{
37public:
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
101private:
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
139class QQuickShapeFillRunnable : public QObject, public QRunnable
140{
141 Q_OBJECT
142
143public:
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
159Q_SIGNALS:
160 void done(QQuickShapeFillRunnable *self);
161};
162
163class QQuickShapeStrokeRunnable : public QObject, public QRunnable
164{
165 Q_OBJECT
166
167public:
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
182Q_SIGNALS:
183 void done(QQuickShapeStrokeRunnable *self);
184};
185
186class QQuickShapeGenericStrokeFillNode : public QObject, public QSGGeometryNode
187{
188 Q_OBJECT
189public:
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
208private Q_SLOTS:
209 void handleTextureChanged();
210 void handleTextureProviderDestroyed();
211
212private:
213 QScopedPointer<QSGMaterial> m_material;
214
215 friend class QQuickShapeGenericRenderer;
216};
217
218class QQuickShapeGenericNode : public QSGNode
219{
220public:
221 QQuickShapeGenericStrokeFillNode *m_fillNode = nullptr;
222 QQuickShapeGenericStrokeFillNode *m_strokeNode = nullptr;
223 QQuickShapeGenericNode *m_next = nullptr;
224};
225
226class QQuickShapeGenericMaterialFactory
227{
228public:
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
236class QQuickShapeLinearGradientRhiShader : public QSGMaterialShader
237{
238public:
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
246private:
247 QSGTransform m_fillTransform;
248 QVector2D m_gradA;
249 QVector2D m_gradB;
250};
251
252class QQuickShapeLinearGradientMaterial : public QSGMaterial
253{
254public:
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
272private:
273 QQuickShapeGenericStrokeFillNode *m_node;
274};
275
276class QQuickShapeRadialGradientRhiShader : public QSGMaterialShader
277{
278public:
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
286private:
287 QSGTransform m_fillTransform;
288 QVector2D m_focalPoint;
289 QVector2D m_focalToCenter;
290 float m_centerRadius;
291 float m_focalRadius;
292};
293
294class QQuickShapeRadialGradientMaterial : public QSGMaterial
295{
296public:
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
309private:
310 QQuickShapeGenericStrokeFillNode *m_node;
311};
312
313class QQuickShapeConicalGradientRhiShader : public QSGMaterialShader
314{
315public:
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
323private:
324 QSGTransform m_fillTransform;
325 QVector2D m_centerPoint;
326 float m_angle;
327};
328
329class QQuickShapeConicalGradientMaterial : public QSGMaterial
330{
331public:
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
344private:
345 QQuickShapeGenericStrokeFillNode *m_node;
346};
347
348class QQuickShapeTextureFillRhiShader : public QSGMaterialShader
349{
350public:
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
358private:
359 QSGTransform m_fillTransform;
360 QVector2D m_boundsOffset;
361 QVector2D m_boundsSize;
362};
363
364class QQuickShapeTextureFillMaterial : public QSGMaterial
365{
366public:
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
390private:
391 QQuickShapeGenericStrokeFillNode *m_node;
392 QSGPlainTexture *m_dummyTexture = nullptr;
393};
394
395QT_END_NAMESPACE
396
397#endif // QQUICKSHAPEGENERICRENDERER_P_H
398

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtdeclarative/src/quickshapes/qquickshapegenericrenderer_p.h