Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
53
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);
72 gd.path = m_referenceFont.pathForGlyph(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
97void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
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
131void QSGDistanceFieldGlyphCache::release(const QVector<glyph_t> &glyphs)
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)
160 qsg_render_timer.start();
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()) {
195 quint64 now = qsg_render_timer.elapsed();
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
209void QSGDistanceFieldGlyphCache::setGlyphsPosition(const QList<GlyphPosition> &glyphs)
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();
225 gd.texCoord.width = gd.boundingRect.width();
226 gd.texCoord.height = gd.boundingRect.height();
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 /* Intentionally empty */
239}
240
241void QSGDistanceFieldGlyphCache::setGlyphsTexture(const QVector<glyph_t> &glyphs, const Texture &tex)
242{
243 int i = m_textures.indexOf(tex);
244 if (i == -1) {
245 m_textures.append(tex);
246 i = m_textures.size() - 1;
247 } else {
248 m_textures[i].size = tex.size;
249 }
250 Texture *texture = &(m_textures[i]);
251
252 QVector<quint32> invalidatedGlyphs;
253
254 int count = glyphs.size();
255 for (int j = 0; j < count; ++j) {
256 glyph_t glyphIndex = glyphs.at(j);
257 GlyphData &gd = glyphData(glyphIndex);
258 if (gd.texture != &s_emptyTexture)
259 invalidatedGlyphs.append(glyphIndex);
260 gd.texture = texture;
261 }
262
263 if (!invalidatedGlyphs.isEmpty()) {
264 for (QSGDistanceFieldGlyphConsumerList::iterator iter = m_registeredNodes.begin(); iter != m_registeredNodes.end(); ++iter) {
265 iter->invalidateGlyphs(invalidatedGlyphs);
266 }
267 }
268}
269
270void QSGDistanceFieldGlyphCache::markGlyphsToRender(const QVector<glyph_t> &glyphs)
271{
272 int count = glyphs.size();
273 for (int i = 0; i < count; ++i)
274 m_pendingGlyphs.add(glyphs.at(i));
275}
276
278{
279 int count = m_textures.size();
280 for (int i = 0; i < count; ++i) {
281 Texture &tex = m_textures[i];
282 if (tex.texture == oldTex) {
283 tex.texture = newTex;
284 tex.size = newTexSize;
285 return;
286 }
287 }
288}
289
291 = default;
292
294{
295 for (QSGNode *child = node->firstChild(); child; child = child->nextSibling()) {
296 switch (child->type()) {
298 QSGClipNode *c = static_cast<QSGClipNode*>(child);
299 if (visit(c))
301 endVisit(c);
302 break;
303 }
305 QSGTransformNode *c = static_cast<QSGTransformNode*>(child);
306 if (visit(c))
308 endVisit(c);
309 break;
310 }
312 QSGOpacityNode *c = static_cast<QSGOpacityNode*>(child);
313 if (visit(c))
315 endVisit(c);
316 break;
317 }
319 if (child->flags() & QSGNode::IsVisitableNode) {
320 QSGVisitableNode *v = static_cast<QSGVisitableNode*>(child);
321 v->accept(this);
322 } else {
323 QSGGeometryNode *c = static_cast<QSGGeometryNode*>(child);
324 if (visit(c))
326 endVisit(c);
327 }
328 break;
329 }
331 QSGRootNode *root = static_cast<QSGRootNode*>(child);
332 if (visit(root))
333 visitChildren(root);
334 endVisit(root);
335 break;
336 }
339 break;
340 }
342 QSGRenderNode *r = static_cast<QSGRenderNode*>(child);
343 if (visit(r))
345 endVisit(r);
346 break;
347 }
348 default:
349 Q_UNREACHABLE();
350 break;
351 }
352 }
353}
354
356 = default;
357
359 = default;
360
362 = default;
363
365 = default;
366
367#ifndef QT_NO_DEBUG_STREAM
369{
370 QDebugStateSaver saver(debug);
371 debug.space();
372 debug << v.name;
373 switch (v.type) {
375 debug << "cvar" << "offset" << v.offset << "size" << v.size;
376 break;
378 debug << "sampler" << "bindpoint" << v.bindPoint;
379 break;
381 debug << "texture" << "bindpoint" << v.bindPoint;
382 break;
383 default:
384 break;
385 }
386 return debug;
387}
388
390{
391 QDebugStateSaver saver(debug);
392 debug.space();
393 debug << vd.specialType;
394 return debug;
395}
396#endif
397
405
407 = default;
408
409#if QT_CONFIG(quick_sprite)
410
411QSGSpriteNode::~QSGSpriteNode()
412 = default;
413
414#endif
415
417 = default;
418
420 = default;
421
423 = default;
424
426 = default;
427
429
430#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
void setPixelSize(int)
Sets the font size to pixelSize pixels, with a maxiumum size of an unsigned 16-bit integer.
Definition qfont.cpp:1049
\inmodule QtCore
Definition qhash.h:1103
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.
\inmodule QtGui
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
static QRawFontPrivate * get(const QRawFont &font)
Definition qrawfont_p.h:104
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
\inmodule QtGui
Definition qrhi.h:895
The QSGClipNode class implements the clipping functionality in the scene graph.
Definition qsgnode.h:221
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 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:188
~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:276
~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:259
~QSGShaderEffectNode() override
The QSGTransformNode class implements transformations in the scene graph.
Definition qsgnode.h:241
~QSGVisitableNode() override
virtual void accept(QSGNodeVisitorEx *)=0
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:166
#define qCDebug(category,...)
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLboolean r
[2]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint texture
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_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:61
long long qint64
Definition qtypes.h:60
double qreal
Definition qtypes.h:187
QLayoutItem * child
[0]