1use crate::context::{ContextAttributeFlags, ContextAttributes};
4use crate::gl;
5use crate::Gl;
6use std::thread;
7
8use euclid::default::Size2D;
9use gl::Renderbuffer;
10use glow::HasContext;
11
12pub(crate) enum Renderbuffers {
13 IndividualDepthStencil {
14 depth: Option<Renderbuffer>,
15 stencil: Option<Renderbuffer>,
16 },
17 CombinedDepthStencil(Option<Renderbuffer>),
18}
19
20impl Drop for Renderbuffers {
21 fn drop(&mut self) {
22 match *self {
23 Renderbuffers::IndividualDepthStencil {
24 depth: None,
25 stencil: None,
26 }
27 | Renderbuffers::CombinedDepthStencil(None) => {}
28 _ => {
29 if !thread::panicking() {
30 panic!("Should have destroyed the FBO renderbuffers with `destroy()`!")
31 }
32 }
33 }
34 }
35}
36
37impl Renderbuffers {
38 pub(crate) fn new(
39 gl: &Gl,
40 size: &Size2D<i32>,
41 attributes: &ContextAttributes,
42 ) -> Renderbuffers {
43 unsafe {
44 if attributes
45 .flags
46 .contains(ContextAttributeFlags::DEPTH | ContextAttributeFlags::STENCIL)
47 {
48 let renderbuffer = gl.create_renderbuffer().unwrap();
49 gl.bind_renderbuffer(gl::RENDERBUFFER, Some(renderbuffer));
50 gl.renderbuffer_storage(
51 gl::RENDERBUFFER,
52 gl::DEPTH24_STENCIL8,
53 size.width,
54 size.height,
55 );
56 gl.bind_renderbuffer(gl::RENDERBUFFER, None);
57 return Renderbuffers::CombinedDepthStencil(Some(renderbuffer));
58 }
59
60 let (mut depth_renderbuffer, mut stencil_renderbuffer) = (None, None);
61 if attributes.flags.contains(ContextAttributeFlags::DEPTH) {
62 depth_renderbuffer = Some(gl.create_renderbuffer().unwrap());
63 gl.bind_renderbuffer(gl::RENDERBUFFER, depth_renderbuffer);
64 gl.renderbuffer_storage(
65 gl::RENDERBUFFER,
66 gl::DEPTH_COMPONENT24,
67 size.width,
68 size.height,
69 );
70 }
71 if attributes.flags.contains(ContextAttributeFlags::STENCIL) {
72 stencil_renderbuffer = Some(gl.create_renderbuffer().unwrap());
73 gl.bind_renderbuffer(gl::RENDERBUFFER, stencil_renderbuffer);
74 gl.renderbuffer_storage(
75 gl::RENDERBUFFER,
76 gl::STENCIL_INDEX8,
77 size.width,
78 size.height,
79 );
80 }
81 gl.bind_renderbuffer(gl::RENDERBUFFER, None);
82
83 Renderbuffers::IndividualDepthStencil {
84 depth: depth_renderbuffer,
85 stencil: stencil_renderbuffer,
86 }
87 }
88 }
89
90 pub(crate) fn bind_to_current_framebuffer(&self, gl: &Gl) {
91 unsafe {
92 match *self {
93 Renderbuffers::CombinedDepthStencil(renderbuffer) => {
94 if renderbuffer.is_some() {
95 gl.framebuffer_renderbuffer(
96 gl::FRAMEBUFFER,
97 gl::DEPTH_STENCIL_ATTACHMENT,
98 gl::RENDERBUFFER,
99 renderbuffer,
100 );
101 }
102 }
103 Renderbuffers::IndividualDepthStencil {
104 depth: depth_renderbuffer,
105 stencil: stencil_renderbuffer,
106 } => {
107 if depth_renderbuffer.is_some() {
108 gl.framebuffer_renderbuffer(
109 gl::FRAMEBUFFER,
110 gl::DEPTH_ATTACHMENT,
111 gl::RENDERBUFFER,
112 depth_renderbuffer,
113 );
114 }
115 if stencil_renderbuffer.is_some() {
116 gl.framebuffer_renderbuffer(
117 gl::FRAMEBUFFER,
118 gl::STENCIL_ATTACHMENT,
119 gl::RENDERBUFFER,
120 stencil_renderbuffer,
121 );
122 }
123 }
124 }
125 }
126 }
127
128 pub(crate) fn destroy(&mut self, gl: &Gl) {
129 unsafe {
130 gl.bind_renderbuffer(gl::RENDERBUFFER, None);
131
132 match *self {
133 Renderbuffers::CombinedDepthStencil(ref mut renderbuffer) => {
134 if let Some(renderbuffer) = renderbuffer.take() {
135 gl.delete_renderbuffer(renderbuffer);
136 }
137 }
138 Renderbuffers::IndividualDepthStencil {
139 depth: ref mut depth_renderbuffer,
140 stencil: ref mut stencil_renderbuffer,
141 } => {
142 if let Some(stencil_renderbuffer) = stencil_renderbuffer.take() {
143 gl.delete_renderbuffer(stencil_renderbuffer);
144 }
145 if let Some(depth_renderbuffer) = depth_renderbuffer.take() {
146 gl.delete_renderbuffer(depth_renderbuffer);
147 }
148 }
149 }
150 }
151 }
152}