1use crate::{DepthBuffer, Gl, GlError, Settings, Texture};
2use std::rc::Rc;
3use web_sys::{WebGlFramebuffer, WebGlRenderingContext};
4
5#[derive(Clone, Debug)]
6struct FrameBufferInfo {
7 gl: Gl,
8 handle: WebGlFramebuffer,
9}
10
11impl Drop for FrameBufferInfo {
12 fn drop(&mut self) {
13 self.gl.context().delete_framebuffer(Some(&self.handle));
14 }
15}
16
17#[derive(Clone, Debug)]
18pub struct FrameBuffer {
19 data: Rc<FrameBufferInfo>,
20 color_buffer: Option<Texture>,
21 depth_buffer: Option<DepthBuffer>,
22}
23
24impl PartialEq for FrameBuffer {
25 fn eq(&self, other: &Self) -> bool {
26 self.data.handle == other.data.handle
27 }
28}
29
30impl Eq for FrameBuffer {}
31
32impl FrameBuffer {
33 pub fn new(gl: Gl) -> Result<FrameBuffer, GlError> {
34 Ok(FrameBuffer {
35 data: Rc::new(FrameBufferInfo {
36 handle: gl
37 .context()
38 .create_framebuffer()
39 .ok_or(GlError::FrameBufferError)?,
40 gl,
41 }),
42 color_buffer: None,
43 depth_buffer: None,
44 })
45 }
46 pub fn set_color_buffer(&mut self, texture: Option<Texture>) -> &mut Self {
47 self.color_buffer = texture.clone();
48 self.data
49 .gl
50 .apply(Gl::settings().frame_buffer(self.clone()), || {
51 self.data.gl.context().framebuffer_texture_2d(
52 WebGlRenderingContext::FRAMEBUFFER,
53 WebGlRenderingContext::COLOR_ATTACHMENT0,
54 WebGlRenderingContext::TEXTURE_2D,
55 self.color_buffer.as_ref().map(|buffer| buffer.handle()),
56 0,
57 );
58 });
59 self
60 }
61 pub fn set_depth_buffer(&mut self, buffer: Option<DepthBuffer>) -> &mut Self {
62 self.depth_buffer = buffer;
63 self.data
64 .gl
65 .apply(Gl::settings().frame_buffer(self.clone()), || {
66 self.data.gl.context().framebuffer_renderbuffer(
67 WebGlRenderingContext::FRAMEBUFFER,
68 WebGlRenderingContext::DEPTH_ATTACHMENT,
69 WebGlRenderingContext::RENDERBUFFER,
70 self.depth_buffer.as_ref().map(|buffer| buffer.handle()),
71 );
72 });
73 self
74 }
75 pub fn color_buffer(&self) -> Option<Texture> {
76 self.color_buffer.clone()
77 }
78 pub fn depth_buffer(&self) -> Option<DepthBuffer> {
79 self.depth_buffer.clone()
80 }
81
82 pub(crate) fn handle(&self) -> &WebGlFramebuffer {
83 &self.data.handle
84 }
85}