glow/
native.rs

1use super::*;
2use crate::{gl46 as native_gl, version::Version};
3use std::ffi::CStr;
4use std::ptr;
5use std::{collections::HashSet, ffi::CString, num::NonZeroU32};
6
7#[derive(Default)]
8struct Constants {
9    max_label_length: i32,
10}
11
12/// Store a boxed callback (i.e., `Box<Box<dyn FnMut(...)>>`) as a raw pointer, so that it can be
13/// referenced by the C API and later converted back into a `Box` and dropped.
14///
15/// We use a raw pointer here because `Box` aliasing rules are not fully defined, so we can'
16/// guarantee that it's not undefined behavior to keep a `Box` here while it's used as a raw
17/// pointer in the C API.
18struct DebugCallbackRawPtr {
19    callback: *mut std::os::raw::c_void,
20}
21
22unsafe impl Send for DebugCallbackRawPtr {}
23unsafe impl Sync for DebugCallbackRawPtr {}
24
25impl Drop for DebugCallbackRawPtr {
26    fn drop(&mut self) {
27        unsafe {
28            // Convert callback back into `Box` and drop it.
29            let thin_ptr = Box::from_raw(self.callback as *mut DebugCallback);
30            let callback = *thin_ptr;
31            drop(callback);
32        }
33    }
34}
35
36pub struct Context {
37    raw: native_gl::GlFns,
38    extensions: HashSet<String>,
39    constants: Constants,
40    version: Version,
41    debug_callback: Option<DebugCallbackRawPtr>,
42}
43
44impl Context {
45    pub unsafe fn from_loader_function_cstr<F>(mut loader_function: F) -> Self
46    where
47        F: FnMut(&CStr) -> *const std::os::raw::c_void,
48    {
49        let raw: native_gl::GlFns =
50            native_gl::GlFns::load_with(|p: *const std::os::raw::c_char| {
51                let c_str = std::ffi::CStr::from_ptr(p);
52                loader_function(c_str) as *mut std::os::raw::c_void
53            });
54
55        // Retrieve and parse `GL_VERSION`
56        let raw_string = raw.GetString(VERSION);
57
58        if raw_string.is_null() {
59            panic!("Reading GL_VERSION failed. Make sure there is a valid GL context currently active.")
60        }
61
62        let raw_version = std::ffi::CStr::from_ptr(raw_string as *const native_gl::GLchar)
63            .to_str()
64            .unwrap()
65            .to_owned();
66        let version = Version::parse(&raw_version).unwrap();
67
68        // Setup extensions and constants after the context has been built
69        let mut context = Self {
70            raw,
71            extensions: HashSet::new(),
72            constants: Constants::default(),
73            version,
74            debug_callback: None,
75        };
76
77        // Use core-only functions to populate extension list
78        if (context.version >= Version::new(3, 0, None, String::from("")))
79            || (context.version >= Version::new_embedded(3, 0, String::from("")))
80        {
81            let num_extensions = context.get_parameter_i32(NUM_EXTENSIONS);
82            for i in 0..num_extensions {
83                let extension_name = context.get_parameter_indexed_string(EXTENSIONS, i as u32);
84                context.extensions.insert(extension_name);
85            }
86        } else {
87            // Fallback
88            context.extensions.extend(
89                context
90                    .get_parameter_string(EXTENSIONS)
91                    .split(' ')
92                    .map(|s| s.to_string()),
93            );
94        };
95
96        // After the extensions are known, we can populate constants (including
97        // constants that depend on extensions being enabled)
98        context.constants.max_label_length = if context.supports_debug() {
99            context.get_parameter_i32(MAX_LABEL_LENGTH)
100        } else {
101            0
102        };
103
104        context
105    }
106
107    pub unsafe fn from_loader_function<F>(mut loader_function: F) -> Self
108    where
109        F: FnMut(&str) -> *const std::os::raw::c_void,
110    {
111        Self::from_loader_function_cstr(move |name| loader_function(name.to_str().unwrap()))
112    }
113
114    /// Creates a texture from an external GL name.
115    ///
116    /// This can be useful when a texture is created outside of glow (e.g. OpenXR surface) but glow
117    /// still needs access to it for rendering.
118    #[deprecated = "Use the NativeTexture constructor instead"]
119    pub unsafe fn create_texture_from_gl_name(gl_name: native_gl::GLuint) -> NativeTexture {
120        NativeTexture(non_zero_gl_name(gl_name))
121    }
122
123    /// Creates a framebuffer from an external GL name.
124    ///
125    /// This can be useful when a framebuffer is created outside of glow (e.g: via `surfman` or another
126    /// crate that supports sharing of buffers between GL contexts), but glow needs to set it as a target.
127    #[deprecated = "Use the NativeFramebuffer constructor instead"]
128    pub unsafe fn create_framebuffer_from_gl_name(gl_name: native_gl::GLuint) -> NativeFramebuffer {
129        NativeFramebuffer(non_zero_gl_name(gl_name))
130    }
131
132    unsafe fn get_parameter_gl_name(&self, parameter: u32) -> Option<NonZeroU32> {
133        let value = self.get_parameter_i32(parameter) as u32;
134        if value == 0 {
135            None
136        } else {
137            Some(non_zero_gl_name(value))
138        }
139    }
140}
141
142impl std::fmt::Debug for Context {
143    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
144        write!(f, "Native_GL_Context")
145    }
146}
147
148fn non_zero_gl_name(value: native_gl::GLuint) -> NonZeroU32 {
149    NonZeroU32::new(value as u32).expect("expected non-zero GL name")
150}
151
152#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
153pub struct NativeShader(pub NonZeroU32);
154
155#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
156pub struct NativeProgram(pub NonZeroU32);
157
158#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
159pub struct NativeBuffer(pub NonZeroU32);
160
161#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
162pub struct NativeVertexArray(pub NonZeroU32);
163
164#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
165pub struct NativeTexture(pub NonZeroU32);
166
167#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
168pub struct NativeSampler(pub NonZeroU32);
169
170#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
171pub struct NativeFence(pub native_gl::GLsync);
172
173#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
174pub struct NativeFramebuffer(pub NonZeroU32);
175
176#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
177pub struct NativeRenderbuffer(pub NonZeroU32);
178
179#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
180pub struct NativeQuery(pub NonZeroU32);
181
182#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
183pub struct NativeUniformLocation(pub native_gl::GLuint);
184
185#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
186pub struct NativeTransformFeedback(pub NonZeroU32);
187
188impl crate::__private::Sealed for Context {}
189
190impl HasContext for Context {
191    type Shader = NativeShader;
192    type Program = NativeProgram;
193    type Buffer = NativeBuffer;
194    type VertexArray = NativeVertexArray;
195    type Texture = NativeTexture;
196    type Sampler = NativeSampler;
197    type Fence = NativeFence;
198    type Framebuffer = NativeFramebuffer;
199    type Renderbuffer = NativeRenderbuffer;
200    type Query = NativeQuery;
201    type UniformLocation = NativeUniformLocation;
202    type TransformFeedback = NativeTransformFeedback;
203
204    fn supported_extensions(&self) -> &HashSet<String> {
205        &self.extensions
206    }
207
208    fn supports_debug(&self) -> bool {
209        if self.extensions.contains("GL_KHR_debug") {
210            // Supports extension (either GL or GL ES)
211            true
212        } else if self.version.is_embedded {
213            // GL ES >= 3.2
214            self.version.major == 3 && self.version.minor >= 2
215        } else {
216            // GL >= 4.3
217            self.version.major == 4 && self.version.minor >= 3
218        }
219    }
220
221    fn version(&self) -> &Version {
222        &self.version
223    }
224
225    unsafe fn create_framebuffer(&self) -> Result<Self::Framebuffer, String> {
226        let gl = &self.raw;
227        let mut name = 0;
228        gl.GenFramebuffers(1, &mut name);
229        Ok(NativeFramebuffer(non_zero_gl_name(name)))
230    }
231
232    unsafe fn create_named_framebuffer(&self) -> Result<Self::Framebuffer, String> {
233        let gl = &self.raw;
234        let mut name = 0;
235        gl.CreateFramebuffers(1, &mut name);
236        Ok(NativeFramebuffer(non_zero_gl_name(name)))
237    }
238
239    unsafe fn is_framebuffer(&self, framebuffer: Self::Framebuffer) -> bool {
240        let gl = &self.raw;
241        gl.IsFramebuffer(framebuffer.0.get()) != 0
242    }
243
244    unsafe fn create_query(&self) -> Result<Self::Query, String> {
245        let gl = &self.raw;
246        let mut name = 0;
247        gl.GenQueries(1, &mut name);
248        Ok(NativeQuery(non_zero_gl_name(name)))
249    }
250
251    unsafe fn create_renderbuffer(&self) -> Result<Self::Renderbuffer, String> {
252        let gl = &self.raw;
253        let mut name = 0;
254        gl.GenRenderbuffers(1, &mut name);
255        Ok(NativeRenderbuffer(non_zero_gl_name(name)))
256    }
257
258    unsafe fn is_renderbuffer(&self, renderbuffer: Self::Renderbuffer) -> bool {
259        let gl = &self.raw;
260        gl.IsRenderbuffer(renderbuffer.0.get()) != 0
261    }
262
263    unsafe fn create_sampler(&self) -> Result<Self::Sampler, String> {
264        let gl = &self.raw;
265        let mut name = 0;
266        gl.GenSamplers(1, &mut name);
267        Ok(NativeSampler(non_zero_gl_name(name)))
268    }
269
270    unsafe fn create_shader(&self, shader_type: u32) -> Result<Self::Shader, String> {
271        let gl = &self.raw;
272        Ok(NativeShader(non_zero_gl_name(
273            gl.CreateShader(shader_type as u32),
274        )))
275    }
276
277    unsafe fn is_shader(&self, shader: Self::Shader) -> bool {
278        let gl = &self.raw;
279        gl.IsShader(shader.0.get()) != 0
280    }
281
282    unsafe fn create_texture(&self) -> Result<Self::Texture, String> {
283        let gl = &self.raw;
284        let mut name = 0;
285        gl.GenTextures(1, &mut name);
286        Ok(NativeTexture(non_zero_gl_name(name)))
287    }
288
289    unsafe fn create_named_texture(&self, target: u32) -> Result<Self::Texture, String> {
290        let gl = &self.raw;
291        let mut name = 0;
292        gl.CreateTextures(target, 1, &mut name);
293        Ok(NativeTexture(non_zero_gl_name(name)))
294    }
295
296    unsafe fn is_texture(&self, texture: Self::Texture) -> bool {
297        let gl = &self.raw;
298        gl.IsTexture(texture.0.get()) != 0
299    }
300
301    unsafe fn delete_shader(&self, shader: Self::Shader) {
302        let gl = &self.raw;
303        gl.DeleteShader(shader.0.get());
304    }
305
306    unsafe fn shader_source(&self, shader: Self::Shader, source: &str) {
307        let gl = &self.raw;
308        gl.ShaderSource(
309            shader.0.get(),
310            1,
311            &(source.as_ptr() as *const native_gl::GLchar),
312            &(source.len() as native_gl::GLint),
313        );
314    }
315
316    unsafe fn compile_shader(&self, shader: Self::Shader) {
317        let gl = &self.raw;
318        gl.CompileShader(shader.0.get());
319    }
320
321    unsafe fn get_shader_completion_status(&self, shader: Self::Shader) -> bool {
322        let gl = &self.raw;
323        let mut status = 0;
324        gl.GetShaderiv(shader.0.get(), COMPLETION_STATUS, &mut status);
325        1 == status
326    }
327
328    unsafe fn get_shader_compile_status(&self, shader: Self::Shader) -> bool {
329        let gl = &self.raw;
330        let mut status = 0;
331        gl.GetShaderiv(shader.0.get(), COMPILE_STATUS, &mut status);
332        1 == status
333    }
334
335    unsafe fn get_shader_info_log(&self, shader: Self::Shader) -> String {
336        let gl = &self.raw;
337        let mut length = 0;
338        gl.GetShaderiv(shader.0.get(), INFO_LOG_LENGTH, &mut length);
339        if length > 0 {
340            let mut log = String::with_capacity(length as usize);
341            log.extend(std::iter::repeat('\0').take(length as usize));
342            gl.GetShaderInfoLog(
343                shader.0.get(),
344                length,
345                &mut length,
346                (&log[..]).as_ptr() as *mut native_gl::GLchar,
347            );
348            log.truncate(length as usize);
349            log
350        } else {
351            String::from("")
352        }
353    }
354
355    unsafe fn get_tex_image(
356        &self,
357        target: u32,
358        level: i32,
359        format: u32,
360        ty: u32,
361        pixels: PixelPackData,
362    ) {
363        let gl = &self.raw;
364        gl.GetTexImage(
365            target,
366            level,
367            format,
368            ty,
369            match pixels {
370                PixelPackData::BufferOffset(offset) => offset as *mut std::ffi::c_void,
371                PixelPackData::Slice(data) => data.as_mut_ptr() as *mut std::ffi::c_void,
372            },
373        );
374    }
375
376    unsafe fn create_program(&self) -> Result<Self::Program, String> {
377        let gl = &self.raw;
378        Ok(NativeProgram(non_zero_gl_name(gl.CreateProgram())))
379    }
380
381    unsafe fn is_program(&self, program: Self::Program) -> bool {
382        let gl = &self.raw;
383        gl.IsProgram(program.0.get()) != 0
384    }
385
386    unsafe fn delete_program(&self, program: Self::Program) {
387        let gl = &self.raw;
388        gl.DeleteProgram(program.0.get());
389    }
390
391    unsafe fn attach_shader(&self, program: Self::Program, shader: Self::Shader) {
392        let gl = &self.raw;
393        gl.AttachShader(program.0.get(), shader.0.get());
394    }
395
396    unsafe fn detach_shader(&self, program: Self::Program, shader: Self::Shader) {
397        let gl = &self.raw;
398        gl.DetachShader(program.0.get(), shader.0.get());
399    }
400
401    unsafe fn link_program(&self, program: Self::Program) {
402        let gl = &self.raw;
403        gl.LinkProgram(program.0.get());
404    }
405
406    unsafe fn get_program_completion_status(&self, program: Self::Program) -> bool {
407        let gl = &self.raw;
408        let mut status = 0;
409        gl.GetProgramiv(program.0.get(), COMPLETION_STATUS, &mut status);
410        1 == status
411    }
412
413    unsafe fn get_program_link_status(&self, program: Self::Program) -> bool {
414        let gl = &self.raw;
415        let mut status = 0;
416        gl.GetProgramiv(program.0.get(), LINK_STATUS, &mut status);
417        1 == status
418    }
419
420    unsafe fn get_program_info_log(&self, program: Self::Program) -> String {
421        let gl = &self.raw;
422        let mut length = 0;
423        gl.GetProgramiv(program.0.get(), INFO_LOG_LENGTH, &mut length);
424        if length > 0 {
425            let mut log = String::with_capacity(length as usize);
426            log.extend(std::iter::repeat('\0').take(length as usize));
427            gl.GetProgramInfoLog(
428                program.0.get(),
429                length,
430                &mut length,
431                (&log[..]).as_ptr() as *mut native_gl::GLchar,
432            );
433            log.truncate(length as usize);
434            log
435        } else {
436            String::from("")
437        }
438    }
439
440    unsafe fn get_program_resource_i32(
441        &self,
442        program: Self::Program,
443        interface: u32,
444        index: u32,
445        properties: &[u32],
446    ) -> Vec<i32> {
447        let gl = &self.raw;
448        // query the number of output parameters first
449        let mut length = 0i32;
450        gl.GetProgramResourceiv(
451            program.0.get(),
452            interface,
453            index,
454            properties.len() as i32,
455            properties.as_ptr(),
456            0,
457            &mut length,
458            ptr::null_mut(),
459        );
460        // get the parameter values
461        let mut params = vec![0i32; length as usize];
462        gl.GetProgramResourceiv(
463            program.0.get(),
464            interface,
465            index,
466            properties.len() as i32,
467            properties.as_ptr(),
468            length,
469            &mut length,
470            params.as_mut_ptr(),
471        );
472        params
473    }
474
475    unsafe fn program_uniform_1_i32(
476        &self,
477        program: Self::Program,
478        location: Option<&Self::UniformLocation>,
479        x: i32,
480    ) {
481        let gl = &self.raw;
482        if let Some(loc) = location {
483            gl.ProgramUniform1i(program.0.get(), loc.0 as i32, x);
484        }
485    }
486
487    unsafe fn program_uniform_2_i32(
488        &self,
489        program: Self::Program,
490        location: Option<&Self::UniformLocation>,
491        x: i32,
492        y: i32,
493    ) {
494        let gl = &self.raw;
495        if let Some(loc) = location {
496            gl.ProgramUniform2i(program.0.get(), loc.0 as i32, x, y);
497        }
498    }
499
500    unsafe fn program_uniform_3_i32(
501        &self,
502        program: Self::Program,
503        location: Option<&Self::UniformLocation>,
504        x: i32,
505        y: i32,
506        z: i32,
507    ) {
508        let gl = &self.raw;
509        if let Some(loc) = location {
510            gl.ProgramUniform3i(program.0.get(), loc.0 as i32, x, y, z);
511        }
512    }
513
514    unsafe fn program_uniform_4_i32(
515        &self,
516        program: Self::Program,
517        location: Option<&Self::UniformLocation>,
518        x: i32,
519        y: i32,
520        z: i32,
521        w: i32,
522    ) {
523        let gl = &self.raw;
524        if let Some(loc) = location {
525            gl.ProgramUniform4i(program.0.get(), loc.0 as i32, x, y, z, w);
526        }
527    }
528
529    unsafe fn program_uniform_1_i32_slice(
530        &self,
531        program: Self::Program,
532        location: Option<&Self::UniformLocation>,
533        v: &[i32],
534    ) {
535        let gl = &self.raw;
536        if let Some(loc) = location {
537            gl.ProgramUniform1iv(program.0.get(), loc.0 as i32, v.len() as i32, v.as_ptr());
538        }
539    }
540
541    unsafe fn program_uniform_2_i32_slice(
542        &self,
543        program: Self::Program,
544        location: Option<&Self::UniformLocation>,
545        v: &[i32],
546    ) {
547        let gl = &self.raw;
548        if let Some(loc) = location {
549            gl.ProgramUniform2iv(
550                program.0.get(),
551                loc.0 as i32,
552                v.len() as i32 / 2,
553                v.as_ptr(),
554            );
555        }
556    }
557
558    unsafe fn program_uniform_3_i32_slice(
559        &self,
560        program: Self::Program,
561        location: Option<&Self::UniformLocation>,
562        v: &[i32],
563    ) {
564        let gl = &self.raw;
565        if let Some(loc) = location {
566            gl.ProgramUniform3iv(
567                program.0.get(),
568                loc.0 as i32,
569                v.len() as i32 / 3,
570                v.as_ptr(),
571            );
572        }
573    }
574
575    unsafe fn program_uniform_4_i32_slice(
576        &self,
577        program: Self::Program,
578        location: Option<&Self::UniformLocation>,
579        v: &[i32],
580    ) {
581        let gl = &self.raw;
582        if let Some(loc) = location {
583            gl.ProgramUniform4iv(
584                program.0.get(),
585                loc.0 as i32,
586                v.len() as i32 / 4,
587                v.as_ptr(),
588            );
589        }
590    }
591
592    unsafe fn program_uniform_1_u32(
593        &self,
594        program: Self::Program,
595        location: Option<&Self::UniformLocation>,
596        x: u32,
597    ) {
598        let gl = &self.raw;
599        if let Some(loc) = location {
600            gl.ProgramUniform1ui(program.0.get(), loc.0 as i32, x);
601        }
602    }
603
604    unsafe fn program_uniform_2_u32(
605        &self,
606        program: Self::Program,
607        location: Option<&Self::UniformLocation>,
608        x: u32,
609        y: u32,
610    ) {
611        let gl = &self.raw;
612        if let Some(loc) = location {
613            gl.ProgramUniform2ui(program.0.get(), loc.0 as i32, x, y);
614        }
615    }
616
617    unsafe fn program_uniform_3_u32(
618        &self,
619        program: Self::Program,
620        location: Option<&Self::UniformLocation>,
621        x: u32,
622        y: u32,
623        z: u32,
624    ) {
625        let gl = &self.raw;
626        if let Some(loc) = location {
627            gl.ProgramUniform3ui(program.0.get(), loc.0 as i32, x, y, z);
628        }
629    }
630
631    unsafe fn program_uniform_4_u32(
632        &self,
633        program: Self::Program,
634        location: Option<&Self::UniformLocation>,
635        x: u32,
636        y: u32,
637        z: u32,
638        w: u32,
639    ) {
640        let gl = &self.raw;
641        if let Some(loc) = location {
642            gl.ProgramUniform4ui(program.0.get(), loc.0 as i32, x, y, z, w);
643        }
644    }
645
646    unsafe fn program_uniform_1_u32_slice(
647        &self,
648        program: Self::Program,
649        location: Option<&Self::UniformLocation>,
650        v: &[u32],
651    ) {
652        let gl = &self.raw;
653        if let Some(loc) = location {
654            gl.ProgramUniform1uiv(program.0.get(), loc.0 as i32, v.len() as i32, v.as_ptr());
655        }
656    }
657
658    unsafe fn program_uniform_2_u32_slice(
659        &self,
660        program: Self::Program,
661        location: Option<&Self::UniformLocation>,
662        v: &[u32],
663    ) {
664        let gl = &self.raw;
665        if let Some(loc) = location {
666            gl.ProgramUniform2uiv(
667                program.0.get(),
668                loc.0 as i32,
669                v.len() as i32 / 2,
670                v.as_ptr(),
671            );
672        }
673    }
674
675    unsafe fn program_uniform_3_u32_slice(
676        &self,
677        program: Self::Program,
678        location: Option<&Self::UniformLocation>,
679        v: &[u32],
680    ) {
681        let gl = &self.raw;
682        if let Some(loc) = location {
683            gl.ProgramUniform3uiv(
684                program.0.get(),
685                loc.0 as i32,
686                v.len() as i32 / 3,
687                v.as_ptr(),
688            );
689        }
690    }
691
692    unsafe fn program_uniform_4_u32_slice(
693        &self,
694        program: Self::Program,
695        location: Option<&Self::UniformLocation>,
696        v: &[u32],
697    ) {
698        let gl = &self.raw;
699        if let Some(loc) = location {
700            gl.ProgramUniform4uiv(
701                program.0.get(),
702                loc.0 as i32,
703                v.len() as i32 / 4,
704                v.as_ptr(),
705            );
706        }
707    }
708
709    unsafe fn program_uniform_1_f32(
710        &self,
711        program: Self::Program,
712        location: Option<&Self::UniformLocation>,
713        x: f32,
714    ) {
715        let gl = &self.raw;
716        if let Some(loc) = location {
717            gl.ProgramUniform1f(program.0.get(), loc.0 as i32, x);
718        }
719    }
720
721    unsafe fn program_uniform_2_f32(
722        &self,
723        program: Self::Program,
724        location: Option<&Self::UniformLocation>,
725        x: f32,
726        y: f32,
727    ) {
728        let gl = &self.raw;
729        if let Some(loc) = location {
730            gl.ProgramUniform2f(program.0.get(), loc.0 as i32, x, y);
731        }
732    }
733
734    unsafe fn program_uniform_3_f32(
735        &self,
736        program: Self::Program,
737        location: Option<&Self::UniformLocation>,
738        x: f32,
739        y: f32,
740        z: f32,
741    ) {
742        let gl = &self.raw;
743        if let Some(loc) = location {
744            gl.ProgramUniform3f(program.0.get(), loc.0 as i32, x, y, z);
745        }
746    }
747
748    unsafe fn program_uniform_4_f32(
749        &self,
750        program: Self::Program,
751        location: Option<&Self::UniformLocation>,
752        x: f32,
753        y: f32,
754        z: f32,
755        w: f32,
756    ) {
757        let gl = &self.raw;
758        if let Some(loc) = location {
759            gl.ProgramUniform4f(program.0.get(), loc.0 as i32, x, y, z, w);
760        }
761    }
762
763    unsafe fn program_uniform_1_f32_slice(
764        &self,
765        program: Self::Program,
766        location: Option<&Self::UniformLocation>,
767        v: &[f32],
768    ) {
769        let gl = &self.raw;
770        if let Some(loc) = location {
771            gl.ProgramUniform1fv(program.0.get(), loc.0 as i32, v.len() as i32, v.as_ptr());
772        }
773    }
774
775    unsafe fn program_uniform_2_f32_slice(
776        &self,
777        program: Self::Program,
778        location: Option<&Self::UniformLocation>,
779        v: &[f32],
780    ) {
781        let gl = &self.raw;
782        if let Some(loc) = location {
783            gl.ProgramUniform2fv(
784                program.0.get(),
785                loc.0 as i32,
786                v.len() as i32 / 2,
787                v.as_ptr(),
788            );
789        }
790    }
791
792    unsafe fn program_uniform_3_f32_slice(
793        &self,
794        program: Self::Program,
795        location: Option<&Self::UniformLocation>,
796        v: &[f32],
797    ) {
798        let gl = &self.raw;
799        if let Some(loc) = location {
800            gl.ProgramUniform3fv(
801                program.0.get(),
802                loc.0 as i32,
803                v.len() as i32 / 3,
804                v.as_ptr(),
805            );
806        }
807    }
808
809    unsafe fn program_uniform_4_f32_slice(
810        &self,
811        program: Self::Program,
812        location: Option<&Self::UniformLocation>,
813        v: &[f32],
814    ) {
815        let gl = &self.raw;
816        if let Some(loc) = location {
817            gl.ProgramUniform4fv(
818                program.0.get(),
819                loc.0 as i32,
820                v.len() as i32 / 4,
821                v.as_ptr(),
822            );
823        }
824    }
825
826    unsafe fn program_uniform_matrix_2_f32_slice(
827        &self,
828        program: Self::Program,
829        location: Option<&Self::UniformLocation>,
830        transpose: bool,
831        v: &[f32],
832    ) {
833        let gl = &self.raw;
834        if let Some(loc) = location {
835            gl.ProgramUniformMatrix2fv(
836                program.0.get(),
837                loc.0 as i32,
838                v.len() as i32 / 4,
839                transpose as u8,
840                v.as_ptr(),
841            );
842        }
843    }
844
845    unsafe fn program_uniform_matrix_2x3_f32_slice(
846        &self,
847        program: Self::Program,
848        location: Option<&Self::UniformLocation>,
849        transpose: bool,
850        v: &[f32],
851    ) {
852        let gl = &self.raw;
853        if let Some(loc) = location {
854            gl.ProgramUniformMatrix2x3fv(
855                program.0.get(),
856                loc.0 as i32,
857                v.len() as i32 / 6,
858                transpose as u8,
859                v.as_ptr(),
860            );
861        }
862    }
863
864    unsafe fn program_uniform_matrix_2x4_f32_slice(
865        &self,
866        program: Self::Program,
867        location: Option<&Self::UniformLocation>,
868        transpose: bool,
869        v: &[f32],
870    ) {
871        let gl = &self.raw;
872        if let Some(loc) = location {
873            gl.ProgramUniformMatrix2x4fv(
874                program.0.get(),
875                loc.0 as i32,
876                v.len() as i32 / 8,
877                transpose as u8,
878                v.as_ptr(),
879            );
880        }
881    }
882
883    unsafe fn program_uniform_matrix_3x2_f32_slice(
884        &self,
885        program: Self::Program,
886        location: Option<&Self::UniformLocation>,
887        transpose: bool,
888        v: &[f32],
889    ) {
890        let gl = &self.raw;
891        if let Some(loc) = location {
892            gl.ProgramUniformMatrix3x2fv(
893                program.0.get(),
894                loc.0 as i32,
895                v.len() as i32 / 6,
896                transpose as u8,
897                v.as_ptr(),
898            );
899        }
900    }
901
902    unsafe fn program_uniform_matrix_3_f32_slice(
903        &self,
904        program: Self::Program,
905        location: Option<&Self::UniformLocation>,
906        transpose: bool,
907        v: &[f32],
908    ) {
909        let gl = &self.raw;
910        if let Some(loc) = location {
911            gl.ProgramUniformMatrix3fv(
912                program.0.get(),
913                loc.0 as i32,
914                v.len() as i32 / 9,
915                transpose as u8,
916                v.as_ptr(),
917            );
918        }
919    }
920
921    unsafe fn program_uniform_matrix_3x4_f32_slice(
922        &self,
923        program: Self::Program,
924        location: Option<&Self::UniformLocation>,
925        transpose: bool,
926        v: &[f32],
927    ) {
928        let gl = &self.raw;
929        if let Some(loc) = location {
930            gl.ProgramUniformMatrix3x4fv(
931                program.0.get(),
932                loc.0 as i32,
933                v.len() as i32 / 12,
934                transpose as u8,
935                v.as_ptr(),
936            );
937        }
938    }
939
940    unsafe fn program_uniform_matrix_4x2_f32_slice(
941        &self,
942        program: Self::Program,
943        location: Option<&Self::UniformLocation>,
944        transpose: bool,
945        v: &[f32],
946    ) {
947        let gl = &self.raw;
948        if let Some(loc) = location {
949            gl.ProgramUniformMatrix4x2fv(
950                program.0.get(),
951                loc.0 as i32,
952                v.len() as i32 / 8,
953                transpose as u8,
954                v.as_ptr(),
955            );
956        }
957    }
958
959    unsafe fn program_uniform_matrix_4x3_f32_slice(
960        &self,
961        program: Self::Program,
962        location: Option<&Self::UniformLocation>,
963        transpose: bool,
964        v: &[f32],
965    ) {
966        let gl = &self.raw;
967        if let Some(loc) = location {
968            gl.ProgramUniformMatrix4x3fv(
969                program.0.get(),
970                loc.0 as i32,
971                v.len() as i32 / 12,
972                transpose as u8,
973                v.as_ptr(),
974            );
975        }
976    }
977
978    unsafe fn program_uniform_matrix_4_f32_slice(
979        &self,
980        program: Self::Program,
981        location: Option<&Self::UniformLocation>,
982        transpose: bool,
983        v: &[f32],
984    ) {
985        let gl = &self.raw;
986        if let Some(loc) = location {
987            gl.ProgramUniformMatrix4fv(
988                program.0.get(),
989                loc.0 as i32,
990                v.len() as i32 / 16,
991                transpose as u8,
992                v.as_ptr(),
993            );
994        }
995    }
996
997    unsafe fn program_binary_retrievable_hint(&self, program: Self::Program, value: bool) {
998        let gl = &self.raw;
999        gl.ProgramParameteri(
1000            program.0.get(),
1001            crate::PROGRAM_BINARY_RETRIEVABLE_HINT,
1002            value as i32,
1003        )
1004    }
1005
1006    unsafe fn get_program_binary(&self, program: Self::Program) -> Option<ProgramBinary> {
1007        let gl = &self.raw;
1008
1009        // We don't need to error check here as if the call fails, length will be returned as 0.
1010        let mut len = 0;
1011        gl.GetProgramiv(program.0.get(), crate::PROGRAM_BINARY_LENGTH, &mut len);
1012
1013        let mut format = 0;
1014        let mut buffer = vec![0u8; len as usize];
1015
1016        gl.GetProgramBinary(
1017            program.0.get(),
1018            len,
1019            ptr::null_mut(),
1020            &mut format,
1021            buffer.as_mut_ptr() as *mut core::ffi::c_void,
1022        );
1023
1024        if gl.GetError() == crate::NO_ERROR {
1025            Some(ProgramBinary { buffer, format })
1026        } else {
1027            None
1028        }
1029    }
1030
1031    unsafe fn program_binary(&self, program: Self::Program, binary: &ProgramBinary) {
1032        let gl = &self.raw;
1033
1034        gl.ProgramBinary(
1035            program.0.get(),
1036            binary.format,
1037            binary.buffer.as_ptr() as *const core::ffi::c_void,
1038            binary.buffer.len() as native_gl::types::GLsizei,
1039        )
1040    }
1041
1042    unsafe fn get_active_uniforms(&self, program: Self::Program) -> u32 {
1043        let gl = &self.raw;
1044        let mut count = 0;
1045        gl.GetProgramiv(program.0.get(), ACTIVE_UNIFORMS, &mut count);
1046        count as u32
1047    }
1048
1049    unsafe fn get_active_uniform(
1050        &self,
1051        program: Self::Program,
1052        index: u32,
1053    ) -> Option<ActiveUniform> {
1054        let gl = &self.raw;
1055        let mut uniform_max_size = 0;
1056        gl.GetProgramiv(
1057            program.0.get(),
1058            ACTIVE_UNIFORM_MAX_LENGTH,
1059            &mut uniform_max_size,
1060        );
1061
1062        let mut name = String::with_capacity(uniform_max_size as usize);
1063        name.extend(std::iter::repeat('\0').take(uniform_max_size as usize));
1064        let mut length = 0;
1065        let mut size = 0;
1066        let mut utype = 0;
1067        gl.GetActiveUniform(
1068            program.0.get(),
1069            index,
1070            uniform_max_size,
1071            &mut length,
1072            &mut size,
1073            &mut utype,
1074            name.as_ptr() as *mut native_gl::GLchar,
1075        );
1076        name.truncate(length as usize);
1077
1078        Some(ActiveUniform { size, utype, name })
1079    }
1080
1081    unsafe fn use_program(&self, program: Option<Self::Program>) {
1082        let gl = &self.raw;
1083        gl.UseProgram(program.map(|p| p.0.get()).unwrap_or(0));
1084    }
1085
1086    unsafe fn create_buffer(&self) -> Result<Self::Buffer, String> {
1087        let gl = &self.raw;
1088        let mut buffer = 0;
1089        gl.GenBuffers(1, &mut buffer);
1090        Ok(NativeBuffer(non_zero_gl_name(buffer)))
1091    }
1092
1093    unsafe fn create_named_buffer(&self) -> Result<Self::Buffer, String> {
1094        let gl = &self.raw;
1095        let mut buffer = 0;
1096        gl.CreateBuffers(1, &mut buffer);
1097        Ok(NativeBuffer(non_zero_gl_name(buffer)))
1098    }
1099
1100    unsafe fn is_buffer(&self, buffer: Self::Buffer) -> bool {
1101        let gl = &self.raw;
1102        gl.IsBuffer(buffer.0.get()) != 0
1103    }
1104
1105    unsafe fn bind_buffer(&self, target: u32, buffer: Option<Self::Buffer>) {
1106        let gl = &self.raw;
1107        gl.BindBuffer(target, buffer.map(|b| b.0.get()).unwrap_or(0));
1108    }
1109
1110    unsafe fn bind_buffer_base(&self, target: u32, index: u32, buffer: Option<Self::Buffer>) {
1111        let gl = &self.raw;
1112        gl.BindBufferBase(target, index, buffer.map(|b| b.0.get()).unwrap_or(0));
1113    }
1114
1115    unsafe fn bind_buffer_range(
1116        &self,
1117        target: u32,
1118        index: u32,
1119        buffer: Option<Self::Buffer>,
1120        offset: i32,
1121        size: i32,
1122    ) {
1123        let gl = &self.raw;
1124        gl.BindBufferRange(
1125            target,
1126            index,
1127            buffer.map(|b| b.0.get()).unwrap_or(0),
1128            offset as isize,
1129            size as isize,
1130        );
1131    }
1132
1133    unsafe fn bind_vertex_buffer(
1134        &self,
1135        binding_index: u32,
1136        buffer: Option<Buffer>,
1137        offset: i32,
1138        stride: i32,
1139    ) {
1140        let gl = &self.raw;
1141        gl.BindVertexBuffer(
1142            binding_index,
1143            buffer.map(|b| b.0.get()).unwrap_or(0),
1144            offset as isize,
1145            stride,
1146        );
1147    }
1148
1149    unsafe fn bind_framebuffer(&self, target: u32, framebuffer: Option<Self::Framebuffer>) {
1150        let gl = &self.raw;
1151        gl.BindFramebuffer(target, framebuffer.map(|fb| fb.0.get()).unwrap_or(0));
1152    }
1153
1154    unsafe fn bind_renderbuffer(&self, target: u32, renderbuffer: Option<Self::Renderbuffer>) {
1155        let gl = &self.raw;
1156        gl.BindRenderbuffer(target, renderbuffer.map(|rb| rb.0.get()).unwrap_or(0));
1157    }
1158
1159    unsafe fn blit_framebuffer(
1160        &self,
1161        src_x0: i32,
1162        src_y0: i32,
1163        src_x1: i32,
1164        src_y1: i32,
1165        dst_x0: i32,
1166        dst_y0: i32,
1167        dst_x1: i32,
1168        dst_y1: i32,
1169        mask: u32,
1170        filter: u32,
1171    ) {
1172        let gl = &self.raw;
1173        gl.BlitFramebuffer(
1174            src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter,
1175        );
1176    }
1177
1178    unsafe fn blit_named_framebuffer(
1179        &self,
1180        read_buffer: Option<Self::Framebuffer>,
1181        draw_buffer: Option<Self::Framebuffer>,
1182        src_x0: i32,
1183        src_y0: i32,
1184        src_x1: i32,
1185        src_y1: i32,
1186        dst_x0: i32,
1187        dst_y0: i32,
1188        dst_x1: i32,
1189        dst_y1: i32,
1190        mask: u32,
1191        filter: u32,
1192    ) {
1193        let gl = &self.raw;
1194        gl.BlitNamedFramebuffer(
1195            read_buffer.map(|f| f.0.get()).unwrap_or(0),
1196            draw_buffer.map(|f| f.0.get()).unwrap_or(0),
1197            src_x0,
1198            src_y0,
1199            src_x1,
1200            src_y1,
1201            dst_x0,
1202            dst_y0,
1203            dst_x1,
1204            dst_y1,
1205            mask,
1206            filter,
1207        );
1208    }
1209
1210    unsafe fn create_vertex_array(&self) -> Result<Self::VertexArray, String> {
1211        let gl = &self.raw;
1212        let mut vertex_array = 0;
1213        gl.GenVertexArrays(1, &mut vertex_array);
1214        Ok(NativeVertexArray(non_zero_gl_name(vertex_array)))
1215    }
1216
1217    unsafe fn create_named_vertex_array(&self) -> Result<Self::VertexArray, String> {
1218        let gl = &self.raw;
1219        let mut vertex_array = 0;
1220        gl.CreateVertexArrays(1, &mut vertex_array);
1221        Ok(NativeVertexArray(non_zero_gl_name(vertex_array)))
1222    }
1223
1224    unsafe fn delete_vertex_array(&self, vertex_array: Self::VertexArray) {
1225        let gl = &self.raw;
1226        gl.DeleteVertexArrays(1, &vertex_array.0.get());
1227    }
1228
1229    unsafe fn bind_vertex_array(&self, vertex_array: Option<Self::VertexArray>) {
1230        let gl = &self.raw;
1231        gl.BindVertexArray(vertex_array.map(|va| va.0.get()).unwrap_or(0));
1232    }
1233
1234    unsafe fn clear_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
1235        let gl = &self.raw;
1236        gl.ClearColor(red, green, blue, alpha);
1237    }
1238
1239    unsafe fn supports_f64_precision() -> bool {
1240        // TODO: Handle OpenGL ES
1241        true
1242    }
1243
1244    unsafe fn clear_depth_f64(&self, depth: f64) {
1245        let gl = &self.raw;
1246        gl.ClearDepth(depth);
1247    }
1248
1249    unsafe fn clear_depth_f32(&self, depth: f32) {
1250        let gl = &self.raw;
1251        gl.ClearDepthf(depth);
1252    }
1253
1254    unsafe fn clear_stencil(&self, stencil: i32) {
1255        let gl = &self.raw;
1256        gl.ClearStencil(stencil);
1257    }
1258
1259    unsafe fn clear(&self, mask: u32) {
1260        let gl = &self.raw;
1261        gl.Clear(mask);
1262    }
1263
1264    unsafe fn patch_parameter_i32(&self, parameter: u32, value: i32) {
1265        let gl = &self.raw;
1266        gl.PatchParameteri(parameter, value);
1267    }
1268
1269    unsafe fn pixel_store_i32(&self, parameter: u32, value: i32) {
1270        let gl = &self.raw;
1271        gl.PixelStorei(parameter, value);
1272    }
1273
1274    unsafe fn pixel_store_bool(&self, parameter: u32, value: bool) {
1275        let gl = &self.raw;
1276        gl.PixelStorei(parameter, value as i32);
1277    }
1278
1279    unsafe fn bind_frag_data_location(
1280        &self,
1281        program: Self::Program,
1282        color_number: u32,
1283        name: &str,
1284    ) {
1285        let gl = &self.raw;
1286        gl.BindFragDataLocation(
1287            program.0.get(),
1288            color_number,
1289            name.as_ptr() as *const native_gl::GLchar,
1290        );
1291    }
1292
1293    unsafe fn buffer_data_size(&self, target: u32, size: i32, usage: u32) {
1294        let gl = &self.raw;
1295        gl.BufferData(target, size as isize, std::ptr::null(), usage);
1296    }
1297
1298    unsafe fn named_buffer_data_size(&self, buffer: Self::Buffer, size: i32, usage: u32) {
1299        let gl = &self.raw;
1300        gl.NamedBufferData(buffer.0.get(), size as isize, std::ptr::null(), usage);
1301    }
1302
1303    unsafe fn buffer_data_u8_slice(&self, target: u32, data: &[u8], usage: u32) {
1304        let gl = &self.raw;
1305        gl.BufferData(
1306            target,
1307            data.len() as isize,
1308            data.as_ptr() as *const std::ffi::c_void,
1309            usage,
1310        );
1311    }
1312
1313    unsafe fn named_buffer_data_u8_slice(&self, buffer: Self::Buffer, data: &[u8], usage: u32) {
1314        let gl = &self.raw;
1315        gl.NamedBufferData(
1316            buffer.0.get(),
1317            data.len() as isize,
1318            data.as_ptr() as *const std::ffi::c_void,
1319            usage,
1320        );
1321    }
1322
1323    unsafe fn buffer_sub_data_u8_slice(&self, target: u32, offset: i32, src_data: &[u8]) {
1324        let gl = &self.raw;
1325        gl.BufferSubData(
1326            target,
1327            offset as isize,
1328            src_data.len() as isize,
1329            src_data.as_ptr() as *const std::ffi::c_void,
1330        );
1331    }
1332
1333    unsafe fn named_buffer_sub_data_u8_slice(
1334        &self,
1335        buffer: Self::Buffer,
1336        offset: i32,
1337        src_data: &[u8],
1338    ) {
1339        let gl = &self.raw;
1340        gl.NamedBufferSubData(
1341            buffer.0.get(),
1342            offset as isize,
1343            src_data.len() as isize,
1344            src_data.as_ptr() as *const std::ffi::c_void,
1345        );
1346    }
1347
1348    unsafe fn get_buffer_sub_data(&self, target: u32, offset: i32, dst_data: &mut [u8]) {
1349        let gl = &self.raw;
1350        gl.GetBufferSubData(
1351            target,
1352            offset as isize,
1353            dst_data.len() as isize,
1354            dst_data.as_mut_ptr() as *mut std::ffi::c_void,
1355        );
1356    }
1357
1358    unsafe fn buffer_storage(&self, target: u32, size: i32, data: Option<&[u8]>, flags: u32) {
1359        let gl = &self.raw;
1360        let size = size as isize;
1361        let data = data.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void;
1362        if gl.BufferStorage_is_loaded() {
1363            gl.BufferStorage(target, size, data, flags);
1364        } else {
1365            gl.BufferStorageEXT(target, size, data, flags);
1366        }
1367    }
1368
1369    unsafe fn check_framebuffer_status(&self, target: u32) -> u32 {
1370        let gl = &self.raw;
1371        gl.CheckFramebufferStatus(target)
1372    }
1373
1374    unsafe fn check_named_framebuffer_status(
1375        &self,
1376        framebuffer: Option<Self::Framebuffer>,
1377        target: u32,
1378    ) -> u32 {
1379        let gl = &self.raw;
1380        gl.CheckNamedFramebufferStatus(framebuffer.map(|f| f.0.get()).unwrap_or(0), target)
1381    }
1382
1383    unsafe fn clear_buffer_i32_slice(&self, target: u32, draw_buffer: u32, values: &[i32]) {
1384        let gl = &self.raw;
1385        gl.ClearBufferiv(target, draw_buffer as i32, values.as_ptr());
1386    }
1387
1388    unsafe fn clear_buffer_u32_slice(&self, target: u32, draw_buffer: u32, values: &[u32]) {
1389        let gl = &self.raw;
1390        gl.ClearBufferuiv(target, draw_buffer as i32, values.as_ptr());
1391    }
1392
1393    unsafe fn clear_buffer_f32_slice(&self, target: u32, draw_buffer: u32, values: &[f32]) {
1394        let gl = &self.raw;
1395        gl.ClearBufferfv(target, draw_buffer as i32, values.as_ptr());
1396    }
1397
1398    unsafe fn clear_buffer_depth_stencil(
1399        &self,
1400        target: u32,
1401        draw_buffer: u32,
1402        depth: f32,
1403        stencil: i32,
1404    ) {
1405        let gl = &self.raw;
1406        gl.ClearBufferfi(target, draw_buffer as i32, depth, stencil);
1407    }
1408
1409    unsafe fn clear_named_framebuffer_i32_slice(
1410        &self,
1411        framebuffer: Option<Self::Framebuffer>,
1412        target: u32,
1413        draw_buffer: u32,
1414        values: &[i32],
1415    ) {
1416        let gl = &self.raw;
1417        gl.ClearNamedFramebufferiv(
1418            framebuffer.map(|f| f.0.get()).unwrap_or(0),
1419            target,
1420            draw_buffer as i32,
1421            values.as_ptr(),
1422        );
1423    }
1424
1425    unsafe fn clear_named_framebuffer_u32_slice(
1426        &self,
1427        framebuffer: Option<Self::Framebuffer>,
1428        target: u32,
1429        draw_buffer: u32,
1430        values: &[u32],
1431    ) {
1432        let gl = &self.raw;
1433        gl.ClearNamedFramebufferuiv(
1434            framebuffer.map(|f| f.0.get()).unwrap_or(0),
1435            target,
1436            draw_buffer as i32,
1437            values.as_ptr(),
1438        );
1439    }
1440
1441    unsafe fn clear_named_framebuffer_f32_slice(
1442        &self,
1443        framebuffer: Option<Self::Framebuffer>,
1444        target: u32,
1445        draw_buffer: u32,
1446        values: &[f32],
1447    ) {
1448        let gl = &self.raw;
1449        gl.ClearNamedFramebufferfv(
1450            framebuffer.map(|f| f.0.get()).unwrap_or(0),
1451            target,
1452            draw_buffer as i32,
1453            values.as_ptr(),
1454        );
1455    }
1456
1457    unsafe fn clear_named_framebuffer_depth_stencil(
1458        &self,
1459        framebuffer: Option<Self::Framebuffer>,
1460        target: u32,
1461        draw_buffer: u32,
1462        depth: f32,
1463        stencil: i32,
1464    ) {
1465        let gl = &self.raw;
1466        gl.ClearNamedFramebufferfi(
1467            framebuffer.map(|f| f.0.get()).unwrap_or(0),
1468            target,
1469            draw_buffer as i32,
1470            depth,
1471            stencil,
1472        );
1473    }
1474
1475    unsafe fn client_wait_sync(&self, fence: Self::Fence, flags: u32, timeout: i32) -> u32 {
1476        let gl = &self.raw;
1477        gl.ClientWaitSync(fence.0, flags, timeout as u64)
1478    }
1479
1480    unsafe fn wait_sync(&self, fence: Self::Fence, flags: u32, timeout: u64) {
1481        let gl = &self.raw;
1482        gl.WaitSync(fence.0, flags, timeout)
1483    }
1484
1485    unsafe fn copy_buffer_sub_data(
1486        &self,
1487        src_target: u32,
1488        dst_target: u32,
1489        src_offset: i32,
1490        dst_offset: i32,
1491        size: i32,
1492    ) {
1493        let gl = &self.raw;
1494        gl.CopyBufferSubData(
1495            src_target,
1496            dst_target,
1497            src_offset as isize,
1498            dst_offset as isize,
1499            size as isize,
1500        );
1501    }
1502
1503    unsafe fn copy_image_sub_data(
1504        &self,
1505        src_name: Self::Texture,
1506        src_target: u32,
1507        src_level: i32,
1508        src_x: i32,
1509        src_y: i32,
1510        src_z: i32,
1511        dst_name: Self::Texture,
1512        dst_target: u32,
1513        dst_level: i32,
1514        dst_x: i32,
1515        dst_y: i32,
1516        dst_z: i32,
1517        src_width: i32,
1518        src_height: i32,
1519        src_depth: i32,
1520    ) {
1521        let gl = &self.raw;
1522        gl.CopyImageSubData(
1523            src_name.0.get(),
1524            src_target,
1525            src_level,
1526            src_x,
1527            src_y,
1528            src_z,
1529            dst_name.0.get(),
1530            dst_target,
1531            dst_level,
1532            dst_x,
1533            dst_y,
1534            dst_z,
1535            src_width,
1536            src_height,
1537            src_depth,
1538        );
1539    }
1540
1541    unsafe fn copy_tex_image_2d(
1542        &self,
1543        target: u32,
1544        level: i32,
1545        internal_format: u32,
1546        x: i32,
1547        y: i32,
1548        width: i32,
1549        height: i32,
1550        border: i32,
1551    ) {
1552        let gl = &self.raw;
1553        gl.CopyTexImage2D(target, level, internal_format, x, y, width, height, border);
1554    }
1555
1556    unsafe fn copy_tex_sub_image_2d(
1557        &self,
1558        target: u32,
1559        level: i32,
1560        x_offset: i32,
1561        y_offset: i32,
1562        x: i32,
1563        y: i32,
1564        width: i32,
1565        height: i32,
1566    ) {
1567        let gl = &self.raw;
1568        gl.CopyTexSubImage2D(target, level, x_offset, y_offset, x, y, width, height);
1569    }
1570
1571    unsafe fn copy_tex_sub_image_3d(
1572        &self,
1573        target: u32,
1574        level: i32,
1575        x_offset: i32,
1576        y_offset: i32,
1577        z_offset: i32,
1578        x: i32,
1579        y: i32,
1580        width: i32,
1581        height: i32,
1582    ) {
1583        let gl = &self.raw;
1584        gl.CopyTexSubImage3D(
1585            target, level, x_offset, y_offset, z_offset, x, y, width, height,
1586        );
1587    }
1588
1589    unsafe fn delete_buffer(&self, buffer: Self::Buffer) {
1590        let gl = &self.raw;
1591        gl.DeleteBuffers(1, &buffer.0.get());
1592    }
1593
1594    unsafe fn delete_framebuffer(&self, framebuffer: Self::Framebuffer) {
1595        let gl = &self.raw;
1596        gl.DeleteFramebuffers(1, &framebuffer.0.get());
1597    }
1598
1599    unsafe fn delete_query(&self, query: Self::Query) {
1600        let gl = &self.raw;
1601        gl.DeleteQueries(1, &query.0.get());
1602    }
1603
1604    unsafe fn delete_renderbuffer(&self, renderbuffer: Self::Renderbuffer) {
1605        let gl = &self.raw;
1606        gl.DeleteRenderbuffers(1, &renderbuffer.0.get());
1607    }
1608
1609    unsafe fn delete_sampler(&self, sampler: Self::Sampler) {
1610        let gl = &self.raw;
1611        gl.DeleteSamplers(1, &sampler.0.get());
1612    }
1613
1614    unsafe fn delete_sync(&self, fence: Self::Fence) {
1615        let gl = &self.raw;
1616        gl.DeleteSync(fence.0);
1617    }
1618
1619    unsafe fn delete_texture(&self, texture: Self::Texture) {
1620        let gl = &self.raw;
1621        gl.DeleteTextures(1, &texture.0.get());
1622    }
1623
1624    unsafe fn disable(&self, parameter: u32) {
1625        let gl = &self.raw;
1626        gl.Disable(parameter);
1627    }
1628
1629    unsafe fn disable_draw_buffer(&self, parameter: u32, draw_buffer: u32) {
1630        let gl = &self.raw;
1631        gl.Disablei(parameter, draw_buffer);
1632    }
1633
1634    unsafe fn disable_vertex_attrib_array(&self, index: u32) {
1635        let gl = &self.raw;
1636        gl.DisableVertexAttribArray(index);
1637    }
1638
1639    unsafe fn dispatch_compute(&self, groups_x: u32, groups_y: u32, groups_z: u32) {
1640        let gl = &self.raw;
1641        gl.DispatchCompute(groups_x, groups_y, groups_z);
1642    }
1643
1644    unsafe fn dispatch_compute_indirect(&self, offset: i32) {
1645        let gl = &self.raw;
1646        gl.DispatchComputeIndirect(offset as isize);
1647    }
1648
1649    unsafe fn draw_arrays(&self, mode: u32, first: i32, count: i32) {
1650        let gl = &self.raw;
1651        gl.DrawArrays(mode as u32, first, count);
1652    }
1653
1654    unsafe fn draw_arrays_instanced(&self, mode: u32, first: i32, count: i32, instance_count: i32) {
1655        let gl = &self.raw;
1656        gl.DrawArraysInstanced(mode as u32, first, count, instance_count);
1657    }
1658
1659    unsafe fn draw_arrays_instanced_base_instance(
1660        &self,
1661        mode: u32,
1662        first: i32,
1663        count: i32,
1664        instance_count: i32,
1665        base_instance: u32,
1666    ) {
1667        let gl = &self.raw;
1668        gl.DrawArraysInstancedBaseInstance(
1669            mode as u32,
1670            first,
1671            count,
1672            instance_count,
1673            base_instance,
1674        );
1675    }
1676
1677    unsafe fn draw_arrays_indirect_offset(&self, mode: u32, offset: i32) {
1678        let gl = &self.raw;
1679        gl.DrawArraysIndirect(mode, offset as *const std::ffi::c_void);
1680    }
1681
1682    unsafe fn draw_buffer(&self, draw_buffer: u32) {
1683        let gl = &self.raw;
1684        gl.DrawBuffer(draw_buffer);
1685    }
1686
1687    unsafe fn named_framebuffer_draw_buffer(
1688        &self,
1689        framebuffer: Option<Self::Framebuffer>,
1690        draw_buffer: u32,
1691    ) {
1692        let gl = &self.raw;
1693        gl.NamedFramebufferDrawBuffer(framebuffer.map(|f| f.0.get()).unwrap_or(0), draw_buffer);
1694    }
1695
1696    unsafe fn draw_buffers(&self, buffers: &[u32]) {
1697        let gl = &self.raw;
1698        gl.DrawBuffers(buffers.len() as i32, buffers.as_ptr());
1699    }
1700
1701    unsafe fn named_framebuffer_draw_buffers(
1702        &self,
1703        framebuffer: Option<Self::Framebuffer>,
1704        buffers: &[u32],
1705    ) {
1706        let gl = &self.raw;
1707        gl.NamedFramebufferDrawBuffers(
1708            framebuffer.map(|f| f.0.get()).unwrap_or(0),
1709            buffers.len() as i32,
1710            buffers.as_ptr(),
1711        );
1712    }
1713
1714    unsafe fn draw_elements(&self, mode: u32, count: i32, element_type: u32, offset: i32) {
1715        let gl = &self.raw;
1716        gl.DrawElements(
1717            mode as u32,
1718            count,
1719            element_type as u32,
1720            offset as *const std::ffi::c_void,
1721        );
1722    }
1723
1724    unsafe fn draw_elements_base_vertex(
1725        &self,
1726        mode: u32,
1727        count: i32,
1728        element_type: u32,
1729        offset: i32,
1730        base_vertex: i32,
1731    ) {
1732        let gl = &self.raw;
1733        gl.DrawElementsBaseVertex(
1734            mode as u32,
1735            count,
1736            element_type as u32,
1737            offset as *const std::ffi::c_void,
1738            base_vertex,
1739        );
1740    }
1741
1742    unsafe fn draw_elements_instanced(
1743        &self,
1744        mode: u32,
1745        count: i32,
1746        element_type: u32,
1747        offset: i32,
1748        instance_count: i32,
1749    ) {
1750        let gl = &self.raw;
1751        gl.DrawElementsInstanced(
1752            mode as u32,
1753            count,
1754            element_type as u32,
1755            offset as *const std::ffi::c_void,
1756            instance_count,
1757        );
1758    }
1759
1760    unsafe fn draw_elements_instanced_base_vertex(
1761        &self,
1762        mode: u32,
1763        count: i32,
1764        element_type: u32,
1765        offset: i32,
1766        instance_count: i32,
1767        base_vertex: i32,
1768    ) {
1769        let gl = &self.raw;
1770        gl.DrawElementsInstancedBaseVertex(
1771            mode as u32,
1772            count,
1773            element_type as u32,
1774            offset as *const std::ffi::c_void,
1775            instance_count,
1776            base_vertex,
1777        );
1778    }
1779
1780    unsafe fn draw_elements_instanced_base_vertex_base_instance(
1781        &self,
1782        mode: u32,
1783        count: i32,
1784        element_type: u32,
1785        offset: i32,
1786        instance_count: i32,
1787        base_vertex: i32,
1788        base_instance: u32,
1789    ) {
1790        let gl = &self.raw;
1791        gl.DrawElementsInstancedBaseVertexBaseInstance(
1792            mode as u32,
1793            count,
1794            element_type as u32,
1795            offset as *const std::ffi::c_void,
1796            instance_count,
1797            base_vertex,
1798            base_instance,
1799        );
1800    }
1801
1802    unsafe fn draw_elements_indirect_offset(&self, mode: u32, element_type: u32, offset: i32) {
1803        let gl = &self.raw;
1804        gl.DrawElementsIndirect(mode, element_type, offset as *const std::ffi::c_void);
1805    }
1806
1807    unsafe fn enable(&self, parameter: u32) {
1808        let gl = &self.raw;
1809        gl.Enable(parameter);
1810    }
1811
1812    unsafe fn is_enabled(&self, parameter: u32) -> bool {
1813        let gl = &self.raw;
1814        gl.IsEnabled(parameter) != 0
1815    }
1816
1817    unsafe fn enable_draw_buffer(&self, parameter: u32, draw_buffer: u32) {
1818        let gl = &self.raw;
1819        gl.Enablei(parameter, draw_buffer);
1820    }
1821
1822    unsafe fn enable_vertex_array_attrib(&self, vao: Self::VertexArray, index: u32) {
1823        let gl = &self.raw;
1824        gl.EnableVertexArrayAttrib(vao.0.get(), index);
1825    }
1826
1827    unsafe fn enable_vertex_attrib_array(&self, index: u32) {
1828        let gl = &self.raw;
1829        gl.EnableVertexAttribArray(index);
1830    }
1831
1832    unsafe fn flush(&self) {
1833        let gl = &self.raw;
1834        gl.Flush();
1835    }
1836
1837    unsafe fn framebuffer_renderbuffer(
1838        &self,
1839        target: u32,
1840        attachment: u32,
1841        renderbuffer_target: u32,
1842        renderbuffer: Option<Self::Renderbuffer>,
1843    ) {
1844        let gl = &self.raw;
1845        gl.FramebufferRenderbuffer(
1846            target,
1847            attachment,
1848            renderbuffer_target,
1849            renderbuffer.map(|rb| rb.0.get()).unwrap_or(0),
1850        );
1851    }
1852
1853    unsafe fn framebuffer_texture(
1854        &self,
1855        target: u32,
1856        attachment: u32,
1857        texture: Option<Self::Texture>,
1858        level: i32,
1859    ) {
1860        let gl = &self.raw;
1861        gl.FramebufferTexture(
1862            target,
1863            attachment,
1864            texture.map(|t| t.0.get()).unwrap_or(0),
1865            level,
1866        );
1867    }
1868
1869    unsafe fn framebuffer_texture_2d(
1870        &self,
1871        target: u32,
1872        attachment: u32,
1873        texture_target: u32,
1874        texture: Option<Self::Texture>,
1875        level: i32,
1876    ) {
1877        let gl = &self.raw;
1878        gl.FramebufferTexture2D(
1879            target,
1880            attachment,
1881            texture_target,
1882            texture.map(|t| t.0.get()).unwrap_or(0),
1883            level,
1884        );
1885    }
1886
1887    unsafe fn framebuffer_texture_3d(
1888        &self,
1889        target: u32,
1890        attachment: u32,
1891        texture_target: u32,
1892        texture: Option<Self::Texture>,
1893        level: i32,
1894        layer: i32,
1895    ) {
1896        let gl = &self.raw;
1897        gl.FramebufferTexture3D(
1898            target,
1899            attachment,
1900            texture_target,
1901            texture.map(|t| t.0.get()).unwrap_or(0),
1902            level,
1903            layer,
1904        );
1905    }
1906
1907    unsafe fn framebuffer_texture_layer(
1908        &self,
1909        target: u32,
1910        attachment: u32,
1911        texture: Option<Self::Texture>,
1912        level: i32,
1913        layer: i32,
1914    ) {
1915        let gl = &self.raw;
1916        gl.FramebufferTextureLayer(
1917            target,
1918            attachment,
1919            texture.map(|t| t.0.get()).unwrap_or(0),
1920            level,
1921            layer,
1922        );
1923    }
1924
1925    unsafe fn named_framebuffer_renderbuffer(
1926        &self,
1927        framebuffer: Option<Self::Framebuffer>,
1928        attachment: u32,
1929        renderbuffer_target: u32,
1930        renderbuffer: Option<Self::Renderbuffer>,
1931    ) {
1932        let gl = &self.raw;
1933        gl.NamedFramebufferRenderbuffer(
1934            framebuffer.map(|f| f.0.get()).unwrap_or(0),
1935            attachment,
1936            renderbuffer_target,
1937            renderbuffer.map(|rb| rb.0.get()).unwrap_or(0),
1938        );
1939    }
1940
1941    unsafe fn named_framebuffer_texture(
1942        &self,
1943        framebuffer: Option<Self::Framebuffer>,
1944        attachment: u32,
1945        texture: Option<Self::Texture>,
1946        level: i32,
1947    ) {
1948        let gl = &self.raw;
1949        gl.NamedFramebufferTexture(
1950            framebuffer.map(|f| f.0.get()).unwrap_or(0),
1951            attachment,
1952            texture.map(|t| t.0.get()).unwrap_or(0),
1953            level,
1954        );
1955    }
1956
1957    unsafe fn named_framebuffer_texture_layer(
1958        &self,
1959        framebuffer: Option<Self::Framebuffer>,
1960        attachment: u32,
1961        texture: Option<Self::Texture>,
1962        level: i32,
1963        layer: i32,
1964    ) {
1965        let gl = &self.raw;
1966        gl.NamedFramebufferTextureLayer(
1967            framebuffer.map(|f| f.0.get()).unwrap_or(0),
1968            attachment,
1969            texture.map(|t| t.0.get()).unwrap_or(0),
1970            level,
1971            layer,
1972        );
1973    }
1974
1975    unsafe fn front_face(&self, value: u32) {
1976        let gl = &self.raw;
1977        gl.FrontFace(value as u32);
1978    }
1979
1980    unsafe fn get_error(&self) -> u32 {
1981        let gl = &self.raw;
1982        gl.GetError()
1983    }
1984
1985    unsafe fn get_tex_parameter_i32(&self, target: u32, parameter: u32) -> i32 {
1986        let gl = &self.raw;
1987        let mut value = 0;
1988        gl.GetTexParameteriv(target, parameter, &mut value);
1989        value
1990    }
1991
1992    unsafe fn get_buffer_parameter_i32(&self, target: u32, parameter: u32) -> i32 {
1993        let gl = &self.raw;
1994        let mut value = 0;
1995        gl.GetBufferParameteriv(target, parameter, &mut value);
1996        value
1997    }
1998
1999    unsafe fn get_parameter_bool(&self, parameter: u32) -> bool {
2000        let gl = &self.raw;
2001        let mut value = 0;
2002        gl.GetBooleanv(parameter, &mut value);
2003        value != FALSE
2004    }
2005
2006    unsafe fn get_parameter_bool_array<const N: usize>(&self, parameter: u32) -> [bool; N] {
2007        let gl = &self.raw;
2008        let mut value = [0; N];
2009        gl.GetBooleanv(parameter, &mut value[0]);
2010        value.map(|v| v != FALSE)
2011    }
2012
2013    unsafe fn get_parameter_i32(&self, parameter: u32) -> i32 {
2014        let gl = &self.raw;
2015        let mut value = 0;
2016        gl.GetIntegerv(parameter, &mut value);
2017        value
2018    }
2019
2020    unsafe fn get_parameter_i32_slice(&self, parameter: u32, out: &mut [i32]) {
2021        let gl = &self.raw;
2022        gl.GetIntegerv(parameter, &mut out[0]);
2023    }
2024
2025    unsafe fn get_parameter_f32(&self, parameter: u32) -> f32 {
2026        let gl = &self.raw;
2027        let mut value: f32 = 0.0;
2028        gl.GetFloatv(parameter, &mut value);
2029        value
2030    }
2031
2032    unsafe fn get_parameter_f32_slice(&self, parameter: u32, out: &mut [f32]) {
2033        let gl = &self.raw;
2034        gl.GetFloatv(parameter, &mut out[0]);
2035    }
2036
2037    unsafe fn get_parameter_indexed_i32(&self, parameter: u32, index: u32) -> i32 {
2038        let gl = &self.raw;
2039        let mut value = 0;
2040        gl.GetIntegeri_v(parameter, index, &mut value);
2041        value
2042    }
2043
2044    unsafe fn get_parameter_indexed_string(&self, parameter: u32, index: u32) -> String {
2045        let gl = &self.raw;
2046        let raw_ptr = gl.GetStringi(parameter, index);
2047        std::ffi::CStr::from_ptr(raw_ptr as *const native_gl::GLchar)
2048            .to_str()
2049            .unwrap()
2050            .to_owned()
2051    }
2052
2053    unsafe fn get_parameter_string(&self, parameter: u32) -> String {
2054        let gl = &self.raw;
2055        let raw_ptr = gl.GetString(parameter);
2056        if raw_ptr.is_null() {
2057            panic!(
2058                "Get parameter string 0x{:X} failed. Maybe your GL context version is too outdated.",
2059                parameter
2060            )
2061        }
2062        std::ffi::CStr::from_ptr(raw_ptr as *const native_gl::GLchar)
2063            .to_str()
2064            .unwrap()
2065            .to_owned()
2066    }
2067
2068    unsafe fn get_parameter_buffer(&self, parameter: u32) -> Option<Self::Buffer> {
2069        self.get_parameter_gl_name(parameter).map(NativeBuffer)
2070    }
2071
2072    unsafe fn get_parameter_framebuffer(&self, parameter: u32) -> Option<Self::Framebuffer> {
2073        self.get_parameter_gl_name(parameter).map(NativeFramebuffer)
2074    }
2075
2076    unsafe fn get_parameter_program(&self, parameter: u32) -> Option<Self::Program> {
2077        self.get_parameter_gl_name(parameter).map(NativeProgram)
2078    }
2079
2080    unsafe fn get_parameter_renderbuffer(&self, parameter: u32) -> Option<Self::Renderbuffer> {
2081        self.get_parameter_gl_name(parameter)
2082            .map(NativeRenderbuffer)
2083    }
2084
2085    unsafe fn get_parameter_sampler(&self, parameter: u32) -> Option<Self::Sampler> {
2086        self.get_parameter_gl_name(parameter).map(NativeSampler)
2087    }
2088
2089    unsafe fn get_parameter_texture(&self, parameter: u32) -> Option<Self::Texture> {
2090        self.get_parameter_gl_name(parameter).map(NativeTexture)
2091    }
2092
2093    unsafe fn get_parameter_transform_feedback(
2094        &self,
2095        parameter: u32,
2096    ) -> Option<Self::TransformFeedback> {
2097        self.get_parameter_gl_name(parameter)
2098            .map(NativeTransformFeedback)
2099    }
2100
2101    unsafe fn get_parameter_vertex_array(&self, parameter: u32) -> Option<Self::VertexArray> {
2102        self.get_parameter_gl_name(parameter).map(NativeVertexArray)
2103    }
2104
2105    unsafe fn get_framebuffer_parameter_i32(&self, target: u32, parameter: u32) -> i32 {
2106        let gl = &self.raw;
2107        let mut value = 0;
2108        gl.GetFramebufferParameteriv(target, parameter, &mut value);
2109        value
2110    }
2111
2112    unsafe fn get_named_framebuffer_parameter_i32(
2113        &self,
2114        framebuffer: Option<Self::Framebuffer>,
2115        parameter: u32,
2116    ) -> i32 {
2117        let gl = &self.raw;
2118        let mut value = 0;
2119        gl.GetNamedFramebufferParameteriv(
2120            framebuffer.map(|f| f.0.get()).unwrap_or(0),
2121            parameter,
2122            &mut value,
2123        );
2124        value
2125    }
2126
2127    unsafe fn get_framebuffer_attachment_parameter_i32(
2128        &self,
2129        target: u32,
2130        attachment: u32,
2131        parameter: u32,
2132    ) -> i32 {
2133        let gl = &self.raw;
2134        let mut value = 0;
2135        gl.GetFramebufferAttachmentParameteriv(target, attachment, parameter, &mut value);
2136        value
2137    }
2138
2139    unsafe fn get_named_framebuffer_attachment_parameter_i32(
2140        &self,
2141        framebuffer: Option<Self::Framebuffer>,
2142        attachment: u32,
2143        parameter: u32,
2144    ) -> i32 {
2145        let gl = &self.raw;
2146        let mut value = 0;
2147        gl.GetNamedFramebufferAttachmentParameteriv(
2148            framebuffer.map(|f| f.0.get()).unwrap_or(0),
2149            attachment,
2150            parameter,
2151            &mut value,
2152        );
2153        value
2154    }
2155
2156    unsafe fn get_uniform_location(
2157        &self,
2158        program: Self::Program,
2159        name: &str,
2160    ) -> Option<Self::UniformLocation> {
2161        let gl = &self.raw;
2162        let name = CString::new(name).unwrap();
2163        let uniform_location =
2164            gl.GetUniformLocation(program.0.get(), name.as_ptr() as *const native_gl::GLchar);
2165        if uniform_location < 0 {
2166            None
2167        } else {
2168            Some(NativeUniformLocation(uniform_location as u32))
2169        }
2170    }
2171
2172    unsafe fn get_attrib_location(&self, program: Self::Program, name: &str) -> Option<u32> {
2173        let gl = &self.raw;
2174        let name = CString::new(name).unwrap();
2175        let attrib_location =
2176            gl.GetAttribLocation(program.0.get(), name.as_ptr() as *const native_gl::GLchar);
2177        if attrib_location < 0 {
2178            None
2179        } else {
2180            Some(attrib_location as u32)
2181        }
2182    }
2183
2184    unsafe fn bind_attrib_location(&self, program: Self::Program, index: u32, name: &str) {
2185        let gl = &self.raw;
2186        let name = CString::new(name).unwrap();
2187        gl.BindAttribLocation(
2188            program.0.get(),
2189            index,
2190            name.as_ptr() as *const native_gl::GLchar,
2191        );
2192    }
2193
2194    unsafe fn get_active_attributes(&self, program: Self::Program) -> u32 {
2195        let gl = &self.raw;
2196        let mut count = 0;
2197        gl.GetProgramiv(program.0.get(), ACTIVE_ATTRIBUTES, &mut count);
2198        count as u32
2199    }
2200
2201    unsafe fn get_active_attribute(
2202        &self,
2203        program: Self::Program,
2204        index: u32,
2205    ) -> Option<ActiveAttribute> {
2206        let gl = &self.raw;
2207        let mut attribute_max_size = 0;
2208        gl.GetProgramiv(
2209            program.0.get(),
2210            ACTIVE_ATTRIBUTE_MAX_LENGTH,
2211            &mut attribute_max_size,
2212        );
2213        let mut name = String::with_capacity(attribute_max_size as usize);
2214        name.extend(std::iter::repeat('\0').take(attribute_max_size as usize));
2215        let mut length = 0;
2216        let mut size = 0;
2217        let mut atype = 0;
2218        gl.GetActiveAttrib(
2219            program.0.get(),
2220            index,
2221            attribute_max_size,
2222            &mut length,
2223            &mut size,
2224            &mut atype,
2225            name.as_ptr() as *mut native_gl::GLchar,
2226        );
2227
2228        name.truncate(length as usize);
2229
2230        Some(ActiveAttribute { name, size, atype })
2231    }
2232
2233    unsafe fn get_sync_status(&self, fence: Self::Fence) -> u32 {
2234        let gl = &self.raw;
2235        let mut len = 0;
2236        let mut values = [UNSIGNALED as i32];
2237        gl.GetSynciv(
2238            fence.0,
2239            SYNC_STATUS,
2240            values.len() as i32,
2241            &mut len,
2242            values.as_mut_ptr(),
2243        );
2244        values[0] as u32
2245    }
2246
2247    unsafe fn is_sync(&self, fence: Self::Fence) -> bool {
2248        let gl = &self.raw;
2249        1 == gl.IsSync(fence.0)
2250    }
2251
2252    unsafe fn renderbuffer_storage(
2253        &self,
2254        target: u32,
2255        internal_format: u32,
2256        width: i32,
2257        height: i32,
2258    ) {
2259        let gl = &self.raw;
2260        gl.RenderbufferStorage(target, internal_format, width, height);
2261    }
2262
2263    unsafe fn renderbuffer_storage_multisample(
2264        &self,
2265        target: u32,
2266        samples: i32,
2267        internal_format: u32,
2268        width: i32,
2269        height: i32,
2270    ) {
2271        let gl = &self.raw;
2272        gl.RenderbufferStorageMultisample(target, samples, internal_format, width, height);
2273    }
2274
2275    unsafe fn sampler_parameter_f32(&self, sampler: Self::Sampler, name: u32, value: f32) {
2276        let gl = &self.raw;
2277        gl.SamplerParameterf(sampler.0.get(), name, value);
2278    }
2279
2280    unsafe fn sampler_parameter_f32_slice(&self, sampler: Self::Sampler, name: u32, value: &[f32]) {
2281        let gl = &self.raw;
2282        gl.SamplerParameterfv(sampler.0.get(), name, value.as_ptr());
2283    }
2284
2285    unsafe fn sampler_parameter_i32(&self, sampler: Self::Sampler, name: u32, value: i32) {
2286        let gl = &self.raw;
2287        gl.SamplerParameteri(sampler.0.get(), name, value);
2288    }
2289
2290    unsafe fn generate_mipmap(&self, target: u32) {
2291        let gl = &self.raw;
2292        gl.GenerateMipmap(target);
2293    }
2294
2295    unsafe fn generate_texture_mipmap(&self, texture: Self::Texture) {
2296        let gl = &self.raw;
2297        gl.GenerateTextureMipmap(texture.0.get());
2298    }
2299
2300    unsafe fn tex_image_1d(
2301        &self,
2302        target: u32,
2303        level: i32,
2304        internal_format: i32,
2305        width: i32,
2306        border: i32,
2307        format: u32,
2308        ty: u32,
2309        pixels: Option<&[u8]>,
2310    ) {
2311        let gl = &self.raw;
2312        gl.TexImage1D(
2313            target,
2314            level,
2315            internal_format,
2316            width,
2317            border,
2318            format,
2319            ty,
2320            pixels.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void,
2321        );
2322    }
2323
2324    unsafe fn compressed_tex_image_1d(
2325        &self,
2326        target: u32,
2327        level: i32,
2328        internal_format: i32,
2329        width: i32,
2330        border: i32,
2331        image_size: i32,
2332        pixels: &[u8],
2333    ) {
2334        let gl = &self.raw;
2335        gl.CompressedTexImage1D(
2336            target,
2337            level,
2338            internal_format as u32,
2339            width,
2340            border,
2341            image_size,
2342            pixels.as_ptr() as *const std::ffi::c_void,
2343        );
2344    }
2345
2346    unsafe fn tex_image_2d(
2347        &self,
2348        target: u32,
2349        level: i32,
2350        internal_format: i32,
2351        width: i32,
2352        height: i32,
2353        border: i32,
2354        format: u32,
2355        ty: u32,
2356        pixels: Option<&[u8]>,
2357    ) {
2358        let gl = &self.raw;
2359        gl.TexImage2D(
2360            target,
2361            level,
2362            internal_format,
2363            width,
2364            height,
2365            border,
2366            format,
2367            ty,
2368            pixels.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void,
2369        );
2370    }
2371
2372    unsafe fn tex_image_2d_multisample(
2373        &self,
2374        target: u32,
2375        samples: i32,
2376        internal_format: i32,
2377        width: i32,
2378        height: i32,
2379        fixed_sample_locations: bool,
2380    ) {
2381        let gl = &self.raw;
2382        gl.TexImage2DMultisample(
2383            target,
2384            samples,
2385            internal_format as u32,
2386            width,
2387            height,
2388            if fixed_sample_locations { 1 } else { 0 },
2389        );
2390    }
2391
2392    unsafe fn compressed_tex_image_2d(
2393        &self,
2394        target: u32,
2395        level: i32,
2396        internal_format: i32,
2397        width: i32,
2398        height: i32,
2399        border: i32,
2400        image_size: i32,
2401        pixels: &[u8],
2402    ) {
2403        let gl = &self.raw;
2404        gl.CompressedTexImage2D(
2405            target,
2406            level,
2407            internal_format as u32,
2408            width,
2409            height,
2410            border,
2411            image_size,
2412            pixels.as_ptr() as *const std::ffi::c_void,
2413        );
2414    }
2415
2416    unsafe fn tex_image_3d(
2417        &self,
2418        target: u32,
2419        level: i32,
2420        internal_format: i32,
2421        width: i32,
2422        height: i32,
2423        depth: i32,
2424        border: i32,
2425        format: u32,
2426        ty: u32,
2427        pixels: Option<&[u8]>,
2428    ) {
2429        let gl = &self.raw;
2430        gl.TexImage3D(
2431            target,
2432            level,
2433            internal_format,
2434            width,
2435            height,
2436            depth,
2437            border,
2438            format,
2439            ty,
2440            pixels.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void,
2441        );
2442    }
2443
2444    unsafe fn compressed_tex_image_3d(
2445        &self,
2446        target: u32,
2447        level: i32,
2448        internal_format: i32,
2449        width: i32,
2450        height: i32,
2451        depth: i32,
2452        border: i32,
2453        image_size: i32,
2454        pixels: &[u8],
2455    ) {
2456        let gl = &self.raw;
2457        gl.CompressedTexImage3D(
2458            target,
2459            level,
2460            internal_format as u32,
2461            width,
2462            height,
2463            depth,
2464            border,
2465            image_size,
2466            pixels.as_ptr() as *const std::ffi::c_void,
2467        );
2468    }
2469
2470    unsafe fn tex_storage_1d(&self, target: u32, levels: i32, internal_format: u32, width: i32) {
2471        let gl = &self.raw;
2472        gl.TexStorage1D(target, levels, internal_format, width);
2473    }
2474
2475    unsafe fn tex_storage_2d(
2476        &self,
2477        target: u32,
2478        levels: i32,
2479        internal_format: u32,
2480        width: i32,
2481        height: i32,
2482    ) {
2483        let gl = &self.raw;
2484        gl.TexStorage2D(target, levels, internal_format, width, height);
2485    }
2486
2487    unsafe fn texture_storage_2d(
2488        &self,
2489        texture: Self::Texture,
2490        levels: i32,
2491        internal_format: u32,
2492        width: i32,
2493        height: i32,
2494    ) {
2495        let gl = &self.raw;
2496        gl.TextureStorage2D(texture.0.get(), levels, internal_format, width, height);
2497    }
2498
2499    unsafe fn tex_storage_2d_multisample(
2500        &self,
2501        target: u32,
2502        samples: i32,
2503        internal_format: u32,
2504        width: i32,
2505        height: i32,
2506        fixed_sample_locations: bool,
2507    ) {
2508        let gl = &self.raw;
2509        gl.TexStorage2DMultisample(
2510            target,
2511            samples,
2512            internal_format,
2513            width,
2514            height,
2515            if fixed_sample_locations { 1 } else { 0 },
2516        );
2517    }
2518
2519    unsafe fn tex_storage_3d(
2520        &self,
2521        target: u32,
2522        levels: i32,
2523        internal_format: u32,
2524        width: i32,
2525        height: i32,
2526        depth: i32,
2527    ) {
2528        let gl = &self.raw;
2529        gl.TexStorage3D(target, levels, internal_format, width, height, depth);
2530    }
2531
2532    unsafe fn texture_storage_3d(
2533        &self,
2534        texture: Self::Texture,
2535        levels: i32,
2536        internal_format: u32,
2537        width: i32,
2538        height: i32,
2539        depth: i32,
2540    ) {
2541        let gl = &self.raw;
2542        gl.TextureStorage3D(
2543            texture.0.get(),
2544            levels,
2545            internal_format,
2546            width,
2547            height,
2548            depth,
2549        );
2550    }
2551
2552    unsafe fn get_uniform_i32(
2553        &self,
2554        program: Self::Program,
2555        location: &Self::UniformLocation,
2556        v: &mut [i32],
2557    ) {
2558        let gl = &self.raw;
2559        gl.GetUniformiv(
2560            program.0.get() as u32,
2561            location.0 as i32,
2562            v.as_mut_ptr() as *mut i32,
2563        )
2564    }
2565
2566    unsafe fn get_uniform_f32(
2567        &self,
2568        program: Self::Program,
2569        location: &Self::UniformLocation,
2570        v: &mut [f32],
2571    ) {
2572        let gl = &self.raw;
2573        gl.GetUniformfv(
2574            program.0.get() as u32,
2575            location.0 as i32,
2576            v.as_mut_ptr() as *mut f32,
2577        )
2578    }
2579
2580    unsafe fn uniform_1_i32(&self, location: Option<&Self::UniformLocation>, x: i32) {
2581        let gl = &self.raw;
2582        if let Some(loc) = location {
2583            gl.Uniform1i(loc.0 as i32, x);
2584        }
2585    }
2586
2587    unsafe fn uniform_2_i32(&self, location: Option<&Self::UniformLocation>, x: i32, y: i32) {
2588        let gl = &self.raw;
2589        if let Some(loc) = location {
2590            gl.Uniform2i(loc.0 as i32, x, y);
2591        }
2592    }
2593
2594    unsafe fn uniform_3_i32(
2595        &self,
2596        location: Option<&Self::UniformLocation>,
2597        x: i32,
2598        y: i32,
2599        z: i32,
2600    ) {
2601        let gl = &self.raw;
2602        if let Some(loc) = location {
2603            gl.Uniform3i(loc.0 as i32, x, y, z);
2604        }
2605    }
2606
2607    unsafe fn uniform_4_i32(
2608        &self,
2609        location: Option<&Self::UniformLocation>,
2610        x: i32,
2611        y: i32,
2612        z: i32,
2613        w: i32,
2614    ) {
2615        let gl = &self.raw;
2616        if let Some(loc) = location {
2617            gl.Uniform4i(loc.0 as i32, x, y, z, w);
2618        }
2619    }
2620
2621    unsafe fn uniform_1_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
2622        let gl = &self.raw;
2623        if let Some(loc) = location {
2624            gl.Uniform1iv(loc.0 as i32, v.len() as i32, v.as_ptr());
2625        }
2626    }
2627
2628    unsafe fn uniform_2_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
2629        let gl = &self.raw;
2630        if let Some(loc) = location {
2631            gl.Uniform2iv(loc.0 as i32, v.len() as i32 / 2, v.as_ptr());
2632        }
2633    }
2634
2635    unsafe fn uniform_3_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
2636        let gl = &self.raw;
2637        if let Some(loc) = location {
2638            gl.Uniform3iv(loc.0 as i32, v.len() as i32 / 3, v.as_ptr());
2639        }
2640    }
2641
2642    unsafe fn uniform_4_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
2643        let gl = &self.raw;
2644        if let Some(loc) = location {
2645            gl.Uniform4iv(loc.0 as i32, v.len() as i32 / 4, v.as_ptr());
2646        }
2647    }
2648
2649    unsafe fn uniform_1_u32(&self, location: Option<&Self::UniformLocation>, x: u32) {
2650        let gl = &self.raw;
2651        if let Some(loc) = location {
2652            gl.Uniform1ui(loc.0 as i32, x);
2653        }
2654    }
2655
2656    unsafe fn uniform_2_u32(&self, location: Option<&Self::UniformLocation>, x: u32, y: u32) {
2657        let gl = &self.raw;
2658        if let Some(loc) = location {
2659            gl.Uniform2ui(loc.0 as i32, x, y);
2660        }
2661    }
2662
2663    unsafe fn uniform_3_u32(
2664        &self,
2665        location: Option<&Self::UniformLocation>,
2666        x: u32,
2667        y: u32,
2668        z: u32,
2669    ) {
2670        let gl = &self.raw;
2671        if let Some(loc) = location {
2672            gl.Uniform3ui(loc.0 as i32, x, y, z);
2673        }
2674    }
2675
2676    unsafe fn uniform_4_u32(
2677        &self,
2678        location: Option<&Self::UniformLocation>,
2679        x: u32,
2680        y: u32,
2681        z: u32,
2682        w: u32,
2683    ) {
2684        let gl = &self.raw;
2685        if let Some(loc) = location {
2686            gl.Uniform4ui(loc.0 as i32, x, y, z, w);
2687        }
2688    }
2689
2690    unsafe fn uniform_1_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
2691        let gl = &self.raw;
2692        if let Some(loc) = location {
2693            gl.Uniform1uiv(loc.0 as i32, v.len() as i32, v.as_ptr());
2694        }
2695    }
2696
2697    unsafe fn uniform_2_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
2698        let gl = &self.raw;
2699        if let Some(loc) = location {
2700            gl.Uniform2uiv(loc.0 as i32, v.len() as i32 / 2, v.as_ptr());
2701        }
2702    }
2703
2704    unsafe fn uniform_3_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
2705        let gl = &self.raw;
2706        if let Some(loc) = location {
2707            gl.Uniform3uiv(loc.0 as i32, v.len() as i32 / 3, v.as_ptr());
2708        }
2709    }
2710
2711    unsafe fn uniform_4_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
2712        let gl = &self.raw;
2713        if let Some(loc) = location {
2714            gl.Uniform4uiv(loc.0 as i32, v.len() as i32 / 4, v.as_ptr());
2715        }
2716    }
2717
2718    unsafe fn uniform_1_f32(&self, location: Option<&Self::UniformLocation>, x: f32) {
2719        let gl = &self.raw;
2720        if let Some(loc) = location {
2721            gl.Uniform1f(loc.0 as i32, x);
2722        }
2723    }
2724
2725    unsafe fn uniform_2_f32(&self, location: Option<&Self::UniformLocation>, x: f32, y: f32) {
2726        let gl = &self.raw;
2727        if let Some(loc) = location {
2728            gl.Uniform2f(loc.0 as i32, x, y);
2729        }
2730    }
2731
2732    unsafe fn uniform_3_f32(
2733        &self,
2734        location: Option<&Self::UniformLocation>,
2735        x: f32,
2736        y: f32,
2737        z: f32,
2738    ) {
2739        let gl = &self.raw;
2740        if let Some(loc) = location {
2741            gl.Uniform3f(loc.0 as i32, x, y, z);
2742        }
2743    }
2744
2745    unsafe fn uniform_4_f32(
2746        &self,
2747        location: Option<&Self::UniformLocation>,
2748        x: f32,
2749        y: f32,
2750        z: f32,
2751        w: f32,
2752    ) {
2753        let gl = &self.raw;
2754        if let Some(loc) = location {
2755            gl.Uniform4f(loc.0 as i32, x, y, z, w);
2756        }
2757    }
2758
2759    unsafe fn uniform_1_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
2760        let gl = &self.raw;
2761        if let Some(loc) = location {
2762            gl.Uniform1fv(loc.0 as i32, v.len() as i32, v.as_ptr());
2763        }
2764    }
2765
2766    unsafe fn uniform_2_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
2767        let gl = &self.raw;
2768        if let Some(loc) = location {
2769            gl.Uniform2fv(loc.0 as i32, v.len() as i32 / 2, v.as_ptr());
2770        }
2771    }
2772
2773    unsafe fn uniform_3_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
2774        let gl = &self.raw;
2775        if let Some(loc) = location {
2776            gl.Uniform3fv(loc.0 as i32, v.len() as i32 / 3, v.as_ptr());
2777        }
2778    }
2779
2780    unsafe fn uniform_4_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
2781        let gl = &self.raw;
2782        if let Some(loc) = location {
2783            gl.Uniform4fv(loc.0 as i32, v.len() as i32 / 4, v.as_ptr());
2784        }
2785    }
2786
2787    unsafe fn uniform_matrix_2_f32_slice(
2788        &self,
2789        location: Option<&Self::UniformLocation>,
2790        transpose: bool,
2791        v: &[f32],
2792    ) {
2793        let gl = &self.raw;
2794        if let Some(loc) = location {
2795            gl.UniformMatrix2fv(
2796                loc.0 as i32,
2797                v.len() as i32 / 4,
2798                transpose as u8,
2799                v.as_ptr(),
2800            );
2801        }
2802    }
2803
2804    unsafe fn uniform_matrix_2x3_f32_slice(
2805        &self,
2806        location: Option<&Self::UniformLocation>,
2807        transpose: bool,
2808        v: &[f32],
2809    ) {
2810        let gl = &self.raw;
2811        if let Some(loc) = location {
2812            gl.UniformMatrix2x3fv(
2813                loc.0 as i32,
2814                v.len() as i32 / 6,
2815                transpose as u8,
2816                v.as_ptr(),
2817            );
2818        }
2819    }
2820
2821    unsafe fn uniform_matrix_2x4_f32_slice(
2822        &self,
2823        location: Option<&Self::UniformLocation>,
2824        transpose: bool,
2825        v: &[f32],
2826    ) {
2827        let gl = &self.raw;
2828        if let Some(loc) = location {
2829            gl.UniformMatrix2x4fv(
2830                loc.0 as i32,
2831                v.len() as i32 / 8,
2832                transpose as u8,
2833                v.as_ptr(),
2834            );
2835        }
2836    }
2837
2838    unsafe fn uniform_matrix_3x2_f32_slice(
2839        &self,
2840        location: Option<&Self::UniformLocation>,
2841        transpose: bool,
2842        v: &[f32],
2843    ) {
2844        let gl = &self.raw;
2845        if let Some(loc) = location {
2846            gl.UniformMatrix3x2fv(
2847                loc.0 as i32,
2848                v.len() as i32 / 6,
2849                transpose as u8,
2850                v.as_ptr(),
2851            );
2852        }
2853    }
2854
2855    unsafe fn uniform_matrix_3_f32_slice(
2856        &self,
2857        location: Option<&Self::UniformLocation>,
2858        transpose: bool,
2859        v: &[f32],
2860    ) {
2861        let gl = &self.raw;
2862        if let Some(loc) = location {
2863            gl.UniformMatrix3fv(
2864                loc.0 as i32,
2865                v.len() as i32 / 9,
2866                transpose as u8,
2867                v.as_ptr(),
2868            );
2869        }
2870    }
2871
2872    unsafe fn uniform_matrix_3x4_f32_slice(
2873        &self,
2874        location: Option<&Self::UniformLocation>,
2875        transpose: bool,
2876        v: &[f32],
2877    ) {
2878        let gl = &self.raw;
2879        if let Some(loc) = location {
2880            gl.UniformMatrix3x4fv(
2881                loc.0 as i32,
2882                v.len() as i32 / 12,
2883                transpose as u8,
2884                v.as_ptr(),
2885            );
2886        }
2887    }
2888
2889    unsafe fn uniform_matrix_4x2_f32_slice(
2890        &self,
2891        location: Option<&Self::UniformLocation>,
2892        transpose: bool,
2893        v: &[f32],
2894    ) {
2895        let gl = &self.raw;
2896        if let Some(loc) = location {
2897            gl.UniformMatrix4x2fv(
2898                loc.0 as i32,
2899                v.len() as i32 / 8,
2900                transpose as u8,
2901                v.as_ptr(),
2902            );
2903        }
2904    }
2905
2906    unsafe fn uniform_matrix_4x3_f32_slice(
2907        &self,
2908        location: Option<&Self::UniformLocation>,
2909        transpose: bool,
2910        v: &[f32],
2911    ) {
2912        let gl = &self.raw;
2913        if let Some(loc) = location {
2914            gl.UniformMatrix4x3fv(
2915                loc.0 as i32,
2916                v.len() as i32 / 12,
2917                transpose as u8,
2918                v.as_ptr(),
2919            );
2920        }
2921    }
2922
2923    unsafe fn uniform_matrix_4_f32_slice(
2924        &self,
2925        location: Option<&Self::UniformLocation>,
2926        transpose: bool,
2927        v: &[f32],
2928    ) {
2929        let gl = &self.raw;
2930        if let Some(loc) = location {
2931            gl.UniformMatrix4fv(
2932                loc.0 as i32,
2933                v.len() as i32 / 16,
2934                transpose as u8,
2935                v.as_ptr(),
2936            );
2937        }
2938    }
2939
2940    unsafe fn unmap_buffer(&self, target: u32) {
2941        let gl = &self.raw;
2942        gl.UnmapBuffer(target);
2943    }
2944
2945    unsafe fn cull_face(&self, value: u32) {
2946        let gl = &self.raw;
2947        gl.CullFace(value as u32);
2948    }
2949
2950    unsafe fn color_mask(&self, red: bool, green: bool, blue: bool, alpha: bool) {
2951        let gl = &self.raw;
2952        gl.ColorMask(red as u8, green as u8, blue as u8, alpha as u8);
2953    }
2954
2955    unsafe fn color_mask_draw_buffer(
2956        &self,
2957        draw_buffer: u32,
2958        red: bool,
2959        green: bool,
2960        blue: bool,
2961        alpha: bool,
2962    ) {
2963        let gl = &self.raw;
2964        gl.ColorMaski(draw_buffer, red as u8, green as u8, blue as u8, alpha as u8);
2965    }
2966
2967    unsafe fn depth_mask(&self, value: bool) {
2968        let gl = &self.raw;
2969        gl.DepthMask(value as u8);
2970    }
2971
2972    unsafe fn blend_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
2973        let gl = &self.raw;
2974        gl.BlendColor(red, green, blue, alpha);
2975    }
2976
2977    unsafe fn line_width(&self, width: f32) {
2978        let gl = &self.raw;
2979        gl.LineWidth(width);
2980    }
2981
2982    unsafe fn map_buffer_range(
2983        &self,
2984        target: u32,
2985        offset: i32,
2986        length: i32,
2987        access: u32,
2988    ) -> *mut u8 {
2989        let gl = &self.raw;
2990        gl.MapBufferRange(target, offset as isize, length as isize, access) as *mut u8
2991    }
2992
2993    unsafe fn flush_mapped_buffer_range(&self, target: u32, offset: i32, length: i32) {
2994        let gl = &self.raw;
2995        gl.FlushMappedBufferRange(target, offset as isize, length as isize)
2996    }
2997
2998    unsafe fn invalidate_buffer_sub_data(&self, target: u32, offset: i32, length: i32) {
2999        let gl = &self.raw;
3000        gl.InvalidateBufferSubData(target, offset as isize, length as isize)
3001    }
3002
3003    unsafe fn invalidate_framebuffer(&self, target: u32, attachments: &[u32]) {
3004        let gl = &self.raw;
3005        gl.InvalidateFramebuffer(target, attachments.len() as i32, attachments.as_ptr());
3006    }
3007
3008    unsafe fn polygon_offset(&self, factor: f32, units: f32) {
3009        let gl = &self.raw;
3010        gl.PolygonOffset(factor, units);
3011    }
3012
3013    unsafe fn polygon_mode(&self, face: u32, mode: u32) {
3014        let gl = &self.raw;
3015        gl.PolygonMode(face as u32, mode as u32);
3016    }
3017
3018    unsafe fn finish(&self) {
3019        let gl = &self.raw;
3020        gl.Finish();
3021    }
3022
3023    unsafe fn bind_texture(&self, target: u32, texture: Option<Self::Texture>) {
3024        let gl = &self.raw;
3025        gl.BindTexture(target, texture.map(|t| t.0.get()).unwrap_or(0));
3026    }
3027
3028    unsafe fn bind_texture_unit(&self, unit: u32, texture: Option<Self::Texture>) {
3029        let gl = &self.raw;
3030        gl.BindTextureUnit(unit, texture.map(|t| t.0.get()).unwrap_or(0));
3031    }
3032
3033    unsafe fn bind_sampler(&self, unit: u32, sampler: Option<Self::Sampler>) {
3034        let gl = &self.raw;
3035        gl.BindSampler(unit, sampler.map(|s| s.0.get()).unwrap_or(0));
3036    }
3037
3038    unsafe fn active_texture(&self, unit: u32) {
3039        let gl = &self.raw;
3040        gl.ActiveTexture(unit);
3041    }
3042
3043    unsafe fn fence_sync(&self, condition: u32, flags: u32) -> Result<Self::Fence, String> {
3044        let gl = &self.raw;
3045        Ok(NativeFence(gl.FenceSync(condition as u32, flags)))
3046    }
3047
3048    unsafe fn tex_parameter_f32(&self, target: u32, parameter: u32, value: f32) {
3049        let gl = &self.raw;
3050        gl.TexParameterf(target, parameter, value);
3051    }
3052
3053    unsafe fn tex_parameter_i32(&self, target: u32, parameter: u32, value: i32) {
3054        let gl = &self.raw;
3055        gl.TexParameteri(target, parameter, value);
3056    }
3057
3058    unsafe fn texture_parameter_i32(&self, texture: Self::Texture, parameter: u32, value: i32) {
3059        let gl = &self.raw;
3060        gl.TextureParameteri(texture.0.get(), parameter, value);
3061    }
3062
3063    unsafe fn tex_parameter_f32_slice(&self, target: u32, parameter: u32, values: &[f32]) {
3064        let gl = &self.raw;
3065        gl.TexParameterfv(target, parameter, values.as_ptr());
3066    }
3067
3068    unsafe fn tex_parameter_i32_slice(&self, target: u32, parameter: u32, values: &[i32]) {
3069        let gl = &self.raw;
3070        gl.TexParameteriv(target, parameter, values.as_ptr());
3071    }
3072
3073    unsafe fn tex_sub_image_2d(
3074        &self,
3075        target: u32,
3076        level: i32,
3077        x_offset: i32,
3078        y_offset: i32,
3079        width: i32,
3080        height: i32,
3081        format: u32,
3082        ty: u32,
3083        pixels: PixelUnpackData,
3084    ) {
3085        let gl = &self.raw;
3086        gl.TexSubImage2D(
3087            target,
3088            level,
3089            x_offset,
3090            y_offset,
3091            width,
3092            height,
3093            format,
3094            ty,
3095            match pixels {
3096                PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
3097                PixelUnpackData::Slice(data) => data.as_ptr() as *const std::ffi::c_void,
3098            },
3099        );
3100    }
3101
3102    unsafe fn texture_sub_image_2d(
3103        &self,
3104        texture: Self::Texture,
3105        level: i32,
3106        x_offset: i32,
3107        y_offset: i32,
3108        width: i32,
3109        height: i32,
3110        format: u32,
3111        ty: u32,
3112        pixels: PixelUnpackData,
3113    ) {
3114        let gl = &self.raw;
3115        gl.TextureSubImage2D(
3116            texture.0.get(),
3117            level,
3118            x_offset,
3119            y_offset,
3120            width,
3121            height,
3122            format,
3123            ty,
3124            match pixels {
3125                PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
3126                PixelUnpackData::Slice(data) => data.as_ptr() as *const std::ffi::c_void,
3127            },
3128        );
3129    }
3130
3131    unsafe fn compressed_tex_sub_image_2d(
3132        &self,
3133        target: u32,
3134        level: i32,
3135        x_offset: i32,
3136        y_offset: i32,
3137        width: i32,
3138        height: i32,
3139        format: u32,
3140        pixels: CompressedPixelUnpackData,
3141    ) {
3142        let gl = &self.raw;
3143        let (data, image_size) = match pixels {
3144            CompressedPixelUnpackData::BufferRange(ref range) => (
3145                range.start as *const std::ffi::c_void,
3146                (range.end - range.start) as i32,
3147            ),
3148            CompressedPixelUnpackData::Slice(data) => {
3149                (data.as_ptr() as *const std::ffi::c_void, data.len() as i32)
3150            }
3151        };
3152
3153        gl.CompressedTexSubImage2D(
3154            target, level, x_offset, y_offset, width, height, format, image_size, data,
3155        );
3156    }
3157
3158    unsafe fn tex_sub_image_3d(
3159        &self,
3160        target: u32,
3161        level: i32,
3162        x_offset: i32,
3163        y_offset: i32,
3164        z_offset: i32,
3165        width: i32,
3166        height: i32,
3167        depth: i32,
3168        format: u32,
3169        ty: u32,
3170        pixels: PixelUnpackData,
3171    ) {
3172        let gl = &self.raw;
3173        gl.TexSubImage3D(
3174            target,
3175            level,
3176            x_offset,
3177            y_offset,
3178            z_offset,
3179            width,
3180            height,
3181            depth,
3182            format,
3183            ty,
3184            match pixels {
3185                PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
3186                PixelUnpackData::Slice(data) => data.as_ptr() as *const std::ffi::c_void,
3187            },
3188        );
3189    }
3190
3191    unsafe fn texture_sub_image_3d(
3192        &self,
3193        texture: Self::Texture,
3194        level: i32,
3195        x_offset: i32,
3196        y_offset: i32,
3197        z_offset: i32,
3198        width: i32,
3199        height: i32,
3200        depth: i32,
3201        format: u32,
3202        ty: u32,
3203        pixels: PixelUnpackData,
3204    ) {
3205        let gl = &self.raw;
3206        gl.TextureSubImage3D(
3207            texture.0.get(),
3208            level,
3209            x_offset,
3210            y_offset,
3211            z_offset,
3212            width,
3213            height,
3214            depth,
3215            format,
3216            ty,
3217            match pixels {
3218                PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
3219                PixelUnpackData::Slice(data) => data.as_ptr() as *const std::ffi::c_void,
3220            },
3221        );
3222    }
3223
3224    unsafe fn compressed_tex_sub_image_3d(
3225        &self,
3226        target: u32,
3227        level: i32,
3228        x_offset: i32,
3229        y_offset: i32,
3230        z_offset: i32,
3231        width: i32,
3232        height: i32,
3233        depth: i32,
3234        format: u32,
3235        pixels: CompressedPixelUnpackData,
3236    ) {
3237        let gl = &self.raw;
3238        let (data, image_size) = match pixels {
3239            CompressedPixelUnpackData::BufferRange(ref range) => (
3240                range.start as *const std::ffi::c_void,
3241                (range.end - range.start) as i32,
3242            ),
3243            CompressedPixelUnpackData::Slice(data) => {
3244                (data.as_ptr() as *const std::ffi::c_void, data.len() as i32)
3245            }
3246        };
3247
3248        gl.CompressedTexSubImage3D(
3249            target, level, x_offset, y_offset, z_offset, width, height, depth, format, image_size,
3250            data,
3251        );
3252    }
3253
3254    unsafe fn depth_func(&self, func: u32) {
3255        let gl = &self.raw;
3256        gl.DepthFunc(func as u32);
3257    }
3258
3259    unsafe fn depth_range_f32(&self, near: f32, far: f32) {
3260        let gl = &self.raw;
3261        gl.DepthRangef(near, far);
3262    }
3263
3264    unsafe fn depth_range_f64(&self, near: f64, far: f64) {
3265        let gl = &self.raw;
3266        gl.DepthRange(near, far);
3267    }
3268
3269    unsafe fn depth_range_f64_slice(&self, first: u32, count: i32, values: &[[f64; 2]]) {
3270        let gl = &self.raw;
3271        gl.DepthRangeArrayv(first, count, values.as_ptr() as *const f64);
3272    }
3273
3274    unsafe fn scissor(&self, x: i32, y: i32, width: i32, height: i32) {
3275        let gl = &self.raw;
3276        gl.Scissor(x, y, width, height);
3277    }
3278
3279    unsafe fn scissor_slice(&self, first: u32, count: i32, scissors: &[[i32; 4]]) {
3280        let gl = &self.raw;
3281        gl.ScissorArrayv(first, count, scissors.as_ptr() as *const i32);
3282    }
3283
3284    unsafe fn vertex_array_attrib_binding_f32(
3285        &self,
3286        vao: Self::VertexArray,
3287        index: u32,
3288        binding_index: u32,
3289    ) {
3290        let gl = &self.raw;
3291        gl.VertexArrayAttribBinding(vao.0.get(), index, binding_index);
3292    }
3293
3294    unsafe fn vertex_array_attrib_format_f32(
3295        &self,
3296        vao: Self::VertexArray,
3297        index: u32,
3298        size: i32,
3299        data_type: u32,
3300        normalized: bool,
3301        relative_offset: u32,
3302    ) {
3303        let gl = &self.raw;
3304        gl.VertexArrayAttribFormat(
3305            vao.0.get(),
3306            index,
3307            size,
3308            data_type,
3309            normalized as u8,
3310            relative_offset,
3311        );
3312    }
3313
3314    unsafe fn vertex_array_attrib_format_i32(
3315        &self,
3316        vao: Self::VertexArray,
3317        index: u32,
3318        size: i32,
3319        data_type: u32,
3320        relative_offset: u32,
3321    ) {
3322        let gl = &self.raw;
3323        gl.VertexArrayAttribIFormat(vao.0.get(), index, size, data_type, relative_offset);
3324    }
3325
3326    unsafe fn vertex_array_attrib_format_f64(
3327        &self,
3328        vao: Self::VertexArray,
3329        index: u32,
3330        size: i32,
3331        data_type: u32,
3332        relative_offset: u32,
3333    ) {
3334        let gl = &self.raw;
3335        gl.VertexArrayAttribLFormat(vao.0.get(), index, size, data_type, relative_offset);
3336    }
3337
3338    unsafe fn vertex_array_element_buffer(
3339        &self,
3340        vao: Self::VertexArray,
3341        buffer: Option<Self::Buffer>,
3342    ) {
3343        let gl = &self.raw;
3344        gl.VertexArrayElementBuffer(vao.0.get(), buffer.map(|b| b.0.get()).unwrap_or(0));
3345    }
3346
3347    unsafe fn vertex_array_vertex_buffer(
3348        &self,
3349        vao: Self::VertexArray,
3350        binding_index: u32,
3351        buffer: Option<Self::Buffer>,
3352        offset: i32,
3353        stride: i32,
3354    ) {
3355        let gl = &self.raw;
3356        gl.VertexArrayVertexBuffer(
3357            vao.0.get(),
3358            binding_index,
3359            buffer.map(|b| b.0.get()).unwrap_or(0),
3360            offset as isize,
3361            stride,
3362        );
3363    }
3364
3365    unsafe fn vertex_attrib_divisor(&self, index: u32, divisor: u32) {
3366        let gl = &self.raw;
3367        gl.VertexAttribDivisor(index, divisor);
3368    }
3369
3370    unsafe fn vertex_attrib_pointer_f32(
3371        &self,
3372        index: u32,
3373        size: i32,
3374        data_type: u32,
3375        normalized: bool,
3376        stride: i32,
3377        offset: i32,
3378    ) {
3379        let gl = &self.raw;
3380        gl.VertexAttribPointer(
3381            index,
3382            size,
3383            data_type,
3384            normalized as u8,
3385            stride,
3386            offset as *const std::ffi::c_void,
3387        );
3388    }
3389
3390    unsafe fn vertex_attrib_pointer_i32(
3391        &self,
3392        index: u32,
3393        size: i32,
3394        data_type: u32,
3395        stride: i32,
3396        offset: i32,
3397    ) {
3398        let gl = &self.raw;
3399        gl.VertexAttribIPointer(
3400            index,
3401            size,
3402            data_type,
3403            stride,
3404            offset as *const std::ffi::c_void,
3405        );
3406    }
3407
3408    unsafe fn vertex_attrib_pointer_f64(
3409        &self,
3410        index: u32,
3411        size: i32,
3412        data_type: u32,
3413        stride: i32,
3414        offset: i32,
3415    ) {
3416        let gl = &self.raw;
3417        gl.VertexAttribLPointer(
3418            index,
3419            size,
3420            data_type,
3421            stride,
3422            offset as *const std::ffi::c_void,
3423        );
3424    }
3425
3426    unsafe fn vertex_attrib_format_f32(
3427        &self,
3428        index: u32,
3429        size: i32,
3430        data_type: u32,
3431        normalized: bool,
3432        relative_offset: u32,
3433    ) {
3434        let gl = &self.raw;
3435        gl.VertexAttribFormat(index, size, data_type, normalized as u8, relative_offset);
3436    }
3437
3438    unsafe fn vertex_attrib_format_i32(
3439        &self,
3440        index: u32,
3441        size: i32,
3442        data_type: u32,
3443        relative_offset: u32,
3444    ) {
3445        let gl = &self.raw;
3446        gl.VertexAttribIFormat(index, size, data_type, relative_offset);
3447    }
3448
3449    unsafe fn vertex_attrib_format_f64(
3450        &self,
3451        index: u32,
3452        size: i32,
3453        data_type: u32,
3454        relative_offset: u32,
3455    ) {
3456        let gl = &self.raw;
3457        gl.VertexAttribLFormat(index, size, data_type, relative_offset);
3458    }
3459
3460    unsafe fn vertex_attrib_1_f32(&self, index: u32, x: f32) {
3461        let gl = &self.raw;
3462        gl.VertexAttrib1f(index, x);
3463    }
3464
3465    unsafe fn vertex_attrib_2_f32(&self, index: u32, x: f32, y: f32) {
3466        let gl = &self.raw;
3467        gl.VertexAttrib2f(index, x, y);
3468    }
3469
3470    unsafe fn vertex_attrib_3_f32(&self, index: u32, x: f32, y: f32, z: f32) {
3471        let gl = &self.raw;
3472        gl.VertexAttrib3f(index, x, y, z);
3473    }
3474
3475    unsafe fn vertex_attrib_4_f32(&self, index: u32, x: f32, y: f32, z: f32, w: f32) {
3476        let gl = &self.raw;
3477        gl.VertexAttrib4f(index, x, y, z, w);
3478    }
3479
3480    unsafe fn vertex_attrib_1_f32_slice(&self, index: u32, v: &[f32]) {
3481        let gl = &self.raw;
3482        gl.VertexAttrib1fv(index, v.as_ptr());
3483    }
3484
3485    unsafe fn vertex_attrib_2_f32_slice(&self, index: u32, v: &[f32]) {
3486        let gl = &self.raw;
3487        gl.VertexAttrib2fv(index, v.as_ptr());
3488    }
3489
3490    unsafe fn vertex_attrib_3_f32_slice(&self, index: u32, v: &[f32]) {
3491        let gl = &self.raw;
3492        gl.VertexAttrib3fv(index, v.as_ptr());
3493    }
3494
3495    unsafe fn vertex_attrib_4_f32_slice(&self, index: u32, v: &[f32]) {
3496        let gl = &self.raw;
3497        gl.VertexAttrib4fv(index, v.as_ptr());
3498    }
3499
3500    unsafe fn vertex_attrib_binding(&self, attrib_index: u32, binding_index: u32) {
3501        let gl = &self.raw;
3502        gl.VertexAttribBinding(attrib_index, binding_index);
3503    }
3504
3505    unsafe fn vertex_binding_divisor(&self, binding_index: u32, divisor: u32) {
3506        let gl = &self.raw;
3507        gl.VertexBindingDivisor(binding_index, divisor);
3508    }
3509
3510    unsafe fn viewport(&self, x: i32, y: i32, width: i32, height: i32) {
3511        let gl = &self.raw;
3512        gl.Viewport(x, y, width, height);
3513    }
3514
3515    unsafe fn viewport_f32_slice(&self, first: u32, count: i32, values: &[[f32; 4]]) {
3516        let gl = &self.raw;
3517        gl.ViewportArrayv(first, count, values.as_ptr() as *const f32);
3518    }
3519
3520    unsafe fn blend_equation(&self, mode: u32) {
3521        let gl = &self.raw;
3522        gl.BlendEquation(mode as u32);
3523    }
3524
3525    unsafe fn blend_equation_draw_buffer(&self, draw_buffer: u32, mode: u32) {
3526        let gl = &self.raw;
3527        gl.BlendEquationi(draw_buffer, mode as u32);
3528    }
3529
3530    unsafe fn blend_equation_separate(&self, mode_rgb: u32, mode_alpha: u32) {
3531        let gl = &self.raw;
3532        gl.BlendEquationSeparate(mode_rgb as u32, mode_alpha as u32);
3533    }
3534
3535    unsafe fn blend_equation_separate_draw_buffer(
3536        &self,
3537        draw_buffer: u32,
3538        mode_rgb: u32,
3539        mode_alpha: u32,
3540    ) {
3541        let gl = &self.raw;
3542        gl.BlendEquationSeparatei(draw_buffer, mode_rgb as u32, mode_alpha as u32);
3543    }
3544
3545    unsafe fn blend_func(&self, src: u32, dst: u32) {
3546        let gl = &self.raw;
3547        gl.BlendFunc(src as u32, dst as u32);
3548    }
3549
3550    unsafe fn blend_func_draw_buffer(&self, draw_buffer: u32, src: u32, dst: u32) {
3551        let gl = &self.raw;
3552        gl.BlendFunci(draw_buffer, src as u32, dst as u32);
3553    }
3554
3555    unsafe fn blend_func_separate(
3556        &self,
3557        src_rgb: u32,
3558        dst_rgb: u32,
3559        src_alpha: u32,
3560        dst_alpha: u32,
3561    ) {
3562        let gl = &self.raw;
3563        gl.BlendFuncSeparate(
3564            src_rgb as u32,
3565            dst_rgb as u32,
3566            src_alpha as u32,
3567            dst_alpha as u32,
3568        );
3569    }
3570
3571    unsafe fn blend_func_separate_draw_buffer(
3572        &self,
3573        draw_buffer: u32,
3574        src_rgb: u32,
3575        dst_rgb: u32,
3576        src_alpha: u32,
3577        dst_alpha: u32,
3578    ) {
3579        let gl = &self.raw;
3580        gl.BlendFuncSeparatei(
3581            draw_buffer,
3582            src_rgb as u32,
3583            dst_rgb as u32,
3584            src_alpha as u32,
3585            dst_alpha as u32,
3586        );
3587    }
3588
3589    unsafe fn stencil_func(&self, func: u32, reference: i32, mask: u32) {
3590        let gl = &self.raw;
3591        gl.StencilFunc(func as u32, reference, mask);
3592    }
3593
3594    unsafe fn stencil_func_separate(&self, face: u32, func: u32, reference: i32, mask: u32) {
3595        let gl = &self.raw;
3596        gl.StencilFuncSeparate(face as u32, func as u32, reference, mask);
3597    }
3598
3599    unsafe fn stencil_mask(&self, mask: u32) {
3600        let gl = &self.raw;
3601        gl.StencilMask(mask);
3602    }
3603
3604    unsafe fn stencil_mask_separate(&self, face: u32, mask: u32) {
3605        let gl = &self.raw;
3606        gl.StencilMaskSeparate(face as u32, mask);
3607    }
3608
3609    unsafe fn stencil_op(&self, stencil_fail: u32, depth_fail: u32, pass: u32) {
3610        let gl = &self.raw;
3611        gl.StencilOp(stencil_fail as u32, depth_fail as u32, pass as u32);
3612    }
3613
3614    unsafe fn stencil_op_separate(&self, face: u32, stencil_fail: u32, depth_fail: u32, pass: u32) {
3615        let gl = &self.raw;
3616        gl.StencilOpSeparate(
3617            face as u32,
3618            stencil_fail as u32,
3619            depth_fail as u32,
3620            pass as u32,
3621        );
3622    }
3623
3624    unsafe fn debug_message_control(
3625        &self,
3626        source: u32,
3627        msg_type: u32,
3628        severity: u32,
3629        ids: &[u32],
3630        enabled: bool,
3631    ) {
3632        let gl = &self.raw;
3633
3634        let ids_ptr = if ids.is_empty() {
3635            std::ptr::null()
3636        } else {
3637            ids.as_ptr()
3638        };
3639
3640        gl.DebugMessageControl(
3641            source,
3642            msg_type,
3643            severity,
3644            ids.len() as i32,
3645            ids_ptr,
3646            enabled as u8,
3647        );
3648    }
3649
3650    unsafe fn debug_message_insert<S>(
3651        &self,
3652        source: u32,
3653        msg_type: u32,
3654        id: u32,
3655        severity: u32,
3656        msg: S,
3657    ) where
3658        S: AsRef<str>,
3659    {
3660        let gl = &self.raw;
3661        let message = msg.as_ref().as_bytes();
3662        let length = message.len() as i32;
3663        gl.DebugMessageInsert(
3664            source,
3665            msg_type,
3666            id,
3667            severity,
3668            length,
3669            message.as_ptr() as *const native_gl::GLchar,
3670        );
3671    }
3672
3673    unsafe fn debug_message_callback<F>(&mut self, callback: F)
3674    where
3675        F: Fn(u32, u32, u32, u32, &str) + Send + Sync + 'static,
3676    {
3677        match self.debug_callback {
3678            Some(_) => {
3679                panic!("Debug callback already set");
3680            }
3681            None => {
3682                let trait_object: DebugCallback = Box::new(callback);
3683                let thin_ptr = Box::new(trait_object);
3684                let raw_ptr = Box::into_raw(thin_ptr) as *mut _ as *mut std::ffi::c_void;
3685
3686                let gl = &self.raw;
3687
3688                if gl.DebugMessageCallback_is_loaded() {
3689                    gl.DebugMessageCallback(Some(raw_debug_message_callback), raw_ptr);
3690                } else {
3691                    // Fallback to extension
3692                    gl.DebugMessageCallbackKHR(Some(raw_debug_message_callback), raw_ptr);
3693                }
3694
3695                self.debug_callback = Some(DebugCallbackRawPtr { callback: raw_ptr });
3696            }
3697        }
3698    }
3699
3700    unsafe fn get_debug_message_log(&self, count: u32) -> Vec<DebugMessageLogEntry> {
3701        let ct = count as usize;
3702        let mut sources = Vec::with_capacity(ct);
3703        let mut types = Vec::with_capacity(ct);
3704        let mut ids = Vec::with_capacity(ct);
3705        let mut severities = Vec::with_capacity(ct);
3706        let mut lengths = Vec::with_capacity(ct);
3707        let buf_size = (count * MAX_DEBUG_MESSAGE_LENGTH) as i32;
3708        let mut message_log = Vec::with_capacity(buf_size as usize);
3709
3710        let gl = &self.raw;
3711        let received = gl.GetDebugMessageLog(
3712            count,
3713            buf_size,
3714            sources.as_mut_ptr(),
3715            types.as_mut_ptr(),
3716            ids.as_mut_ptr(),
3717            severities.as_mut_ptr(),
3718            lengths.as_mut_ptr(),
3719            message_log.as_mut_ptr(),
3720        ) as usize;
3721
3722        sources.set_len(received);
3723        types.set_len(received);
3724        ids.set_len(received);
3725        severities.set_len(received);
3726        lengths.set_len(received);
3727        message_log.set_len(buf_size as usize);
3728
3729        let mut entries = Vec::new();
3730        let mut offset = 0;
3731        for i in 0..received {
3732            let message =
3733                std::ffi::CStr::from_ptr(message_log[offset..].as_ptr()).to_string_lossy();
3734            offset += lengths[i] as usize;
3735            entries.push(DebugMessageLogEntry {
3736                source: sources[i],
3737                msg_type: types[i],
3738                id: ids[i],
3739                severity: severities[i],
3740                message: message.to_string(),
3741            });
3742        }
3743
3744        entries
3745    }
3746
3747    unsafe fn push_debug_group<S>(&self, source: u32, id: u32, message: S)
3748    where
3749        S: AsRef<str>,
3750    {
3751        let gl = &self.raw;
3752        let msg = message.as_ref().as_bytes();
3753        let length = msg.len() as i32;
3754        gl.PushDebugGroup(source, id, length, msg.as_ptr() as *const native_gl::GLchar);
3755    }
3756
3757    unsafe fn pop_debug_group(&self) {
3758        let gl = &self.raw;
3759        gl.PopDebugGroup();
3760    }
3761
3762    unsafe fn object_label<S>(&self, identifier: u32, name: u32, label: Option<S>)
3763    where
3764        S: AsRef<str>,
3765    {
3766        let gl = &self.raw;
3767
3768        match label {
3769            Some(l) => {
3770                let lbl = l.as_ref().as_bytes();
3771                let length = lbl.len() as i32;
3772                gl.ObjectLabel(
3773                    identifier,
3774                    name,
3775                    length,
3776                    lbl.as_ptr() as *const native_gl::GLchar,
3777                );
3778            }
3779            None => gl.ObjectLabel(identifier, name, 0, std::ptr::null()),
3780        }
3781    }
3782
3783    unsafe fn get_object_label(&self, identifier: u32, name: u32) -> String {
3784        let gl = &self.raw;
3785        let mut len = 0;
3786        let mut label_buf = Vec::with_capacity(self.constants.max_label_length as usize);
3787        gl.GetObjectLabel(
3788            identifier,
3789            name,
3790            self.constants.max_label_length,
3791            &mut len,
3792            label_buf.as_mut_ptr(),
3793        );
3794        label_buf.set_len(len as usize);
3795        std::ffi::CStr::from_ptr(label_buf.as_ptr())
3796            .to_str()
3797            .unwrap()
3798            .to_owned()
3799    }
3800
3801    unsafe fn object_ptr_label<S>(&self, sync: Self::Fence, label: Option<S>)
3802    where
3803        S: AsRef<str>,
3804    {
3805        let gl = &self.raw;
3806
3807        match label {
3808            Some(l) => {
3809                let lbl = l.as_ref().as_bytes();
3810                let length = lbl.len() as i32;
3811                gl.ObjectPtrLabel(
3812                    sync.0 as *mut std::ffi::c_void,
3813                    length,
3814                    lbl.as_ptr() as *const native_gl::GLchar,
3815                );
3816            }
3817            None => gl.ObjectPtrLabel(sync.0 as *mut std::ffi::c_void, 0, std::ptr::null()),
3818        }
3819    }
3820
3821    unsafe fn get_object_ptr_label(&self, sync: Self::Fence) -> String {
3822        let gl = &self.raw;
3823        let mut len = 0;
3824        let mut label_buf = Vec::with_capacity(self.constants.max_label_length as usize);
3825        gl.GetObjectPtrLabel(
3826            sync.0 as *mut std::ffi::c_void,
3827            self.constants.max_label_length,
3828            &mut len,
3829            label_buf.as_mut_ptr(),
3830        );
3831        label_buf.set_len(len as usize);
3832        std::ffi::CStr::from_ptr(label_buf.as_ptr())
3833            .to_str()
3834            .unwrap()
3835            .to_owned()
3836    }
3837
3838    unsafe fn get_uniform_block_index(&self, program: Self::Program, name: &str) -> Option<u32> {
3839        let gl = &self.raw;
3840        let name = CString::new(name).unwrap();
3841        let index = gl.GetUniformBlockIndex(program.0.get(), name.as_ptr());
3842        if index == INVALID_INDEX {
3843            None
3844        } else {
3845            Some(index)
3846        }
3847    }
3848
3849    unsafe fn uniform_block_binding(&self, program: Self::Program, index: u32, binding: u32) {
3850        let gl = &self.raw;
3851        gl.UniformBlockBinding(program.0.get(), index, binding);
3852    }
3853
3854    unsafe fn get_shader_storage_block_index(
3855        &self,
3856        program: Self::Program,
3857        name: &str,
3858    ) -> Option<u32> {
3859        let gl = &self.raw;
3860        let name = CString::new(name).unwrap();
3861        let index =
3862            gl.GetProgramResourceIndex(program.0.get(), SHADER_STORAGE_BLOCK, name.as_ptr());
3863        if index == INVALID_INDEX {
3864            None
3865        } else {
3866            Some(index)
3867        }
3868    }
3869
3870    unsafe fn shader_storage_block_binding(
3871        &self,
3872        program: Self::Program,
3873        index: u32,
3874        binding: u32,
3875    ) {
3876        let gl = &self.raw;
3877        gl.ShaderStorageBlockBinding(program.0.get(), index, binding);
3878    }
3879
3880    unsafe fn read_buffer(&self, src: u32) {
3881        let gl = &self.raw;
3882        gl.ReadBuffer(src);
3883    }
3884
3885    unsafe fn named_framebuffer_read_buffer(
3886        &self,
3887        framebuffer: Option<Self::Framebuffer>,
3888        src: u32,
3889    ) {
3890        let gl = &self.raw;
3891        gl.NamedFramebufferReadBuffer(framebuffer.map(|f| f.0.get()).unwrap_or(0), src);
3892    }
3893
3894    unsafe fn read_pixels(
3895        &self,
3896        x: i32,
3897        y: i32,
3898        width: i32,
3899        height: i32,
3900        format: u32,
3901        gltype: u32,
3902        pixels: PixelPackData,
3903    ) {
3904        let gl = &self.raw;
3905        gl.ReadPixels(
3906            x,
3907            y,
3908            width,
3909            height,
3910            format,
3911            gltype,
3912            match pixels {
3913                PixelPackData::BufferOffset(offset) => offset as *mut std::ffi::c_void,
3914                PixelPackData::Slice(data) => data.as_mut_ptr() as *mut std::ffi::c_void,
3915            },
3916        );
3917    }
3918
3919    unsafe fn begin_query(&self, target: u32, query: Self::Query) {
3920        let gl = &self.raw;
3921        gl.BeginQuery(target, query.0.get());
3922    }
3923
3924    unsafe fn end_query(&self, target: u32) {
3925        let gl = &self.raw;
3926        gl.EndQuery(target);
3927    }
3928
3929    unsafe fn query_counter(&self, query: Self::Query, target: u32) {
3930        let gl = &self.raw;
3931        gl.QueryCounter(query.0.get(), target);
3932    }
3933
3934    unsafe fn get_query_parameter_u32(&self, query: Self::Query, parameter: u32) -> u32 {
3935        let gl = &self.raw;
3936        let mut value = 0;
3937        gl.GetQueryObjectuiv(query.0.get(), parameter, &mut value);
3938        value
3939    }
3940
3941    unsafe fn get_query_parameter_u64_with_offset(
3942        &self,
3943        query: Self::Query,
3944        parameter: u32,
3945        offset: usize,
3946    ) {
3947        let gl = &self.raw;
3948        gl.GetQueryObjectui64v(query.0.get(), parameter, offset as *mut _);
3949    }
3950
3951    unsafe fn create_transform_feedback(&self) -> Result<Self::TransformFeedback, String> {
3952        let gl = &self.raw;
3953        let mut name = 0;
3954        gl.GenTransformFeedbacks(1, &mut name);
3955        Ok(NativeTransformFeedback(non_zero_gl_name(name)))
3956    }
3957
3958    unsafe fn delete_transform_feedback(&self, transform_feedback: Self::TransformFeedback) {
3959        let gl = &self.raw;
3960        gl.DeleteTransformFeedbacks(1, &transform_feedback.0.get());
3961    }
3962
3963    unsafe fn bind_transform_feedback(
3964        &self,
3965        target: u32,
3966        transform_feedback: Option<Self::TransformFeedback>,
3967    ) {
3968        let gl = &self.raw;
3969        gl.BindTransformFeedback(target, transform_feedback.map(|tf| tf.0.get()).unwrap_or(0));
3970    }
3971
3972    unsafe fn begin_transform_feedback(&self, primitive_mode: u32) {
3973        let gl = &self.raw;
3974        gl.BeginTransformFeedback(primitive_mode);
3975    }
3976
3977    unsafe fn end_transform_feedback(&self) {
3978        let gl = &self.raw;
3979        gl.EndTransformFeedback();
3980    }
3981
3982    unsafe fn pause_transform_feedback(&self) {
3983        let gl = &self.raw;
3984        gl.PauseTransformFeedback();
3985    }
3986
3987    unsafe fn resume_transform_feedback(&self) {
3988        let gl = &self.raw;
3989        gl.ResumeTransformFeedback();
3990    }
3991
3992    unsafe fn transform_feedback_varyings(
3993        &self,
3994        program: Self::Program,
3995        varyings: &[&str],
3996        buffer_mode: u32,
3997    ) {
3998        let gl = &self.raw;
3999
4000        let strings: Vec<CString> = varyings
4001            .iter()
4002            .copied()
4003            .map(CString::new)
4004            .collect::<Result<_, _>>()
4005            .unwrap();
4006        let varyings: Vec<_> = strings.iter().map(|c_str| c_str.as_ptr()).collect();
4007
4008        gl.TransformFeedbackVaryings(
4009            program.0.get(),
4010            varyings.len() as i32,
4011            varyings.as_ptr(),
4012            buffer_mode,
4013        );
4014    }
4015
4016    unsafe fn get_transform_feedback_varying(
4017        &self,
4018        program: Self::Program,
4019        index: u32,
4020    ) -> Option<ActiveTransformFeedback> {
4021        let gl = &self.raw;
4022
4023        const buf_size: usize = 256;
4024        const bytes: [u8; buf_size] = [0; buf_size];
4025
4026        let size: i32 = 0;
4027        let tftype: u32 = 0;
4028        let c_name = CString::new(bytes.to_vec()).unwrap();
4029        let c_name_buf = c_name.into_raw();
4030
4031        gl.GetTransformFeedbackVarying(
4032            program.0.get(),
4033            index,
4034            buf_size as i32,
4035            std::ptr::null_mut(),
4036            size as *mut i32,
4037            tftype as *mut u32,
4038            c_name_buf,
4039        );
4040
4041        let name = CString::from_raw(c_name_buf).into_string().unwrap();
4042
4043        Some(ActiveTransformFeedback { size, tftype, name })
4044    }
4045
4046    unsafe fn memory_barrier(&self, barriers: u32) {
4047        let gl = &self.raw;
4048        gl.MemoryBarrier(barriers);
4049    }
4050
4051    unsafe fn memory_barrier_by_region(&self, barriers: u32) {
4052        let gl = &self.raw;
4053        gl.MemoryBarrierByRegion(barriers);
4054    }
4055
4056    unsafe fn bind_image_texture(
4057        &self,
4058        unit: u32,
4059        texture: Self::Texture,
4060        level: i32,
4061        layered: bool,
4062        layer: i32,
4063        access: u32,
4064        format: u32,
4065    ) {
4066        let gl = &self.raw;
4067        gl.BindImageTexture(
4068            unit,
4069            texture.0.get(),
4070            level,
4071            layered as u8,
4072            layer,
4073            access,
4074            format,
4075        );
4076    }
4077    unsafe fn get_active_uniform_block_parameter_i32(
4078        &self,
4079        program: Self::Program,
4080        uniform_block_index: u32,
4081        parameter: u32,
4082    ) -> i32 {
4083        let gl = &self.raw;
4084        let mut value = 0;
4085        gl.GetActiveUniformBlockiv(program.0.get(), uniform_block_index, parameter, &mut value);
4086        value
4087    }
4088
4089    unsafe fn get_active_uniform_block_parameter_i32_slice(
4090        &self,
4091        program: Self::Program,
4092        uniform_block_index: u32,
4093        parameter: u32,
4094        out: &mut [i32],
4095    ) {
4096        let gl = &self.raw;
4097        gl.GetActiveUniformBlockiv(
4098            program.0.get(),
4099            uniform_block_index,
4100            parameter,
4101            out.as_mut_ptr(),
4102        );
4103    }
4104    unsafe fn get_active_uniform_block_name(
4105        &self,
4106        program: Self::Program,
4107        uniform_block_index: u32,
4108    ) -> String {
4109        let gl = &self.raw;
4110
4111        // Probe for the length of the name of the uniform block, and, failing
4112        // that, fall back to allocating a buffer that is 256 bytes long. This
4113        // should be good enough for pretty much all contexts, including faulty
4114        // or partially faulty ones.
4115        let len = self.get_active_uniform_block_parameter_i32(
4116            program,
4117            uniform_block_index,
4118            crate::UNIFORM_BLOCK_NAME_LENGTH,
4119        );
4120        let len = if gl.GetError() == crate::NO_ERROR && len > 0 {
4121            len as usize
4122        } else {
4123            256
4124        };
4125
4126        let mut buffer = vec![0; len];
4127        let mut length = 0;
4128        gl.GetActiveUniformBlockName(
4129            program.0.get(),
4130            uniform_block_index,
4131            buffer.len() as _,
4132            &mut length,
4133            buffer.as_mut_ptr(),
4134        );
4135
4136        if length > 0 {
4137            assert_eq!(
4138                std::mem::size_of::<u8>(),
4139                std::mem::size_of::<native_gl::GLchar>(),
4140                "This operation is only safe in systems in which the length of \
4141                a GLchar is the same as that of an u8"
4142            );
4143            assert_eq!(
4144                std::mem::align_of::<u8>(),
4145                std::mem::align_of::<native_gl::GLchar>(),
4146                "This operation is only safe in systems in which the alignment \
4147                of a GLchar is the same as that of an u8"
4148            );
4149            let buffer = std::slice::from_raw_parts(
4150                buffer.as_ptr() as *const u8,
4151                (length as usize + 1).min(buffer.len()),
4152            );
4153
4154            let name = CStr::from_bytes_with_nul(&buffer[..])
4155                .unwrap()
4156                .to_str()
4157                .unwrap()
4158                .to_owned();
4159
4160            name
4161        } else {
4162            String::from("")
4163        }
4164    }
4165
4166    unsafe fn max_shader_compiler_threads(&self, count: u32) {
4167        let gl = &self.raw;
4168        if gl.MaxShaderCompilerThreadsKHR_is_loaded() {
4169            gl.MaxShaderCompilerThreadsKHR(count);
4170        } else {
4171            gl.MaxShaderCompilerThreadsARB(count);
4172        }
4173    }
4174}
4175
4176impl Drop for Context {
4177    fn drop(&mut self) {
4178        match self.debug_callback.take() {
4179            Some(_) => {
4180                // Unset the debug callback before destroying the context.
4181                unsafe {
4182                    let gl = &self.raw;
4183                    if gl.DebugMessageCallback_is_loaded() {
4184                        gl.DebugMessageCallback(None, std::ptr::null());
4185                    } else {
4186                        gl.DebugMessageCallbackKHR(None, std::ptr::null());
4187                    }
4188                }
4189            }
4190            None => {}
4191        }
4192    }
4193}
4194
4195extern "system" fn raw_debug_message_callback(
4196    source: u32,
4197    gltype: u32,
4198    id: u32,
4199    severity: u32,
4200    length: i32,
4201    message: *const native_gl::GLchar,
4202    user_param: *mut std::ffi::c_void,
4203) {
4204    let _result = std::panic::catch_unwind(move || unsafe {
4205        let callback: &DebugCallback = &*(user_param as *const DebugCallback);
4206        let slice = std::slice::from_raw_parts(message as *const u8, length as usize);
4207        let msg = String::from_utf8_lossy(slice);
4208        (callback)(source, gltype, id, severity, &msg);
4209    });
4210}
4211
4212#[cfg(test)]
4213mod tests {
4214    use super::*;
4215
4216    #[test]
4217    fn test_send() {
4218        fn assert_send<T: Send>() {}
4219        assert_send::<Context>();
4220    }
4221
4222    #[test]
4223    fn test_sync() {
4224        fn assert_sync<T: Sync>() {}
4225        assert_sync::<Context>();
4226    }
4227}