use raw::*;
const ENABLE_OPTIONS_INDICES: [EnableOption; 15] = [
EnableOption::Blend,
EnableOption::ColorLogicOperation,
EnableOption::CullFace,
EnableOption::DepthClamp,
EnableOption::DepthTest,
EnableOption::Dither,
EnableOption::FramebufferSRGB,
EnableOption::LineSmooth,
EnableOption::Multisample,
EnableOption::SampleShading,
EnableOption::SampleMask,
EnableOption::ScissorTest,
EnableOption::StencilTest,
EnableOption::TextureCubeMapSeamless,
EnableOption::ProgramPointSize,
];
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct FramebufferState {
pub viewport: Viewport,
pub options: [bool; 15],
pub stencil_test: [StencilTest; 2],
pub depth_test: DepthTest,
pub depth_mask: DepthMask,
pub depth_range: DepthRange,
pub logic_operation: LogicOperation,
pub blending_equation_rgb: BlendingEquation,
pub blending_equation_alpha: BlendingEquation,
pub linear_blending_factors: Option<[LinearBlendingFactor; 4]>,
pub face_orientation: FaceOrientation,
pub cull_face: Face,
pub clear_color: ClearColor,
pub clear_depth: f64,
pub color_mask: [bool; 4],
pub clip_control_origin: ClipControlOrigin,
pub clip_control_depth: ClipControlDepth,
}
impl FramebufferState {
pub fn sync(&mut self, other: &FramebufferState) {
if self == other {
return;
}
if self.viewport != other.viewport {
viewport(other.viewport);
}
for i in 0..15 {
if self.options[i] != other.options[i] {
match other.options[i] {
true => enable(ENABLE_OPTIONS_INDICES[i]),
false => disable(ENABLE_OPTIONS_INDICES[i]),
}
}
}
if self.stencil_test[0] != other.stencil_test[0] {
stencil_func_separate(Face::Front, other.stencil_test[0]);
}
if self.stencil_test[1] != other.stencil_test[1] {
stencil_func_separate(Face::Front, other.stencil_test[1]);
}
if self.depth_test != other.depth_test {
depth_function(other.depth_test);
}
if self.depth_mask != other.depth_mask {
depth_mask(other.depth_mask);
}
if self.depth_range != other.depth_range {
depth_range(other.depth_range);
}
if self.logic_operation != other.logic_operation {
logic_op(other.logic_operation);
}
if self.blending_equation_rgb != other.blending_equation_rgb
|| self.blending_equation_alpha != other.blending_equation_alpha
{
blend_equation_separate(other.blending_equation_rgb, other.blending_equation_alpha);
}
if self.linear_blending_factors != other.linear_blending_factors {
if let Some(blending_factors) = other.linear_blending_factors {
blend_func_separate(
blending_factors[0],
blending_factors[1],
blending_factors[2],
blending_factors[3],
);
}
}
if self.face_orientation != other.face_orientation {
front_face(other.face_orientation);
}
if self.cull_face != other.cull_face {
cull_face(other.cull_face);
}
if self.clear_color != other.clear_color {
clear_color(other.clear_color);
}
if self.clear_depth != other.clear_depth {
clear_depth(other.clear_depth);
}
if self.color_mask != other.color_mask {
color_mask(
other.color_mask[0],
other.color_mask[1],
other.color_mask[2],
other.color_mask[3],
);
}
if self.clip_control_depth != other.clip_control_depth || self.clip_control_origin != other.clip_control_origin
{
clip_control(other.clip_control_origin, other.clip_control_depth);
}
*self = *other;
}
}
#[derive(Debug, Copy, Clone, PartialEq, Default)]
pub struct FramebufferStateBuilder {
viewport: Viewport,
options: [bool; 15],
stencil_test: [StencilTest; 2],
depth_test: DepthTest,
depth_mask: DepthMask,
depth_range: DepthRange,
logic_operation: LogicOperation,
blending_equation_rgb: BlendingEquation,
blending_equation_alpha: BlendingEquation,
linear_blending_factors: Option<[LinearBlendingFactor; 4]>,
face_orientation: FaceOrientation,
cull_face: Face,
clear_color: ClearColor,
clear_depth: f64,
color_mask: [bool; 4],
clip_control_origin: ClipControlOrigin,
clip_control_depth: ClipControlDepth,
}
impl FramebufferStateBuilder {
pub fn new() -> FramebufferStateBuilder {
FramebufferStateBuilder::default()
}
pub fn viewport<'a>(&'a mut self, viewport: Viewport) -> &'a mut FramebufferStateBuilder {
self.viewport = viewport;
self
}
pub fn enable<'a>(&'a mut self, option: EnableOption) -> &'a mut FramebufferStateBuilder {
self.options[usize::from(option)] = true;
self
}
pub fn disable<'a>(&'a mut self, option: EnableOption) -> &'a mut FramebufferStateBuilder {
self.options[usize::from(option)] = false;
self
}
pub fn stencil_test<'a>(&'a mut self, face: Face, stencil_test: StencilTest) -> &'a mut FramebufferStateBuilder {
match face {
Face::Front => self.stencil_test[0] = stencil_test,
Face::Back => self.stencil_test[1] = stencil_test,
Face::FrontBack => {
self.stencil_test[0] = stencil_test;
self.stencil_test[1] = stencil_test;
}
}
self
}
pub fn depth_test<'a>(&'a mut self, depth_test: DepthTest) -> &'a mut FramebufferStateBuilder {
self.depth_test = depth_test;
self
}
pub fn depth_mask<'a>(&'a mut self, depth_mask: DepthMask) -> &'a mut FramebufferStateBuilder {
self.depth_mask = depth_mask;
self
}
pub fn depth_range<'a>(&'a mut self, depth_range: DepthRange) -> &'a mut FramebufferStateBuilder {
self.depth_range = depth_range;
self
}
pub fn logic_operation<'a>(&'a mut self, logic_operation: LogicOperation) -> &'a mut FramebufferStateBuilder {
self.logic_operation = logic_operation;
self
}
pub fn blending_equation<'a>(
&'a mut self,
blending_equation_rgb: BlendingEquation,
blending_equation_alpha: BlendingEquation,
) -> &'a mut FramebufferStateBuilder {
self.blending_equation_rgb = blending_equation_rgb;
self.blending_equation_alpha = blending_equation_alpha;
self
}
pub fn linear_blending_factors<'a>(
&'a mut self,
source_rgb: LinearBlendingFactor,
destination_rgb: LinearBlendingFactor,
source_alpha: LinearBlendingFactor,
destination_alpha: LinearBlendingFactor,
) -> &'a mut FramebufferStateBuilder {
self.linear_blending_factors = Some([source_rgb, destination_rgb, source_alpha, destination_alpha]);
self
}
pub fn face_orientation<'a>(&'a mut self, face_orientation: FaceOrientation) -> &'a mut FramebufferStateBuilder {
self.face_orientation = face_orientation;
self
}
pub fn cull_face<'a>(&'a mut self, cull_face: Face) -> &'a mut FramebufferStateBuilder {
self.cull_face = cull_face;
self
}
pub fn clear_color<'a>(&'a mut self, clear_color: ClearColor) -> &'a mut FramebufferStateBuilder {
self.clear_color = clear_color;
self
}
pub fn color_mask<'a>(
&'a mut self,
red: bool,
green: bool,
blue: bool,
alpha: bool,
) -> &'a mut FramebufferStateBuilder {
self.color_mask = [red, green, blue, alpha];
self
}
pub fn clip_control_origin<'a>(
&'a mut self,
clip_control_origin: ClipControlOrigin,
) -> &'a mut FramebufferStateBuilder {
self.clip_control_origin = clip_control_origin;
self
}
pub fn clip_control_depth<'a>(
&'a mut self,
clip_control_depth: ClipControlDepth,
) -> &'a mut FramebufferStateBuilder {
self.clip_control_depth = clip_control_depth;
self
}
pub fn build(&mut self) -> FramebufferState {
FramebufferState {
viewport: self.viewport,
options: self.options,
stencil_test: self.stencil_test,
depth_test: self.depth_test,
depth_mask: self.depth_mask,
depth_range: self.depth_range,
logic_operation: self.logic_operation,
blending_equation_rgb: self.blending_equation_rgb,
blending_equation_alpha: self.blending_equation_alpha,
linear_blending_factors: self.linear_blending_factors,
face_orientation: self.face_orientation,
cull_face: self.cull_face,
clear_color: self.clear_color,
clear_depth: self.clear_depth,
color_mask: self.color_mask,
clip_control_origin: self.clip_control_origin,
clip_control_depth: self.clip_control_depth,
}
}
}
impl Default for FramebufferState {
fn default() -> FramebufferState {
let mut options = [false; 15];
options[usize::from(EnableOption::Dither)] = true;
options[usize::from(EnableOption::Multisample)] = true;
FramebufferState {
viewport: Viewport::default(),
options: options,
stencil_test: [StencilTest::default(); 2],
depth_test: DepthTest::default(),
depth_mask: DepthMask::default(),
depth_range: DepthRange::default(),
logic_operation: LogicOperation::default(),
blending_equation_rgb: BlendingEquation::default(),
blending_equation_alpha: BlendingEquation::default(),
linear_blending_factors: None,
face_orientation: FaceOrientation::default(),
cull_face: Face::default(),
clear_color: ClearColor::default(),
clear_depth: 1.0f64,
color_mask: [true, true, true, true],
clip_control_origin: ClipControlOrigin::LowerLeft,
clip_control_depth: ClipControlDepth::NegativeOneToOne,
}
}
}