Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
ShaderRegistry.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 fuddlesworth
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include <PhosphorShaders/phosphorshaders_export.h>
7
8#include <PhosphorRegistry/IFactoryBase.h>
9#include <PhosphorRegistry/MetadataPackLoader.h>
10#include <PhosphorRegistry/Registry.h>
11
12#include <QHash>
13#include <QImage>
14#include <QList>
15#include <QMap>
16#include <QMutex>
17#include <QObject>
18#include <QRect>
19#include <QSize>
20#include <QString>
21#include <QUrl>
22#include <QVariant>
23#include <array>
24#include <memory>
25
26namespace PhosphorShaders {
27
28class IWallpaperProvider;
29
60class PHOSPHORSHADERS_EXPORT ShaderRegistry : public QObject
61{
62 Q_OBJECT
63
64public:
66 {
67 QString id;
68 QString name;
69 QString group;
70 QString type;
71 int slot = -1;
72 QVariant defaultValue;
73 QVariant minValue;
74 QVariant maxValue;
75 bool useZoneColor = false;
76 QString wrap;
77
79 QString uniformName() const;
80 };
81
83 {
84 QString id;
85 QString name;
86 QString description;
87 QString author;
88 QString version;
90 QString sourcePath;
92 QStringList bufferShaderPaths;
93 QString previewPath;
94 QString category;
95 QList<ParameterInfo> parameters;
96 QMap<QString, QVariantMap> presets;
97 bool isUserShader = false;
98 bool isMultipass = false;
99 bool useWallpaper = false;
100 bool bufferFeedback = false;
101 qreal bufferScale = 1.0;
102 QString bufferWrap = QStringLiteral("clamp");
103 QStringList bufferWraps;
104 QString bufferFilter = QStringLiteral("linear");
105 QStringList bufferFilters;
106 bool useDepthBuffer = false;
107
108 bool isValid() const
109 {
110 return !id.isEmpty() && (isNoneShader(id) || shaderUrl.isValid());
111 }
112 };
113
119 class ShaderPack final : public PhosphorRegistry::IFactoryBase
120 {
121 public:
122 explicit ShaderPack(ShaderInfo info)
123 : m_info(std::move(info))
124 {
125 }
126 [[nodiscard]] QString id() const override
127 {
128 return m_info.id;
129 }
130 [[nodiscard]] QString displayName() const override
131 {
132 return m_info.name;
133 }
134 [[nodiscard]] const ShaderInfo& info() const
135 {
136 return m_info;
137 }
138
139 private:
140 ShaderInfo m_info;
141 };
142
143 explicit ShaderRegistry(QObject* parent = nullptr);
144 ~ShaderRegistry() override;
145
146 // ── Search paths (forwarded to the internal MetadataPackLoader) ───
147 //
148 // Same surface the legacy MetadataPackRegistryBase provided. liveReload
149 // defaults to On (production hot-reload); pass Off for one-shot scans.
152 const QStringList& paths, PhosphorFsLoader::LiveReload liveReload = PhosphorFsLoader::LiveReload::On,
154 [[nodiscard]] QStringList searchPaths() const;
155 void setUserPath(const QString& path);
156 Q_INVOKABLE void refresh();
157
158 // ── Shader discovery ──────────────────────────────────────────────
159
160 static QString noneShaderUuid();
161 static bool isNoneShader(const QString& id);
162
163 QList<ShaderInfo> availableShaders() const;
164 Q_INVOKABLE QVariantList availableShadersVariant() const;
165
166 ShaderInfo shader(const QString& id) const;
167 Q_INVOKABLE QVariantMap shaderInfo(const QString& id) const;
168 Q_INVOKABLE QUrl shaderUrl(const QString& id) const;
169
170 // ── Parameters & presets ──────────────────────────────────────────
171
172 Q_INVOKABLE QVariantMap defaultParams(const QString& id) const;
173 bool validateParams(const QString& id, const QVariantMap& params) const;
174 QVariantMap validateAndCoerceParams(const QString& id, const QVariantMap& params) const;
175 Q_INVOKABLE QVariantMap translateParamsToUniforms(const QString& shaderId, const QVariantMap& storedParams) const;
176
188 static QString paramPreamble(const ShaderInfo& info);
189
197 static ShaderInfo parsePackMetadata(const QString& packDir, QString* error = nullptr);
198
199 Q_INVOKABLE QVariantMap presetParams(const QString& shaderId, const QString& presetName) const;
200 Q_INVOKABLE QStringList shaderPresetNames(const QString& shaderId) const;
201 Q_INVOKABLE QVariantList shaderPresetsVariant(const QString& shaderId) const;
202
211 Q_INVOKABLE bool shadersEnabled() const
212 {
213 return true;
214 }
215
216 // ── Lifecycle ─────────────────────────────────────────────────────
217
218 void reportShaderBakeStarted(const QString& shaderId);
219 void reportShaderBakeFinished(const QString& shaderId, bool success, const QString& error);
220
221 // ── Wallpaper ─────────────────────────────────────────────────────
222
223 static QString wallpaperPath();
224 static QImage loadWallpaperImage();
225
241 static QImage loadWallpaperImage(const QRect& subGeom, const QRect& physGeom);
242
249 static QRect computeWallpaperCropRect(QSize wpSize, const QRect& physGeom, const QRect& subGeom);
250
252
253Q_SIGNALS:
255 void shaderCompilationStarted(const QString& shaderId);
256 void shaderCompilationFinished(const QString& shaderId, bool success, const QString& error);
257
258private:
259 bool validateParameterValue(const ParameterInfo& param, const QVariant& value) const;
260 QVariantMap shaderInfoToVariantMap(const ShaderInfo& info) const;
261 QVariantMap parameterInfoToVariantMap(const ParameterInfo& param) const;
262
263 // Generic id-keyed storage + change-notify for the discovered shader
264 // packs. m_loader (below) populates it from disk; the lookup methods
265 // read it. Declared before m_loader so it is destroyed AFTER the loader:
266 // the loader holds a borrowed Registry pointer (used during live rescans
267 // in reconcile(), not at teardown), which must stay valid for the loader's
268 // whole lifetime.
269 PhosphorRegistry::Registry<ShaderPack> m_registry;
270 // On-disk scan + hot-reload. Parses each pack's metadata.json into a
271 // ShaderPack and reconciles m_registry; its onCommitted hook re-emits
272 // shadersChanged. unique_ptr so the ctor can configure it after the
273 // member-init list (parser, watch paths, signature, commit hook).
274 std::unique_ptr<PhosphorRegistry::MetadataPackLoader<ShaderPack>> m_loader;
275
276 static std::unique_ptr<IWallpaperProvider> s_wallpaperProvider;
277 static QString s_cachedWallpaperPath;
278 static QImage s_cachedWallpaperImage;
279 static qint64 s_cachedWallpaperMtime;
280 static QMutex s_wallpaperCacheMutex;
281
282 // Per-VS crop cache: keeps the same QImage (and cacheKey) for repeated
283 // loadWallpaperImage(sub, phys) calls so downstream cacheKey()-based
284 // short-circuits in ShaderEffect/ShaderNodeRhi keep working and the GPU
285 // doesn't re-upload the wallpaper on every overlay update.
286 struct WallpaperCropEntry
287 {
288 QRect sub;
289 QRect phys;
290 qint64 mtime = 0;
291 QImage img;
292 };
293 static constexpr int CropCacheCapacity = 8;
294 static std::array<WallpaperCropEntry, CropCacheCapacity> s_cachedWallpaperCrops;
295 static int s_cachedWallpaperCropNextSlot;
296};
297
298} // namespace PhosphorShaders
Registry entry: a discovered shader as a PhosphorRegistry factory.
Definition ShaderRegistry.h:120
QString displayName() const override
Definition ShaderRegistry.h:130
QString id() const override
Definition ShaderRegistry.h:126
ShaderPack(ShaderInfo info)
Definition ShaderRegistry.h:122
const ShaderInfo & info() const
Definition ShaderRegistry.h:134
Registry of available shader effects.
Definition ShaderRegistry.h:61
ShaderRegistry(QObject *parent=nullptr)
QVariantMap shaderInfo(const QString &id) const
void reportShaderBakeFinished(const QString &shaderId, bool success, const QString &error)
void shaderCompilationStarted(const QString &shaderId)
QStringList shaderPresetNames(const QString &shaderId) const
void setUserPath(const QString &path)
static QImage loadWallpaperImage(const QRect &subGeom, const QRect &physGeom)
Return the wallpaper image cropped to the portion that a sub-region (subGeom) occupies on a physical ...
QVariantMap translateParamsToUniforms(const QString &shaderId, const QVariantMap &storedParams) const
static ShaderInfo parsePackMetadata(const QString &packDir, QString *error=nullptr)
Parse a pack directory's metadata.json into a ShaderInfo using the SAME parser the live registry uses...
QList< ShaderInfo > availableShaders() const
static QString paramPreamble(const ShaderInfo &info)
Build the generated #define p_<id> <glsl-accessor> preamble (T1.1) for info's declared parameters,...
ShaderInfo shader(const QString &id) const
static QImage loadWallpaperImage()
QVariantList availableShadersVariant() const
static void invalidateWallpaperCache()
void shaderCompilationFinished(const QString &shaderId, bool success, const QString &error)
QVariantList shaderPresetsVariant(const QString &shaderId) const
bool shadersEnabled() const
Always true — once a ShaderRegistry is constructed, shader discovery and metadata are functional (the...
Definition ShaderRegistry.h:211
QVariantMap validateAndCoerceParams(const QString &id, const QVariantMap &params) const
QVariantMap defaultParams(const QString &id) const
void addSearchPaths(const QStringList &paths, PhosphorFsLoader::LiveReload liveReload=PhosphorFsLoader::LiveReload::On, PhosphorFsLoader::RegistrationOrder order=PhosphorFsLoader::RegistrationOrder::LowestPriorityFirst)
bool validateParams(const QString &id, const QVariantMap &params) const
static bool isNoneShader(const QString &id)
void reportShaderBakeStarted(const QString &shaderId)
void addSearchPath(const QString &path, PhosphorFsLoader::LiveReload liveReload=PhosphorFsLoader::LiveReload::On)
QStringList searchPaths() const
QUrl shaderUrl(const QString &id) const
static QRect computeWallpaperCropRect(QSize wpSize, const QRect &physGeom, const QRect &subGeom)
Pure geometry helper: compute the pixel rect inside a wallpaper of size wpSize that corresponds to su...
QVariantMap presetParams(const QString &shaderId, const QString &presetName) const
RegistrationOrder
Caller's declared priority direction for registerDirectories / setDirectories input.
Definition WatchedDirectorySet.h:58
@ LowestPriorityFirst
[sys-lowest, ..., sys-highest, user] — the canonical strategy view.
LiveReload
Opt-in policy for directory watching.
Definition WatchedDirectorySet.h:34
Definition ShaderEffect.h:30
QString group
Definition ShaderRegistry.h:69
QVariant maxValue
Definition ShaderRegistry.h:74
QString uniformName() const
Convert slot to uniform name (e.g., slot 0 → "customParams1_x")
QVariant defaultValue
Definition ShaderRegistry.h:72
QString wrap
Definition ShaderRegistry.h:76
QVariant minValue
Definition ShaderRegistry.h:73
QString id
Definition ShaderRegistry.h:67
QString name
Definition ShaderRegistry.h:68
QString type
"float", "color", "int", "bool", "image"
Definition ShaderRegistry.h:70
Definition ShaderRegistry.h:83
QString vertexShaderPath
Definition ShaderRegistry.h:91
QString id
Definition ShaderRegistry.h:84
QString sourcePath
Definition ShaderRegistry.h:90
bool isValid() const
Definition ShaderRegistry.h:108
QString author
Definition ShaderRegistry.h:87
QMap< QString, QVariantMap > presets
Definition ShaderRegistry.h:96
QString category
Definition ShaderRegistry.h:94
QList< ParameterInfo > parameters
Definition ShaderRegistry.h:95
QUrl shaderUrl
Definition ShaderRegistry.h:89
QString name
Definition ShaderRegistry.h:85
QString previewPath
Definition ShaderRegistry.h:93
QStringList bufferFilters
Definition ShaderRegistry.h:105
QString description
Definition ShaderRegistry.h:86
QString version
Definition ShaderRegistry.h:88
QStringList bufferShaderPaths
Definition ShaderRegistry.h:92
QStringList bufferWraps
Definition ShaderRegistry.h:103