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