Expand description
Filter wire types, built-in filters, and the filter registry: the
layer-based filter style chain.
This module owns the filter wire format and registry the way
crate::canvas/crate::animations own theirs: protocol/
reconcile/ui_map reference these types by module path, never the
reverse. On the wire a filter is one {"name", "params"} object or an
ordered array of them; params stays an untyped JSON map at this layer —
typed validation happens later against the registry, not during decode.
Decoding follows the protocol’s warn-don’t-abort convention (see
Length’s custom Deserialize): a malformed
value emits a decode_warn and the whole chain degrades to empty, never
failing the containing Style’s deserialization.
The typed layer below the wire — ReactFilter, the built-in param
structs, and FilterRegistry — turns a FilterUse into
ResolvedFilterPasses: deserialize the raw params (strict:
deny-unknown-fields), pack them into a Vec4 uniform array with a
ParamSlot layout (no-straddle rule: a slot never crosses a Vec4
boundary), and pick the pass shader. The ten built-ins register via
register_builtin_filters; custom filters are #[react_filter] structs
registered with add_react_filter.
The module also owns the runtime write path of a chain.
resolve_chains turns a promoted root’s FilterInput into a
ResolvedFilterChain component — resolving each entry against the
registry (invalid entries skip with a filterParams warning), rewriting
Length slots to physical px, stamping ResolvedFilterPass::wire_index,
and summing the chain outset. The interpolation primitives
(lerp_packed_params, lerp_angle) blend packed param arrays
layout-aware for the easing paths. Exactly three systems write
ResolvedFilterChain and bump its version counter: the resolver’s
snap, the transition filter channel’s whole-value ease (transition.rs,
planned by [plan_filter_ease] with identity-padding for chain
extensions), and the animation per-param filter[<i>].<param> bindings
(animations) — see ResolvedFilterChain::version for the writer
registry and precedence.
File map: wire (the wire format + warn-don’t-abort decode), params
(packing layout, caps, param value types, interpolation), registry (the
ReactFilter trait, resolved passes, the registry), builtin (the
ten built-ins), transition (whole-value filter transition planning),
resolve (the chain resolve system). Submodules are private; everything
is re-exported here, so crate::filters::X is the one path.
Structs§
- Backdrop
Input - The wire
backdropFilterchain of a node, mirrored off the applied style bycrate::ui_map::apply_style_masked’s BACKDROP arm — present iff the style carries a non-empty chain. Same contract asFilterInput: the style apply owns writes (the applied style may be hover/press/focus-merged), the resolver only reads. - Bloom
Params bloom: glow where bright areas bleed light — a bright-pass thresholded atthreshold, blurred byradius, and added back onto the original scaled byintensity.{ name: "bloom" }with no params is a visible glow (shorthand-default convention); the true identity isintensity: 0.- Blur
Params blur: separable Gaussian blur.radiusdefaults to0— CSSblur()with the value omitted means0(identity).- Brightness
Params brightness:amountdefaults to1.0— CSSbrightness()with the value omitted means1(identity).- Chromatic
Aberration Params chromaticAberration: directional color fringing — the R channel’s image shiftsoffsetpx alongangle(degrees, clockwise from +X in screen space; bare number = degrees,"0.25turn"etc. accepted), B the same distance opposite, G stays put. The split is uniform across the layer.{ name: "chromaticAberration" }with no params is visible fringing (shorthand-default convention); the true identity isoffset: 0.- Contrast
Params contrast:amountdefaults to1.0— CSScontrast()with the value omitted means1(identity).- Filter
Chain - An ordered filter chain. Decodes from a single
{"name", "params"}object (a 1-element chain) or an array of them (applied in order); any malformed entry — or non-object/array garbage — warns and degrades the whole value to an empty chain. - Filter
Color - A color filter parameter: linear (shader-ready) straight-alpha RGBA.
- Filter
Input - The wire
filterchain of a node, mirrored off the applied style by the apply path (crate::ui_map::apply_style_masked’s FILTER arm) — present iff the style carries a non-empty chain. The thin input side of theresolve_chainssystem, mirroring thecrate::transition::TransitionInputpattern: the style apply owns writes, the resolver only reads. The applied style may be a hover/press/focus- merged one (the field isoverlay), so an interaction flip re-stamps the merged chain here. - Filter
Registration - One registered filter: everything the chain resolver needs, baked into
AssetServer-free fn pointers at registration time (shader loading stays lazy — the pointers receive the&AssetServer). - Filter
Registry - Known filters, keyed by wire name. Populated by
register_builtin_filters; consumed byresolve_chains. - Filter
Use - One filter invocation in a chain: a registry name plus its raw, untyped
parameter map (empty when the wire object has no
paramsorparamsisnull). - Grayscale
Params grayscale:amountdefaults to1.0— CSSgrayscale()with the value omitted means1(full effect; identity is0), so a bare{name:"grayscale"}applies the effect.- HueRotate
Params hueRotate:angledefaults to0deg— CSShue-rotate()with the value omitted means0deg(identity). Packs radians atparams[1].zof the shared color-matrix packing.- Invert
Params invert:amountdefaults to1.0— CSSinvert()with the value omitted means1(full effect; identity is0).- Param
Slot - Where one named parameter lands in a pass’s packed
Vec4array:vecis theVec4index,compthe starting component within it,lenhow many consecutive components the param spans. - Resolved
Backdrop Chain - A node’s fully resolved
backdropFilterchain — a newtype overResolvedFilterChainso extract, transitions, animations, and devtools reuse the inner type via.0. Attached to promoted roots by the backdropresolve_chainsinstance; absent when the chain has no valid entries. Removed on demotion byevaluate_layer_promotions’s cleanup (like the content chain). - Resolved
Filter Chain - A node’s fully resolved
filterchain, attached to promoted layer roots byresolve_chains. Absent on a promoted root whose chain has no valid entries (pure capture/composite — no filter machinery). - Resolved
Filter Pass - One resolved render pass of a filter chain.
- Saturate
Params saturate:amountdefaults to1.0— CSSsaturate()with the value omitted means1(identity).- Sepia
Params sepia:amountdefaults to1.0— CSSsepia()with the value omitted means1(full effect; identity is0).
Constants§
- MAX_
CHAIN_ LEN - Longest decodable chain.
ResolvedFilterPass::wire_indexis au8, so only entry indices0..=u8::MAXare addressable; a longer chain is nonsense input and degrades whole-value like any other malformed chain. - MAX_
FILTER_ OUTSET_ PX - Defensive cap on a chain’s summed outset, physical px per side. Far beyond
any sane blur (quality is bounded well before this — see
blur.wgsl’s MAX_HALF note), it bounds the inflation math:2 * outsetadds at most 2048 texels to the capture, leaving real headroom under wgpu’s default 8192max_texture_dimension_2dfor the content itself. (Texture-limit safety proper is the allocator’s concern, not this cap’s.) - MAX_
FILTER_ PARAM_ VECS - Cap on the packed
Vec4array per pass — the fixed-size uniform array the filter shaders declare.
Traits§
- Chain
Input - Input side of one
resolve_chainsinstance: which wire-chain component feeds it, its diag kinds, and per-instance semantics. Implemented byFilterInput(the contentfilterchain) andBackdropInput(backdropFilter). - React
Filter - A typed, named filter: how its params deserialize (strict — built-ins use
#[serde(deny_unknown_fields)]), pack into shader uniforms, and resolve into render passes. - Resolved
Chain - Output side of one
resolve_chainsinstance — a component wrapping (or being) aResolvedFilterChain. The newtype projection keeps every downstream consumer (extract, transitions, animations, devtools) on the one inner type.
Functions§
- length_
logical_ px - A
Lengthfilter param’s logical-px value. OnlyPxhas a fixed logical size here — percent/viewport units have no basis for a filter param — so any other unit is rejected with a message naming it, instead of silently resolving to0.0. Bare wire numbers decode asPxand stay accepted. - lerp_
angle - Shortest-arc interpolation between two angles in radians, for packed
ValueKind::Anglefilter params. - lerp_
packed_ params - Interpolate two packed param arrays of the same layout, slot-by-slot: the layout (not the raw components) decides how each param blends.
- quantize_
outset - Quantize a physical-px outset up to the next multiple of 16 so an animated radius grows a layer texture in coarse steps instead of reallocating every frame.
- register_
builtin_ filters - Register the ten built-in filters. Called by
ReactUiPlugin::build. DeliberatelyAssetServer-free: shader loads happen lazily inside each entry’sresolve. - resolve_
chains - Turn each promoted root’s wire chain input
Iinto a packed resolved chainR. Two instances run inUpdateafter the interaction restyle (the last input writer this frame) and before the transition/animation appliers — both write onto the resolved chain: the content instance (FilterInput→ResolvedFilterChain, thefilterstyle) and the backdrop instance (BackdropInput→ResolvedBackdropChain, thebackdropFilterstyle — seecrate::filters::backdrop). - resolve_
single_ pass - The default single-pass resolve body:
ReactFilter::pack+ the param-vec cap check + one pass taggedwire_index: 0.