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