Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qsgdistancefieldglyphnode_p.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 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
6#include <QtGui/qsurface.h>
7#include <QtGui/qwindow.h>
8#include <qmath.h>
9
11
12static float qt_sg_envFloat(const char *name, float defaultValue)
13{
15 return defaultValue;
16 bool ok = false;
17 const float value = qgetenv(name).toFloat(&ok);
18 return ok ? value : defaultValue;
19}
20
21static float thresholdFunc(float glyphScale)
22{
23 static const float base = qt_sg_envFloat("QT_DF_BASE", 0.5f);
24 static const float baseDev = qt_sg_envFloat("QT_DF_BASEDEVIATION", 0.065f);
25 static const float devScaleMin = qt_sg_envFloat("QT_DF_SCALEFORMAXDEV", 0.15f);
26 static const float devScaleMax = qt_sg_envFloat("QT_DF_SCALEFORNODEV", 0.3f);
27 return base - ((qBound(devScaleMin, glyphScale, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev);
28}
29
30static float spreadFunc(float glyphScale)
31{
32 static const float range = qt_sg_envFloat("QT_DF_RANGE", 0.06f);
33 return range / glyphScale;
34}
35
37{
38public:
40
42 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
43
45 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
46
47protected:
48 float m_fontScale = 1.0;
49 float m_matrixScale = 1.0;
50};
51
53{
55 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"));
56
57 if (alphaTexture)
59 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a.frag.qsb"));
60 else
62 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.frag.qsb"));
63}
64
66 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
67{
68 Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type());
69 QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial);
70 QSGDistanceFieldTextMaterial *oldMat = static_cast<QSGDistanceFieldTextMaterial *>(oldMaterial);
71
72 // updateUniformData() is called before updateSampledImage() by the
73 // renderer. Hence updating the glyph cache stuff here.
74 const bool textureUpdated = mat->updateTextureSizeAndWrapper();
76 Q_ASSERT(oldMat == nullptr || oldMat->texture());
77
78 bool changed = false;
79 QByteArray *buf = state.uniformData();
80 Q_ASSERT(buf->size() >= 104);
81
82 bool updateRange = false;
83 if (!oldMat || mat->fontScale() != oldMat->fontScale()) {
84 m_fontScale = mat->fontScale();
85 updateRange = true;
86 }
87 if (state.isMatrixDirty()) {
88 const QMatrix4x4 m = state.combinedMatrix();
89 memcpy(buf->data(), m.constData(), 64);
90 changed = true;
91 m_matrixScale = qSqrt(qAbs(state.determinant())) * state.devicePixelRatio();
92 updateRange = true;
93 }
94 if (textureUpdated || !oldMat || oldMat->texture()->texture != mat->texture()->texture) {
95 const QVector2D ts(1.0f / mat->textureSize().width(), 1.0f / mat->textureSize().height());
96 Q_ASSERT(sizeof(ts) == 8);
97 memcpy(buf->data() + 64, &ts, 8);
98 changed = true;
99 }
100 if (!oldMat || mat->color() != oldMat->color() || state.isOpacityDirty()) {
101 const QVector4D color = mat->color() * state.opacity();
102 Q_ASSERT(sizeof(color) == 16);
103 memcpy(buf->data() + 80, &color, 16);
104 changed = true;
105 }
106 if (updateRange) { // deferred because depends on m_fontScale and m_matrixScale
107 const float combinedScale = m_fontScale * m_matrixScale;
108 const float base = thresholdFunc(combinedScale);
109 const float range = spreadFunc(combinedScale);
110 const QVector2D alphaMinMax(qMax(0.0f, base - range), qMin(base + range, 1.0f));
111 memcpy(buf->data() + 96, &alphaMinMax, 8);
112 changed = true;
113 }
114
115 // move texture uploads/copies onto the renderer's soon-to-be-committed list
116 static_cast<QSGRhiDistanceFieldGlyphCache *>(mat->glyphCache())->commitResourceUpdates(state.resourceUpdateBatch());
117
118 return changed;
119}
120
122 QSGMaterial *newMaterial, QSGMaterial *)
123{
125 if (binding != 1)
126 return;
127
128 QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial);
129 QSGTexture *t = mat->wrapperTexture();
131 *texture = t;
132}
133
135{
136public:
138};
139
142{
144 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"));
145 if (alphaTexture)
147 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag.qsb"));
148 else
150 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_fwidth.frag.qsb"));
151}
152
154 : m_glyph_cache(nullptr)
155 , m_texture(nullptr)
156 , m_fontScale(1.0)
157 , m_sgTexture(nullptr)
158{
160}
161
163{
164 delete m_sgTexture;
165}
166
168{
169 static QSGMaterialType type;
170 return &type;
171}
172
174{
175 float r, g, b, a;
176 color.getRgbF(&r, &g, &b, &a);
177 m_color = QVector4D(r * a, g * a, b * a, a);
178}
179
181{
184 else
186}
187
189{
190 if (!m_texture)
191 m_texture = m_glyph_cache->glyphTexture(0); // invalid texture
192
193 if (m_texture->size != m_size) {
195 return true;
196 }
197
198 return false;
199}
200
201// When using the RHI we need a QSGTexture wrapping the QRhiTexture, just
202// exposing a QRhiTexture * (which would be the equivalent of GLuint textureId)
203// is not sufficient to play nice with the material.
205{
206 bool updated = updateTextureSize();
207 if (updated) {
208 if (m_sgTexture)
209 delete m_sgTexture;
214 }
215 return updated;
216}
217
219{
220 Q_ASSERT(o && type() == o->type());
222 if (m_glyph_cache != other->m_glyph_cache)
223 return m_glyph_cache - other->m_glyph_cache;
224 if (m_fontScale != other->m_fontScale) {
225 return int(other->m_fontScale < m_fontScale) - int(m_fontScale < other->m_fontScale);
226 }
227 if (m_color != other->m_color)
228 return &m_color < &other->m_color ? -1 : 1;
230 qintptr t1 = other->m_texture ? qintptr(other->m_texture->texture) : 0;
231 const qintptr diff = t0 - t1;
232 return diff < 0 ? -1 : (diff > 0 ? 1 : 0);
233}
235{
236public:
238
239 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
240};
241
244{
245}
246
248 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
249{
250 bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
253
254 QByteArray *buf = state.uniformData();
255 Q_ASSERT(buf->size() >= 128);
256
257 if (!oldMat || mat->styleColor() != oldMat->styleColor() || state.isOpacityDirty()) {
258 QVector4D styleColor = mat->styleColor();
259 styleColor *= state.opacity();
260 memcpy(buf->data() + 112, &styleColor, 16);
261 changed = true;
262 }
263
264 return changed;
265}
266
269{
270}
271
273{
274}
275
277{
278 float r, g, b, a;
279 color.getRgbF(&r, &g, &b, &a);
280 m_styleColor = QVector4D(r * a, g * a, b * a, a);
281}
282
284{
285 Q_ASSERT(o && type() == o->type());
287 if (m_styleColor != other->m_styleColor)
288 return &m_styleColor < &other->m_styleColor ? -1 : 1;
290}
291
293{
294public:
296
297 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
298};
299
302{
304 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"));
305
306 if (alphaTexture)
308 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag.qsb"));
309 else
311 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsb"));
312}
313
315{
316public:
318};
319
322{
324 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"));
325 if (alphaTexture)
327 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag.qsb"));
328 else
330 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag.qsb"));
331}
332
334 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
335{
336 bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
339
340 QByteArray *buf = state.uniformData();
341 Q_ASSERT(buf->size() >= 136);
342
343 if (!oldMat || mat->fontScale() != oldMat->fontScale() || state.isMatrixDirty()) {
344 float dfRadius = mat->glyphCache()->distanceFieldRadius();
345 float combinedScale = m_fontScale * m_matrixScale;
346 float base = thresholdFunc(combinedScale);
347 float range = spreadFunc(combinedScale);
348 float outlineLimit = qMax(0.2f, base - 0.5f / dfRadius / m_fontScale);
349 float alphaMin = qMax(0.0f, base - range);
350 float styleAlphaMin0 = qMax(0.0f, outlineLimit - range);
351 float styleAlphaMin1 = qMin(outlineLimit + range, alphaMin);
352 memcpy(buf->data() + 128, &styleAlphaMin0, 4);
353 memcpy(buf->data() + 132, &styleAlphaMin1, 4);
354 changed = true;
355 }
356
357 return changed;
358}
359
362{
363}
364
366{
367}
368
370{
371 static QSGMaterialType type;
372 return &type;
373}
374
376{
379 else
381}
382
384{
385public:
387
388 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
389};
390
393{
395 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"));
396 if (alphaTexture)
398 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag.qsb"));
399 else
401 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb"));
402}
403
405 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
406{
407 bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
410
411 QByteArray *buf = state.uniformData();
412 Q_ASSERT(buf->size() >= 136);
413
414 if (!oldMat || oldMat->fontScale() != mat->fontScale() || oldMat->shift() != mat->shift()
415 || oldMat->textureSize() != mat->textureSize())
416 {
417 QVector2D shift(1.0 / mat->fontScale() * mat->shift().x(),
418 1.0 / mat->fontScale() * mat->shift().y());
419 memcpy(buf->data() + 128, &shift, 8);
420 changed = true;
421 }
422
423 return changed;
424}
425
427{
428public:
430};
431
434{
436 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"));
437 if (alphaTexture)
439 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag.qsb"));
440 else
442 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag.qsb"));
443}
444
447{
448}
449
451{
452}
453
455{
456 static QSGMaterialType type;
457 return &type;
458}
459
461{
464 else
466}
467
469{
471 if (m_shift != other->m_shift)
472 return &m_shift < &other->m_shift ? -1 : 1;
474}
475
477{
478public:
480
481 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
483 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
484};
485
488{
490
492 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.vert.qsb"));
493 if (alphaTexture)
495 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag.qsb"));
496 else
498 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb"));
499}
500
502 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
503{
504 bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
507
508 QByteArray *buf = state.uniformData();
509 Q_ASSERT(buf->size() >= 128);
510
511 if (!oldMat || mat->fontScale() != oldMat->fontScale()) {
512 float fontScale = mat->fontScale();
513 memcpy(buf->data() + 104, &fontScale, 4);
514 changed = true;
515 }
516
517 if (!oldMat || state.isMatrixDirty()) {
518 int viewportWidth = state.viewportRect().width();
519 QMatrix4x4 mat = state.combinedMatrix().inverted();
520 QVector4D vecDelta = mat.column(0) * (qreal(2) / viewportWidth);
521 memcpy(buf->data() + 112, &vecDelta, 16);
522 }
523
524 return changed;
525}
526
528 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
529{
531 Q_UNUSED(oldMaterial);
533
534 ps->blendEnable = true;
535 ps->srcColor = GraphicsPipelineState::ConstantColor;
536 ps->dstColor = GraphicsPipelineState::OneMinusSrcColor;
537
538 const QVector4D color = mat->color();
539 // this is dynamic state but it's - magic! - taken care of by the renderer
540 ps->blendConstant = QColor::fromRgbF(color.x(), color.y(), color.z(), 1.0f);
541
542 return true;
543}
544
546{
547 static QSGMaterialType type;
548 return &type;
549}
550
552{
555 else
557}
558
560{
561public:
563};
564
567{
569 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.vert.qsb"));
570 if (alphaTexture)
572 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag.qsb"));
573 else
575 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag.qsb"));
576}
577
579{
580 static QSGMaterialType type;
581 return &type;
582}
583
585{
588 else
590}
591
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
\inmodule QtCore
Definition qbytearray.h:57
float toFloat(bool *ok=nullptr) const
Returns the byte array converted to a float value.
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static QColor fromRgbF(float r, float g, float b, float a=1.0)
Static convenience function that returns a QColor constructed from the RGB color values,...
Definition qcolor.cpp:2427
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
QVector4D column(int index) const
Returns the elements of column index as a 4D vector.
Definition qmatrix4x4.h:259
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
virtual bool screenSpaceDerivativesSupported() const =0
const Texture * glyphTexture(glyph_t glyph)
virtual bool eightBitFormatIsAlphaSwizzled() const =0
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
QSGMaterialType * type() const override=0
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to prepare use of sampled images in the shader,...
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
virtual void setColor(const QColor &color)
const QSGDistanceFieldGlyphCache::Texture * m_texture
const QSGDistanceFieldGlyphCache::Texture * texture() const
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
QSGDistanceFieldGlyphCache * glyphCache() const
QSGDistanceFieldGlyphCache * m_glyph_cache
bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to enable the material to provide a custom set of graphics...
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
Encapsulates the current rendering state during a call to QSGMaterialShader::updateUniformData() and ...
The QSGMaterialShader class represents a graphics API independent shader program.
void setShaderFileName(Stage stage, const QString &filename)
Sets the filename for the shader for the specified stage.
void setFlag(Flags flags, bool on=true)
Sets the flags on this material shader if on is true; otherwise clears the specified flags.
The QSGMaterial class encapsulates rendering state for a shader program.
Definition qsgmaterial.h:15
virtual QSGMaterialType * type() const =0
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
void setFlag(Flags flags, bool on=true)
Sets the flags flags on this material if on is true; otherwise clears the attribute.
@ RequiresDeterminant
Definition qsgmaterial.h:19
void setTextureSize(const QSize &size)
void setTexture(QRhiTexture *texture)
void setOwnsTexture(bool owns)
RenderMode
\value RenderMode2D Normal 2D rendering \value RenderMode2DNoDepthBuffer Normal 2D rendering with dep...
\inmodule QtQuick
Definition qsgtexture.h:20
void setFiltering(Filtering filter)
Sets the sampling mode to filter.
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
The QVector2D class represents a vector or vertex in 2D space.
Definition qvectornd.h:31
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
else opt state
[0]
Combined button and popup list for selecting options.
static QT_WARNING_DISABLE_FLOAT_COMPARE ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
Definition qbezier.cpp:309
#define Q_LIKELY(x)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
qfloat16 qSqrt(qfloat16 f)
Definition qfloat16.h:243
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLboolean GLboolean GLboolean b
const GLfloat * m
GLboolean GLboolean GLboolean GLboolean a
[7]
GLboolean r
[2]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
[4]
GLsizei range
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLuint texture
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
GLboolean GLboolean g
GLuint name
GLdouble GLdouble t
Definition qopenglext.h:243
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static float thresholdFunc(float glyphScale)
static QT_BEGIN_NAMESPACE float qt_sg_envFloat(const char *name, float defaultValue)
static float spreadFunc(float glyphScale)
#define QStringLiteral(str)
#define t1
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:92
ptrdiff_t qintptr
Definition qtypes.h:71
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
Describes state changes that the material wants to apply to the currently active graphics pipeline st...
The QSGMaterialType class is used as a unique type token in combination with QSGMaterial.