use crate::texture::Texture; use crate::MaybeCurrentContextWithFns; #[derive(Debug, Clone)] pub struct Framebuffer { inner: crate::sys::types::GLuint, } impl Framebuffer { #[must_use] pub fn new(current_context: &MaybeCurrentContextWithFns) -> Self { let mut inner = 0; unsafe { current_context.fns().GenFramebuffers(1, &raw mut inner); } Self { inner } } /// Attaches a texture object as a logical buffer of this framebuffer object. pub fn attach_texture( &self, current_context: &MaybeCurrentContextWithFns, attachment: Attachment, texture: Texture, texture_mipmap_level: u16, ) { unsafe { current_context.fns().NamedFramebufferTexture( self.inner, attachment.into_gl(), texture.into_raw(), texture_mipmap_level.into(), ); } } /// Detaches the texture object at the specified attachment point. pub fn detach_texture( &self, current_context: &MaybeCurrentContextWithFns, attachment: Attachment, ) { unsafe { current_context.fns().NamedFramebufferTexture( self.inner, attachment.into_gl(), 0, 0, ); } } /// Specifies which color buffer is to be drawn into when colors are written to this /// framebuffer object. /// /// If `buffer` is `None`, no color buffer will be written into. pub fn set_draw_buffer( &self, current_context: &MaybeCurrentContextWithFns, buffer: Option, ) { unsafe { current_context.fns().NamedFramebufferDrawBuffer( self.inner, buffer .map(ColorAttachment::into_gl) .unwrap_or(crate::sys::NONE), ); } } pub fn delete(self, current_context: &MaybeCurrentContextWithFns) { unsafe { current_context .fns() .DeleteFramebuffers(1, &raw const self.inner); } } pub fn from_raw(raw: u32) -> Self { Self { inner: raw } } pub fn into_raw(self) -> u32 { self.inner } } /// Binds a framebuffer to a framebuffer target. /// /// If `framebuffer` is `None`, breaks the existing binding of a framebuffer object to /// the framebuffer target `target`. pub fn bind( current_context: &MaybeCurrentContextWithFns, target: Target, framebuffer: Option<&Framebuffer>, ) { unsafe { current_context.fns().BindFramebuffer( target.into_gl(), framebuffer .map(|framebuffer| framebuffer.inner) .unwrap_or(0), ); } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Target { Draw, Read, DrawAndRead, } impl Target { fn into_gl(self) -> crate::sys::types::GLenum { match self { Self::Draw => crate::sys::DRAW_FRAMEBUFFER, Self::Read => crate::sys::READ_FRAMEBUFFER, Self::DrawAndRead => crate::sys::FRAMEBUFFER, } } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[non_exhaustive] pub enum Attachment { Color(ColorAttachment), Depth, Stencil, DepthStencil, } impl Attachment { fn into_gl(self) -> crate::sys::types::GLenum { match self { Self::Color(color_attachment) => color_attachment.into_gl(), Self::Depth => crate::sys::DEPTH_ATTACHMENT, Self::Stencil => crate::sys::STENCIL_ATTACHMENT, Self::DepthStencil => crate::sys::DEPTH_STENCIL_ATTACHMENT, } } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ColorAttachment(pub u8); impl ColorAttachment { fn into_gl(self) -> crate::sys::types::GLenum { match self.0 { 0 => crate::sys::COLOR_ATTACHMENT0, 1 => crate::sys::COLOR_ATTACHMENT1, 10 => crate::sys::COLOR_ATTACHMENT10, 11 => crate::sys::COLOR_ATTACHMENT11, 12 => crate::sys::COLOR_ATTACHMENT12, 13 => crate::sys::COLOR_ATTACHMENT13, 14 => crate::sys::COLOR_ATTACHMENT14, 15 => crate::sys::COLOR_ATTACHMENT15, 16 => crate::sys::COLOR_ATTACHMENT16, 17 => crate::sys::COLOR_ATTACHMENT17, 18 => crate::sys::COLOR_ATTACHMENT18, 19 => crate::sys::COLOR_ATTACHMENT19, 2 => crate::sys::COLOR_ATTACHMENT2, 20 => crate::sys::COLOR_ATTACHMENT20, 21 => crate::sys::COLOR_ATTACHMENT21, 22 => crate::sys::COLOR_ATTACHMENT22, 23 => crate::sys::COLOR_ATTACHMENT23, 24 => crate::sys::COLOR_ATTACHMENT24, 25 => crate::sys::COLOR_ATTACHMENT25, 26 => crate::sys::COLOR_ATTACHMENT26, 27 => crate::sys::COLOR_ATTACHMENT27, 28 => crate::sys::COLOR_ATTACHMENT28, 29 => crate::sys::COLOR_ATTACHMENT29, 3 => crate::sys::COLOR_ATTACHMENT3, 30 => crate::sys::COLOR_ATTACHMENT30, 31 => crate::sys::COLOR_ATTACHMENT31, 4 => crate::sys::COLOR_ATTACHMENT4, 5 => crate::sys::COLOR_ATTACHMENT5, 6 => crate::sys::COLOR_ATTACHMENT6, 7 => crate::sys::COLOR_ATTACHMENT7, 8 => crate::sys::COLOR_ATTACHMENT8, 9 => crate::sys::COLOR_ATTACHMENT9, _ => panic!("Invalid color attachment index. Must be < 32"), } } }