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