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#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 <qsgnode.h>
21#include <qsggeometry.h>
22#include <qsgmaterial.h>
23#include <qsgrendererinterface.h>
24#include <qsgtexture.h>
25#include <QtCore/qrunnable.h>
26
27QT_BEGIN_NAMESPACE
28
29class QQuickShapeGenericNode;
30class QQuickShapeGenericStrokeFillNode;
31class QQuickShapeFillRunnable;
32class QQuickShapeStrokeRunnable;
33
34class QQuickShapeGenericRenderer : public QQuickAbstractPathRenderer
35{
36public:
37 enum Dirty {
38 DirtyFillGeom = 0x01,
39 DirtyStrokeGeom = 0x02,
40 DirtyColor = 0x04,
41 DirtyFillGradient = 0x08,
42 DirtyList = 0x10 // only for accDirty
43 };
44
45 QQuickShapeGenericRenderer(QQuickItem *item)
46 : m_item(item),
47 m_api(QSGRendererInterface::Unknown),
48 m_rootNode(nullptr),
49 m_accDirty(0),
50 m_asyncCallback(nullptr),
51 m_asyncCallbackData(nullptr)
52 { }
53 ~QQuickShapeGenericRenderer();
54
55 void beginSync(int totalCount, bool *countChanged) override;
56 void setPath(int index, const QQuickPath *path) override;
57 void setStrokeColor(int index, const QColor &color) override;
58 void setStrokeWidth(int index, qreal w) override;
59 void setFillColor(int index, const QColor &color) override;
60 void setFillRule(int index, QQuickShapePath::FillRule fillRule) override;
61 void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override;
62 void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override;
63 void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
64 qreal dashOffset, const QVector<qreal> &dashPattern) override;
65 void setFillGradient(int index, QQuickShapeGradient *gradient) override;
66 void setTriangulationScale(qreal scale) override;
67 void endSync(bool async) override;
68 void setAsyncCallback(void (*)(void *), void *) override;
69 Flags flags() const override { return SupportsAsync; }
70
71 void updateNode() override;
72
73 void setRootNode(QQuickShapeGenericNode *node);
74
75 struct Color4ub { unsigned char r, g, b, a; };
76 typedef QVector<QSGGeometry::ColoredPoint2D> VertexContainerType;
77 typedef QVector<quint32> IndexContainerType;
78
79 static void triangulateFill(const QPainterPath &path,
80 const Color4ub &fillColor,
81 VertexContainerType *fillVertices,
82 IndexContainerType *fillIndices,
83 QSGGeometry::Type *indexType,
84 bool supportsElementIndexUint,
85 qreal triangulationScale);
86 static void triangulateStroke(const QPainterPath &path,
87 const QPen &pen,
88 const Color4ub &strokeColor,
89 VertexContainerType *strokeVertices,
90 const QSize &clipSize,
91 qreal triangulationScale);
92
93private:
94 void maybeUpdateAsyncItem();
95
96 struct ShapePathData {
97 float strokeWidth;
98 QPen pen;
99 Color4ub strokeColor;
100 Color4ub fillColor;
101 Qt::FillRule fillRule;
102 QPainterPath path;
103 FillGradientType fillGradientActive;
104 GradientDesc fillGradient;
105 VertexContainerType fillVertices;
106 IndexContainerType fillIndices;
107 QSGGeometry::Type indexType;
108 VertexContainerType strokeVertices;
109 int syncDirty;
110 int effectiveDirty = 0;
111 QQuickShapeFillRunnable *pendingFill = nullptr;
112 QQuickShapeStrokeRunnable *pendingStroke = nullptr;
113 };
114
115 void updateShadowDataInNode(ShapePathData *d, QQuickShapeGenericStrokeFillNode *n);
116 void updateFillNode(ShapePathData *d, QQuickShapeGenericNode *node);
117 void updateStrokeNode(ShapePathData *d, QQuickShapeGenericNode *node);
118
119 QQuickItem *m_item;
120 QSGRendererInterface::GraphicsApi m_api;
121 QQuickShapeGenericNode *m_rootNode;
122 QVector<ShapePathData> m_sp;
123 int m_accDirty;
124 void (*m_asyncCallback)(void *);
125 void *m_asyncCallbackData;
126 float m_triangulationScale = 1.0;
127};
128
129class QQuickShapeFillRunnable : public QObject, public QRunnable
130{
131 Q_OBJECT
132
133public:
134 void run() override;
135
136 bool orphaned = false;
137
138 // input
139 QPainterPath path;
140 QQuickShapeGenericRenderer::Color4ub fillColor;
141 bool supportsElementIndexUint;
142 qreal triangulationScale;
143
144 // output
145 QQuickShapeGenericRenderer::VertexContainerType fillVertices;
146 QQuickShapeGenericRenderer::IndexContainerType fillIndices;
147 QSGGeometry::Type indexType;
148
149Q_SIGNALS:
150 void done(QQuickShapeFillRunnable *self);
151};
152
153class QQuickShapeStrokeRunnable : public QObject, public QRunnable
154{
155 Q_OBJECT
156
157public:
158 void run() override;
159
160 bool orphaned = false;
161
162 // input
163 QPainterPath path;
164 QPen pen;
165 QQuickShapeGenericRenderer::Color4ub strokeColor;
166 QSize clipSize;
167 qreal triangulationScale;
168
169 // output
170 QQuickShapeGenericRenderer::VertexContainerType strokeVertices;
171
172Q_SIGNALS:
173 void done(QQuickShapeStrokeRunnable *self);
174};
175
176class QQuickShapeGenericStrokeFillNode : public QSGGeometryNode
177{
178public:
179 QQuickShapeGenericStrokeFillNode(QQuickWindow *window);
180
181 enum Material {
182 MatSolidColor,
183 MatLinearGradient,
184 MatRadialGradient,
185 MatConicalGradient
186 };
187
188 void activateMaterial(QQuickWindow *window, Material m);
189
190 // shadow data for custom materials
191 QQuickAbstractPathRenderer::GradientDesc m_fillGradient;
192
193private:
194 QScopedPointer<QSGMaterial> m_material;
195
196 friend class QQuickShapeGenericRenderer;
197};
198
199class QQuickShapeGenericNode : public QSGNode
200{
201public:
202 QQuickShapeGenericStrokeFillNode *m_fillNode = nullptr;
203 QQuickShapeGenericStrokeFillNode *m_strokeNode = nullptr;
204 QQuickShapeGenericNode *m_next = nullptr;
205};
206
207class QQuickShapeGenericMaterialFactory
208{
209public:
210 static QSGMaterial *createVertexColor(QQuickWindow *window);
211 static QSGMaterial *createLinearGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node);
212 static QSGMaterial *createRadialGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node);
213 static QSGMaterial *createConicalGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node);
214};
215
216class QQuickShapeLinearGradientRhiShader : public QSGMaterialShader
217{
218public:
219 QQuickShapeLinearGradientRhiShader();
220
221 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
222 QSGMaterial *oldMaterial) override;
223 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
224 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
225
226private:
227 QVector2D m_gradA;
228 QVector2D m_gradB;
229};
230
231class QQuickShapeLinearGradientMaterial : public QSGMaterial
232{
233public:
234 QQuickShapeLinearGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
235 : m_node(node)
236 {
237 // Passing RequiresFullMatrix is essential in order to prevent the
238 // batch renderer from baking in simple, translate-only transforms into
239 // the vertex data. The shader will rely on the fact that
240 // vertexCoord.xy is the Shape-space coordinate and so no modifications
241 // are welcome.
242 setFlag(flags: Blending | RequiresFullMatrix);
243 }
244
245 QSGMaterialType *type() const override;
246 int compare(const QSGMaterial *other) const override;
247 QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override;
248
249 QQuickShapeGenericStrokeFillNode *node() const { return m_node; }
250
251private:
252 QQuickShapeGenericStrokeFillNode *m_node;
253};
254
255class QQuickShapeRadialGradientRhiShader : public QSGMaterialShader
256{
257public:
258 QQuickShapeRadialGradientRhiShader();
259
260 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
261 QSGMaterial *oldMaterial) override;
262 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
263 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
264
265private:
266 QVector2D m_focalPoint;
267 QVector2D m_focalToCenter;
268 float m_centerRadius;
269 float m_focalRadius;
270};
271
272class QQuickShapeRadialGradientMaterial : public QSGMaterial
273{
274public:
275 QQuickShapeRadialGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
276 : m_node(node)
277 {
278 setFlag(flags: Blending | RequiresFullMatrix);
279 }
280
281 QSGMaterialType *type() const override;
282 int compare(const QSGMaterial *other) const override;
283 QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override;
284
285 QQuickShapeGenericStrokeFillNode *node() const { return m_node; }
286
287private:
288 QQuickShapeGenericStrokeFillNode *m_node;
289};
290
291class QQuickShapeConicalGradientRhiShader : public QSGMaterialShader
292{
293public:
294 QQuickShapeConicalGradientRhiShader();
295
296 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
297 QSGMaterial *oldMaterial) override;
298 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
299 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
300
301private:
302 QVector2D m_centerPoint;
303 float m_angle;
304};
305
306class QQuickShapeConicalGradientMaterial : public QSGMaterial
307{
308public:
309 QQuickShapeConicalGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
310 : m_node(node)
311 {
312 setFlag(flags: Blending | RequiresFullMatrix);
313 }
314
315 QSGMaterialType *type() const override;
316 int compare(const QSGMaterial *other) const override;
317 QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override;
318
319 QQuickShapeGenericStrokeFillNode *node() const { return m_node; }
320
321private:
322 QQuickShapeGenericStrokeFillNode *m_node;
323};
324
325QT_END_NAMESPACE
326
327#endif // QQUICKSHAPEGENERICRENDERER_P_H
328

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