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, int viewCount);
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 quint32 m_currentUbufOffset;
51};
52
53QSGDistanceFieldTextMaterialRhiShader::QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount)
54{
55 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"), viewCount);
56 if (alphaTexture)
57 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a.frag.qsb"), viewCount);
58 else
59 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.frag.qsb"), viewCount);
60}
61
62bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state,
63 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
64{
65 Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type());
66 QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial);
67 QSGDistanceFieldTextMaterial *oldMat = static_cast<QSGDistanceFieldTextMaterial *>(oldMaterial);
68
69 // updateUniformData() is called before updateSampledImage() by the
70 // renderer. Hence updating the glyph cache stuff here.
71 const bool textureUpdated = mat->updateTextureSizeAndWrapper();
72 Q_ASSERT(mat->wrapperTexture());
73 Q_ASSERT(oldMat == nullptr || oldMat->texture());
74
75 bool changed = false;
76 QByteArray *buf = state.uniformData();
77 Q_ASSERT(buf->size() >= 104);
78
79 bool updateRange = false;
80 if (!oldMat || mat->fontScale() != oldMat->fontScale()) {
81 m_fontScale = mat->fontScale();
82 updateRange = true;
83 }
84 if (state.isMatrixDirty()) {
85 m_matrixScale = qSqrt(v: qAbs(t: state.determinant())) * state.devicePixelRatio();
86 updateRange = true;
87 }
88 quint32 offset = 0;
89 const int matrixCount = qMin(a: state.projectionMatrixCount(), b: newMaterial->viewCount());
90 for (int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) {
91 if (state.isMatrixDirty()) {
92 const QMatrix4x4 m = state.combinedMatrix(index: viewIndex);
93 memcpy(dest: buf->data() + 64 * viewIndex, src: m.constData(), n: 64);
94 changed = true;
95 }
96 offset += 64;
97 }
98 if (textureUpdated || !oldMat || oldMat->texture()->texture != mat->texture()->texture) {
99 const QVector2D ts(1.0f / mat->textureSize().width(), 1.0f / mat->textureSize().height());
100 Q_ASSERT(sizeof(ts) == 8);
101 memcpy(dest: buf->data() + offset, src: &ts, n: 8);
102 changed = true;
103 }
104 offset += 8 + 8; // 8 is padding for vec4 alignment
105 if (!oldMat || mat->color() != oldMat->color() || state.isOpacityDirty()) {
106 const QVector4D color = mat->color() * state.opacity();
107 Q_ASSERT(sizeof(color) == 16);
108 memcpy(dest: buf->data() + offset, src: &color, n: 16);
109 changed = true;
110 }
111 offset += 16;
112 if (updateRange) { // deferred because depends on m_fontScale and m_matrixScale
113 const float combinedScale = m_fontScale * m_matrixScale;
114 const float base = thresholdFunc(glyphScale: combinedScale);
115 const float range = spreadFunc(glyphScale: combinedScale);
116 const QVector2D alphaMinMax(qMax(a: 0.0f, b: base - range), qMin(a: base + range, b: 1.0f));
117 memcpy(dest: buf->data() + offset, src: &alphaMinMax, n: 8);
118 changed = true;
119 }
120 offset += 8; // not adding any padding here since we are not sure what comes afterwards in the subclasses' shaders
121
122 // move texture uploads/copies onto the renderer's soon-to-be-committed list
123 static_cast<QSGRhiDistanceFieldGlyphCache *>(mat->glyphCache())->commitResourceUpdates(mergeInto: state.resourceUpdateBatch());
124
125 m_currentUbufOffset = offset;
126 return changed;
127}
128
129void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
130 QSGMaterial *newMaterial, QSGMaterial *)
131{
132 Q_UNUSED(state);
133 if (binding != 1)
134 return;
135
136 QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial);
137 QSGTexture *t = mat->wrapperTexture();
138 t->setFiltering(QSGTexture::Linear);
139 *texture = t;
140}
141
142class DistanceFieldAnisotropicTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader
143{
144public:
145 DistanceFieldAnisotropicTextMaterialRhiShader(bool alphaTexture, int viewCount);
146};
147
148DistanceFieldAnisotropicTextMaterialRhiShader::DistanceFieldAnisotropicTextMaterialRhiShader(bool alphaTexture, int viewCount)
149 : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount)
150{
151 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"), viewCount);
152 if (alphaTexture)
153 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag.qsb"), viewCount);
154 else
155 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_fwidth.frag.qsb"), viewCount);
156}
157
158QSGDistanceFieldTextMaterial::QSGDistanceFieldTextMaterial()
159 : m_glyph_cache(nullptr)
160 , m_texture(nullptr)
161 , m_fontScale(1.0)
162 , m_sgTexture(nullptr)
163{
164 setFlag(flags: Blending | RequiresDeterminant, on: true);
165}
166
167QSGDistanceFieldTextMaterial::~QSGDistanceFieldTextMaterial()
168{
169 delete m_sgTexture;
170}
171
172QSGMaterialType *QSGDistanceFieldTextMaterial::type() const
173{
174 static QSGMaterialType type;
175 return &type;
176}
177
178void QSGDistanceFieldTextMaterial::setColor(const QColor &color)
179{
180 float r, g, b, a;
181 color.getRgbF(r: &r, g: &g, b: &b, a: &a);
182 m_color = QVector4D(r * a, g * a, b * a, a);
183}
184
185QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
186{
187 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
188 return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
189 else
190 return new QSGDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
191}
192
193bool QSGDistanceFieldTextMaterial::updateTextureSize()
194{
195 if (!m_texture)
196 m_texture = m_glyph_cache->glyphTexture(glyph: 0); // invalid texture
197
198 if (m_texture->size != m_size) {
199 m_size = m_texture->size;
200 return true;
201 }
202
203 return false;
204}
205
206// When using the RHI we need a QSGTexture wrapping the QRhiTexture, just
207// exposing a QRhiTexture * (which would be the equivalent of GLuint textureId)
208// is not sufficient to play nice with the material.
209bool QSGDistanceFieldTextMaterial::updateTextureSizeAndWrapper()
210{
211 bool updated = updateTextureSize();
212 if (updated) {
213 if (m_sgTexture)
214 delete m_sgTexture;
215 m_sgTexture = new QSGPlainTexture;
216 m_sgTexture->setTexture(m_texture->texture);
217 m_sgTexture->setTextureSize(m_size);
218 m_sgTexture->setOwnsTexture(false);
219 }
220 return updated;
221}
222
223int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const
224{
225 Q_ASSERT(o && type() == o->type());
226 const QSGDistanceFieldTextMaterial *other = static_cast<const QSGDistanceFieldTextMaterial *>(o);
227 if (m_glyph_cache != other->m_glyph_cache)
228 return m_glyph_cache - other->m_glyph_cache;
229 if (m_fontScale != other->m_fontScale) {
230 return int(other->m_fontScale < m_fontScale) - int(m_fontScale < other->m_fontScale);
231 }
232 if (m_color != other->m_color)
233 return &m_color < &other->m_color ? -1 : 1;
234 qintptr t0 = m_texture ? qintptr(m_texture->texture) : 0;
235 qintptr t1 = other->m_texture ? qintptr(other->m_texture->texture) : 0;
236 const qintptr diff = t0 - t1;
237 return diff < 0 ? -1 : (diff > 0 ? 1 : 0);
238}
239class DistanceFieldStyledTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader
240{
241public:
242 DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture, int viewCount);
243
244 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
245};
246
247DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture, int viewCount)
248 : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount)
249{
250}
251
252bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(RenderState &state,
253 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
254{
255 bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
256 QSGDistanceFieldStyledTextMaterial *mat = static_cast<QSGDistanceFieldStyledTextMaterial *>(newMaterial);
257 QSGDistanceFieldStyledTextMaterial *oldMat = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldMaterial);
258
259 QByteArray *buf = state.uniformData();
260 Q_ASSERT(buf->size() >= 128);
261
262 // must add 8 bytes padding for vec4 alignment, the base class did not do this
263 m_currentUbufOffset += 8; // now at StyleColor
264
265 if (!oldMat || mat->styleColor() != oldMat->styleColor() || state.isOpacityDirty()) {
266 QVector4D styleColor = mat->styleColor();
267 styleColor *= state.opacity();
268
269 memcpy(dest: buf->data() + m_currentUbufOffset, src: &styleColor, n: 16);
270 changed = true;
271 }
272 m_currentUbufOffset += 16;
273
274 return changed;
275}
276
277QSGDistanceFieldStyledTextMaterial::QSGDistanceFieldStyledTextMaterial()
278 : QSGDistanceFieldTextMaterial()
279{
280}
281
282QSGDistanceFieldStyledTextMaterial::~QSGDistanceFieldStyledTextMaterial()
283{
284}
285
286void QSGDistanceFieldStyledTextMaterial::setStyleColor(const QColor &color)
287{
288 float r, g, b, a;
289 color.getRgbF(r: &r, g: &g, b: &b, a: &a);
290 m_styleColor = QVector4D(r * a, g * a, b * a, a);
291}
292
293int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const
294{
295 Q_ASSERT(o && type() == o->type());
296 const QSGDistanceFieldStyledTextMaterial *other = static_cast<const QSGDistanceFieldStyledTextMaterial *>(o);
297 if (m_styleColor != other->m_styleColor)
298 return &m_styleColor < &other->m_styleColor ? -1 : 1;
299 return QSGDistanceFieldTextMaterial::compare(o);
300}
301
302class DistanceFieldOutlineTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader
303{
304public:
305 DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount);
306
307 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
308};
309
310DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount)
311 : DistanceFieldStyledTextMaterialRhiShader(alphaTexture, viewCount)
312{
313 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"), viewCount);
314 if (alphaTexture)
315 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag.qsb"), viewCount);
316 else
317 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsb"), viewCount);
318}
319
320class DistanceFieldAnisotropicOutlineTextMaterialRhiShader : public DistanceFieldOutlineTextMaterialRhiShader
321{
322public:
323 DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount);
324};
325
326DistanceFieldAnisotropicOutlineTextMaterialRhiShader::DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount)
327 : DistanceFieldOutlineTextMaterialRhiShader(alphaTexture, viewCount)
328{
329 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"), viewCount);
330 if (alphaTexture)
331 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag.qsb"), viewCount);
332 else
333 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag.qsb"), viewCount);
334}
335
336bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(RenderState &state,
337 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
338{
339 bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
340 QSGDistanceFieldOutlineTextMaterial *mat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newMaterial);
341 QSGDistanceFieldOutlineTextMaterial *oldMat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldMaterial);
342
343 QByteArray *buf = state.uniformData();
344 Q_ASSERT(buf->size() >= 136);
345
346 if (!oldMat || mat->fontScale() != oldMat->fontScale() || state.isMatrixDirty()) {
347 float dfRadius = mat->glyphCache()->distanceFieldRadius();
348 float combinedScale = m_fontScale * m_matrixScale;
349 float base = thresholdFunc(glyphScale: combinedScale);
350 float range = spreadFunc(glyphScale: combinedScale);
351 float outlineLimit = qMax(a: 0.2f, b: base - 0.5f / dfRadius / m_fontScale);
352 float alphaMin = qMax(a: 0.0f, b: base - range);
353 float styleAlphaMin0 = qMax(a: 0.0f, b: outlineLimit - range);
354 float styleAlphaMin1 = qMin(a: outlineLimit + range, b: alphaMin);
355 memcpy(dest: buf->data() + m_currentUbufOffset, src: &styleAlphaMin0, n: 4);
356 memcpy(dest: buf->data() + m_currentUbufOffset + 4, src: &styleAlphaMin1, n: 4);
357 changed = true;
358 }
359
360 return changed;
361}
362
363QSGDistanceFieldOutlineTextMaterial::QSGDistanceFieldOutlineTextMaterial()
364 : QSGDistanceFieldStyledTextMaterial()
365{
366}
367
368QSGDistanceFieldOutlineTextMaterial::~QSGDistanceFieldOutlineTextMaterial()
369{
370}
371
372QSGMaterialType *QSGDistanceFieldOutlineTextMaterial::type() const
373{
374 static QSGMaterialType type;
375 return &type;
376}
377
378QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
379{
380 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
381 return new DistanceFieldAnisotropicOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
382 else
383 return new DistanceFieldOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
384}
385
386class DistanceFieldShiftedStyleTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader
387{
388public:
389 DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture, int viewCount);
390
391 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
392};
393
394DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture, int viewCount)
395 : DistanceFieldStyledTextMaterialRhiShader(alphaTexture, viewCount)
396{
397 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"), viewCount);
398 if (alphaTexture)
399 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag.qsb"), viewCount);
400 else
401 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb"), viewCount);
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() + m_currentUbufOffset, src: &shift, n: 8);
420 changed = true;
421 }
422
423 return changed;
424}
425
426class DistanceFieldAnisotropicShiftedTextMaterialRhiShader : public DistanceFieldShiftedStyleTextMaterialRhiShader
427{
428public:
429 DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture, int viewCount);
430};
431
432DistanceFieldAnisotropicShiftedTextMaterialRhiShader::DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture, int viewCount)
433 : DistanceFieldShiftedStyleTextMaterialRhiShader(alphaTexture, viewCount)
434{
435 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"), viewCount);
436 if (alphaTexture)
437 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag.qsb"), viewCount);
438 else
439 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag.qsb"), viewCount);
440}
441
442QSGDistanceFieldShiftedStyleTextMaterial::QSGDistanceFieldShiftedStyleTextMaterial()
443 : QSGDistanceFieldStyledTextMaterial()
444{
445}
446
447QSGDistanceFieldShiftedStyleTextMaterial::~QSGDistanceFieldShiftedStyleTextMaterial()
448{
449}
450
451QSGMaterialType *QSGDistanceFieldShiftedStyleTextMaterial::type() const
452{
453 static QSGMaterialType type;
454 return &type;
455}
456
457QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
458{
459 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
460 return new DistanceFieldAnisotropicShiftedTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
461 else
462 return new DistanceFieldShiftedStyleTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
463}
464
465int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) const
466{
467 const QSGDistanceFieldShiftedStyleTextMaterial *other = static_cast<const QSGDistanceFieldShiftedStyleTextMaterial *>(o);
468 if (m_shift != other->m_shift)
469 return &m_shift < &other->m_shift ? -1 : 1;
470 return QSGDistanceFieldStyledTextMaterial::compare(o);
471}
472
473class QSGHiQSubPixelDistanceFieldTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader
474{
475public:
476 QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount);
477
478 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
479 bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
480 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
481};
482
483QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount)
484 : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount)
485{
486 setFlag(flags: UpdatesGraphicsPipelineState, on: true);
487 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.vert.qsb"), viewCount);
488 if (alphaTexture)
489 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag.qsb"), viewCount);
490 else
491 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb"), viewCount);
492}
493
494bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state,
495 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
496{
497 bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
498 QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial);
499 QSGHiQSubPixelDistanceFieldTextMaterial *oldMat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(oldMaterial);
500
501 QByteArray *buf = state.uniformData();
502 Q_ASSERT(buf->size() >= 128);
503
504 if (!oldMat || mat->fontScale() != oldMat->fontScale()) {
505 float fontScale = mat->fontScale();
506 memcpy(dest: buf->data() + m_currentUbufOffset, src: &fontScale, n: 4);
507 changed = true;
508 }
509 m_currentUbufOffset += 4 + 4; // 4 for padding for vec2 alignment
510
511 if (!oldMat || state.isMatrixDirty()) {
512 int viewportWidth = state.viewportRect().width();
513 QMatrix4x4 mat = state.combinedMatrix().inverted();
514 QVector4D vecDelta = mat.column(index: 0) * (qreal(2) / viewportWidth);
515 memcpy(dest: buf->data() + m_currentUbufOffset, src: &vecDelta, n: 16);
516 }
517
518 return changed;
519}
520
521bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
522 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
523{
524 Q_UNUSED(state);
525 Q_UNUSED(oldMaterial);
526 QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial);
527
528 ps->blendEnable = true;
529 ps->srcColor = GraphicsPipelineState::ConstantColor;
530 ps->dstColor = GraphicsPipelineState::OneMinusSrcColor;
531
532 const QVector4D color = mat->color();
533 // this is dynamic state but it's - magic! - taken care of by the renderer
534 ps->blendConstant = QColor::fromRgbF(r: color.x(), g: color.y(), b: color.z(), a: 1.0f);
535
536 return true;
537}
538
539QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const
540{
541 static QSGMaterialType type;
542 return &type;
543}
544
545QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
546{
547 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
548 return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
549 else
550 return new QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
551}
552
553class QSGLoQSubPixelDistanceFieldTextMaterialRhiShader : public QSGHiQSubPixelDistanceFieldTextMaterialRhiShader
554{
555public:
556 QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount);
557};
558
559QSGLoQSubPixelDistanceFieldTextMaterialRhiShader::QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount)
560 : QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount)
561{
562 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.vert.qsb"), viewCount);
563 if (alphaTexture)
564 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag.qsb"), viewCount);
565 else
566 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag.qsb"), viewCount);
567}
568
569QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const
570{
571 static QSGMaterialType type;
572 return &type;
573}
574
575QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
576{
577 if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
578 return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
579 else
580 return new QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
581}
582
583QT_END_NAMESPACE
584

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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