Mixin for widgets whose body can be painted by a custom SkSL shader. More...
#include <custom_shader_host.hpp>
Classes | |
| struct | ShaderValueBinding |
| struct | ShaderScopeBinding |
Public Member Functions | |
| virtual | ~CustomShaderHost ()=default |
| void | set_custom_shader (std::string sksl) |
| Install an SkSL body shader. | |
| void | clear_custom_shader () |
| Remove the shader and restore the default C++ paint path. | |
| bool | has_custom_shader () const |
| const std::string & | custom_shader () const |
| void | set_chart_shader (std::string sksl, float reach=0.0f) |
| Install a chart shader with the extra reach its own source needs (a glow preset's halo). | |
| const std::string & | chart_shader () const |
| float | chart_reach () const |
| void | set_shader_uniforms (std::vector< canvas::Canvas::NamedUniform > uniforms) |
| const std::vector< canvas::Canvas::NamedUniform > & | shader_uniforms () const |
| void | set_shader_value_bindings (std::vector< ShaderValueBinding > bindings) |
| const std::vector< ShaderValueBinding > & | shader_value_bindings () const |
| std::vector< ShaderValueBinding > & | shader_value_bindings () |
| bool | shader_uniform_bound (const std::string &name) const |
| void | set_shader_scope_binding (std::optional< ShaderScopeBinding > binding) |
| const std::optional< ShaderScopeBinding > & | shader_scope_binding () const |
| std::optional< ShaderScopeBinding > & | shader_scope_binding () |
| bool | set_shader_uniform_value (const std::string &name, float value) |
| void | set_shader_reach (float reach) |
| float | shader_reach () const |
| void | set_shader_geometry (std::optional< canvas::Canvas::ShaderGeometry > geometry) |
| const std::optional< canvas::Canvas::ShaderGeometry > & | shader_geometry () const |
| void | set_shader_geometry_spec (std::string spec, std::uint64_t topology_hash) |
| const std::string & | shader_geometry_spec () const |
| std::uint64_t | shader_geometry_topology_hash () const |
| bool | shader_uses_time () const |
| True when the shader actually declares a time uniform, and therefore needs a continuous repaint to animate. | |
| bool | shader_draw_failure_logged () const |
| One-shot latch for "the body shader failed to draw and we logged it". | |
| void | mark_shader_draw_failure_logged () |
Mixin for widgets whose body can be painted by a custom SkSL shader.
The shader replaces the widget's body / track / fill drawing only — labels, value text, and hover glow keep painting in C++. Widgets opt in by inheriting this alongside View, which is what makes shader support discoverable: the JS bridge locates shader-capable widgets with a single dynamic_cast<CustomShaderHost*> rather than a hardcoded chain of concrete widget types.
The render loop discovers this mixin too. Core shader widgets use an allocation-free type tag on their hot path; any other future widget falls back to this mixin, including a subclass that inherits a non-shader tag, so a shader declaring a time uniform still keeps its view tree live.
|
virtualdefault |
|
inline |
|
inline |
| void pulp::view::CustomShaderHost::clear_custom_shader | ( | ) |
Remove the shader and restore the default C++ paint path.
|
inline |
|
inline |
|
inline |
|
inline |
Install a chart shader with the extra reach its own source needs (a glow preset's halo).
That reach is replaced with the shader, so moving from a glow to a preset without one does not keep the wide rect, and it pads only the chart draw, never the body shader's.
| void pulp::view::CustomShaderHost::set_custom_shader | ( | std::string | sksl | ) |
Install an SkSL body shader.
Whether the shader is time-driven is resolved once, here — see shader_uses_time().
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
One-shot latch for "the body shader failed to draw and we logged it".
A shader can fail at DRAW time (not just install time) — e.g. the runtime effect compiles but the backend can't produce a shader — and the widget paint path must then fall back to its C++ body instead of leaving the widget blank. The paint path logs that once per host instance (guarded by this latch) so it does not spam a line every frame.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
True when the shader actually declares a time uniform, and therefore needs a continuous repaint to animate.
Resolved when the shader is installed, not on each call: this is read once per widget per frame by needs_continuous_frames(), so it must not recompile or rescan. It is a real uniform lookup on the compiled effect, not a substring search — a shader with a timeline uniform must not pin the render loop to 120 Hz, and one that spells its uniform differently must not silently freeze.
|
inline |
|
inline |