tessera_ui/renderer/
command.rs

1//! Unified command system for rendering and computation.
2//!
3//! This module defines the `Command` enum that unifies draw and compute operations
4//! into a single type, enabling seamless integration of graphics and compute pipelines
5//! in the rendering workflow.
6
7use std::any::Any;
8
9use crate::{
10    ComputeCommand, DrawCommand,
11    px::{Px, PxRect},
12};
13
14/// Defines the sampling requirements for a rendering command that needs a barrier.
15#[derive(Debug, Clone, Copy, PartialEq)]
16pub enum BarrierRequirement {
17    /// The command needs to sample from the entire previously rendered scene.
18    /// This will cause a full-screen texture copy.
19    Global,
20
21    /// The command needs to sample from a region relative to its own bounding box.
22    /// The `padding` value extends the sampling area beyond the component's own size.
23    /// For example, a `padding` of `10.0` on all sides means the component can
24    /// access pixels up to 10px outside its own boundaries.
25    PaddedLocal {
26        top: Px,
27        right: Px,
28        bottom: Px,
29        left: Px,
30    },
31
32    /// The command needs to sample from a specific, absolute region of the screen.
33    Absolute(PxRect),
34}
35
36impl BarrierRequirement {
37    pub const ZERO_PADDING_LOCAL: Self = Self::PaddedLocal {
38        top: Px::ZERO,
39        right: Px::ZERO,
40        bottom: Px::ZERO,
41        left: Px::ZERO,
42    };
43}
44
45/// Trait providing type erasure capabilities for command objects.
46///
47/// This trait allows commands to be stored and passed around as trait objects
48/// while still providing access to their concrete types when needed for
49/// pipeline dispatch.
50pub trait AsAny {
51    /// Returns a reference to the concrete type as `&dyn Any`.
52    fn as_any(&self) -> &dyn Any;
53}
54
55/// Blanket implementation of `AsAny` for all types that implement `Any`.
56impl<T: Any> AsAny for T {
57    fn as_any(&self) -> &dyn Any {
58        self
59    }
60}
61
62/// Unified command enum that can represent either a draw or compute operation.
63///
64/// This enum enables the rendering system to process both graphics and compute
65/// commands in a unified pipeline, with proper barrier handling for multi-pass
66/// rendering scenarios.
67///
68/// # Examples
69///
70/// ```rust,ignore
71/// // Creating a draw command
72/// let draw_cmd = Command::Draw(Box::new(ShapeCommand::Rect { /* ... */ }));
73///
74/// // Creating a compute command
75/// let compute_cmd = Command::Compute(Box::new(BlurCommand { /* ... */ }));
76/// ```
77pub enum Command {
78    /// A graphics rendering command processed by draw pipelines
79    Draw(Box<dyn DrawCommand>),
80    /// A GPU computation command processed by compute pipelines
81    Compute(Box<dyn ComputeCommand>),
82    /// A command to push a clipping rectangle onto the stack
83    ClipPush(PxRect),
84    /// A command to pop the most recent clipping rectangle from the stack
85    ClipPop,
86}
87
88impl Command {
89    /// Returns the barrier requirement for this command.
90    ///
91    /// Commands that need to sample from previously rendered content
92    /// should return a barrier requirement to ensure proper synchronization.
93    pub fn barrier(&self) -> Option<BarrierRequirement> {
94        match self {
95            Command::Draw(command) => command.barrier(),
96            // Currently, compute can only be used for after effects,
97            Command::Compute(command) => Some(command.barrier()),
98            Command::ClipPush(_) => None, // Clipping commands do not require barriers
99            Command::ClipPop => None,     // Clipping commands do not require barriers
100        }
101    }
102}
103
104impl Clone for Command {
105    fn clone(&self) -> Self {
106        match self {
107            Command::Draw(cmd) => Command::Draw(cmd.clone_box()),
108            Command::Compute(cmd) => Command::Compute(cmd.clone_box()),
109            Command::ClipPush(rect) => Command::ClipPush(*rect),
110            Command::ClipPop => Command::ClipPop,
111        }
112    }
113}
114
115/// Automatic conversion from boxed draw commands to unified commands
116impl From<Box<dyn DrawCommand>> for Command {
117    fn from(val: Box<dyn DrawCommand>) -> Self {
118        Command::Draw(val)
119    }
120}
121
122/// Automatic conversion from boxed compute commands to unified commands
123impl From<Box<dyn ComputeCommand>> for Command {
124    fn from(val: Box<dyn ComputeCommand>) -> Self {
125        Command::Compute(val)
126    }
127}