1use crate::__gl;
4use crate::__gl::types::{GLenum, GLuint};
5
6use crate::debug::{Object, ObjectType};
7use crate::device::Device;
8use crate::error::Result;
9use crate::{Format, ImageView, Region};
10
11pub enum ClearAttachment {
13 ColorInt(usize, [i32; 4]),
14 ColorUint(usize, [u32; 4]),
15 ColorFloat(usize, [f32; 4]),
16 Depth(f32),
17 Stencil(i32),
18 DepthStencil(f32, i32),
19}
20
21#[derive(Copy, Clone, Debug)]
23pub enum Attachment {
24 Color(usize),
25 Depth,
26 Stencil,
27 DepthStencil,
28}
29
30impl Attachment {
31 fn target(&self) -> GLenum {
32 match *self {
33 Attachment::Color(slot) => __gl::COLOR_ATTACHMENT0 + slot as u32,
34 Attachment::Depth => __gl::DEPTH_ATTACHMENT,
35 Attachment::Stencil => __gl::STENCIL_ATTACHMENT,
36 Attachment::DepthStencil => __gl::DEPTH_STENCIL_ATTACHMENT,
37 }
38 }
39}
40
41pub enum AttachmentView {
43 Image(ImageView),
44 Renderbuffer(Renderbuffer),
45}
46
47#[repr(transparent)]
49#[derive(Clone, Copy)]
50pub struct Framebuffer(pub(crate) GLuint);
51
52impl Framebuffer {
53 pub const DEFAULT: Self = Framebuffer(0);
58}
59
60impl Object for Framebuffer {
61 const TYPE: ObjectType = ObjectType::Framebuffer;
62 fn handle(&self) -> GLuint {
63 self.0
64 }
65}
66
67#[repr(transparent)]
69#[derive(Clone, Copy)]
70pub struct Renderbuffer(GLuint);
71
72impl Object for Renderbuffer {
73 const TYPE: ObjectType = ObjectType::Renderbuffer;
74 fn handle(&self) -> GLuint {
75 self.0
76 }
77}
78
79impl Device {
80 pub unsafe fn create_framebuffer(&self) -> Result<Framebuffer> {
82 let mut framebuffer = 0;
83 self.0.CreateFramebuffers(1, &mut framebuffer);
84 self.get_error()?;
85
86 Ok(Framebuffer(framebuffer))
87 }
88
89 pub unsafe fn delete_framebuffer(&self, framebuffer: Framebuffer) {
91 self.delete_framebuffers(&[framebuffer])
92 }
93
94 pub unsafe fn delete_framebuffers(&self, framebuffers: &[Framebuffer]) {
96 self.0.DeleteFramebuffers(
97 framebuffers.len() as _,
98 framebuffers.as_ptr() as *const _, );
100 }
101
102 pub unsafe fn create_renderbuffer(
104 &self,
105 format: Format,
106 width: u32,
107 height: u32,
108 samples: u32,
109 ) -> Result<Renderbuffer> {
110 let mut renderbuffer = 0;
111 self.0.CreateRenderbuffers(1, &mut renderbuffer);
112 self.get_error()?;
113
114 if samples > 1 {
115 self.0.NamedRenderbufferStorageMultisample(
116 renderbuffer,
117 samples as _,
118 format as _,
119 width as _,
120 height as _,
121 );
122 } else {
123 self.0
124 .NamedRenderbufferStorage(renderbuffer, format as _, width as _, height as _);
125 }
126
127 Ok(Renderbuffer(renderbuffer))
128 }
129
130 pub unsafe fn delete_renderbuffer(&self, renderbuffer: Renderbuffer) {
132 self.delete_renderbuffers(&[renderbuffer])
133 }
134
135 pub unsafe fn delete_renderbuffers(&self, renderbuffers: &[Renderbuffer]) {
137 self.0.DeleteRenderbuffers(
138 renderbuffers.len() as _,
139 renderbuffers.as_ptr() as *const _, );
141 }
142
143 pub unsafe fn clear_attachment(&self, fb: Framebuffer, cv: ClearAttachment) {
145 match cv {
146 ClearAttachment::ColorInt(id, color) => {
147 self.0
148 .ClearNamedFramebufferiv(fb.0, __gl::COLOR, id as _, color.as_ptr());
149 }
150 ClearAttachment::ColorUint(id, color) => {
151 self.0
152 .ClearNamedFramebufferuiv(fb.0, __gl::COLOR, id as _, color.as_ptr());
153 }
154 ClearAttachment::ColorFloat(id, color) => {
155 self.0
156 .ClearNamedFramebufferfv(fb.0, __gl::COLOR, id as _, color.as_ptr());
157 }
158 ClearAttachment::Depth(depth) => {
159 self.0
160 .ClearNamedFramebufferfv(fb.0, __gl::DEPTH, 0, &depth as *const _);
161 }
162 ClearAttachment::Stencil(stencil) => {
163 self.0
164 .ClearNamedFramebufferiv(fb.0, __gl::STENCIL, 0, &stencil as *const _);
165 }
166 ClearAttachment::DepthStencil(depth, stencil) => {
167 self.0
168 .ClearNamedFramebufferfi(fb.0, __gl::DEPTH_STENCIL, 0, depth, stencil);
169 }
170 }
171 }
172
173 pub unsafe fn invalidate_attachments(
175 &self,
176 framebuffer: Framebuffer,
177 attachments: &[Attachment],
178 region: Region,
179 ) {
180 let attachments = attachments
181 .iter()
182 .map(|att| att.target())
183 .collect::<Vec<_>>();
184
185 self.0.InvalidateNamedFramebufferSubData(
186 framebuffer.0,
187 attachments.len() as _,
188 attachments.as_ptr(),
189 region.x,
190 region.y,
191 region.w,
192 region.h,
193 )
194 }
195
196 pub unsafe fn bind_framebuffer(&self, framebuffer: Framebuffer) {
200 self.0.BindFramebuffer(__gl::FRAMEBUFFER, framebuffer.0);
201 }
202
203 pub unsafe fn bind_draw_framebuffer(&self, framebuffer: Framebuffer) {
205 self.0
206 .BindFramebuffer(__gl::DRAW_FRAMEBUFFER, framebuffer.0);
207 }
208
209 pub unsafe fn bind_read_framebuffer(&self, framebuffer: Framebuffer) {
211 self.0
212 .BindFramebuffer(__gl::READ_FRAMEBUFFER, framebuffer.0);
213 }
214
215 pub unsafe fn bind_attachments(
219 &self,
220 framebuffer: Framebuffer,
221 attachments: &[(Attachment, AttachmentView)],
222 ) {
223 assert_ne!(
224 framebuffer.0, 0,
225 "The default framebuffer can't be changed."
226 );
227
228 for (attachment, view) in attachments {
229 let target = attachment.target();
230 match *view {
231 AttachmentView::Image(image) => {
232 self.0
233 .NamedFramebufferTexture(framebuffer.0, target, image.0, 0);
234 }
235 AttachmentView::Renderbuffer(renderbuffer) => {
236 self.0.NamedFramebufferRenderbuffer(
237 framebuffer.0,
238 target,
239 __gl::RENDERBUFFER,
240 renderbuffer.0,
241 );
242 }
243 }
244 }
245 }
246
247 pub unsafe fn set_color_attachments(&self, framebuffer: Framebuffer, attachments: &[u32]) {
253 assert_ne!(
254 framebuffer.0, 0,
255 "The default framebuffer can't be changed."
256 );
257
258 let attachments = attachments
259 .iter()
260 .map(|i| i + __gl::COLOR_ATTACHMENT0)
261 .collect::<Vec<_>>();
262 self.0.NamedFramebufferDrawBuffers(
263 framebuffer.0,
264 attachments.len() as _,
265 attachments.as_ptr(),
266 );
267 }
268
269 pub unsafe fn set_read_attachment(&self, framebuffer: Framebuffer, attachment: u32) {
271 assert_ne!(
272 framebuffer.0, 0,
273 "The default framebuffer can't be changed."
274 );
275
276 self.0
277 .NamedFramebufferReadBuffer(framebuffer.0, __gl::COLOR_ATTACHMENT0 + attachment);
278 }
279}