aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp')
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp655
1 files changed, 322 insertions, 333 deletions
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
index aa58218505..afb41f32e4 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -1,92 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgdistancefieldglyphnode_p_p.h"
-#include <QtQuick/private/qsgtexture_p.h>
-#include <QtGui/qopenglfunctions.h>
+#include "qsgrhidistancefieldglyphcache_p.h"
#include <QtGui/qsurface.h>
#include <QtGui/qwindow.h>
#include <qmath.h>
QT_BEGIN_NAMESPACE
-class QSGDistanceFieldTextMaterialShader : public QSGMaterialShader
-{
-public:
- QSGDistanceFieldTextMaterialShader();
-
- void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
- char const *const *attributeNames() const override;
-
-protected:
- void initialize() override;
-
- void updateAlphaRange();
- void updateColor(const QVector4D &c);
- void updateTextureScale(const QVector2D &ts);
-
- float m_fontScale = 1.0;
- float m_matrixScale = 1.0;
-
- int m_matrix_id = -1;
- int m_textureScale_id = -1;
- int m_alphaMin_id = -1;
- int m_alphaMax_id = -1;
- int m_color_id = -1;
-
- QVector2D m_lastTextureScale;
- QVector4D m_lastColor;
- float m_lastAlphaMin = -1;
- float m_lastAlphaMax = -1;
-};
-
-char const *const *QSGDistanceFieldTextMaterialShader::attributeNames() const {
- static char const *const attr[] = { "vCoord", "tCoord", nullptr };
- return attr;
-}
-
-QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader()
-{
- setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldtext.vert"));
- setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldtext.frag"));
-}
-
static float qt_sg_envFloat(const char *name, float defaultValue)
{
if (Q_LIKELY(!qEnvironmentVariableIsSet(name)))
@@ -111,112 +33,140 @@ static float spreadFunc(float glyphScale)
return range / glyphScale;
}
-void QSGDistanceFieldTextMaterialShader::updateAlphaRange()
+class QSGDistanceFieldTextMaterialRhiShader : public QSGMaterialShader
{
- float combinedScale = m_fontScale * m_matrixScale;
- float base = thresholdFunc(combinedScale);
- float range = spreadFunc(combinedScale);
- float alphaMin = qMax(0.0f, base - range);
- float alphaMax = qMin(base + range, 1.0f);
- if (alphaMin != m_lastAlphaMin) {
- program()->setUniformValue(m_alphaMin_id, GLfloat(alphaMin));
- m_lastAlphaMin = alphaMin;
- }
- if (alphaMax != m_lastAlphaMax) {
- program()->setUniformValue(m_alphaMax_id, GLfloat(alphaMax));
- m_lastAlphaMax = alphaMax;
- }
-}
+public:
+ QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount);
-void QSGDistanceFieldTextMaterialShader::updateColor(const QVector4D &c)
-{
- if (m_lastColor != c) {
- program()->setUniformValue(m_color_id, c);
- m_lastColor = c;
- }
-}
+ bool updateUniformData(RenderState &state,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
-void QSGDistanceFieldTextMaterialShader::updateTextureScale(const QVector2D &ts)
-{
- if (m_lastTextureScale != ts) {
- program()->setUniformValue(m_textureScale_id, ts);
- m_lastTextureScale = ts;
- }
-}
+ void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
-void QSGDistanceFieldTextMaterialShader::initialize()
+protected:
+ float m_fontScale = 1.0;
+ float m_matrixScale = 1.0;
+ quint32 m_currentUbufOffset;
+};
+
+QSGDistanceFieldTextMaterialRhiShader::QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount)
{
- QSGMaterialShader::initialize();
- m_matrix_id = program()->uniformLocation("matrix");
- m_textureScale_id = program()->uniformLocation("textureScale");
- m_color_id = program()->uniformLocation("color");
- m_alphaMin_id = program()->uniformLocation("alphaMin");
- m_alphaMax_id = program()->uniformLocation("alphaMax");
+ setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"), viewCount);
+ if (alphaTexture)
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a.frag.qsb"), viewCount);
+ else
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.frag.qsb"), viewCount);
}
-void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
- Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type());
- QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
- QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
+ Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type());
+ QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial);
+ QSGDistanceFieldTextMaterial *oldMat = static_cast<QSGDistanceFieldTextMaterial *>(oldMaterial);
- bool updated = material->updateTextureSize();
+ // updateUniformData() is called before updateSampledImage() by the
+ // renderer. Hence updating the glyph cache stuff here.
+ const bool textureUpdated = mat->updateTextureSizeAndWrapper();
+ Q_ASSERT(mat->wrapperTexture());
+ Q_ASSERT(oldMat == nullptr || oldMat->texture());
- if (oldMaterial == nullptr
- || material->color() != oldMaterial->color()
- || state.isOpacityDirty()) {
- QVector4D color = material->color();
- color *= state.opacity();
- updateColor(color);
- }
+ bool changed = false;
+ QByteArray *buf = state.uniformData();
+ Q_ASSERT(buf->size() >= 104);
bool updateRange = false;
- if (oldMaterial == nullptr
- || material->fontScale() != oldMaterial->fontScale()) {
- m_fontScale = material->fontScale();
+ if (!oldMat || mat->fontScale() != oldMat->fontScale()) {
+ m_fontScale = mat->fontScale();
updateRange = true;
}
if (state.isMatrixDirty()) {
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
m_matrixScale = qSqrt(qAbs(state.determinant())) * state.devicePixelRatio();
updateRange = true;
}
- if (updateRange) {
- updateAlphaRange();
+ quint32 offset = 0;
+ const int matrixCount = qMin(state.projectionMatrixCount(), newMaterial->viewCount());
+ for (int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) {
+ if (state.isMatrixDirty()) {
+ const QMatrix4x4 m = state.combinedMatrix(viewIndex);
+ memcpy(buf->data() + 64 * viewIndex, m.constData(), 64);
+ changed = true;
+ }
+ offset += 64;
+ }
+ if (textureUpdated || !oldMat || oldMat->texture()->texture != mat->texture()->texture) {
+ const QVector2D ts(1.0f / mat->textureSize().width(), 1.0f / mat->textureSize().height());
+ Q_ASSERT(sizeof(ts) == 8);
+ memcpy(buf->data() + offset, &ts, 8);
+ changed = true;
+ }
+ offset += 8 + 8; // 8 is padding for vec4 alignment
+ if (!oldMat || mat->color() != oldMat->color() || state.isOpacityDirty()) {
+ const QVector4D color = mat->color() * state.opacity();
+ Q_ASSERT(sizeof(color) == 16);
+ memcpy(buf->data() + offset, &color, 16);
+ changed = true;
}
+ offset += 16;
+ if (updateRange) { // deferred because depends on m_fontScale and m_matrixScale
+ const float combinedScale = m_fontScale * m_matrixScale;
+ const float base = thresholdFunc(combinedScale);
+ const float range = spreadFunc(combinedScale);
+ const QVector2D alphaMinMax(qMax(0.0f, base - range), qMin(base + range, 1.0f));
+ memcpy(buf->data() + offset, &alphaMinMax, 8);
+ changed = true;
+ }
+ offset += 8; // not adding any padding here since we are not sure what comes afterwards in the subclasses' shaders
- Q_ASSERT(material->glyphCache());
+ // move texture uploads/copies onto the renderer's soon-to-be-committed list
+ static_cast<QSGRhiDistanceFieldGlyphCache *>(mat->glyphCache())->commitResourceUpdates(state.resourceUpdateBatch());
- if (updated
- || oldMaterial == nullptr
- || oldMaterial->texture()->textureId != material->texture()->textureId) {
- updateTextureScale(QVector2D(1.0 / material->textureSize().width(),
- 1.0 / material->textureSize().height()));
+ m_currentUbufOffset = offset;
+ return changed;
+}
- QOpenGLFunctions *funcs = state.context()->functions();
- funcs->glBindTexture(GL_TEXTURE_2D, material->texture()->textureId);
+void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
+ QSGMaterial *newMaterial, QSGMaterial *)
+{
+ Q_UNUSED(state);
+ if (binding != 1)
+ return;
- if (updated) {
- // Set the mag/min filters to be linear. We only need to do this when the texture
- // has been recreated.
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- }
+ QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial);
+ QSGTexture *t = mat->wrapperTexture();
+ t->setFiltering(QSGTexture::Linear);
+ *texture = t;
+}
+
+class DistanceFieldAnisotropicTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader
+{
+public:
+ DistanceFieldAnisotropicTextMaterialRhiShader(bool alphaTexture, int viewCount);
+};
+
+DistanceFieldAnisotropicTextMaterialRhiShader::DistanceFieldAnisotropicTextMaterialRhiShader(bool alphaTexture, int viewCount)
+ : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount)
+{
+ setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"), viewCount);
+ if (alphaTexture)
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag.qsb"), viewCount);
+ else
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_fwidth.frag.qsb"), viewCount);
}
QSGDistanceFieldTextMaterial::QSGDistanceFieldTextMaterial()
: m_glyph_cache(nullptr)
, m_texture(nullptr)
, m_fontScale(1.0)
+ , m_sgTexture(nullptr)
{
setFlag(Blending | RequiresDeterminant, true);
}
QSGDistanceFieldTextMaterial::~QSGDistanceFieldTextMaterial()
{
+ delete m_sgTexture;
}
QSGMaterialType *QSGDistanceFieldTextMaterial::type() const
@@ -227,15 +177,17 @@ QSGMaterialType *QSGDistanceFieldTextMaterial::type() const
void QSGDistanceFieldTextMaterial::setColor(const QColor &color)
{
- m_color = QVector4D(color.redF() * color.alphaF(),
- color.greenF() * color.alphaF(),
- color.blueF() * color.alphaF(),
- color.alphaF());
+ float r, g, b, a;
+ color.getRgbF(&r, &g, &b, &a);
+ m_color = QVector4D(r * a, g * a, b * a, a);
}
-QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader() const
+QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
{
- return new QSGDistanceFieldTextMaterialShader;
+ if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
+ return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
+ else
+ return new QSGDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
}
bool QSGDistanceFieldTextMaterial::updateTextureSize()
@@ -246,9 +198,26 @@ bool QSGDistanceFieldTextMaterial::updateTextureSize()
if (m_texture->size != m_size) {
m_size = m_texture->size;
return true;
- } else {
- return false;
}
+
+ return false;
+}
+
+// When using the RHI we need a QSGTexture wrapping the QRhiTexture, just
+// exposing a QRhiTexture * (which would be the equivalent of GLuint textureId)
+// is not sufficient to play nice with the material.
+bool QSGDistanceFieldTextMaterial::updateTextureSizeAndWrapper()
+{
+ bool updated = updateTextureSize();
+ if (updated) {
+ if (m_sgTexture)
+ delete m_sgTexture;
+ m_sgTexture = new QSGPlainTexture;
+ m_sgTexture->setTexture(m_texture->texture);
+ m_sgTexture->setTextureSize(m_size);
+ m_sgTexture->setOwnsTexture(false);
+ }
+ return updated;
}
int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const
@@ -262,50 +231,47 @@ int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const
}
if (m_color != other->m_color)
return &m_color < &other->m_color ? -1 : 1;
- int t0 = m_texture ? m_texture->textureId : 0;
- int t1 = other->m_texture ? other->m_texture->textureId : 0;
- return t0 - t1;
+ qintptr t0 = m_texture ? qintptr(m_texture->texture) : 0;
+ qintptr t1 = other->m_texture ? qintptr(other->m_texture->texture) : 0;
+ const qintptr diff = t0 - t1;
+ return diff < 0 ? -1 : (diff > 0 ? 1 : 0);
}
-
-
-class DistanceFieldStyledTextMaterialShader : public QSGDistanceFieldTextMaterialShader
+class DistanceFieldStyledTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader
{
public:
- DistanceFieldStyledTextMaterialShader();
-
- void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
-
-protected:
- void initialize() override;
+ DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture, int viewCount);
- int m_styleColor_id = -1;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
-DistanceFieldStyledTextMaterialShader::DistanceFieldStyledTextMaterialShader()
- : QSGDistanceFieldTextMaterialShader()
+DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture, int viewCount)
+ : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount)
{
}
-void DistanceFieldStyledTextMaterialShader::initialize()
+bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(RenderState &state,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
- QSGDistanceFieldTextMaterialShader::initialize();
- m_styleColor_id = program()->uniformLocation("styleColor");
-}
+ bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
+ QSGDistanceFieldStyledTextMaterial *mat = static_cast<QSGDistanceFieldStyledTextMaterial *>(newMaterial);
+ QSGDistanceFieldStyledTextMaterial *oldMat = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldMaterial);
-void DistanceFieldStyledTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect);
+ QByteArray *buf = state.uniformData();
+ Q_ASSERT(buf->size() >= 128);
+
+ // must add 8 bytes padding for vec4 alignment, the base class did not do this
+ m_currentUbufOffset += 8; // now at StyleColor
- QSGDistanceFieldStyledTextMaterial *material = static_cast<QSGDistanceFieldStyledTextMaterial *>(newEffect);
- QSGDistanceFieldStyledTextMaterial *oldMaterial = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldEffect);
+ if (!oldMat || mat->styleColor() != oldMat->styleColor() || state.isOpacityDirty()) {
+ QVector4D styleColor = mat->styleColor();
+ styleColor *= state.opacity();
- if (oldMaterial == nullptr
- || material->styleColor() != oldMaterial->styleColor()
- || (state.isOpacityDirty())) {
- QVector4D color = material->styleColor();
- color *= state.opacity();
- program()->setUniformValue(m_styleColor_id, color);
+ memcpy(buf->data() + m_currentUbufOffset, &styleColor, 16);
+ changed = true;
}
+ m_currentUbufOffset += 16;
+
+ return changed;
}
QSGDistanceFieldStyledTextMaterial::QSGDistanceFieldStyledTextMaterial()
@@ -319,10 +285,9 @@ QSGDistanceFieldStyledTextMaterial::~QSGDistanceFieldStyledTextMaterial()
void QSGDistanceFieldStyledTextMaterial::setStyleColor(const QColor &color)
{
- m_styleColor = QVector4D(color.redF() * color.alphaF(),
- color.greenF() * color.alphaF(),
- color.blueF() * color.alphaF(),
- color.alphaF());
+ float r, g, b, a;
+ color.getRgbF(&r, &g, &b, &a);
+ m_styleColor = QVector4D(r * a, g * a, b * a, a);
}
int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const
@@ -334,64 +299,67 @@ int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const
return QSGDistanceFieldTextMaterial::compare(o);
}
-
-class DistanceFieldOutlineTextMaterialShader : public DistanceFieldStyledTextMaterialShader
+class DistanceFieldOutlineTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader
{
public:
- DistanceFieldOutlineTextMaterialShader();
+ DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount);
- void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
-
-protected:
- void initialize() override;
-
- void updateOutlineAlphaRange(int dfRadius);
-
- int m_outlineAlphaMax0_id = -1;
- int m_outlineAlphaMax1_id = -1;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
-DistanceFieldOutlineTextMaterialShader::DistanceFieldOutlineTextMaterialShader()
- : DistanceFieldStyledTextMaterialShader()
+DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount)
+ : DistanceFieldStyledTextMaterialRhiShader(alphaTexture, viewCount)
{
- setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldoutlinetext.frag"));
+ setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"), viewCount);
+ if (alphaTexture)
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag.qsb"), viewCount);
+ else
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsb"), viewCount);
}
-void DistanceFieldOutlineTextMaterialShader::initialize()
+class DistanceFieldAnisotropicOutlineTextMaterialRhiShader : public DistanceFieldOutlineTextMaterialRhiShader
{
- DistanceFieldStyledTextMaterialShader::initialize();
- m_outlineAlphaMax0_id = program()->uniformLocation("outlineAlphaMax0");
- m_outlineAlphaMax1_id = program()->uniformLocation("outlineAlphaMax1");
-}
-
-void DistanceFieldOutlineTextMaterialShader::updateOutlineAlphaRange(int dfRadius)
-{
- float combinedScale = m_fontScale * m_matrixScale;
- float base = thresholdFunc(combinedScale);
- float range = spreadFunc(combinedScale);
- float outlineLimit = qMax(0.2f, base - 0.5f / dfRadius / m_fontScale);
-
- float alphaMin = qMax(0.0f, base - range);
- float styleAlphaMin0 = qMax(0.0f, outlineLimit - range);
- float styleAlphaMin1 = qMin(outlineLimit + range, alphaMin);
- program()->setUniformValue(m_outlineAlphaMax0_id, GLfloat(styleAlphaMin0));
- program()->setUniformValue(m_outlineAlphaMax1_id, GLfloat(styleAlphaMin1));
-}
-
-void DistanceFieldOutlineTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect);
+public:
+ DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount);
+};
- QSGDistanceFieldOutlineTextMaterial *material = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newEffect);
- QSGDistanceFieldOutlineTextMaterial *oldMaterial = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldEffect);
+DistanceFieldAnisotropicOutlineTextMaterialRhiShader::DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount)
+ : DistanceFieldOutlineTextMaterialRhiShader(alphaTexture, viewCount)
+{
+ setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"), viewCount);
+ if (alphaTexture)
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag.qsb"), viewCount);
+ else
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag.qsb"), viewCount);
+}
+
+bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(RenderState &state,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+{
+ bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
+ QSGDistanceFieldOutlineTextMaterial *mat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newMaterial);
+ QSGDistanceFieldOutlineTextMaterial *oldMat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldMaterial);
+
+ QByteArray *buf = state.uniformData();
+ Q_ASSERT(buf->size() >= 136);
+
+ if (!oldMat || mat->fontScale() != oldMat->fontScale() || state.isMatrixDirty()) {
+ float dfRadius = mat->glyphCache()->distanceFieldRadius();
+ float combinedScale = m_fontScale * m_matrixScale;
+ float base = thresholdFunc(combinedScale);
+ float range = spreadFunc(combinedScale);
+ float outlineLimit = qMax(0.2f, base - 0.5f / dfRadius / m_fontScale);
+ float alphaMin = qMax(0.0f, base - range);
+ float styleAlphaMin0 = qMax(0.0f, outlineLimit - range);
+ float styleAlphaMin1 = qMin(outlineLimit + range, alphaMin);
+ memcpy(buf->data() + m_currentUbufOffset, &styleAlphaMin0, 4);
+ memcpy(buf->data() + m_currentUbufOffset + 4, &styleAlphaMin1, 4);
+ changed = true;
+ }
- if (oldMaterial == nullptr
- || material->fontScale() != oldMaterial->fontScale()
- || state.isMatrixDirty())
- updateOutlineAlphaRange(material->glyphCache()->distanceFieldRadius());
+ return changed;
}
-
QSGDistanceFieldOutlineTextMaterial::QSGDistanceFieldOutlineTextMaterial()
: QSGDistanceFieldStyledTextMaterial()
{
@@ -407,60 +375,68 @@ QSGMaterialType *QSGDistanceFieldOutlineTextMaterial::type() const
return &type;
}
-QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader() const
+QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
{
- return new DistanceFieldOutlineTextMaterialShader;
+ if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
+ return new DistanceFieldAnisotropicOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
+ else
+ return new DistanceFieldOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
}
-
-class DistanceFieldShiftedStyleTextMaterialShader : public DistanceFieldStyledTextMaterialShader
+class DistanceFieldShiftedStyleTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader
{
public:
- DistanceFieldShiftedStyleTextMaterialShader();
-
- void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
-
-protected:
- void initialize() override;
-
- void updateShift(qreal fontScale, const QPointF& shift);
+ DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture, int viewCount);
- int m_shift_id = -1;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
-DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader()
- : DistanceFieldStyledTextMaterialShader()
+DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture, int viewCount)
+ : DistanceFieldStyledTextMaterialRhiShader(alphaTexture, viewCount)
{
- setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldshiftedtext.vert"));
- setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldshiftedtext.frag"));
+ setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"), viewCount);
+ if (alphaTexture)
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag.qsb"), viewCount);
+ else
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb"), viewCount);
}
-void DistanceFieldShiftedStyleTextMaterialShader::initialize()
+bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(RenderState &state,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
- DistanceFieldStyledTextMaterialShader::initialize();
- m_shift_id = program()->uniformLocation("shift");
-}
+ bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
+ QSGDistanceFieldShiftedStyleTextMaterial *mat = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(newMaterial);
+ QSGDistanceFieldShiftedStyleTextMaterial *oldMat = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(oldMaterial);
-void DistanceFieldShiftedStyleTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect);
+ QByteArray *buf = state.uniformData();
+ Q_ASSERT(buf->size() >= 136);
- QSGDistanceFieldShiftedStyleTextMaterial *material = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(newEffect);
- QSGDistanceFieldShiftedStyleTextMaterial *oldMaterial = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(oldEffect);
-
- if (oldMaterial == nullptr
- || oldMaterial->fontScale() != material->fontScale()
- || oldMaterial->shift() != material->shift()
- || oldMaterial->textureSize() != material->textureSize()) {
- updateShift(material->fontScale(), material->shift());
+ if (!oldMat || oldMat->fontScale() != mat->fontScale() || oldMat->shift() != mat->shift()
+ || oldMat->textureSize() != mat->textureSize())
+ {
+ QVector2D shift(1.0 / mat->fontScale() * mat->shift().x(),
+ 1.0 / mat->fontScale() * mat->shift().y());
+ memcpy(buf->data() + m_currentUbufOffset, &shift, 8);
+ changed = true;
}
+
+ return changed;
}
-void DistanceFieldShiftedStyleTextMaterialShader::updateShift(qreal fontScale, const QPointF &shift)
+class DistanceFieldAnisotropicShiftedTextMaterialRhiShader : public DistanceFieldShiftedStyleTextMaterialRhiShader
+{
+public:
+ DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture, int viewCount);
+};
+
+DistanceFieldAnisotropicShiftedTextMaterialRhiShader::DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture, int viewCount)
+ : DistanceFieldShiftedStyleTextMaterialRhiShader(alphaTexture, viewCount)
{
- QPointF texel(1.0 / fontScale * shift.x(),
- 1.0 / fontScale * shift.y());
- program()->setUniformValue(m_shift_id, texel);
+ setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"), viewCount);
+ if (alphaTexture)
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag.qsb"), viewCount);
+ else
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag.qsb"), viewCount);
}
QSGDistanceFieldShiftedStyleTextMaterial::QSGDistanceFieldShiftedStyleTextMaterial()
@@ -478,9 +454,12 @@ QSGMaterialType *QSGDistanceFieldShiftedStyleTextMaterial::type() const
return &type;
}
-QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() const
+QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
{
- return new DistanceFieldShiftedStyleTextMaterialShader;
+ if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
+ return new DistanceFieldAnisotropicShiftedTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
+ else
+ return new DistanceFieldShiftedStyleTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
}
int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) const
@@ -491,68 +470,70 @@ int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) cons
return QSGDistanceFieldStyledTextMaterial::compare(o);
}
-class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader
+class QSGHiQSubPixelDistanceFieldTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader
{
public:
- QSGHiQSubPixelDistanceFieldTextMaterialShader();
-
- void initialize() override;
- void activate() override;
- void deactivate() override;
- void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount);
-private:
- int m_fontScale_id = -1;
- int m_vecDelta_id = -1;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
-QSGHiQSubPixelDistanceFieldTextMaterialShader::QSGHiQSubPixelDistanceFieldTextMaterialShader()
- : QSGDistanceFieldTextMaterialShader()
+QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount)
+ : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount)
{
- setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert"));
- setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag"));
+ setFlag(UpdatesGraphicsPipelineState, true);
+ setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.vert.qsb"), viewCount);
+ if (alphaTexture)
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag.qsb"), viewCount);
+ else
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb"), viewCount);
}
-void QSGHiQSubPixelDistanceFieldTextMaterialShader::initialize()
+bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
- QSGDistanceFieldTextMaterialShader::initialize();
- m_fontScale_id = program()->uniformLocation("fontScale");
- m_vecDelta_id = program()->uniformLocation("vecDelta");
-}
+ bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
+ QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial);
+ QSGHiQSubPixelDistanceFieldTextMaterial *oldMat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(oldMaterial);
-void QSGHiQSubPixelDistanceFieldTextMaterialShader::activate()
-{
- QSGDistanceFieldTextMaterialShader::activate();
- QOpenGLContext::currentContext()->functions()->glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
-}
+ QByteArray *buf = state.uniformData();
+ Q_ASSERT(buf->size() >= 128);
-void QSGHiQSubPixelDistanceFieldTextMaterialShader::deactivate()
-{
- QSGDistanceFieldTextMaterialShader::deactivate();
- QOpenGLContext::currentContext()->functions()->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-}
-
-void QSGHiQSubPixelDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type());
- QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
- QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
-
- if (oldMaterial == nullptr || material->color() != oldMaterial->color()) {
- QVector4D c = material->color();
- state.context()->functions()->glBlendColor(c.x(), c.y(), c.z(), 1.0f);
+ if (!oldMat || mat->fontScale() != oldMat->fontScale()) {
+ float fontScale = mat->fontScale();
+ memcpy(buf->data() + m_currentUbufOffset, &fontScale, 4);
+ changed = true;
}
+ m_currentUbufOffset += 4 + 4; // 4 for padding for vec2 alignment
- if (oldMaterial == nullptr || material->fontScale() != oldMaterial->fontScale())
- program()->setUniformValue(m_fontScale_id, GLfloat(material->fontScale()));
-
- if (oldMaterial == nullptr || state.isMatrixDirty()) {
+ if (!oldMat || state.isMatrixDirty()) {
int viewportWidth = state.viewportRect().width();
QMatrix4x4 mat = state.combinedMatrix().inverted();
- program()->setUniformValue(m_vecDelta_id, mat.column(0) * (qreal(2) / viewportWidth));
+ QVector4D vecDelta = mat.column(0) * (qreal(2) / viewportWidth);
+ memcpy(buf->data() + m_currentUbufOffset, &vecDelta, 16);
}
- QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect);
+ return changed;
+}
+
+bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+{
+ Q_UNUSED(state);
+ Q_UNUSED(oldMaterial);
+ QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial);
+
+ ps->blendEnable = true;
+ ps->srcColor = GraphicsPipelineState::ConstantColor;
+ ps->dstColor = GraphicsPipelineState::OneMinusSrcColor;
+
+ const QVector4D color = mat->color();
+ // this is dynamic state but it's - magic! - taken care of by the renderer
+ ps->blendConstant = QColor::fromRgbF(color.x(), color.y(), color.z(), 1.0f);
+
+ return true;
}
QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const
@@ -561,23 +542,28 @@ QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const
return &type;
}
-QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader() const
+QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
{
- return new QSGHiQSubPixelDistanceFieldTextMaterialShader;
+ if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
+ return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
+ else
+ return new QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
}
-
-class QSGLoQSubPixelDistanceFieldTextMaterialShader : public QSGHiQSubPixelDistanceFieldTextMaterialShader
+class QSGLoQSubPixelDistanceFieldTextMaterialRhiShader : public QSGHiQSubPixelDistanceFieldTextMaterialRhiShader
{
public:
- QSGLoQSubPixelDistanceFieldTextMaterialShader();
+ QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount);
};
-QSGLoQSubPixelDistanceFieldTextMaterialShader::QSGLoQSubPixelDistanceFieldTextMaterialShader()
- : QSGHiQSubPixelDistanceFieldTextMaterialShader()
+QSGLoQSubPixelDistanceFieldTextMaterialRhiShader::QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount)
+ : QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount)
{
- setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/loqsubpixeldistancefieldtext.vert"));
- setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/loqsubpixeldistancefieldtext.frag"));
+ setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.vert.qsb"), viewCount);
+ if (alphaTexture)
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag.qsb"), viewCount);
+ else
+ setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag.qsb"), viewCount);
}
QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const
@@ -586,9 +572,12 @@ QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const
return &type;
}
-QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader() const
+QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
{
- return new QSGLoQSubPixelDistanceFieldTextMaterialShader;
+ if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported())
+ return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
+ else
+ return new QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount());
}
QT_END_NAMESPACE