Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
ShaderEffect.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
7#include <PhosphorRendering/phosphorrendering_export.h>
8
10
11#include <QColor>
12#include <QImage>
13#include <QMutex>
14#include <QPointF>
15#include <QQuickItem>
16#include <QSizeF>
17#include <QStringList>
18#include <QUrl>
19#include <QVariantMap>
20#include <QVector4D>
21
22#include <QPointer>
23#include <array>
24#include <atomic>
25#include <functional>
26#include <memory>
27#include <mutex>
28
29QT_BEGIN_NAMESPACE
30class QSGNode;
31QT_END_NAMESPACE
32
33namespace PhosphorShaders {
35}
36
37namespace PhosphorRendering {
38
39class ShaderNodeRhi;
40
46inline constexpr int kMaxUserTextureSlots = 4;
47
50inline constexpr int kDefaultUserTextureSvgSize = 1024;
51
64PHOSPHORRENDERING_EXPORT QVariant peelQmlVariant(const QVariant& value);
65
80class PHOSPHORRENDERING_EXPORT ShaderEffect : public QQuickItem
81{
82 Q_OBJECT
83
84 // ── Shadertoy-compatible animation uniforms ──────────────────────
85 Q_PROPERTY(qreal iTime READ iTime WRITE setITime NOTIFY iTimeChanged FINAL)
86 Q_PROPERTY(qreal iTimeDelta READ iTimeDelta WRITE setITimeDelta NOTIFY iTimeDeltaChanged FINAL)
87 Q_PROPERTY(int iFrame READ iFrame WRITE setIFrame NOTIFY iFrameChanged FINAL)
88 Q_PROPERTY(QSizeF iResolution READ iResolution WRITE setIResolution NOTIFY iResolutionChanged FINAL)
89 Q_PROPERTY(QPointF iMouse READ iMouse WRITE setIMouse NOTIFY iMouseChanged FINAL)
90 Q_PROPERTY(bool isReversed READ isReversed WRITE setIsReversed NOTIFY isReversedChanged FINAL)
91
92
108 Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged FINAL)
109
110 // ── Shader source ────────────────────────────────────────────────
111 Q_PROPERTY(QUrl shaderSource READ shaderSource WRITE setShaderSource NOTIFY shaderSourceChanged FINAL)
112 Q_PROPERTY(QUrl vertexShaderUrl READ vertexShaderUrl WRITE setVertexShaderUrl NOTIFY vertexShaderUrlChanged FINAL)
113 Q_PROPERTY(QVariantMap shaderParams READ shaderParams WRITE setShaderParams NOTIFY shaderParamsChanged)
114 Q_PROPERTY(QString paramPreamble READ paramPreamble WRITE setParamPreamble NOTIFY paramPreambleChanged)
115 Q_PROPERTY(QQuickItem* sourceItem READ sourceItem WRITE setSourceItem NOTIFY sourceItemChanged FINAL)
116
117 // ── Multipass ────────────────────────────────────────────────────
118 Q_PROPERTY(
119 QString bufferShaderPath READ bufferShaderPath WRITE setBufferShaderPath NOTIFY bufferShaderPathChanged FINAL)
120 Q_PROPERTY(QStringList bufferShaderPaths READ bufferShaderPaths WRITE setBufferShaderPaths NOTIFY
121 bufferShaderPathsChanged FINAL)
122 Q_PROPERTY(bool bufferFeedback READ bufferFeedback WRITE setBufferFeedback NOTIFY bufferFeedbackChanged FINAL)
123 Q_PROPERTY(qreal bufferScale READ bufferScale WRITE setBufferScale NOTIFY bufferScaleChanged FINAL)
124 Q_PROPERTY(
125 bool halfFloatBuffers READ halfFloatBuffers WRITE setHalfFloatBuffers NOTIFY halfFloatBuffersChanged FINAL)
126 Q_PROPERTY(QString bufferWrap READ bufferWrap WRITE setBufferWrap NOTIFY bufferWrapChanged FINAL)
127 Q_PROPERTY(QStringList bufferWraps READ bufferWraps WRITE setBufferWraps NOTIFY bufferWrapsChanged FINAL)
128 Q_PROPERTY(QString bufferFilter READ bufferFilter WRITE setBufferFilter NOTIFY bufferFilterChanged FINAL)
129 Q_PROPERTY(QStringList bufferFilters READ bufferFilters WRITE setBufferFilters NOTIFY bufferFiltersChanged FINAL)
130
131 // ── Custom parameters (32 floats in 8 vec4s) ────────────────────
132 Q_PROPERTY(QVector4D customParams1 READ customParams1 WRITE setCustomParams1 NOTIFY customParamsChanged FINAL)
133 Q_PROPERTY(QVector4D customParams2 READ customParams2 WRITE setCustomParams2 NOTIFY customParamsChanged FINAL)
134 Q_PROPERTY(QVector4D customParams3 READ customParams3 WRITE setCustomParams3 NOTIFY customParamsChanged FINAL)
135 Q_PROPERTY(QVector4D customParams4 READ customParams4 WRITE setCustomParams4 NOTIFY customParamsChanged FINAL)
136 Q_PROPERTY(QVector4D customParams5 READ customParams5 WRITE setCustomParams5 NOTIFY customParamsChanged FINAL)
137 Q_PROPERTY(QVector4D customParams6 READ customParams6 WRITE setCustomParams6 NOTIFY customParamsChanged FINAL)
138 Q_PROPERTY(QVector4D customParams7 READ customParams7 WRITE setCustomParams7 NOTIFY customParamsChanged FINAL)
139 Q_PROPERTY(QVector4D customParams8 READ customParams8 WRITE setCustomParams8 NOTIFY customParamsChanged FINAL)
140
141 // ── Custom colors (16 color slots) ───────────────────────────────
142 Q_PROPERTY(QColor customColor1 READ customColor1 WRITE setCustomColor1 NOTIFY customColorsChanged FINAL)
143 Q_PROPERTY(QColor customColor2 READ customColor2 WRITE setCustomColor2 NOTIFY customColorsChanged FINAL)
144 Q_PROPERTY(QColor customColor3 READ customColor3 WRITE setCustomColor3 NOTIFY customColorsChanged FINAL)
145 Q_PROPERTY(QColor customColor4 READ customColor4 WRITE setCustomColor4 NOTIFY customColorsChanged FINAL)
146 Q_PROPERTY(QColor customColor5 READ customColor5 WRITE setCustomColor5 NOTIFY customColorsChanged FINAL)
147 Q_PROPERTY(QColor customColor6 READ customColor6 WRITE setCustomColor6 NOTIFY customColorsChanged FINAL)
148 Q_PROPERTY(QColor customColor7 READ customColor7 WRITE setCustomColor7 NOTIFY customColorsChanged FINAL)
149 Q_PROPERTY(QColor customColor8 READ customColor8 WRITE setCustomColor8 NOTIFY customColorsChanged FINAL)
150 Q_PROPERTY(QColor customColor9 READ customColor9 WRITE setCustomColor9 NOTIFY customColorsChanged FINAL)
151 Q_PROPERTY(QColor customColor10 READ customColor10 WRITE setCustomColor10 NOTIFY customColorsChanged FINAL)
152 Q_PROPERTY(QColor customColor11 READ customColor11 WRITE setCustomColor11 NOTIFY customColorsChanged FINAL)
153 Q_PROPERTY(QColor customColor12 READ customColor12 WRITE setCustomColor12 NOTIFY customColorsChanged FINAL)
154 Q_PROPERTY(QColor customColor13 READ customColor13 WRITE setCustomColor13 NOTIFY customColorsChanged FINAL)
155 Q_PROPERTY(QColor customColor14 READ customColor14 WRITE setCustomColor14 NOTIFY customColorsChanged FINAL)
156 Q_PROPERTY(QColor customColor15 READ customColor15 WRITE setCustomColor15 NOTIFY customColorsChanged FINAL)
157 Q_PROPERTY(QColor customColor16 READ customColor16 WRITE setCustomColor16 NOTIFY customColorsChanged FINAL)
158
159 // ── Textures ─────────────────────────────────────────────────────
160 Q_PROPERTY(QVariant audioSpectrum READ audioSpectrumVariant WRITE setAudioSpectrumVariant NOTIFY
161 audioSpectrumChanged FINAL)
162 Q_PROPERTY(QVariant wallpaperTexture READ wallpaperTextureVariant WRITE setWallpaperTextureVariant NOTIFY
163 wallpaperTextureChanged FINAL)
164 Q_PROPERTY(bool useWallpaper READ useWallpaper WRITE setUseWallpaper NOTIFY useWallpaperChanged FINAL)
165 Q_PROPERTY(bool useDepthBuffer READ useDepthBuffer WRITE setUseDepthBuffer NOTIFY useDepthBufferChanged FINAL)
166
167 // ── Status ───────────────────────────────────────────────────────
168 Q_PROPERTY(Status status READ status NOTIFY statusChanged FINAL)
169 Q_PROPERTY(QString errorLog READ errorLog NOTIFY errorLogChanged FINAL)
170
171public:
175 enum class Status {
176 Null,
177 Loading,
178 Ready,
179 Error,
180 };
181 Q_ENUM(Status)
182
183
189 static constexpr int kMaxSvgDimension = 2048;
190
194 static constexpr int kMinSvgDimension = 64;
195
202 static constexpr qint64 kMaxSvgPixelBytes = 16LL * 1024 * 1024;
203
204 explicit ShaderEffect(QQuickItem* parent = nullptr);
205 ~ShaderEffect() override;
206
207 // ── Uniform extension ────────────────────────────────────────────
208
218 virtual void setUniformExtension(std::shared_ptr<PhosphorShaders::IUniformExtension> extension);
219 std::shared_ptr<PhosphorShaders::IUniformExtension> uniformExtension() const;
220
221 // ── Shadertoy uniforms ───────────────────────────────────────────
222
223 qreal iTime() const
224 {
225 return m_iTime;
226 }
227 void setITime(qreal time);
228
229 qreal iTimeDelta() const
230 {
231 return m_iTimeDelta;
232 }
233 void setITimeDelta(qreal delta);
234
235 int iFrame() const
236 {
237 return m_iFrame;
238 }
239 void setIFrame(int frame);
240
241 bool isPlaying() const
242 {
243 return m_playing;
244 }
245 void setPlaying(bool playing);
246
247 bool isReversed() const
248 {
249 return m_isReversed;
250 }
255 void setIsReversed(bool reverse);
256
257 QSizeF iResolution() const
258 {
259 return m_iResolution;
260 }
261 void setIResolution(const QSizeF& resolution);
262
263 QPointF iMouse() const
264 {
265 return m_iMouse;
266 }
267 void setIMouse(const QPointF& mouse);
268
269 // ── Shader source ────────────────────────────────────────────────
270
271 QUrl shaderSource() const
272 {
273 return m_shaderSource;
274 }
275 void setShaderSource(const QUrl& source);
276
277 QUrl vertexShaderUrl() const
278 {
279 return m_vertexShaderUrl;
280 }
281 void setVertexShaderUrl(const QUrl& source);
282
283 QVariantMap shaderParams() const
284 {
285 return m_shaderParams;
286 }
337 virtual void setShaderParams(const QVariantMap& params);
338
351 static QImage loadUserTextureFile(const QString& path, int svgMaxDim);
352
375 QQuickItem* sourceItem() const
376 {
377 return m_sourceItem.data();
378 }
379 void setSourceItem(QQuickItem* item);
380
381 // ── Multipass ────────────────────────────────────────────────────
382
383 QString bufferShaderPath() const
384 {
385 return m_bufferShaderPath;
386 }
387 void setBufferShaderPath(const QString& path);
388
389 QStringList bufferShaderPaths() const
390 {
391 return m_bufferShaderPaths;
392 }
393 void setBufferShaderPaths(const QStringList& paths);
394
395 bool bufferFeedback() const
396 {
397 return m_bufferFeedback;
398 }
399 void setBufferFeedback(bool enable);
400
401 qreal bufferScale() const
402 {
403 return m_bufferScale;
404 }
405 void setBufferScale(qreal scale);
406
407 bool halfFloatBuffers() const
408 {
409 return m_halfFloatBuffers;
410 }
411 void setHalfFloatBuffers(bool enable);
412
413 QString bufferWrap() const
414 {
415 return m_bufferWrap;
416 }
417 void setBufferWrap(const QString& wrap);
418
419 QStringList bufferWraps() const
420 {
421 return m_bufferWraps;
422 }
423 void setBufferWraps(const QStringList& wraps);
424
425 QString bufferFilter() const
426 {
427 return m_bufferFilter;
428 }
429 void setBufferFilter(const QString& filter);
430
431 QStringList bufferFilters() const
432 {
433 return m_bufferFilters;
434 }
435 void setBufferFilters(const QStringList& filters);
436
437 // ── Custom parameters (32 float slots in 8 vec4s) ────────────────
438
439 QVector4D customParams1() const
440 {
441 return m_customParams[0];
442 }
443 void setCustomParams1(const QVector4D& params);
444 QVector4D customParams2() const
445 {
446 return m_customParams[1];
447 }
448 void setCustomParams2(const QVector4D& params);
449 QVector4D customParams3() const
450 {
451 return m_customParams[2];
452 }
453 void setCustomParams3(const QVector4D& params);
454 QVector4D customParams4() const
455 {
456 return m_customParams[3];
457 }
458 void setCustomParams4(const QVector4D& params);
459 QVector4D customParams5() const
460 {
461 return m_customParams[4];
462 }
463 void setCustomParams5(const QVector4D& params);
464 QVector4D customParams6() const
465 {
466 return m_customParams[5];
467 }
468 void setCustomParams6(const QVector4D& params);
469 QVector4D customParams7() const
470 {
471 return m_customParams[6];
472 }
473 void setCustomParams7(const QVector4D& params);
474 QVector4D customParams8() const
475 {
476 return m_customParams[7];
477 }
478 void setCustomParams8(const QVector4D& params);
479
480 // ── Custom colors (16 color slots) ───────────────────────────────
481
482 QColor customColor1() const
483 {
484 return m_customColors[0];
485 }
486 void setCustomColor1(const QColor& color);
487 QColor customColor2() const
488 {
489 return m_customColors[1];
490 }
491 void setCustomColor2(const QColor& color);
492 QColor customColor3() const
493 {
494 return m_customColors[2];
495 }
496 void setCustomColor3(const QColor& color);
497 QColor customColor4() const
498 {
499 return m_customColors[3];
500 }
501 void setCustomColor4(const QColor& color);
502 QColor customColor5() const
503 {
504 return m_customColors[4];
505 }
506 void setCustomColor5(const QColor& color);
507 QColor customColor6() const
508 {
509 return m_customColors[5];
510 }
511 void setCustomColor6(const QColor& color);
512 QColor customColor7() const
513 {
514 return m_customColors[6];
515 }
516 void setCustomColor7(const QColor& color);
517 QColor customColor8() const
518 {
519 return m_customColors[7];
520 }
521 void setCustomColor8(const QColor& color);
522 QColor customColor9() const
523 {
524 return m_customColors[8];
525 }
526 void setCustomColor9(const QColor& color);
527 QColor customColor10() const
528 {
529 return m_customColors[9];
530 }
531 void setCustomColor10(const QColor& color);
532 QColor customColor11() const
533 {
534 return m_customColors[10];
535 }
536 void setCustomColor11(const QColor& color);
537 QColor customColor12() const
538 {
539 return m_customColors[11];
540 }
541 void setCustomColor12(const QColor& color);
542 QColor customColor13() const
543 {
544 return m_customColors[12];
545 }
546 void setCustomColor13(const QColor& color);
547 QColor customColor14() const
548 {
549 return m_customColors[13];
550 }
551 void setCustomColor14(const QColor& color);
552 QColor customColor15() const
553 {
554 return m_customColors[14];
555 }
556 void setCustomColor15(const QColor& color);
557 QColor customColor16() const
558 {
559 return m_customColors[15];
560 }
561 void setCustomColor16(const QColor& color);
562
563 // ── Indexed accessors (avoid per-slot function-pointer tables at call sites) ──
568 QVector4D customParamAt(int index) const;
576 void setCustomParamAt(int index, const QVector4D& params);
577
582 QColor customColorAt(int index) const;
587 void setCustomColorAt(int index, const QColor& color);
588
589 // ── Textures ─────────────────────────────────────────────────────
590
591 QVariant audioSpectrumVariant() const;
592 void setAudioSpectrumVariant(const QVariant& spectrum);
594 void setAudioSpectrum(const QVector<float>& spectrum);
595
612 void setUserTexture(int slot, const QImage& image);
614 void setUserTextureWrap(int slot, const QString& wrap);
615
616 QImage wallpaperTexture() const;
617
651 QVariant wallpaperTextureVariant() const;
652 void setWallpaperTexture(const QImage& image);
659 void setWallpaperTextureVariant(const QVariant& texture);
660
661 bool useWallpaper() const
662 {
663 return m_useWallpaper;
664 }
665 void setUseWallpaper(bool use);
666
667 bool useDepthBuffer() const
668 {
669 return m_useDepthBuffer;
670 }
671 void setUseDepthBuffer(bool use);
672
673 // ── Shader include paths ─────────────────────────────────────────
674
676 void setShaderIncludePaths(const QStringList& paths);
677 QStringList shaderIncludePaths() const
678 {
679 return m_shaderIncludePaths;
680 }
681
682 // ── Parameter preamble (T1.1: generated `#define p_<id> ...`) ─────
683
689 void setParamPreamble(const QString& preamble);
690 QString paramPreamble() const
691 {
692 return m_paramPreamble;
693 }
694
695 // ── Entry-point scaffold (T1.4: harness-generated `main()`) ────────
696
702 void setEntryScaffold(const QString& prologue, const QList<PhosphorShaders::EntryCandidate>& candidates);
703
704 // ── Status ───────────────────────────────────────────────────────
705
707 {
708 return m_status.load(std::memory_order_acquire);
709 }
710 QString errorLog() const
711 {
712 QMutexLocker lock(&m_errorLogMutex);
713 return m_errorLog;
714 }
715
716 // ── Actions ──────────────────────────────────────────────────────
717
719 Q_INVOKABLE void reloadShader();
720
742
743Q_SIGNALS:
789
790protected:
791 QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* data) override;
792 void geometryChange(const QRectF& newGeometry, const QRectF& oldGeometry) override;
793 void componentComplete() override;
794 void itemChange(ItemChange change, const ItemChangeData& value) override;
795
813
825
835 {
836 return m_shaderDirty.exchange(false);
837 }
838
851
870
871 void setError(const QString& error);
872 void setStatus(Status newStatus);
873
874private:
875 // ── Auto-tick (playing=true) plumbing ────────────────────────────
879 void updatePlayingConnection();
882 void onPlayingTick();
883
884 // ── Output-scale plumbing ────────────────────────────────────────
908 void updateScaleConnections();
909
910 // ── Animation state ──────────────────────────────────────────────
911 // Field order minimises padding: 8-byte (qreal/QSizeF/QPointF) members
912 // grouped together, followed by 4-byte (int), trailing 1-byte bool.
913 // qreal-bool-int interleaving wastes 7 bytes via alignment padding.
914 qreal m_iTime = 0.0;
915 qreal m_iTimeDelta = 0.0;
916 qreal m_playingLastFrameSeconds = 0.0;
917 QSizeF m_iResolution;
918 QPointF m_iMouse;
919 int m_iFrame = 0;
920 bool m_isReversed = false;
921 bool m_playing = false;
922 QMetaObject::Connection m_playingConnection;
925 QMetaObject::Connection m_scaleConnection;
932 QMetaObject::Connection m_screenDprConnection;
933
934 // ── Shader source ────────────────────────────────────────────────
935 QUrl m_shaderSource;
936 QUrl m_vertexShaderUrl;
937 QVariantMap m_shaderParams;
938 QStringList m_shaderIncludePaths;
939 QString m_paramPreamble;
940 QString m_entryPrologue;
941 QList<PhosphorShaders::EntryCandidate> m_entryCandidates;
942
943 // QPointer because the source item is owned by the QML scene, not
944 // the ShaderEffect — a torn-down source must auto-null rather than
945 // leave a dangling pointer that the per-frame textureProvider()
946 // lookup would dereference.
947 QPointer<QQuickItem> m_sourceItem;
951 bool m_warnedSelfSourceItem = false;
952
953 // ── Multipass ────────────────────────────────────────────────────
954 QString m_bufferShaderPath;
955 QStringList m_bufferShaderPaths;
956 bool m_bufferFeedback = false;
957 qreal m_bufferScale = 1.0;
958 bool m_halfFloatBuffers = true;
959 QString m_bufferWrap = QStringLiteral("clamp");
960 QStringList m_bufferWraps;
961 QString m_bufferFilter = QStringLiteral("linear");
962 QStringList m_bufferFilters;
963
964 // ── Custom parameters (8 vec4s, initialized to -1.0 "unset" sentinel) ──
965 std::array<QVector4D, 8> m_customParams = {{
966 QVector4D(-1.0f, -1.0f, -1.0f, -1.0f),
967 QVector4D(-1.0f, -1.0f, -1.0f, -1.0f),
968 QVector4D(-1.0f, -1.0f, -1.0f, -1.0f),
969 QVector4D(-1.0f, -1.0f, -1.0f, -1.0f),
970 QVector4D(-1.0f, -1.0f, -1.0f, -1.0f),
971 QVector4D(-1.0f, -1.0f, -1.0f, -1.0f),
972 QVector4D(-1.0f, -1.0f, -1.0f, -1.0f),
973 QVector4D(-1.0f, -1.0f, -1.0f, -1.0f),
974 }};
975
976 // ── Custom colors (16 colors) ────────────────────────────────────
977 std::array<QColor, 16> m_customColors = {{
978 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
979 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
980 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
981 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
982 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
983 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
984 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
985 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
986 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
987 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
988 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
989 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
990 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
991 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
992 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
993 QColor::fromRgbF(0.0f, 0.0f, 0.0f, 0.0f),
994 }};
995
996 // ── Textures ─────────────────────────────────────────────────────
997 QVector<float> m_audioSpectrum;
998 std::array<QImage, kMaxUserTextureSlots> m_userTextureImages;
999 // Spelled out rather than default-constructed, matching the node's array of
1000 // the same name. setShaderParams string-compares against these to decide
1001 // whether a wrap actually changed, so a null default made the first
1002 // assignment of the effective default ("clamp") look like a change.
1003 std::array<QString, kMaxUserTextureSlots> m_userTextureWraps = {QStringLiteral("clamp"), QStringLiteral("clamp"),
1004 QStringLiteral("clamp"), QStringLiteral("clamp")};
1010 std::array<QString, kMaxUserTextureSlots> m_userTexturePaths;
1017 // Filled with kDefaultUserTextureSvgSize by the constructor rather than a
1018 // brace list, so bumping kMaxUserTextureSlots cannot silently zero-fill the
1019 // new slots (qBound would then rasterise them at the 64 px floor).
1020 std::array<int, kMaxUserTextureSlots> m_userTextureSvgSizes{};
1030 bool m_userTexturesDirectlyOverridden = false;
1031 QImage m_wallpaperTexture;
1032 mutable QMutex m_wallpaperTextureMutex;
1033 bool m_useWallpaper = false;
1034 bool m_useDepthBuffer = false;
1035
1036 // ── Uniform extension ────────────────────────────────────────────
1037 std::shared_ptr<PhosphorShaders::IUniformExtension> m_uniformExtension;
1038
1039 // ── Status ───────────────────────────────────────────────────────
1040 // Atomic because setStatus is called from updatePaintNode (render
1041 // thread under threaded render loop) while onPlayingTick reads it on
1042 // the GUI thread. A torn read would only matter at status
1043 // transitions, but the gate at `m_status != Status::Ready` would
1044 // skip-or-tick spuriously around the boundary. Acquire/release
1045 // semantics suffice — there's no associated data we need to publish
1046 // alongside.
1047 std::atomic<Status> m_status{Status::Null};
1055 mutable QMutex m_errorLogMutex;
1056 QString m_errorLog;
1057
1058 // ── Render node tracking ─────────────────────────────────────────
1070 std::shared_ptr<ShaderNodeLiveness> m_renderNodeLink;
1075 mutable std::mutex m_renderNodeMutex;
1079 std::shared_ptr<ShaderNodeLiveness> trackedNodeLink() const;
1083 void withTrackedNode(const std::function<void(ShaderNodeRhi*)>& fn) const;
1084 // QPointer defends against reparent/teardown storms where the window is
1085 // destroyed out from under us before windowChanged(nullptr) fires.
1086 QPointer<QQuickWindow> m_connectedWindow;
1099 struct SelfToken
1100 {
1101 std::mutex mutex;
1102 ShaderEffect* effect = nullptr;
1103 };
1104 std::shared_ptr<SelfToken> m_selfToken = std::make_shared<SelfToken>();
1105
1109 void notifyOnGuiThread(void (ShaderEffect::*signal)());
1110
1111 // ── Thread-safe dirty flags for main -> render thread sync ───────
1112 std::atomic<bool> m_shaderDirty{false};
1113};
1114
1115} // namespace PhosphorRendering
QQuickItem that renders a fullscreen fragment shader via Qt RHI.
Definition ShaderEffect.h:81
void reloadShader()
Force reload of shader from source (callable from QML).
qreal effectiveResolutionScale() const
The factor the GPU-bound iResolution is multiplied by.
QColor customColor4() const
Definition ShaderEffect.h:497
QVariant wallpaperTextureVariant() const
QML-facing form of wallpaperTexture, and the reason the Q_PROPERTY is a QVariant rather than a QImage...
void setCustomParams4(const QVector4D &params)
void setCustomParams6(const QVector4D &params)
QVariant audioSpectrumVariant() const
void setUserTexture(int slot, const QImage &image)
Set a user texture (slots 0-3, bindings 7-10) directly from a QImage, bypassing the path-driven loade...
void setUserTextureWrap(int slot, const QString &wrap)
Set user texture wrap mode (slots 0-3).
void setShaderSource(const QUrl &source)
void setIResolution(const QSizeF &resolution)
QColor customColorAt(int index) const
Read a customColor slot by index.
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
QVariantMap shaderParams() const
Definition ShaderEffect.h:283
QString paramPreamble() const
Definition ShaderEffect.h:690
void setCustomColor3(const QColor &color)
void releaseIdleGraphicsResources()
Release the render node's RHI resources (buffer FBOs, pipelines, uploaded textures) while the item si...
bool useDepthBuffer() const
Definition ShaderEffect.h:667
void setBufferShaderPath(const QString &path)
void setCustomColor7(const QColor &color)
QVector4D customParams7() const
Definition ShaderEffect.h:469
QVector4D customParams4() const
Definition ShaderEffect.h:454
void setBufferFilters(const QStringList &filters)
QPointF iMouse() const
Definition ShaderEffect.h:263
void setCustomColor2(const QColor &color)
void setBufferFeedback(bool enable)
void setCustomColor11(const QColor &color)
QColor customColor15() const
Definition ShaderEffect.h:552
void setCustomColor10(const QColor &color)
void statusChanged()
Emitted when status() transitions.
qreal bufferScale() const
Definition ShaderEffect.h:401
bool isReversed() const
Definition ShaderEffect.h:247
QUrl shaderSource() const
Definition ShaderEffect.h:271
QColor customColor1() const
Definition ShaderEffect.h:482
void setStatus(Status newStatus)
void setAudioSpectrumVariant(const QVariant &spectrum)
bool halfFloatBuffers() const
Definition ShaderEffect.h:407
void setCustomColor15(const QColor &color)
bool useWallpaper() const
Definition ShaderEffect.h:661
void setCustomColorAt(int index, const QColor &color)
Write a customColor slot by index.
QColor customColor16() const
Definition ShaderEffect.h:557
void setBufferShaderPaths(const QStringList &paths)
void setPlaying(bool playing)
void setBufferWrap(const QString &wrap)
QUrl vertexShaderUrl() const
Definition ShaderEffect.h:277
void errorLogChanged()
Emitted from setError().
void setCustomParams2(const QVector4D &params)
void setCustomColor9(const QColor &color)
QColor customColor13() const
Definition ShaderEffect.h:542
QVector4D customParams3() const
Definition ShaderEffect.h:449
void setCustomParams7(const QVector4D &params)
QVector4D customParams1() const
Definition ShaderEffect.h:439
void setCustomColor4(const QColor &color)
QColor customColor14() const
Definition ShaderEffect.h:547
void setParamPreamble(const QString &preamble)
Set the generated named-parameter preamble spliced after #version into the fragment source at load ti...
QColor customColor7() const
Definition ShaderEffect.h:512
void setBufferFilter(const QString &filter)
void registerRenderNode(ShaderNodeRhi *node)
Register the live render node for base-class teardown coverage.
QSGNode * updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) override
QVector4D customParamAt(int index) const
Read a customParams slot by index.
void setIMouse(const QPointF &mouse)
void setCustomParamAt(int index, const QVector4D &params)
Write a customParams slot by index.
QVector4D customParams8() const
Definition ShaderEffect.h:474
QStringList bufferFilters() const
Definition ShaderEffect.h:431
void setCustomColor6(const QColor &color)
void setCustomColor13(const QColor &color)
void setCustomParams5(const QVector4D &params)
bool bufferFeedback() const
Definition ShaderEffect.h:395
QString bufferWrap() const
Definition ShaderEffect.h:413
void setCustomParams3(const QVector4D &params)
bool isPlaying() const
Definition ShaderEffect.h:241
void syncBasePropertiesToNode(ShaderNodeRhi *node)
Sync base properties (time, params, colors, audio, multipass, depth, wallpaper, user textures,...
void setBufferWraps(const QStringList &wraps)
QVector4D customParams5() const
Definition ShaderEffect.h:459
QColor customColor3() const
Definition ShaderEffect.h:492
QString bufferFilter() const
Definition ShaderEffect.h:425
Status status() const
Definition ShaderEffect.h:706
QColor customColor2() const
Definition ShaderEffect.h:487
virtual ShaderNodeRhi * createShaderNode()
Factory hook for the render node updatePaintNode() will create.
QStringList bufferWraps() const
Definition ShaderEffect.h:419
void setCustomColor8(const QColor &color)
QColor customColor8() const
Definition ShaderEffect.h:517
QVector4D customParams2() const
Definition ShaderEffect.h:444
QColor customColor11() const
Definition ShaderEffect.h:532
Status
Auto-tick mode.
Definition ShaderEffect.h:175
QStringList bufferShaderPaths() const
Definition ShaderEffect.h:389
void setCustomColor5(const QColor &color)
int iFrame() const
Definition ShaderEffect.h:235
QVector4D customParams6() const
Definition ShaderEffect.h:464
void setShaderIncludePaths(const QStringList &paths)
Set directories to search for #include directives in shaders.
void itemChange(ItemChange change, const ItemChangeData &value) override
void setAudioSpectrum(const QVector< float > &spectrum)
Direct setter from C++ avoiding QVariantList round-trip.
void setCustomColor16(const QColor &color)
void setHalfFloatBuffers(bool enable)
QString errorLog() const
Definition ShaderEffect.h:710
void setCustomColor1(const QColor &color)
void setCustomColor14(const QColor &color)
void setWallpaperTexture(const QImage &image)
void setCustomParams8(const QVector4D &params)
QSizeF iResolution() const
Definition ShaderEffect.h:257
void setEntryScaffold(const QString &prologue, const QList< PhosphorShaders::EntryCandidate > &candidates)
Install the entry-point scaffold forwarded to the render node: when the fragment source defines no ma...
void setITimeDelta(qreal delta)
QColor customColor5() const
Definition ShaderEffect.h:502
QColor customColor6() const
Definition ShaderEffect.h:507
void setIsReversed(bool reverse)
Direction signal forwarded to ShaderNodeRhi → BaseUniforms::iIsReversed.
virtual void setShaderParams(const QVariantMap &params)
Push a parameter map onto the shader.
void setSourceItem(QQuickItem *item)
void setCustomColor12(const QColor &color)
static QImage loadUserTextureFile(const QString &path, int svgMaxDim)
Static helper that loads a user-texture file (PNG/JPG/etc.
QColor customColor12() const
Definition ShaderEffect.h:537
void setError(const QString &error)
void setBufferScale(qreal scale)
void setCustomParams1(const QVector4D &params)
QStringList shaderIncludePaths() const
Definition ShaderEffect.h:677
QColor customColor10() const
Definition ShaderEffect.h:527
QString bufferShaderPath() const
Definition ShaderEffect.h:383
void setVertexShaderUrl(const QUrl &source)
void setWallpaperTextureVariant(const QVariant &texture)
Accepts a QImage, a null, an undefined, an absent key, or an invalid QVariant — a host with nothing b...
qreal iTimeDelta() const
Definition ShaderEffect.h:229
QQuickItem * sourceItem() const
Live texture-provider source bound to SRB binding 7 (uTexture0).
Definition ShaderEffect.h:375
QColor customColor9() const
Definition ShaderEffect.h:522
bool consumeShaderDirty()
Atomically read-and-clear the shader-dirty flag.
Definition ShaderEffect.h:834
QSGRenderNode for fullscreen-quad shader rendering via Qt RHI (Vulkan / OpenGL)
Definition ShaderNodeRhi.h:126
Interface for appending custom uniform data after the base UBO layout.
Definition IUniformExtension.h:18
Definition ShaderCompiler.h:15
PHOSPHORRENDERING_EXPORT QVariant peelQmlVariant(const QVariant &value)
Peel the QML delivery wrappers off a property value and return the inner QVariant.
constexpr int kMaxUserTextureSlots
Public mirror of ShaderNodeRhi::kMaxUserTextures (4 user-texture slots at SRB bindings 7....
Definition ShaderEffect.h:46
constexpr int kDefaultUserTextureSvgSize
Default per-axis rasterisation size for an SVG user texture, used until a slot's shader param overrid...
Definition ShaderEffect.h:50
Definition ShaderEffect.h:33