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>
10#include <PhosphorRegistry/MetadataPackLoader.h>
11#include <PhosphorRegistry/Registry.h>
12
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#include <optional>
26
27namespace PhosphorShaders {
28
29class IWallpaperProvider;
30
66class PHOSPHORSHADERS_EXPORT ShaderRegistry : public QObject
67{
68 Q_OBJECT
69
70public:
72 {
73 QString id;
74 QString name;
75 QString group;
76 QString type;
77 int slot = -1;
78 QVariant defaultValue;
79 QVariant minValue;
80 QVariant maxValue;
81 bool useZoneColor = false;
82 QString wrap;
90 QString unit;
91
93 QString uniformName() const;
94 };
95
97 {
98 QString id;
99 QString name;
100 QString description;
101 QString author;
102 QString version;
104 QString sourcePath;
110 QString packDir;
111 QStringList bufferShaderPaths;
112 QString previewPath;
113 QString category;
114 QList<ParameterInfo> parameters;
115 QMap<QString, QVariantMap> presets;
116 bool isUserShader = false;
117 bool isMultipass = false;
118 bool useWallpaper = false;
119 bool bufferFeedback = false;
120 qreal bufferScale = 1.0;
125 bool halfFloatBuffers = true;
126 QString bufferWrap = QStringLiteral("clamp");
127 QStringList bufferWraps;
128 QString bufferFilter = QStringLiteral("linear");
129 QStringList bufferFilters;
130 bool useDepthBuffer = false;
131
132 bool isValid() const
133 {
134 // isNoneShader(id) is just id.isEmpty(), which the first conjunct
135 // already excludes, so the "none" shader is never valid here.
136 //
137 // This says the metadata is WELL-FORMED, not that the pack will
138 // load: `shaderUrl` is built from the declared fragment path
139 // without a filesystem check, so a pack naming a frag that is not
140 // there still reports valid. The live scan re-checks existence
141 // before compiling; an offline caller has to check the file itself
142 // (the shader validator reports it as its own lint).
143 return !id.isEmpty() && shaderUrl.isValid();
144 }
145 };
146
152 class ShaderPack final : public PhosphorRegistry::IFactoryBase
153 {
154 public:
155 explicit ShaderPack(ShaderInfo info)
156 : m_info(std::move(info))
157 {
158 }
159 [[nodiscard]] QString id() const override
160 {
161 return m_info.id;
162 }
163 [[nodiscard]] QString displayName() const override
164 {
165 return m_info.name;
166 }
167 [[nodiscard]] const ShaderInfo& info() const
168 {
169 return m_info;
170 }
171
172 private:
173 ShaderInfo m_info;
174 };
175
176 explicit ShaderRegistry(QObject* parent = nullptr);
177 ~ShaderRegistry() override;
178
179 // ── Search paths (forwarded to the internal MetadataPackLoader) ───
180 //
181 // Same surface the since-removed MetadataPackRegistryBase provided. liveReload
182 // defaults to On (production hot-reload); pass Off for one-shot scans.
185 const QStringList& paths, PhosphorFsLoader::LiveReload liveReload = PhosphorFsLoader::LiveReload::On,
187 [[nodiscard]] QStringList searchPaths() const;
188 void setUserPath(const QString& path);
189 Q_INVOKABLE void refresh();
190
191 // ── Shader discovery ──────────────────────────────────────────────
192
193 static QString noneShaderUuid();
194 static bool isNoneShader(const QString& id);
195
196 QList<ShaderInfo> availableShaders() const;
197 Q_INVOKABLE QVariantList availableShadersVariant() const;
198
199 ShaderInfo shader(const QString& id) const;
200 Q_INVOKABLE QVariantMap shaderInfo(const QString& id) const;
201 Q_INVOKABLE QUrl shaderUrl(const QString& id) const;
202
203 // ── Parameters & presets ──────────────────────────────────────────
204
205 Q_INVOKABLE QVariantMap defaultParams(const QString& id) const;
206 bool validateParams(const QString& id, const QVariantMap& params) const;
207 QVariantMap validateAndCoerceParams(const QString& id, const QVariantMap& params) const;
208 Q_INVOKABLE QVariantMap translateParamsToUniforms(const QString& shaderId, const QVariantMap& storedParams) const;
209
221 static QString paramPreamble(const ShaderInfo& info);
222
259 static ShaderInfo parsePackMetadata(const QString& packDir, QString* error = nullptr, bool validateSchema = true);
260
261 Q_INVOKABLE QVariantMap presetParams(const QString& shaderId, const QString& presetName) const;
262 Q_INVOKABLE QStringList shaderPresetNames(const QString& shaderId) const;
263 Q_INVOKABLE QVariantList shaderPresetsVariant(const QString& shaderId) const;
264
273 Q_INVOKABLE bool shadersEnabled() const
274 {
275 return true;
276 }
277
278 // ── Lifecycle ─────────────────────────────────────────────────────
279
280 void reportShaderBakeStarted(const QString& shaderId);
281 void reportShaderBakeFinished(const QString& shaderId, bool success, const QString& error);
282
283 // ── Wallpaper ─────────────────────────────────────────────────────
284
285 static QString wallpaperPath();
286 static QImage loadWallpaperImage();
287
303 static QImage loadWallpaperImage(const QRect& subGeom, const QRect& physGeom);
304
311 static QRect computeWallpaperCropRect(QSize wpSize, const QRect& physGeom, const QRect& subGeom);
312
332 static std::optional<QRectF> wallpaperSliceNormalized(QSize wpSize, const QRect& physGeom, const QRect& subGeom);
333
335
336Q_SIGNALS:
338 void shaderCompilationStarted(const QString& shaderId);
339 void shaderCompilationFinished(const QString& shaderId, bool success, const QString& error);
340
341private:
342 bool validateParameterValue(const ParameterInfo& param, const QVariant& value) const;
343 QVariantMap shaderInfoToVariantMap(const ShaderInfo& info) const;
344 QVariantMap parameterInfoToVariantMap(const ParameterInfo& param) const;
345
346 // Generic id-keyed storage + change-notify for the discovered shader
347 // packs. m_loader (below) populates it from disk; the lookup methods
348 // read it. Declared before m_loader so it is destroyed AFTER the loader:
349 // the loader holds a borrowed Registry pointer (used during live rescans
350 // in reconcile(), not at teardown), which must stay valid for the loader's
351 // whole lifetime.
352 PhosphorRegistry::Registry<ShaderPack> m_registry;
353 // On-disk scan + hot-reload. Parses each pack's metadata.json into a
354 // ShaderPack and reconciles m_registry; its onCommitted hook re-emits
355 // shadersChanged. unique_ptr so the ctor can configure it after the
356 // member-init list (parser, watch paths, signature, commit hook).
357 std::unique_ptr<PhosphorRegistry::MetadataPackLoader<ShaderPack>> m_loader;
358
359 static std::unique_ptr<IWallpaperProvider> s_wallpaperProvider;
360 static QString s_cachedWallpaperPath;
370 static bool s_wallpaperPathResolved;
371 static qint64 s_wallpaperPathResolvedAtMs;
372 static QImage s_cachedWallpaperImage;
373 static qint64 s_cachedWallpaperMtime;
374 static QMutex s_wallpaperCacheMutex;
375
376 // Per-VS crop cache: keeps the same QImage (and cacheKey) for repeated
377 // loadWallpaperImage(sub, phys) calls so downstream cacheKey()-based
378 // short-circuits in ShaderEffect/ShaderNodeRhi keep working and the GPU
379 // doesn't re-upload the wallpaper on every overlay update.
380 struct WallpaperCropEntry
381 {
382 QRect sub;
383 QRect phys;
384 qint64 mtime = 0;
385 QImage img;
386 };
387 static constexpr int CropCacheCapacity = 8;
388 static std::array<WallpaperCropEntry, CropCacheCapacity> s_cachedWallpaperCrops;
389 static int s_cachedWallpaperCropNextSlot;
390};
391
392} // namespace PhosphorShaders
Registry entry: a discovered shader as a PhosphorRegistry factory.
Definition ShaderRegistry.h:153
QString displayName() const override
Definition ShaderRegistry.h:163
QString id() const override
Definition ShaderRegistry.h:159
ShaderPack(ShaderInfo info)
Definition ShaderRegistry.h:155
const ShaderInfo & info() const
Definition ShaderRegistry.h:167
Registry of available shader effects.
Definition ShaderRegistry.h:67
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
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,...
static ShaderInfo parsePackMetadata(const QString &packDir, QString *error=nullptr, bool validateSchema=true)
Parse a pack directory's metadata.json into a ShaderInfo using the SAME parser the live registry uses...
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:273
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)
static std::optional< QRectF > wallpaperSliceNormalized(QSize wpSize, const QRect &physGeom, const QRect &subGeom)
The same placement as computeWallpaperCropRect, but NORMALIZED and UNCLAMPED: the slice of the wallpa...
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:33
QString group
Definition ShaderRegistry.h:75
QVariant maxValue
Definition ShaderRegistry.h:80
QString uniformName() const
Convert slot to uniform name (e.g., slot 0 → "customParams1_x")
QVariant defaultValue
Definition ShaderRegistry.h:78
QString wrap
Definition ShaderRegistry.h:82
QVariant minValue
Definition ShaderRegistry.h:79
QString id
Definition ShaderRegistry.h:73
QString name
Definition ShaderRegistry.h:74
QString type
"float", "color", "int", "bool", "image"
Definition ShaderRegistry.h:76
QString unit
Unit the value is expressed in.
Definition ShaderRegistry.h:90
Definition ShaderRegistry.h:97
QString vertexShaderPath
Definition ShaderRegistry.h:105
QString id
Definition ShaderRegistry.h:98
QString sourcePath
Definition ShaderRegistry.h:104
bool isValid() const
Definition ShaderRegistry.h:132
QString author
Definition ShaderRegistry.h:101
QMap< QString, QVariantMap > presets
Definition ShaderRegistry.h:115
QString category
Definition ShaderRegistry.h:113
QList< ParameterInfo > parameters
Definition ShaderRegistry.h:114
QUrl shaderUrl
Definition ShaderRegistry.h:103
QString name
Definition ShaderRegistry.h:99
QString previewPath
Definition ShaderRegistry.h:112
QStringList bufferFilters
Definition ShaderRegistry.h:129
QString description
Definition ShaderRegistry.h:100
QString version
Definition ShaderRegistry.h:102
QStringList bufferShaderPaths
Definition ShaderRegistry.h:111
QString packDir
Absolute pack directory (where metadata.json lives).
Definition ShaderRegistry.h:110
QStringList bufferWraps
Definition ShaderRegistry.h:127