1 //! Output Merger (OM) stage description.
2 //! The final stage in a pipeline that creates pixel colors from
3 //! the input shader results, depth/stencil information, etc.
4 
5 use crate::pso::{graphics::StencilValue, State};
6 
7 /// A pixel-wise comparison function.
8 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
9 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10 pub enum Comparison {
11     /// `false`
12     Never = 0,
13     /// `x < y`
14     Less = 1,
15     /// `x == y`
16     Equal = 2,
17     /// `x <= y`
18     LessEqual = 3,
19     /// `x > y`
20     Greater = 4,
21     /// `x != y`
22     NotEqual = 5,
23     /// `x >= y`
24     GreaterEqual = 6,
25     /// `true`
26     Always = 7,
27 }
28 
29 bitflags!(
30     /// Target output color mask.
31     #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32     pub struct ColorMask: u8 {
33         /// Red mask
34         const RED     = 0x1;
35         /// Green mask
36         const GREEN   = 0x2;
37         /// Blue mask
38         const BLUE    = 0x4;
39         /// Alpha channel mask
40         const ALPHA   = 0x8;
41         /// Mask for RGB channels
42         const COLOR   = 0x7;
43         /// Mask all channels
44         const ALL     = 0xF;
45         /// Mask no channels.
46         const NONE    = 0x0;
47     }
48 );
49 
50 impl Default for ColorMask {
default() -> Self51     fn default() -> Self {
52         Self::ALL
53     }
54 }
55 
56 /// Defines the possible blending factors.
57 /// During blending, the source or destination fragment may be
58 /// multiplied by a factor to produce the final result.
59 #[allow(missing_docs)]
60 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
61 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62 pub enum Factor {
63     Zero = 0,
64     One = 1,
65     SrcColor = 2,
66     OneMinusSrcColor = 3,
67     DstColor = 4,
68     OneMinusDstColor = 5,
69     SrcAlpha = 6,
70     OneMinusSrcAlpha = 7,
71     DstAlpha = 8,
72     OneMinusDstAlpha = 9,
73     ConstColor = 10,
74     OneMinusConstColor = 11,
75     ConstAlpha = 12,
76     OneMinusConstAlpha = 13,
77     SrcAlphaSaturate = 14,
78     Src1Color = 15,
79     OneMinusSrc1Color = 16,
80     Src1Alpha = 17,
81     OneMinusSrc1Alpha = 18,
82 }
83 
84 /// Blending operations.
85 #[allow(missing_docs)]
86 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
87 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
88 pub enum BlendOp {
89     /// Adds source and destination.
90     /// Source and destination are multiplied by factors before addition.
91     Add { src: Factor, dst: Factor },
92     /// Subtracts destination from source.
93     /// Source and destination are multiplied by factors before subtraction.
94     Sub { src: Factor, dst: Factor },
95     /// Subtracts source from destination.
96     /// Source and destination are multiplied by factors before subtraction.
97     RevSub { src: Factor, dst: Factor },
98     /// Component-wise minimum value of source and destination.
99     Min,
100     /// Component-wise maximum value of source and destination.
101     Max,
102 }
103 
104 impl BlendOp {
105     /// Replace the destination value with the source.
106     pub const REPLACE: Self = BlendOp::Add {
107         src: Factor::One,
108         dst: Factor::Zero,
109     };
110     /// Add the source and destination together.
111     pub const ADD: Self = BlendOp::Add {
112         src: Factor::One,
113         dst: Factor::One,
114     };
115     /// Alpha blend the source and destination together.
116     pub const ALPHA: Self = BlendOp::Add {
117         src: Factor::SrcAlpha,
118         dst: Factor::OneMinusSrcAlpha,
119     };
120     /// Alpha blend a premultiplied-alpha source with the destination.
121     pub const PREMULTIPLIED_ALPHA: Self = BlendOp::Add {
122         src: Factor::One,
123         dst: Factor::OneMinusSrcAlpha,
124     };
125 }
126 
127 /// Specifies whether to use blending, and if so,
128 /// which operations to use for color and alpha channels.
129 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
130 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
131 pub struct BlendState {
132     /// The blend operation to use for the color channels.
133     pub color: BlendOp,
134     /// The blend operation to use for the alpha channel.
135     pub alpha: BlendOp,
136 }
137 
138 impl BlendState {
139     /// Replace the color.
140     pub const REPLACE: Self = BlendState {
141         color: BlendOp::REPLACE,
142         alpha: BlendOp::REPLACE,
143     };
144     /// Additive blending.
145     pub const ADD: Self = BlendState {
146         color: BlendOp::ADD,
147         alpha: BlendOp::ADD,
148     };
149     /// Multiplicative blending.
150     pub const MULTIPLY: Self = BlendState {
151         color: BlendOp::Add {
152             src: Factor::Zero,
153             dst: Factor::SrcColor,
154         },
155         alpha: BlendOp::Add {
156             src: Factor::Zero,
157             dst: Factor::SrcAlpha,
158         },
159     };
160     /// Alpha blending.
161     pub const ALPHA: Self = BlendState {
162         color: BlendOp::ALPHA,
163         alpha: BlendOp::PREMULTIPLIED_ALPHA,
164     };
165     /// Pre-multiplied alpha blending.
166     pub const PREMULTIPLIED_ALPHA: Self = BlendState {
167         color: BlendOp::PREMULTIPLIED_ALPHA,
168         alpha: BlendOp::PREMULTIPLIED_ALPHA,
169     };
170 }
171 
172 /// PSO color target descriptor.
173 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
174 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
175 pub struct ColorBlendDesc {
176     /// Color write mask.
177     pub mask: ColorMask,
178     /// Blend state, if enabled.
179     pub blend: Option<BlendState>,
180 }
181 
182 impl ColorBlendDesc {
183     /// Empty blend descriptor just writes out the color without blending.
184     // this can be used because `Default::default()` isn't a const function...
185     pub const EMPTY: Self = ColorBlendDesc {
186         mask: ColorMask::ALL,
187         blend: None,
188     };
189 }
190 
191 /// Depth test state.
192 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
193 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
194 pub struct DepthTest {
195     /// Comparison function to use.
196     pub fun: Comparison,
197     /// Specify whether to write to the depth buffer or not.
198     pub write: bool,
199 }
200 
201 impl DepthTest {
202     /// A depth test that always fails.
203     pub const FAIL: Self = DepthTest {
204         fun: Comparison::Never,
205         write: false,
206     };
207     /// A depth test that always succeeds but doesn't
208     /// write to the depth buffer
209     // DOC TODO: Not a terribly helpful description there...
210     pub const PASS_TEST: Self = DepthTest {
211         fun: Comparison::Always,
212         write: false,
213     };
214     /// A depth test that always succeeds and writes its result
215     /// to the depth buffer.
216     pub const PASS_WRITE: Self = DepthTest {
217         fun: Comparison::Always,
218         write: true,
219     };
220 }
221 
222 /// The operation to use for stencil masking.
223 #[repr(u8)]
224 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
225 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
226 pub enum StencilOp {
227     /// Keep the current value in the stencil buffer (no change).
228     Keep = 0,
229     /// Set the value in the stencil buffer to zero.
230     Zero = 1,
231     /// Set the stencil buffer value to `reference` from `StencilFace`.
232     Replace = 2,
233     /// Increment the stencil buffer value, clamping to its maximum value.
234     IncrementClamp = 3,
235     /// Decrement the stencil buffer value, clamping to its minimum value.
236     DecrementClamp = 4,
237     /// Bitwise invert the current value in the stencil buffer.
238     Invert = 5,
239     /// Increment the stencil buffer value, wrapping around to 0 on overflow.
240     IncrementWrap = 6,
241     /// Decrement the stencil buffer value, wrapping around to the maximum value on overflow.
242     DecrementWrap = 7,
243 }
244 
245 /// Complete stencil state for a given side of a face.
246 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
247 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
248 pub struct StencilFace {
249     /// Comparison function to use to determine if the stencil test passes.
250     pub fun: Comparison,
251     /// What operation to do if the stencil test fails.
252     pub op_fail: StencilOp,
253     /// What operation to do if the stencil test passes but the depth test fails.
254     pub op_depth_fail: StencilOp,
255     /// What operation to do if both the depth and stencil test pass.
256     pub op_pass: StencilOp,
257 }
258 
259 impl Default for StencilFace {
default() -> StencilFace260     fn default() -> StencilFace {
261         StencilFace {
262             fun: Comparison::Never,
263             op_fail: StencilOp::Keep,
264             op_depth_fail: StencilOp::Keep,
265             op_pass: StencilOp::Keep,
266         }
267     }
268 }
269 
270 /// A generic struct holding the properties of two sides of a polygon.
271 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
272 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
273 pub struct Sided<T> {
274     /// Information about the front face.
275     pub front: T,
276     /// Information about the back face.
277     pub back: T,
278 }
279 
280 impl<T: Copy> Sided<T> {
281     /// Create a new `Sided` structure with both `front` and `back` holding
282     /// the same value.
new(value: T) -> Self283     pub fn new(value: T) -> Self {
284         Sided {
285             front: value,
286             back: value,
287         }
288     }
289 }
290 
291 /// Pair of stencil values that could be either baked into a graphics pipeline
292 /// or provided dynamically.
293 pub type StencilValues = State<Sided<StencilValue>>;
294 
295 /// Defines a stencil test. Stencil testing is an operation
296 /// performed to cull fragments;
297 /// the new fragment is tested against the value held in the
298 /// stencil buffer, and if the test fails the fragment is
299 /// discarded.
300 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
301 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
302 pub struct StencilTest {
303     /// Operations for stencil faces.
304     pub faces: Sided<StencilFace>,
305     /// Masks that are ANDd with both the stencil buffer value and the reference value when they
306     /// are read before doing the stencil test.
307     pub read_masks: StencilValues,
308     /// Mask that are ANDd with the stencil value before writing to the stencil buffer.
309     pub write_masks: StencilValues,
310     /// The reference values used for stencil tests.
311     pub reference_values: StencilValues,
312 }
313 
314 impl Default for StencilTest {
default() -> Self315     fn default() -> Self {
316         StencilTest {
317             faces: Sided::default(),
318             read_masks: State::Static(Sided::new(!0)),
319             write_masks: State::Static(Sided::new(!0)),
320             reference_values: State::Static(Sided::new(0)),
321         }
322     }
323 }
324 
325 /// PSO depth-stencil target descriptor.
326 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
327 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
328 pub struct DepthStencilDesc {
329     /// Optional depth testing/writing.
330     pub depth: Option<DepthTest>,
331     /// Enable depth bounds testing.
332     pub depth_bounds: bool,
333     /// Stencil test/write.
334     pub stencil: Option<StencilTest>,
335 }
336 
337 impl DepthStencilDesc {
338     /// Returns true if the descriptor assumes the depth attachment.
uses_depth(&self) -> bool339     pub fn uses_depth(&self) -> bool {
340         self.depth.is_some() || self.depth_bounds
341     }
342     /// Returns true if the descriptor assumes the stencil attachment.
uses_stencil(&self) -> bool343     pub fn uses_stencil(&self) -> bool {
344         self.stencil.is_some()
345     }
346 }
347 
348 bitflags!(
349     /// Face.
350     #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
351     pub struct Face: u32 {
352         /// Empty face. TODO: remove when constexpr are stabilized to use empty()
353         const NONE = 0x0;
354         /// Front face.
355         const FRONT = 0x1;
356         /// Back face.
357         const BACK = 0x2;
358     }
359 );
360