glow/
native.rs

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