1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2019 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtQuick module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qsgdistancefieldglyphnode_p_p.h" |
41 | #include "qsgrhidistancefieldglyphcache_p.h" |
42 | #include <QtGui/qopenglfunctions.h> |
43 | #include <QtGui/qsurface.h> |
44 | #include <QtGui/qwindow.h> |
45 | #include <qmath.h> |
46 | |
47 | QT_BEGIN_NAMESPACE |
48 | |
49 | static float qt_sg_envFloat(const char *name, float defaultValue) |
50 | { |
51 | if (Q_LIKELY(!qEnvironmentVariableIsSet(name))) |
52 | return defaultValue; |
53 | bool ok = false; |
54 | const float value = qgetenv(varName: name).toFloat(ok: &ok); |
55 | return ok ? value : defaultValue; |
56 | } |
57 | |
58 | static float thresholdFunc(float glyphScale) |
59 | { |
60 | static const float base = qt_sg_envFloat(name: "QT_DF_BASE" , defaultValue: 0.5f); |
61 | static const float baseDev = qt_sg_envFloat(name: "QT_DF_BASEDEVIATION" , defaultValue: 0.065f); |
62 | static const float devScaleMin = qt_sg_envFloat(name: "QT_DF_SCALEFORMAXDEV" , defaultValue: 0.15f); |
63 | static const float devScaleMax = qt_sg_envFloat(name: "QT_DF_SCALEFORNODEV" , defaultValue: 0.3f); |
64 | return base - ((qBound(min: devScaleMin, val: glyphScale, max: devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev); |
65 | } |
66 | |
67 | static float spreadFunc(float glyphScale) |
68 | { |
69 | static const float range = qt_sg_envFloat(name: "QT_DF_RANGE" , defaultValue: 0.06f); |
70 | return range / glyphScale; |
71 | } |
72 | |
73 | class QSGDistanceFieldTextMaterialShader : public QSGMaterialShader |
74 | { |
75 | public: |
76 | QSGDistanceFieldTextMaterialShader(); |
77 | |
78 | void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; |
79 | char const *const *attributeNames() const override; |
80 | |
81 | protected: |
82 | void initialize() override; |
83 | |
84 | void updateAlphaRange(); |
85 | void updateColor(const QVector4D &c); |
86 | void updateTextureScale(const QVector2D &ts); |
87 | |
88 | float m_fontScale = 1.0; |
89 | float m_matrixScale = 1.0; |
90 | |
91 | int m_matrix_id = -1; |
92 | int m_textureScale_id = -1; |
93 | int m_alphaMin_id = -1; |
94 | int m_alphaMax_id = -1; |
95 | int m_color_id = -1; |
96 | |
97 | QVector2D m_lastTextureScale; |
98 | QVector4D m_lastColor; |
99 | float m_lastAlphaMin = -1; |
100 | float m_lastAlphaMax = -1; |
101 | }; |
102 | |
103 | char const *const *QSGDistanceFieldTextMaterialShader::attributeNames() const { |
104 | static char const *const attr[] = { "vCoord" , "tCoord" , nullptr }; |
105 | return attr; |
106 | } |
107 | |
108 | QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader() |
109 | { |
110 | setShaderSourceFile(type: QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldtext.vert" )); |
111 | setShaderSourceFile(type: QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldtext.frag" )); |
112 | } |
113 | |
114 | void QSGDistanceFieldTextMaterialShader::updateAlphaRange() |
115 | { |
116 | float combinedScale = m_fontScale * m_matrixScale; |
117 | float base = thresholdFunc(glyphScale: combinedScale); |
118 | float range = spreadFunc(glyphScale: combinedScale); |
119 | float alphaMin = qMax(a: 0.0f, b: base - range); |
120 | float alphaMax = qMin(a: base + range, b: 1.0f); |
121 | if (alphaMin != m_lastAlphaMin) { |
122 | program()->setUniformValue(location: m_alphaMin_id, value: GLfloat(alphaMin)); |
123 | m_lastAlphaMin = alphaMin; |
124 | } |
125 | if (alphaMax != m_lastAlphaMax) { |
126 | program()->setUniformValue(location: m_alphaMax_id, value: GLfloat(alphaMax)); |
127 | m_lastAlphaMax = alphaMax; |
128 | } |
129 | } |
130 | |
131 | void QSGDistanceFieldTextMaterialShader::updateColor(const QVector4D &c) |
132 | { |
133 | if (m_lastColor != c) { |
134 | program()->setUniformValue(location: m_color_id, value: c); |
135 | m_lastColor = c; |
136 | } |
137 | } |
138 | |
139 | void QSGDistanceFieldTextMaterialShader::updateTextureScale(const QVector2D &ts) |
140 | { |
141 | if (m_lastTextureScale != ts) { |
142 | program()->setUniformValue(location: m_textureScale_id, value: ts); |
143 | m_lastTextureScale = ts; |
144 | } |
145 | } |
146 | |
147 | void QSGDistanceFieldTextMaterialShader::initialize() |
148 | { |
149 | QSGMaterialShader::initialize(); |
150 | m_matrix_id = program()->uniformLocation(name: "matrix" ); |
151 | m_textureScale_id = program()->uniformLocation(name: "textureScale" ); |
152 | m_color_id = program()->uniformLocation(name: "color" ); |
153 | m_alphaMin_id = program()->uniformLocation(name: "alphaMin" ); |
154 | m_alphaMax_id = program()->uniformLocation(name: "alphaMax" ); |
155 | } |
156 | |
157 | void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) |
158 | { |
159 | Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type()); |
160 | QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect); |
161 | QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect); |
162 | |
163 | bool updated = material->updateTextureSize(); |
164 | |
165 | if (oldMaterial == nullptr |
166 | || material->color() != oldMaterial->color() |
167 | || state.isOpacityDirty()) { |
168 | QVector4D color = material->color(); |
169 | color *= state.opacity(); |
170 | updateColor(c: color); |
171 | } |
172 | |
173 | bool updateRange = false; |
174 | if (oldMaterial == nullptr |
175 | || material->fontScale() != oldMaterial->fontScale()) { |
176 | m_fontScale = material->fontScale(); |
177 | updateRange = true; |
178 | } |
179 | if (state.isMatrixDirty()) { |
180 | program()->setUniformValue(location: m_matrix_id, value: state.combinedMatrix()); |
181 | m_matrixScale = qSqrt(v: qAbs(t: state.determinant())) * state.devicePixelRatio(); |
182 | updateRange = true; |
183 | } |
184 | if (updateRange) { |
185 | updateAlphaRange(); |
186 | } |
187 | |
188 | Q_ASSERT(material->glyphCache()); |
189 | |
190 | if (updated |
191 | || oldMaterial == nullptr |
192 | || oldMaterial->texture()->textureId != material->texture()->textureId) { |
193 | updateTextureScale(ts: QVector2D(1.0 / material->textureSize().width(), |
194 | 1.0 / material->textureSize().height())); |
195 | |
196 | QOpenGLFunctions *funcs = state.context()->functions(); |
197 | funcs->glBindTexture(GL_TEXTURE_2D, texture: material->texture()->textureId); |
198 | |
199 | if (updated) { |
200 | // Set the mag/min filters to be linear. We only need to do this when the texture |
201 | // has been recreated. |
202 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
203 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
204 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
205 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
206 | } |
207 | } |
208 | } |
209 | |
210 | class QSGDistanceFieldTextMaterialRhiShader : public QSGMaterialRhiShader |
211 | { |
212 | public: |
213 | QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture); |
214 | |
215 | bool updateUniformData(RenderState &state, |
216 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
217 | |
218 | void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, |
219 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
220 | |
221 | protected: |
222 | float m_fontScale = 1.0; |
223 | float m_matrixScale = 1.0; |
224 | }; |
225 | |
226 | QSGDistanceFieldTextMaterialRhiShader::QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture) |
227 | { |
228 | setShaderFileName(stage: VertexStage, |
229 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb" )); |
230 | if (alphaTexture) |
231 | setShaderFileName(stage: FragmentStage, |
232 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a.frag.qsb" )); |
233 | else |
234 | setShaderFileName(stage: FragmentStage, |
235 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.frag.qsb" )); |
236 | } |
237 | |
238 | bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state, |
239 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
240 | { |
241 | Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type()); |
242 | QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial); |
243 | QSGDistanceFieldTextMaterial *oldMat = static_cast<QSGDistanceFieldTextMaterial *>(oldMaterial); |
244 | |
245 | // updateUniformData() is called before updateSampledImage() by the |
246 | // renderer. Hence updating the glyph cache stuff here. |
247 | const bool textureUpdated = mat->updateTextureSizeAndWrapper(); |
248 | Q_ASSERT(mat->wrapperTexture()); |
249 | Q_ASSERT(oldMat == nullptr || oldMat->texture()); |
250 | |
251 | bool changed = false; |
252 | QByteArray *buf = state.uniformData(); |
253 | Q_ASSERT(buf->size() >= 104); |
254 | |
255 | bool updateRange = false; |
256 | if (!oldMat || mat->fontScale() != oldMat->fontScale()) { |
257 | m_fontScale = mat->fontScale(); |
258 | updateRange = true; |
259 | } |
260 | if (state.isMatrixDirty()) { |
261 | const QMatrix4x4 m = state.combinedMatrix(); |
262 | memcpy(dest: buf->data(), src: m.constData(), n: 64); |
263 | changed = true; |
264 | m_matrixScale = qSqrt(v: qAbs(t: state.determinant())) * state.devicePixelRatio(); |
265 | updateRange = true; |
266 | } |
267 | if (textureUpdated || !oldMat || oldMat->texture()->texture != mat->texture()->texture) { |
268 | const QVector2D ts(1.0f / mat->textureSize().width(), 1.0f / mat->textureSize().height()); |
269 | Q_ASSERT(sizeof(ts) == 8); |
270 | memcpy(dest: buf->data() + 64, src: &ts, n: 8); |
271 | changed = true; |
272 | } |
273 | if (!oldMat || mat->color() != oldMat->color() || state.isOpacityDirty()) { |
274 | const QVector4D color = mat->color() * state.opacity(); |
275 | Q_ASSERT(sizeof(color) == 16); |
276 | memcpy(dest: buf->data() + 80, src: &color, n: 16); |
277 | changed = true; |
278 | } |
279 | if (updateRange) { // deferred because depends on m_fontScale and m_matrixScale |
280 | const float combinedScale = m_fontScale * m_matrixScale; |
281 | const float base = thresholdFunc(glyphScale: combinedScale); |
282 | const float range = spreadFunc(glyphScale: combinedScale); |
283 | const QVector2D alphaMinMax(qMax(a: 0.0f, b: base - range), qMin(a: base + range, b: 1.0f)); |
284 | memcpy(dest: buf->data() + 96, src: &alphaMinMax, n: 8); |
285 | changed = true; |
286 | } |
287 | |
288 | // move texture uploads/copies onto the renderer's soon-to-be-committed list |
289 | static_cast<QSGRhiDistanceFieldGlyphCache *>(mat->glyphCache())->commitResourceUpdates(mergeInto: state.resourceUpdateBatch()); |
290 | |
291 | return changed; |
292 | } |
293 | |
294 | void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture, |
295 | QSGMaterial *newMaterial, QSGMaterial *) |
296 | { |
297 | Q_UNUSED(state); |
298 | if (binding != 1) |
299 | return; |
300 | |
301 | QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial); |
302 | QSGTexture *t = mat->wrapperTexture(); |
303 | t->setFiltering(QSGTexture::Linear); |
304 | *texture = t; |
305 | } |
306 | |
307 | QSGDistanceFieldTextMaterial::QSGDistanceFieldTextMaterial() |
308 | : m_glyph_cache(nullptr) |
309 | , m_texture(nullptr) |
310 | , m_fontScale(1.0) |
311 | , m_sgTexture(nullptr) |
312 | { |
313 | setFlag(flags: Blending | RequiresDeterminant | SupportsRhiShader, on: true); |
314 | } |
315 | |
316 | QSGDistanceFieldTextMaterial::~QSGDistanceFieldTextMaterial() |
317 | { |
318 | delete m_sgTexture; |
319 | } |
320 | |
321 | QSGMaterialType *QSGDistanceFieldTextMaterial::type() const |
322 | { |
323 | static QSGMaterialType type; |
324 | return &type; |
325 | } |
326 | |
327 | void QSGDistanceFieldTextMaterial::setColor(const QColor &color) |
328 | { |
329 | m_color = QVector4D(color.redF() * color.alphaF(), |
330 | color.greenF() * color.alphaF(), |
331 | color.blueF() * color.alphaF(), |
332 | color.alphaF()); |
333 | } |
334 | |
335 | QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader() const |
336 | { |
337 | if (flags().testFlag(flag: RhiShaderWanted)) |
338 | return new QSGDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); |
339 | else |
340 | return new QSGDistanceFieldTextMaterialShader; |
341 | } |
342 | |
343 | bool QSGDistanceFieldTextMaterial::updateTextureSize() |
344 | { |
345 | if (!m_texture) |
346 | m_texture = m_glyph_cache->glyphTexture(glyph: 0); // invalid texture |
347 | |
348 | if (m_texture->size != m_size) { |
349 | m_size = m_texture->size; |
350 | return true; |
351 | } |
352 | |
353 | return false; |
354 | } |
355 | |
356 | // When using the RHI we need a QSGTexture wrapping the QRhiTexture, just |
357 | // exposing a QRhiTexture * (which would be the equivalent of GLuint textureId) |
358 | // is not sufficient to play nice with the material. |
359 | bool QSGDistanceFieldTextMaterial::updateTextureSizeAndWrapper() |
360 | { |
361 | bool updated = updateTextureSize(); |
362 | if (updated) { |
363 | if (m_sgTexture) |
364 | delete m_sgTexture; |
365 | m_sgTexture = new QSGPlainTexture; |
366 | m_sgTexture->setTexture(m_texture->texture); |
367 | m_sgTexture->setTextureSize(m_size); |
368 | m_sgTexture->setOwnsTexture(false); |
369 | } |
370 | return updated; |
371 | } |
372 | |
373 | int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const |
374 | { |
375 | Q_ASSERT(o && type() == o->type()); |
376 | const QSGDistanceFieldTextMaterial *other = static_cast<const QSGDistanceFieldTextMaterial *>(o); |
377 | if (m_glyph_cache != other->m_glyph_cache) |
378 | return m_glyph_cache - other->m_glyph_cache; |
379 | if (m_fontScale != other->m_fontScale) { |
380 | return int(other->m_fontScale < m_fontScale) - int(m_fontScale < other->m_fontScale); |
381 | } |
382 | if (m_color != other->m_color) |
383 | return &m_color < &other->m_color ? -1 : 1; |
384 | int t0 = m_texture ? (m_texture->rhiBased ? qintptr(m_texture->texture) : m_texture->textureId) : 0; |
385 | int t1 = other->m_texture ? (other->m_texture->rhiBased ? qintptr(other->m_texture->texture) : other->m_texture->textureId) : 0; |
386 | return t0 - t1; |
387 | } |
388 | |
389 | |
390 | class DistanceFieldStyledTextMaterialShader : public QSGDistanceFieldTextMaterialShader |
391 | { |
392 | public: |
393 | DistanceFieldStyledTextMaterialShader(); |
394 | |
395 | void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; |
396 | |
397 | protected: |
398 | void initialize() override; |
399 | |
400 | int m_styleColor_id = -1; |
401 | }; |
402 | |
403 | DistanceFieldStyledTextMaterialShader::DistanceFieldStyledTextMaterialShader() |
404 | : QSGDistanceFieldTextMaterialShader() |
405 | { |
406 | } |
407 | |
408 | void DistanceFieldStyledTextMaterialShader::initialize() |
409 | { |
410 | QSGDistanceFieldTextMaterialShader::initialize(); |
411 | m_styleColor_id = program()->uniformLocation(name: "styleColor" ); |
412 | } |
413 | |
414 | void DistanceFieldStyledTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) |
415 | { |
416 | QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect); |
417 | |
418 | QSGDistanceFieldStyledTextMaterial *material = static_cast<QSGDistanceFieldStyledTextMaterial *>(newEffect); |
419 | QSGDistanceFieldStyledTextMaterial *oldMaterial = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldEffect); |
420 | |
421 | if (oldMaterial == nullptr |
422 | || material->styleColor() != oldMaterial->styleColor() |
423 | || (state.isOpacityDirty())) { |
424 | QVector4D color = material->styleColor(); |
425 | color *= state.opacity(); |
426 | program()->setUniformValue(location: m_styleColor_id, value: color); |
427 | } |
428 | } |
429 | |
430 | class DistanceFieldStyledTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader |
431 | { |
432 | public: |
433 | DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture); |
434 | |
435 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
436 | }; |
437 | |
438 | DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture) |
439 | : QSGDistanceFieldTextMaterialRhiShader(alphaTexture) |
440 | { |
441 | } |
442 | |
443 | bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(RenderState &state, |
444 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
445 | { |
446 | bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); |
447 | QSGDistanceFieldStyledTextMaterial *mat = static_cast<QSGDistanceFieldStyledTextMaterial *>(newMaterial); |
448 | QSGDistanceFieldStyledTextMaterial *oldMat = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldMaterial); |
449 | |
450 | QByteArray *buf = state.uniformData(); |
451 | Q_ASSERT(buf->size() >= 128); |
452 | |
453 | if (!oldMat || mat->styleColor() != oldMat->styleColor() || state.isOpacityDirty()) { |
454 | QVector4D styleColor = mat->styleColor(); |
455 | styleColor *= state.opacity(); |
456 | memcpy(dest: buf->data() + 112, src: &styleColor, n: 16); |
457 | changed = true; |
458 | } |
459 | |
460 | return changed; |
461 | } |
462 | |
463 | QSGDistanceFieldStyledTextMaterial::QSGDistanceFieldStyledTextMaterial() |
464 | : QSGDistanceFieldTextMaterial() |
465 | { |
466 | } |
467 | |
468 | QSGDistanceFieldStyledTextMaterial::~QSGDistanceFieldStyledTextMaterial() |
469 | { |
470 | } |
471 | |
472 | void QSGDistanceFieldStyledTextMaterial::setStyleColor(const QColor &color) |
473 | { |
474 | m_styleColor = QVector4D(color.redF() * color.alphaF(), |
475 | color.greenF() * color.alphaF(), |
476 | color.blueF() * color.alphaF(), |
477 | color.alphaF()); |
478 | } |
479 | |
480 | int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const |
481 | { |
482 | Q_ASSERT(o && type() == o->type()); |
483 | const QSGDistanceFieldStyledTextMaterial *other = static_cast<const QSGDistanceFieldStyledTextMaterial *>(o); |
484 | if (m_styleColor != other->m_styleColor) |
485 | return &m_styleColor < &other->m_styleColor ? -1 : 1; |
486 | return QSGDistanceFieldTextMaterial::compare(o); |
487 | } |
488 | |
489 | |
490 | class DistanceFieldOutlineTextMaterialShader : public DistanceFieldStyledTextMaterialShader |
491 | { |
492 | public: |
493 | DistanceFieldOutlineTextMaterialShader(); |
494 | |
495 | void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; |
496 | |
497 | protected: |
498 | void initialize() override; |
499 | |
500 | void updateOutlineAlphaRange(int dfRadius); |
501 | |
502 | int m_outlineAlphaMax0_id = -1; |
503 | int m_outlineAlphaMax1_id = -1; |
504 | }; |
505 | |
506 | DistanceFieldOutlineTextMaterialShader::DistanceFieldOutlineTextMaterialShader() |
507 | : DistanceFieldStyledTextMaterialShader() |
508 | { |
509 | setShaderSourceFile(type: QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldoutlinetext.frag" )); |
510 | } |
511 | |
512 | void DistanceFieldOutlineTextMaterialShader::initialize() |
513 | { |
514 | DistanceFieldStyledTextMaterialShader::initialize(); |
515 | m_outlineAlphaMax0_id = program()->uniformLocation(name: "outlineAlphaMax0" ); |
516 | m_outlineAlphaMax1_id = program()->uniformLocation(name: "outlineAlphaMax1" ); |
517 | } |
518 | |
519 | void DistanceFieldOutlineTextMaterialShader::updateOutlineAlphaRange(int dfRadius) |
520 | { |
521 | float combinedScale = m_fontScale * m_matrixScale; |
522 | float base = thresholdFunc(glyphScale: combinedScale); |
523 | float range = spreadFunc(glyphScale: combinedScale); |
524 | float outlineLimit = qMax(a: 0.2f, b: base - 0.5f / dfRadius / m_fontScale); |
525 | |
526 | float alphaMin = qMax(a: 0.0f, b: base - range); |
527 | float styleAlphaMin0 = qMax(a: 0.0f, b: outlineLimit - range); |
528 | float styleAlphaMin1 = qMin(a: outlineLimit + range, b: alphaMin); |
529 | program()->setUniformValue(location: m_outlineAlphaMax0_id, value: GLfloat(styleAlphaMin0)); |
530 | program()->setUniformValue(location: m_outlineAlphaMax1_id, value: GLfloat(styleAlphaMin1)); |
531 | } |
532 | |
533 | void DistanceFieldOutlineTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) |
534 | { |
535 | DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect); |
536 | |
537 | QSGDistanceFieldOutlineTextMaterial *material = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newEffect); |
538 | QSGDistanceFieldOutlineTextMaterial *oldMaterial = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldEffect); |
539 | |
540 | if (oldMaterial == nullptr |
541 | || material->fontScale() != oldMaterial->fontScale() |
542 | || state.isMatrixDirty()) |
543 | updateOutlineAlphaRange(dfRadius: material->glyphCache()->distanceFieldRadius()); |
544 | } |
545 | |
546 | class DistanceFieldOutlineTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader |
547 | { |
548 | public: |
549 | DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture); |
550 | |
551 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
552 | }; |
553 | |
554 | DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture) |
555 | : DistanceFieldStyledTextMaterialRhiShader(alphaTexture) |
556 | { |
557 | setShaderFileName(stage: VertexStage, |
558 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb" )); |
559 | if (alphaTexture) |
560 | setShaderFileName(stage: FragmentStage, |
561 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag.qsb" )); |
562 | else |
563 | setShaderFileName(stage: FragmentStage, |
564 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsb" )); |
565 | } |
566 | |
567 | bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(RenderState &state, |
568 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
569 | { |
570 | bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); |
571 | QSGDistanceFieldOutlineTextMaterial *mat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newMaterial); |
572 | QSGDistanceFieldOutlineTextMaterial *oldMat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldMaterial); |
573 | |
574 | QByteArray *buf = state.uniformData(); |
575 | Q_ASSERT(buf->size() >= 136); |
576 | |
577 | if (!oldMat || mat->fontScale() != oldMat->fontScale() || state.isMatrixDirty()) { |
578 | float dfRadius = mat->glyphCache()->distanceFieldRadius(); |
579 | float combinedScale = m_fontScale * m_matrixScale; |
580 | float base = thresholdFunc(glyphScale: combinedScale); |
581 | float range = spreadFunc(glyphScale: combinedScale); |
582 | float outlineLimit = qMax(a: 0.2f, b: base - 0.5f / dfRadius / m_fontScale); |
583 | float alphaMin = qMax(a: 0.0f, b: base - range); |
584 | float styleAlphaMin0 = qMax(a: 0.0f, b: outlineLimit - range); |
585 | float styleAlphaMin1 = qMin(a: outlineLimit + range, b: alphaMin); |
586 | memcpy(dest: buf->data() + 128, src: &styleAlphaMin0, n: 4); |
587 | memcpy(dest: buf->data() + 132, src: &styleAlphaMin1, n: 4); |
588 | changed = true; |
589 | } |
590 | |
591 | return changed; |
592 | } |
593 | |
594 | QSGDistanceFieldOutlineTextMaterial::QSGDistanceFieldOutlineTextMaterial() |
595 | : QSGDistanceFieldStyledTextMaterial() |
596 | { |
597 | } |
598 | |
599 | QSGDistanceFieldOutlineTextMaterial::~QSGDistanceFieldOutlineTextMaterial() |
600 | { |
601 | } |
602 | |
603 | QSGMaterialType *QSGDistanceFieldOutlineTextMaterial::type() const |
604 | { |
605 | static QSGMaterialType type; |
606 | return &type; |
607 | } |
608 | |
609 | QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader() const |
610 | { |
611 | if (flags().testFlag(flag: RhiShaderWanted)) |
612 | return new DistanceFieldOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); |
613 | else |
614 | return new DistanceFieldOutlineTextMaterialShader; |
615 | } |
616 | |
617 | |
618 | class DistanceFieldShiftedStyleTextMaterialShader : public DistanceFieldStyledTextMaterialShader |
619 | { |
620 | public: |
621 | DistanceFieldShiftedStyleTextMaterialShader(); |
622 | |
623 | void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; |
624 | |
625 | protected: |
626 | void initialize() override; |
627 | |
628 | void updateShift(qreal fontScale, const QPointF& shift); |
629 | |
630 | int m_shift_id = -1; |
631 | }; |
632 | |
633 | DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader() |
634 | : DistanceFieldStyledTextMaterialShader() |
635 | { |
636 | setShaderSourceFile(type: QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldshiftedtext.vert" )); |
637 | setShaderSourceFile(type: QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldshiftedtext.frag" )); |
638 | } |
639 | |
640 | void DistanceFieldShiftedStyleTextMaterialShader::initialize() |
641 | { |
642 | DistanceFieldStyledTextMaterialShader::initialize(); |
643 | m_shift_id = program()->uniformLocation(name: "shift" ); |
644 | } |
645 | |
646 | void DistanceFieldShiftedStyleTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) |
647 | { |
648 | DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect); |
649 | |
650 | QSGDistanceFieldShiftedStyleTextMaterial *material = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(newEffect); |
651 | QSGDistanceFieldShiftedStyleTextMaterial *oldMaterial = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(oldEffect); |
652 | |
653 | if (oldMaterial == nullptr |
654 | || oldMaterial->fontScale() != material->fontScale() |
655 | || oldMaterial->shift() != material->shift() |
656 | || oldMaterial->textureSize() != material->textureSize()) { |
657 | updateShift(fontScale: material->fontScale(), shift: material->shift()); |
658 | } |
659 | } |
660 | |
661 | void DistanceFieldShiftedStyleTextMaterialShader::updateShift(qreal fontScale, const QPointF &shift) |
662 | { |
663 | QPointF texel(1.0 / fontScale * shift.x(), |
664 | 1.0 / fontScale * shift.y()); |
665 | program()->setUniformValue(location: m_shift_id, point: texel); |
666 | } |
667 | |
668 | class DistanceFieldShiftedStyleTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader |
669 | { |
670 | public: |
671 | DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture); |
672 | |
673 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
674 | }; |
675 | |
676 | DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture) |
677 | : DistanceFieldStyledTextMaterialRhiShader(alphaTexture) |
678 | { |
679 | setShaderFileName(stage: VertexStage, |
680 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb" )); |
681 | if (alphaTexture) |
682 | setShaderFileName(stage: FragmentStage, |
683 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag.qsb" )); |
684 | else |
685 | setShaderFileName(stage: FragmentStage, |
686 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb" )); |
687 | } |
688 | |
689 | bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(RenderState &state, |
690 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
691 | { |
692 | bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); |
693 | QSGDistanceFieldShiftedStyleTextMaterial *mat = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(newMaterial); |
694 | QSGDistanceFieldShiftedStyleTextMaterial *oldMat = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(oldMaterial); |
695 | |
696 | QByteArray *buf = state.uniformData(); |
697 | Q_ASSERT(buf->size() >= 136); |
698 | |
699 | if (!oldMat || oldMat->fontScale() != mat->fontScale() || oldMat->shift() != mat->shift() |
700 | || oldMat->textureSize() != mat->textureSize()) |
701 | { |
702 | QPointF shift(1.0 / mat->fontScale() * mat->shift().x(), |
703 | 1.0 / mat->fontScale() * mat->shift().y()); |
704 | memcpy(dest: buf->data() + 128, src: &shift, n: 8); |
705 | changed = true; |
706 | } |
707 | |
708 | return changed; |
709 | } |
710 | |
711 | QSGDistanceFieldShiftedStyleTextMaterial::QSGDistanceFieldShiftedStyleTextMaterial() |
712 | : QSGDistanceFieldStyledTextMaterial() |
713 | { |
714 | } |
715 | |
716 | QSGDistanceFieldShiftedStyleTextMaterial::~QSGDistanceFieldShiftedStyleTextMaterial() |
717 | { |
718 | } |
719 | |
720 | QSGMaterialType *QSGDistanceFieldShiftedStyleTextMaterial::type() const |
721 | { |
722 | static QSGMaterialType type; |
723 | return &type; |
724 | } |
725 | |
726 | QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() const |
727 | { |
728 | if (flags().testFlag(flag: RhiShaderWanted)) |
729 | return new DistanceFieldShiftedStyleTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); |
730 | else |
731 | return new DistanceFieldShiftedStyleTextMaterialShader; |
732 | } |
733 | |
734 | int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) const |
735 | { |
736 | const QSGDistanceFieldShiftedStyleTextMaterial *other = static_cast<const QSGDistanceFieldShiftedStyleTextMaterial *>(o); |
737 | if (m_shift != other->m_shift) |
738 | return &m_shift < &other->m_shift ? -1 : 1; |
739 | return QSGDistanceFieldStyledTextMaterial::compare(o); |
740 | } |
741 | |
742 | |
743 | class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader |
744 | { |
745 | public: |
746 | QSGHiQSubPixelDistanceFieldTextMaterialShader(); |
747 | |
748 | void initialize() override; |
749 | void activate() override; |
750 | void deactivate() override; |
751 | void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; |
752 | |
753 | private: |
754 | int m_fontScale_id = -1; |
755 | int m_vecDelta_id = -1; |
756 | }; |
757 | |
758 | QSGHiQSubPixelDistanceFieldTextMaterialShader::QSGHiQSubPixelDistanceFieldTextMaterialShader() |
759 | : QSGDistanceFieldTextMaterialShader() |
760 | { |
761 | setShaderSourceFile(type: QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert" )); |
762 | setShaderSourceFile(type: QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag" )); |
763 | } |
764 | |
765 | void QSGHiQSubPixelDistanceFieldTextMaterialShader::initialize() |
766 | { |
767 | QSGDistanceFieldTextMaterialShader::initialize(); |
768 | m_fontScale_id = program()->uniformLocation(name: "fontScale" ); |
769 | m_vecDelta_id = program()->uniformLocation(name: "vecDelta" ); |
770 | } |
771 | |
772 | void QSGHiQSubPixelDistanceFieldTextMaterialShader::activate() |
773 | { |
774 | QSGDistanceFieldTextMaterialShader::activate(); |
775 | QOpenGLContext::currentContext()->functions()->glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR); |
776 | } |
777 | |
778 | void QSGHiQSubPixelDistanceFieldTextMaterialShader::deactivate() |
779 | { |
780 | QSGDistanceFieldTextMaterialShader::deactivate(); |
781 | QOpenGLContext::currentContext()->functions()->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); |
782 | } |
783 | |
784 | void QSGHiQSubPixelDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) |
785 | { |
786 | Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type()); |
787 | QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect); |
788 | QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect); |
789 | |
790 | if (oldMaterial == nullptr || material->color() != oldMaterial->color()) { |
791 | QVector4D c = material->color(); |
792 | state.context()->functions()->glBlendColor(red: c.x(), green: c.y(), blue: c.z(), alpha: 1.0f); |
793 | } |
794 | |
795 | if (oldMaterial == nullptr || material->fontScale() != oldMaterial->fontScale()) |
796 | program()->setUniformValue(location: m_fontScale_id, value: GLfloat(material->fontScale())); |
797 | |
798 | if (oldMaterial == nullptr || state.isMatrixDirty()) { |
799 | int viewportWidth = state.viewportRect().width(); |
800 | QMatrix4x4 mat = state.combinedMatrix().inverted(); |
801 | program()->setUniformValue(location: m_vecDelta_id, value: mat.column(index: 0) * (qreal(2) / viewportWidth)); |
802 | } |
803 | |
804 | QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect); |
805 | } |
806 | |
807 | class QSGHiQSubPixelDistanceFieldTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader |
808 | { |
809 | public: |
810 | QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture); |
811 | |
812 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
813 | bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, |
814 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
815 | }; |
816 | |
817 | QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture) |
818 | : QSGDistanceFieldTextMaterialRhiShader(alphaTexture) |
819 | { |
820 | setFlag(flags: UpdatesGraphicsPipelineState, on: true); |
821 | |
822 | setShaderFileName(stage: VertexStage, |
823 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.vert.qsb" )); |
824 | if (alphaTexture) |
825 | setShaderFileName(stage: FragmentStage, |
826 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag.qsb" )); |
827 | else |
828 | setShaderFileName(stage: FragmentStage, |
829 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb" )); |
830 | } |
831 | |
832 | bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state, |
833 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
834 | { |
835 | bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); |
836 | QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial); |
837 | QSGHiQSubPixelDistanceFieldTextMaterial *oldMat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(oldMaterial); |
838 | |
839 | QByteArray *buf = state.uniformData(); |
840 | Q_ASSERT(buf->size() >= 128); |
841 | |
842 | if (!oldMat || mat->fontScale() != oldMat->fontScale()) { |
843 | float fontScale = mat->fontScale(); |
844 | memcpy(dest: buf->data() + 104, src: &fontScale, n: 4); |
845 | changed = true; |
846 | } |
847 | |
848 | if (!oldMat || state.isMatrixDirty()) { |
849 | int viewportWidth = state.viewportRect().width(); |
850 | QMatrix4x4 mat = state.combinedMatrix().inverted(); |
851 | QVector4D vecDelta = mat.column(index: 0) * (qreal(2) / viewportWidth); |
852 | memcpy(dest: buf->data() + 112, src: &vecDelta, n: 16); |
853 | } |
854 | |
855 | return changed; |
856 | } |
857 | |
858 | bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, |
859 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
860 | { |
861 | Q_UNUSED(state); |
862 | Q_UNUSED(oldMaterial); |
863 | QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial); |
864 | |
865 | ps->blendEnable = true; |
866 | ps->srcColor = GraphicsPipelineState::ConstantColor; |
867 | ps->dstColor = GraphicsPipelineState::OneMinusSrcColor; |
868 | |
869 | const QVector4D color = mat->color(); |
870 | // this is dynamic state but it's - magic! - taken care of by the renderer |
871 | ps->blendConstant = QColor::fromRgbF(r: color.x(), g: color.y(), b: color.z(), a: 1.0f); |
872 | |
873 | return true; |
874 | } |
875 | |
876 | QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const |
877 | { |
878 | static QSGMaterialType type; |
879 | return &type; |
880 | } |
881 | |
882 | QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader() const |
883 | { |
884 | if (flags().testFlag(flag: RhiShaderWanted)) |
885 | return new QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); |
886 | else |
887 | return new QSGHiQSubPixelDistanceFieldTextMaterialShader; |
888 | } |
889 | |
890 | |
891 | class QSGLoQSubPixelDistanceFieldTextMaterialShader : public QSGHiQSubPixelDistanceFieldTextMaterialShader |
892 | { |
893 | public: |
894 | QSGLoQSubPixelDistanceFieldTextMaterialShader(); |
895 | }; |
896 | |
897 | QSGLoQSubPixelDistanceFieldTextMaterialShader::QSGLoQSubPixelDistanceFieldTextMaterialShader() |
898 | : QSGHiQSubPixelDistanceFieldTextMaterialShader() |
899 | { |
900 | setShaderSourceFile(type: QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/loqsubpixeldistancefieldtext.vert" )); |
901 | setShaderSourceFile(type: QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/loqsubpixeldistancefieldtext.frag" )); |
902 | } |
903 | |
904 | class QSGLoQSubPixelDistanceFieldTextMaterialRhiShader : public QSGHiQSubPixelDistanceFieldTextMaterialRhiShader |
905 | { |
906 | public: |
907 | QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture); |
908 | }; |
909 | |
910 | QSGLoQSubPixelDistanceFieldTextMaterialRhiShader::QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture) |
911 | : QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(alphaTexture) |
912 | { |
913 | setShaderFileName(stage: VertexStage, |
914 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.vert.qsb" )); |
915 | if (alphaTexture) |
916 | setShaderFileName(stage: FragmentStage, |
917 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag.qsb" )); |
918 | else |
919 | setShaderFileName(stage: FragmentStage, |
920 | QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag.qsb" )); |
921 | } |
922 | |
923 | QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const |
924 | { |
925 | static QSGMaterialType type; |
926 | return &type; |
927 | } |
928 | |
929 | QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader() const |
930 | { |
931 | if (flags().testFlag(flag: RhiShaderWanted)) |
932 | return new QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); |
933 | else |
934 | return new QSGLoQSubPixelDistanceFieldTextMaterialShader; |
935 | } |
936 | |
937 | QT_END_NAMESPACE |
938 | |