sparkle/
lib.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5pub mod gl {
6    pub use self::ffi::types::*;
7    pub use self::ffi::*;
8    use std::ffi::{CStr, CString};
9    use std::mem::size_of;
10    use std::os::raw::{c_char, c_int, c_void};
11    use std::ptr;
12    use std::rc::Rc;
13    use std::str;
14
15    #[derive(Copy, Clone, Debug, PartialEq)]
16    pub enum GlType {
17        Gl,
18        Gles,
19    }
20
21    pub enum Gl {
22        Gl(self::ffi_gl::Gl),
23        Gles(self::ffi_gles::Gles2),
24    }
25
26    pub enum TexImageSource<'a> {
27        Pixels(Option<&'a [u8]>),
28        BufferOffset(i64),
29    }
30
31    impl Gl {
32        pub fn get_type(&self) -> GlType {
33            match self {
34                Gl::Gl(..) => GlType::Gl,
35                Gl::Gles(..) => GlType::Gles,
36            }
37        }
38
39        pub fn gl_fns(gl: self::ffi_gl::Gl) -> Rc<Gl> {
40            Rc::new(Gl::Gl(gl))
41        }
42
43        pub fn gles_fns(gl: self::ffi_gles::Gles2) -> Rc<Gl> {
44            Rc::new(Gl::Gles(gl))
45        }
46
47        pub fn gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint> {
48            let mut ids = vec![0 as GLuint; n as usize];
49            match self {
50                Gl::Gl(gl) => unsafe { gl.GenFramebuffers(n, ids.as_mut_ptr()) },
51                Gl::Gles(gles) => unsafe { gles.GenFramebuffers(n, ids.as_mut_ptr()) },
52            }
53            ids
54        }
55
56        pub fn gen_textures(&self, n: GLsizei) -> Vec<GLuint> {
57            let mut ids = vec![0 as GLuint; n as usize];
58            match self {
59                Gl::Gl(gl) => unsafe { gl.GenTextures(n, ids.as_mut_ptr()) },
60                Gl::Gles(gles) => unsafe { gles.GenTextures(n, ids.as_mut_ptr()) },
61            }
62            ids
63        }
64
65        pub fn gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint> {
66            let mut ids = vec![0 as GLuint; n as usize];
67            match self {
68                Gl::Gl(gl) => unsafe { gl.GenRenderbuffers(n, ids.as_mut_ptr()) },
69                Gl::Gles(gles) => unsafe { gles.GenRenderbuffers(n, ids.as_mut_ptr()) },
70            }
71            ids
72        }
73
74        pub fn gen_buffers(&self, n: GLsizei) -> Vec<GLuint> {
75            let mut ids = vec![0 as GLuint; n as usize];
76            match self {
77                Gl::Gl(gl) => unsafe { gl.GenBuffers(n, ids.as_mut_ptr()) },
78                Gl::Gles(gles) => unsafe { gles.GenBuffers(n, ids.as_mut_ptr()) },
79            }
80            ids
81        }
82
83        pub fn gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint> {
84            let mut ids = vec![0 as GLuint; n as usize];
85            match self {
86                Gl::Gl(gl) => unsafe { gl.GenVertexArrays(n, ids.as_mut_ptr()) },
87                Gl::Gles(gles) => unsafe { gles.GenVertexArrays(n, ids.as_mut_ptr()) },
88            }
89            ids
90        }
91
92        pub fn shader_source(&self, shader: GLuint, strings: &[&[u8]]) {
93            let pointers: Vec<*const u8> =
94                strings.iter().map(|string| (*string).as_ptr()).collect();
95            let lengths: Vec<GLint> = strings.iter().map(|string| string.len() as GLint).collect();
96            let len = pointers.len() as GLsizei;
97            let pointers = pointers.as_ptr() as *const *const GLchar;
98            match self {
99                Gl::Gl(gl) => unsafe { gl.ShaderSource(shader, len, pointers, lengths.as_ptr()) },
100                Gl::Gles(gles) => unsafe {
101                    gles.ShaderSource(shader, len, pointers, lengths.as_ptr())
102                },
103            }
104        }
105
106        pub fn create_program(&self) -> GLuint {
107            match self {
108                Gl::Gl(gl) => unsafe { gl.CreateProgram() },
109                Gl::Gles(gles) => unsafe { gles.CreateProgram() },
110            }
111        }
112
113        pub fn tex_image_2d(
114            &self,
115            target: GLenum,
116            level: GLint,
117            internal_format: GLint,
118            width: GLsizei,
119            height: GLsizei,
120            border: GLint,
121            format: GLenum,
122            ty: GLenum,
123            source: TexImageSource,
124        ) {
125            let data = match source {
126                TexImageSource::Pixels(pixels) => {
127                    pixels.map(|d| d.as_ptr()).unwrap_or(ptr::null()) as *const _
128                },
129                TexImageSource::BufferOffset(offset) => unsafe {
130                    let mut buffer = [0];
131                    self.get_integer_v(PIXEL_UNPACK_BUFFER_BINDING, &mut buffer);
132                    assert!(buffer[0] != 0);
133                    offset as *const _
134                }
135            };
136            match self {
137                Gl::Gl(gl) => unsafe {
138                    gl.TexImage2D(
139                        target,
140                        level,
141                        internal_format,
142                        width,
143                        height,
144                        border,
145                        format,
146                        ty,
147                        data,
148                    )
149                },
150                Gl::Gles(gles) => unsafe {
151                    gles.TexImage2D(
152                        target,
153                        level,
154                        internal_format,
155                        width,
156                        height,
157                        border,
158                        format,
159                        ty,
160                        data,
161                    )
162                },
163            }
164        }
165
166        pub fn tex_sub_image_2d(
167            &self,
168            target: GLenum,
169            level: GLint,
170            xoffset: GLint,
171            yoffset: GLint,
172            width: GLsizei,
173            height: GLsizei,
174            format: GLenum,
175            ty: GLenum,
176            data: &[u8],
177        ) {
178            let data = data.as_ptr() as *const c_void;
179            match self {
180                Gl::Gl(gl) => unsafe {
181                    gl.TexSubImage2D(
182                        target, level, xoffset, yoffset, width, height, format, ty, data,
183                    )
184                },
185                Gl::Gles(gles) => unsafe {
186                    gles.TexSubImage2D(
187                        target, level, xoffset, yoffset, width, height, format, ty, data,
188                    )
189                },
190            }
191        }
192
193        pub fn copy_tex_image_2d(
194            &self,
195            target: GLenum,
196            level: GLint,
197            internal_format: GLenum,
198            x: GLint,
199            y: GLint,
200            width: GLsizei,
201            height: GLsizei,
202            border: GLint,
203        ) {
204            match self {
205                Gl::Gl(gl) => unsafe {
206                    gl.CopyTexImage2D(target, level, internal_format, x, y, width, height, border)
207                },
208                Gl::Gles(gles) => unsafe {
209                    gles.CopyTexImage2D(target, level, internal_format, x, y, width, height, border)
210                },
211            }
212        }
213
214        pub fn copy_tex_sub_image_2d(
215            &self,
216            target: GLenum,
217            level: GLint,
218            xoffset: GLint,
219            yoffset: GLint,
220            x: GLint,
221            y: GLint,
222            width: GLsizei,
223            height: GLsizei,
224        ) {
225            match self {
226                Gl::Gl(gl) => unsafe {
227                    gl.CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height)
228                },
229                Gl::Gles(gles) => unsafe {
230                    gles.CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height)
231                },
232            }
233        }
234
235        pub fn compressed_tex_image_2d(
236            &self,
237            target: GLenum,
238            level: GLint,
239            internal_format: GLenum,
240            width: GLsizei,
241            height: GLsizei,
242            border: GLint,
243            data: &[u8],
244        ) {
245            let len = data.len() as GLsizei;
246            let data = data.as_ptr() as *const c_void;
247            match self {
248                Gl::Gl(gl) => unsafe {
249                    gl.CompressedTexImage2D(
250                        target,
251                        level,
252                        internal_format,
253                        width,
254                        height,
255                        border,
256                        len,
257                        data,
258                    )
259                },
260                Gl::Gles(gles) => unsafe {
261                    gles.CompressedTexImage2D(
262                        target,
263                        level,
264                        internal_format,
265                        width,
266                        height,
267                        border,
268                        len,
269                        data,
270                    )
271                },
272            }
273        }
274
275        pub fn compressed_tex_sub_image_2d(
276            &self,
277            target: GLenum,
278            level: GLint,
279            xoffset: GLint,
280            yoffset: GLint,
281            width: GLsizei,
282            height: GLsizei,
283            format: GLenum,
284            data: &[u8],
285        ) {
286            let len = data.len() as GLsizei;
287            let data = data.as_ptr() as *const c_void;
288            match self {
289                Gl::Gl(gl) => unsafe {
290                    gl.CompressedTexSubImage2D(
291                        target, level, xoffset, yoffset, width, height, format, len, data,
292                    )
293                },
294                Gl::Gles(gles) => unsafe {
295                    gles.CompressedTexSubImage2D(
296                        target, level, xoffset, yoffset, width, height, format, len, data,
297                    )
298                },
299            }
300        }
301
302        pub fn tex_storage_2d(
303            &self,
304            target: GLenum,
305            levels: GLsizei,
306            internal_format: GLenum,
307            width: GLsizei,
308            height: GLsizei,
309        ) {
310            match self {
311                Gl::Gl(gl) => unsafe {
312                    gl.TexStorage2D(target, levels, internal_format, width, height)
313                },
314                Gl::Gles(gles) => unsafe {
315                    gles.TexStorage2D(target, levels, internal_format, width, height)
316                },
317            }
318        }
319
320        pub fn tex_storage_3d(
321            &self,
322            target: GLenum,
323            levels: GLsizei,
324            internal_format: GLenum,
325            width: GLsizei,
326            height: GLsizei,
327            depth: GLsizei,
328        ) {
329            match self {
330                Gl::Gl(gl) => unsafe {
331                    gl.TexStorage3D(target, levels, internal_format, width, height, depth)
332                },
333                Gl::Gles(gles) => unsafe {
334                    gles.TexStorage3D(target, levels, internal_format, width, height, depth)
335                },
336            }
337        }
338
339        pub fn generate_mipmap(&self, target: GLenum) {
340            match self {
341                Gl::Gl(gl) => unsafe { gl.GenerateMipmap(target) },
342                Gl::Gles(gles) => unsafe { gles.GenerateMipmap(target) },
343            }
344        }
345
346        pub fn active_texture(&self, texture: GLenum) {
347            match self {
348                Gl::Gl(gl) => unsafe { gl.ActiveTexture(texture) },
349                Gl::Gles(gles) => unsafe { gles.ActiveTexture(texture) },
350            }
351        }
352
353        pub fn attach_shader(&self, program: GLuint, shader: GLuint) {
354            match self {
355                Gl::Gl(gl) => unsafe { gl.AttachShader(program, shader) },
356                Gl::Gles(gles) => unsafe { gles.AttachShader(program, shader) },
357            }
358        }
359
360        pub fn create_shader(&self, shader_type: GLenum) -> GLuint {
361            match self {
362                Gl::Gl(gl) => unsafe { gl.CreateShader(shader_type) },
363                Gl::Gles(gles) => unsafe { gles.CreateShader(shader_type) },
364            }
365        }
366
367        pub fn delete_shader(&self, shader: GLuint) {
368            match self {
369                Gl::Gl(gl) => unsafe { gl.DeleteShader(shader) },
370                Gl::Gles(gles) => unsafe { gles.DeleteShader(shader) },
371            }
372        }
373
374        pub fn detach_shader(&self, program: GLuint, shader: GLuint) {
375            match self {
376                Gl::Gl(gl) => unsafe { gl.DetachShader(program, shader) },
377                Gl::Gles(gles) => unsafe { gles.DetachShader(program, shader) },
378            }
379        }
380
381        pub fn bind_buffer(&self, target: GLenum, buffer: GLuint) {
382            match self {
383                Gl::Gl(gl) => unsafe { gl.BindBuffer(target, buffer) },
384                Gl::Gles(gles) => unsafe { gles.BindBuffer(target, buffer) },
385            }
386        }
387
388        pub fn delete_buffers(&self, buffers: &[GLuint]) {
389            let len = buffers.len() as GLsizei;
390            let buffers = buffers.as_ptr();
391            match self {
392                Gl::Gl(gl) => unsafe { gl.DeleteBuffers(len, buffers) },
393                Gl::Gles(gles) => unsafe { gles.DeleteBuffers(len, buffers) },
394            }
395        }
396
397        pub fn copy_buffer_sub_data(
398            &self,
399            read_target: u32,
400            write_target: u32,
401            read_offset: isize,
402            write_offset: isize,
403            size: isize,
404        ) {
405            match self {
406                Gl::Gl(gl) => unsafe { gl.CopyBufferSubData(read_target, write_target, read_offset, write_offset, size) },
407                Gl::Gles(gles) => unsafe { gles.CopyBufferSubData(read_target, write_target, read_offset, write_offset, size) },
408            }
409        }
410
411        pub fn map_buffer_range(
412            &self,
413            target: GLenum,
414            offset: GLintptr,
415            length: GLsizeiptr,
416            access: GLbitfield,
417        ) -> *mut c_void {
418            match self {
419                Gl::Gl(gl) => unsafe { gl.MapBufferRange(target, offset, length, access) },
420                Gl::Gles(gles) => unsafe { gles.MapBufferRange(target, offset, length, access) },
421            }
422        }
423
424        pub fn unmap_buffer(&self, target: GLenum) {
425            match self {
426                Gl::Gl(gl) => unsafe { gl.UnmapBuffer(target); },
427                Gl::Gles(gles) => unsafe { gles.UnmapBuffer(target); },
428            }
429        }
430
431        pub fn link_program(&self, program: GLuint) {
432            match self {
433                Gl::Gl(gl) => unsafe { gl.LinkProgram(program) },
434                Gl::Gles(gles) => unsafe { gles.LinkProgram(program) },
435            }
436        }
437
438        pub fn validate_program(&self, program: GLuint) {
439            match self {
440                Gl::Gl(gl) => unsafe { gl.ValidateProgram(program) },
441                Gl::Gles(gles) => unsafe { gles.ValidateProgram(program) },
442            }
443        }
444
445        pub fn delete_program(&self, program: GLuint) {
446            match self {
447                Gl::Gl(gl) => unsafe { gl.DeleteProgram(program) },
448                Gl::Gles(gles) => unsafe { gles.DeleteProgram(program) },
449            }
450        }
451
452        pub fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]) {
453            let len = vertex_arrays.len() as GLsizei;
454            match self {
455                Gl::Gl(gl) => unsafe { gl.DeleteVertexArrays(len, vertex_arrays.as_ptr()) },
456                Gl::Gles(gles) => unsafe { gles.DeleteVertexArrays(len, vertex_arrays.as_ptr()) },
457            }
458        }
459
460        pub fn bind_vertex_array(&self, vao: GLuint) {
461            match self {
462                Gl::Gl(gl) => unsafe { gl.BindVertexArray(vao) },
463                Gl::Gles(gles) => unsafe { gles.BindVertexArray(vao) },
464            }
465        }
466
467        pub fn enable_vertex_attrib_array(&self, index: GLuint) {
468            match self {
469                Gl::Gl(gl) => unsafe { gl.EnableVertexAttribArray(index) },
470                Gl::Gles(gles) => unsafe { gles.EnableVertexAttribArray(index) },
471            }
472        }
473
474        pub fn disable_vertex_attrib_array(&self, index: GLuint) {
475            match self {
476                Gl::Gl(gl) => unsafe { gl.DisableVertexAttribArray(index) },
477                Gl::Gles(gles) => unsafe { gles.DisableVertexAttribArray(index) },
478            }
479        }
480
481        pub fn vertex_attrib_4f(
482            &self,
483            index: GLuint,
484            x: GLfloat,
485            y: GLfloat,
486            z: GLfloat,
487            w: GLfloat,
488        ) {
489            match self {
490                Gl::Gl(gl) => unsafe { gl.VertexAttrib4f(index, x, y, z, w) },
491                Gl::Gles(gles) => unsafe { gles.VertexAttrib4f(index, x, y, z, w) },
492            }
493        }
494
495        pub fn vertex_attrib_4i(
496            &self,
497            index: GLuint,
498            x: GLint,
499            y: GLint,
500            z: GLint,
501            w: GLint,
502        ) {
503            match self {
504                Gl::Gl(gl) => unsafe { gl.VertexAttribI4i(index, x, y, z, w) },
505                Gl::Gles(gles) => unsafe { gles.VertexAttribI4i(index, x, y, z, w) },
506            }
507        }
508
509        pub fn vertex_attrib_4ui(
510            &self,
511            index: GLuint,
512            x: GLuint,
513            y: GLuint,
514            z: GLuint,
515            w: GLuint,
516        ) {
517            match self {
518                Gl::Gl(gl) => unsafe { gl.VertexAttribI4ui(index, x, y, z, w) },
519                Gl::Gles(gles) => unsafe { gles.VertexAttribI4ui(index, x, y, z, w) },
520            }
521        }
522
523        pub fn vertex_attrib_pointer_f32(
524            &self,
525            index: GLuint,
526            size: GLint,
527            normalized: bool,
528            stride: GLsizei,
529            offset: GLuint,
530        ) {
531            self.vertex_attrib_pointer(index, size, ffi::FLOAT, normalized, stride, offset)
532        }
533
534        pub fn vertex_attrib_pointer(
535            &self,
536            index: GLuint,
537            size: GLint,
538            type_: GLenum,
539            normalized: bool,
540            stride: GLsizei,
541            offset: GLuint,
542        ) {
543            let normalized = normalized as GLboolean;
544            let offset = offset as *const GLvoid;
545            match self {
546                Gl::Gl(gl) => unsafe {
547                    gl.VertexAttribPointer(index, size, type_, normalized, stride, offset)
548                },
549                Gl::Gles(gles) => unsafe {
550                    gles.VertexAttribPointer(index, size, type_, normalized, stride, offset)
551                },
552            }
553        }
554
555        pub fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) {
556            match self {
557                Gl::Gl(gl) => unsafe { gl.VertexAttribDivisor(index, divisor) },
558                Gl::Gles(gles) => unsafe { gles.VertexAttribDivisor(index, divisor) },
559            }
560        }
561
562        pub fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) {
563            let c_string = CString::new(name).unwrap();
564            match self {
565                Gl::Gl(gl) => unsafe { gl.BindAttribLocation(program, index, c_string.as_ptr()) },
566                Gl::Gles(gles) => unsafe {
567                    gles.BindAttribLocation(program, index, c_string.as_ptr())
568                },
569            }
570        }
571
572        pub unsafe fn get_uniform_iv(
573            &self,
574            program: GLuint,
575            location: GLint,
576            result: &mut [GLint],
577        ) {
578            match self {
579                Gl::Gl(gl) => gl.GetUniformiv(program, location, result.as_mut_ptr()),
580                Gl::Gles(gles) => gles.GetUniformiv(program, location, result.as_mut_ptr()),
581            }
582        }
583
584        pub unsafe fn get_uniform_uiv(
585            &self,
586            program: GLuint,
587            location: GLint,
588            result: &mut [GLuint],
589        ) {
590            match self {
591                Gl::Gl(gl) => gl.GetUniformuiv(program, location, result.as_mut_ptr()),
592                Gl::Gles(gles) => gles.GetUniformuiv(program, location, result.as_mut_ptr()),
593            }
594        }
595
596        pub unsafe fn get_uniform_fv(
597            &self,
598            program: GLuint,
599            location: GLint,
600            result: &mut [GLfloat],
601        ) {
602            match self {
603                Gl::Gl(gl) => gl.GetUniformfv(program, location, result.as_mut_ptr()),
604                Gl::Gles(gles) => gles.GetUniformfv(program, location, result.as_mut_ptr()),
605            }
606        }
607
608        pub fn hint(&self, param_name: GLenum, param_val: GLenum) {
609            match self {
610                Gl::Gl(gl) => unsafe { gl.Hint(param_name, param_val) },
611                Gl::Gles(gles) => unsafe { gles.Hint(param_name, param_val) },
612            }
613        }
614
615        pub fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) {
616            match self {
617                Gl::Gl(gl) => unsafe { gl.BlendColor(r, g, b, a) },
618                Gl::Gles(gles) => unsafe { gles.BlendColor(r, g, b, a) },
619            }
620        }
621
622        pub fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) {
623            match self {
624                Gl::Gl(gl) => unsafe { gl.BlendFunc(sfactor, dfactor) },
625                Gl::Gles(gles) => unsafe { gles.BlendFunc(sfactor, dfactor) },
626            }
627        }
628
629        pub fn blend_func_separate(
630            &self,
631            src_rgb: GLenum,
632            dest_rgb: GLenum,
633            src_alpha: GLenum,
634            dest_alpha: GLenum,
635        ) {
636            match self {
637                Gl::Gl(gl) => unsafe {
638                    gl.BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha)
639                },
640                Gl::Gles(gles) => unsafe {
641                    gles.BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha)
642                },
643            }
644        }
645
646        pub fn blend_equation(&self, mode: GLenum) {
647            match self {
648                Gl::Gl(gl) => unsafe { gl.BlendEquation(mode) },
649                Gl::Gles(gles) => unsafe { gles.BlendEquation(mode) },
650            }
651        }
652
653        pub fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) {
654            match self {
655                Gl::Gl(gl) => unsafe { gl.BlendEquationSeparate(mode_rgb, mode_alpha) },
656                Gl::Gles(gles) => unsafe { gles.BlendEquationSeparate(mode_rgb, mode_alpha) },
657            }
658        }
659
660        pub fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
661            let (r, g, b, a) = (
662                r as GLboolean,
663                g as GLboolean,
664                b as GLboolean,
665                a as GLboolean,
666            );
667            match self {
668                Gl::Gl(gl) => unsafe { gl.ColorMask(r, g, b, a) },
669                Gl::Gles(gles) => unsafe { gles.ColorMask(r, g, b, a) },
670            }
671        }
672
673        pub fn cull_face(&self, mode: GLenum) {
674            match self {
675                Gl::Gl(gl) => unsafe { gl.CullFace(mode) },
676                Gl::Gles(gles) => unsafe { gles.CullFace(mode) },
677            }
678        }
679
680        pub fn front_face(&self, mode: GLenum) {
681            match self {
682                Gl::Gl(gl) => unsafe { gl.FrontFace(mode) },
683                Gl::Gles(gles) => unsafe { gles.FrontFace(mode) },
684            }
685        }
686
687        pub fn depth_func(&self, func: GLenum) {
688            match self {
689                Gl::Gl(gl) => unsafe { gl.DepthFunc(func) },
690                Gl::Gles(gles) => unsafe { gles.DepthFunc(func) },
691            }
692        }
693
694        pub fn depth_mask(&self, flag: bool) {
695            match self {
696                Gl::Gl(gl) => unsafe { gl.DepthMask(flag as GLboolean) },
697                Gl::Gles(gles) => unsafe { gles.DepthMask(flag as GLboolean) },
698            }
699        }
700
701        pub fn depth_range(&self, near: f64, far: f64) {
702            match self {
703                Gl::Gl(gl) => unsafe { gl.DepthRange(near, far) },
704                Gl::Gles(gles) => unsafe { gles.DepthRangef(near as f32, far as f32) },
705            }
706        }
707
708        pub fn line_width(&self, width: GLfloat) {
709            match self {
710                Gl::Gl(gl) => unsafe { gl.LineWidth(width) },
711                Gl::Gles(gles) => unsafe { gles.LineWidth(width) },
712            }
713        }
714
715        pub fn polygon_offset(&self, factor: GLfloat, units: GLfloat) {
716            match self {
717                Gl::Gl(gl) => unsafe { gl.PolygonOffset(factor, units) },
718                Gl::Gles(gles) => unsafe { gles.PolygonOffset(factor, units) },
719            }
720        }
721
722        pub fn sample_coverage(&self, value: GLclampf, invert: bool) {
723            match self {
724                Gl::Gl(gl) => unsafe { gl.SampleCoverage(value, invert as GLboolean) },
725                Gl::Gles(gles) => unsafe { gles.SampleCoverage(value, invert as GLboolean) },
726            }
727        }
728
729        pub fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) {
730            match self {
731                Gl::Gl(gl) => unsafe { gl.ClearColor(r, g, b, a) },
732                Gl::Gles(gles) => unsafe { gles.ClearColor(r, g, b, a) },
733            }
734        }
735
736        pub fn clear_depth(&self, depth: f64) {
737            match self {
738                Gl::Gl(gl) => unsafe { gl.ClearDepth(depth) },
739                Gl::Gles(gles) => unsafe { gles.ClearDepthf(depth as f32) },
740            }
741        }
742
743        pub fn clear_stencil(&self, s: GLint) {
744            match self {
745                Gl::Gl(gl) => unsafe { gl.ClearStencil(s) },
746                Gl::Gles(gles) => unsafe { gles.ClearStencil(s) },
747            }
748        }
749
750        pub fn clear(&self, buffer_mask: GLbitfield) {
751            match self {
752                Gl::Gl(gl) => unsafe { gl.Clear(buffer_mask) },
753                Gl::Gles(gles) => unsafe { gles.Clear(buffer_mask) },
754            }
755        }
756
757        pub fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
758            match self {
759                Gl::Gl(gl) => unsafe { gl.Scissor(x, y, width, height) },
760                Gl::Gles(gles) => unsafe { gles.Scissor(x, y, width, height) },
761            }
762        }
763
764        pub fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
765            match self {
766                Gl::Gl(gl) => unsafe { gl.StencilOp(sfail, dpfail, dppass) },
767                Gl::Gles(gles) => unsafe { gles.StencilOp(sfail, dpfail, dppass) },
768            }
769        }
770
771        pub fn stencil_op_separate(
772            &self,
773            face: GLenum,
774            sfail: GLenum,
775            dpfail: GLenum,
776            dppass: GLenum,
777        ) {
778            match self {
779                Gl::Gl(gl) => unsafe { gl.StencilOpSeparate(face, sfail, dpfail, dppass) },
780                Gl::Gles(gles) => unsafe { gles.StencilOpSeparate(face, sfail, dpfail, dppass) },
781            }
782        }
783
784        pub fn stencil_mask(&self, mask: GLuint) {
785            match self {
786                Gl::Gl(gl) => unsafe { gl.StencilMask(mask) },
787                Gl::Gles(gles) => unsafe { gles.StencilMask(mask) },
788            }
789        }
790
791        pub fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) {
792            match self {
793                Gl::Gl(gl) => unsafe { gl.StencilMaskSeparate(face, mask) },
794                Gl::Gles(gles) => unsafe { gles.StencilMaskSeparate(face, mask) },
795            }
796        }
797
798        pub fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint) {
799            match self {
800                Gl::Gl(gl) => unsafe { gl.StencilFunc(func, ref_, mask) },
801                Gl::Gles(gles) => unsafe { gles.StencilFunc(func, ref_, mask) },
802            }
803        }
804
805        pub fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint) {
806            match self {
807                Gl::Gl(gl) => unsafe { gl.StencilFuncSeparate(face, func, ref_, mask) },
808                Gl::Gles(gles) => unsafe { gles.StencilFuncSeparate(face, func, ref_, mask) },
809            }
810        }
811
812        pub fn is_enabled(&self, cap: GLenum) -> bool {
813            TRUE == match self {
814                Gl::Gl(gl) => unsafe { gl.IsEnabled(cap) },
815                Gl::Gles(gles) => unsafe { gles.IsEnabled(cap) },
816            }
817        }
818
819        pub fn enable(&self, cap: GLenum) {
820            match self {
821                Gl::Gl(gl) => unsafe { gl.Enable(cap) },
822                Gl::Gles(gles) => unsafe { gles.Enable(cap) },
823            }
824        }
825
826        pub fn disable(&self, cap: GLenum) {
827            match self {
828                Gl::Gl(gl) => unsafe { gl.Disable(cap) },
829                Gl::Gles(gles) => unsafe { gles.Disable(cap) },
830            }
831        }
832
833        pub fn finish(&self) {
834            match self {
835                Gl::Gl(gl) => unsafe { gl.Finish() },
836                Gl::Gles(gles) => unsafe { gles.Finish() },
837            }
838        }
839
840        pub fn flush(&self) {
841            match self {
842                Gl::Gl(gl) => unsafe { gl.Flush() },
843                Gl::Gles(gles) => unsafe { gles.Flush() },
844            }
845        }
846
847        pub fn get_string(&self, which: GLenum) -> String {
848            let llstr = match self {
849                Gl::Gl(gl) => unsafe { gl.GetString(which) },
850                Gl::Gles(gles) => unsafe { gles.GetString(which) },
851            };
852            if !llstr.is_null() {
853                unsafe {
854                    str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes())
855                        .to_string()
856                }
857            } else {
858                "".to_string()
859            }
860        }
861
862        pub fn get_string_i(&self, which: GLenum, index: GLuint) -> String {
863            let llstr = match self {
864                Gl::Gl(gl) => unsafe { gl.GetStringi(which, index) },
865                Gl::Gles(gles) => unsafe { gles.GetStringi(which, index) },
866            };
867            if !llstr.is_null() {
868                unsafe {
869                    str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes())
870                        .to_string()
871                }
872            } else {
873                "".to_string()
874            }
875        }
876
877        pub unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]) {
878            assert!(!result.is_empty());
879            match self {
880                Gl::Gl(gl) => gl.GetShaderiv(shader, pname, result.as_mut_ptr()),
881                Gl::Gles(gles) => gles.GetShaderiv(shader, pname, result.as_mut_ptr()),
882            }
883        }
884
885        pub fn get_shader_precision_format(
886            &self,
887            shader_type: GLuint,
888            precision_type: GLuint,
889        ) -> (GLint, GLint, GLint) {
890            match self {
891                Gl::Gl(..) => {
892                    // gl.GetShaderPrecisionFormat is not available until OpenGL 4.1.
893                    // Fall back to OpenGL standard precision that most desktop hardware support.
894                    match precision_type {
895                        ffi::LOW_FLOAT | ffi::MEDIUM_FLOAT | ffi::HIGH_FLOAT => {
896                            // Fallback to IEEE 754 single precision
897                            // Range: from -2^127 to 2^127
898                            // Significand precision: 23 bits
899                            (127, 127, 23)
900                        }
901                        ffi::LOW_INT | ffi::MEDIUM_INT | ffi::HIGH_INT => {
902                            // Fallback to single precision integer
903                            // Range: from -2^24 to 2^24
904                            // Precision: For integer formats this value is always 0
905                            (24, 24, 0)
906                        }
907                        _ => (0, 0, 0),
908                    }
909                }
910                Gl::Gles(gles) => {
911                    let (mut range, mut precision) = match precision_type {
912                        // These values are for a 32-bit twos-complement integer format.
913                        ffi::LOW_INT | ffi::MEDIUM_INT | ffi::HIGH_INT => ([31, 30], 0),
914
915                        // These values are for an IEEE single-precision floating-point format.
916                        ffi::LOW_FLOAT | ffi::MEDIUM_FLOAT | ffi::HIGH_FLOAT => ([127, 127], 23),
917
918                        _ => unreachable!("invalid precision"),
919                    };
920                    // This function is sometimes defined even though it's really just
921                    // a stub, so we need to set range and precision as if it weren't
922                    // defined before calling it. Suppress any error that might occur.
923                    unsafe {
924                        gles.GetShaderPrecisionFormat(
925                            shader_type,
926                            precision_type,
927                            range.as_mut_ptr(),
928                            &mut precision,
929                        );
930                        let _ = gles.GetError();
931                    }
932                    (range[0], range[1], precision)
933                }
934            }
935        }
936
937        pub fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
938            match self {
939                Gl::Gl(gl) => unsafe { gl.Viewport(x, y, width, height) },
940                Gl::Gles(gles) => unsafe { gles.Viewport(x, y, width, height) },
941            }
942        }
943
944        pub fn get_framebuffer_attachment_parameter_iv(
945            &self,
946            target: GLenum,
947            attachment: GLenum,
948            pname: GLenum,
949        ) -> GLint {
950            let mut result = 0;
951            match self {
952                Gl::Gl(gl) => unsafe {
953                    gl.GetFramebufferAttachmentParameteriv(target, attachment, pname, &mut result)
954                },
955                Gl::Gles(gles) => unsafe {
956                    gles.GetFramebufferAttachmentParameteriv(target, attachment, pname, &mut result)
957                },
958            }
959            result
960        }
961
962        pub fn get_internal_format_iv(
963            &self,
964            target: GLenum,
965            internalformat: GLenum,
966            pname: GLenum,
967            result: &mut [GLint],
968        ) {
969            match self {
970                Gl::Gl(gl) => unsafe {
971                    gl.GetInternalformativ(target, internalformat, pname, result.len() as _, result.as_mut_ptr())
972                },
973                Gl::Gles(gles) => unsafe {
974                    gles.GetInternalformativ(target, internalformat, pname, result.len() as _, result.as_mut_ptr())
975                },
976            }
977        }
978
979        pub fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
980            let mut result = 0;
981            match self {
982                Gl::Gl(gl) => unsafe { gl.GetRenderbufferParameteriv(target, pname, &mut result) },
983                Gl::Gles(gles) => unsafe {
984                    gles.GetRenderbufferParameteriv(target, pname, &mut result)
985                },
986            }
987            result
988        }
989
990        pub fn delete_renderbuffers(&self, buffers: &[GLuint]) {
991            match self {
992                Gl::Gl(gl) => unsafe {
993                    gl.DeleteRenderbuffers(buffers.len() as GLsizei, buffers.as_ptr())
994                },
995                Gl::Gles(gles) => unsafe {
996                    gles.DeleteRenderbuffers(buffers.len() as GLsizei, buffers.as_ptr())
997                },
998            }
999        }
1000
1001        pub fn delete_textures(&self, textures: &[GLuint]) {
1002            match self {
1003                Gl::Gl(gl) => unsafe {
1004                    gl.DeleteTextures(textures.len() as GLsizei, textures.as_ptr())
1005                },
1006                Gl::Gles(gles) => unsafe {
1007                    gles.DeleteTextures(textures.len() as GLsizei, textures.as_ptr())
1008                },
1009            }
1010        }
1011
1012        pub fn delete_framebuffers(&self, framebuffers: &[GLuint]) {
1013            match self {
1014                Gl::Gl(gl) => unsafe {
1015                    gl.DeleteFramebuffers(framebuffers.len() as GLsizei, framebuffers.as_ptr())
1016                },
1017                Gl::Gles(gles) => unsafe {
1018                    gles.DeleteFramebuffers(framebuffers.len() as GLsizei, framebuffers.as_ptr())
1019                },
1020            }
1021        }
1022
1023        pub fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) {
1024            match self {
1025                Gl::Gl(gl) => unsafe { gl.BindRenderbuffer(target, renderbuffer) },
1026                Gl::Gles(gles) => unsafe { gles.BindRenderbuffer(target, renderbuffer) },
1027            }
1028        }
1029
1030        pub fn is_renderbuffer(&self, renderbuffer: GLuint) -> bool {
1031            TRUE == match self {
1032                Gl::Gl(gl) => unsafe { gl.IsRenderbuffer(renderbuffer) },
1033                Gl::Gles(gles) => unsafe { gles.IsRenderbuffer(renderbuffer) },
1034            }
1035        }
1036
1037        pub fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) {
1038            match self {
1039                Gl::Gl(gl) => unsafe { gl.BindFramebuffer(target, framebuffer) },
1040                Gl::Gles(gles) => unsafe { gles.BindFramebuffer(target, framebuffer) },
1041            }
1042        }
1043
1044        pub fn is_framebuffer(&self, framebuffer: GLuint) -> bool {
1045            TRUE == match self {
1046                Gl::Gl(gl) => unsafe { gl.IsFramebuffer(framebuffer) },
1047                Gl::Gles(gles) => unsafe { gles.IsFramebuffer(framebuffer) },
1048            }
1049        }
1050
1051        pub fn bind_texture(&self, target: GLenum, texture: GLuint) {
1052            match self {
1053                Gl::Gl(gl) => unsafe { gl.BindTexture(target, texture) },
1054                Gl::Gles(gles) => unsafe { gles.BindTexture(target, texture) },
1055            }
1056        }
1057
1058        pub fn is_texture(&self, texture: GLuint) -> bool {
1059            TRUE == match self {
1060                Gl::Gl(gl) => unsafe { gl.IsTexture(texture) },
1061                Gl::Gles(gles) => unsafe { gles.IsTexture(texture) },
1062            }
1063        }
1064
1065        pub fn is_shader(&self, shader: GLuint) -> bool {
1066            TRUE == match self {
1067                Gl::Gl(gl) => unsafe { gl.IsShader(shader) },
1068                Gl::Gles(gles) => unsafe { gles.IsShader(shader) },
1069            }
1070        }
1071
1072        pub unsafe fn buffer_data(
1073            &self,
1074            target: GLenum,
1075            size: GLsizeiptr,
1076            data: *const GLvoid,
1077            usage: GLenum,
1078        ) {
1079            match self {
1080                Gl::Gl(gl) => gl.BufferData(target, size, data, usage),
1081                Gl::Gles(gles) => gles.BufferData(target, size, data, usage),
1082            }
1083        }
1084
1085        pub unsafe fn buffer_sub_data(
1086            &self,
1087            target: GLenum,
1088            offset: isize,
1089            size: GLsizeiptr,
1090            data: *const GLvoid,
1091        ) {
1092            match self {
1093                Gl::Gl(gl) => gl.BufferSubData(target, offset, size, data),
1094                Gl::Gles(gles) => gles.BufferSubData(target, offset, size, data),
1095            }
1096        }
1097
1098        pub fn read_buffer(&self, buffer: GLenum) {
1099            match self {
1100                Gl::Gl(gl) => unsafe { gl.ReadBuffer(buffer) },
1101                Gl::Gles(gles) => unsafe { gles.ReadBuffer(buffer) },
1102            }
1103        }
1104
1105        pub fn draw_buffers(&self, bufs: &[GLenum]) {
1106            let len = bufs.len() as GLsizei;
1107            match self {
1108                Gl::Gl(gl) => unsafe { gl.DrawBuffers(len, bufs.as_ptr()) },
1109                Gl::Gles(gles) => unsafe { gles.DrawBuffers(len, bufs.as_ptr()) },
1110            }
1111        }
1112
1113        pub fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) {
1114            match self {
1115                Gl::Gl(gl) => unsafe { gl.DrawArrays(mode, first, count) },
1116                Gl::Gles(gles) => unsafe { gles.DrawArrays(mode, first, count) },
1117            }
1118        }
1119
1120        pub fn draw_arrays_instanced(
1121            &self,
1122            mode: GLenum,
1123            first: GLint,
1124            count: GLsizei,
1125            primcount: GLsizei,
1126        ) {
1127            match self {
1128                Gl::Gl(gl) => unsafe { gl.DrawArraysInstanced(mode, first, count, primcount) },
1129                Gl::Gles(gles) => unsafe {
1130                    gles.DrawArraysInstanced(mode, first, count, primcount)
1131                },
1132            }
1133        }
1134
1135        pub fn draw_elements(
1136            &self,
1137            mode: GLenum,
1138            count: GLsizei,
1139            element_type: GLenum,
1140            indices_offset: GLuint,
1141        ) {
1142            match self {
1143                Gl::Gl(gl) => unsafe {
1144                    gl.DrawElements(mode, count, element_type, indices_offset as *const c_void)
1145                },
1146                Gl::Gles(gles) => unsafe {
1147                    gles.DrawElements(mode, count, element_type, indices_offset as *const c_void)
1148                },
1149            }
1150        }
1151
1152        pub fn draw_elements_instanced(
1153            &self,
1154            mode: GLenum,
1155            count: GLsizei,
1156            element_type: GLenum,
1157            indices_offset: GLuint,
1158            primcount: GLsizei,
1159        ) {
1160            match self {
1161                Gl::Gl(gl) => unsafe {
1162                    gl.DrawElementsInstanced(
1163                        mode,
1164                        count,
1165                        element_type,
1166                        indices_offset as *const c_void,
1167                        primcount,
1168                    )
1169                },
1170                Gl::Gles(gles) => unsafe {
1171                    gles.DrawElementsInstanced(
1172                        mode,
1173                        count,
1174                        element_type,
1175                        indices_offset as *const c_void,
1176                        primcount,
1177                    )
1178                },
1179            }
1180        }
1181
1182        pub fn framebuffer_renderbuffer(
1183            &self,
1184            target: GLenum,
1185            attachment: GLenum,
1186            renderbuffertarget: GLenum,
1187            renderbuffer: GLuint,
1188        ) {
1189            match self {
1190                Gl::Gl(gl) => unsafe {
1191                    gl.FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer)
1192                },
1193                Gl::Gles(gles) => unsafe {
1194                    gles.FramebufferRenderbuffer(
1195                        target,
1196                        attachment,
1197                        renderbuffertarget,
1198                        renderbuffer,
1199                    )
1200                },
1201            }
1202        }
1203
1204        pub fn framebuffer_texture_2d(
1205            &self,
1206            target: GLenum,
1207            attachment: GLenum,
1208            textarget: GLenum,
1209            texture: GLuint,
1210            level: GLint,
1211        ) {
1212            match self {
1213                Gl::Gl(gl) => unsafe {
1214                    gl.FramebufferTexture2D(target, attachment, textarget, texture, level)
1215                },
1216                Gl::Gles(gles) => unsafe {
1217                    gles.FramebufferTexture2D(target, attachment, textarget, texture, level)
1218                },
1219            }
1220        }
1221
1222        pub fn framebuffer_texture_layer(
1223            &self,
1224            target: GLenum,
1225            attachment: GLenum,
1226            texture: GLuint,
1227            level: GLint,
1228            layer: GLint,
1229        ) {
1230            match self {
1231                Gl::Gl(gl) => unsafe {
1232                    gl.FramebufferTextureLayer(
1233                        target,
1234                        attachment,
1235                        texture,
1236                        level,
1237                        layer,
1238                    )
1239                },
1240                Gl::Gles(gles) => unsafe {
1241                    gles.FramebufferTextureLayer(
1242                        target,
1243                        attachment,
1244                        texture,
1245                        level,
1246                        layer,
1247                    )
1248                },
1249            }
1250        }
1251
1252        pub fn invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum]) {
1253            match self {
1254                Gl::Gl(gl) => unsafe {
1255                    gl.InvalidateFramebuffer(
1256                        target,
1257                        attachments.len() as GLsizei,
1258                        attachments.as_ptr(),
1259                    )
1260                },
1261                Gl::Gles(gles) => unsafe {
1262                    gles.InvalidateFramebuffer(
1263                        target,
1264                        attachments.len() as GLsizei,
1265                        attachments.as_ptr(),
1266                    )
1267                },
1268            }
1269        }
1270
1271        pub fn invalidate_sub_framebuffer(
1272            &self,
1273            target: GLenum,
1274            attachments: &[GLenum],
1275            x: i32,
1276            y: i32,
1277            width: GLsizei,
1278            height: GLsizei,
1279        ) {
1280            match self {
1281                Gl::Gl(gl) => unsafe {
1282                    gl.InvalidateSubFramebuffer(
1283                        target,
1284                        attachments.len() as GLsizei,
1285                        attachments.as_ptr(),
1286                        x,
1287                        y,
1288                        width,
1289                        height,
1290                    )
1291                },
1292                Gl::Gles(gles) => unsafe {
1293                    gles.InvalidateSubFramebuffer(
1294                        target,
1295                        attachments.len() as GLsizei,
1296                        attachments.as_ptr(),
1297                        x,
1298                        y,
1299                        width,
1300                        height,
1301                    )
1302                },
1303            }
1304        }
1305
1306        pub fn renderbuffer_storage(
1307            &self,
1308            target: GLenum,
1309            internalformat: GLenum,
1310            width: GLsizei,
1311            height: GLsizei,
1312        ) {
1313            match self {
1314                Gl::Gl(gl) => unsafe {
1315                    gl.RenderbufferStorage(target, internalformat, width, height)
1316                },
1317                Gl::Gles(gles) => unsafe {
1318                    gles.RenderbufferStorage(target, internalformat, width, height)
1319                },
1320            }
1321        }
1322
1323        pub fn renderbuffer_storage_multisample(
1324            &self,
1325            target: GLenum,
1326            samples: GLsizei,
1327            internalformat: GLenum,
1328            width: GLsizei,
1329            height: GLsizei,
1330        ) {
1331            match self {
1332                Gl::Gl(gl) => unsafe {
1333                    gl.RenderbufferStorageMultisample(target, samples, internalformat, width, height)
1334                },
1335                Gl::Gles(gles) => unsafe {
1336                    gles.RenderbufferStorageMultisample(target, samples, internalformat, width, height)
1337                },
1338            }
1339        }
1340
1341        pub fn check_framebuffer_status(&self, target: GLenum) -> GLenum {
1342            match self {
1343                Gl::Gl(gl) => unsafe { gl.CheckFramebufferStatus(target) },
1344                Gl::Gles(gles) => unsafe { gles.CheckFramebufferStatus(target) },
1345            }
1346        }
1347
1348        pub fn get_error(&self) -> GLenum {
1349            match self {
1350                Gl::Gl(gl) => unsafe { gl.GetError() },
1351                Gl::Gles(gles) => unsafe { gles.GetError() },
1352            }
1353        }
1354
1355        pub fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) {
1356            match self {
1357                Gl::Gl(gl) => unsafe { gl.TexParameteri(target, pname, param) },
1358                Gl::Gles(gles) => unsafe { gles.TexParameteri(target, pname, param) },
1359            }
1360        }
1361
1362        pub fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) {
1363            match self {
1364                Gl::Gl(gl) => unsafe { gl.TexParameterf(target, pname, param) },
1365                Gl::Gles(gles) => unsafe { gles.TexParameterf(target, pname, param) },
1366            }
1367        }
1368
1369        pub fn get_tex_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
1370            let mut result = 0;
1371            match self {
1372                Gl::Gl(gl) => unsafe { gl.GetTexParameteriv(target, pname, &mut result) },
1373                Gl::Gles(gles) => unsafe { gles.GetTexParameteriv(target, pname, &mut result) },
1374            };
1375            result
1376        }
1377
1378        pub fn get_tex_parameter_fv(&self, target: GLenum, pname: GLenum) -> GLfloat {
1379            let mut result = 0.;
1380            match self {
1381                Gl::Gl(gl) => unsafe { gl.GetTexParameterfv(target, pname, &mut result) },
1382                Gl::Gles(gles) => unsafe { gles.GetTexParameterfv(target, pname, &mut result) },
1383            };
1384            result
1385        }
1386
1387        pub fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1388            let mut buf_size = [0];
1389            unsafe {
1390                self.get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH, &mut buf_size);
1391            }
1392            let mut name = vec![0u8; buf_size[0] as usize];
1393            let mut length = 0 as GLsizei;
1394            let mut size = 0 as i32;
1395            let mut type_ = 0 as u32;
1396            match self {
1397                Gl::Gl(gl) => unsafe {
1398                    gl.GetActiveAttrib(
1399                        program,
1400                        index,
1401                        buf_size[0],
1402                        &mut length,
1403                        &mut size,
1404                        &mut type_,
1405                        name.as_mut_ptr() as *mut GLchar,
1406                    );
1407                },
1408                Gl::Gles(gles) => unsafe {
1409                    gles.GetActiveAttrib(
1410                        program,
1411                        index,
1412                        buf_size[0],
1413                        &mut length,
1414                        &mut size,
1415                        &mut type_,
1416                        name.as_mut_ptr() as *mut GLchar,
1417                    );
1418                },
1419            }
1420            name.truncate(if length > 0 { length as usize } else { 0 });
1421            (size, type_, String::from_utf8(name).unwrap())
1422        }
1423
1424        pub fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1425            let mut buf_size = [0];
1426            unsafe {
1427                self.get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH, &mut buf_size);
1428            }
1429            let mut name = vec![0 as u8; buf_size[0] as usize];
1430            let mut length: GLsizei = 0;
1431            let mut size: i32 = 0;
1432            let mut type_: u32 = 0;
1433
1434            match self {
1435                Gl::Gl(gl) => unsafe {
1436                    gl.GetActiveUniform(
1437                        program,
1438                        index,
1439                        buf_size[0],
1440                        &mut length,
1441                        &mut size,
1442                        &mut type_,
1443                        name.as_mut_ptr() as *mut GLchar,
1444                    );
1445                },
1446                Gl::Gles(gles) => unsafe {
1447                    gles.GetActiveUniform(
1448                        program,
1449                        index,
1450                        buf_size[0],
1451                        &mut length,
1452                        &mut size,
1453                        &mut type_,
1454                        name.as_mut_ptr() as *mut GLchar,
1455                    );
1456                },
1457            }
1458
1459            name.truncate(if length > 0 { length as usize } else { 0 });
1460
1461            (size, type_, String::from_utf8(name).unwrap())
1462        }
1463
1464        pub fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int {
1465            let name = CString::new(name).unwrap();
1466            match self {
1467                Gl::Gl(gl) => unsafe { gl.GetAttribLocation(program, name.as_ptr()) },
1468                Gl::Gles(gles) => unsafe { gles.GetAttribLocation(program, name.as_ptr()) },
1469            }
1470        }
1471
1472        pub fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int {
1473            let name = CString::new(name).unwrap();
1474            match self {
1475                Gl::Gl(gl) => unsafe { gl.GetFragDataLocation(program, name.as_ptr()) },
1476                Gl::Gles(gles) => unsafe { gles.GetFragDataLocation(program, name.as_ptr()) },
1477            }
1478        }
1479
1480        pub fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int {
1481            let name = CString::new(name).unwrap();
1482            match self {
1483                Gl::Gl(gl) => unsafe { gl.GetUniformLocation(program, name.as_ptr()) },
1484                Gl::Gles(gles) => unsafe { gles.GetUniformLocation(program, name.as_ptr()) },
1485            }
1486        }
1487
1488        pub fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint {
1489            let name = CString::new(name).unwrap();
1490            match self {
1491                Gl::Gl(gl) => unsafe { gl.GetUniformBlockIndex(program, name.as_ptr()) },
1492                Gl::Gles(gles) => unsafe { gles.GetUniformBlockIndex(program, name.as_ptr()) },
1493            }
1494        }
1495
1496        pub fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec<GLuint> {
1497            let count = names.len() as GLsizei;
1498            let c_names = names
1499                .iter()
1500                .map(|&name| std::ffi::CString::new(name).unwrap())
1501                .collect::<Vec<_>>();
1502            let c_name_ptrs = c_names
1503                .iter()
1504                .map(|name| name.as_ptr())
1505                .collect::<Vec<_>>();
1506
1507            let mut indices = vec![0 as GLuint; names.len()];
1508            match self {
1509                Gl::Gl(gl) => unsafe {
1510                    gl.GetUniformIndices(
1511                        program,
1512                        count,
1513                        c_name_ptrs.as_ptr(),
1514                        indices.as_mut_ptr(),
1515                    )
1516                },
1517                Gl::Gles(gles) => unsafe {
1518                    gles.GetUniformIndices(
1519                        program,
1520                        count,
1521                        c_name_ptrs.as_ptr(),
1522                        indices.as_mut_ptr(),
1523                    )
1524                },
1525            }
1526            indices
1527        }
1528
1529        pub fn get_active_uniforms_iv(
1530            &self,
1531            program: GLuint,
1532            uniforms: &[GLuint],
1533            pname: GLenum,
1534        ) -> Vec<GLint> {
1535            let mut results = vec![0 as GLint; uniforms.len()];
1536            match self {
1537                Gl::Gl(gl) => unsafe {
1538                    gl.GetActiveUniformsiv(
1539                        program,
1540                        uniforms.len() as GLsizei,
1541                        uniforms.as_ptr(),
1542                        pname,
1543                        results.as_mut_ptr(),
1544                    )
1545                },
1546                Gl::Gles(gles) => unsafe {
1547                    gles.GetActiveUniformsiv(
1548                        program,
1549                        uniforms.len() as GLsizei,
1550                        uniforms.as_ptr(),
1551                        pname,
1552                        results.as_mut_ptr(),
1553                    )
1554                },
1555            }
1556            results
1557        }
1558
1559        pub fn get_active_uniform_block_iv(
1560            &self,
1561            program: GLuint,
1562            index: GLuint,
1563            pname: GLenum,
1564        ) -> Vec<GLint> {
1565            let buf_size = match pname {
1566                ffi::UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES => {
1567                    self.get_active_uniform_block_iv(
1568                        program,
1569                        index,
1570                        ffi::UNIFORM_BLOCK_ACTIVE_UNIFORMS,
1571                    )[0] as usize
1572                },
1573                _ => 1,
1574            };
1575            let mut results = vec![0 as i32; buf_size];
1576            match self {
1577                Gl::Gl(gl) => unsafe {
1578                    gl.GetActiveUniformBlockiv(
1579                        program,
1580                        index,
1581                        pname,
1582                        results.as_mut_ptr(),
1583                    )
1584                },
1585                Gl::Gles(gles) => unsafe {
1586                    gles.GetActiveUniformBlockiv(
1587                        program,
1588                        index,
1589                        pname,
1590                        results.as_mut_ptr(),
1591                    )
1592                },
1593            }
1594            results
1595        }
1596
1597        pub fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String {
1598            let buf_size = self.get_active_uniform_block_iv(program, index, ffi::UNIFORM_BLOCK_NAME_LENGTH)[0];
1599            let mut name = vec![0 as u8; buf_size as usize];
1600            let mut length: GLsizei = 0;
1601
1602            match self {
1603                Gl::Gl(gl) => unsafe {
1604                    gl.GetActiveUniformBlockName(
1605                        program,
1606                        index,
1607                        buf_size,
1608                        &mut length,
1609                        name.as_mut_ptr() as *mut GLchar,
1610                    );
1611                },
1612                Gl::Gles(gles) => unsafe {
1613                    gles.GetActiveUniformBlockName(
1614                        program,
1615                        index,
1616                        buf_size,
1617                        &mut length,
1618                        name.as_mut_ptr() as *mut GLchar,
1619                    );
1620                },
1621            }
1622
1623            name.truncate(if length > 0 { length as usize } else { 0 });
1624            String::from_utf8(name).unwrap()
1625        }
1626
1627        pub fn uniform_block_binding(
1628            &self,
1629            program: GLuint,
1630            uniform_block_index: GLuint,
1631            uniform_block_binding: GLuint,
1632        ) {
1633            match self {
1634                Gl::Gl(gl) => unsafe {
1635                    gl.UniformBlockBinding(
1636                        program,
1637                        uniform_block_index,
1638                        uniform_block_binding,
1639                    )
1640                },
1641                Gl::Gles(gles) => unsafe {
1642                    gles.UniformBlockBinding(
1643                        program,
1644                        uniform_block_index,
1645                        uniform_block_binding,
1646                    )
1647                },
1648            }
1649        }
1650
1651        pub fn bind_buffer_base(&self, program: GLenum, index: GLuint, buffer: GLuint) {
1652            match self {
1653                Gl::Gl(gl) => unsafe { gl.BindBufferBase(program, index, buffer) },
1654                Gl::Gles(gles) => unsafe { gles.BindBufferBase(program, index, buffer) },
1655            }
1656        }
1657
1658        pub fn bind_buffer_range(
1659            &self,
1660            program: GLenum,
1661            index: GLuint,
1662            buffer: GLuint,
1663            offset: GLintptr,
1664            size: GLsizeiptr,
1665        ) {
1666            assert!(offset >= 0);
1667            assert!(size >= 0);
1668            match self {
1669                Gl::Gl(gl) => unsafe { gl.BindBufferRange(program, index, buffer, offset, size) },
1670                Gl::Gles(gles) => unsafe { gles.BindBufferRange(program, index, buffer, offset, size) },
1671            }
1672        }
1673
1674        pub fn get_program_info_log(&self, program: GLuint) -> String {
1675            let mut max_len = [0];
1676            unsafe {
1677                self.get_program_iv(program, ffi::INFO_LOG_LENGTH, &mut max_len);
1678            }
1679            if max_len[0] == 0 {
1680                return String::new();
1681            }
1682            let mut result = vec![0u8; max_len[0] as usize];
1683            let mut result_len = 0 as GLsizei;
1684            let max_len = max_len[0] as GLsizei;
1685            match self {
1686                Gl::Gl(gl) => unsafe {
1687                    gl.GetProgramInfoLog(
1688                        program,
1689                        max_len,
1690                        &mut result_len,
1691                        result.as_mut_ptr() as *mut GLchar,
1692                    )
1693                },
1694                Gl::Gles(gles) => unsafe {
1695                    gles.GetProgramInfoLog(
1696                        program,
1697                        max_len,
1698                        &mut result_len,
1699                        result.as_mut_ptr() as *mut GLchar,
1700                    )
1701                },
1702            }
1703            result.truncate(if result_len > 0 {
1704                result_len as usize
1705            } else {
1706                0
1707            });
1708            String::from_utf8(result).unwrap()
1709        }
1710
1711        pub unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]) {
1712            assert!(!result.is_empty());
1713            match self {
1714                Gl::Gl(gl) => gl.GetProgramiv(program, pname, result.as_mut_ptr()),
1715                Gl::Gles(gles) => gles.GetProgramiv(program, pname, result.as_mut_ptr()),
1716            }
1717        }
1718
1719        pub unsafe fn get_vertex_attrib_fv(
1720            &self,
1721            index: GLuint,
1722            pname: GLenum,
1723            result: &mut [GLfloat],
1724        ) {
1725            assert!(!result.is_empty());
1726            match self {
1727                Gl::Gl(gl) => gl.GetVertexAttribfv(index, pname, result.as_mut_ptr()),
1728                Gl::Gles(gles) => gles.GetVertexAttribfv(index, pname, result.as_mut_ptr()),
1729            }
1730        }
1731
1732        pub fn get_shader_info_log(&self, shader: GLuint) -> String {
1733            let mut max_len = [0];
1734            unsafe {
1735                self.get_shader_iv(shader, ffi::INFO_LOG_LENGTH, &mut max_len);
1736            }
1737            if max_len[0] == 0 {
1738                return String::new();
1739            }
1740            let mut result = vec![0u8; max_len[0] as usize];
1741            let mut result_len = 0 as GLsizei;
1742            let max_len = max_len[0] as GLsizei;
1743            match self {
1744                Gl::Gl(gl) => unsafe {
1745                    gl.GetShaderInfoLog(
1746                        shader,
1747                        max_len,
1748                        &mut result_len,
1749                        result.as_mut_ptr() as *mut GLchar,
1750                    )
1751                },
1752                Gl::Gles(gles) => unsafe {
1753                    gles.GetShaderInfoLog(
1754                        shader,
1755                        max_len,
1756                        &mut result_len,
1757                        result.as_mut_ptr() as *mut GLchar,
1758                    )
1759                },
1760            }
1761            result.truncate(if result_len > 0 {
1762                result_len as usize
1763            } else {
1764                0
1765            });
1766            String::from_utf8(result).unwrap()
1767        }
1768
1769        pub unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]) {
1770            assert!(!result.is_empty());
1771            match self {
1772                Gl::Gl(gl) => gl.GetIntegerv(name, result.as_mut_ptr()),
1773                Gl::Gles(gles) => gles.GetIntegerv(name, result.as_mut_ptr()),
1774            }
1775        }
1776
1777        pub unsafe fn get_integer64_v(&self, name: GLenum, result: &mut [GLint64]) {
1778            assert!(!result.is_empty());
1779            match self {
1780                Gl::Gl(gl) => gl.GetInteger64v(name, result.as_mut_ptr()),
1781                Gl::Gles(gles) => gles.GetInteger64v(name, result.as_mut_ptr()),
1782            }
1783        }
1784
1785        pub unsafe fn get_integeri_v(&self, name: GLenum, index: GLuint, result: &mut [GLint]) {
1786            assert!(!result.is_empty());
1787            match self {
1788                Gl::Gl(gl) => gl.GetIntegeri_v(name, index, result.as_mut_ptr()),
1789                Gl::Gles(gles) => gles.GetIntegeri_v(name, index, result.as_mut_ptr()),
1790            }
1791        }
1792
1793        pub unsafe fn get_integer64i_v(&self, name: GLenum, index: GLuint, result: &mut [GLint64]) {
1794            assert!(!result.is_empty());
1795            match self {
1796                Gl::Gl(gl) => gl.GetInteger64i_v(name, index, result.as_mut_ptr()),
1797                Gl::Gles(gles) => gles.GetInteger64i_v(name, index, result.as_mut_ptr()),
1798            }
1799        }
1800
1801        pub unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]) {
1802            assert!(!result.is_empty());
1803            match self {
1804                Gl::Gl(gl) => gl.GetBooleanv(name, result.as_mut_ptr()),
1805                Gl::Gles(gles) => gles.GetBooleanv(name, result.as_mut_ptr()),
1806            }
1807        }
1808
1809        pub unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]) {
1810            assert!(!result.is_empty());
1811            match self {
1812                Gl::Gl(gl) => gl.GetFloatv(name, result.as_mut_ptr()),
1813                Gl::Gles(gles) => gles.GetFloatv(name, result.as_mut_ptr()),
1814            }
1815        }
1816
1817        pub fn compile_shader(&self, shader: GLuint) {
1818            match self {
1819                Gl::Gl(gl) => unsafe { gl.CompileShader(shader) },
1820                Gl::Gles(gles) => unsafe { gles.CompileShader(shader) },
1821            }
1822        }
1823
1824        pub fn pixel_store_i(&self, name: GLenum, param: GLint) {
1825            match self {
1826                Gl::Gl(gl) => unsafe { gl.PixelStorei(name, param) },
1827                Gl::Gles(gles) => unsafe { gles.PixelStorei(name, param) },
1828            }
1829        }
1830
1831        pub fn read_pixels_into_buffer(
1832            &self,
1833            x: GLint,
1834            y: GLint,
1835            width: GLsizei,
1836            height: GLsizei,
1837            format: GLenum,
1838            pixel_type: GLenum,
1839            buffer: &mut [u8],
1840        ) {
1841            // Assumes that the user properly allocated the size for buffer.
1842            assert_eq!(
1843                calculate_length(width, height, format, pixel_type),
1844                buffer.len()
1845            );
1846
1847            // We don't want any alignment padding on pixel rows.
1848            self.pixel_store_i(ffi::PACK_ALIGNMENT, 1);
1849
1850            match self {
1851                Gl::Gl(gl) => unsafe {
1852                    gl.ReadPixels(
1853                        x,
1854                        y,
1855                        width,
1856                        height,
1857                        format,
1858                        pixel_type,
1859                        buffer.as_mut_ptr() as *mut _,
1860                    )
1861                },
1862                Gl::Gles(gles) => unsafe {
1863                    gles.ReadPixels(
1864                        x,
1865                        y,
1866                        width,
1867                        height,
1868                        format,
1869                        pixel_type,
1870                        buffer.as_mut_ptr() as *mut _,
1871                    )
1872                },
1873            }
1874        }
1875
1876        /// Used when a WebGLBuffer object is bound to PIXEL_PACK_BUFFER.
1877        /// Reads the current pixel buffer into the bound buffer object
1878        /// at the provided offset. Unsafe because no validation is performed
1879        /// to ensure that there is actually a buffer object bound; GL
1880        /// will write at an invalid pointer value in this case.
1881        pub unsafe fn read_pixels_into_pixel_pack_buffer(
1882            &self,
1883            x: GLint,
1884            y: GLint,
1885            width: GLsizei,
1886            height: GLsizei,
1887            format: GLenum,
1888            pixel_type: GLenum,
1889            buffer_byte_offset: usize,
1890        ) {
1891            match self {
1892                Gl::Gl(gl) =>
1893                    gl.ReadPixels(
1894                        x,
1895                        y,
1896                        width,
1897                        height,
1898                        format,
1899                        pixel_type,
1900                        buffer_byte_offset as *mut _,
1901                    ),
1902                Gl::Gles(gles) =>
1903                    gles.ReadPixels(
1904                        x,
1905                        y,
1906                        width,
1907                        height,
1908                        format,
1909                        pixel_type,
1910                        buffer_byte_offset as *mut _,
1911                    ),
1912            }
1913        }
1914
1915        pub fn read_pixels(
1916            &self,
1917            x: GLint,
1918            y: GLint,
1919            width: GLsizei,
1920            height: GLsizei,
1921            format: GLenum,
1922            pixel_type: GLenum,
1923        ) -> Vec<u8> {
1924            let len = calculate_length(width, height, format, pixel_type);
1925            let mut pixels: Vec<u8> = Vec::new();
1926            pixels.reserve(len);
1927            unsafe {
1928                pixels.set_len(len);
1929            }
1930            self.read_pixels_into_buffer(x, y, width, height, format, pixel_type, &mut pixels[..]);
1931            pixels
1932        }
1933
1934        pub fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync {
1935            match self {
1936                Gl::Gl(gl) => unsafe { gl.FenceSync(condition, flags) as GLsync },
1937                Gl::Gles(gles) => unsafe { gles.FenceSync(condition, flags) as GLsync },
1938            }
1939        }
1940
1941        pub fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) -> GLenum {
1942            match self {
1943                Gl::Gl(gl) => unsafe { gl.ClientWaitSync(sync as *const _, flags, timeout) },
1944                Gl::Gles(gles) => unsafe { gles.ClientWaitSync(sync as *const _, flags, timeout) },
1945            }
1946        }
1947
1948        pub fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) {
1949            match self {
1950                Gl::Gl(gl) => unsafe { gl.WaitSync(sync as *const _, flags, timeout) },
1951                Gl::Gles(gles) => unsafe { gles.WaitSync(sync as *const _, flags, timeout) },
1952            };
1953        }
1954
1955        pub fn get_sync_iv(&self, sync: GLsync, pname: GLenum) -> Vec<GLint> {
1956            let mut result = vec![0 as GLint];
1957            match self {
1958                Gl::Gl(gl) => unsafe { gl.GetSynciv(sync as *const _, pname, result.len() as _, ptr::null_mut(), result.as_mut_ptr()); },
1959                Gl::Gles(gles) => unsafe { gles.GetSynciv(sync as *const _, pname, result.len() as _, ptr::null_mut(), result.as_mut_ptr()); },
1960            };
1961            result
1962        }
1963
1964        pub fn is_sync(&self, sync: GLsync) -> bool {
1965            TRUE == match self {
1966                Gl::Gl(gl) => unsafe { gl.IsSync(sync as *const _) as GLboolean },
1967                Gl::Gles(gles) =>  unsafe { gles.IsSync(sync as *const _) as GLboolean },
1968            }
1969        }
1970
1971        pub fn delete_sync(&self, sync: GLsync) {
1972            match self {
1973                Gl::Gl(gl) => unsafe { gl.DeleteSync(sync as *const _) },
1974                Gl::Gles(gles) => unsafe { gles.DeleteSync(sync as *const _) },
1975            }
1976        }
1977
1978        pub fn uniform_1f(&self, location: GLint, v0: GLfloat) {
1979            match self {
1980                Gl::Gl(gl) => unsafe { gl.Uniform1f(location, v0) },
1981                Gl::Gles(gles) => unsafe { gles.Uniform1f(location, v0) },
1982            }
1983        }
1984
1985        pub fn uniform_1fv(&self, location: GLint, values: &[f32]) {
1986            let len = values.len() as GLsizei;
1987            match self {
1988                Gl::Gl(gl) => unsafe { gl.Uniform1fv(location, len, values.as_ptr()) },
1989                Gl::Gles(gles) => unsafe { gles.Uniform1fv(location, len, values.as_ptr()) },
1990            }
1991        }
1992
1993        pub fn uniform_1i(&self, location: GLint, v0: GLint) {
1994            match self {
1995                Gl::Gl(gl) => unsafe { gl.Uniform1i(location, v0) },
1996                Gl::Gles(gles) => unsafe { gles.Uniform1i(location, v0) },
1997            }
1998        }
1999
2000        pub fn uniform_1iv(&self, location: GLint, values: &[i32]) {
2001            let len = values.len() as GLsizei;
2002            match self {
2003                Gl::Gl(gl) => unsafe { gl.Uniform1iv(location, len, values.as_ptr()) },
2004                Gl::Gles(gles) => unsafe { gles.Uniform1iv(location, len, values.as_ptr()) },
2005            }
2006        }
2007
2008        pub fn uniform_1ui(&self, location: GLint, v0: GLuint) {
2009            match self {
2010                Gl::Gl(gl) => unsafe { gl.Uniform1ui(location, v0) },
2011                Gl::Gles(gles) => unsafe { gles.Uniform1ui(location, v0) },
2012            }
2013        }
2014
2015        pub fn uniform_1uiv(&self, location: GLint, values: &[u32]) {
2016            let len = values.len() as GLsizei;
2017            match self {
2018                Gl::Gl(gl) => unsafe { gl.Uniform1uiv(location, len, values.as_ptr()) },
2019                Gl::Gles(gles) => unsafe { gles.Uniform1uiv(location, len, values.as_ptr()) },
2020            }
2021        }
2022
2023        pub fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) {
2024            match self {
2025                Gl::Gl(gl) => unsafe { gl.Uniform2f(location, v0, v1) },
2026                Gl::Gles(gles) => unsafe { gles.Uniform2f(location, v0, v1) },
2027            }
2028        }
2029
2030        pub fn uniform_2fv(&self, location: GLint, values: &[f32]) {
2031            let len = values.len() as GLsizei / 2;
2032            match self {
2033                Gl::Gl(gl) => unsafe { gl.Uniform2fv(location, len, values.as_ptr()) },
2034                Gl::Gles(gles) => unsafe { gles.Uniform2fv(location, len, values.as_ptr()) },
2035            }
2036        }
2037
2038        pub fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) {
2039            match self {
2040                Gl::Gl(gl) => unsafe { gl.Uniform2i(location, v0, v1) },
2041                Gl::Gles(gles) => unsafe { gles.Uniform2i(location, v0, v1) },
2042            }
2043        }
2044
2045        pub fn uniform_2iv(&self, location: GLint, values: &[i32]) {
2046            let len = values.len() as GLsizei / 2;
2047            match self {
2048                Gl::Gl(gl) => unsafe { gl.Uniform2iv(location, len, values.as_ptr()) },
2049                Gl::Gles(gles) => unsafe { gles.Uniform2iv(location, len, values.as_ptr()) },
2050            }
2051        }
2052
2053        pub fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) {
2054            match self {
2055                Gl::Gl(gl) => unsafe { gl.Uniform2ui(location, v0, v1) },
2056                Gl::Gles(gles) => unsafe { gles.Uniform2ui(location, v0, v1) },
2057            }
2058        }
2059
2060        pub fn uniform_2uiv(&self, location: GLint, values: &[u32]) {
2061            let len = values.len() as GLsizei / 2;
2062            match self {
2063                Gl::Gl(gl) => unsafe { gl.Uniform2uiv(location, len, values.as_ptr()) },
2064                Gl::Gles(gles) => unsafe { gles.Uniform2uiv(location, len, values.as_ptr()) },
2065            }
2066        }
2067
2068        pub fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
2069            match self {
2070                Gl::Gl(gl) => unsafe { gl.Uniform3f(location, v0, v1, v2) },
2071                Gl::Gles(gles) => unsafe { gles.Uniform3f(location, v0, v1, v2) },
2072            }
2073        }
2074
2075        pub fn uniform_3fv(&self, location: GLint, values: &[f32]) {
2076            let len = values.len() as GLsizei / 3;
2077            match self {
2078                Gl::Gl(gl) => unsafe { gl.Uniform3fv(location, len, values.as_ptr()) },
2079                Gl::Gles(gles) => unsafe { gles.Uniform3fv(location, len, values.as_ptr()) },
2080            }
2081        }
2082
2083        pub fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) {
2084            match self {
2085                Gl::Gl(gl) => unsafe { gl.Uniform3i(location, v0, v1, v2) },
2086                Gl::Gles(gles) => unsafe { gles.Uniform3i(location, v0, v1, v2) },
2087            }
2088        }
2089
2090        pub fn uniform_3iv(&self, location: GLint, values: &[i32]) {
2091            let len = values.len() as GLsizei / 3;
2092            match self {
2093                Gl::Gl(gl) => unsafe { gl.Uniform3iv(location, len, values.as_ptr()) },
2094                Gl::Gles(gles) => unsafe { gles.Uniform3iv(location, len, values.as_ptr()) },
2095            }
2096        }
2097
2098        pub fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
2099            match self {
2100                Gl::Gl(gl) => unsafe { gl.Uniform3ui(location, v0, v1, v2) },
2101                Gl::Gles(gles) => unsafe { gles.Uniform3ui(location, v0, v1, v2) },
2102            }
2103        }
2104
2105        pub fn uniform_3uiv(&self, location: GLint, values: &[u32]) {
2106            let len = values.len() as GLsizei / 3;
2107            match self {
2108                Gl::Gl(gl) => unsafe { gl.Uniform3uiv(location, len, values.as_ptr()) },
2109                Gl::Gles(gles) => unsafe { gles.Uniform3uiv(location, len, values.as_ptr()) },
2110            }
2111        }
2112
2113        pub fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
2114            match self {
2115                Gl::Gl(gl) => unsafe { gl.Uniform4f(location, x, y, z, w) },
2116                Gl::Gles(gles) => unsafe { gles.Uniform4f(location, x, y, z, w) },
2117            }
2118        }
2119
2120        pub fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) {
2121            match self {
2122                Gl::Gl(gl) => unsafe { gl.Uniform4i(location, x, y, z, w) },
2123                Gl::Gles(gles) => unsafe { gles.Uniform4i(location, x, y, z, w) },
2124            }
2125        }
2126
2127        pub fn uniform_4iv(&self, location: GLint, values: &[i32]) {
2128            let len = values.len() as GLsizei / 4;
2129            match self {
2130                Gl::Gl(gl) => unsafe { gl.Uniform4iv(location, len, values.as_ptr()) },
2131                Gl::Gles(gles) => unsafe { gles.Uniform4iv(location, len, values.as_ptr()) },
2132            }
2133        }
2134
2135        pub fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
2136            match self {
2137                Gl::Gl(gl) => unsafe { gl.Uniform4ui(location, x, y, z, w) },
2138                Gl::Gles(gles) => unsafe { gles.Uniform4ui(location, x, y, z, w) },
2139            }
2140        }
2141
2142        pub fn uniform_4uiv(&self, location: GLint, values: &[u32]) {
2143            let len = values.len() as GLsizei / 4;
2144            match self {
2145                Gl::Gl(gl) => unsafe { gl.Uniform4uiv(location, len, values.as_ptr()) },
2146                Gl::Gles(gles) => unsafe { gles.Uniform4uiv(location, len, values.as_ptr()) },
2147            }
2148        }
2149
2150        pub fn uniform_4fv(&self, location: GLint, values: &[f32]) {
2151            let len = values.len() as GLsizei / 4;
2152            match self {
2153                Gl::Gl(gl) => unsafe { gl.Uniform4fv(location, len, values.as_ptr()) },
2154                Gl::Gles(gles) => unsafe { gles.Uniform4fv(location, len, values.as_ptr()) },
2155            }
2156        }
2157
2158        pub fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, values: &[f32]) {
2159            let len = values.len() as GLsizei / 4;
2160            let transpose = transpose as GLboolean;
2161            match self {
2162                Gl::Gl(gl) => unsafe {
2163                    gl.UniformMatrix2fv(location, len, transpose, values.as_ptr())
2164                },
2165                Gl::Gles(gles) => unsafe {
2166                    gles.UniformMatrix2fv(location, len, transpose, values.as_ptr())
2167                },
2168            }
2169        }
2170
2171        pub fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, values: &[f32]) {
2172            let len = values.len() as GLsizei / 9;
2173            let transpose = transpose as GLboolean;
2174            match self {
2175                Gl::Gl(gl) => unsafe {
2176                    gl.UniformMatrix3fv(location, len, transpose, values.as_ptr())
2177                },
2178                Gl::Gles(gles) => unsafe {
2179                    gles.UniformMatrix3fv(location, len, transpose, values.as_ptr())
2180                },
2181            }
2182        }
2183
2184        pub fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, values: &[f32]) {
2185            let len = values.len() as GLsizei / 16;
2186            let transpose = transpose as GLboolean;
2187            match self {
2188                Gl::Gl(gl) => unsafe {
2189                    gl.UniformMatrix4fv(location, len, transpose, values.as_ptr())
2190                },
2191                Gl::Gles(gles) => unsafe {
2192                    gles.UniformMatrix4fv(location, len, transpose, values.as_ptr())
2193                },
2194            }
2195        }
2196
2197        pub fn uniform_matrix_3x2fv(&self, location: GLint, transpose: bool, values: &[f32]) {
2198            let len = values.len() as GLsizei / (3 * 2);
2199            let transpose = transpose as GLboolean;
2200            match self {
2201                Gl::Gl(gl) => unsafe {
2202                    gl.UniformMatrix3x2fv(location, len, transpose, values.as_ptr())
2203                },
2204                Gl::Gles(gles) => unsafe {
2205                    gles.UniformMatrix3x2fv(location, len, transpose, values.as_ptr())
2206                },
2207            }
2208        }
2209
2210        pub fn uniform_matrix_4x2fv(&self, location: GLint, transpose: bool, values: &[f32]) {
2211            let len = values.len() as GLsizei / (4 * 2);
2212            let transpose = transpose as GLboolean;
2213            match self {
2214                Gl::Gl(gl) => unsafe {
2215                    gl.UniformMatrix4x2fv(location, len, transpose, values.as_ptr())
2216                },
2217                Gl::Gles(gles) => unsafe {
2218                    gles.UniformMatrix4x2fv(location, len, transpose, values.as_ptr())
2219                },
2220            }
2221        }
2222
2223        pub fn uniform_matrix_2x3fv(&self, location: GLint, transpose: bool, values: &[f32]) {
2224            let len = values.len() as GLsizei / (2 * 3);
2225            let transpose = transpose as GLboolean;
2226            match self {
2227                Gl::Gl(gl) => unsafe {
2228                    gl.UniformMatrix2x3fv(location, len, transpose, values.as_ptr())
2229                },
2230                Gl::Gles(gles) => unsafe {
2231                    gles.UniformMatrix2x3fv(location, len, transpose, values.as_ptr())
2232                },
2233            }
2234        }
2235
2236        pub fn uniform_matrix_4x3fv(&self, location: GLint, transpose: bool, values: &[f32]) {
2237            let len = values.len() as GLsizei / (4 * 3);
2238            let transpose = transpose as GLboolean;
2239            match self {
2240                Gl::Gl(gl) => unsafe {
2241                    gl.UniformMatrix4x3fv(location, len, transpose, values.as_ptr())
2242                },
2243                Gl::Gles(gles) => unsafe {
2244                    gles.UniformMatrix4x3fv(location, len, transpose, values.as_ptr())
2245                },
2246            }
2247        }
2248
2249        pub fn uniform_matrix_2x4fv(&self, location: GLint, transpose: bool, values: &[f32]) {
2250            let len = values.len() as GLsizei / (2 * 4);
2251            let transpose = transpose as GLboolean;
2252            match self {
2253                Gl::Gl(gl) => unsafe {
2254                    gl.UniformMatrix2x4fv(location, len, transpose, values.as_ptr())
2255                },
2256                Gl::Gles(gles) => unsafe {
2257                    gles.UniformMatrix2x4fv(location, len, transpose, values.as_ptr())
2258                },
2259            }
2260        }
2261
2262        pub fn uniform_matrix_3x4fv(&self, location: GLint, transpose: bool, values: &[f32]) {
2263            let len = values.len() as GLsizei / (3 * 4);
2264            let transpose = transpose as GLboolean;
2265            match self {
2266                Gl::Gl(gl) => unsafe {
2267                    gl.UniformMatrix3x4fv(location, len, transpose, values.as_ptr())
2268                },
2269                Gl::Gles(gles) => unsafe {
2270                    gles.UniformMatrix3x4fv(location, len, transpose, values.as_ptr())
2271                },
2272            }
2273        }
2274
2275
2276        pub fn use_program(&self, program: GLuint) {
2277            match self {
2278                Gl::Gl(gl) => unsafe { gl.UseProgram(program) },
2279                Gl::Gles(gles) => unsafe { gles.UseProgram(program) },
2280            }
2281        }
2282
2283        pub fn blit_framebuffer(
2284            &self,
2285            src_x0: GLint,
2286            src_y0: GLint,
2287            src_x1: GLint,
2288            src_y1: GLint,
2289            dst_x0: GLint,
2290            dst_y0: GLint,
2291            dst_x1: GLint,
2292            dst_y1: GLint,
2293            mask: GLbitfield,
2294            filter: GLenum,
2295        ) {
2296            match self {
2297                Gl::Gl(gl) => unsafe {
2298                    gl.BlitFramebuffer(
2299                        src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter,
2300                    )
2301                },
2302                Gl::Gles(gles) => unsafe {
2303                    gles.BlitFramebuffer(
2304                        src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter,
2305                    )
2306                },
2307            }
2308        }
2309
2310        pub fn gen_queries(&self, n: GLsizei) -> Vec<GLuint> {
2311            if let Gl::Gles(gles) = self {
2312                if !gles.GenQueriesEXT.is_loaded() {
2313                    return Vec::new();
2314                }
2315            }
2316            let mut result = vec![0 as GLuint; n as usize];
2317            match self {
2318                Gl::Gl(gl) => unsafe { gl.GenQueries(n, result.as_mut_ptr()) },
2319                Gl::Gles(gles) => unsafe { gles.GenQueriesEXT(n, result.as_mut_ptr()) },
2320            };
2321            result
2322        }
2323
2324        pub fn begin_query(&self, target: GLenum, id: GLuint) {
2325            match self {
2326                Gl::Gl(gl) => unsafe { gl.BeginQuery(target, id) },
2327                Gl::Gles(gles) => {
2328                    if gles.BeginQueryEXT.is_loaded() {
2329                        unsafe { gles.BeginQueryEXT(target, id) }
2330                    }
2331                },
2332            }
2333        }
2334
2335        pub fn end_query(&self, target: GLenum) {
2336            match self {
2337                Gl::Gl(gl) => unsafe { gl.EndQuery(target) },
2338                Gl::Gles(gles) => {
2339                    if gles.EndQueryEXT.is_loaded() {
2340                        unsafe { gles.EndQueryEXT(target) }
2341                    }
2342                },
2343            }
2344        }
2345
2346        pub fn delete_queries(&self, ids: &[GLuint]) {
2347            match self {
2348                Gl::Gl(gl) => unsafe { gl.DeleteQueries(ids.len() as GLsizei, ids.as_ptr()) },
2349                Gl::Gles(gles) => {
2350                    if gles.DeleteQueriesEXT.is_loaded() {
2351                        unsafe { gles.DeleteQueriesEXT(ids.len() as GLsizei, ids.as_ptr()) }
2352                    }
2353                },
2354            }
2355        }
2356
2357        pub fn is_query(&self, id: GLuint) -> bool {
2358            TRUE == match self {
2359                Gl::Gl(gl) => unsafe { gl.IsQuery(id) },
2360                Gl::Gles(gles) => {
2361                    match gles.IsQueryEXT.is_loaded() {
2362                        true => unsafe { gles.IsQueryEXT(id) },
2363                        false => FALSE,
2364                    }
2365                },
2366            }
2367        }
2368
2369        pub fn get_query_iv(&self, target: GLenum, pname: GLenum) -> i32 {
2370            let mut result = 0;
2371            match self {
2372                Gl::Gl(gl) => unsafe { gl.GetQueryiv(target, pname, &mut result) },
2373                Gl::Gles(gles) => {
2374                    if gles.GetQueryivEXT.is_loaded() {
2375                        unsafe { gles.GetQueryivEXT(target, pname, &mut result) }
2376                    }
2377                },
2378            };
2379            result
2380        }
2381
2382        pub fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32 {
2383            let mut result = 0;
2384            match self {
2385                Gl::Gl(gl) => unsafe { gl.GetQueryObjectiv(id, pname, &mut result) },
2386                Gl::Gles(gles) => {
2387                    if gles.GetQueryObjectivEXT.is_loaded() {
2388                        unsafe { gles.GetQueryObjectivEXT(id, pname, &mut result) }
2389                    }
2390                },
2391            }
2392            result
2393        }
2394
2395        pub fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32 {
2396            let mut result = 0;
2397            match self {
2398                Gl::Gl(gl) => unsafe { gl.GetQueryObjectuiv(id, pname, &mut result) },
2399                Gl::Gles(gles) => {
2400                    if gles.GetQueryObjectuivEXT.is_loaded() {
2401                        unsafe { gles.GetQueryObjectuivEXT(id, pname, &mut result) }
2402                    }
2403                },
2404            }
2405            result
2406        }
2407
2408        pub fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64 {
2409            let mut result = 0;
2410            match self {
2411                Gl::Gl(gl) => unsafe { gl.GetQueryObjecti64v(id, pname, &mut result) },
2412                Gl::Gles(gles) => {
2413                    if gles.GetQueryObjecti64vEXT.is_loaded() {
2414                        unsafe { gles.GetQueryObjecti64vEXT(id, pname, &mut result) }
2415                    }
2416                },
2417            }
2418            result
2419        }
2420
2421        pub fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64 {
2422            let mut result = 0;
2423            match self {
2424                Gl::Gl(gl) => unsafe { gl.GetQueryObjectui64v(id, pname, &mut result) },
2425                Gl::Gles(gles) => {
2426                    if gles.GetQueryObjectui64vEXT.is_loaded() {
2427                        unsafe { gles.GetQueryObjectui64vEXT(id, pname, &mut result) }
2428                    }
2429                },
2430            }
2431            result
2432        }
2433
2434        pub fn gen_samplers(&self, n: GLsizei) -> Vec<GLuint> {
2435            let mut result = vec![0 as GLuint; n as usize];
2436            match self {
2437                Gl::Gl(gl) => unsafe { gl.GenSamplers(n, result.as_mut_ptr()) },
2438                Gl::Gles(gles) => unsafe { gles.GenSamplers(n, result.as_mut_ptr()) },
2439            };
2440            result
2441        }
2442
2443        pub fn delete_samplers(&self, samplers: &[GLuint]) {
2444            match self {
2445                Gl::Gl(gl) => unsafe { gl.DeleteSamplers(samplers.len() as GLsizei, samplers.as_ptr()) },
2446                Gl::Gles(gles) => unsafe { gles.DeleteSamplers(samplers.len() as GLsizei, samplers.as_ptr()) },
2447            }
2448        }
2449
2450        pub fn is_sampler(&self, sampler: GLuint) -> bool {
2451            TRUE == match self {
2452                Gl::Gl(gl) => unsafe { gl.IsSampler(sampler) },
2453                Gl::Gles(gles) => unsafe { gles.IsSampler(sampler) },
2454            }
2455        }
2456
2457        pub fn bind_sampler(&self, target: GLenum, sampler: GLuint) {
2458            match self {
2459                Gl::Gl(gl) => unsafe { gl.BindSampler(target, sampler) },
2460                Gl::Gles(gles) => unsafe { gles.BindSampler(target, sampler) },
2461            }
2462        }
2463
2464        pub fn get_sampler_parameter_iv(&self, sampler: GLuint, pname: GLenum) -> Vec<GLint> {
2465            let mut result = vec![0 as GLint];
2466            match self {
2467                Gl::Gl(gl) => unsafe { gl.GetSamplerParameteriv(sampler, pname, result.as_mut_ptr()) },
2468                Gl::Gles(gles) => unsafe { gles.GetSamplerParameteriv(sampler, pname, result.as_mut_ptr()) },
2469            }
2470            result
2471        }
2472
2473        pub fn get_sampler_parameter_fv(&self, sampler: GLuint, pname: GLenum) -> Vec<GLfloat> {
2474            let mut result = vec![0.0_f32 as GLfloat];
2475            match self {
2476                Gl::Gl(gl) => unsafe { gl.GetSamplerParameterfv(sampler, pname, result.as_mut_ptr()) },
2477                Gl::Gles(gles) => unsafe { gles.GetSamplerParameterfv(sampler, pname, result.as_mut_ptr()) },
2478            }
2479            result
2480        }
2481
2482        pub fn sampler_parameter_i(&self, sampler: GLuint, pname: GLenum, param: GLint) {
2483            match self {
2484                Gl::Gl(gl) => unsafe { gl.SamplerParameteri(sampler, pname, param) },
2485                Gl::Gles(gles) => unsafe { gles.SamplerParameteri(sampler, pname, param) },
2486            }
2487        }
2488
2489        pub fn sampler_parameter_f(&self, sampler: GLuint, pname: GLenum, param: GLfloat) {
2490            match self {
2491                Gl::Gl(gl) => unsafe { gl.SamplerParameterf(sampler, pname, param) },
2492                Gl::Gles(gles) => unsafe { gles.SamplerParameterf(sampler, pname, param) },
2493            }
2494        }
2495
2496        pub fn sampler_parameter_iv(&self, sampler: GLuint, pname: GLenum, params: &[GLint]) {
2497            assert!(!params.is_empty());
2498            match self {
2499                Gl::Gl(gl) => unsafe { gl.SamplerParameteriv(sampler, pname, params.as_ptr()) },
2500                Gl::Gles(gles) => unsafe { gles.SamplerParameteriv(sampler, pname, params.as_ptr()) },
2501            }
2502        }
2503
2504        pub fn sampler_parameter_fv(&self, sampler: GLuint, pname: GLenum, params: &[GLfloat]) {
2505            assert!(!params.is_empty());
2506            match self {
2507                Gl::Gl(gl) => unsafe { gl.SamplerParameterfv(sampler, pname, params.as_ptr()) },
2508                Gl::Gles(gles) => unsafe { gles.SamplerParameterfv(sampler, pname, params.as_ptr()) },
2509            }
2510        }
2511
2512        pub fn gen_transform_feedbacks(&self) -> u32 {
2513            let mut ids = vec![0 as GLuint];
2514            match self {
2515                Gl::Gl(gl) => unsafe { gl.GenTransformFeedbacks(ids.len() as _, ids.as_mut_ptr()) },
2516                Gl::Gles(gles) => unsafe { gles.GenTransformFeedbacks(ids.len() as _, ids.as_mut_ptr()) },
2517            }
2518            ids[0]
2519        }
2520
2521        pub fn delete_transform_feedbacks(&self, id: GLuint) {
2522            let ids = vec![id];
2523            match self {
2524                Gl::Gl(gl) => unsafe { gl.DeleteTransformFeedbacks(ids.len() as _, ids.as_ptr()) },
2525                Gl::Gles(gles) => unsafe { gles.DeleteTransformFeedbacks(ids.len() as _, ids.as_ptr()) },
2526            }
2527        }
2528
2529        pub fn is_transform_feedback(&self, id: GLuint) -> bool {
2530            TRUE == match self {
2531                Gl::Gl(gl) => unsafe { gl.IsTransformFeedback(id) },
2532                Gl::Gles(gles) => unsafe { gles.IsTransformFeedback(id) },
2533            }
2534        }
2535
2536        pub fn bind_transform_feedback(&self, target: GLenum, id: u32) {
2537            match self {
2538                Gl::Gl(gl) => unsafe { gl.BindTransformFeedback(target, id) },
2539                Gl::Gles(gles) => unsafe { gles.BindTransformFeedback(target, id) },
2540            }
2541        }
2542
2543        pub fn begin_transform_feedback(&self, mode: GLenum) {
2544            match self {
2545                Gl::Gl(gl) => unsafe { gl.BeginTransformFeedback(mode) },
2546                Gl::Gles(gles) => unsafe { gles.BeginTransformFeedback(mode) },
2547            }
2548        }
2549
2550        pub fn end_transform_feedback(&self) {
2551            match self {
2552                Gl::Gl(gl) => unsafe { gl.EndTransformFeedback() },
2553                Gl::Gles(gles) => unsafe { gles.EndTransformFeedback() },
2554            }
2555        }
2556
2557        pub fn pause_transform_feedback(&self) {
2558            match self {
2559                Gl::Gl(gl) => unsafe { gl.PauseTransformFeedback() },
2560                Gl::Gles(gles) => unsafe { gles.PauseTransformFeedback() },
2561            }
2562        }
2563
2564        pub fn resume_transform_feedback(&self) {
2565            match self {
2566                Gl::Gl(gl) => unsafe { gl.ResumeTransformFeedback() },
2567                Gl::Gles(gles) => unsafe { gles.ResumeTransformFeedback() },
2568            }
2569        }
2570
2571        pub fn get_transform_feedback_varying(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
2572            let mut length = 0;
2573            let buf_size = 128;
2574            let mut name = vec![0 as c_char; buf_size as usize];
2575            let mut size = 0;
2576            let mut ty = 0;
2577            match self {
2578                Gl::Gl(gl) => unsafe { gl.GetTransformFeedbackVarying(program, index, buf_size, &mut length, &mut size, &mut ty, name.as_mut_ptr()) },
2579                Gl::Gles(gles) => unsafe { gles.GetTransformFeedbackVarying(program, index, buf_size, &mut length, &mut size, &mut ty, name.as_mut_ptr()) },
2580            }
2581            let name: &[u8] = unsafe { std::slice::from_raw_parts(name.as_ptr() as _, length as usize) };
2582            let name = String::from_utf8(name.to_vec()).unwrap();
2583            (size, ty, name)
2584        }
2585
2586        pub fn transform_feedback_varyings(&self, program: GLuint, varyings: &[String], buffer_mode: GLenum) {
2587            let c_varyings = varyings
2588                .iter()
2589                .map(|varying| {
2590                    std::ffi::CString::new("_u".to_owned() + varying.as_str()).unwrap()
2591                })
2592                .collect::<Vec<_>>();
2593            let pointers: Vec<*const c_char> =
2594                c_varyings.iter().map(|p| p.as_ptr()).collect();
2595            match self {
2596                Gl::Gl(gl) => unsafe { gl.TransformFeedbackVaryings(program, varyings.len() as _, pointers.as_ptr() as _, buffer_mode) },
2597                Gl::Gles(gles) => unsafe { gles.TransformFeedbackVaryings(program, varyings.len() as _, pointers.as_ptr() as _, buffer_mode) },
2598            }
2599        }
2600
2601        pub fn clear_buffer_iv(&self, buffer: GLenum, draw_buffer: GLint, value: &[GLint]) {
2602            match self {
2603                Gl::Gl(gl) => unsafe { gl.ClearBufferiv(buffer, draw_buffer, value.as_ptr()) },
2604                Gl::Gles(gles) => unsafe { gles.ClearBufferiv(buffer, draw_buffer, value.as_ptr()) },
2605            }
2606        }
2607
2608        pub fn clear_buffer_uiv(&self, buffer: GLenum, draw_buffer: GLint, value: &[GLuint]) {
2609            match self {
2610                Gl::Gl(gl) => unsafe { gl.ClearBufferuiv(buffer, draw_buffer, value.as_ptr()) },
2611                Gl::Gles(gles) => unsafe { gles.ClearBufferuiv(buffer, draw_buffer, value.as_ptr()) },
2612            }
2613        }
2614
2615        pub fn clear_buffer_fv(&self, buffer: GLenum, draw_buffer: GLint, value: &[GLfloat]) {
2616            match self {
2617                Gl::Gl(gl) => unsafe { gl.ClearBufferfv(buffer, draw_buffer, value.as_ptr()) },
2618                Gl::Gles(gles) => unsafe { gles.ClearBufferfv(buffer, draw_buffer, value.as_ptr()) },
2619            }
2620        }
2621
2622        pub fn clear_buffer_fi(
2623            &self,
2624            buffer: GLenum,
2625            draw_buffer: GLint,
2626            depth: GLfloat,
2627            stencil: GLint,
2628        ) {
2629            match self {
2630                Gl::Gl(gl) => unsafe { gl.ClearBufferfi(buffer, draw_buffer, depth, stencil) },
2631                Gl::Gles(gles) => unsafe { gles.ClearBufferfi(buffer, draw_buffer, depth, stencil) },
2632            }
2633        }
2634    }
2635
2636    fn calculate_length(
2637        width: GLsizei,
2638        height: GLsizei,
2639        format: GLenum,
2640        pixel_type: GLenum,
2641    ) -> usize {
2642        let colors = match format {
2643            ffi::RED => 1,
2644            ffi::RGB => 3,
2645            ffi::BGR => 3,
2646
2647            ffi::RGBA => 4,
2648            ffi::BGRA => 4,
2649
2650            ffi::ALPHA => 1,
2651            ffi::R16 => 1,
2652            ffi::LUMINANCE => 1,
2653            ffi::DEPTH_COMPONENT => 1,
2654            _ => panic!("unsupported format: {:?}", format),
2655        };
2656        let depth = match pixel_type {
2657            ffi::UNSIGNED_BYTE => 1,
2658            ffi::UNSIGNED_SHORT => 2,
2659            ffi::SHORT => 2,
2660            ffi::FLOAT => 4,
2661            _ => panic!("unsupported pixel_type: {:?}", pixel_type),
2662        };
2663
2664        (width * height * colors * depth) as usize
2665    }
2666
2667    pub fn buffer_data<T>(gl_: &Gl, target: GLenum, data: &[T], usage: GLenum) {
2668        unsafe {
2669            gl_.buffer_data(
2670                target,
2671                (data.len() * size_of::<T>()) as GLsizeiptr,
2672                data.as_ptr() as *const GLvoid,
2673                usage,
2674            )
2675        }
2676    }
2677
2678    pub fn buffer_sub_data<T>(gl_: &Gl, target: GLenum, offset: isize, data: &[T]) {
2679        unsafe {
2680            gl_.buffer_sub_data(
2681                target,
2682                offset,
2683                (data.len() * size_of::<T>()) as GLsizeiptr,
2684                data.as_ptr() as *const GLvoid,
2685            );
2686        }
2687    }
2688
2689    pub mod ffi {
2690        include!(concat!(env!("OUT_DIR"), "/gl_and_gles_bindings.rs"));
2691    }
2692
2693    pub mod ffi_gl {
2694        include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
2695    }
2696
2697    pub mod ffi_gles {
2698        include!(concat!(env!("OUT_DIR"), "/gles_bindings.rs"));
2699    }
2700}