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 QSGADAPTATIONLAYER_P_H
5#define QSGADAPTATIONLAYER_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 purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtQuick/qsgnode.h>
19#include <QtQuick/qsgtexture.h>
20#include <QtQuick/qquickpainteditem.h>
21#include <QtCore/qobject.h>
22#include <QtCore/qrect.h>
23#include <QtGui/qbrush.h>
24#include <QtGui/qcolor.h>
25#include <QtGui/qpainterpath.h>
26#include <QtCore/qsharedpointer.h>
27#include <QtGui/qglyphrun.h>
28#include <QtGui/qpainterpath.h>
29#include <QtCore/qurl.h>
30#include <private/qfontengine_p.h>
31#include <QtGui/private/qdatabuffer_p.h>
32#include <private/qdistancefield_p.h>
33#include <private/qintrusivelist_p.h>
34#include <rhi/qshader.h>
35
36// ### remove
37#include <QtQuick/private/qquicktext_p.h>
38
39QT_BEGIN_NAMESPACE
40
41class QSGNode;
42class QImage;
43class TextureReference;
44class QSGDistanceFieldGlyphNode;
45class QSGInternalImageNode;
46class QSGPainterNode;
47class QSGInternalRectangleNode;
48class QSGGlyphNode;
49class QSGRootNode;
50class QSGSpriteNode;
51class QSGRenderNode;
52class QSGRenderContext;
53class QRhiTexture;
54
55class Q_QUICK_PRIVATE_EXPORT QSGNodeVisitorEx
56{
57public:
58 virtual ~QSGNodeVisitorEx();
59
60 // visit(...) returns true if the children are supposed to be
61 // visisted and false if they're supposed to be skipped by the visitor.
62
63 virtual bool visit(QSGTransformNode *) = 0;
64 virtual void endVisit(QSGTransformNode *) = 0;
65 virtual bool visit(QSGClipNode *) = 0;
66 virtual void endVisit(QSGClipNode *) = 0;
67 virtual bool visit(QSGGeometryNode *) = 0;
68 virtual void endVisit(QSGGeometryNode *) = 0;
69 virtual bool visit(QSGOpacityNode *) = 0;
70 virtual void endVisit(QSGOpacityNode *) = 0;
71 virtual bool visit(QSGInternalImageNode *) = 0;
72 virtual void endVisit(QSGInternalImageNode *) = 0;
73 virtual bool visit(QSGPainterNode *) = 0;
74 virtual void endVisit(QSGPainterNode *) = 0;
75 virtual bool visit(QSGInternalRectangleNode *) = 0;
76 virtual void endVisit(QSGInternalRectangleNode *) = 0;
77 virtual bool visit(QSGGlyphNode *) = 0;
78 virtual void endVisit(QSGGlyphNode *) = 0;
79 virtual bool visit(QSGRootNode *) = 0;
80 virtual void endVisit(QSGRootNode *) = 0;
81#if QT_CONFIG(quick_sprite)
82 virtual bool visit(QSGSpriteNode *) = 0;
83 virtual void endVisit(QSGSpriteNode *) = 0;
84#endif
85 virtual bool visit(QSGRenderNode *) = 0;
86 virtual void endVisit(QSGRenderNode *) = 0;
87
88 void visitChildren(QSGNode *node);
89};
90
91
92class Q_QUICK_PRIVATE_EXPORT QSGVisitableNode : public QSGGeometryNode
93{
94public:
95 QSGVisitableNode() { setFlag(IsVisitableNode); }
96 ~QSGVisitableNode() override;
97
98 virtual void accept(QSGNodeVisitorEx *) = 0;
99};
100
101class Q_QUICK_PRIVATE_EXPORT QSGInternalRectangleNode : public QSGVisitableNode
102{
103public:
104 ~QSGInternalRectangleNode() override;
105
106 virtual void setRect(const QRectF &rect) = 0;
107 virtual void setColor(const QColor &color) = 0;
108 virtual void setPenColor(const QColor &color) = 0;
109 virtual void setPenWidth(qreal width) = 0;
110 virtual void setGradientStops(const QGradientStops &stops) = 0;
111 virtual void setGradientVertical(bool vertical) = 0;
112 virtual void setRadius(qreal radius) = 0;
113 virtual void setAntialiasing(bool antialiasing) { Q_UNUSED(antialiasing); }
114 virtual void setAligned(bool aligned) = 0;
115
116 virtual void update() = 0;
117
118 void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(node: this); visitor->endVisit(this); }
119};
120
121
122class Q_QUICK_PRIVATE_EXPORT QSGInternalImageNode : public QSGVisitableNode
123{
124public:
125 ~QSGInternalImageNode() override;
126
127 virtual void setTargetRect(const QRectF &rect) = 0;
128 virtual void setInnerTargetRect(const QRectF &rect) = 0;
129 virtual void setInnerSourceRect(const QRectF &rect) = 0;
130 // The sub-source rect's width and height specify the number of times the inner source rect
131 // is repeated inside the inner target rect. The x and y specify which (normalized) location
132 // in the inner source rect maps to the upper-left corner of the inner target rect.
133 virtual void setSubSourceRect(const QRectF &rect) = 0;
134 virtual void setTexture(QSGTexture *texture) = 0;
135 virtual void setAntialiasing(bool antialiasing) { Q_UNUSED(antialiasing); }
136 virtual void setMirror(bool horizontally, bool vertically) = 0;
137 virtual void setMipmapFiltering(QSGTexture::Filtering filtering) = 0;
138 virtual void setFiltering(QSGTexture::Filtering filtering) = 0;
139 virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
140 virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
141
142 virtual void update() = 0;
143
144 void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(node: this); visitor->endVisit(this); }
145};
146
147class Q_QUICK_PRIVATE_EXPORT QSGPainterNode : public QSGVisitableNode
148{
149public:
150 ~QSGPainterNode() override;
151
152 virtual void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target) = 0;
153 virtual void setSize(const QSize &size) = 0;
154 virtual void setDirty(const QRect &dirtyRect = QRect()) = 0;
155 virtual void setOpaquePainting(bool opaque) = 0;
156 virtual void setLinearFiltering(bool linearFiltering) = 0;
157 virtual void setMipmapping(bool mipmapping) = 0;
158 virtual void setSmoothPainting(bool s) = 0;
159 virtual void setFillColor(const QColor &c) = 0;
160 virtual void setContentsScale(qreal s) = 0;
161 virtual void setFastFBOResizing(bool dynamic) = 0;
162 virtual void setTextureSize(const QSize &size) = 0;
163
164 virtual QImage toImage() const = 0;
165 virtual void update() = 0;
166 virtual QSGTexture *texture() const = 0;
167
168 void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(node: this); visitor->endVisit(this); }
169};
170
171class Q_QUICK_EXPORT QSGLayer : public QSGDynamicTexture
172{
173 Q_OBJECT
174public:
175 ~QSGLayer() override;
176
177 enum Format {
178 RGBA8 = 1,
179 RGBA16F,
180 RGBA32F
181 };
182 virtual void setItem(QSGNode *item) = 0;
183 virtual void setRect(const QRectF &logicalRect) = 0;
184 virtual void setSize(const QSize &pixelSize) = 0;
185 virtual void scheduleUpdate() = 0;
186 virtual QImage toImage() const = 0;
187 virtual void setLive(bool live) = 0;
188 virtual void setRecursive(bool recursive) = 0;
189 virtual void setFormat(Format format) = 0;
190 virtual void setHasMipmaps(bool mipmap) = 0;
191 virtual void setDevicePixelRatio(qreal ratio) = 0;
192 virtual void setMirrorHorizontal(bool mirror) = 0;
193 virtual void setMirrorVertical(bool mirror) = 0;
194 virtual void setSamples(int samples) = 0;
195 Q_SLOT virtual void markDirtyTexture() = 0;
196 Q_SLOT virtual void invalidated() = 0;
197
198Q_SIGNALS:
199 void updateRequested();
200 void scheduledUpdateCompleted();
201
202protected:
203 QSGLayer(QSGTexturePrivate &dd);
204};
205
206#if QT_CONFIG(quick_sprite)
207
208class Q_QUICK_PRIVATE_EXPORT QSGSpriteNode : public QSGVisitableNode
209{
210public:
211 ~QSGSpriteNode() override;
212
213 virtual void setTexture(QSGTexture *texture) = 0;
214 virtual void setTime(float time) = 0;
215 virtual void setSourceA(const QPoint &source) = 0;
216 virtual void setSourceB(const QPoint &source) = 0;
217 virtual void setSpriteSize(const QSize &size) = 0;
218 virtual void setSheetSize(const QSize &size) = 0;
219 virtual void setSize(const QSizeF &size) = 0;
220 virtual void setFiltering(QSGTexture::Filtering filtering) = 0;
221
222 virtual void update() = 0;
223
224 void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(node: this); visitor->endVisit(this); }
225};
226
227#endif
228
229class Q_QUICK_PRIVATE_EXPORT QSGGuiThreadShaderEffectManager : public QObject
230{
231 Q_OBJECT
232
233public:
234 ~QSGGuiThreadShaderEffectManager() override;
235
236 enum Status {
237 Compiled,
238 Uncompiled,
239 Error
240 };
241
242 virtual bool hasSeparateSamplerAndTextureObjects() const = 0;
243
244 virtual QString log() const = 0;
245 virtual Status status() const = 0;
246
247 struct ShaderInfo {
248 enum Type {
249 TypeVertex,
250 TypeFragment,
251 TypeOther
252 };
253 enum VariableType {
254 Constant, // cbuffer members or uniforms
255 Sampler,
256 Texture // for APIs with separate texture and sampler objects
257 };
258 struct Variable {
259 VariableType type = Constant;
260 QByteArray name;
261 uint offset = 0; // for cbuffer members
262 uint size = 0; // for cbuffer members
263 int bindPoint = 0; // for textures/samplers, where applicable
264 };
265
266 QString name; // optional, f.ex. the filename, used for debugging purposes only
267 QShader rhiShader;
268 Type type;
269 QVector<Variable> variables;
270 uint constantDataSize;
271
272 // Vertex inputs are not tracked here as QSGGeometry::AttributeSet
273 // hardwires that anyways so it is up to the shader to provide
274 // compatible inputs (e.g. compatible with
275 // QSGGeometry::defaultAttributes_TexturedPoint2D()).
276 };
277
278 virtual void prepareShaderCode(ShaderInfo::Type typeHint, const QUrl &src, ShaderInfo *result) = 0;
279
280Q_SIGNALS:
281 void shaderCodePrepared(bool ok, ShaderInfo::Type typeHint, const QUrl &src, ShaderInfo *result);
282 void logAndStatusChanged();
283};
284
285#ifndef QT_NO_DEBUG_STREAM
286Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug debug, const QSGGuiThreadShaderEffectManager::ShaderInfo::Variable &v);
287#endif
288
289class Q_QUICK_PRIVATE_EXPORT QSGShaderEffectNode : public QObject, public QSGVisitableNode
290{
291 Q_OBJECT
292
293public:
294 ~QSGShaderEffectNode() override;
295
296 enum DirtyShaderFlag {
297 DirtyShaders = 0x01,
298 DirtyShaderConstant = 0x02,
299 DirtyShaderTexture = 0x04,
300 DirtyShaderGeometry = 0x08,
301 DirtyShaderMesh = 0x10,
302
303 DirtyShaderAll = 0xFF
304 };
305 Q_DECLARE_FLAGS(DirtyShaderFlags, DirtyShaderFlag)
306
307 enum CullMode { // must match ShaderEffect
308 NoCulling,
309 BackFaceCulling,
310 FrontFaceCulling
311 };
312
313 struct VariableData {
314 enum SpecialType { None, Unused, Source, SubRect, Opacity, Matrix };
315
316 QVariant value;
317 SpecialType specialType;
318 int propertyIndex = -1;
319 };
320
321 struct ShaderData {
322 ShaderData() {}
323 bool hasShaderCode = false;
324 QSGGuiThreadShaderEffectManager::ShaderInfo shaderInfo;
325 QVector<VariableData> varData;
326 };
327
328 struct SyncData {
329 DirtyShaderFlags dirty;
330 CullMode cullMode;
331 bool blending;
332 struct ShaderSyncData {
333 const ShaderData *shader;
334 const QSet<int> *dirtyConstants;
335 const QSet<int> *dirtyTextures;
336 };
337 ShaderSyncData vertex;
338 ShaderSyncData fragment;
339 void *materialTypeCacheKey;
340 };
341
342 // Each ShaderEffect item has one node (render thread) and one manager (gui thread).
343
344 virtual QRectF updateNormalizedTextureSubRect(bool supportsAtlasTextures) = 0;
345 virtual void syncMaterial(SyncData *syncData) = 0;
346
347 void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(node: this); visitor->endVisit(this); }
348
349Q_SIGNALS:
350 void textureChanged();
351};
352
353Q_DECLARE_OPERATORS_FOR_FLAGS(QSGShaderEffectNode::DirtyShaderFlags)
354
355#ifndef QT_NO_DEBUG_STREAM
356Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug debug, const QSGShaderEffectNode::VariableData &vd);
357#endif
358
359class Q_QUICK_PRIVATE_EXPORT QSGGlyphNode : public QSGVisitableNode
360{
361public:
362 enum AntialiasingMode
363 {
364 DefaultAntialiasing = -1,
365 GrayAntialiasing,
366 LowQualitySubPixelAntialiasing,
367 HighQualitySubPixelAntialiasing
368 };
369
370 QSGGlyphNode() {}
371 ~QSGGlyphNode() override;
372
373 virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) = 0;
374 virtual void setColor(const QColor &color) = 0;
375 virtual void setStyle(QQuickText::TextStyle style) = 0;
376 virtual void setStyleColor(const QColor &color) = 0;
377 virtual QPointF baseLine() const = 0;
378
379 virtual QRectF boundingRect() const { return m_bounding_rect; }
380 virtual void setBoundingRect(const QRectF &bounds) { m_bounding_rect = bounds; }
381
382 virtual void setPreferredAntialiasingMode(AntialiasingMode) = 0;
383 virtual void setRenderTypeQuality(int renderTypeQuality) { Q_UNUSED(renderTypeQuality) }
384
385 virtual void update() = 0;
386
387 void setOwnerElement(QQuickItem *ownerElement) { m_ownerElement = ownerElement; }
388 QQuickItem *ownerElement() const { return m_ownerElement; }
389
390 void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(node: this); visitor->endVisit(this); }
391protected:
392 QRectF m_bounding_rect;
393 QQuickItem *m_ownerElement = nullptr;
394};
395
396class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphConsumer
397{
398public:
399 virtual ~QSGDistanceFieldGlyphConsumer();
400
401 virtual void invalidateGlyphs(const QVector<quint32> &glyphs) = 0;
402 QIntrusiveListNode node;
403};
404typedef QIntrusiveList<QSGDistanceFieldGlyphConsumer, &QSGDistanceFieldGlyphConsumer::node> QSGDistanceFieldGlyphConsumerList;
405
406class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphCache
407{
408public:
409 QSGDistanceFieldGlyphCache(const QRawFont &font,
410 int renderTypeQuality);
411 virtual ~QSGDistanceFieldGlyphCache();
412
413 struct Metrics {
414 qreal width;
415 qreal height;
416 qreal baselineX;
417 qreal baselineY;
418
419 bool isNull() const { return width == 0 || height == 0; }
420 };
421
422 struct TexCoord {
423 qreal x = 0;
424 qreal y = 0;
425 qreal width = -1;
426 qreal height = -1;
427 qreal xMargin = 0;
428 qreal yMargin = 0;
429
430 TexCoord() {}
431
432 bool isNull() const { return width <= 0 || height <= 0; }
433 bool isValid() const { return width >= 0 && height >= 0; }
434 };
435
436 struct Texture {
437 QRhiTexture *texture = nullptr;
438 QSize size;
439
440 bool operator == (const Texture &other) const {
441 return texture == other.texture;
442 }
443 };
444
445 const QRawFont &referenceFont() const { return m_referenceFont; }
446
447 qreal fontScale(qreal pixelSize) const
448 {
449 return pixelSize / baseFontSize();
450 }
451 qreal distanceFieldRadius() const
452 {
453 return QT_DISTANCEFIELD_RADIUS(narrowOutlineFont: m_doubleGlyphResolution) / qreal(QT_DISTANCEFIELD_SCALE(narrowOutlineFont: m_doubleGlyphResolution));
454 }
455 int glyphCount() const { return m_glyphCount; }
456 bool doubleGlyphResolution() const { return m_doubleGlyphResolution; }
457 int renderTypeQuality() const { return m_renderTypeQuality; }
458
459 Metrics glyphMetrics(glyph_t glyph, qreal pixelSize);
460 inline TexCoord glyphTexCoord(glyph_t glyph);
461 inline const Texture *glyphTexture(glyph_t glyph);
462
463 void populate(const QVector<glyph_t> &glyphs);
464 void release(const QVector<glyph_t> &glyphs);
465
466 void update();
467
468 void registerGlyphNode(QSGDistanceFieldGlyphConsumer *node) { m_registeredNodes.insert(n: node); }
469 void unregisterGlyphNode(QSGDistanceFieldGlyphConsumer *node) { m_registeredNodes.remove(n: node); }
470
471 virtual void registerOwnerElement(QQuickItem *ownerElement);
472 virtual void unregisterOwnerElement(QQuickItem *ownerElement);
473 virtual void processPendingGlyphs();
474
475 virtual bool eightBitFormatIsAlphaSwizzled() const = 0;
476 virtual bool screenSpaceDerivativesSupported() const = 0;
477 virtual bool isActive() const;
478
479protected:
480 struct GlyphPosition {
481 glyph_t glyph;
482 QPointF position;
483 };
484
485 struct GlyphData {
486 Texture *texture = nullptr;
487 TexCoord texCoord;
488 QRectF boundingRect;
489 QPainterPath path;
490 quint32 ref = 0;
491
492 GlyphData() {}
493 };
494
495 virtual void requestGlyphs(const QSet<glyph_t> &glyphs) = 0;
496 virtual void storeGlyphs(const QList<QDistanceField> &glyphs) = 0;
497 virtual void referenceGlyphs(const QSet<glyph_t> &glyphs) = 0;
498 virtual void releaseGlyphs(const QSet<glyph_t> &glyphs) = 0;
499
500 void setGlyphsPosition(const QList<GlyphPosition> &glyphs);
501 void setGlyphsTexture(const QVector<glyph_t> &glyphs, const Texture &tex);
502 void markGlyphsToRender(const QVector<glyph_t> &glyphs);
503 inline void removeGlyph(glyph_t glyph);
504
505 void updateRhiTexture(QRhiTexture *oldTex, QRhiTexture *newTex, const QSize &newTexSize);
506
507 inline bool containsGlyph(glyph_t glyph);
508
509 GlyphData &glyphData(glyph_t glyph);
510 GlyphData &emptyData(glyph_t glyph);
511
512 int baseFontSize() const;
513
514#if defined(QSG_DISTANCEFIELD_CACHE_DEBUG)
515 virtual void saveTexture(QRhiTexture *texture, const QString &nameBase) const = 0;
516#endif
517
518 bool m_doubleGlyphResolution;
519 int m_renderTypeQuality;
520
521protected:
522 QRawFont m_referenceFont;
523
524private:
525 int m_glyphCount;
526 QList<Texture> m_textures;
527 QHash<glyph_t, GlyphData> m_glyphsData;
528 QDataBuffer<glyph_t> m_pendingGlyphs;
529 QSet<glyph_t> m_populatingGlyphs;
530 QSGDistanceFieldGlyphConsumerList m_registeredNodes;
531
532 static Texture s_emptyTexture;
533};
534
535inline QSGDistanceFieldGlyphCache::TexCoord QSGDistanceFieldGlyphCache::glyphTexCoord(glyph_t glyph)
536{
537 return glyphData(glyph).texCoord;
538}
539
540inline const QSGDistanceFieldGlyphCache::Texture *QSGDistanceFieldGlyphCache::glyphTexture(glyph_t glyph)
541{
542 return glyphData(glyph).texture;
543}
544
545inline void QSGDistanceFieldGlyphCache::removeGlyph(glyph_t glyph)
546{
547 GlyphData &gd = glyphData(glyph);
548 gd.texCoord = TexCoord();
549 gd.texture = &s_emptyTexture;
550}
551
552inline bool QSGDistanceFieldGlyphCache::containsGlyph(glyph_t glyph)
553{
554 return glyphData(glyph).texCoord.isValid();
555}
556
557QT_END_NAMESPACE
558
559Q_DECLARE_METATYPE(QSGGuiThreadShaderEffectManager::ShaderInfo::Type)
560
561#endif
562

source code of qtdeclarative/src/quick/scenegraph/qsgadaptationlayer_p.h