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
4#include "qsgdistancefieldglyphnode_p_p.h"
5#include "qsgrhidistancefieldglyphcache_p.h"
6#include <QtGui/qsurface.h>
7#include <QtGui/qwindow.h>
8#include <qmath.h>
9
10QT_BEGIN_NAMESPACE
11
12static float qt_sg_envFloat(const char *name, float defaultValue)
13{
14 if (Q_LIKELY(!qEnvironmentVariableIsSet(name)))
15 return defaultValue;
16 bool ok = false;
17 const float value = qgetenv(varName: name).toFloat(ok: &ok);
18 return ok ? value : defaultValue;
19}
20
21static float thresholdFunc(float glyphScale)
22{
23 static const float base = qt_sg_envFloat(name: "QT_DF_BASE", defaultValue: 0.5f);
24 static const float baseDev = qt_sg_envFloat(name: "QT_DF_BASEDEVIATION", defaultValue: 0.065f);
25 static const float devScaleMin = qt_sg_envFloat(name: "QT_DF_SCALEFORMAXDEV", defaultValue: 0.15f);
26 static const float devScaleMax = qt_sg_envFloat(name: "QT_DF_SCALEFORNODEV", defaultValue: 0.3f);
27 return base - ((qBound(min: devScaleMin, val: glyphScale, max: devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev);
28}
29
30static float spreadFunc(float glyphScale)
31{
32 static const float range = qt_sg_envFloat(name: "QT_DF_RANGE", defaultValue: 0.06f);
33 return range / glyphScale;
34}
35
36class QSGDistanceFieldTextMaterialRhiShader : public QSGMaterialShader
37{
38public:
39 QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture);
40
41 bool updateUniformData(RenderState &state,
42 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
43
44 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
45 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
46
47protected:
48 float m_fontScale = 1.0;
49 float m_matrixScale = 1.0;
50};
51
52QSGDistanceFieldTextMaterialRhiShader::QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture)
53{
54 setShaderFileName(stage: VertexStage,
55 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"));
56
57 if (alphaTexture)
58 setShaderFileName(stage: FragmentStage,
59 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a.frag.qsb"));
60 else
61 setShaderFileName(stage: FragmentStage,
62 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.frag.qsb"));
63}
64
65bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state,
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();
75 Q_ASSERT(mat->wrapperTexture());
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(dest: buf->data(), src: m.constData(), n: 64);
90 changed = true;
91 m_matrixScale = qSqrt(v: qAbs(t: 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(dest: buf->data() + 64, src: &ts, n: 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(dest: buf->data() + 80, src: &color, n: 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(glyphScale: combinedScale);
109 const float range = spreadFunc(glyphScale: combinedScale);
110 const QVector2D alphaMinMax(qMax(a: 0.0f, b: base - range), qMin(a: base + range, b: 1.0f));
111 memcpy(dest: buf->data() + 96, src: &alphaMinMax, n: 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(mergeInto: state.resourceUpdateBatch());
117
118 return changed;
119}
120
121void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
122 QSGMaterial *newMaterial, QSGMaterial *)
123{
124 Q_UNUSED(state);
125 if (binding != 1)
126 return;
127
128 QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial);
129 QSGTexture *t = mat->wrapperTexture();
130 t->setFiltering(QSGTexture::Linear);
131 *texture = t;
132}
133
134class DistanceFieldAnisotropicTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader
135{
136public:
137 DistanceFieldAnisotropicTextMaterialRhiShader(bool alphaTexture);
138};
139
140DistanceFieldAnisotropicTextMaterialRhiShader::DistanceFieldAnisotropicTextMaterialRhiShader(bool alphaTexture)
141 : QSGDistanceFieldTextMaterialRhiShader(alphaTexture)
142{
143 setShaderFileName(stage: VertexStage,
144 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"));
145 if (alphaTexture)
146 setShaderFileName(stage: FragmentStage,
147 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag.qsb"));
148 else
149 setShaderFileName(stage: FragmentStage,
150 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_fwidth.frag.qsb"));
151}
152
153QSGDistanceFieldTextMaterial::QSGDistanceFieldTextMaterial()
154 : m_glyph_cache(nullptr)
155 , m_texture(nullptr)
156 , m_fontScale(1.0)
157 , m_sgTexture(nullptr)
158{
159 setFlag(flags: Blending | RequiresDeterminant, on: true);
160}
161
162QSGDistanceFieldTextMaterial::~QSGDistanceFieldTextMaterial()
163{
164 delete m_sgTexture;
165}
166
167QSGMaterialType *QSGDistanceFieldTextMaterial::type() const
168{
169 static QSGMaterialType type;
170 return &type;
171}
172
173void QSGDistanceFieldTextMaterial::setColor(const QColor &color)
174{
175 float r, g, b, a;
176 color.getRgbF(r: &r, g: &g, b: &b, a: &a);
177 m_color = QVector4D(r * a, g * a, b * a, a);
178}
179
180QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
181{
182 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
183 return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
184 else
185 return new QSGDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
186}
187
188bool QSGDistanceFieldTextMaterial::updateTextureSize()
189{
190 if (!m_texture)
191 m_texture = m_glyph_cache->glyphTexture(glyph: 0); // invalid texture
192
193 if (m_texture->size != m_size) {
194 m_size = m_texture->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.
204bool QSGDistanceFieldTextMaterial::updateTextureSizeAndWrapper()
205{
206 bool updated = updateTextureSize();
207 if (updated) {
208 if (m_sgTexture)
209 delete m_sgTexture;
210 m_sgTexture = new QSGPlainTexture;
211 m_sgTexture->setTexture(m_texture->texture);
212 m_sgTexture->setTextureSize(m_size);
213 m_sgTexture->setOwnsTexture(false);
214 }
215 return updated;
216}
217
218int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const
219{
220 Q_ASSERT(o && type() == o->type());
221 const QSGDistanceFieldTextMaterial *other = static_cast<const QSGDistanceFieldTextMaterial *>(o);
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;
229 qintptr t0 = m_texture ? qintptr(m_texture->texture) : 0;
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}
234class DistanceFieldStyledTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader
235{
236public:
237 DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture);
238
239 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
240};
241
242DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture)
243 : QSGDistanceFieldTextMaterialRhiShader(alphaTexture)
244{
245}
246
247bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(RenderState &state,
248 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
249{
250 bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
251 QSGDistanceFieldStyledTextMaterial *mat = static_cast<QSGDistanceFieldStyledTextMaterial *>(newMaterial);
252 QSGDistanceFieldStyledTextMaterial *oldMat = static_cast<QSGDistanceFieldStyledTextMaterial *>(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(dest: buf->data() + 112, src: &styleColor, n: 16);
261 changed = true;
262 }
263
264 return changed;
265}
266
267QSGDistanceFieldStyledTextMaterial::QSGDistanceFieldStyledTextMaterial()
268 : QSGDistanceFieldTextMaterial()
269{
270}
271
272QSGDistanceFieldStyledTextMaterial::~QSGDistanceFieldStyledTextMaterial()
273{
274}
275
276void QSGDistanceFieldStyledTextMaterial::setStyleColor(const QColor &color)
277{
278 float r, g, b, a;
279 color.getRgbF(r: &r, g: &g, b: &b, a: &a);
280 m_styleColor = QVector4D(r * a, g * a, b * a, a);
281}
282
283int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const
284{
285 Q_ASSERT(o && type() == o->type());
286 const QSGDistanceFieldStyledTextMaterial *other = static_cast<const QSGDistanceFieldStyledTextMaterial *>(o);
287 if (m_styleColor != other->m_styleColor)
288 return &m_styleColor < &other->m_styleColor ? -1 : 1;
289 return QSGDistanceFieldTextMaterial::compare(o);
290}
291
292class DistanceFieldOutlineTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader
293{
294public:
295 DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture);
296
297 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
298};
299
300DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture)
301 : DistanceFieldStyledTextMaterialRhiShader(alphaTexture)
302{
303 setShaderFileName(stage: VertexStage,
304 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"));
305
306 if (alphaTexture)
307 setShaderFileName(stage: FragmentStage,
308 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag.qsb"));
309 else
310 setShaderFileName(stage: FragmentStage,
311 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsb"));
312}
313
314class DistanceFieldAnisotropicOutlineTextMaterialRhiShader : public DistanceFieldOutlineTextMaterialRhiShader
315{
316public:
317 DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture);
318};
319
320DistanceFieldAnisotropicOutlineTextMaterialRhiShader::DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture)
321 : DistanceFieldOutlineTextMaterialRhiShader(alphaTexture)
322{
323 setShaderFileName(stage: VertexStage,
324 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"));
325 if (alphaTexture)
326 setShaderFileName(stage: FragmentStage,
327 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag.qsb"));
328 else
329 setShaderFileName(stage: FragmentStage,
330 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag.qsb"));
331}
332
333bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(RenderState &state,
334 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
335{
336 bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
337 QSGDistanceFieldOutlineTextMaterial *mat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newMaterial);
338 QSGDistanceFieldOutlineTextMaterial *oldMat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(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(glyphScale: combinedScale);
347 float range = spreadFunc(glyphScale: combinedScale);
348 float outlineLimit = qMax(a: 0.2f, b: base - 0.5f / dfRadius / m_fontScale);
349 float alphaMin = qMax(a: 0.0f, b: base - range);
350 float styleAlphaMin0 = qMax(a: 0.0f, b: outlineLimit - range);
351 float styleAlphaMin1 = qMin(a: outlineLimit + range, b: alphaMin);
352 memcpy(dest: buf->data() + 128, src: &styleAlphaMin0, n: 4);
353 memcpy(dest: buf->data() + 132, src: &styleAlphaMin1, n: 4);
354 changed = true;
355 }
356
357 return changed;
358}
359
360QSGDistanceFieldOutlineTextMaterial::QSGDistanceFieldOutlineTextMaterial()
361 : QSGDistanceFieldStyledTextMaterial()
362{
363}
364
365QSGDistanceFieldOutlineTextMaterial::~QSGDistanceFieldOutlineTextMaterial()
366{
367}
368
369QSGMaterialType *QSGDistanceFieldOutlineTextMaterial::type() const
370{
371 static QSGMaterialType type;
372 return &type;
373}
374
375QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
376{
377 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
378 return new DistanceFieldAnisotropicOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
379 else
380 return new DistanceFieldOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
381}
382
383class DistanceFieldShiftedStyleTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader
384{
385public:
386 DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture);
387
388 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
389};
390
391DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture)
392 : DistanceFieldStyledTextMaterialRhiShader(alphaTexture)
393{
394 setShaderFileName(stage: VertexStage,
395 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"));
396 if (alphaTexture)
397 setShaderFileName(stage: FragmentStage,
398 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag.qsb"));
399 else
400 setShaderFileName(stage: FragmentStage,
401 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb"));
402}
403
404bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(RenderState &state,
405 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
406{
407 bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
408 QSGDistanceFieldShiftedStyleTextMaterial *mat = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(newMaterial);
409 QSGDistanceFieldShiftedStyleTextMaterial *oldMat = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(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(dest: buf->data() + 128, src: &shift, n: 8);
420 changed = true;
421 }
422
423 return changed;
424}
425
426class DistanceFieldAnisotropicShiftedTextMaterialRhiShader : public DistanceFieldShiftedStyleTextMaterialRhiShader
427{
428public:
429 DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture);
430};
431
432DistanceFieldAnisotropicShiftedTextMaterialRhiShader::DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture)
433 : DistanceFieldShiftedStyleTextMaterialRhiShader(alphaTexture)
434{
435 setShaderFileName(stage: VertexStage,
436 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"));
437 if (alphaTexture)
438 setShaderFileName(stage: FragmentStage,
439 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag.qsb"));
440 else
441 setShaderFileName(stage: FragmentStage,
442 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag.qsb"));
443}
444
445QSGDistanceFieldShiftedStyleTextMaterial::QSGDistanceFieldShiftedStyleTextMaterial()
446 : QSGDistanceFieldStyledTextMaterial()
447{
448}
449
450QSGDistanceFieldShiftedStyleTextMaterial::~QSGDistanceFieldShiftedStyleTextMaterial()
451{
452}
453
454QSGMaterialType *QSGDistanceFieldShiftedStyleTextMaterial::type() const
455{
456 static QSGMaterialType type;
457 return &type;
458}
459
460QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
461{
462 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
463 return new DistanceFieldAnisotropicShiftedTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
464 else
465 return new DistanceFieldShiftedStyleTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
466}
467
468int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) const
469{
470 const QSGDistanceFieldShiftedStyleTextMaterial *other = static_cast<const QSGDistanceFieldShiftedStyleTextMaterial *>(o);
471 if (m_shift != other->m_shift)
472 return &m_shift < &other->m_shift ? -1 : 1;
473 return QSGDistanceFieldStyledTextMaterial::compare(o);
474}
475
476class QSGHiQSubPixelDistanceFieldTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader
477{
478public:
479 QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture);
480
481 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
482 bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
483 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
484};
485
486QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture)
487 : QSGDistanceFieldTextMaterialRhiShader(alphaTexture)
488{
489 setFlag(flags: UpdatesGraphicsPipelineState, on: true);
490
491 setShaderFileName(stage: VertexStage,
492 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.vert.qsb"));
493 if (alphaTexture)
494 setShaderFileName(stage: FragmentStage,
495 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag.qsb"));
496 else
497 setShaderFileName(stage: FragmentStage,
498 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb"));
499}
500
501bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state,
502 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
503{
504 bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
505 QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial);
506 QSGHiQSubPixelDistanceFieldTextMaterial *oldMat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(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(dest: buf->data() + 104, src: &fontScale, n: 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(index: 0) * (qreal(2) / viewportWidth);
521 memcpy(dest: buf->data() + 112, src: &vecDelta, n: 16);
522 }
523
524 return changed;
525}
526
527bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
528 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
529{
530 Q_UNUSED(state);
531 Q_UNUSED(oldMaterial);
532 QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial);
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(r: color.x(), g: color.y(), b: color.z(), a: 1.0f);
541
542 return true;
543}
544
545QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const
546{
547 static QSGMaterialType type;
548 return &type;
549}
550
551QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
552{
553 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
554 return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
555 else
556 return new QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
557}
558
559class QSGLoQSubPixelDistanceFieldTextMaterialRhiShader : public QSGHiQSubPixelDistanceFieldTextMaterialRhiShader
560{
561public:
562 QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture);
563};
564
565QSGLoQSubPixelDistanceFieldTextMaterialRhiShader::QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture)
566 : QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(alphaTexture)
567{
568 setShaderFileName(stage: VertexStage,
569 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.vert.qsb"));
570 if (alphaTexture)
571 setShaderFileName(stage: FragmentStage,
572 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag.qsb"));
573 else
574 setShaderFileName(stage: FragmentStage,
575 QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag.qsb"));
576}
577
578QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const
579{
580 static QSGMaterialType type;
581 return &type;
582}
583
584QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
585{
586 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
587 return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
588 else
589 return new QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled());
590}
591
592QT_END_NAMESPACE
593

source code of qtdeclarative/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp