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