glow/
native.rs

1use super::*;
2use crate::{gl46 as native_gl, version::Version};
3use std::ffi::CStr;
4use std::ptr;
5use std::{collections::HashSet, ffi::CString, num::NonZeroU32};
6
7#[derive(Default)]
8struct Constants {
9    max_label_length: i32,
10}
11
12/// Store a boxed callback (i.e., `Box<Box<dyn FnMut(...)>>`) as a raw pointer, so that it can be
13/// referenced by the C API and later converted back into a `Box` and dropped.
14///
15/// We use a raw pointer here because `Box` aliasing rules are not fully defined, so we can'
16/// guarantee that it's not undefined behavior to keep a `Box` here while it's used as a raw
17/// pointer in the C API.
18struct DebugCallbackRawPtr {
19    callback: *mut std::os::raw::c_void,
20}
21
22impl Drop for DebugCallbackRawPtr {
23    fn drop(&mut self) {
24        unsafe {
25            // Convert callback back into `Box` and drop it.
26            let thin_ptr = Box::from_raw(self.callback as *mut DebugCallback);
27            let callback = *thin_ptr;
28            drop(callback);
29        }
30    }
31}
32
33pub struct Context {
34    raw: native_gl::GlFns,
35    extensions: HashSet<String>,
36    constants: Constants,
37    version: Version,
38    debug_callback: Option<DebugCallbackRawPtr>,
39}
40
41impl Context {
42    pub unsafe fn from_loader_function_cstr<F>(mut loader_function: F) -> Self
43    where
44        F: FnMut(&CStr) -> *const std::os::raw::c_void,
45    {
46        let raw: native_gl::GlFns =
47            native_gl::GlFns::load_with(|p: *const std::os::raw::c_char| {
48                let c_str = std::ffi::CStr::from_ptr(p);
49                loader_function(c_str) as *mut std::os::raw::c_void
50            });
51
52        // Retrieve and parse `GL_VERSION`
53        let raw_string = raw.GetString(VERSION);
54
55        if raw_string.is_null() {
56            panic!("Reading GL_VERSION failed. Make sure there is a valid GL context currently active.")
57        }
58
59        let raw_version = std::ffi::CStr::from_ptr(raw_string as *const native_gl::GLchar)
60            .to_str()
61            .unwrap()
62            .to_owned();
63        let version = Version::parse(&raw_version).unwrap();
64
65        // Setup extensions and constants after the context has been built
66        let mut context = Self {
67            raw,
68            extensions: HashSet::new(),
69            constants: Constants::default(),
70            version,
71            debug_callback: None,
72        };
73
74        // Use core-only functions to populate extension list
75        if (context.version >= Version::new(3, 0, None, String::from("")))
76            || (context.version >= Version::new_embedded(3, 0, String::from("")))
77        {
78            let num_extensions = context.get_parameter_i32(NUM_EXTENSIONS);
79            for i in 0..num_extensions {
80                let extension_name = context.get_parameter_indexed_string(EXTENSIONS, i as u32);
81                context.extensions.insert(extension_name);
82            }
83        } else {
84            // Fallback
85            context.extensions.extend(
86                context
87                    .get_parameter_string(EXTENSIONS)
88                    .split(' ')
89                    .map(|s| s.to_string()),
90            );
91        };
92
93        // After the extensions are known, we can populate constants (including
94        // constants that depend on extensions being enabled)
95        context.constants.max_label_length = if context.supports_debug() {
96            context.get_parameter_i32(MAX_LABEL_LENGTH)
97        } else {
98            0
99        };
100
101        context
102    }
103
104    pub unsafe fn from_loader_function<F>(mut loader_function: F) -> Self
105    where
106        F: FnMut(&str) -> *const std::os::raw::c_void,
107    {
108        Self::from_loader_function_cstr(move |name| loader_function(name.to_str().unwrap()))
109    }
110
111    /// Creates a texture from an external GL name.
112    ///
113    /// This can be useful when a texture is created outside of glow (e.g. OpenXR surface) but glow
114    /// still needs access to it for rendering.
115    #[deprecated = "Use the NativeTexture constructor instead"]
116    pub unsafe fn create_texture_from_gl_name(gl_name: native_gl::GLuint) -> NativeTexture {
117        NativeTexture(non_zero_gl_name(gl_name))
118    }
119
120    /// Creates a framebuffer from an external GL name.
121    ///
122    /// This can be useful when a framebuffer is created outside of glow (e.g: via `surfman` or another
123    /// crate that supports sharing of buffers between GL contexts), but glow needs to set it as a target.
124    #[deprecated = "Use the NativeFramebuffer constructor instead"]
125    pub unsafe fn create_framebuffer_from_gl_name(gl_name: native_gl::GLuint) -> NativeFramebuffer {
126        NativeFramebuffer(non_zero_gl_name(gl_name))
127    }
128}
129
130impl std::fmt::Debug for Context {
131    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
132        write!(f, "Native_GL_Context")
133    }
134}
135
136fn non_zero_gl_name(value: native_gl::GLuint) -> NonZeroU32 {
137    NonZeroU32::new(value as u32).expect("expected non-zero GL name")
138}
139
140#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
141pub struct NativeShader(pub NonZeroU32);
142
143#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
144pub struct NativeProgram(pub NonZeroU32);
145
146#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
147pub struct NativeBuffer(pub NonZeroU32);
148
149#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
150pub struct NativeVertexArray(pub NonZeroU32);
151
152#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
153pub struct NativeTexture(pub NonZeroU32);
154
155#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
156pub struct NativeSampler(pub NonZeroU32);
157
158#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
159pub struct NativeFence(pub native_gl::GLsync);
160
161#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
162pub struct NativeFramebuffer(pub NonZeroU32);
163
164#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
165pub struct NativeRenderbuffer(pub NonZeroU32);
166
167#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
168pub struct NativeQuery(pub NonZeroU32);
169
170#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
171pub struct NativeUniformLocation(pub native_gl::GLuint);
172
173#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
174pub struct NativeTransformFeedback(pub NonZeroU32);
175
176impl HasContext for Context {
177    type Shader = NativeShader;
178    type Program = NativeProgram;
179    type Buffer = NativeBuffer;
180    type VertexArray = NativeVertexArray;
181    type Texture = NativeTexture;
182    type Sampler = NativeSampler;
183    type Fence = NativeFence;
184    type Framebuffer = NativeFramebuffer;
185    type Renderbuffer = NativeRenderbuffer;
186    type Query = NativeQuery;
187    type UniformLocation = NativeUniformLocation;
188    type TransformFeedback = NativeTransformFeedback;
189
190    fn supported_extensions(&self) -> &HashSet<String> {
191        &self.extensions
192    }
193
194    fn supports_debug(&self) -> bool {
195        if self.extensions.contains("GL_KHR_debug") {
196            // Supports extension (either GL or GL ES)
197            true
198        } else if self.version.is_embedded {
199            // GL ES >= 3.2
200            self.version.major == 3 && self.version.minor >= 2
201        } else {
202            // GL >= 4.3
203            self.version.major == 4 && self.version.minor >= 3
204        }
205    }
206
207    fn version(&self) -> &Version {
208        &self.version
209    }
210
211    unsafe fn create_framebuffer(&self) -> Result<Self::Framebuffer, String> {
212        let gl = &self.raw;
213        let mut name = 0;
214        gl.GenFramebuffers(1, &mut name);
215        Ok(NativeFramebuffer(non_zero_gl_name(name)))
216    }
217
218    unsafe fn is_framebuffer(&self, framebuffer: Self::Framebuffer) -> bool {
219        let gl = &self.raw;
220        gl.IsFramebuffer(framebuffer.0.get()) != 0
221    }
222
223    unsafe fn create_query(&self) -> Result<Self::Query, String> {
224        let gl = &self.raw;
225        let mut name = 0;
226        gl.GenQueries(1, &mut name);
227        Ok(NativeQuery(non_zero_gl_name(name)))
228    }
229
230    unsafe fn create_renderbuffer(&self) -> Result<Self::Renderbuffer, String> {
231        let gl = &self.raw;
232        let mut name = 0;
233        gl.GenRenderbuffers(1, &mut name);
234        Ok(NativeRenderbuffer(non_zero_gl_name(name)))
235    }
236
237    unsafe fn is_renderbuffer(&self, renderbuffer: Self::Renderbuffer) -> bool {
238        let gl = &self.raw;
239        gl.IsRenderbuffer(renderbuffer.0.get()) != 0
240    }
241
242    unsafe fn create_sampler(&self) -> Result<Self::Sampler, String> {
243        let gl = &self.raw;
244        let mut name = 0;
245        gl.GenSamplers(1, &mut name);
246        Ok(NativeSampler(non_zero_gl_name(name)))
247    }
248
249    unsafe fn create_shader(&self, shader_type: u32) -> Result<Self::Shader, String> {
250        let gl = &self.raw;
251        Ok(NativeShader(non_zero_gl_name(
252            gl.CreateShader(shader_type as u32),
253        )))
254    }
255
256    unsafe fn is_shader(&self, shader: Self::Shader) -> bool {
257        let gl = &self.raw;
258        gl.IsShader(shader.0.get()) != 0
259    }
260
261    unsafe fn create_texture(&self) -> Result<Self::Texture, String> {
262        let gl = &self.raw;
263        let mut name = 0;
264        gl.GenTextures(1, &mut name);
265        Ok(NativeTexture(non_zero_gl_name(name)))
266    }
267
268    unsafe fn create_named_texture(&self, target: u32) -> Result<Self::Texture, String> {
269        let gl = &self.raw;
270        let mut name = 0;
271        gl.CreateTextures(target, 1, &mut name);
272        Ok(NativeTexture(non_zero_gl_name(name)))
273    }
274
275    unsafe fn is_texture(&self, texture: Self::Texture) -> bool {
276        let gl = &self.raw;
277        gl.IsTexture(texture.0.get()) != 0
278    }
279
280    unsafe fn delete_shader(&self, shader: Self::Shader) {
281        let gl = &self.raw;
282        gl.DeleteShader(shader.0.get());
283    }
284
285    unsafe fn shader_source(&self, shader: Self::Shader, source: &str) {
286        let gl = &self.raw;
287        gl.ShaderSource(
288            shader.0.get(),
289            1,
290            &(source.as_ptr() as *const native_gl::GLchar),
291            &(source.len() as native_gl::GLint),
292        );
293    }
294
295    unsafe fn compile_shader(&self, shader: Self::Shader) {
296        let gl = &self.raw;
297        gl.CompileShader(shader.0.get());
298    }
299
300    unsafe fn get_shader_completion_status(&self, shader: Self::Shader) -> bool {
301        let gl = &self.raw;
302        let mut status = 0;
303        gl.GetShaderiv(shader.0.get(), COMPLETION_STATUS, &mut status);
304        1 == status
305    }
306
307    unsafe fn get_shader_compile_status(&self, shader: Self::Shader) -> bool {
308        let gl = &self.raw;
309        let mut status = 0;
310        gl.GetShaderiv(shader.0.get(), COMPILE_STATUS, &mut status);
311        1 == status
312    }
313
314    unsafe fn get_shader_info_log(&self, shader: Self::Shader) -> String {
315        let gl = &self.raw;
316        let mut length = 0;
317        gl.GetShaderiv(shader.0.get(), INFO_LOG_LENGTH, &mut length);
318        if length > 0 {
319            let mut log = String::with_capacity(length as usize);
320            log.extend(std::iter::repeat('\0').take(length as usize));
321            gl.GetShaderInfoLog(
322                shader.0.get(),
323                length,
324                &mut length,
325                (&log[..]).as_ptr() as *mut native_gl::GLchar,
326            );
327            log.truncate(length as usize);
328            log
329        } else {
330            String::from("")
331        }
332    }
333
334    unsafe fn get_tex_image(
335        &self,
336        target: u32,
337        level: i32,
338        format: u32,
339        ty: u32,
340        pixels: PixelPackData,
341    ) {
342        let gl = &self.raw;
343        gl.GetTexImage(
344            target,
345            level,
346            format,
347            ty,
348            match pixels {
349                PixelPackData::BufferOffset(offset) => offset as *mut std::ffi::c_void,
350                PixelPackData::Slice(data) => data.as_mut_ptr() as *mut std::ffi::c_void,
351            },
352        );
353    }
354
355    unsafe fn create_program(&self) -> Result<Self::Program, String> {
356        let gl = &self.raw;
357        Ok(NativeProgram(non_zero_gl_name(gl.CreateProgram())))
358    }
359
360    unsafe fn is_program(&self, program: Self::Program) -> bool {
361        let gl = &self.raw;
362        gl.IsProgram(program.0.get()) != 0
363    }
364
365    unsafe fn delete_program(&self, program: Self::Program) {
366        let gl = &self.raw;
367        gl.DeleteProgram(program.0.get());
368    }
369
370    unsafe fn attach_shader(&self, program: Self::Program, shader: Self::Shader) {
371        let gl = &self.raw;
372        gl.AttachShader(program.0.get(), shader.0.get());
373    }
374
375    unsafe fn detach_shader(&self, program: Self::Program, shader: Self::Shader) {
376        let gl = &self.raw;
377        gl.DetachShader(program.0.get(), shader.0.get());
378    }
379
380    unsafe fn link_program(&self, program: Self::Program) {
381        let gl = &self.raw;
382        gl.LinkProgram(program.0.get());
383    }
384
385    unsafe fn get_program_completion_status(&self, program: Self::Program) -> bool {
386        let gl = &self.raw;
387        let mut status = 0;
388        gl.GetProgramiv(program.0.get(), COMPLETION_STATUS, &mut status);
389        1 == status
390    }
391
392    unsafe fn get_program_link_status(&self, program: Self::Program) -> bool {
393        let gl = &self.raw;
394        let mut status = 0;
395        gl.GetProgramiv(program.0.get(), LINK_STATUS, &mut status);
396        1 == status
397    }
398
399    unsafe fn get_program_info_log(&self, program: Self::Program) -> String {
400        let gl = &self.raw;
401        let mut length = 0;
402        gl.GetProgramiv(program.0.get(), INFO_LOG_LENGTH, &mut length);
403        if length > 0 {
404            let mut log = String::with_capacity(length as usize);
405            log.extend(std::iter::repeat('\0').take(length as usize));
406            gl.GetProgramInfoLog(
407                program.0.get(),
408                length,
409                &mut length,
410                (&log[..]).as_ptr() as *mut native_gl::GLchar,
411            );
412            log.truncate(length as usize);
413            log
414        } else {
415            String::from("")
416        }
417    }
418
419    unsafe fn get_program_resource_i32(
420        &self,
421        program: Self::Program,
422        interface: u32,
423        index: u32,
424        properties: &[u32],
425    ) -> Vec<i32> {
426        let gl = &self.raw;
427        // query the number of output parameters first
428        let mut length = 0i32;
429        gl.GetProgramResourceiv(
430            program.0.get(),
431            interface,
432            index,
433            properties.len() as i32,
434            properties.as_ptr(),
435            0,
436            &mut length,
437            ptr::null_mut(),
438        );
439        // get the parameter values
440        let mut params = vec![0i32; length as usize];
441        gl.GetProgramResourceiv(
442            program.0.get(),
443            interface,
444            index,
445            properties.len() as i32,
446            properties.as_ptr(),
447            length,
448            &mut length,
449            params.as_mut_ptr(),
450        );
451        params
452    }
453
454    unsafe fn get_active_uniforms(&self, program: Self::Program) -> u32 {
455        let gl = &self.raw;
456        let mut count = 0;
457        gl.GetProgramiv(program.0.get(), ACTIVE_UNIFORMS, &mut count);
458        count as u32
459    }
460
461    unsafe fn get_active_uniform(
462        &self,
463        program: Self::Program,
464        index: u32,
465    ) -> Option<ActiveUniform> {
466        let gl = &self.raw;
467        let mut uniform_max_size = 0;
468        gl.GetProgramiv(
469            program.0.get(),
470            ACTIVE_UNIFORM_MAX_LENGTH,
471            &mut uniform_max_size,
472        );
473
474        let mut name = String::with_capacity(uniform_max_size as usize);
475        name.extend(std::iter::repeat('\0').take(uniform_max_size as usize));
476        let mut length = 0;
477        let mut size = 0;
478        let mut utype = 0;
479        gl.GetActiveUniform(
480            program.0.get(),
481            index,
482            uniform_max_size,
483            &mut length,
484            &mut size,
485            &mut utype,
486            name.as_ptr() as *mut native_gl::GLchar,
487        );
488        name.truncate(length as usize);
489
490        Some(ActiveUniform { size, utype, name })
491    }
492
493    unsafe fn use_program(&self, program: Option<Self::Program>) {
494        let gl = &self.raw;
495        gl.UseProgram(program.map(|p| p.0.get()).unwrap_or(0));
496    }
497
498    unsafe fn create_buffer(&self) -> Result<Self::Buffer, String> {
499        let gl = &self.raw;
500        let mut buffer = 0;
501        gl.GenBuffers(1, &mut buffer);
502        Ok(NativeBuffer(non_zero_gl_name(buffer)))
503    }
504
505    unsafe fn create_named_buffer(&self) -> Result<Self::Buffer, String> {
506        let gl = &self.raw;
507        let mut buffer = 0;
508        gl.CreateBuffers(1, &mut buffer);
509        Ok(NativeBuffer(non_zero_gl_name(buffer)))
510    }
511
512    unsafe fn is_buffer(&self, buffer: Self::Buffer) -> bool {
513        let gl = &self.raw;
514        gl.IsBuffer(buffer.0.get()) != 0
515    }
516
517    unsafe fn bind_buffer(&self, target: u32, buffer: Option<Self::Buffer>) {
518        let gl = &self.raw;
519        gl.BindBuffer(target, buffer.map(|b| b.0.get()).unwrap_or(0));
520    }
521
522    unsafe fn bind_buffer_base(&self, target: u32, index: u32, buffer: Option<Self::Buffer>) {
523        let gl = &self.raw;
524        gl.BindBufferBase(target, index, buffer.map(|b| b.0.get()).unwrap_or(0));
525    }
526
527    unsafe fn bind_buffer_range(
528        &self,
529        target: u32,
530        index: u32,
531        buffer: Option<Self::Buffer>,
532        offset: i32,
533        size: i32,
534    ) {
535        let gl = &self.raw;
536        gl.BindBufferRange(
537            target,
538            index,
539            buffer.map(|b| b.0.get()).unwrap_or(0),
540            offset as isize,
541            size as isize,
542        );
543    }
544
545    unsafe fn bind_vertex_buffer(
546        &self,
547        binding_index: u32,
548        buffer: Option<Buffer>,
549        offset: i32,
550        stride: i32,
551    ) {
552        let gl = &self.raw;
553        gl.BindVertexBuffer(
554            binding_index,
555            buffer.map(|b| b.0.get()).unwrap_or(0),
556            offset as isize,
557            stride,
558        );
559    }
560
561    unsafe fn bind_framebuffer(&self, target: u32, framebuffer: Option<Self::Framebuffer>) {
562        let gl = &self.raw;
563        gl.BindFramebuffer(target, framebuffer.map(|fb| fb.0.get()).unwrap_or(0));
564    }
565
566    unsafe fn bind_renderbuffer(&self, target: u32, renderbuffer: Option<Self::Renderbuffer>) {
567        let gl = &self.raw;
568        gl.BindRenderbuffer(target, renderbuffer.map(|rb| rb.0.get()).unwrap_or(0));
569    }
570
571    unsafe fn blit_framebuffer(
572        &self,
573        src_x0: i32,
574        src_y0: i32,
575        src_x1: i32,
576        src_y1: i32,
577        dst_x0: i32,
578        dst_y0: i32,
579        dst_x1: i32,
580        dst_y1: i32,
581        mask: u32,
582        filter: u32,
583    ) {
584        let gl = &self.raw;
585        gl.BlitFramebuffer(
586            src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter,
587        );
588    }
589
590    unsafe fn create_vertex_array(&self) -> Result<Self::VertexArray, String> {
591        let gl = &self.raw;
592        let mut vertex_array = 0;
593        gl.GenVertexArrays(1, &mut vertex_array);
594        Ok(NativeVertexArray(non_zero_gl_name(vertex_array)))
595    }
596
597    unsafe fn delete_vertex_array(&self, vertex_array: Self::VertexArray) {
598        let gl = &self.raw;
599        gl.DeleteVertexArrays(1, &vertex_array.0.get());
600    }
601
602    unsafe fn bind_vertex_array(&self, vertex_array: Option<Self::VertexArray>) {
603        let gl = &self.raw;
604        gl.BindVertexArray(vertex_array.map(|va| va.0.get()).unwrap_or(0));
605    }
606
607    unsafe fn clear_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
608        let gl = &self.raw;
609        gl.ClearColor(red, green, blue, alpha);
610    }
611
612    unsafe fn supports_f64_precision() -> bool {
613        // TODO: Handle OpenGL ES
614        true
615    }
616
617    unsafe fn clear_depth_f64(&self, depth: f64) {
618        let gl = &self.raw;
619        gl.ClearDepth(depth);
620    }
621
622    unsafe fn clear_depth_f32(&self, depth: f32) {
623        let gl = &self.raw;
624        gl.ClearDepthf(depth);
625    }
626
627    unsafe fn clear_stencil(&self, stencil: i32) {
628        let gl = &self.raw;
629        gl.ClearStencil(stencil);
630    }
631
632    unsafe fn clear(&self, mask: u32) {
633        let gl = &self.raw;
634        gl.Clear(mask);
635    }
636
637    unsafe fn patch_parameter_i32(&self, parameter: u32, value: i32) {
638        let gl = &self.raw;
639        gl.PatchParameteri(parameter, value);
640    }
641
642    unsafe fn pixel_store_i32(&self, parameter: u32, value: i32) {
643        let gl = &self.raw;
644        gl.PixelStorei(parameter, value);
645    }
646
647    unsafe fn pixel_store_bool(&self, parameter: u32, value: bool) {
648        let gl = &self.raw;
649        gl.PixelStorei(parameter, value as i32);
650    }
651
652    unsafe fn bind_frag_data_location(
653        &self,
654        program: Self::Program,
655        color_number: u32,
656        name: &str,
657    ) {
658        let gl = &self.raw;
659        gl.BindFragDataLocation(
660            program.0.get(),
661            color_number,
662            name.as_ptr() as *const native_gl::GLchar,
663        );
664    }
665
666    unsafe fn buffer_data_size(&self, target: u32, size: i32, usage: u32) {
667        let gl = &self.raw;
668        gl.BufferData(target, size as isize, std::ptr::null(), usage);
669    }
670
671    unsafe fn buffer_data_u8_slice(&self, target: u32, data: &[u8], usage: u32) {
672        let gl = &self.raw;
673        gl.BufferData(
674            target,
675            data.len() as isize,
676            data.as_ptr() as *const std::ffi::c_void,
677            usage,
678        );
679    }
680
681    unsafe fn named_buffer_data_u8_slice(&self, buffer: Self::Buffer, data: &[u8], usage: u32) {
682        let gl = &self.raw;
683        gl.NamedBufferData(
684            buffer.0.get(),
685            data.len() as isize,
686            data.as_ptr() as *const std::ffi::c_void,
687            usage,
688        );
689    }
690
691    unsafe fn buffer_sub_data_u8_slice(&self, target: u32, offset: i32, src_data: &[u8]) {
692        let gl = &self.raw;
693        gl.BufferSubData(
694            target,
695            offset as isize,
696            src_data.len() as isize,
697            src_data.as_ptr() as *const std::ffi::c_void,
698        );
699    }
700
701    unsafe fn get_buffer_sub_data(&self, target: u32, offset: i32, dst_data: &mut [u8]) {
702        let gl = &self.raw;
703        gl.GetBufferSubData(
704            target,
705            offset as isize,
706            dst_data.len() as isize,
707            dst_data.as_mut_ptr() as *mut std::ffi::c_void,
708        );
709    }
710
711    unsafe fn buffer_storage(&self, target: u32, size: i32, data: Option<&[u8]>, flags: u32) {
712        let gl = &self.raw;
713        let size = size as isize;
714        let data = data.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void;
715        if gl.BufferStorage_is_loaded() {
716            gl.BufferStorage(target, size, data, flags);
717        } else {
718            gl.BufferStorageEXT(target, size, data, flags);
719        }
720    }
721
722    unsafe fn check_framebuffer_status(&self, target: u32) -> u32 {
723        let gl = &self.raw;
724        gl.CheckFramebufferStatus(target)
725    }
726
727    unsafe fn clear_buffer_i32_slice(&self, target: u32, draw_buffer: u32, values: &[i32]) {
728        let gl = &self.raw;
729        gl.ClearBufferiv(target, draw_buffer as i32, values.as_ptr());
730    }
731
732    unsafe fn clear_buffer_u32_slice(&self, target: u32, draw_buffer: u32, values: &[u32]) {
733        let gl = &self.raw;
734        gl.ClearBufferuiv(target, draw_buffer as i32, values.as_ptr());
735    }
736
737    unsafe fn clear_buffer_f32_slice(&self, target: u32, draw_buffer: u32, values: &[f32]) {
738        let gl = &self.raw;
739        gl.ClearBufferfv(target, draw_buffer as i32, values.as_ptr());
740    }
741
742    unsafe fn clear_buffer_depth_stencil(
743        &self,
744        target: u32,
745        draw_buffer: u32,
746        depth: f32,
747        stencil: i32,
748    ) {
749        let gl = &self.raw;
750        gl.ClearBufferfi(target, draw_buffer as i32, depth, stencil);
751    }
752
753    unsafe fn client_wait_sync(&self, fence: Self::Fence, flags: u32, timeout: i32) -> u32 {
754        let gl = &self.raw;
755        gl.ClientWaitSync(fence.0, flags, timeout as u64)
756    }
757
758    unsafe fn wait_sync(&self, fence: Self::Fence, flags: u32, timeout: u64) {
759        let gl = &self.raw;
760        gl.WaitSync(fence.0, flags, timeout)
761    }
762
763    unsafe fn copy_buffer_sub_data(
764        &self,
765        src_target: u32,
766        dst_target: u32,
767        src_offset: i32,
768        dst_offset: i32,
769        size: i32,
770    ) {
771        let gl = &self.raw;
772        gl.CopyBufferSubData(
773            src_target,
774            dst_target,
775            src_offset as isize,
776            dst_offset as isize,
777            size as isize,
778        );
779    }
780
781    unsafe fn copy_image_sub_data(
782        &self,
783        src_name: Self::Texture,
784        src_target: u32,
785        src_level: i32,
786        src_x: i32,
787        src_y: i32,
788        src_z: i32,
789        dst_name: Self::Texture,
790        dst_target: u32,
791        dst_level: i32,
792        dst_x: i32,
793        dst_y: i32,
794        dst_z: i32,
795        src_width: i32,
796        src_height: i32,
797        src_depth: i32,
798    ) {
799        let gl = &self.raw;
800        gl.CopyImageSubData(
801            src_name.0.get(),
802            src_target,
803            src_level,
804            src_x,
805            src_y,
806            src_z,
807            dst_name.0.get(),
808            dst_target,
809            dst_level,
810            dst_x,
811            dst_y,
812            dst_z,
813            src_width,
814            src_height,
815            src_depth,
816        );
817    }
818
819    unsafe fn copy_tex_image_2d(
820        &self,
821        target: u32,
822        level: i32,
823        internal_format: u32,
824        x: i32,
825        y: i32,
826        width: i32,
827        height: i32,
828        border: i32,
829    ) {
830        let gl = &self.raw;
831        gl.CopyTexImage2D(target, level, internal_format, x, y, width, height, border);
832    }
833
834    unsafe fn copy_tex_sub_image_2d(
835        &self,
836        target: u32,
837        level: i32,
838        x_offset: i32,
839        y_offset: i32,
840        x: i32,
841        y: i32,
842        width: i32,
843        height: i32,
844    ) {
845        let gl = &self.raw;
846        gl.CopyTexSubImage2D(target, level, x_offset, y_offset, x, y, width, height);
847    }
848
849    unsafe fn copy_tex_sub_image_3d(
850        &self,
851        target: u32,
852        level: i32,
853        x_offset: i32,
854        y_offset: i32,
855        z_offset: i32,
856        x: i32,
857        y: i32,
858        width: i32,
859        height: i32,
860    ) {
861        let gl = &self.raw;
862        gl.CopyTexSubImage3D(
863            target, level, x_offset, y_offset, z_offset, x, y, width, height,
864        );
865    }
866
867    unsafe fn delete_buffer(&self, buffer: Self::Buffer) {
868        let gl = &self.raw;
869        gl.DeleteBuffers(1, &buffer.0.get());
870    }
871
872    unsafe fn delete_framebuffer(&self, framebuffer: Self::Framebuffer) {
873        let gl = &self.raw;
874        gl.DeleteFramebuffers(1, &framebuffer.0.get());
875    }
876
877    unsafe fn delete_query(&self, query: Self::Query) {
878        let gl = &self.raw;
879        gl.DeleteQueries(1, &query.0.get());
880    }
881
882    unsafe fn delete_renderbuffer(&self, renderbuffer: Self::Renderbuffer) {
883        let gl = &self.raw;
884        gl.DeleteRenderbuffers(1, &renderbuffer.0.get());
885    }
886
887    unsafe fn delete_sampler(&self, sampler: Self::Sampler) {
888        let gl = &self.raw;
889        gl.DeleteSamplers(1, &sampler.0.get());
890    }
891
892    unsafe fn delete_sync(&self, fence: Self::Fence) {
893        let gl = &self.raw;
894        gl.DeleteSync(fence.0);
895    }
896
897    unsafe fn delete_texture(&self, texture: Self::Texture) {
898        let gl = &self.raw;
899        gl.DeleteTextures(1, &texture.0.get());
900    }
901
902    unsafe fn disable(&self, parameter: u32) {
903        let gl = &self.raw;
904        gl.Disable(parameter);
905    }
906
907    unsafe fn disable_draw_buffer(&self, parameter: u32, draw_buffer: u32) {
908        let gl = &self.raw;
909        gl.Disablei(parameter, draw_buffer);
910    }
911
912    unsafe fn disable_vertex_attrib_array(&self, index: u32) {
913        let gl = &self.raw;
914        gl.DisableVertexAttribArray(index);
915    }
916
917    unsafe fn dispatch_compute(&self, groups_x: u32, groups_y: u32, groups_z: u32) {
918        let gl = &self.raw;
919        gl.DispatchCompute(groups_x, groups_y, groups_z);
920    }
921
922    unsafe fn dispatch_compute_indirect(&self, offset: i32) {
923        let gl = &self.raw;
924        gl.DispatchComputeIndirect(offset as isize);
925    }
926
927    unsafe fn draw_arrays(&self, mode: u32, first: i32, count: i32) {
928        let gl = &self.raw;
929        gl.DrawArrays(mode as u32, first, count);
930    }
931
932    unsafe fn draw_arrays_instanced(&self, mode: u32, first: i32, count: i32, instance_count: i32) {
933        let gl = &self.raw;
934        gl.DrawArraysInstanced(mode as u32, first, count, instance_count);
935    }
936
937    unsafe fn draw_arrays_instanced_base_instance(
938        &self,
939        mode: u32,
940        first: i32,
941        count: i32,
942        instance_count: i32,
943        base_instance: u32,
944    ) {
945        let gl = &self.raw;
946        gl.DrawArraysInstancedBaseInstance(
947            mode as u32,
948            first,
949            count,
950            instance_count,
951            base_instance,
952        );
953    }
954
955    unsafe fn draw_arrays_indirect_offset(&self, mode: u32, offset: i32) {
956        let gl = &self.raw;
957        gl.DrawArraysIndirect(mode, offset as *const std::ffi::c_void);
958    }
959
960    unsafe fn draw_buffer(&self, draw_buffer: u32) {
961        let gl = &self.raw;
962        gl.DrawBuffer(draw_buffer);
963    }
964
965    unsafe fn draw_buffers(&self, buffers: &[u32]) {
966        let gl = &self.raw;
967        gl.DrawBuffers(buffers.len() as i32, buffers.as_ptr());
968    }
969
970    unsafe fn draw_elements(&self, mode: u32, count: i32, element_type: u32, offset: i32) {
971        let gl = &self.raw;
972        gl.DrawElements(
973            mode as u32,
974            count,
975            element_type as u32,
976            offset as *const std::ffi::c_void,
977        );
978    }
979
980    unsafe fn draw_elements_base_vertex(
981        &self,
982        mode: u32,
983        count: i32,
984        element_type: u32,
985        offset: i32,
986        base_vertex: i32,
987    ) {
988        let gl = &self.raw;
989        gl.DrawElementsBaseVertex(
990            mode as u32,
991            count,
992            element_type as u32,
993            offset as *const std::ffi::c_void,
994            base_vertex,
995        );
996    }
997
998    unsafe fn draw_elements_instanced(
999        &self,
1000        mode: u32,
1001        count: i32,
1002        element_type: u32,
1003        offset: i32,
1004        instance_count: i32,
1005    ) {
1006        let gl = &self.raw;
1007        gl.DrawElementsInstanced(
1008            mode as u32,
1009            count,
1010            element_type as u32,
1011            offset as *const std::ffi::c_void,
1012            instance_count,
1013        );
1014    }
1015
1016    unsafe fn draw_elements_instanced_base_vertex(
1017        &self,
1018        mode: u32,
1019        count: i32,
1020        element_type: u32,
1021        offset: i32,
1022        instance_count: i32,
1023        base_vertex: i32,
1024    ) {
1025        let gl = &self.raw;
1026        gl.DrawElementsInstancedBaseVertex(
1027            mode as u32,
1028            count,
1029            element_type as u32,
1030            offset as *const std::ffi::c_void,
1031            instance_count,
1032            base_vertex,
1033        );
1034    }
1035
1036    unsafe fn draw_elements_instanced_base_vertex_base_instance(
1037        &self,
1038        mode: u32,
1039        count: i32,
1040        element_type: u32,
1041        offset: i32,
1042        instance_count: i32,
1043        base_vertex: i32,
1044        base_instance: u32,
1045    ) {
1046        let gl = &self.raw;
1047        gl.DrawElementsInstancedBaseVertexBaseInstance(
1048            mode as u32,
1049            count,
1050            element_type as u32,
1051            offset as *const std::ffi::c_void,
1052            instance_count,
1053            base_vertex,
1054            base_instance,
1055        );
1056    }
1057
1058    unsafe fn draw_elements_indirect_offset(&self, mode: u32, element_type: u32, offset: i32) {
1059        let gl = &self.raw;
1060        gl.DrawElementsIndirect(mode, element_type, offset as *const std::ffi::c_void);
1061    }
1062
1063    unsafe fn enable(&self, parameter: u32) {
1064        let gl = &self.raw;
1065        gl.Enable(parameter);
1066    }
1067
1068    unsafe fn is_enabled(&self, parameter: u32) -> bool {
1069        let gl = &self.raw;
1070        gl.IsEnabled(parameter) != 0
1071    }
1072
1073    unsafe fn enable_draw_buffer(&self, parameter: u32, draw_buffer: u32) {
1074        let gl = &self.raw;
1075        gl.Enablei(parameter, draw_buffer);
1076    }
1077
1078    unsafe fn enable_vertex_array_attrib(&self, vao: Self::VertexArray, index: u32) {
1079        let gl = &self.raw;
1080        gl.EnableVertexArrayAttrib(vao.0.get(), index);
1081    }
1082
1083    unsafe fn enable_vertex_attrib_array(&self, index: u32) {
1084        let gl = &self.raw;
1085        gl.EnableVertexAttribArray(index);
1086    }
1087
1088    unsafe fn flush(&self) {
1089        let gl = &self.raw;
1090        gl.Flush();
1091    }
1092
1093    unsafe fn framebuffer_renderbuffer(
1094        &self,
1095        target: u32,
1096        attachment: u32,
1097        renderbuffer_target: u32,
1098        renderbuffer: Option<Self::Renderbuffer>,
1099    ) {
1100        let gl = &self.raw;
1101        gl.FramebufferRenderbuffer(
1102            target,
1103            attachment,
1104            renderbuffer_target,
1105            renderbuffer.map(|rb| rb.0.get()).unwrap_or(0),
1106        );
1107    }
1108
1109    unsafe fn framebuffer_texture(
1110        &self,
1111        target: u32,
1112        attachment: u32,
1113        texture: Option<Self::Texture>,
1114        level: i32,
1115    ) {
1116        let gl = &self.raw;
1117        gl.FramebufferTexture(
1118            target,
1119            attachment,
1120            texture.map(|t| t.0.get()).unwrap_or(0),
1121            level,
1122        );
1123    }
1124
1125    unsafe fn framebuffer_texture_2d(
1126        &self,
1127        target: u32,
1128        attachment: u32,
1129        texture_target: u32,
1130        texture: Option<Self::Texture>,
1131        level: i32,
1132    ) {
1133        let gl = &self.raw;
1134        gl.FramebufferTexture2D(
1135            target,
1136            attachment,
1137            texture_target,
1138            texture.map(|t| t.0.get()).unwrap_or(0),
1139            level,
1140        );
1141    }
1142
1143    unsafe fn framebuffer_texture_3d(
1144        &self,
1145        target: u32,
1146        attachment: u32,
1147        texture_target: u32,
1148        texture: Option<Self::Texture>,
1149        level: i32,
1150        layer: i32,
1151    ) {
1152        let gl = &self.raw;
1153        gl.FramebufferTexture3D(
1154            target,
1155            attachment,
1156            texture_target,
1157            texture.map(|t| t.0.get()).unwrap_or(0),
1158            level,
1159            layer,
1160        );
1161    }
1162
1163    unsafe fn framebuffer_texture_layer(
1164        &self,
1165        target: u32,
1166        attachment: u32,
1167        texture: Option<Self::Texture>,
1168        level: i32,
1169        layer: i32,
1170    ) {
1171        let gl = &self.raw;
1172        gl.FramebufferTextureLayer(
1173            target,
1174            attachment,
1175            texture.map(|t| t.0.get()).unwrap_or(0),
1176            level,
1177            layer,
1178        );
1179    }
1180
1181    unsafe fn front_face(&self, value: u32) {
1182        let gl = &self.raw;
1183        gl.FrontFace(value as u32);
1184    }
1185
1186    unsafe fn get_error(&self) -> u32 {
1187        let gl = &self.raw;
1188        gl.GetError()
1189    }
1190
1191    unsafe fn get_tex_parameter_i32(&self, target: u32, parameter: u32) -> i32 {
1192        let gl = &self.raw;
1193        let mut value = 0;
1194        gl.GetTexParameteriv(target, parameter, &mut value);
1195        value
1196    }
1197
1198    unsafe fn get_buffer_parameter_i32(&self, target: u32, parameter: u32) -> i32 {
1199        let gl = &self.raw;
1200        let mut value = 0;
1201        gl.GetBufferParameteriv(target, parameter, &mut value);
1202        value
1203    }
1204
1205    unsafe fn get_parameter_i32(&self, parameter: u32) -> i32 {
1206        let gl = &self.raw;
1207        let mut value = 0;
1208        gl.GetIntegerv(parameter, &mut value);
1209        value
1210    }
1211
1212    unsafe fn get_parameter_i32_slice(&self, parameter: u32, out: &mut [i32]) {
1213        let gl = &self.raw;
1214        gl.GetIntegerv(parameter, &mut out[0]);
1215    }
1216
1217    unsafe fn get_parameter_f32(&self, parameter: u32) -> f32 {
1218        let gl = &self.raw;
1219        let mut value: f32 = 0.0;
1220        gl.GetFloatv(parameter, &mut value);
1221        value
1222    }
1223
1224    unsafe fn get_parameter_f32_slice(&self, parameter: u32, out: &mut [f32]) {
1225        let gl = &self.raw;
1226        gl.GetFloatv(parameter, &mut out[0]);
1227    }
1228
1229    unsafe fn get_parameter_indexed_i32(&self, parameter: u32, index: u32) -> i32 {
1230        let gl = &self.raw;
1231        let mut value = 0;
1232        gl.GetIntegeri_v(parameter, index, &mut value);
1233        value
1234    }
1235
1236    unsafe fn get_parameter_indexed_string(&self, parameter: u32, index: u32) -> String {
1237        let gl = &self.raw;
1238        let raw_ptr = gl.GetStringi(parameter, index);
1239        std::ffi::CStr::from_ptr(raw_ptr as *const native_gl::GLchar)
1240            .to_str()
1241            .unwrap()
1242            .to_owned()
1243    }
1244
1245    unsafe fn get_parameter_string(&self, parameter: u32) -> String {
1246        let gl = &self.raw;
1247        let raw_ptr = gl.GetString(parameter);
1248        if raw_ptr.is_null() {
1249            panic!(
1250                "Get parameter string 0x{:X} failed. Maybe your GL context version is too outdated.",
1251                parameter
1252            )
1253        }
1254        std::ffi::CStr::from_ptr(raw_ptr as *const native_gl::GLchar)
1255            .to_str()
1256            .unwrap()
1257            .to_owned()
1258    }
1259
1260    unsafe fn get_uniform_location(
1261        &self,
1262        program: Self::Program,
1263        name: &str,
1264    ) -> Option<Self::UniformLocation> {
1265        let gl = &self.raw;
1266        let name = CString::new(name).unwrap();
1267        let uniform_location =
1268            gl.GetUniformLocation(program.0.get(), name.as_ptr() as *const native_gl::GLchar);
1269        if uniform_location < 0 {
1270            None
1271        } else {
1272            Some(NativeUniformLocation(uniform_location as u32))
1273        }
1274    }
1275
1276    unsafe fn get_attrib_location(&self, program: Self::Program, name: &str) -> Option<u32> {
1277        let gl = &self.raw;
1278        let name = CString::new(name).unwrap();
1279        let attrib_location =
1280            gl.GetAttribLocation(program.0.get(), name.as_ptr() as *const native_gl::GLchar);
1281        if attrib_location < 0 {
1282            None
1283        } else {
1284            Some(attrib_location as u32)
1285        }
1286    }
1287
1288    unsafe fn bind_attrib_location(&self, program: Self::Program, index: u32, name: &str) {
1289        let gl = &self.raw;
1290        let name = CString::new(name).unwrap();
1291        gl.BindAttribLocation(
1292            program.0.get(),
1293            index,
1294            name.as_ptr() as *const native_gl::GLchar,
1295        );
1296    }
1297
1298    unsafe fn get_active_attributes(&self, program: Self::Program) -> u32 {
1299        let gl = &self.raw;
1300        let mut count = 0;
1301        gl.GetProgramiv(program.0.get(), ACTIVE_ATTRIBUTES, &mut count);
1302        count as u32
1303    }
1304
1305    unsafe fn get_active_attribute(
1306        &self,
1307        program: Self::Program,
1308        index: u32,
1309    ) -> Option<ActiveAttribute> {
1310        let gl = &self.raw;
1311        let mut attribute_max_size = 0;
1312        gl.GetProgramiv(
1313            program.0.get(),
1314            ACTIVE_ATTRIBUTE_MAX_LENGTH,
1315            &mut attribute_max_size,
1316        );
1317        let mut name = String::with_capacity(attribute_max_size as usize);
1318        name.extend(std::iter::repeat('\0').take(attribute_max_size as usize));
1319        let mut length = 0;
1320        let mut size = 0;
1321        let mut atype = 0;
1322        gl.GetActiveAttrib(
1323            program.0.get(),
1324            index,
1325            attribute_max_size,
1326            &mut length,
1327            &mut size,
1328            &mut atype,
1329            name.as_ptr() as *mut native_gl::GLchar,
1330        );
1331
1332        name.truncate(length as usize);
1333
1334        Some(ActiveAttribute { name, size, atype })
1335    }
1336
1337    unsafe fn get_sync_status(&self, fence: Self::Fence) -> u32 {
1338        let gl = &self.raw;
1339        let mut len = 0;
1340        let mut values = [UNSIGNALED as i32];
1341        gl.GetSynciv(
1342            fence.0,
1343            SYNC_STATUS,
1344            values.len() as i32,
1345            &mut len,
1346            values.as_mut_ptr(),
1347        );
1348        values[0] as u32
1349    }
1350
1351    unsafe fn is_sync(&self, fence: Self::Fence) -> bool {
1352        let gl = &self.raw;
1353        1 == gl.IsSync(fence.0)
1354    }
1355
1356    unsafe fn renderbuffer_storage(
1357        &self,
1358        target: u32,
1359        internal_format: u32,
1360        width: i32,
1361        height: i32,
1362    ) {
1363        let gl = &self.raw;
1364        gl.RenderbufferStorage(target, internal_format, width, height);
1365    }
1366
1367    unsafe fn renderbuffer_storage_multisample(
1368        &self,
1369        target: u32,
1370        samples: i32,
1371        internal_format: u32,
1372        width: i32,
1373        height: i32,
1374    ) {
1375        let gl = &self.raw;
1376        gl.RenderbufferStorageMultisample(target, samples, internal_format, width, height);
1377    }
1378
1379    unsafe fn sampler_parameter_f32(&self, sampler: Self::Sampler, name: u32, value: f32) {
1380        let gl = &self.raw;
1381        gl.SamplerParameterf(sampler.0.get(), name, value);
1382    }
1383
1384    unsafe fn sampler_parameter_f32_slice(&self, sampler: Self::Sampler, name: u32, value: &[f32]) {
1385        let gl = &self.raw;
1386        gl.SamplerParameterfv(sampler.0.get(), name, value.as_ptr());
1387    }
1388
1389    unsafe fn sampler_parameter_i32(&self, sampler: Self::Sampler, name: u32, value: i32) {
1390        let gl = &self.raw;
1391        gl.SamplerParameteri(sampler.0.get(), name, value);
1392    }
1393
1394    unsafe fn generate_mipmap(&self, target: u32) {
1395        let gl = &self.raw;
1396        gl.GenerateMipmap(target);
1397    }
1398
1399    unsafe fn generate_texture_mipmap(&self, texture: Self::Texture) {
1400        let gl = &self.raw;
1401        gl.GenerateTextureMipmap(texture.0.get());
1402    }
1403
1404    unsafe fn tex_image_1d(
1405        &self,
1406        target: u32,
1407        level: i32,
1408        internal_format: i32,
1409        width: i32,
1410        border: i32,
1411        format: u32,
1412        ty: u32,
1413        pixels: Option<&[u8]>,
1414    ) {
1415        let gl = &self.raw;
1416        gl.TexImage1D(
1417            target,
1418            level,
1419            internal_format,
1420            width,
1421            border,
1422            format,
1423            ty,
1424            pixels.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void,
1425        );
1426    }
1427
1428    unsafe fn compressed_tex_image_1d(
1429        &self,
1430        target: u32,
1431        level: i32,
1432        internal_format: i32,
1433        width: i32,
1434        border: i32,
1435        image_size: i32,
1436        pixels: &[u8],
1437    ) {
1438        let gl = &self.raw;
1439        gl.CompressedTexImage1D(
1440            target,
1441            level,
1442            internal_format as u32,
1443            width,
1444            border,
1445            image_size,
1446            pixels.as_ptr() as *const std::ffi::c_void,
1447        );
1448    }
1449
1450    unsafe fn tex_image_2d(
1451        &self,
1452        target: u32,
1453        level: i32,
1454        internal_format: i32,
1455        width: i32,
1456        height: i32,
1457        border: i32,
1458        format: u32,
1459        ty: u32,
1460        pixels: Option<&[u8]>,
1461    ) {
1462        let gl = &self.raw;
1463        gl.TexImage2D(
1464            target,
1465            level,
1466            internal_format,
1467            width,
1468            height,
1469            border,
1470            format,
1471            ty,
1472            pixels.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void,
1473        );
1474    }
1475
1476    unsafe fn tex_image_2d_multisample(
1477        &self,
1478        target: u32,
1479        samples: i32,
1480        internal_format: i32,
1481        width: i32,
1482        height: i32,
1483        fixed_sample_locations: bool,
1484    ) {
1485        let gl = &self.raw;
1486        gl.TexImage2DMultisample(
1487            target,
1488            samples,
1489            internal_format as u32,
1490            width,
1491            height,
1492            if fixed_sample_locations { 1 } else { 0 },
1493        );
1494    }
1495
1496    unsafe fn compressed_tex_image_2d(
1497        &self,
1498        target: u32,
1499        level: i32,
1500        internal_format: i32,
1501        width: i32,
1502        height: i32,
1503        border: i32,
1504        image_size: i32,
1505        pixels: &[u8],
1506    ) {
1507        let gl = &self.raw;
1508        gl.CompressedTexImage2D(
1509            target,
1510            level,
1511            internal_format as u32,
1512            width,
1513            height,
1514            border,
1515            image_size,
1516            pixels.as_ptr() as *const std::ffi::c_void,
1517        );
1518    }
1519
1520    unsafe fn tex_image_3d(
1521        &self,
1522        target: u32,
1523        level: i32,
1524        internal_format: i32,
1525        width: i32,
1526        height: i32,
1527        depth: i32,
1528        border: i32,
1529        format: u32,
1530        ty: u32,
1531        pixels: Option<&[u8]>,
1532    ) {
1533        let gl = &self.raw;
1534        gl.TexImage3D(
1535            target,
1536            level,
1537            internal_format,
1538            width,
1539            height,
1540            depth,
1541            border,
1542            format,
1543            ty,
1544            pixels.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void,
1545        );
1546    }
1547
1548    unsafe fn compressed_tex_image_3d(
1549        &self,
1550        target: u32,
1551        level: i32,
1552        internal_format: i32,
1553        width: i32,
1554        height: i32,
1555        depth: i32,
1556        border: i32,
1557        image_size: i32,
1558        pixels: &[u8],
1559    ) {
1560        let gl = &self.raw;
1561        gl.CompressedTexImage3D(
1562            target,
1563            level,
1564            internal_format as u32,
1565            width,
1566            height,
1567            depth,
1568            border,
1569            image_size,
1570            pixels.as_ptr() as *const std::ffi::c_void,
1571        );
1572    }
1573
1574    unsafe fn tex_storage_1d(&self, target: u32, levels: i32, internal_format: u32, width: i32) {
1575        let gl = &self.raw;
1576        gl.TexStorage1D(target, levels, internal_format, width);
1577    }
1578
1579    unsafe fn tex_storage_2d(
1580        &self,
1581        target: u32,
1582        levels: i32,
1583        internal_format: u32,
1584        width: i32,
1585        height: i32,
1586    ) {
1587        let gl = &self.raw;
1588        gl.TexStorage2D(target, levels, internal_format, width, height);
1589    }
1590
1591    unsafe fn tex_storage_2d_multisample(
1592        &self,
1593        target: u32,
1594        samples: i32,
1595        internal_format: u32,
1596        width: i32,
1597        height: i32,
1598        fixed_sample_locations: bool,
1599    ) {
1600        let gl = &self.raw;
1601        gl.TexStorage2DMultisample(
1602            target,
1603            samples,
1604            internal_format,
1605            width,
1606            height,
1607            if fixed_sample_locations { 1 } else { 0 },
1608        );
1609    }
1610
1611    unsafe fn tex_storage_3d(
1612        &self,
1613        target: u32,
1614        levels: i32,
1615        internal_format: u32,
1616        width: i32,
1617        height: i32,
1618        depth: i32,
1619    ) {
1620        let gl = &self.raw;
1621        gl.TexStorage3D(target, levels, internal_format, width, height, depth);
1622    }
1623
1624    unsafe fn texture_storage_3d(
1625        &self,
1626        texture: Self::Texture,
1627        levels: i32,
1628        internal_format: u32,
1629        width: i32,
1630        height: i32,
1631        depth: i32,
1632    ) {
1633        let gl = &self.raw;
1634        gl.TextureStorage3D(
1635            texture.0.get(),
1636            levels,
1637            internal_format,
1638            width,
1639            height,
1640            depth,
1641        );
1642    }
1643
1644    unsafe fn get_uniform_i32(
1645        &self,
1646        program: Self::Program,
1647        location: &Self::UniformLocation,
1648        v: &mut [i32],
1649    ) {
1650        let gl = &self.raw;
1651        gl.GetUniformiv(
1652            program.0.get() as u32,
1653            location.0 as i32,
1654            v.as_mut_ptr() as *mut i32,
1655        )
1656    }
1657
1658    unsafe fn get_uniform_f32(
1659        &self,
1660        program: Self::Program,
1661        location: &Self::UniformLocation,
1662        v: &mut [f32],
1663    ) {
1664        let gl = &self.raw;
1665        gl.GetUniformfv(
1666            program.0.get() as u32,
1667            location.0 as i32,
1668            v.as_mut_ptr() as *mut f32,
1669        )
1670    }
1671
1672    unsafe fn uniform_1_i32(&self, location: Option<&Self::UniformLocation>, x: i32) {
1673        let gl = &self.raw;
1674        if let Some(loc) = location {
1675            gl.Uniform1i(loc.0 as i32, x);
1676        }
1677    }
1678
1679    unsafe fn uniform_2_i32(&self, location: Option<&Self::UniformLocation>, x: i32, y: i32) {
1680        let gl = &self.raw;
1681        if let Some(loc) = location {
1682            gl.Uniform2i(loc.0 as i32, x, y);
1683        }
1684    }
1685
1686    unsafe fn uniform_3_i32(
1687        &self,
1688        location: Option<&Self::UniformLocation>,
1689        x: i32,
1690        y: i32,
1691        z: i32,
1692    ) {
1693        let gl = &self.raw;
1694        if let Some(loc) = location {
1695            gl.Uniform3i(loc.0 as i32, x, y, z);
1696        }
1697    }
1698
1699    unsafe fn uniform_4_i32(
1700        &self,
1701        location: Option<&Self::UniformLocation>,
1702        x: i32,
1703        y: i32,
1704        z: i32,
1705        w: i32,
1706    ) {
1707        let gl = &self.raw;
1708        if let Some(loc) = location {
1709            gl.Uniform4i(loc.0 as i32, x, y, z, w);
1710        }
1711    }
1712
1713    unsafe fn uniform_1_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
1714        let gl = &self.raw;
1715        if let Some(loc) = location {
1716            gl.Uniform1iv(loc.0 as i32, v.len() as i32, v.as_ptr());
1717        }
1718    }
1719
1720    unsafe fn uniform_2_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
1721        let gl = &self.raw;
1722        if let Some(loc) = location {
1723            gl.Uniform2iv(loc.0 as i32, v.len() as i32 / 2, v.as_ptr());
1724        }
1725    }
1726
1727    unsafe fn uniform_3_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
1728        let gl = &self.raw;
1729        if let Some(loc) = location {
1730            gl.Uniform3iv(loc.0 as i32, v.len() as i32 / 3, v.as_ptr());
1731        }
1732    }
1733
1734    unsafe fn uniform_4_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
1735        let gl = &self.raw;
1736        if let Some(loc) = location {
1737            gl.Uniform4iv(loc.0 as i32, v.len() as i32 / 4, v.as_ptr());
1738        }
1739    }
1740
1741    unsafe fn uniform_1_u32(&self, location: Option<&Self::UniformLocation>, x: u32) {
1742        let gl = &self.raw;
1743        if let Some(loc) = location {
1744            gl.Uniform1ui(loc.0 as i32, x);
1745        }
1746    }
1747
1748    unsafe fn uniform_2_u32(&self, location: Option<&Self::UniformLocation>, x: u32, y: u32) {
1749        let gl = &self.raw;
1750        if let Some(loc) = location {
1751            gl.Uniform2ui(loc.0 as i32, x, y);
1752        }
1753    }
1754
1755    unsafe fn uniform_3_u32(
1756        &self,
1757        location: Option<&Self::UniformLocation>,
1758        x: u32,
1759        y: u32,
1760        z: u32,
1761    ) {
1762        let gl = &self.raw;
1763        if let Some(loc) = location {
1764            gl.Uniform3ui(loc.0 as i32, x, y, z);
1765        }
1766    }
1767
1768    unsafe fn uniform_4_u32(
1769        &self,
1770        location: Option<&Self::UniformLocation>,
1771        x: u32,
1772        y: u32,
1773        z: u32,
1774        w: u32,
1775    ) {
1776        let gl = &self.raw;
1777        if let Some(loc) = location {
1778            gl.Uniform4ui(loc.0 as i32, x, y, z, w);
1779        }
1780    }
1781
1782    unsafe fn uniform_1_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
1783        let gl = &self.raw;
1784        if let Some(loc) = location {
1785            gl.Uniform1uiv(loc.0 as i32, v.len() as i32, v.as_ptr());
1786        }
1787    }
1788
1789    unsafe fn uniform_2_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
1790        let gl = &self.raw;
1791        if let Some(loc) = location {
1792            gl.Uniform2uiv(loc.0 as i32, v.len() as i32 / 2, v.as_ptr());
1793        }
1794    }
1795
1796    unsafe fn uniform_3_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
1797        let gl = &self.raw;
1798        if let Some(loc) = location {
1799            gl.Uniform3uiv(loc.0 as i32, v.len() as i32 / 3, v.as_ptr());
1800        }
1801    }
1802
1803    unsafe fn uniform_4_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
1804        let gl = &self.raw;
1805        if let Some(loc) = location {
1806            gl.Uniform4uiv(loc.0 as i32, v.len() as i32 / 4, v.as_ptr());
1807        }
1808    }
1809
1810    unsafe fn uniform_1_f32(&self, location: Option<&Self::UniformLocation>, x: f32) {
1811        let gl = &self.raw;
1812        if let Some(loc) = location {
1813            gl.Uniform1f(loc.0 as i32, x);
1814        }
1815    }
1816
1817    unsafe fn uniform_2_f32(&self, location: Option<&Self::UniformLocation>, x: f32, y: f32) {
1818        let gl = &self.raw;
1819        if let Some(loc) = location {
1820            gl.Uniform2f(loc.0 as i32, x, y);
1821        }
1822    }
1823
1824    unsafe fn uniform_3_f32(
1825        &self,
1826        location: Option<&Self::UniformLocation>,
1827        x: f32,
1828        y: f32,
1829        z: f32,
1830    ) {
1831        let gl = &self.raw;
1832        if let Some(loc) = location {
1833            gl.Uniform3f(loc.0 as i32, x, y, z);
1834        }
1835    }
1836
1837    unsafe fn uniform_4_f32(
1838        &self,
1839        location: Option<&Self::UniformLocation>,
1840        x: f32,
1841        y: f32,
1842        z: f32,
1843        w: f32,
1844    ) {
1845        let gl = &self.raw;
1846        if let Some(loc) = location {
1847            gl.Uniform4f(loc.0 as i32, x, y, z, w);
1848        }
1849    }
1850
1851    unsafe fn uniform_1_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
1852        let gl = &self.raw;
1853        if let Some(loc) = location {
1854            gl.Uniform1fv(loc.0 as i32, v.len() as i32, v.as_ptr());
1855        }
1856    }
1857
1858    unsafe fn uniform_2_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
1859        let gl = &self.raw;
1860        if let Some(loc) = location {
1861            gl.Uniform2fv(loc.0 as i32, v.len() as i32 / 2, v.as_ptr());
1862        }
1863    }
1864
1865    unsafe fn uniform_3_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
1866        let gl = &self.raw;
1867        if let Some(loc) = location {
1868            gl.Uniform3fv(loc.0 as i32, v.len() as i32 / 3, v.as_ptr());
1869        }
1870    }
1871
1872    unsafe fn uniform_4_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
1873        let gl = &self.raw;
1874        if let Some(loc) = location {
1875            gl.Uniform4fv(loc.0 as i32, v.len() as i32 / 4, v.as_ptr());
1876        }
1877    }
1878
1879    unsafe fn uniform_matrix_2_f32_slice(
1880        &self,
1881        location: Option<&Self::UniformLocation>,
1882        transpose: bool,
1883        v: &[f32],
1884    ) {
1885        let gl = &self.raw;
1886        if let Some(loc) = location {
1887            gl.UniformMatrix2fv(
1888                loc.0 as i32,
1889                v.len() as i32 / 4,
1890                transpose as u8,
1891                v.as_ptr(),
1892            );
1893        }
1894    }
1895
1896    unsafe fn uniform_matrix_2x3_f32_slice(
1897        &self,
1898        location: Option<&Self::UniformLocation>,
1899        transpose: bool,
1900        v: &[f32],
1901    ) {
1902        let gl = &self.raw;
1903        if let Some(loc) = location {
1904            gl.UniformMatrix2x3fv(
1905                loc.0 as i32,
1906                v.len() as i32 / 6,
1907                transpose as u8,
1908                v.as_ptr(),
1909            );
1910        }
1911    }
1912
1913    unsafe fn uniform_matrix_2x4_f32_slice(
1914        &self,
1915        location: Option<&Self::UniformLocation>,
1916        transpose: bool,
1917        v: &[f32],
1918    ) {
1919        let gl = &self.raw;
1920        if let Some(loc) = location {
1921            gl.UniformMatrix2x4fv(
1922                loc.0 as i32,
1923                v.len() as i32 / 8,
1924                transpose as u8,
1925                v.as_ptr(),
1926            );
1927        }
1928    }
1929
1930    unsafe fn uniform_matrix_3x2_f32_slice(
1931        &self,
1932        location: Option<&Self::UniformLocation>,
1933        transpose: bool,
1934        v: &[f32],
1935    ) {
1936        let gl = &self.raw;
1937        if let Some(loc) = location {
1938            gl.UniformMatrix3x2fv(
1939                loc.0 as i32,
1940                v.len() as i32 / 6,
1941                transpose as u8,
1942                v.as_ptr(),
1943            );
1944        }
1945    }
1946
1947    unsafe fn uniform_matrix_3_f32_slice(
1948        &self,
1949        location: Option<&Self::UniformLocation>,
1950        transpose: bool,
1951        v: &[f32],
1952    ) {
1953        let gl = &self.raw;
1954        if let Some(loc) = location {
1955            gl.UniformMatrix3fv(
1956                loc.0 as i32,
1957                v.len() as i32 / 9,
1958                transpose as u8,
1959                v.as_ptr(),
1960            );
1961        }
1962    }
1963
1964    unsafe fn uniform_matrix_3x4_f32_slice(
1965        &self,
1966        location: Option<&Self::UniformLocation>,
1967        transpose: bool,
1968        v: &[f32],
1969    ) {
1970        let gl = &self.raw;
1971        if let Some(loc) = location {
1972            gl.UniformMatrix3x4fv(
1973                loc.0 as i32,
1974                v.len() as i32 / 12,
1975                transpose as u8,
1976                v.as_ptr(),
1977            );
1978        }
1979    }
1980
1981    unsafe fn uniform_matrix_4x2_f32_slice(
1982        &self,
1983        location: Option<&Self::UniformLocation>,
1984        transpose: bool,
1985        v: &[f32],
1986    ) {
1987        let gl = &self.raw;
1988        if let Some(loc) = location {
1989            gl.UniformMatrix4x2fv(
1990                loc.0 as i32,
1991                v.len() as i32 / 8,
1992                transpose as u8,
1993                v.as_ptr(),
1994            );
1995        }
1996    }
1997
1998    unsafe fn uniform_matrix_4x3_f32_slice(
1999        &self,
2000        location: Option<&Self::UniformLocation>,
2001        transpose: bool,
2002        v: &[f32],
2003    ) {
2004        let gl = &self.raw;
2005        if let Some(loc) = location {
2006            gl.UniformMatrix4x3fv(
2007                loc.0 as i32,
2008                v.len() as i32 / 12,
2009                transpose as u8,
2010                v.as_ptr(),
2011            );
2012        }
2013    }
2014
2015    unsafe fn uniform_matrix_4_f32_slice(
2016        &self,
2017        location: Option<&Self::UniformLocation>,
2018        transpose: bool,
2019        v: &[f32],
2020    ) {
2021        let gl = &self.raw;
2022        if let Some(loc) = location {
2023            gl.UniformMatrix4fv(
2024                loc.0 as i32,
2025                v.len() as i32 / 16,
2026                transpose as u8,
2027                v.as_ptr(),
2028            );
2029        }
2030    }
2031
2032    unsafe fn unmap_buffer(&self, target: u32) {
2033        let gl = &self.raw;
2034        gl.UnmapBuffer(target);
2035    }
2036
2037    unsafe fn cull_face(&self, value: u32) {
2038        let gl = &self.raw;
2039        gl.CullFace(value as u32);
2040    }
2041
2042    unsafe fn color_mask(&self, red: bool, green: bool, blue: bool, alpha: bool) {
2043        let gl = &self.raw;
2044        gl.ColorMask(red as u8, green as u8, blue as u8, alpha as u8);
2045    }
2046
2047    unsafe fn color_mask_draw_buffer(
2048        &self,
2049        draw_buffer: u32,
2050        red: bool,
2051        green: bool,
2052        blue: bool,
2053        alpha: bool,
2054    ) {
2055        let gl = &self.raw;
2056        gl.ColorMaski(draw_buffer, red as u8, green as u8, blue as u8, alpha as u8);
2057    }
2058
2059    unsafe fn depth_mask(&self, value: bool) {
2060        let gl = &self.raw;
2061        gl.DepthMask(value as u8);
2062    }
2063
2064    unsafe fn blend_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
2065        let gl = &self.raw;
2066        gl.BlendColor(red, green, blue, alpha);
2067    }
2068
2069    unsafe fn line_width(&self, width: f32) {
2070        let gl = &self.raw;
2071        gl.LineWidth(width);
2072    }
2073
2074    unsafe fn map_buffer_range(
2075        &self,
2076        target: u32,
2077        offset: i32,
2078        length: i32,
2079        access: u32,
2080    ) -> *mut u8 {
2081        let gl = &self.raw;
2082        gl.MapBufferRange(target, offset as isize, length as isize, access) as *mut u8
2083    }
2084
2085    unsafe fn flush_mapped_buffer_range(&self, target: u32, offset: i32, length: i32) {
2086        let gl = &self.raw;
2087        gl.FlushMappedBufferRange(target, offset as isize, length as isize)
2088    }
2089
2090    unsafe fn invalidate_buffer_sub_data(&self, target: u32, offset: i32, length: i32) {
2091        let gl = &self.raw;
2092        gl.InvalidateBufferSubData(target, offset as isize, length as isize)
2093    }
2094
2095    unsafe fn invalidate_framebuffer(&self, target: u32, attachments: &[u32]) {
2096        let gl = &self.raw;
2097        gl.InvalidateFramebuffer(target, attachments.len() as i32, attachments.as_ptr());
2098    }
2099
2100    unsafe fn polygon_offset(&self, factor: f32, units: f32) {
2101        let gl = &self.raw;
2102        gl.PolygonOffset(factor, units);
2103    }
2104
2105    unsafe fn polygon_mode(&self, face: u32, mode: u32) {
2106        let gl = &self.raw;
2107        gl.PolygonMode(face as u32, mode as u32);
2108    }
2109
2110    unsafe fn finish(&self) {
2111        let gl = &self.raw;
2112        gl.Finish();
2113    }
2114
2115    unsafe fn bind_texture(&self, target: u32, texture: Option<Self::Texture>) {
2116        let gl = &self.raw;
2117        gl.BindTexture(target, texture.map(|t| t.0.get()).unwrap_or(0));
2118    }
2119
2120    unsafe fn bind_sampler(&self, unit: u32, sampler: Option<Self::Sampler>) {
2121        let gl = &self.raw;
2122        gl.BindSampler(unit, sampler.map(|s| s.0.get()).unwrap_or(0));
2123    }
2124
2125    unsafe fn active_texture(&self, unit: u32) {
2126        let gl = &self.raw;
2127        gl.ActiveTexture(unit);
2128    }
2129
2130    unsafe fn fence_sync(&self, condition: u32, flags: u32) -> Result<Self::Fence, String> {
2131        let gl = &self.raw;
2132        Ok(NativeFence(gl.FenceSync(condition as u32, flags)))
2133    }
2134
2135    unsafe fn tex_parameter_f32(&self, target: u32, parameter: u32, value: f32) {
2136        let gl = &self.raw;
2137        gl.TexParameterf(target, parameter, value);
2138    }
2139
2140    unsafe fn tex_parameter_i32(&self, target: u32, parameter: u32, value: i32) {
2141        let gl = &self.raw;
2142        gl.TexParameteri(target, parameter, value);
2143    }
2144
2145    unsafe fn texture_parameter_i32(&self, texture: Self::Texture, parameter: u32, value: i32) {
2146        let gl = &self.raw;
2147        gl.TextureParameteri(texture.0.get(), parameter, value);
2148    }
2149
2150    unsafe fn tex_parameter_f32_slice(&self, target: u32, parameter: u32, values: &[f32]) {
2151        let gl = &self.raw;
2152        gl.TexParameterfv(target, parameter, values.as_ptr());
2153    }
2154
2155    unsafe fn tex_parameter_i32_slice(&self, target: u32, parameter: u32, values: &[i32]) {
2156        let gl = &self.raw;
2157        gl.TexParameteriv(target, parameter, values.as_ptr());
2158    }
2159
2160    unsafe fn tex_sub_image_2d(
2161        &self,
2162        target: u32,
2163        level: i32,
2164        x_offset: i32,
2165        y_offset: i32,
2166        width: i32,
2167        height: i32,
2168        format: u32,
2169        ty: u32,
2170        pixels: PixelUnpackData,
2171    ) {
2172        let gl = &self.raw;
2173        gl.TexSubImage2D(
2174            target,
2175            level,
2176            x_offset,
2177            y_offset,
2178            width,
2179            height,
2180            format,
2181            ty,
2182            match pixels {
2183                PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
2184                PixelUnpackData::Slice(data) => data.as_ptr() as *const std::ffi::c_void,
2185            },
2186        );
2187    }
2188
2189    unsafe fn compressed_tex_sub_image_2d(
2190        &self,
2191        target: u32,
2192        level: i32,
2193        x_offset: i32,
2194        y_offset: i32,
2195        width: i32,
2196        height: i32,
2197        format: u32,
2198        pixels: CompressedPixelUnpackData,
2199    ) {
2200        let gl = &self.raw;
2201        let (data, image_size) = match pixels {
2202            CompressedPixelUnpackData::BufferRange(ref range) => (
2203                range.start as *const std::ffi::c_void,
2204                (range.end - range.start) as i32,
2205            ),
2206            CompressedPixelUnpackData::Slice(data) => {
2207                (data.as_ptr() as *const std::ffi::c_void, data.len() as i32)
2208            }
2209        };
2210
2211        gl.CompressedTexSubImage2D(
2212            target, level, x_offset, y_offset, width, height, format, image_size, data,
2213        );
2214    }
2215
2216    unsafe fn tex_sub_image_3d(
2217        &self,
2218        target: u32,
2219        level: i32,
2220        x_offset: i32,
2221        y_offset: i32,
2222        z_offset: i32,
2223        width: i32,
2224        height: i32,
2225        depth: i32,
2226        format: u32,
2227        ty: u32,
2228        pixels: PixelUnpackData,
2229    ) {
2230        let gl = &self.raw;
2231        gl.TexSubImage3D(
2232            target,
2233            level,
2234            x_offset,
2235            y_offset,
2236            z_offset,
2237            width,
2238            height,
2239            depth,
2240            format,
2241            ty,
2242            match pixels {
2243                PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
2244                PixelUnpackData::Slice(data) => data.as_ptr() as *const std::ffi::c_void,
2245            },
2246        );
2247    }
2248
2249    unsafe fn texture_sub_image_3d(
2250        &self,
2251        texture: Self::Texture,
2252        level: i32,
2253        x_offset: i32,
2254        y_offset: i32,
2255        z_offset: i32,
2256        width: i32,
2257        height: i32,
2258        depth: i32,
2259        format: u32,
2260        ty: u32,
2261        pixels: PixelUnpackData,
2262    ) {
2263        let gl = &self.raw;
2264        gl.TextureSubImage3D(
2265            texture.0.get(),
2266            level,
2267            x_offset,
2268            y_offset,
2269            z_offset,
2270            width,
2271            height,
2272            depth,
2273            format,
2274            ty,
2275            match pixels {
2276                PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
2277                PixelUnpackData::Slice(data) => data.as_ptr() as *const std::ffi::c_void,
2278            },
2279        );
2280    }
2281
2282    unsafe fn compressed_tex_sub_image_3d(
2283        &self,
2284        target: u32,
2285        level: i32,
2286        x_offset: i32,
2287        y_offset: i32,
2288        z_offset: i32,
2289        width: i32,
2290        height: i32,
2291        depth: i32,
2292        format: u32,
2293        pixels: CompressedPixelUnpackData,
2294    ) {
2295        let gl = &self.raw;
2296        let (data, image_size) = match pixels {
2297            CompressedPixelUnpackData::BufferRange(ref range) => (
2298                range.start as *const std::ffi::c_void,
2299                (range.end - range.start) as i32,
2300            ),
2301            CompressedPixelUnpackData::Slice(data) => {
2302                (data.as_ptr() as *const std::ffi::c_void, data.len() as i32)
2303            }
2304        };
2305
2306        gl.CompressedTexSubImage3D(
2307            target, level, x_offset, y_offset, z_offset, width, height, depth, format, image_size,
2308            data,
2309        );
2310    }
2311
2312    unsafe fn depth_func(&self, func: u32) {
2313        let gl = &self.raw;
2314        gl.DepthFunc(func as u32);
2315    }
2316
2317    unsafe fn depth_range_f32(&self, near: f32, far: f32) {
2318        let gl = &self.raw;
2319        gl.DepthRangef(near, far);
2320    }
2321
2322    unsafe fn depth_range_f64(&self, near: f64, far: f64) {
2323        let gl = &self.raw;
2324        gl.DepthRange(near, far);
2325    }
2326
2327    unsafe fn depth_range_f64_slice(&self, first: u32, count: i32, values: &[[f64; 2]]) {
2328        let gl = &self.raw;
2329        gl.DepthRangeArrayv(first, count, values.as_ptr() as *const f64);
2330    }
2331
2332    unsafe fn scissor(&self, x: i32, y: i32, width: i32, height: i32) {
2333        let gl = &self.raw;
2334        gl.Scissor(x, y, width, height);
2335    }
2336
2337    unsafe fn scissor_slice(&self, first: u32, count: i32, scissors: &[[i32; 4]]) {
2338        let gl = &self.raw;
2339        gl.ScissorArrayv(first, count, scissors.as_ptr() as *const i32);
2340    }
2341
2342    unsafe fn vertex_array_attrib_binding_f32(
2343        &self,
2344        vao: Self::VertexArray,
2345        index: u32,
2346        binding_index: u32,
2347    ) {
2348        let gl = &self.raw;
2349        gl.VertexArrayAttribBinding(vao.0.get(), index, binding_index);
2350    }
2351
2352    unsafe fn vertex_array_attrib_format_f32(
2353        &self,
2354        vao: Self::VertexArray,
2355        index: u32,
2356        size: i32,
2357        data_type: u32,
2358        normalized: bool,
2359        relative_offset: u32,
2360    ) {
2361        let gl = &self.raw;
2362        gl.VertexArrayAttribFormat(
2363            vao.0.get(),
2364            index,
2365            size,
2366            data_type,
2367            normalized as u8,
2368            relative_offset,
2369        );
2370    }
2371
2372    unsafe fn vertex_array_attrib_format_i32(
2373        &self,
2374        vao: Self::VertexArray,
2375        index: u32,
2376        size: i32,
2377        data_type: u32,
2378        relative_offset: u32,
2379    ) {
2380        let gl = &self.raw;
2381        gl.VertexArrayAttribIFormat(vao.0.get(), index, size, data_type, relative_offset);
2382    }
2383
2384    unsafe fn vertex_array_element_buffer(
2385        &self,
2386        vao: Self::VertexArray,
2387        buffer: Option<Self::Buffer>,
2388    ) {
2389        let gl = &self.raw;
2390        gl.VertexArrayElementBuffer(vao.0.get(), buffer.map(|b| b.0.get()).unwrap_or(0));
2391    }
2392
2393    unsafe fn vertex_array_vertex_buffer(
2394        &self,
2395        vao: Self::VertexArray,
2396        binding_index: u32,
2397        buffer: Option<Self::Buffer>,
2398        offset: i32,
2399        stride: i32,
2400    ) {
2401        let gl = &self.raw;
2402        gl.VertexArrayVertexBuffer(
2403            vao.0.get(),
2404            binding_index,
2405            buffer.map(|b| b.0.get()).unwrap_or(0),
2406            offset as isize,
2407            stride,
2408        );
2409    }
2410
2411    unsafe fn vertex_attrib_divisor(&self, index: u32, divisor: u32) {
2412        let gl = &self.raw;
2413        gl.VertexAttribDivisor(index, divisor);
2414    }
2415
2416    unsafe fn vertex_attrib_pointer_f32(
2417        &self,
2418        index: u32,
2419        size: i32,
2420        data_type: u32,
2421        normalized: bool,
2422        stride: i32,
2423        offset: i32,
2424    ) {
2425        let gl = &self.raw;
2426        gl.VertexAttribPointer(
2427            index,
2428            size,
2429            data_type,
2430            normalized as u8,
2431            stride,
2432            offset as *const std::ffi::c_void,
2433        );
2434    }
2435
2436    unsafe fn vertex_attrib_pointer_i32(
2437        &self,
2438        index: u32,
2439        size: i32,
2440        data_type: u32,
2441        stride: i32,
2442        offset: i32,
2443    ) {
2444        let gl = &self.raw;
2445        gl.VertexAttribIPointer(
2446            index,
2447            size,
2448            data_type,
2449            stride,
2450            offset as *const std::ffi::c_void,
2451        );
2452    }
2453
2454    unsafe fn vertex_attrib_pointer_f64(
2455        &self,
2456        index: u32,
2457        size: i32,
2458        data_type: u32,
2459        stride: i32,
2460        offset: i32,
2461    ) {
2462        let gl = &self.raw;
2463        gl.VertexAttribLPointer(
2464            index,
2465            size,
2466            data_type,
2467            stride,
2468            offset as *const std::ffi::c_void,
2469        );
2470    }
2471
2472    unsafe fn vertex_attrib_format_f32(
2473        &self,
2474        index: u32,
2475        size: i32,
2476        data_type: u32,
2477        normalized: bool,
2478        relative_offset: u32,
2479    ) {
2480        let gl = &self.raw;
2481        gl.VertexAttribFormat(index, size, data_type, normalized as u8, relative_offset);
2482    }
2483
2484    unsafe fn vertex_attrib_format_i32(
2485        &self,
2486        index: u32,
2487        size: i32,
2488        data_type: u32,
2489        relative_offset: u32,
2490    ) {
2491        let gl = &self.raw;
2492        gl.VertexAttribIFormat(index, size, data_type, relative_offset);
2493    }
2494
2495    unsafe fn vertex_attrib_1_f32(&self, index: u32, x: f32) {
2496        let gl = &self.raw;
2497        gl.VertexAttrib1f(index, x);
2498    }
2499
2500    unsafe fn vertex_attrib_2_f32(&self, index: u32, x: f32, y: f32) {
2501        let gl = &self.raw;
2502        gl.VertexAttrib2f(index, x, y);
2503    }
2504
2505    unsafe fn vertex_attrib_3_f32(&self, index: u32, x: f32, y: f32, z: f32) {
2506        let gl = &self.raw;
2507        gl.VertexAttrib3f(index, x, y, z);
2508    }
2509
2510    unsafe fn vertex_attrib_4_f32(&self, index: u32, x: f32, y: f32, z: f32, w: f32) {
2511        let gl = &self.raw;
2512        gl.VertexAttrib4f(index, x, y, z, w);
2513    }
2514
2515    unsafe fn vertex_attrib_1_f32_slice(&self, index: u32, v: &[f32]) {
2516        let gl = &self.raw;
2517        gl.VertexAttrib1fv(index, v.as_ptr());
2518    }
2519
2520    unsafe fn vertex_attrib_2_f32_slice(&self, index: u32, v: &[f32]) {
2521        let gl = &self.raw;
2522        gl.VertexAttrib2fv(index, v.as_ptr());
2523    }
2524
2525    unsafe fn vertex_attrib_3_f32_slice(&self, index: u32, v: &[f32]) {
2526        let gl = &self.raw;
2527        gl.VertexAttrib3fv(index, v.as_ptr());
2528    }
2529
2530    unsafe fn vertex_attrib_4_f32_slice(&self, index: u32, v: &[f32]) {
2531        let gl = &self.raw;
2532        gl.VertexAttrib4fv(index, v.as_ptr());
2533    }
2534
2535    unsafe fn vertex_attrib_binding(&self, attrib_index: u32, binding_index: u32) {
2536        let gl = &self.raw;
2537        gl.VertexAttribBinding(attrib_index, binding_index);
2538    }
2539
2540    unsafe fn vertex_binding_divisor(&self, binding_index: u32, divisor: u32) {
2541        let gl = &self.raw;
2542        gl.VertexBindingDivisor(binding_index, divisor);
2543    }
2544
2545    unsafe fn viewport(&self, x: i32, y: i32, width: i32, height: i32) {
2546        let gl = &self.raw;
2547        gl.Viewport(x, y, width, height);
2548    }
2549
2550    unsafe fn viewport_f32_slice(&self, first: u32, count: i32, values: &[[f32; 4]]) {
2551        let gl = &self.raw;
2552        gl.ViewportArrayv(first, count, values.as_ptr() as *const f32);
2553    }
2554
2555    unsafe fn blend_equation(&self, mode: u32) {
2556        let gl = &self.raw;
2557        gl.BlendEquation(mode as u32);
2558    }
2559
2560    unsafe fn blend_equation_draw_buffer(&self, draw_buffer: u32, mode: u32) {
2561        let gl = &self.raw;
2562        gl.BlendEquationi(draw_buffer, mode as u32);
2563    }
2564
2565    unsafe fn blend_equation_separate(&self, mode_rgb: u32, mode_alpha: u32) {
2566        let gl = &self.raw;
2567        gl.BlendEquationSeparate(mode_rgb as u32, mode_alpha as u32);
2568    }
2569
2570    unsafe fn blend_equation_separate_draw_buffer(
2571        &self,
2572        draw_buffer: u32,
2573        mode_rgb: u32,
2574        mode_alpha: u32,
2575    ) {
2576        let gl = &self.raw;
2577        gl.BlendEquationSeparatei(draw_buffer, mode_rgb as u32, mode_alpha as u32);
2578    }
2579
2580    unsafe fn blend_func(&self, src: u32, dst: u32) {
2581        let gl = &self.raw;
2582        gl.BlendFunc(src as u32, dst as u32);
2583    }
2584
2585    unsafe fn blend_func_draw_buffer(&self, draw_buffer: u32, src: u32, dst: u32) {
2586        let gl = &self.raw;
2587        gl.BlendFunci(draw_buffer, src as u32, dst as u32);
2588    }
2589
2590    unsafe fn blend_func_separate(
2591        &self,
2592        src_rgb: u32,
2593        dst_rgb: u32,
2594        src_alpha: u32,
2595        dst_alpha: u32,
2596    ) {
2597        let gl = &self.raw;
2598        gl.BlendFuncSeparate(
2599            src_rgb as u32,
2600            dst_rgb as u32,
2601            src_alpha as u32,
2602            dst_alpha as u32,
2603        );
2604    }
2605
2606    unsafe fn blend_func_separate_draw_buffer(
2607        &self,
2608        draw_buffer: u32,
2609        src_rgb: u32,
2610        dst_rgb: u32,
2611        src_alpha: u32,
2612        dst_alpha: u32,
2613    ) {
2614        let gl = &self.raw;
2615        gl.BlendFuncSeparatei(
2616            draw_buffer,
2617            src_rgb as u32,
2618            dst_rgb as u32,
2619            src_alpha as u32,
2620            dst_alpha as u32,
2621        );
2622    }
2623
2624    unsafe fn stencil_func(&self, func: u32, reference: i32, mask: u32) {
2625        let gl = &self.raw;
2626        gl.StencilFunc(func as u32, reference, mask);
2627    }
2628
2629    unsafe fn stencil_func_separate(&self, face: u32, func: u32, reference: i32, mask: u32) {
2630        let gl = &self.raw;
2631        gl.StencilFuncSeparate(face as u32, func as u32, reference, mask);
2632    }
2633
2634    unsafe fn stencil_mask(&self, mask: u32) {
2635        let gl = &self.raw;
2636        gl.StencilMask(mask);
2637    }
2638
2639    unsafe fn stencil_mask_separate(&self, face: u32, mask: u32) {
2640        let gl = &self.raw;
2641        gl.StencilMaskSeparate(face as u32, mask);
2642    }
2643
2644    unsafe fn stencil_op(&self, stencil_fail: u32, depth_fail: u32, pass: u32) {
2645        let gl = &self.raw;
2646        gl.StencilOp(stencil_fail as u32, depth_fail as u32, pass as u32);
2647    }
2648
2649    unsafe fn stencil_op_separate(&self, face: u32, stencil_fail: u32, depth_fail: u32, pass: u32) {
2650        let gl = &self.raw;
2651        gl.StencilOpSeparate(
2652            face as u32,
2653            stencil_fail as u32,
2654            depth_fail as u32,
2655            pass as u32,
2656        );
2657    }
2658
2659    unsafe fn debug_message_control(
2660        &self,
2661        source: u32,
2662        msg_type: u32,
2663        severity: u32,
2664        ids: &[u32],
2665        enabled: bool,
2666    ) {
2667        let gl = &self.raw;
2668
2669        let ids_ptr = if ids.is_empty() {
2670            std::ptr::null()
2671        } else {
2672            ids.as_ptr()
2673        };
2674
2675        gl.DebugMessageControl(
2676            source,
2677            msg_type,
2678            severity,
2679            ids.len() as i32,
2680            ids_ptr,
2681            enabled as u8,
2682        );
2683    }
2684
2685    unsafe fn debug_message_insert<S>(
2686        &self,
2687        source: u32,
2688        msg_type: u32,
2689        id: u32,
2690        severity: u32,
2691        msg: S,
2692    ) where
2693        S: AsRef<str>,
2694    {
2695        let gl = &self.raw;
2696        let message = msg.as_ref().as_bytes();
2697        let length = message.len() as i32;
2698        gl.DebugMessageInsert(
2699            source,
2700            msg_type,
2701            id,
2702            severity,
2703            length,
2704            message.as_ptr() as *const native_gl::GLchar,
2705        );
2706    }
2707
2708    unsafe fn debug_message_callback<F>(&mut self, callback: F)
2709    where
2710        F: FnMut(u32, u32, u32, u32, &str) + 'static,
2711    {
2712        match self.debug_callback {
2713            Some(_) => {
2714                panic!("Debug callback already set");
2715            }
2716            None => {
2717                let trait_object: DebugCallback = Box::new(callback);
2718                let thin_ptr = Box::new(trait_object);
2719                let raw_ptr = Box::into_raw(thin_ptr) as *mut _ as *mut std::ffi::c_void;
2720
2721                let gl = &self.raw;
2722
2723                if gl.DebugMessageCallback_is_loaded() {
2724                    gl.DebugMessageCallback(Some(raw_debug_message_callback), raw_ptr);
2725                } else {
2726                    // Fallback to extension
2727                    gl.DebugMessageCallbackKHR(Some(raw_debug_message_callback), raw_ptr);
2728                }
2729
2730                self.debug_callback = Some(DebugCallbackRawPtr { callback: raw_ptr });
2731            }
2732        }
2733    }
2734
2735    unsafe fn get_debug_message_log(&self, count: u32) -> Vec<DebugMessageLogEntry> {
2736        let ct = count as usize;
2737        let mut sources = Vec::with_capacity(ct);
2738        let mut types = Vec::with_capacity(ct);
2739        let mut ids = Vec::with_capacity(ct);
2740        let mut severities = Vec::with_capacity(ct);
2741        let mut lengths = Vec::with_capacity(ct);
2742        let buf_size = (count * MAX_DEBUG_MESSAGE_LENGTH) as i32;
2743        let mut message_log = Vec::with_capacity(buf_size as usize);
2744
2745        let gl = &self.raw;
2746        let received = gl.GetDebugMessageLog(
2747            count,
2748            buf_size,
2749            sources.as_mut_ptr(),
2750            types.as_mut_ptr(),
2751            ids.as_mut_ptr(),
2752            severities.as_mut_ptr(),
2753            lengths.as_mut_ptr(),
2754            message_log.as_mut_ptr(),
2755        ) as usize;
2756
2757        sources.set_len(received);
2758        types.set_len(received);
2759        ids.set_len(received);
2760        severities.set_len(received);
2761        lengths.set_len(received);
2762        message_log.set_len(buf_size as usize);
2763
2764        let mut entries = Vec::new();
2765        let mut offset = 0;
2766        for i in 0..received {
2767            let message =
2768                std::ffi::CStr::from_ptr(message_log[offset..].as_ptr()).to_string_lossy();
2769            offset += lengths[i] as usize;
2770            entries.push(DebugMessageLogEntry {
2771                source: sources[i],
2772                msg_type: types[i],
2773                id: ids[i],
2774                severity: severities[i],
2775                message: message.to_string(),
2776            });
2777        }
2778
2779        entries
2780    }
2781
2782    unsafe fn push_debug_group<S>(&self, source: u32, id: u32, message: S)
2783    where
2784        S: AsRef<str>,
2785    {
2786        let gl = &self.raw;
2787        let msg = message.as_ref().as_bytes();
2788        let length = msg.len() as i32;
2789        gl.PushDebugGroup(source, id, length, msg.as_ptr() as *const native_gl::GLchar);
2790    }
2791
2792    unsafe fn pop_debug_group(&self) {
2793        let gl = &self.raw;
2794        gl.PopDebugGroup();
2795    }
2796
2797    unsafe fn object_label<S>(&self, identifier: u32, name: u32, label: Option<S>)
2798    where
2799        S: AsRef<str>,
2800    {
2801        let gl = &self.raw;
2802
2803        match label {
2804            Some(l) => {
2805                let lbl = l.as_ref().as_bytes();
2806                let length = lbl.len() as i32;
2807                gl.ObjectLabel(
2808                    identifier,
2809                    name,
2810                    length,
2811                    lbl.as_ptr() as *const native_gl::GLchar,
2812                );
2813            }
2814            None => gl.ObjectLabel(identifier, name, 0, std::ptr::null()),
2815        }
2816    }
2817
2818    unsafe fn get_object_label(&self, identifier: u32, name: u32) -> String {
2819        let gl = &self.raw;
2820        let mut len = 0;
2821        let mut label_buf = Vec::with_capacity(self.constants.max_label_length as usize);
2822        gl.GetObjectLabel(
2823            identifier,
2824            name,
2825            self.constants.max_label_length,
2826            &mut len,
2827            label_buf.as_mut_ptr(),
2828        );
2829        label_buf.set_len(len as usize);
2830        std::ffi::CStr::from_ptr(label_buf.as_ptr())
2831            .to_str()
2832            .unwrap()
2833            .to_owned()
2834    }
2835
2836    unsafe fn object_ptr_label<S>(&self, sync: Self::Fence, label: Option<S>)
2837    where
2838        S: AsRef<str>,
2839    {
2840        let gl = &self.raw;
2841
2842        match label {
2843            Some(l) => {
2844                let lbl = l.as_ref().as_bytes();
2845                let length = lbl.len() as i32;
2846                gl.ObjectPtrLabel(
2847                    sync.0 as *mut std::ffi::c_void,
2848                    length,
2849                    lbl.as_ptr() as *const native_gl::GLchar,
2850                );
2851            }
2852            None => gl.ObjectPtrLabel(sync.0 as *mut std::ffi::c_void, 0, std::ptr::null()),
2853        }
2854    }
2855
2856    unsafe fn get_object_ptr_label(&self, sync: Self::Fence) -> String {
2857        let gl = &self.raw;
2858        let mut len = 0;
2859        let mut label_buf = Vec::with_capacity(self.constants.max_label_length as usize);
2860        gl.GetObjectPtrLabel(
2861            sync.0 as *mut std::ffi::c_void,
2862            self.constants.max_label_length,
2863            &mut len,
2864            label_buf.as_mut_ptr(),
2865        );
2866        label_buf.set_len(len as usize);
2867        std::ffi::CStr::from_ptr(label_buf.as_ptr())
2868            .to_str()
2869            .unwrap()
2870            .to_owned()
2871    }
2872
2873    unsafe fn get_uniform_block_index(&self, program: Self::Program, name: &str) -> Option<u32> {
2874        let gl = &self.raw;
2875        let name = CString::new(name).unwrap();
2876        let index = gl.GetUniformBlockIndex(program.0.get(), name.as_ptr());
2877        if index == INVALID_INDEX {
2878            None
2879        } else {
2880            Some(index)
2881        }
2882    }
2883
2884    unsafe fn uniform_block_binding(&self, program: Self::Program, index: u32, binding: u32) {
2885        let gl = &self.raw;
2886        gl.UniformBlockBinding(program.0.get(), index, binding);
2887    }
2888
2889    unsafe fn get_shader_storage_block_index(
2890        &self,
2891        program: Self::Program,
2892        name: &str,
2893    ) -> Option<u32> {
2894        let gl = &self.raw;
2895        let name = CString::new(name).unwrap();
2896        let index =
2897            gl.GetProgramResourceIndex(program.0.get(), SHADER_STORAGE_BLOCK, name.as_ptr());
2898        if index == INVALID_INDEX {
2899            None
2900        } else {
2901            Some(index)
2902        }
2903    }
2904
2905    unsafe fn shader_storage_block_binding(
2906        &self,
2907        program: Self::Program,
2908        index: u32,
2909        binding: u32,
2910    ) {
2911        let gl = &self.raw;
2912        gl.ShaderStorageBlockBinding(program.0.get(), index, binding);
2913    }
2914
2915    unsafe fn read_buffer(&self, src: u32) {
2916        let gl = &self.raw;
2917        gl.ReadBuffer(src);
2918    }
2919
2920    unsafe fn read_pixels(
2921        &self,
2922        x: i32,
2923        y: i32,
2924        width: i32,
2925        height: i32,
2926        format: u32,
2927        gltype: u32,
2928        pixels: PixelPackData,
2929    ) {
2930        let gl = &self.raw;
2931        gl.ReadPixels(
2932            x,
2933            y,
2934            width,
2935            height,
2936            format,
2937            gltype,
2938            match pixels {
2939                PixelPackData::BufferOffset(offset) => offset as *mut std::ffi::c_void,
2940                PixelPackData::Slice(data) => data.as_mut_ptr() as *mut std::ffi::c_void,
2941            },
2942        );
2943    }
2944
2945    unsafe fn begin_query(&self, target: u32, query: Self::Query) {
2946        let gl = &self.raw;
2947        gl.BeginQuery(target, query.0.get());
2948    }
2949
2950    unsafe fn end_query(&self, target: u32) {
2951        let gl = &self.raw;
2952        gl.EndQuery(target);
2953    }
2954
2955    unsafe fn query_counter(&self, query: Self::Query, target: u32) {
2956        let gl = &self.raw;
2957        gl.QueryCounter(query.0.get(), target);
2958    }
2959
2960    unsafe fn get_query_parameter_u32(&self, query: Self::Query, parameter: u32) -> u32 {
2961        let gl = &self.raw;
2962        let mut value = 0;
2963        gl.GetQueryObjectuiv(query.0.get(), parameter, &mut value);
2964        value
2965    }
2966
2967    unsafe fn get_query_parameter_u64_with_offset(
2968        &self,
2969        query: Self::Query,
2970        parameter: u32,
2971        offset: usize,
2972    ) {
2973        let gl = &self.raw;
2974        gl.GetQueryObjectui64v(query.0.get(), parameter, offset as *mut _);
2975    }
2976
2977    unsafe fn create_transform_feedback(&self) -> Result<Self::TransformFeedback, String> {
2978        let gl = &self.raw;
2979        let mut name = 0;
2980        gl.GenTransformFeedbacks(1, &mut name);
2981        Ok(NativeTransformFeedback(non_zero_gl_name(name)))
2982    }
2983
2984    unsafe fn delete_transform_feedback(&self, transform_feedback: Self::TransformFeedback) {
2985        let gl = &self.raw;
2986        gl.DeleteTransformFeedbacks(1, &transform_feedback.0.get());
2987    }
2988
2989    unsafe fn bind_transform_feedback(
2990        &self,
2991        target: u32,
2992        transform_feedback: Option<Self::TransformFeedback>,
2993    ) {
2994        let gl = &self.raw;
2995        gl.BindTransformFeedback(target, transform_feedback.map(|tf| tf.0.get()).unwrap_or(0));
2996    }
2997
2998    unsafe fn begin_transform_feedback(&self, primitive_mode: u32) {
2999        let gl = &self.raw;
3000        gl.BeginTransformFeedback(primitive_mode);
3001    }
3002
3003    unsafe fn end_transform_feedback(&self) {
3004        let gl = &self.raw;
3005        gl.EndTransformFeedback();
3006    }
3007
3008    unsafe fn pause_transform_feedback(&self) {
3009        let gl = &self.raw;
3010        gl.PauseTransformFeedback();
3011    }
3012
3013    unsafe fn resume_transform_feedback(&self) {
3014        let gl = &self.raw;
3015        gl.ResumeTransformFeedback();
3016    }
3017
3018    unsafe fn transform_feedback_varyings(
3019        &self,
3020        program: Self::Program,
3021        varyings: &[&str],
3022        buffer_mode: u32,
3023    ) {
3024        let gl = &self.raw;
3025
3026        let strings: Vec<CString> = varyings
3027            .iter()
3028            .copied()
3029            .map(CString::new)
3030            .collect::<Result<_, _>>()
3031            .unwrap();
3032        let varyings: Vec<_> = strings.iter().map(|c_str| c_str.as_ptr()).collect();
3033
3034        gl.TransformFeedbackVaryings(
3035            program.0.get(),
3036            varyings.len() as i32,
3037            varyings.as_ptr(),
3038            buffer_mode,
3039        );
3040    }
3041
3042    unsafe fn get_transform_feedback_varying(
3043        &self,
3044        program: Self::Program,
3045        index: u32,
3046    ) -> Option<ActiveTransformFeedback> {
3047        let gl = &self.raw;
3048
3049        const buf_size: usize = 256;
3050        const bytes: [u8; buf_size] = [0; buf_size];
3051
3052        let size: i32 = 0;
3053        let tftype: u32 = 0;
3054        let c_name = CString::new(bytes.to_vec()).unwrap();
3055        let c_name_buf = c_name.into_raw();
3056
3057        gl.GetTransformFeedbackVarying(
3058            program.0.get(),
3059            index,
3060            buf_size as i32,
3061            std::ptr::null_mut(),
3062            size as *mut i32,
3063            tftype as *mut u32,
3064            c_name_buf,
3065        );
3066
3067        let name = CString::from_raw(c_name_buf).into_string().unwrap();
3068
3069        Some(ActiveTransformFeedback { size, tftype, name })
3070    }
3071
3072    unsafe fn memory_barrier(&self, barriers: u32) {
3073        let gl = &self.raw;
3074        gl.MemoryBarrier(barriers);
3075    }
3076
3077    unsafe fn memory_barrier_by_region(&self, barriers: u32) {
3078        let gl = &self.raw;
3079        gl.MemoryBarrierByRegion(barriers);
3080    }
3081
3082    unsafe fn bind_image_texture(
3083        &self,
3084        unit: u32,
3085        texture: Self::Texture,
3086        level: i32,
3087        layered: bool,
3088        layer: i32,
3089        access: u32,
3090        format: u32,
3091    ) {
3092        let gl = &self.raw;
3093        gl.BindImageTexture(
3094            unit,
3095            texture.0.get(),
3096            level,
3097            layered as u8,
3098            layer,
3099            access,
3100            format,
3101        );
3102    }
3103    unsafe fn get_active_uniform_block_parameter_i32(
3104        &self,
3105        program: Self::Program,
3106        uniform_block_index: u32,
3107        parameter: u32,
3108    ) -> i32 {
3109        let gl = &self.raw;
3110        let mut value = 0;
3111        gl.GetActiveUniformBlockiv(program.0.get(), uniform_block_index, parameter, &mut value);
3112        value
3113    }
3114
3115    unsafe fn get_active_uniform_block_parameter_i32_slice(
3116        &self,
3117        program: Self::Program,
3118        uniform_block_index: u32,
3119        parameter: u32,
3120        out: &mut [i32],
3121    ) {
3122        let gl = &self.raw;
3123        gl.GetActiveUniformBlockiv(
3124            program.0.get(),
3125            uniform_block_index,
3126            parameter,
3127            out.as_mut_ptr(),
3128        );
3129    }
3130    unsafe fn get_active_uniform_block_name(
3131        &self,
3132        program: Self::Program,
3133        uniform_block_index: u32,
3134    ) -> String {
3135        let gl = &self.raw;
3136
3137        // Probe for the length of the name of the uniform block, and, failing
3138        // that, fall back to allocating a buffer that is 256 bytes long. This
3139        // should be good enough for pretty much all contexts, including faulty
3140        // or partially faulty ones.
3141        let len = self.get_active_uniform_block_parameter_i32(
3142            program,
3143            uniform_block_index,
3144            crate::UNIFORM_BLOCK_NAME_LENGTH,
3145        );
3146        let len = if gl.GetError() == crate::NO_ERROR && len > 0 {
3147            len as usize
3148        } else {
3149            256
3150        };
3151
3152        let mut buffer = vec![0; len];
3153        let mut length = 0;
3154        gl.GetActiveUniformBlockName(
3155            program.0.get(),
3156            uniform_block_index,
3157            buffer.len() as _,
3158            &mut length,
3159            buffer.as_mut_ptr(),
3160        );
3161
3162        if length > 0 {
3163            assert_eq!(
3164                std::mem::size_of::<u8>(),
3165                std::mem::size_of::<native_gl::GLchar>(),
3166                "This operation is only safe in systems in which the length of \
3167                a GLchar is the same as that of an u8"
3168            );
3169            assert_eq!(
3170                std::mem::align_of::<u8>(),
3171                std::mem::align_of::<native_gl::GLchar>(),
3172                "This operation is only safe in systems in which the alignment \
3173                of a GLchar is the same as that of an u8"
3174            );
3175            let buffer = std::slice::from_raw_parts(
3176                buffer.as_ptr() as *const u8,
3177                (length as usize + 1).min(buffer.len()),
3178            );
3179
3180            let name = CStr::from_bytes_with_nul(&buffer[..])
3181                .unwrap()
3182                .to_str()
3183                .unwrap()
3184                .to_owned();
3185
3186            name
3187        } else {
3188            String::from("")
3189        }
3190    }
3191
3192    unsafe fn max_shader_compiler_threads(&self, count: u32) {
3193        let gl = &self.raw;
3194        if gl.MaxShaderCompilerThreadsKHR_is_loaded() {
3195            gl.MaxShaderCompilerThreadsKHR(count);
3196        } else {
3197            gl.MaxShaderCompilerThreadsARB(count);
3198        }
3199    }
3200}
3201
3202extern "system" fn raw_debug_message_callback(
3203    source: u32,
3204    gltype: u32,
3205    id: u32,
3206    severity: u32,
3207    length: i32,
3208    message: *const native_gl::GLchar,
3209    user_param: *mut std::ffi::c_void,
3210) {
3211    let _result = std::panic::catch_unwind(move || unsafe {
3212        let callback: &mut DebugCallback = &mut *(user_param as *mut DebugCallback);
3213        let slice = std::slice::from_raw_parts(message as *const u8, length as usize);
3214        let msg = std::str::from_utf8(slice).unwrap();
3215        (callback)(source, gltype, id, severity, msg);
3216    });
3217}