1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use super::*;

mod fbo;
mod read;

pub(crate) use fbo::*;
pub use read::*;

pub enum ColorAttachmentRead<'a> {
    None,
    Texture(&'a Texture),
}

pub enum DepthAttachmentRead<'a> {
    None,
    Renderbuffer(&'a Renderbuffer<DepthComponent>),
}

pub struct FramebufferRead<'a> {
    pub(crate) fbo: FBO,
    color: ColorAttachmentRead<'a>,
    depth: DepthAttachmentRead<'a>,
    size: Vec2<usize>,
}

impl<'a> FramebufferRead<'a> {
    pub fn new(
        ugli: &Rc<Ugli>,
        color: ColorAttachmentRead<'a>,
        depth: DepthAttachmentRead<'a>,
    ) -> Self {
        let gl = &ugli.inner;
        let fbo = FBO::new(ugli);
        fbo.bind();
        let mut size = None;
        match color {
            ColorAttachmentRead::None => {}
            ColorAttachmentRead::Texture(ref texture) => {
                gl.framebuffer_texture_2d(
                    raw::FRAMEBUFFER,
                    raw::COLOR_ATTACHMENT0,
                    raw::TEXTURE_2D,
                    Some(&texture.handle),
                    0,
                );
                size = Some(texture.size());
            }
        }
        match depth {
            DepthAttachmentRead::None => {}
            DepthAttachmentRead::Renderbuffer(ref renderbuffer) => {
                gl.framebuffer_renderbuffer(
                    raw::FRAMEBUFFER,
                    raw::DEPTH_ATTACHMENT,
                    raw::RENDERBUFFER,
                    Some(&renderbuffer.handle),
                );
                // TODO: update/check size
            }
        }
        fbo.check();
        ugli.debug_check();
        Self {
            fbo,
            color,
            depth,
            size: size.unwrap(),
        }
    }
    pub fn new_color(ugli: &Rc<Ugli>, color: ColorAttachmentRead<'a>) -> Self {
        Self::new(ugli, color, DepthAttachmentRead::None)
    }
    pub fn size(&self) -> Vec2<usize> {
        self.size
    }

    pub fn color_attachment(&self) -> &ColorAttachmentRead {
        &self.color
    }
    pub fn depth_attachment(&self) -> &DepthAttachmentRead {
        &self.depth
    }
    pub fn destruct(self) -> (ColorAttachmentRead<'a>, DepthAttachmentRead<'a>) {
        (self.color, self.depth)
    }
}

pub enum ColorAttachment<'a> {
    None,
    Texture(&'a mut Texture),
}

pub enum DepthAttachment<'a> {
    None,
    Renderbuffer(&'a mut Renderbuffer<DepthComponent>),
}

pub struct Framebuffer<'a> {
    read: FramebufferRead<'a>,
}

impl<'a> Framebuffer<'a> {
    pub fn new(ugli: &Rc<Ugli>, color: ColorAttachment<'a>, depth: DepthAttachment<'a>) -> Self {
        Self {
            read: FramebufferRead::new(
                ugli,
                match color {
                    ColorAttachment::None => ColorAttachmentRead::None,
                    ColorAttachment::Texture(texture) => ColorAttachmentRead::Texture(texture),
                },
                match depth {
                    DepthAttachment::None => DepthAttachmentRead::None,
                    DepthAttachment::Renderbuffer(renderbuffer) => {
                        DepthAttachmentRead::Renderbuffer(renderbuffer)
                    }
                },
            ),
        }
    }
    pub fn new_color(ugli: &Rc<Ugli>, color: ColorAttachment<'a>) -> Self {
        Self::new(ugli, color, DepthAttachment::None)
    }
    pub fn destruct(self) -> (ColorAttachmentRead<'a>, DepthAttachmentRead<'a>) {
        self.read.destruct()
    }
}

impl<'a> Deref for Framebuffer<'a> {
    type Target = FramebufferRead<'a>;
    fn deref(&self) -> &Self::Target {
        &self.read
    }
}

impl<'a> Framebuffer<'a> {
    pub fn default(ugli: &Rc<Ugli>) -> Self {
        Self {
            read: FramebufferRead {
                fbo: FBO::default(ugli),
                color: ColorAttachmentRead::None,
                depth: DepthAttachmentRead::None,
                size: ugli.size(),
            },
        }
    }
}