File indexing completed on 2024-05-12 15:42:40
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "shadowedrectanglematerial.h" 0008 0009 #include <QOpenGLContext> 0010 0011 QSGMaterialType ShadowedRectangleMaterial::staticType; 0012 0013 ShadowedRectangleMaterial::ShadowedRectangleMaterial() 0014 { 0015 setFlag(QSGMaterial::Blending, true); 0016 } 0017 0018 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0019 QSGMaterialShader *ShadowedRectangleMaterial::createShader() const 0020 #else 0021 QSGMaterialShader *ShadowedRectangleMaterial::createShader(QSGRendererInterface::RenderMode) const 0022 #endif 0023 { 0024 return new ShadowedRectangleShader{shaderType}; 0025 } 0026 0027 QSGMaterialType *ShadowedRectangleMaterial::type() const 0028 { 0029 return &staticType; 0030 } 0031 0032 int ShadowedRectangleMaterial::compare(const QSGMaterial *other) const 0033 { 0034 auto material = static_cast<const ShadowedRectangleMaterial *>(other); 0035 /* clang-format off */ 0036 if (material->color == color 0037 && material->shadowColor == shadowColor 0038 && material->offset == offset 0039 && material->aspect == aspect 0040 && qFuzzyCompare(material->size, size) 0041 && qFuzzyCompare(material->radius, radius)) { /* clang-format on */ 0042 return 0; 0043 } 0044 0045 return QSGMaterial::compare(other); 0046 } 0047 0048 ShadowedRectangleShader::ShadowedRectangleShader(ShadowedRectangleMaterial::ShaderType shaderType) 0049 { 0050 setShader(shaderType, QStringLiteral("shadowedrectangle")); 0051 } 0052 0053 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0054 const char *const *ShadowedRectangleShader::attributeNames() const 0055 { 0056 static char const *const names[] = {"in_vertex", "in_uv", nullptr}; 0057 return names; 0058 } 0059 0060 void ShadowedRectangleShader::initialize() 0061 { 0062 QSGMaterialShader::initialize(); 0063 m_matrixLocation = program()->uniformLocation("matrix"); 0064 m_aspectLocation = program()->uniformLocation("aspect"); 0065 m_opacityLocation = program()->uniformLocation("opacity"); 0066 m_sizeLocation = program()->uniformLocation("size"); 0067 m_radiusLocation = program()->uniformLocation("radius"); 0068 m_colorLocation = program()->uniformLocation("color"); 0069 m_shadowColorLocation = program()->uniformLocation("shadowColor"); 0070 m_offsetLocation = program()->uniformLocation("offset"); 0071 } 0072 0073 void ShadowedRectangleShader::updateState(const QSGMaterialShader::RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) 0074 { 0075 auto p = program(); 0076 0077 if (state.isMatrixDirty()) { 0078 p->setUniformValue(m_matrixLocation, state.combinedMatrix()); 0079 } 0080 0081 if (state.isOpacityDirty()) { 0082 p->setUniformValue(m_opacityLocation, state.opacity()); 0083 } 0084 0085 if (!oldMaterial || newMaterial->compare(oldMaterial) != 0 || state.isCachedMaterialDataDirty()) { 0086 auto material = static_cast<ShadowedRectangleMaterial *>(newMaterial); 0087 p->setUniformValue(m_aspectLocation, material->aspect); 0088 p->setUniformValue(m_sizeLocation, material->size); 0089 p->setUniformValue(m_radiusLocation, material->radius); 0090 p->setUniformValue(m_colorLocation, material->color); 0091 p->setUniformValue(m_shadowColorLocation, material->shadowColor); 0092 p->setUniformValue(m_offsetLocation, material->offset); 0093 } 0094 } 0095 #else 0096 bool ShadowedRectangleShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) 0097 { 0098 bool changed = false; 0099 QByteArray *buf = state.uniformData(); 0100 Q_ASSERT(buf->size() >= 160); 0101 0102 if (state.isMatrixDirty()) { 0103 const QMatrix4x4 m = state.combinedMatrix(); 0104 memcpy(buf->data(), m.constData(), 64); 0105 changed = true; 0106 } 0107 0108 if (state.isOpacityDirty()) { 0109 const float opacity = state.opacity(); 0110 memcpy(buf->data() + 72, &opacity, 4); 0111 changed = true; 0112 } 0113 0114 if (!oldMaterial || newMaterial->compare(oldMaterial) != 0) { 0115 const auto material = static_cast<ShadowedRectangleMaterial *>(newMaterial); 0116 memcpy(buf->data() + 64, &material->aspect, 8); 0117 memcpy(buf->data() + 76, &material->size, 4); 0118 memcpy(buf->data() + 80, &material->radius, 16); 0119 float c[4]; 0120 material->color.getRgbF(&c[0], &c[1], &c[2], &c[3]); 0121 memcpy(buf->data() + 96, c, 16); 0122 material->shadowColor.getRgbF(&c[0], &c[1], &c[2], &c[3]); 0123 memcpy(buf->data() + 112, c, 16); 0124 memcpy(buf->data() + 128, &material->offset, 8); 0125 changed = true; 0126 } 0127 0128 return changed; 0129 } 0130 #endif 0131 0132 void ShadowedRectangleShader::setShader(ShadowedRectangleMaterial::ShaderType shaderType, const QString &shader) 0133 { 0134 const auto shaderRoot = QStringLiteral(":/org/kde/kirigami/shaders/"); 0135 0136 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0137 auto header = QOpenGLContext::currentContext()->isOpenGLES() ? QStringLiteral("header_es.glsl") : QStringLiteral("header_desktop.glsl"); 0138 0139 setShaderSourceFiles(QOpenGLShader::Vertex, {shaderRoot + header, shaderRoot + QStringLiteral("shadowedrectangle.vert")}); 0140 0141 QString shaderFile = shader + QStringLiteral(".frag"); 0142 auto sdfFile = QStringLiteral("sdf.glsl"); 0143 if (shaderType == ShadowedRectangleMaterial::ShaderType::LowPower) { 0144 shaderFile = shader + QStringLiteral("_lowpower.frag"); 0145 sdfFile = QStringLiteral("sdf_lowpower.glsl"); 0146 } 0147 0148 setShaderSourceFiles(QOpenGLShader::Fragment, {shaderRoot + header, shaderRoot + sdfFile, shaderRoot + shaderFile}); 0149 #else 0150 setShaderFileName(QSGMaterialShader::VertexStage, shaderRoot + QStringLiteral("shadowedrectangle.vert.qsb")); 0151 0152 auto shaderFile = shader; 0153 if (shaderType == ShadowedRectangleMaterial::ShaderType::LowPower) { 0154 shaderFile += QStringLiteral("_lowpower"); 0155 } 0156 setShaderFileName(QSGMaterialShader::FragmentStage, shaderRoot + shaderFile + QStringLiteral(".frag.qsb")); 0157 #endif 0158 }