Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qsgadaptationlayer.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 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
5
6#include <qmath.h>
7#include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
8#include <QtQuick/private/qsgcontext_p.h>
9#include <private/qrawfont_p.h>
10#include <QtGui/qguiapplication.h>
11#include <qdir.h>
12#include <qsgrendernode.h>
13
14#include <private/qquickprofiler_p.h>
15#include <QElapsedTimer>
16
17#include <qtquick_tracepoints_p.h>
18
20
21Q_TRACE_POINT(qtquick, QSGDistanceFieldGlyphCache_update_entry, int count)
22Q_TRACE_POINT(qtquick, QSGDistanceFieldGlyphCache_update_exit)
23Q_TRACE_POINT(qtquick, QSGDistanceFieldGlyphCache_glyphRender_entry)
24Q_TRACE_POINT(qtquick, QSGDistanceFieldGlyphCache_glyphRender_exit)
25Q_TRACE_POINT(qtquick, QSGDistanceFieldGlyphCache_glyphStore_entry)
26Q_TRACE_POINT(qtquick, QSGDistanceFieldGlyphCache_glyphStore_exit)
27
29
31
33 : m_renderTypeQuality(renderTypeQuality)
34 , m_pendingGlyphs(64)
35{
36 Q_ASSERT(font.isValid());
37
39 m_glyphCount = fontD->fontEngine->glyphCount();
40
41 m_doubleGlyphResolution = qt_fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT();
42
43 m_referenceFont = font;
44 // we set the same pixel size as used by the distance field internally.
45 // this allows us to call pathForGlyph once and reuse the result.
46 m_referenceFont.setPixelSize(baseFontSize() * QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution));
47 Q_ASSERT(m_referenceFont.isValid());
48}
49
51{
52}
53
55{
57}
58
60{
61 GlyphData gd;
62 gd.texture = &s_emptyTexture;
63 QHash<glyph_t, GlyphData>::iterator it = m_glyphsData.insert(glyph, gd);
64 return it.value();
65}
66
68{
69 QHash<glyph_t, GlyphData>::iterator data = m_glyphsData.find(glyph);
70 if (data == m_glyphsData.end()) {
71 GlyphData &gd = emptyData(glyph);
73 // need bounding rect in base font size scale
75 QTransform scaleDown;
76 scaleDown.scale(scaleFactor, scaleFactor);
77 gd.boundingRect = scaleDown.mapRect(gd.path.boundingRect());
78 return gd;
79 }
80 return data.value();
81}
82
84{
85 GlyphData &gd = glyphData(glyph);
86 qreal scale = fontScale(pixelSize);
87
88 Metrics m;
89 m.width = gd.boundingRect.width() * scale;
90 m.height = gd.boundingRect.height() * scale;
91 m.baselineX = gd.boundingRect.x() * scale;
92 m.baselineY = -gd.boundingRect.y() * scale;
93
94 return m;
95}
96
98{
99 QSet<glyph_t> referencedGlyphs;
100 QSet<glyph_t> newGlyphs;
101 int count = glyphs.size();
102 for (int i = 0; i < count; ++i) {
103 glyph_t glyphIndex = glyphs.at(i);
104 if ((int) glyphIndex >= glyphCount() && glyphCount() > 0) {
105 qWarning("Warning: distance-field glyph is not available with index %d", glyphIndex);
106 continue;
107 }
108
109 GlyphData &gd = glyphData(glyphIndex);
110 ++gd.ref;
111 referencedGlyphs.insert(glyphIndex);
112
113 if (gd.texCoord.isValid() || m_populatingGlyphs.contains(glyphIndex))
114 continue;
115
116 m_populatingGlyphs.insert(glyphIndex);
117
118 if (gd.boundingRect.isEmpty()) {
119 gd.texCoord.width = 0;
120 gd.texCoord.height = 0;
121 } else {
122 newGlyphs.insert(glyphIndex);
123 }
124 }
125
126 referenceGlyphs(referencedGlyphs);
127 if (!newGlyphs.isEmpty())
128 requestGlyphs(newGlyphs);
129}
130
132{
133 QSet<glyph_t> unusedGlyphs;
134 int count = glyphs.size();
135 for (int i = 0; i < count; ++i) {
136 glyph_t glyphIndex = glyphs.at(i);
137 GlyphData &gd = glyphData(glyphIndex);
138 if (--gd.ref == 0 && !gd.texCoord.isNull())
139 unusedGlyphs.insert(glyphIndex);
140 }
141 releaseGlyphs(unusedGlyphs);
142}
143
145{
146 return true;
147}
148
150{
151 m_populatingGlyphs.clear();
152
153 if (m_pendingGlyphs.isEmpty())
154 return;
155
156 Q_TRACE_SCOPE(QSGDistanceFieldGlyphCache_update, m_pendingGlyphs.size());
157
158 bool profileFrames = QSG_LOG_TIME_GLYPH().isDebugEnabled();
159 if (profileFrames)
161 Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphAdaptationLayerFrame);
162 Q_TRACE(QSGDistanceFieldGlyphCache_glyphRender_entry);
163
164 QList<QDistanceField> distanceFields;
165 const int pendingGlyphsSize = m_pendingGlyphs.size();
166 distanceFields.reserve(pendingGlyphsSize);
167 for (int i = 0; i < pendingGlyphsSize; ++i) {
168 GlyphData &gd = glyphData(m_pendingGlyphs.at(i));
169 distanceFields.append(QDistanceField(gd.path,
170 m_pendingGlyphs.at(i),
172 gd.path = QPainterPath(); // no longer needed, so release memory used by the painter path
173 }
174
175 qint64 renderTime = 0;
176 int count = m_pendingGlyphs.size();
177 if (profileFrames)
178 renderTime = qsg_render_timer.nsecsElapsed();
179
180 Q_TRACE(QSGDistanceFieldGlyphCache_glyphRender_exit);
181 Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphAdaptationLayerFrame,
182 QQuickProfiler::SceneGraphAdaptationLayerGlyphRender);
183 Q_TRACE(QSGDistanceFieldGlyphCache_glyphStore_entry);
184
185 m_pendingGlyphs.reset();
186
187 storeGlyphs(distanceFields);
188
189#if defined(QSG_DISTANCEFIELD_CACHE_DEBUG)
190 for (Texture texture : std::as_const(m_textures))
191 saveTexture(texture.texture, m_referenceFont.familyName());
192#endif
193
194 if (QSG_LOG_TIME_GLYPH().isDebugEnabled()) {
196 qCDebug(QSG_LOG_TIME_GLYPH,
197 "distancefield: %d glyphs prepared in %dms, rendering=%d, upload=%d",
198 count,
199 (int) now,
200 int(renderTime / 1000000),
201 int((now - (renderTime / 1000000))));
202 }
203 Q_TRACE(QSGDistanceFieldGlyphCache_glyphStore_exit);
204 Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(QQuickProfiler::SceneGraphAdaptationLayerFrame,
205 QQuickProfiler::SceneGraphAdaptationLayerGlyphStore,
206 (qint64)count);
207}
208
210{
211 QVector<quint32> invalidatedGlyphs;
212
213 int count = glyphs.size();
214 for (int i = 0; i < count; ++i) {
215 GlyphPosition glyph = glyphs.at(i);
216 GlyphData &gd = glyphData(glyph.glyph);
217
218 if (!gd.texCoord.isNull())
219 invalidatedGlyphs.append(glyph.glyph);
220
223 gd.texCoord.x = glyph.position.x();
224 gd.texCoord.y = glyph.position.y();
227 }
228
229 if (!invalidatedGlyphs.isEmpty()) {
230 for (QSGDistanceFieldGlyphConsumerList::iterator iter = m_registeredNodes.begin(); iter != m_registeredNodes.end(); ++iter) {
231 iter->invalidateGlyphs(invalidatedGlyphs);
232 }
233 }
234}
235
237{
238 Q_UNUSED(ownerElement);
239}
240
242{
243 Q_UNUSED(ownerElement);
244}
245
247{
248 /* Intentionally empty */
249}
250
252{
253 int i = m_textures.indexOf(tex);
254 if (i == -1) {
255 m_textures.append(tex);
256 i = m_textures.size() - 1;
257 } else {
258 m_textures[i].size = tex.size;
259 }
260 Texture *texture = &(m_textures[i]);
261
262 QVector<quint32> invalidatedGlyphs;
263
264 int count = glyphs.size();
265 for (int j = 0; j < count; ++j) {
266 glyph_t glyphIndex = glyphs.at(j);
267 GlyphData &gd = glyphData(glyphIndex);
268 if (gd.texture != &s_emptyTexture)
269 invalidatedGlyphs.append(glyphIndex);
270 gd.texture = texture;
271 }
272
273 if (!invalidatedGlyphs.isEmpty()) {
274 for (QSGDistanceFieldGlyphConsumerList::iterator iter = m_registeredNodes.begin(); iter != m_registeredNodes.end(); ++iter) {
275 iter->invalidateGlyphs(invalidatedGlyphs);
276 }
277 }
278}
279
281{
282 int count = glyphs.size();
283 for (int i = 0; i < count; ++i)
284 m_pendingGlyphs.add(glyphs.at(i));
285}
286
288{
289 int count = m_textures.size();
290 for (int i = 0; i < count; ++i) {
291 Texture &tex = m_textures[i];
292 if (tex.texture == oldTex) {
293 tex.texture = newTex;
294 tex.size = newTexSize;
295 return;
296 }
297 }
298}
299
301 = default;
302
304{
305 for (QSGNode *child = node->firstChild(); child; child = child->nextSibling()) {
306 switch (child->type()) {
308 QSGClipNode *c = static_cast<QSGClipNode*>(child);
309 if (visit(c))
311 endVisit(c);
312 break;
313 }
315 QSGTransformNode *c = static_cast<QSGTransformNode*>(child);
316 if (visit(c))
318 endVisit(c);
319 break;
320 }
322 QSGOpacityNode *c = static_cast<QSGOpacityNode*>(child);
323 if (visit(c))
325 endVisit(c);
326 break;
327 }
329 if (child->flags() & QSGNode::IsVisitableNode) {
330 QSGVisitableNode *v = static_cast<QSGVisitableNode*>(child);
331 v->accept(this);
332 } else {
333 QSGGeometryNode *c = static_cast<QSGGeometryNode*>(child);
334 if (visit(c))
336 endVisit(c);
337 }
338 break;
339 }
341 QSGRootNode *root = static_cast<QSGRootNode*>(child);
342 if (visit(root))
343 visitChildren(root);
344 endVisit(root);
345 break;
346 }
349 break;
350 }
352 QSGRenderNode *r = static_cast<QSGRenderNode*>(child);
353 if (visit(r))
355 endVisit(r);
356 break;
357 }
358 default:
359 Q_UNREACHABLE();
360 break;
361 }
362 }
363}
364
366 = default;
367
369 = default;
370
372 = default;
373
375 = default;
376
377#ifndef QT_NO_DEBUG_STREAM
379{
380 QDebugStateSaver saver(debug);
381 debug.space();
382 debug << v.name;
383 switch (v.type) {
385 debug << "cvar" << "offset" << v.offset << "size" << v.size;
386 break;
388 debug << "sampler" << "bindpoint" << v.bindPoint;
389 break;
391 debug << "texture" << "bindpoint" << v.bindPoint;
392 break;
393 default:
394 break;
395 }
396 return debug;
397}
398
400{
401 QDebugStateSaver saver(debug);
402 debug.space();
403 debug << vd.specialType;
404 return debug;
405}
406#endif
407
413{
414}
415
417 = default;
418
419#if QT_CONFIG(quick_sprite)
420
421QSGSpriteNode::~QSGSpriteNode()
422 = default;
423
424#endif
425
427 = default;
428
430 = default;
431
433 = default;
434
436 = default;
437
439
440#include "moc_qsgadaptationlayer_p.cpp"
void add(const Type &t)
Type & at(qsizetype i)
qsizetype size() const
bool isEmpty() const
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
qint64 elapsed() const noexcept
Returns the number of milliseconds since this QElapsedTimer was last started.
void start() noexcept
Starts this timer.
qint64 nsecsElapsed() const noexcept
virtual int glyphCount() const
void setPixelSize(int)
Sets the font size to pixelSize pixels, with a maxiumum size of an unsigned 16-bit integer.
Definition qfont.cpp:1034
\inmodule QtCore
Definition qhash.h:1093
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list.
iterator begin()
Returns an STL-style interator pointing to the first item in the list.
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtGui
QRectF boundingRect() const
Returns the bounding rectangle of this painter path as a rectangle with floating point precision.
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:333
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:338
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
static QRawFontPrivate * get(const QRawFont &font)
Definition qrawfont_p.h:104
QFontEngine * fontEngine
Definition qrawfont_p.h:106
The QRawFont class provides access to a single physical instance of a font.
Definition qrawfont.h:24
QString familyName() const
Returns the family name of this QRawFont.
Definition qrawfont.cpp:441
QPainterPath pathForGlyph(quint32 glyphIndex) const
This function returns the shape of the glyph at a given glyphIndex in the underlying font if the QRaw...
Definition qrawfont.cpp:264
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
Definition qrect.h:647
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:658
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:718
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:715
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:655
\inmodule QtGui
Definition qrhi.h:883
The QSGClipNode class implements the clipping functionality in the scene graph.
Definition qsgnode.h:224
virtual void registerOwnerElement(QQuickItem *ownerElement)
Metrics glyphMetrics(glyph_t glyph, qreal pixelSize)
qreal fontScale(qreal pixelSize) const
void markGlyphsToRender(const QVector< glyph_t > &glyphs)
GlyphData & emptyData(glyph_t glyph)
void setGlyphsTexture(const QVector< glyph_t > &glyphs, const Texture &tex)
void populate(const QVector< glyph_t > &glyphs)
void setGlyphsPosition(const QList< GlyphPosition > &glyphs)
virtual void releaseGlyphs(const QSet< glyph_t > &glyphs)=0
void release(const QVector< glyph_t > &glyphs)
virtual void unregisterOwnerElement(QQuickItem *ownerElement)
virtual void storeGlyphs(const QList< QDistanceField > &glyphs)=0
void updateRhiTexture(QRhiTexture *oldTex, QRhiTexture *newTex, const QSize &newTexSize)
GlyphData & glyphData(glyph_t glyph)
virtual void referenceGlyphs(const QSet< glyph_t > &glyphs)=0
virtual void requestGlyphs(const QSet< glyph_t > &glyphs)=0
The QSGDynamicTexture class serves as a baseclass for dynamically changing textures,...
Definition qsgtexture.h:100
The QSGGeometryNode class is used for all rendered content in the scene graph.
Definition qsgnode.h:191
~QSGGlyphNode() override
~QSGInternalImageNode() override
~QSGInternalRectangleNode() override
QSGLayer(QSGTexturePrivate &dd)
~QSGLayer() override
virtual ~QSGNodeVisitorEx()
virtual void endVisit(QSGTransformNode *)=0
void visitChildren(QSGNode *node)
virtual bool visit(QSGTransformNode *)=0
\group qtquick-scenegraph-nodes \title Qt Quick Scene Graph Node classes
Definition qsgnode.h:37
@ IsVisitableNode
Definition qsgnode.h:62
@ BasicNodeType
Definition qsgnode.h:40
@ TransformNodeType
Definition qsgnode.h:42
@ RootNodeType
Definition qsgnode.h:45
@ GeometryNodeType
Definition qsgnode.h:41
@ RenderNodeType
Definition qsgnode.h:46
@ ClipNodeType
Definition qsgnode.h:43
@ OpacityNodeType
Definition qsgnode.h:44
QSGNode * firstChild() const
Returns the first child of this node.
Definition qsgnode.h:105
The QSGOpacityNode class is used to change opacity of nodes.
Definition qsgnode.h:279
~QSGPainterNode() override
The QSGRenderNode class represents a set of custom rendering commands targeting the graphics API that...
The QSGRootNode is the toplevel root of any scene graph.
Definition qsgnode.h:262
~QSGShaderEffectNode() override
The QSGTransformNode class implements transformations in the scene graph.
Definition qsgnode.h:244
~QSGVisitableNode() override
virtual void accept(QSGNodeVisitorEx *)=0
Definition qset.h:18
bool isEmpty() const
Definition qset.h:52
void clear()
Definition qset.h:61
bool contains(const T &value) const
Definition qset.h:71
iterator insert(const T &value)
Definition qset.h:155
\inmodule QtCore
Definition qsize.h:25
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
QTransform & scale(qreal sx, qreal sy)
Scales the coordinate system by sx horizontally and sy vertically, and returns a reference to the mat...
QRect mapRect(const QRect &) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
QSet< QString >::iterator it
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
int QT_DISTANCEFIELD_HIGHGLYPHCOUNT()
bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine)
int QT_DISTANCEFIELD_RADIUS(bool narrowOutlineFont)
int QT_DISTANCEFIELD_SCALE(bool narrowOutlineFont)
int QT_DISTANCEFIELD_BASEFONTSIZE(bool narrowOutlineFont)
#define qWarning
Definition qlogging.h:162
#define qCDebug(category,...)
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLboolean r
[2]
GLenum GLenum GLsizei count
GLenum GLuint texture
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
const GLubyte * c
GLenum GLenum GLenum GLenum GLenum scale
#define Q_QUICK_SG_PROFILE_RECORD(Type, position)
#define Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(Type, position, Payload)
#define Q_QUICK_SG_PROFILE_START(Type)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QDebug operator<<(QDebug debug, const QSGGuiThreadShaderEffectManager::ShaderInfo::Variable &v)
static QT_BEGIN_NAMESPACE QElapsedTimer qsg_render_timer
unsigned int glyph_t
#define Q_UNUSED(x)
#define Q_TRACE_SCOPE(x,...)
Definition qtrace_p.h:146
#define Q_TRACE(x,...)
Definition qtrace_p.h:144
#define Q_TRACE_POINT(provider, tracepoint,...)
Definition qtrace_p.h:232
unsigned long long quint64
Definition qtypes.h:56
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
QLayoutItem * child
[0]