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

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