diff options
Diffstat (limited to 'src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp')
-rw-r--r-- | src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp | 636 |
1 files changed, 141 insertions, 495 deletions
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp index e8e9f76d04..afb41f32e4 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp @@ -1,45 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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 "qsgrhidistancefieldglyphcache_p.h" -#include <QtGui/qopenglfunctions.h> #include <QtGui/qsurface.h> #include <QtGui/qwindow.h> #include <qmath.h> @@ -70,147 +33,10 @@ static float spreadFunc(float glyphScale) return range / glyphScale; } -class QSGDistanceFieldTextMaterialShader : public QSGMaterialShader +class QSGDistanceFieldTextMaterialRhiShader : 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")); -} - -void QSGDistanceFieldTextMaterialShader::updateAlphaRange() -{ - 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; - } -} - -void QSGDistanceFieldTextMaterialShader::updateColor(const QVector4D &c) -{ - if (m_lastColor != c) { - program()->setUniformValue(m_color_id, c); - m_lastColor = c; - } -} - -void QSGDistanceFieldTextMaterialShader::updateTextureScale(const QVector2D &ts) -{ - if (m_lastTextureScale != ts) { - program()->setUniformValue(m_textureScale_id, ts); - m_lastTextureScale = ts; - } -} - -void QSGDistanceFieldTextMaterialShader::initialize() -{ - 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"); -} - -void QSGDistanceFieldTextMaterialShader::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); - - bool updated = material->updateTextureSize(); - - if (oldMaterial == nullptr - || material->color() != oldMaterial->color() - || state.isOpacityDirty()) { - QVector4D color = material->color(); - color *= state.opacity(); - updateColor(color); - } - - bool updateRange = false; - if (oldMaterial == nullptr - || material->fontScale() != oldMaterial->fontScale()) { - m_fontScale = material->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(); - } - - Q_ASSERT(material->glyphCache()); - - if (updated - || oldMaterial == nullptr - || oldMaterial->texture()->textureId != material->texture()->textureId) { - updateTextureScale(QVector2D(1.0 / material->textureSize().width(), - 1.0 / material->textureSize().height())); - - QOpenGLFunctions *funcs = state.context()->functions(); - funcs->glBindTexture(GL_TEXTURE_2D, material->texture()->textureId); - - 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); - } - } -} - -class QSGDistanceFieldTextMaterialRhiShader : public QSGMaterialRhiShader -{ -public: - QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture); + QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount); bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; @@ -221,18 +47,16 @@ public: protected: float m_fontScale = 1.0; float m_matrixScale = 1.0; + quint32 m_currentUbufOffset; }; -QSGDistanceFieldTextMaterialRhiShader::QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture) +QSGDistanceFieldTextMaterialRhiShader::QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount) { - setShaderFileName(VertexStage, - QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb")); + 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")); + 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")); + setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.frag.qsb"), viewCount); } bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state, @@ -258,36 +82,47 @@ bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state updateRange = true; } if (state.isMatrixDirty()) { - const QMatrix4x4 m = state.combinedMatrix(); - memcpy(buf->data(), m.constData(), 64); - changed = true; m_matrixScale = qSqrt(qAbs(state.determinant())) * state.devicePixelRatio(); updateRange = true; } + 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() + 64, &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() + 80, &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() + 96, &alphaMinMax, 8); + 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 // move texture uploads/copies onto the renderer's soon-to-be-committed list static_cast<QSGRhiDistanceFieldGlyphCache *>(mat->glyphCache())->commitResourceUpdates(state.resourceUpdateBatch()); + m_currentUbufOffset = offset; return changed; } @@ -304,13 +139,29 @@ void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(RenderState &stat *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 | SupportsRhiShader, true); + setFlag(Blending | RequiresDeterminant, true); } QSGDistanceFieldTextMaterial::~QSGDistanceFieldTextMaterial() @@ -326,18 +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 { - if (flags().testFlag(RhiShaderWanted)) - return new QSGDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); + if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) + return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); else - return new QSGDistanceFieldTextMaterialShader; + return new QSGDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); } bool QSGDistanceFieldTextMaterial::updateTextureSize() @@ -381,62 +231,21 @@ 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->rhiBased ? qintptr(m_texture->texture) : m_texture->textureId) : 0; - int t1 = other->m_texture ? (other->m_texture->rhiBased ? qintptr(other->m_texture->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 -{ -public: - DistanceFieldStyledTextMaterialShader(); - - void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; - -protected: - void initialize() override; - - int m_styleColor_id = -1; -}; - -DistanceFieldStyledTextMaterialShader::DistanceFieldStyledTextMaterialShader() - : QSGDistanceFieldTextMaterialShader() -{ -} - -void DistanceFieldStyledTextMaterialShader::initialize() -{ - QSGDistanceFieldTextMaterialShader::initialize(); - m_styleColor_id = program()->uniformLocation("styleColor"); -} - -void DistanceFieldStyledTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) -{ - QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect); - - QSGDistanceFieldStyledTextMaterial *material = static_cast<QSGDistanceFieldStyledTextMaterial *>(newEffect); - QSGDistanceFieldStyledTextMaterial *oldMaterial = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldEffect); - - if (oldMaterial == nullptr - || material->styleColor() != oldMaterial->styleColor() - || (state.isOpacityDirty())) { - QVector4D color = material->styleColor(); - color *= state.opacity(); - program()->setUniformValue(m_styleColor_id, color); - } -} - class DistanceFieldStyledTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader { public: - DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture); + DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture, int viewCount); bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; -DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture) - : QSGDistanceFieldTextMaterialRhiShader(alphaTexture) +DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture, int viewCount) + : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount) { } @@ -450,12 +259,17 @@ bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(RenderState &st 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 + if (!oldMat || mat->styleColor() != oldMat->styleColor() || state.isOpacityDirty()) { QVector4D styleColor = mat->styleColor(); styleColor *= state.opacity(); - memcpy(buf->data() + 112, &styleColor, 16); + + memcpy(buf->data() + m_currentUbufOffset, &styleColor, 16); changed = true; } + m_currentUbufOffset += 16; return changed; } @@ -471,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 @@ -486,82 +299,38 @@ int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const return QSGDistanceFieldTextMaterial::compare(o); } - -class DistanceFieldOutlineTextMaterialShader : public DistanceFieldStyledTextMaterialShader +class DistanceFieldOutlineTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader { public: - DistanceFieldOutlineTextMaterialShader(); - - void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; + DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount); -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() -{ - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldoutlinetext.frag")); -} - -void DistanceFieldOutlineTextMaterialShader::initialize() -{ - 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) +DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount) + : DistanceFieldStyledTextMaterialRhiShader(alphaTexture, viewCount) { - DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect); - - QSGDistanceFieldOutlineTextMaterial *material = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newEffect); - QSGDistanceFieldOutlineTextMaterial *oldMaterial = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldEffect); - - if (oldMaterial == nullptr - || material->fontScale() != oldMaterial->fontScale() - || state.isMatrixDirty()) - updateOutlineAlphaRange(material->glyphCache()->distanceFieldRadius()); + 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); } -class DistanceFieldOutlineTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader +class DistanceFieldAnisotropicOutlineTextMaterialRhiShader : public DistanceFieldOutlineTextMaterialRhiShader { public: - DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture); - - bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount); }; -DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture) - : DistanceFieldStyledTextMaterialRhiShader(alphaTexture) +DistanceFieldAnisotropicOutlineTextMaterialRhiShader::DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount) + : DistanceFieldOutlineTextMaterialRhiShader(alphaTexture, viewCount) { - setShaderFileName(VertexStage, - QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb")); + 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")); + 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.frag.qsb")); + setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag.qsb"), viewCount); } bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(RenderState &state, @@ -583,8 +352,8 @@ bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(RenderState &s float alphaMin = qMax(0.0f, base - range); float styleAlphaMin0 = qMax(0.0f, outlineLimit - range); float styleAlphaMin1 = qMin(outlineLimit + range, alphaMin); - memcpy(buf->data() + 128, &styleAlphaMin0, 4); - memcpy(buf->data() + 132, &styleAlphaMin1, 4); + memcpy(buf->data() + m_currentUbufOffset, &styleAlphaMin0, 4); + memcpy(buf->data() + m_currentUbufOffset + 4, &styleAlphaMin1, 4); changed = true; } @@ -606,84 +375,30 @@ QSGMaterialType *QSGDistanceFieldOutlineTextMaterial::type() const return &type; } -QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader() const +QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const { - if (flags().testFlag(RhiShaderWanted)) - return new DistanceFieldOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); + if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) + return new DistanceFieldAnisotropicOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); else - return new DistanceFieldOutlineTextMaterialShader; -} - - -class DistanceFieldShiftedStyleTextMaterialShader : public DistanceFieldStyledTextMaterialShader -{ -public: - DistanceFieldShiftedStyleTextMaterialShader(); - - void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; - -protected: - void initialize() override; - - void updateShift(qreal fontScale, const QPointF& shift); - - int m_shift_id = -1; -}; - -DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader() - : DistanceFieldStyledTextMaterialShader() -{ - setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldshiftedtext.vert")); - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldshiftedtext.frag")); -} - -void DistanceFieldShiftedStyleTextMaterialShader::initialize() -{ - DistanceFieldStyledTextMaterialShader::initialize(); - m_shift_id = program()->uniformLocation("shift"); -} - -void DistanceFieldShiftedStyleTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) -{ - DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect); - - 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()); - } -} - -void DistanceFieldShiftedStyleTextMaterialShader::updateShift(qreal fontScale, const QPointF &shift) -{ - QPointF texel(1.0 / fontScale * shift.x(), - 1.0 / fontScale * shift.y()); - program()->setUniformValue(m_shift_id, texel); + return new DistanceFieldOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); } class DistanceFieldShiftedStyleTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader { public: - DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture); + DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture, int viewCount); bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; -DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture) - : DistanceFieldStyledTextMaterialRhiShader(alphaTexture) +DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture, int viewCount) + : DistanceFieldStyledTextMaterialRhiShader(alphaTexture, viewCount) { - setShaderFileName(VertexStage, - QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb")); + 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")); + 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")); + setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb"), viewCount); } bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(RenderState &state, @@ -699,15 +414,31 @@ bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(RenderSta if (!oldMat || oldMat->fontScale() != mat->fontScale() || oldMat->shift() != mat->shift() || oldMat->textureSize() != mat->textureSize()) { - QPointF shift(1.0 / mat->fontScale() * mat->shift().x(), - 1.0 / mat->fontScale() * mat->shift().y()); - memcpy(buf->data() + 128, &shift, 8); + 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; } +class DistanceFieldAnisotropicShiftedTextMaterialRhiShader : public DistanceFieldShiftedStyleTextMaterialRhiShader +{ +public: + DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture, int viewCount); +}; + +DistanceFieldAnisotropicShiftedTextMaterialRhiShader::DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture, int viewCount) + : DistanceFieldShiftedStyleTextMaterialRhiShader(alphaTexture, viewCount) +{ + 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() : QSGDistanceFieldStyledTextMaterial() { @@ -723,12 +454,12 @@ QSGMaterialType *QSGDistanceFieldShiftedStyleTextMaterial::type() const return &type; } -QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() const +QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const { - if (flags().testFlag(RhiShaderWanted)) - return new DistanceFieldShiftedStyleTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); + if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) + return new DistanceFieldAnisotropicShiftedTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); else - return new DistanceFieldShiftedStyleTextMaterialShader; + return new DistanceFieldShiftedStyleTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); } int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) const @@ -739,94 +470,25 @@ int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) cons return QSGDistanceFieldStyledTextMaterial::compare(o); } - -class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader -{ -public: - QSGHiQSubPixelDistanceFieldTextMaterialShader(); - - void initialize() override; - void activate() override; - void deactivate() override; - void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; - -private: - int m_fontScale_id = -1; - int m_vecDelta_id = -1; -}; - -QSGHiQSubPixelDistanceFieldTextMaterialShader::QSGHiQSubPixelDistanceFieldTextMaterialShader() - : QSGDistanceFieldTextMaterialShader() -{ - setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert")); - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag")); -} - -void QSGHiQSubPixelDistanceFieldTextMaterialShader::initialize() -{ - QSGDistanceFieldTextMaterialShader::initialize(); - m_fontScale_id = program()->uniformLocation("fontScale"); - m_vecDelta_id = program()->uniformLocation("vecDelta"); -} - -void QSGHiQSubPixelDistanceFieldTextMaterialShader::activate() -{ - QSGDistanceFieldTextMaterialShader::activate(); - QOpenGLContext::currentContext()->functions()->glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR); -} - -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 (oldMaterial == nullptr || material->fontScale() != oldMaterial->fontScale()) - program()->setUniformValue(m_fontScale_id, GLfloat(material->fontScale())); - - if (oldMaterial == nullptr || state.isMatrixDirty()) { - int viewportWidth = state.viewportRect().width(); - QMatrix4x4 mat = state.combinedMatrix().inverted(); - program()->setUniformValue(m_vecDelta_id, mat.column(0) * (qreal(2) / viewportWidth)); - } - - QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect); -} - class QSGHiQSubPixelDistanceFieldTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader { public: - QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture); + QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount); bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; -QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture) - : QSGDistanceFieldTextMaterialRhiShader(alphaTexture) +QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount) + : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount) { setFlag(UpdatesGraphicsPipelineState, true); - - setShaderFileName(VertexStage, - QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.vert.qsb")); + 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")); + 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")); + setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb"), viewCount); } bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state, @@ -841,15 +503,16 @@ bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(RenderS if (!oldMat || mat->fontScale() != oldMat->fontScale()) { float fontScale = mat->fontScale(); - memcpy(buf->data() + 104, &fontScale, 4); + memcpy(buf->data() + m_currentUbufOffset, &fontScale, 4); changed = true; } + m_currentUbufOffset += 4 + 4; // 4 for padding for vec2 alignment if (!oldMat || state.isMatrixDirty()) { int viewportWidth = state.viewportRect().width(); QMatrix4x4 mat = state.combinedMatrix().inverted(); QVector4D vecDelta = mat.column(0) * (qreal(2) / viewportWidth); - memcpy(buf->data() + 112, &vecDelta, 16); + memcpy(buf->data() + m_currentUbufOffset, &vecDelta, 16); } return changed; @@ -879,45 +542,28 @@ QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const return &type; } -QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader() const +QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const { - if (flags().testFlag(RhiShaderWanted)) - return new QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); + if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) + return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); else - return new QSGHiQSubPixelDistanceFieldTextMaterialShader; -} - - -class QSGLoQSubPixelDistanceFieldTextMaterialShader : public QSGHiQSubPixelDistanceFieldTextMaterialShader -{ -public: - QSGLoQSubPixelDistanceFieldTextMaterialShader(); -}; - -QSGLoQSubPixelDistanceFieldTextMaterialShader::QSGLoQSubPixelDistanceFieldTextMaterialShader() - : QSGHiQSubPixelDistanceFieldTextMaterialShader() -{ - setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/loqsubpixeldistancefieldtext.vert")); - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/loqsubpixeldistancefieldtext.frag")); + return new QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); } class QSGLoQSubPixelDistanceFieldTextMaterialRhiShader : public QSGHiQSubPixelDistanceFieldTextMaterialRhiShader { public: - QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture); + QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount); }; -QSGLoQSubPixelDistanceFieldTextMaterialRhiShader::QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture) - : QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(alphaTexture) +QSGLoQSubPixelDistanceFieldTextMaterialRhiShader::QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount) + : QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount) { - setShaderFileName(VertexStage, - QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.vert.qsb")); + 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")); + 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")); + setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag.qsb"), viewCount); } QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const @@ -926,12 +572,12 @@ QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const return &type; } -QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader() const +QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const { - if (flags().testFlag(RhiShaderWanted)) - return new QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled()); + if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) + return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); else - return new QSGLoQSubPixelDistanceFieldTextMaterialShader; + return new QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); } QT_END_NAMESPACE |