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