1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qsgdistancefieldglyphnode_p_p.h"
43 #include <QtQuick/private/qsgdistancefieldutil_p.h>
44 #include <QtQuick/private/qsgtexture_p.h>
45 #include <QtGui/qopenglfunctions.h>
50 class QSGDistanceFieldTextMaterialShader : public QSGMaterialShader
53 QSGDistanceFieldTextMaterialShader();
55 virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
56 virtual char const *const *attributeNames() const;
59 virtual void initialize();
60 virtual const char *vertexShader() const;
61 virtual const char *fragmentShader() const;
63 void updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc);
69 int m_textureScale_id;
75 const char *QSGDistanceFieldTextMaterialShader::vertexShader() const {
77 "uniform highp mat4 matrix; \n"
78 "uniform highp vec2 textureScale; \n"
79 "attribute highp vec4 vCoord; \n"
80 "attribute highp vec2 tCoord; \n"
81 "varying highp vec2 sampleCoord; \n"
83 " sampleCoord = tCoord * textureScale; \n"
84 " gl_Position = matrix * vCoord; \n"
88 const char *QSGDistanceFieldTextMaterialShader::fragmentShader() const {
90 "varying highp vec2 sampleCoord; \n"
91 "uniform sampler2D texture; \n"
92 "uniform lowp vec4 color; \n"
93 "uniform mediump float alphaMin; \n"
94 "uniform mediump float alphaMax; \n"
96 " gl_FragColor = color * smoothstep(alphaMin, \n"
98 " texture2D(texture, sampleCoord).a); \n"
102 char const *const *QSGDistanceFieldTextMaterialShader::attributeNames() const {
103 static char const *const attr[] = { "vCoord", "tCoord", 0 };
107 QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader()
113 void QSGDistanceFieldTextMaterialShader::updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc)
115 float combinedScale = m_fontScale * m_matrixScale;
116 float base = thresholdFunc(combinedScale);
117 float range = spreadFunc(combinedScale);
119 float alphaMin = qMax(0.0f, base - range);
120 float alphaMax = qMin(base + range, 1.0f);
121 program()->setUniformValue(m_alphaMin_id, GLfloat(alphaMin));
122 program()->setUniformValue(m_alphaMax_id, GLfloat(alphaMax));
125 void QSGDistanceFieldTextMaterialShader::initialize()
127 QSGMaterialShader::initialize();
128 m_matrix_id = program()->uniformLocation("matrix");
129 m_textureScale_id = program()->uniformLocation("textureScale");
130 m_color_id = program()->uniformLocation("color");
131 m_alphaMin_id = program()->uniformLocation("alphaMin");
132 m_alphaMax_id = program()->uniformLocation("alphaMax");
135 void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
137 Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
138 QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
139 QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
141 bool updated = material->updateTextureSize();
144 || material->color() != oldMaterial->color()
145 || state.isOpacityDirty()) {
146 QVector4D color(material->color().redF(), material->color().greenF(),
147 material->color().blueF(), material->color().alphaF());
148 color *= state.opacity();
149 program()->setUniformValue(m_color_id, color);
152 bool updateRange = false;
154 || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale()) {
155 m_fontScale = material->glyphCache()->fontScale();
158 if (state.isMatrixDirty()) {
159 program()->setUniformValue(m_matrix_id, state.combinedMatrix());
160 m_matrixScale = qSqrt(qAbs(state.modelViewMatrix().determinant()));
164 updateAlphaRange(material->glyphCache()->manager()->thresholdFunc(),
165 material->glyphCache()->manager()->antialiasingSpreadFunc());
168 Q_ASSERT(material->glyphCache());
172 || oldMaterial->texture()->textureId != material->texture()->textureId) {
173 program()->setUniformValue(m_textureScale_id, QVector2D(1.0 / material->textureSize().width(),
174 1.0 / material->textureSize().height()));
175 glBindTexture(GL_TEXTURE_2D, material->texture()->textureId);
178 // Set the mag/min filters to be linear. We only need to do this when the texture
179 // has been recreated.
180 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
181 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
188 QSGDistanceFieldTextMaterial::QSGDistanceFieldTextMaterial()
192 setFlag(Blending | RequiresDeterminant, true);
195 QSGDistanceFieldTextMaterial::~QSGDistanceFieldTextMaterial()
199 QSGMaterialType *QSGDistanceFieldTextMaterial::type() const
201 static QSGMaterialType type;
205 QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader() const
207 return new QSGDistanceFieldTextMaterialShader;
210 bool QSGDistanceFieldTextMaterial::updateTextureSize()
213 m_texture = m_glyph_cache->glyphTexture(-1); // invalid texture
215 if (m_texture->size != m_size) {
216 m_size = m_texture->size;
223 int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const
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_glyph_cache->fontScale() != other->m_glyph_cache->fontScale()) {
230 qreal s1 = m_glyph_cache->fontScale();
231 qreal s2 = other->m_glyph_cache->fontScale();
232 return int(s2 < s1) - int(s1 < s2);
234 QRgb c1 = m_color.rgba();
235 QRgb c2 = other->m_color.rgba();
236 return int(c2 < c1) - int(c1 < c2);
240 class DistanceFieldStyledTextMaterialShader : public QSGDistanceFieldTextMaterialShader
243 DistanceFieldStyledTextMaterialShader();
245 virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
248 virtual void initialize();
249 virtual const char *fragmentShader() const = 0;
254 DistanceFieldStyledTextMaterialShader::DistanceFieldStyledTextMaterialShader()
255 : QSGDistanceFieldTextMaterialShader()
259 void DistanceFieldStyledTextMaterialShader::initialize()
261 QSGDistanceFieldTextMaterialShader::initialize();
262 m_styleColor_id = program()->uniformLocation("styleColor");
265 void DistanceFieldStyledTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
267 QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect);
269 QSGDistanceFieldStyledTextMaterial *material = static_cast<QSGDistanceFieldStyledTextMaterial *>(newEffect);
270 QSGDistanceFieldStyledTextMaterial *oldMaterial = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldEffect);
273 || material->styleColor() != oldMaterial->styleColor()
274 || (state.isOpacityDirty())) {
275 QVector4D color(material->styleColor().redF(), material->styleColor().greenF(),
276 material->styleColor().blueF(), material->styleColor().alphaF());
277 color *= state.opacity();
278 program()->setUniformValue(m_styleColor_id, color);
282 QSGDistanceFieldStyledTextMaterial::QSGDistanceFieldStyledTextMaterial()
283 : QSGDistanceFieldTextMaterial()
287 QSGDistanceFieldStyledTextMaterial::~QSGDistanceFieldStyledTextMaterial()
291 int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const
293 Q_ASSERT(o && type() == o->type());
294 const QSGDistanceFieldStyledTextMaterial *other = static_cast<const QSGDistanceFieldStyledTextMaterial *>(o);
295 if (m_styleColor != other->m_styleColor) {
296 QRgb c1 = m_styleColor.rgba();
297 QRgb c2 = other->m_styleColor.rgba();
298 return int(c2 < c1) - int(c1 < c2);
300 return QSGDistanceFieldTextMaterial::compare(o);
304 class DistanceFieldOutlineTextMaterialShader : public DistanceFieldStyledTextMaterialShader
307 DistanceFieldOutlineTextMaterialShader();
309 virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
312 virtual void initialize();
313 virtual const char *fragmentShader() const;
315 void updateOutlineAlphaRange(int dfRadius);
317 int m_outlineAlphaMax0_id;
318 int m_outlineAlphaMax1_id;
321 const char *DistanceFieldOutlineTextMaterialShader::fragmentShader() const {
323 "varying highp vec2 sampleCoord; \n"
324 "uniform sampler2D texture; \n"
325 "uniform lowp vec4 color; \n"
326 "uniform lowp vec4 styleColor; \n"
327 "uniform mediump float alphaMin; \n"
328 "uniform mediump float alphaMax; \n"
329 "uniform mediump float outlineAlphaMax0; \n"
330 "uniform mediump float outlineAlphaMax1; \n"
332 " mediump float d = texture2D(texture, sampleCoord).a; \n"
333 " gl_FragColor = mix(styleColor, color, smoothstep(alphaMin, alphaMax, d)) \n"
334 " * smoothstep(outlineAlphaMax0, outlineAlphaMax1, d); \n"
338 DistanceFieldOutlineTextMaterialShader::DistanceFieldOutlineTextMaterialShader()
339 : DistanceFieldStyledTextMaterialShader()
343 void DistanceFieldOutlineTextMaterialShader::initialize()
345 DistanceFieldStyledTextMaterialShader::initialize();
346 m_outlineAlphaMax0_id = program()->uniformLocation("outlineAlphaMax0");
347 m_outlineAlphaMax1_id = program()->uniformLocation("outlineAlphaMax1");
350 void DistanceFieldOutlineTextMaterialShader::updateOutlineAlphaRange(int dfRadius)
352 qreal outlineLimit = qMax(qreal(0.2), qreal(0.5 - 0.5 / dfRadius / m_fontScale));
354 qreal combinedScale = m_fontScale * m_matrixScale;
355 qreal alphaMin = qMax(0.0, 0.5 - 0.07 / combinedScale);
356 qreal styleAlphaMin0 = qMax(0.0, outlineLimit - 0.07 / combinedScale);
357 qreal styleAlphaMin1 = qMin(qreal(outlineLimit + 0.07 / combinedScale), alphaMin);
358 program()->setUniformValue(m_outlineAlphaMax0_id, GLfloat(styleAlphaMin0));
359 program()->setUniformValue(m_outlineAlphaMax1_id, GLfloat(styleAlphaMin1));
362 void DistanceFieldOutlineTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
364 DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect);
366 QSGDistanceFieldOutlineTextMaterial *material = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newEffect);
367 QSGDistanceFieldOutlineTextMaterial *oldMaterial = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldEffect);
370 || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale()
371 || state.isMatrixDirty())
372 updateOutlineAlphaRange(material->glyphCache()->distanceFieldRadius());
376 QSGDistanceFieldOutlineTextMaterial::QSGDistanceFieldOutlineTextMaterial()
377 : QSGDistanceFieldStyledTextMaterial()
381 QSGDistanceFieldOutlineTextMaterial::~QSGDistanceFieldOutlineTextMaterial()
385 QSGMaterialType *QSGDistanceFieldOutlineTextMaterial::type() const
387 static QSGMaterialType type;
391 QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader() const
393 return new DistanceFieldOutlineTextMaterialShader;
397 class DistanceFieldShiftedStyleTextMaterialShader : public DistanceFieldStyledTextMaterialShader
400 DistanceFieldShiftedStyleTextMaterialShader();
402 virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
405 virtual void initialize();
406 virtual const char *vertexShader() const;
407 virtual const char *fragmentShader() const;
409 void updateShift(const QSGDistanceFieldGlyphCache *cache, const QPointF& shift);
414 DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader()
415 : DistanceFieldStyledTextMaterialShader()
419 void DistanceFieldShiftedStyleTextMaterialShader::initialize()
421 DistanceFieldStyledTextMaterialShader::initialize();
422 m_shift_id = program()->uniformLocation("shift");
425 void DistanceFieldShiftedStyleTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
427 DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect);
429 QSGDistanceFieldShiftedStyleTextMaterial *material = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(newEffect);
430 QSGDistanceFieldShiftedStyleTextMaterial *oldMaterial = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(oldEffect);
433 || oldMaterial->glyphCache()->fontScale() != material->glyphCache()->fontScale()
434 || oldMaterial->shift() != material->shift()
435 || oldMaterial->textureSize() != material->textureSize()) {
436 updateShift(material->glyphCache(), material->shift());
440 void DistanceFieldShiftedStyleTextMaterialShader::updateShift(const QSGDistanceFieldGlyphCache *cache, const QPointF &shift)
442 QPointF texel(1.0 / cache->fontScale() * shift.x(),
443 1.0 / cache->fontScale() * shift.y());
444 program()->setUniformValue(m_shift_id, texel);
447 const char *DistanceFieldShiftedStyleTextMaterialShader::vertexShader() const
450 "uniform highp mat4 matrix; \n"
451 "uniform highp vec2 textureScale; \n"
452 "attribute highp vec4 vCoord; \n"
453 "attribute highp vec2 tCoord; \n"
454 "uniform highp vec2 shift; \n"
455 "varying highp vec2 sampleCoord; \n"
456 "varying highp vec2 shiftedSampleCoord; \n"
458 " sampleCoord = tCoord * textureScale; \n"
459 " shiftedSampleCoord = (tCoord - shift) * textureScale; \n"
460 " gl_Position = matrix * vCoord; \n"
464 const char *DistanceFieldShiftedStyleTextMaterialShader::fragmentShader() const {
466 "varying highp vec2 sampleCoord; \n"
467 "varying highp vec2 shiftedSampleCoord; \n"
468 "uniform sampler2D texture; \n"
469 "uniform lowp vec4 color; \n"
470 "uniform lowp vec4 styleColor; \n"
471 "uniform mediump float alphaMin; \n"
472 "uniform mediump float alphaMax; \n"
474 " highp float a = smoothstep(alphaMin, alphaMax, texture2D(texture, sampleCoord).a);\n"
475 " highp vec4 shifted = styleColor * smoothstep(alphaMin, \n"
477 " texture2D(texture, shiftedSampleCoord).a); \n"
478 " gl_FragColor = mix(shifted, color, a); \n"
482 QSGDistanceFieldShiftedStyleTextMaterial::QSGDistanceFieldShiftedStyleTextMaterial()
483 : QSGDistanceFieldStyledTextMaterial()
487 QSGDistanceFieldShiftedStyleTextMaterial::~QSGDistanceFieldShiftedStyleTextMaterial()
491 QSGMaterialType *QSGDistanceFieldShiftedStyleTextMaterial::type() const
493 static QSGMaterialType type;
497 QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() const
499 return new DistanceFieldShiftedStyleTextMaterialShader;
503 class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader
506 virtual void initialize();
507 virtual void activate();
508 virtual void deactivate();
509 virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
512 virtual const char *vertexShader() const;
513 virtual const char *fragmentShader() const;
520 const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
522 "uniform highp mat4 matrix; \n"
523 "uniform highp vec2 textureScale; \n"
524 "uniform highp float fontScale; \n"
525 "uniform highp vec4 vecDelta; \n"
526 "attribute highp vec4 vCoord; \n"
527 "attribute highp vec2 tCoord; \n"
528 "varying highp vec2 sampleCoord; \n"
529 "varying highp vec3 sampleFarLeft; \n"
530 "varying highp vec3 sampleNearLeft; \n"
531 "varying highp vec3 sampleNearRight; \n"
532 "varying highp vec3 sampleFarRight; \n"
534 " sampleCoord = tCoord * textureScale; \n"
535 " gl_Position = matrix * vCoord; \n"
536 // Calculate neighbour pixel position in item space.
537 " highp vec3 wDelta = gl_Position.w * vecDelta.xyw; \n"
538 " highp vec3 farLeft = vCoord.xyw - 0.667 * wDelta; \n"
539 " highp vec3 nearLeft = vCoord.xyw - 0.333 * wDelta; \n"
540 " highp vec3 nearRight = vCoord.xyw + 0.333 * wDelta; \n"
541 " highp vec3 farRight = vCoord.xyw + 0.667 * wDelta; \n"
542 // Calculate neighbour texture coordinate.
543 " highp vec2 scale = textureScale / fontScale; \n"
544 " highp vec2 base = sampleCoord - scale * vCoord.xy; \n"
545 " sampleFarLeft = vec3(base * farLeft.z + scale * farLeft.xy, farLeft.z); \n"
546 " sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z); \n"
547 " sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z); \n"
548 " sampleFarRight = vec3(base * farRight.z + scale * farRight.xy, farRight.z); \n"
552 const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
554 "varying highp vec2 sampleCoord; \n"
555 "varying highp vec3 sampleFarLeft; \n"
556 "varying highp vec3 sampleNearLeft; \n"
557 "varying highp vec3 sampleNearRight; \n"
558 "varying highp vec3 sampleFarRight; \n"
559 "uniform sampler2D texture; \n"
560 "uniform lowp vec4 color; \n"
561 "uniform mediump float alphaMin; \n"
562 "uniform mediump float alphaMax; \n"
565 " n.x = texture2DProj(texture, sampleFarLeft).a; \n"
566 " n.y = texture2DProj(texture, sampleNearLeft).a; \n"
567 " highp float c = texture2D(texture, sampleCoord).a; \n"
568 " n.z = texture2DProj(texture, sampleNearRight).a; \n"
569 " n.w = texture2DProj(texture, sampleFarRight).a; \n"
572 " n = smoothstep(alphaMin, alphaMax, n); \n"
573 " c = smoothstep(alphaMin, alphaMax, c); \n"
576 " highp vec2 d = min(abs(n.yw - n.xz) * 2., 0.67); \n"
577 " highp vec2 lo = mix(vec2(alphaMin), vec2(0.5), d); \n"
578 " highp vec2 hi = mix(vec2(alphaMax), vec2(0.5), d); \n"
579 " n = smoothstep(lo.xxyy, hi.xxyy, n); \n"
580 " c = smoothstep(lo.x + lo.y, hi.x + hi.y, 2. * c); \n"
582 " gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w; \n"
586 //const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
588 // "#extension GL_OES_standard_derivatives: enable \n"
589 // "varying highp vec2 sampleCoord; \n"
590 // "uniform sampler2D texture; \n"
591 // "uniform lowp vec4 color; \n"
592 // "uniform highp float alphaMin; \n"
593 // "uniform highp float alphaMax; \n"
594 // "void main() { \n"
595 // " highp vec2 delta = dFdx(sampleCoord); \n"
596 // " highp vec4 n; \n"
597 // " n.x = texture2D(texture, sampleCoord - 0.667 * delta).a; \n"
598 // " n.y = texture2D(texture, sampleCoord - 0.333 * delta).a; \n"
599 // " highp float c = texture2D(texture, sampleCoord).a; \n"
600 // " n.z = texture2D(texture, sampleCoord + 0.333 * delta).a; \n"
601 // " n.w = texture2D(texture, sampleCoord + 0.667 * delta).a; \n"
602 // " n = smoothstep(alphaMin, alphaMax, n); \n"
603 // " c = smoothstep(alphaMin, alphaMax, c); \n"
604 // " gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w; \n"
608 void QSGHiQSubPixelDistanceFieldTextMaterialShader::initialize()
610 QSGDistanceFieldTextMaterialShader::initialize();
611 m_fontScale_id = program()->uniformLocation("fontScale");
612 m_vecDelta_id = program()->uniformLocation("vecDelta");
615 void QSGHiQSubPixelDistanceFieldTextMaterialShader::activate()
617 QSGDistanceFieldTextMaterialShader::activate();
618 glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
621 void QSGHiQSubPixelDistanceFieldTextMaterialShader::deactivate()
623 QSGDistanceFieldTextMaterialShader::deactivate();
624 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
627 void QSGHiQSubPixelDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
629 Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
630 QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
631 QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
633 if (oldMaterial == 0 || material->color() != oldMaterial->color()) {
634 QColor c = material->color();
635 state.context()->functions()->glBlendColor(c.redF(), c.greenF(), c.blueF(), 1.0f);
638 if (oldMaterial == 0 || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale())
639 program()->setUniformValue(m_fontScale_id, GLfloat(material->glyphCache()->fontScale()));
641 if (oldMaterial == 0 || state.isMatrixDirty()) {
642 int viewportWidth = state.viewportRect().width();
643 QMatrix4x4 mat = state.combinedMatrix().inverted();
644 program()->setUniformValue(m_vecDelta_id, mat.column(0) * (qreal(2) / viewportWidth));
647 QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect);
650 QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const
652 static QSGMaterialType type;
656 QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader() const
658 return new QSGHiQSubPixelDistanceFieldTextMaterialShader;
662 class QSGLoQSubPixelDistanceFieldTextMaterialShader : public QSGHiQSubPixelDistanceFieldTextMaterialShader
665 virtual const char *vertexShader() const;
666 virtual const char *fragmentShader() const;
669 const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
671 "uniform highp mat4 matrix; \n"
672 "uniform highp vec2 textureScale; \n"
673 "uniform highp float fontScale; \n"
674 "uniform highp vec4 vecDelta; \n"
675 "attribute highp vec4 vCoord; \n"
676 "attribute highp vec2 tCoord; \n"
677 "varying highp vec3 sampleNearLeft; \n"
678 "varying highp vec3 sampleNearRight; \n"
680 " highp vec2 sampleCoord = tCoord * textureScale; \n"
681 " gl_Position = matrix * vCoord; \n"
682 // Calculate neighbour pixel position in item space.
683 " highp vec3 wDelta = gl_Position.w * vecDelta.xyw; \n"
684 " highp vec3 nearLeft = vCoord.xyw - 0.25 * wDelta; \n"
685 " highp vec3 nearRight = vCoord.xyw + 0.25 * wDelta; \n"
686 // Calculate neighbour texture coordinate.
687 " highp vec2 scale = textureScale / fontScale; \n"
688 " highp vec2 base = sampleCoord - scale * vCoord.xy; \n"
689 " sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z); \n"
690 " sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z); \n"
694 const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
696 "varying highp vec3 sampleNearLeft; \n"
697 "varying highp vec3 sampleNearRight; \n"
698 "uniform sampler2D texture; \n"
699 "uniform lowp vec4 color; \n"
700 "uniform mediump float alphaMin; \n"
701 "uniform mediump float alphaMax; \n"
704 " n.x = texture2DProj(texture, sampleNearLeft).a; \n"
705 " n.y = texture2DProj(texture, sampleNearRight).a; \n"
706 " n = smoothstep(alphaMin, alphaMax, n); \n"
707 " highp float c = 0.5 * (n.x + n.y); \n"
708 " gl_FragColor = vec4(n.x, c, n.y, c) * color.w; \n"
712 QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const
714 static QSGMaterialType type;
718 QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader() const
720 return new QSGLoQSubPixelDistanceFieldTextMaterialShader;