1 // Copyright 2017 The Gfx-rs Developers.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Fixed-function hardware state.
16 //!
17 //! Configures the primitive assembly (PA), rasterizer, and output merger (OM) blocks.
18 
19 use std::default::Default;
20 use std::fmt;
21 
22 use target;
23 
24 /// The front face winding order of a set of vertices.
25 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
26 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
27 pub enum FrontFace {
28     /// Clockwise winding order.
29     Clockwise,
30     /// Counter-clockwise winding order.
31     CounterClockwise,
32 }
33 
34 /// Width of a line.
35 /// Could be f32 if not for Hash deriving issues.
36 pub type LineWidth = i32;
37 /// Slope depth offset factor
38 /// Could be f32 if not for Hash deriving issues.
39 pub type OffsetSlope = i32;
40 /// Number of units to offset, where
41 /// the unit is the minimal difference in the depth value
42 /// dictated by the precision of the depth buffer.
43 pub type OffsetUnits = i32;
44 
45 /// How to offset vertices in screen space, if at all.
46 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
47 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
48 pub struct Offset(pub OffsetSlope, pub OffsetUnits);
49 
50 /// Which face, if any, to cull.
51 #[allow(missing_docs)]
52 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
53 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
54 pub enum CullFace {
55     Nothing,
56     Front,
57     Back,
58 }
59 
60 /// How to rasterize a primitive.
61 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
62 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
63 pub enum RasterMethod {
64     /// Rasterize as a point.
65     Point,
66     /// Rasterize as a line with the given width.
67     Line(LineWidth),
68     /// Rasterize as a face.
69     Fill
70 }
71 
72 /// Multi-sampling rasterization mode
73 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
74 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
75 pub struct MultiSample;
76     //sample_mask: u16,
77     //alpha_to_coverage: bool,
78 
79 /// Primitive rasterization state. Note that GL allows different raster
80 /// method to be used for front and back, while this abstraction does not.
81 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
82 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
83 pub struct Rasterizer {
84     /// Which vertex winding is considered to be the front face for culling.
85     pub front_face: FrontFace,
86     /// Which face should be culled.
87     pub cull_face: CullFace,
88     /// How to rasterize this primitive.
89     pub method: RasterMethod,
90     /// Any polygon offset to apply.
91     pub offset: Option<Offset>,
92     /// Multi-sampling mode.
93     pub samples: Option<MultiSample>,
94 }
95 
96 impl Rasterizer {
97     /// Create a new filling rasterizer.
new_fill() -> Self98     pub fn new_fill() -> Self {
99         Rasterizer {
100             front_face: FrontFace::CounterClockwise,
101             cull_face: CullFace::Nothing,
102             method: RasterMethod::Fill,
103             offset: None,
104             samples: None,
105         }
106     }
107 
108     /// Add back face culling.
with_cull_back(self) -> Self109     pub fn with_cull_back(self) -> Self {
110         Rasterizer {
111             cull_face: CullFace::Back,
112             ..self
113         }
114     }
115 
116     /// Add polygon offset.
with_offset(self, slope: f32, units: OffsetUnits) -> Self117     pub fn with_offset(self, slope: f32, units: OffsetUnits) -> Self {
118         Rasterizer {
119             offset: Some(Offset(slope as OffsetSlope, units)),
120             ..self
121         }
122     }
123 }
124 
125 /// A pixel-wise comparison function.
126 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
127 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
128 pub enum Comparison {
129     /// `false`
130     Never,
131     /// `x < y`
132     Less,
133     /// `x <= y`
134     LessEqual,
135     /// `x == y`
136     Equal,
137     /// `x >= y`
138     GreaterEqual,
139     /// `x > y`
140     Greater,
141     /// `x != y`
142     NotEqual,
143     /// `true`
144     Always,
145 }
146 
147 /// Stencil mask operation.
148 #[allow(missing_docs)]
149 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
150 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
151 pub enum StencilOp {
152     /// Keep the current value in the stencil buffer (no change).
153     Keep,
154     /// Set the value in the stencil buffer to zero.
155     Zero,
156     /// Set the stencil buffer value to `value` from `StencilSide`
157     Replace,
158     /// Increment the stencil buffer value, clamping to its maximum value.
159     IncrementClamp,
160     /// Increment the stencil buffer value, wrapping around to 0 on overflow.
161     IncrementWrap,
162     /// Decrement the stencil buffer value, clamping to its minimum value.
163     DecrementClamp,
164     /// Decrement the stencil buffer value, wrapping around to the maximum value on overflow.
165     DecrementWrap,
166     /// Bitwise invert the current value in the stencil buffer.
167     Invert,
168 }
169 
170 /// Complete stencil state for a given side of a face.
171 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
172 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
173 pub struct StencilSide {
174     /// Comparison function to use to determine if the stencil test passes.
175     pub fun: Comparison,
176     /// A mask that is ANDd with both the stencil buffer value and the reference value when they
177     /// are read before doing the stencil test.
178     pub mask_read: target::Stencil,
179     /// A mask that is ANDd with the stencil value before writing to the stencil buffer.
180     pub mask_write: target::Stencil,
181     /// What operation to do if the stencil test fails.
182     pub op_fail: StencilOp,
183     /// What operation to do if the stenil test passes but the depth test fails.
184     pub op_depth_fail: StencilOp,
185     /// What operation to do if both the depth and stencil test pass.
186     pub op_pass: StencilOp,
187 }
188 
189 impl Default for StencilSide {
default() -> Self190     fn default() -> Self {
191         StencilSide {
192             fun: Comparison::Always,
193             mask_read: target::Stencil::max_value(),
194             mask_write: target::Stencil::max_value(),
195             op_fail: StencilOp::Keep,
196             op_depth_fail: StencilOp::Keep,
197             op_pass: StencilOp::Keep,
198         }
199     }
200 }
201 
202 /// Complete stencil state, specifying how to handle the front and back side of a face.
203 #[allow(missing_docs)]
204 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
205 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
206 pub struct Stencil {
207     pub front: StencilSide,
208     pub back: StencilSide,
209 }
210 
211 impl Stencil {
212     /// Create a new stencil state with a given function.
new(fun: Comparison, mask: target::Stencil, ops: (StencilOp, StencilOp, StencilOp)) -> Self213     pub fn new(fun: Comparison, mask: target::Stencil,
214                ops: (StencilOp, StencilOp, StencilOp))
215                -> Self {
216         let side = StencilSide {
217             fun: fun,
218             mask_read: mask,
219             mask_write: mask,
220             op_fail: ops.0,
221             op_depth_fail: ops.1,
222             op_pass: ops.2,
223         };
224         Stencil {
225             front: side,
226             back: side,
227         }
228     }
229 }
230 
231 /// Depth test state.
232 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
233 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
234 pub struct Depth {
235     /// Comparison function to use.
236     pub fun: Comparison,
237     /// Specify whether to write to the depth buffer or not.
238     pub write: bool,
239 }
240 
241 impl Default for Depth {
default() -> Self242     fn default() -> Self {
243         Depth {
244             fun: Comparison::Always,
245             write: false,
246         }
247     }
248 }
249 
250 #[allow(missing_docs)]
251 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
252 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
253 pub enum Equation {
254     /// Adds source and destination.
255     /// Source and destination are multiplied by blending parameters before addition.
256     Add,
257     /// Subtracts destination from source.
258     /// Source and destination are multiplied by blending parameters before subtraction.
259     Sub,
260     /// Subtracts source from destination.
261     /// Source and destination are multiplied by blending parameters before subtraction.
262     RevSub,
263     /// Component-wise minimum value of source and destination.
264     /// Blending parameters are ignored.
265     Min,
266     /// Component-wise maximum value of source and destination.
267     /// Blending parameters are ignored.
268     Max,
269 }
270 
271 #[allow(missing_docs)]
272 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
273 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
274 pub enum BlendValue {
275     SourceColor,
276     SourceAlpha,
277     DestColor,
278     DestAlpha,
279     ConstColor,
280     ConstAlpha,
281 }
282 
283 #[allow(missing_docs)]
284 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
285 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
286 pub enum Factor {
287     Zero,
288     One,
289     SourceAlphaSaturated,
290     ZeroPlus(BlendValue),
291     OneMinus(BlendValue),
292 }
293 
294 #[allow(missing_docs)]
295 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
296 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
297 pub struct BlendChannel {
298     pub equation: Equation,
299     pub source: Factor,
300     pub destination: Factor,
301 }
302 
303 impl Default for BlendChannel {
default() -> Self304     fn default() -> Self {
305         BlendChannel {
306             equation: Equation::Add,
307             source: Factor::One,
308             destination: Factor::Zero,
309         }
310     }
311 }
312 
313 #[allow(missing_docs)]
314 #[derive(Clone, Copy, Default, Eq, Hash, PartialEq, PartialOrd)]
315 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
316 pub struct Blend {
317     pub color: BlendChannel,
318     pub alpha: BlendChannel,
319 }
320 
321 impl Blend {
322     /// Create a new blend state with a given equation.
new(eq: Equation, src: Factor, dst: Factor) -> Self323     pub fn new(eq: Equation, src: Factor, dst: Factor) -> Self {
324         let chan = BlendChannel {
325             equation: eq,
326             source: src,
327             destination: dst,
328         };
329         Blend {
330             color: chan,
331             alpha: chan,
332         }
333     }
334 }
335 
336 impl fmt::Debug for Blend {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result337     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338         write!(f, "Blend {{ color: {:?}, alpha: {:?}}}",
339                self.color, self.alpha)
340     }
341 }
342 
343 bitflags!(
344     #[allow(missing_docs)]
345     #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
346     pub struct ColorMask: u8 {
347         #[allow(missing_docs)]
348         const RED     = 0x1;
349         #[allow(missing_docs)]
350         const GREEN   = 0x2;
351         #[allow(missing_docs)]
352         const BLUE    = 0x4;
353         #[allow(missing_docs)]
354         const ALPHA   = 0x8;
355     }
356 );
357 
358 /// The state of an active color render target
359 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
360 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
361 pub struct Color {
362     /// Color mask to use.
363     pub mask: ColorMask,
364     /// Optional blending.
365     pub blend: Option<Blend>,
366 }
367 
368 impl Default for Color {
default() -> Self369     fn default() -> Self {
370         Color {
371             mask: ColorMask::all(),
372             blend: None,
373         }
374     }
375 }
376 
377 /// The complete set of the rasterizer reference values.
378 /// Switching these doesn't roll the hardware context.
379 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
380 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
381 pub struct RefValues {
382     /// Stencil front and back values.
383     pub stencil: (target::Stencil, target::Stencil),
384     /// Constant blend color.
385     pub blend: target::ColorValue,
386 }
387 
388 impl Default for RefValues {
default() -> Self389     fn default() -> Self {
390         RefValues {
391             stencil: (0, 0),
392             blend: [0f32; 4],
393         }
394     }
395 }
396