QQuickItem that renders a fullscreen fragment shader via Qt RHI. More...
#include <phosphor-rendering/include/PhosphorRendering/ShaderEffect.h>
Public Types | |
| enum class | Status { Null , Loading , Ready , Error } |
| Auto-tick mode. More... | |
Signals | |
| void | iTimeChanged () |
| void | iTimeDeltaChanged () |
| void | iFrameChanged () |
| void | iResolutionChanged () |
| void | iMouseChanged () |
| void | isReversedChanged () |
| void | playingChanged () |
| void | shaderSourceChanged () |
| void | vertexShaderUrlChanged () |
| void | shaderParamsChanged () |
| void | paramPreambleChanged () |
| void | sourceItemChanged () |
| void | bufferShaderPathChanged () |
| void | bufferShaderPathsChanged () |
| void | bufferFeedbackChanged () |
| void | bufferScaleChanged () |
| void | halfFloatBuffersChanged () |
| void | bufferWrapChanged () |
| void | bufferWrapsChanged () |
| void | bufferFilterChanged () |
| void | bufferFiltersChanged () |
| void | customParamsChanged () |
| void | customColorsChanged () |
| void | audioSpectrumChanged () |
| void | wallpaperTextureChanged () |
| void | useWallpaperChanged () |
| void | useDepthBufferChanged () |
| void | statusChanged () |
| Emitted when status() transitions. | |
| void | errorLogChanged () |
| Emitted from setError(). | |
Public Member Functions | |
| ShaderEffect (QQuickItem *parent=nullptr) | |
| ~ShaderEffect () override | |
| virtual void | setUniformExtension (std::shared_ptr< PhosphorShaders::IUniformExtension > extension) |
| Attach a uniform extension that appends custom data after BaseUniforms. | |
| std::shared_ptr< PhosphorShaders::IUniformExtension > | uniformExtension () const |
| qreal | iTime () const |
| void | setITime (qreal time) |
| qreal | iTimeDelta () const |
| void | setITimeDelta (qreal delta) |
| int | iFrame () const |
| void | setIFrame (int frame) |
| bool | isPlaying () const |
| void | setPlaying (bool playing) |
| bool | isReversed () const |
| void | setIsReversed (bool reverse) |
| Direction signal forwarded to ShaderNodeRhi → BaseUniforms::iIsReversed. | |
| QSizeF | iResolution () const |
| void | setIResolution (const QSizeF &resolution) |
| QPointF | iMouse () const |
| void | setIMouse (const QPointF &mouse) |
| QUrl | shaderSource () const |
| void | setShaderSource (const QUrl &source) |
| QUrl | vertexShaderUrl () const |
| void | setVertexShaderUrl (const QUrl &source) |
| QVariantMap | shaderParams () const |
| virtual void | setShaderParams (const QVariantMap ¶ms) |
| Push a parameter map onto the shader. | |
| QQuickItem * | sourceItem () const |
Live texture-provider source bound to SRB binding 7 (uTexture0). | |
| void | setSourceItem (QQuickItem *item) |
| QString | bufferShaderPath () const |
| void | setBufferShaderPath (const QString &path) |
| QStringList | bufferShaderPaths () const |
| void | setBufferShaderPaths (const QStringList &paths) |
| bool | bufferFeedback () const |
| void | setBufferFeedback (bool enable) |
| qreal | bufferScale () const |
| void | setBufferScale (qreal scale) |
| bool | halfFloatBuffers () const |
| void | setHalfFloatBuffers (bool enable) |
| QString | bufferWrap () const |
| void | setBufferWrap (const QString &wrap) |
| QStringList | bufferWraps () const |
| void | setBufferWraps (const QStringList &wraps) |
| QString | bufferFilter () const |
| void | setBufferFilter (const QString &filter) |
| QStringList | bufferFilters () const |
| void | setBufferFilters (const QStringList &filters) |
| QVector4D | customParams1 () const |
| void | setCustomParams1 (const QVector4D ¶ms) |
| QVector4D | customParams2 () const |
| void | setCustomParams2 (const QVector4D ¶ms) |
| QVector4D | customParams3 () const |
| void | setCustomParams3 (const QVector4D ¶ms) |
| QVector4D | customParams4 () const |
| void | setCustomParams4 (const QVector4D ¶ms) |
| QVector4D | customParams5 () const |
| void | setCustomParams5 (const QVector4D ¶ms) |
| QVector4D | customParams6 () const |
| void | setCustomParams6 (const QVector4D ¶ms) |
| QVector4D | customParams7 () const |
| void | setCustomParams7 (const QVector4D ¶ms) |
| QVector4D | customParams8 () const |
| void | setCustomParams8 (const QVector4D ¶ms) |
| QColor | customColor1 () const |
| void | setCustomColor1 (const QColor &color) |
| QColor | customColor2 () const |
| void | setCustomColor2 (const QColor &color) |
| QColor | customColor3 () const |
| void | setCustomColor3 (const QColor &color) |
| QColor | customColor4 () const |
| void | setCustomColor4 (const QColor &color) |
| QColor | customColor5 () const |
| void | setCustomColor5 (const QColor &color) |
| QColor | customColor6 () const |
| void | setCustomColor6 (const QColor &color) |
| QColor | customColor7 () const |
| void | setCustomColor7 (const QColor &color) |
| QColor | customColor8 () const |
| void | setCustomColor8 (const QColor &color) |
| QColor | customColor9 () const |
| void | setCustomColor9 (const QColor &color) |
| QColor | customColor10 () const |
| void | setCustomColor10 (const QColor &color) |
| QColor | customColor11 () const |
| void | setCustomColor11 (const QColor &color) |
| QColor | customColor12 () const |
| void | setCustomColor12 (const QColor &color) |
| QColor | customColor13 () const |
| void | setCustomColor13 (const QColor &color) |
| QColor | customColor14 () const |
| void | setCustomColor14 (const QColor &color) |
| QColor | customColor15 () const |
| void | setCustomColor15 (const QColor &color) |
| QColor | customColor16 () const |
| void | setCustomColor16 (const QColor &color) |
| QVector4D | customParamAt (int index) const |
| Read a customParams slot by index. | |
| void | setCustomParamAt (int index, const QVector4D ¶ms) |
| Write a customParams slot by index. | |
| QColor | customColorAt (int index) const |
| Read a customColor slot by index. | |
| void | setCustomColorAt (int index, const QColor &color) |
| Write a customColor slot by index. | |
| QVariant | audioSpectrumVariant () const |
| void | setAudioSpectrumVariant (const QVariant &spectrum) |
| void | setAudioSpectrum (const QVector< float > &spectrum) |
| Direct setter from C++ avoiding QVariantList round-trip. | |
| 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 loader. | |
| void | setUserTextureWrap (int slot, const QString &wrap) |
| Set user texture wrap mode (slots 0-3). | |
| QImage | wallpaperTexture () const |
| QVariant | wallpaperTextureVariant () const |
QML-facing form of wallpaperTexture, and the reason the Q_PROPERTY is a QVariant rather than a QImage. | |
| void | setWallpaperTexture (const QImage &image) |
| void | setWallpaperTextureVariant (const QVariant &texture) |
| Accepts a QImage, a null, an undefined, an absent key, or an invalid QVariant — a host with nothing behind its surface passes one of the latter four, which is the ordinary no-backdrop state rather than an error, and resolves to a null QImage without a warning. | |
| bool | useWallpaper () const |
| void | setUseWallpaper (bool use) |
| bool | useDepthBuffer () const |
| void | setUseDepthBuffer (bool use) |
| void | setShaderIncludePaths (const QStringList &paths) |
| Set directories to search for #include directives in shaders. | |
| QStringList | shaderIncludePaths () const |
| void | setParamPreamble (const QString &preamble) |
Set the generated named-parameter preamble spliced after #version into the fragment source at load time, so authors read a parameter by name (p_speed) instead of a customParams[N].xyzw lane. | |
| QString | paramPreamble () const |
| 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 main(), the node prepends prologue and appends the generated main() of the first candidates entry function the source defines. | |
| Status | status () const |
| QString | errorLog () const |
| void | reloadShader () |
| Force reload of shader from source (callable from QML). | |
| void | releaseIdleGraphicsResources () |
| Release the render node's RHI resources (buffer FBOs, pipelines, uploaded textures) while the item sits idle, without destroying the node, the item, or the window. | |
Static Public Member Functions | |
| static QImage | loadUserTextureFile (const QString &path, int svgMaxDim) |
| Static helper that loads a user-texture file (PNG/JPG/etc. | |
Static Public Attributes | |
| static constexpr int | kMaxSvgDimension = 2048 |
Hard ceiling on the per-axis SVG rasterisation dimension applied by setShaderParams to the uTexture<N>_svgSize parameter. | |
| static constexpr int | kMinSvgDimension = 64 |
| Floor of the same clamp. | |
| static constexpr qint64 | kMaxSvgPixelBytes = 16LL * 1024 * 1024 |
Hard cap on the byte budget for a single rasterised SVG (16 MiB — matches RGBA8 at kMaxSvgDimension × kMaxSvgDimension). | |
Protected Member Functions | |
| QSGNode * | updatePaintNode (QSGNode *oldNode, UpdatePaintNodeData *data) override |
| void | geometryChange (const QRectF &newGeometry, const QRectF &oldGeometry) override |
| void | componentComplete () override |
| void | itemChange (ItemChange change, const ItemChangeData &value) override |
| qreal | effectiveResolutionScale () const |
| The factor the GPU-bound iResolution is multiplied by. | |
| void | syncBasePropertiesToNode (ShaderNodeRhi *node) |
| Sync base properties (time, params, colors, audio, multipass, depth, wallpaper, user textures, uniform extension) to a render node. | |
| bool | consumeShaderDirty () |
| Atomically read-and-clear the shader-dirty flag. | |
| virtual ShaderNodeRhi * | createShaderNode () |
| Factory hook for the render node updatePaintNode() will create. | |
| void | registerRenderNode (ShaderNodeRhi *node) |
| Register the live render node for base-class teardown coverage. | |
| void | setError (const QString &error) |
| void | setStatus (Status newStatus) |
QQuickItem that renders a fullscreen fragment shader via Qt RHI.
Shadertoy-compatible: iTime, iTimeDelta, iFrame, iResolution, iMouse, multipass buffers, custom parameters, and custom colors.
Extend with IUniformExtension to append application-specific uniform data after the base UBO layout.
Consumers that want this type available in QML must register it themselves with qmlRegisterType() under their own module URI. The library does not ship a QML module — doing so would force every consumer onto one module name and duplicate registration with subclasses (e.g. ZoneShaderItem).
|
strong |
Auto-tick mode.
When true, this item hooks the host QQuickWindow's per-frame signal and advances iTime / iTimeDelta / iFrame on every rendered frame. The Shadertoy-style uniforms then "just work" for QML callers — no FrameAnimation / Timer plumbing required.
When false (default) the iTime/iTimeDelta/iFrame Q_PROPERTYs stay fully under the caller's control. This is what kwin-effect's SurfaceAnimator and phosphor-animation's transition shaders use: they drive iTime by hand to map the animation curve through the shader without committing to wall-clock pacing.
Toggling at runtime is supported. While true, the manual setters for iTime/iTimeDelta/iFrame are additive: the next frame's tick adds the wall-clock delta to whatever value is currently stored, so a manual write is preserved as a baseline rather than overwritten. iFrame is incremented by 1 per tick.
Shader loading and compilation status
| Enumerator | |
|---|---|
| Null | No shader loaded. |
| Loading | Shader is being loaded/compiled. |
| Ready | Shader compiled successfully. |
| Error | Shader compilation failed. |
|
explicit |
|
override |
|
signal |
| QVariant PhosphorRendering::ShaderEffect::audioSpectrumVariant | ( | ) | const |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
signal |
|
overrideprotected |
|
inlineprotected |
Atomically read-and-clear the shader-dirty flag.
Subclasses that override updatePaintNode() must call this to observe pending reload requests from setShaderSource / setShaderIncludePaths / reloadShader(). Without consuming the flag, runtime include-path changes never reach the render node.
|
protectedvirtual |
Factory hook for the render node updatePaintNode() will create.
Default returns a plain ShaderNodeRhi. Subclasses that need an enriched node (e.g. ZoneShaderNodeRhi for zone-aware shaders with a labels texture binding) override this to return their own subclass — base updatePaintNode() will then drive that node through the same sync/render flow without subclasses having to duplicate it.
Called only when oldNode is null. Ownership transfers to the scene graph.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
| QColor PhosphorRendering::ShaderEffect::customColorAt | ( | int | index | ) | const |
Read a customColor slot by index.
| index | [0, 16). Returns an invalid QColor for out-of-range indices. |
|
signal |
| QVector4D PhosphorRendering::ShaderEffect::customParamAt | ( | int | index | ) | const |
Read a customParams slot by index.
| index | [0, 8). Returns a zero vector for out-of-range indices. |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
signal |
|
protected |
The factor the GPU-bound iResolution is multiplied by.
1.0 when the installed extension reports requiresPhysicalResolution() == false (the animation path keeps iResolution logical), and 1.0 whenever the item has no window or the window has no screen. Otherwise the window's effective device-pixel ratio. See the extended rationale at the call site in syncBasePropertiesToNode().
Exposed because a subclass that puts its own lengths into the UBO has to agree with iResolution or its geometry lands in a different space. That agreement is the whole contract, so it is one function rather than a derivation each subclass re-implements and a comment asking them to keep the copies in step.
|
inline |
|
signal |
Emitted from setError().
Same delivery contract as statusChanged(): marshalled to the object's thread by notifyOnGuiThread, so any connection type is safe, and a handler should read errorLog() rather than assume one delivery per write (the log itself is written synchronously under its mutex before the notify is posted, so the handler always observes the updated value).
|
overrideprotected |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
inline |
|
signal |
|
overrideprotected |
|
inline |
|
signal |
|
inline |
|
signal |
|
static |
Static helper that loads a user-texture file (PNG/JPG/etc.
via QImageReader, downscaled during decode when the file exceeds the kMaxSvgPixelBytes budget; SVG/SVGZ via QSvgRenderer rasterised at svgMaxDim max-axis with the same byte-budget guard as setShaderParams). Thread-safe: each invocation constructs its own QSvgRenderer / QImage instance — callers may invoke from a worker thread (e.g. QtConcurrent::run) to off-load the cost from the GUI thread. Returns a null QImage on load failure (file missing, parse error, OOM); callers should keep their prior image in that case. The result is in QImage::Format_RGBA8888, ready for setUserTexture(slot, image) upload on the GUI thread.
|
inline |
|
signal |
|
signal |
|
protected |
Register the live render node for base-class teardown coverage.
The base tracks the node it returned from updatePaintNode so the destructor and the sceneGraphAboutToStop handler can sever the node's back-pointer (invalidateItem) / release its GPU resources. That tracking member is private and is only set by the BASE updatePaintNode — a subclass that fully reimplements updatePaintNode (SurfaceShaderItem) MUST register its node here (and register nullptr when it deletes the node) or the base teardown silently no-ops and a render-thread access between item destruction and node deletion walks a freed item.
Registration takes a share of the node's liveness block, so the base no longer has to guess whether a tracked node is still alive — see ShaderNodeLiveness. Re-registering the same node every frame (the documented usage) is an early-out, not a refcount churn.
| void PhosphorRendering::ShaderEffect::releaseIdleGraphicsResources | ( | ) |
Release the render node's RHI resources (buffer FBOs, pipelines, uploaded textures) while the item sits idle, without destroying the node, the item, or the window.
Safe to call from the GUI thread: the release runs as a scheduled render job on the scene-graph thread, the only thread allowed to touch the node. Everything re-creates lazily through the ensure* paths on the next painted frame (the same recovery the device-loss path exercises), so the cost of calling this on a window that immediately resumes is one warm-up frame, not a teardown. Note the call itself always requests one composited frame of the window (QQuickWindow::update()): that frame is what dispatches the release on an otherwise idle window and what flushes any park state the caller latched alongside.
Intended for long-lived, kept-alive windows whose content goes invisible for long stretches (the daemon's idle-quiesced overlays): an invisible item never reaches updatePaintNode, so without this its full-screen render targets stay pinned in (shared, on an iGPU) memory for the window's whole lifetime.
| void PhosphorRendering::ShaderEffect::reloadShader | ( | ) |
Force reload of shader from source (callable from QML).
| void PhosphorRendering::ShaderEffect::setAudioSpectrum | ( | const QVector< float > & | spectrum | ) |
Direct setter from C++ avoiding QVariantList round-trip.
| void PhosphorRendering::ShaderEffect::setAudioSpectrumVariant | ( | const QVariant & | spectrum | ) |
| void PhosphorRendering::ShaderEffect::setBufferFeedback | ( | bool | enable | ) |
| void PhosphorRendering::ShaderEffect::setBufferFilter | ( | const QString & | filter | ) |
| void PhosphorRendering::ShaderEffect::setBufferFilters | ( | const QStringList & | filters | ) |
| void PhosphorRendering::ShaderEffect::setBufferScale | ( | qreal | scale | ) |
| void PhosphorRendering::ShaderEffect::setBufferShaderPath | ( | const QString & | path | ) |
| void PhosphorRendering::ShaderEffect::setBufferShaderPaths | ( | const QStringList & | paths | ) |
| void PhosphorRendering::ShaderEffect::setBufferWrap | ( | const QString & | wrap | ) |
| void PhosphorRendering::ShaderEffect::setBufferWraps | ( | const QStringList & | wraps | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor1 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor10 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor11 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor12 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor13 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor14 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor15 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor16 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor2 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor3 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor4 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor5 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor6 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor7 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor8 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColor9 | ( | const QColor & | color | ) |
| void PhosphorRendering::ShaderEffect::setCustomColorAt | ( | int | index, |
| const QColor & | color | ||
| ) |
Write a customColor slot by index.
| index | [0, 16). Out-of-range indices are ignored. |
| void PhosphorRendering::ShaderEffect::setCustomParamAt | ( | int | index, |
| const QVector4D & | params | ||
| ) |
Write a customParams slot by index.
| index | [0, 8). Out-of-range indices are ignored. |
Emits customParamsChanged() and schedules an update only when the value actually differs from the stored slot.
| void PhosphorRendering::ShaderEffect::setCustomParams1 | ( | const QVector4D & | params | ) |
| void PhosphorRendering::ShaderEffect::setCustomParams2 | ( | const QVector4D & | params | ) |
| void PhosphorRendering::ShaderEffect::setCustomParams3 | ( | const QVector4D & | params | ) |
| void PhosphorRendering::ShaderEffect::setCustomParams4 | ( | const QVector4D & | params | ) |
| void PhosphorRendering::ShaderEffect::setCustomParams5 | ( | const QVector4D & | params | ) |
| void PhosphorRendering::ShaderEffect::setCustomParams6 | ( | const QVector4D & | params | ) |
| void PhosphorRendering::ShaderEffect::setCustomParams7 | ( | const QVector4D & | params | ) |
| void PhosphorRendering::ShaderEffect::setCustomParams8 | ( | const QVector4D & | params | ) |
| void PhosphorRendering::ShaderEffect::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 main(), the node prepends prologue and appends the generated main() of the first candidates entry function the source defines.
Empty/empty (the default) disables assembly. Forces a reload so the new scaffold takes; folded into the node's bake-cache key.
|
protected |
| void PhosphorRendering::ShaderEffect::setHalfFloatBuffers | ( | bool | enable | ) |
| void PhosphorRendering::ShaderEffect::setIFrame | ( | int | frame | ) |
| void PhosphorRendering::ShaderEffect::setIMouse | ( | const QPointF & | mouse | ) |
| void PhosphorRendering::ShaderEffect::setIResolution | ( | const QSizeF & | resolution | ) |
| void PhosphorRendering::ShaderEffect::setIsReversed | ( | bool | reverse | ) |
Direction signal forwarded to ShaderNodeRhi → BaseUniforms::iIsReversed.
SurfaceAnimator pushes this on every leg attach (false for show, true for hide). Symmetric shaders ignore the value; asymmetric shaders branch on it (see canonical animation_uniforms.glsl docs).
| void PhosphorRendering::ShaderEffect::setITime | ( | qreal | time | ) |
| void PhosphorRendering::ShaderEffect::setITimeDelta | ( | qreal | delta | ) |
| void PhosphorRendering::ShaderEffect::setParamPreamble | ( | const QString & | preamble | ) |
Set the generated named-parameter preamble spliced after #version into the fragment source at load time, so authors read a parameter by name (p_speed) instead of a customParams[N].xyzw lane.
Empty (the default) is a no-op. Forwarded to the render node and folded into its bake-cache key; a change forces a reload so the new defines take.
| void PhosphorRendering::ShaderEffect::setPlaying | ( | bool | playing | ) |
| void PhosphorRendering::ShaderEffect::setShaderIncludePaths | ( | const QStringList & | paths | ) |
Set directories to search for #include directives in shaders.
|
virtual |
Push a parameter map onto the shader.
Recognised keys: • customParams<N>_<x|y|z|w> (1-based) — float vec4 sub-slots • customColor<N> (1-based) — color vec4 slots • uTexture<N> (0-based, 0..3) — file path for the user-texture sampler at SRB binding 7..10 / GLSL uTexture<N> • uTexture<N>_wrap — wrap mode string ("clamp" / "repeat" / "mirror"); ignored if no companion uTexture<N> resolves • uTexture<N>_svgSize — SVG rasterise max-axis dimension (clamped 64..2048; ignored for bitmap formats). The cap is exposed as ShaderEffect::kMaxSvgDimension for callers that want to mirror the clamp without hardcoding the value, and the per-rasterisation byte budget is exposed as ShaderEffect::kMaxSvgPixelBytes (a near-square doc whose RGBA8 size would exceed the budget is downscaled proportionally with a warning).
Trust boundary. uTexture<N> paths are passed verbatim to QImage::load / QSvgRenderer::load. This class does NOT sanitise traversal segments or enforce absolute-path-only — the caller is the trust boundary. AnimationShaderRegistry::translateAnimationParams already resolves and traversal-checks pack-default paths at scan time; the kwin-effect's m_textureCache lookup keys absolute paths. A direct caller (e.g. tests, custom QML embedding) that forwards untrusted strings into params["uTexture<N>"] MUST pre-resolve and traversal-check before calling.
SVG rasterisation cost. When the params map contains a uTexture<N> whose path resolves to an .svg / .svgz file (and the path or uTexture<N>_svgSize differs from the cached state for that slot), this method calls QSvgRenderer and QPainter synchronously on the calling thread to rasterise the document up to the clamped dimension. The cost scales with kMaxSvgPixelBytes in the worst case. Hot-path callers (e.g. per-frame parameter pushes) should pre-warm via loadUserTextureFile(path, svgMaxDim) from a worker thread (it's thread-safe per Qt docs: each call constructs its own QSvgRenderer / QImage instance with no shared mutable state) and call setUserTexture(slot, image) on the GUI thread to install the result. Bitmap formats are decoded via QImageReader under the same kMaxSvgPixelBytes budget — an oversized file is downscaled during decode with a warning, never materialised at full resolution — and carry the same synchronous-IO caveat.
Subclass contract. Overrides MUST chain to ShaderEffect::setShaderParams(params) (or replicate the full trust-boundary parse, including uTexture* / *_wrap / *_svgSize). Skipping the base call leaves user-texture paths uninterpreted and pinned to whatever the previous parse set — silent stale samplers across reloads.
| void PhosphorRendering::ShaderEffect::setShaderSource | ( | const QUrl & | source | ) |
| void PhosphorRendering::ShaderEffect::setSourceItem | ( | QQuickItem * | item | ) |
|
protected |
|
virtual |
Attach a uniform extension that appends custom data after BaseUniforms.
Stored on this item and pushed down to the render node in syncBasePropertiesToNode(). virtual so a subclass that owns its own extension (e.g. ZoneShaderItem) can intercept stray assignments and preserve its internal extension contract instead of having the call silently no-op.
| void PhosphorRendering::ShaderEffect::setUseDepthBuffer | ( | bool | use | ) |
| void PhosphorRendering::ShaderEffect::setUserTexture | ( | int | slot, |
| const QImage & | image | ||
| ) |
Set a user texture (slots 0-3, bindings 7-10) directly from a QImage, bypassing the path-driven loader.
Clears the per-slot cached path and resets the companion svgSize / wrap settings so a subsequent params-driven load starts from a clean slot.
Mixing-with-setShaderParams contract: a subsequent setShaderParams(p) will reload the texture from p["uTextureN"] even when p is byte-equal to the cached params map. The intervening direct-push sets a private dirty flag that suppresses the equality short-circuit on the very next call, so the cleared path is honoured and the on-disk image replaces the directly-set QImage. After that one re-parse, the flag is cleared and the usual fast-path resumes.
| void PhosphorRendering::ShaderEffect::setUserTextureWrap | ( | int | slot, |
| const QString & | wrap | ||
| ) |
Set user texture wrap mode (slots 0-3).
"clamp", "repeat", or "mirror".
| void PhosphorRendering::ShaderEffect::setUseWallpaper | ( | bool | use | ) |
| void PhosphorRendering::ShaderEffect::setVertexShaderUrl | ( | const QUrl & | source | ) |
| void PhosphorRendering::ShaderEffect::setWallpaperTexture | ( | const QImage & | image | ) |
| void PhosphorRendering::ShaderEffect::setWallpaperTextureVariant | ( | const QVariant & | texture | ) |
Accepts a QImage, a null, an undefined, an absent key, or an invalid QVariant — a host with nothing behind its surface passes one of the latter four, which is the ordinary no-backdrop state rather than an error, and resolves to a null QImage without a warning.
A VALID but unconvertible value (a QString, a QUrl, a number) also clears, but logs first: that one is a host bug, not an ordinary state.
|
inline |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
Live texture-provider source bound to SRB binding 7 (uTexture0).
When set to a non-null QQuickItem, the shader samples that item's rendered visual every frame instead of whatever QImage was uploaded via setUserTexture(0, ...). This is what the SurfaceAnimator transition shaders (pixelate / dissolve / glitch) use to operate on the rendered surface — no async grab, no first-show gap, no stale snapshot.
The item is forced to layer.enabled = true on the QML side so QQuickItem::textureProvider() returns the layer's provider; the scene graph allocates an FBO and re-renders the item each frame the consumer dirties it. The shader effect's parent must NOT be the source item (or any of its descendants) — sampling within the same layer creates a feedback loop where the shader's own output is captured into the next frame's texture. Park the shader effect as a sibling of the source item instead.
Setting the property to nullptr unbinds the texture; subsequent frames fall back to the user-texture-0 QImage path (or the transparent fallback if neither has been set).
|
signal |
|
inline |
|
signal |
Emitted when status() transitions.
Always delivered on the object's (GUI) thread: setStatus is called from updatePaintNode on the render thread under Qt's threaded loop, and notifyOnGuiThread marshals the emission there via a queued call — so any connection type is safe, including DirectConnection. Consequence of the marshalling: when a transition originates in the sync phase, delivery is asynchronous relative to the m_status write, and two rapid transitions can coalesce from a handler's point of view (both handlers run with the final status). Handlers MUST gate on the current status() value and must not assume one delivery per transition.
|
protected |
Sync base properties (time, params, colors, audio, multipass, depth, wallpaper, user textures, uniform extension) to a render node.
Does NOT sync shader source — that load is owned by updatePaintNode's needLoad branch (and differs between ShaderEffect and subclasses).
Called from updatePaintNode(); subclasses that override updatePaintNode should call this instead of duplicating the property sync.
| std::shared_ptr< PhosphorShaders::IUniformExtension > PhosphorRendering::ShaderEffect::uniformExtension | ( | ) | const |
|
overrideprotected |
|
inline |
|
signal |
|
inline |
|
signal |
|
inline |
|
signal |
| QImage PhosphorRendering::ShaderEffect::wallpaperTexture | ( | ) | const |
|
signal |
| QVariant PhosphorRendering::ShaderEffect::wallpaperTextureVariant | ( | ) | const |
QML-facing form of wallpaperTexture, and the reason the Q_PROPERTY is a QVariant rather than a QImage.
QML cannot reliably drive a QImage-typed property: a Binding on wallpaperTexture { value: someVarHoldingAnImage } writes NOTHING AT ALL — silently, with no engine warning — while the sibling bool binding beside it applies. That is how every decoration preview in the settings app came to render its no-backdrop fallback: the image reached the host QML and stopped there.
Measured delivery shapes (Qt 6.11.2), because the retype alone does not rescue a Binding and the difference decides how a host must write this:
item.wallpaperTexture = someImage), a createObject initial-property map, and a C++ setProperty all deliver the image intact;null arrives as a VALID std::nullptr_t;undefined, an ABSENT key on a JS object, an undefined property var, and BOTH Binding forms (the Binding { target: …; property: … } element and Binding on wallpaperTexture) ALL arrive as an INVALID QVariant, carrying no payload at all. The QVariant property type does not change that; only writing the value directly does.So a host must assign this property directly. An invalid QVariant is treated as "no texture" and clears, which is correct for the absent-key and undefined cases and is the only option for the Binding case: the two are INDISTINGUISHABLE at the setter. That is why the QML-source sweep test — not this code — is the guard against a host driving one property from both a direct assignment and a Binding.
Mirrors the audioSpectrum property beside it, which is a QVariant for the same class of reason.
|
staticconstexpr |
Hard ceiling on the per-axis SVG rasterisation dimension applied by setShaderParams to the uTexture<N>_svgSize parameter.
Exposed so consumers (UI sliders, validators, tests) can mirror the clamp range without hardcoding the value. The setter performs qBound(kMinSvgDimension, requested, kMaxSvgDimension); values outside the range are silently clamped, not rejected.
|
staticconstexpr |
Hard cap on the byte budget for a single rasterised SVG (16 MiB — matches RGBA8 at kMaxSvgDimension × kMaxSvgDimension).
When a near-square doc would exceed this even after the per-axis clamp, the rasterisation is downscaled proportionally and a warning is logged. Exposed for the same mirror-the-cap reason as kMaxSvgDimension.
|
staticconstexpr |
Floor of the same clamp.
Named for the same mirror-the-cap reason as kMaxSvgDimension, and so the two qBound sites in shadereffect_params.cpp stop repeating a bare literal.