use super::*;
use super::errors::*;
pub trait Framebuffer {
fn get_id(&self) -> FramebufferId;
fn state(&self) -> &FramebufferState;
fn mut_state(&mut self) -> &mut FramebufferState;
fn get_state(&self) -> FramebufferState;
fn set_state(&mut self, FramebufferState);
fn bind(&self) -> ();
fn set_viewport<'a>(&'a mut self, viewport: Viewport) {
self.mut_state().viewport = viewport;
}
fn set_enable<'a>(&'a mut self, option: EnableOption) {
self.mut_state().options[usize::from(option)] = true;
}
fn set_disable<'a>(&'a mut self, option: EnableOption) {
self.mut_state().options[usize::from(option)] = false;
}
fn set_stencil_test<'a>(&'a mut self, face: Face, stencil_test: StencilTest) {
match face {
Face::Front => self.mut_state().stencil_test[0] = stencil_test,
Face::Back => self.mut_state().stencil_test[1] = stencil_test,
Face::FrontBack => {
self.mut_state().stencil_test[0] = stencil_test;
self.mut_state().stencil_test[1] = stencil_test;
}
}
}
fn set_depth_test<'a>(&'a mut self, depth_test: DepthTest) {
self.mut_state().depth_test = depth_test;
}
fn set_depth_mask<'a>(&'a mut self, depth_mask: DepthMask) {
self.mut_state().depth_mask = depth_mask;
}
fn set_depth_range<'a>(&'a mut self, depth_range: DepthRange) {
self.mut_state().depth_range = depth_range;
}
fn set_logic_operation<'a>(&'a mut self, logic_operation: LogicOperation) {
self.mut_state().logic_operation = logic_operation;
}
fn set_blending_equation<'a>(
&'a mut self,
blending_equation_rgb: BlendingEquation,
blending_equation_alpha: BlendingEquation,
) {
self.mut_state().blending_equation_rgb = blending_equation_rgb;
self.mut_state().blending_equation_alpha = blending_equation_alpha;
}
fn set_linear_blending_factors<'a>(
&'a mut self,
source_rgb: LinearBlendingFactor,
destination_rgb: LinearBlendingFactor,
source_alpha: LinearBlendingFactor,
destination_alpha: LinearBlendingFactor,
) {
self.mut_state().linear_blending_factors = Some([source_rgb, destination_rgb, source_alpha, destination_alpha]);
}
fn set_face_orientation<'a>(&'a mut self, face_orientation: FaceOrientation) {
self.mut_state().face_orientation = face_orientation;
}
fn set_cull_face<'a>(&'a mut self, cull_face: Face) {
self.mut_state().cull_face = cull_face;
}
fn set_clear_color<'a>(&'a mut self, clear_color: ClearColor) {
self.mut_state().clear_color = clear_color;
}
fn set_clear_depth<'a>(&'a mut self, clear_depth: f64) {
self.mut_state().clear_depth = clear_depth;
}
fn set_color_mask<'a>(&'a mut self, color_mask: [bool; 4]) {
self.mut_state().color_mask = color_mask;
}
fn set_clip_control_origin<'a>(&'a mut self, clip_control_origin: ClipControlOrigin) {
self.mut_state().clip_control_origin = clip_control_origin;
}
fn set_clip_control_depth<'a>(&'a mut self, clip_control_depth: ClipControlDepth) {
self.mut_state().clip_control_depth = clip_control_depth;
}
}
#[derive(Debug)]
pub struct DefaultFramebuffer {
state: FramebufferState,
}
impl DefaultFramebuffer {
pub fn new() -> DefaultFramebuffer {
let mut default_framebuffer = DefaultFramebuffer {
state: FramebufferState::default(),
};
default_framebuffer.set_depth_test(DepthTest::Greater);
default_framebuffer.set_clear_depth(0.0f64);
default_framebuffer.set_clip_control_origin(ClipControlOrigin::LowerLeft);
default_framebuffer.set_clip_control_depth(ClipControlDepth::ZeroToOne);
default_framebuffer
}
}
impl Framebuffer for DefaultFramebuffer {
fn get_id(&self) -> FramebufferId {
DEFAULT_FRAMEBUFFER_ID
}
fn state(&self) -> &FramebufferState {
&self.state
}
fn mut_state(&mut self) -> &mut FramebufferState {
&mut self.state
}
fn get_state(&self) -> FramebufferState {
self.state
}
fn set_state(&mut self, state: FramebufferState) {
self.state = state;
}
#[allow(unused_must_use)]
fn bind(&self) {
unsafe {
bind_framebuffer(FramebufferTarget::Framebuffer, self.get_id());
}
}
}
#[derive(Debug)]
pub struct GeneralFramebuffer {
id: FramebufferId,
state: FramebufferState,
}
impl Framebuffer for GeneralFramebuffer {
fn get_id(&self) -> FramebufferId {
self.id
}
fn state(&self) -> &FramebufferState {
&self.state
}
fn mut_state(&mut self) -> &mut FramebufferState {
&mut self.state
}
fn get_state(&self) -> FramebufferState {
self.state
}
fn set_state(&mut self, state: FramebufferState) {
self.state = state;
}
#[allow(unused_must_use)]
fn bind(&self) {
unsafe {
bind_framebuffer(FramebufferTarget::Framebuffer, self.id);
}
}
}
impl GeneralFramebuffer {
pub fn new() -> GeneralFramebuffer {
let id;
unsafe {
id = create_framebuffer();
};
let mut general_framebuffer = GeneralFramebuffer {
id: id,
state: FramebufferState::default(),
};
general_framebuffer.set_depth_test(DepthTest::Greater);
general_framebuffer.set_clear_depth(0.0f64);
general_framebuffer.set_clip_control_origin(ClipControlOrigin::LowerLeft);
general_framebuffer.set_clip_control_depth(ClipControlDepth::ZeroToOne);
general_framebuffer
}
pub fn attach_texture(
&self,
attachment: FramebufferAttachment,
texture_option: &DrawTextureAttachOption,
) -> Result<()> {
unsafe {
match *texture_option {
DrawTextureAttachOption::AttachTexture(ref texture) => {
named_framebuffer_texture(self.id, attachment, texture.get_id(), 0)
.chain_err(|| "Could not attach texture to framebuffer")?;
}
DrawTextureAttachOption::AttachTextureLayer {
ref texture,
level,
layer,
} => {
named_framebuffer_texture_layer(self.id, attachment, texture.get_id(), level, layer)
.chain_err(|| format!("Could not attach texture layer to framebuffer"))?;
}
DrawTextureAttachOption::None => {
named_framebuffer_texture(self.id, attachment, TextureId::empty(), 0)
.chain_err(|| "Could not detach texture from framebuffer")?;
}
DrawTextureAttachOption::Keep => {}
}
}
Ok(())
}
pub fn attach_textures(&self, textures: &DrawTextureTarget) -> Result<()> {
let color_attachments = [
&textures.color0,
&textures.color1,
&textures.color2,
&textures.color3,
&textures.color4,
&textures.color5,
&textures.color6,
&textures.color7,
];
let mut draw_buffers = [
FramebufferDrawBuffer::ColorAttachment0,
FramebufferDrawBuffer::ColorAttachment1,
FramebufferDrawBuffer::ColorAttachment2,
FramebufferDrawBuffer::ColorAttachment3,
FramebufferDrawBuffer::ColorAttachment4,
FramebufferDrawBuffer::ColorAttachment5,
FramebufferDrawBuffer::ColorAttachment6,
FramebufferDrawBuffer::ColorAttachment7,
];
for (i, color_attachment_option) in color_attachments.iter().enumerate() {
match **color_attachment_option {
DrawTextureAttachOption::None => draw_buffers[i] = FramebufferDrawBuffer::None,
_ => {}
}
}
unsafe {
named_framebuffer_draw_buffers(self.id, &draw_buffers).chain_err(|| "Could not attach draw buffers")?;
}
match textures.depth_stencil {
DepthStencilOption::Separate {
ref depth,
ref stencil,
} => {
self.attach_texture(FramebufferAttachment::DepthAttachment, &depth)
.chain_err(|| "Could not attach depth texture")?;
self.attach_texture(FramebufferAttachment::StencilAttachment, &stencil)
.chain_err(|| "Could not attach stencil texture")?;;
}
DepthStencilOption::Together(ref depth_stencil) => {
self.attach_texture(
FramebufferAttachment::DepthStencilAttachment,
&depth_stencil,
).chain_err(|| "Could not attach depth stencil texture")?;;
}
}
let color_attachments_enums = [
FramebufferAttachment::ColorAttachment0,
FramebufferAttachment::ColorAttachment1,
FramebufferAttachment::ColorAttachment2,
FramebufferAttachment::ColorAttachment3,
FramebufferAttachment::ColorAttachment4,
FramebufferAttachment::ColorAttachment5,
FramebufferAttachment::ColorAttachment6,
FramebufferAttachment::ColorAttachment7,
];
for (i, color_attachment_option) in color_attachments.iter().enumerate() {
self.attach_texture(color_attachments_enums[i], color_attachment_option)
.chain_err(|| format!("Could not attach color{} texture", i))?;
}
unsafe {
check_named_framebuffer_status(self.get_id(), FramebufferTarget::Framebuffer)
.chain_err(|| "Framebuffer is not complete")?;
}
Ok(())
}
pub fn set_parameter(&mut self, parameter: FramebufferParameter, value: u32) {
unsafe {
framebuffer_parameter(self.id, parameter, value).unwrap();
}
}
}
impl Drop for GeneralFramebuffer {
fn drop(&mut self) {
unsafe {
delete_framebuffer(self.id.into());
}
}
}