1 | /* |
2 | * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> |
3 | * |
4 | * SPDX-License-Identifier: LGPL-2.0-or-later |
5 | */ |
6 | |
7 | #include "shadowedrectanglematerial.h" |
8 | |
9 | #include <QOpenGLContext> |
10 | |
11 | QSGMaterialType ShadowedRectangleMaterial::staticType; |
12 | |
13 | ShadowedRectangleMaterial::ShadowedRectangleMaterial() |
14 | { |
15 | setFlag(flags: QSGMaterial::Blending, on: true); |
16 | } |
17 | |
18 | QSGMaterialShader *ShadowedRectangleMaterial::createShader(QSGRendererInterface::RenderMode) const |
19 | { |
20 | return new ShadowedRectangleShader{shaderType}; |
21 | } |
22 | |
23 | QSGMaterialType *ShadowedRectangleMaterial::type() const |
24 | { |
25 | return &staticType; |
26 | } |
27 | |
28 | int ShadowedRectangleMaterial::compare(const QSGMaterial *other) const |
29 | { |
30 | auto material = static_cast<const ShadowedRectangleMaterial *>(other); |
31 | /* clang-format off */ |
32 | if (material->color == color |
33 | && material->shadowColor == shadowColor |
34 | && material->offset == offset |
35 | && material->aspect == aspect |
36 | && qFuzzyCompare(p1: material->size, p2: size) |
37 | && qFuzzyCompare(v1: material->radius, v2: radius)) { /* clang-format on */ |
38 | return 0; |
39 | } |
40 | |
41 | return QSGMaterial::compare(other); |
42 | } |
43 | |
44 | ShadowedRectangleShader::ShadowedRectangleShader(ShadowedRectangleMaterial::ShaderType shaderType) |
45 | { |
46 | setShader(shaderType, QStringLiteral("shadowedrectangle" )); |
47 | } |
48 | |
49 | bool ShadowedRectangleShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
50 | { |
51 | bool changed = false; |
52 | QByteArray *buf = state.uniformData(); |
53 | Q_ASSERT(buf->size() >= 160); |
54 | |
55 | if (state.isMatrixDirty()) { |
56 | const QMatrix4x4 m = state.combinedMatrix(); |
57 | memcpy(dest: buf->data(), src: m.constData(), n: 64); |
58 | changed = true; |
59 | } |
60 | |
61 | if (state.isOpacityDirty()) { |
62 | const float opacity = state.opacity(); |
63 | memcpy(dest: buf->data() + 72, src: &opacity, n: 4); |
64 | changed = true; |
65 | } |
66 | |
67 | if (!oldMaterial || newMaterial->compare(other: oldMaterial) != 0) { |
68 | const auto material = static_cast<ShadowedRectangleMaterial *>(newMaterial); |
69 | memcpy(dest: buf->data() + 64, src: &material->aspect, n: 8); |
70 | memcpy(dest: buf->data() + 76, src: &material->size, n: 4); |
71 | memcpy(dest: buf->data() + 80, src: &material->radius, n: 16); |
72 | float c[4]; |
73 | material->color.getRgbF(r: &c[0], g: &c[1], b: &c[2], a: &c[3]); |
74 | memcpy(dest: buf->data() + 96, src: c, n: 16); |
75 | material->shadowColor.getRgbF(r: &c[0], g: &c[1], b: &c[2], a: &c[3]); |
76 | memcpy(dest: buf->data() + 112, src: c, n: 16); |
77 | memcpy(dest: buf->data() + 128, src: &material->offset, n: 8); |
78 | changed = true; |
79 | } |
80 | |
81 | return changed; |
82 | } |
83 | |
84 | void ShadowedRectangleShader::setShader(ShadowedRectangleMaterial::ShaderType shaderType, const QString &shader) |
85 | { |
86 | const auto shaderRoot = QStringLiteral(":/org/kde/kirigami/shaders/" ); |
87 | |
88 | setShaderFileName(stage: QSGMaterialShader::VertexStage, filename: shaderRoot + QStringLiteral("shadowedrectangle.vert.qsb" )); |
89 | |
90 | auto shaderFile = shader; |
91 | if (shaderType == ShadowedRectangleMaterial::ShaderType::LowPower) { |
92 | shaderFile += QStringLiteral("_lowpower" ); |
93 | } |
94 | setShaderFileName(stage: QSGMaterialShader::FragmentStage, filename: shaderRoot + shaderFile + QStringLiteral(".frag.qsb" )); |
95 | } |
96 | |