gleam/
gles_fns.rs

1// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10pub struct GlesFns {
11    ffi_gl_: GlesFfi,
12}
13
14impl GlesFns {
15    pub unsafe fn load_with<'a, F>(loadfn: F) -> Rc<dyn Gl>
16    where
17        F: FnMut(&str) -> *const c_void,
18    {
19        let ffi_gl_ = GlesFfi::load_with(loadfn);
20        Rc::new(GlesFns { ffi_gl_: ffi_gl_ }) as Rc<dyn Gl>
21    }
22}
23
24impl Gl for GlesFns {
25    fn get_type(&self) -> GlType {
26        GlType::Gles
27    }
28
29    fn buffer_data_untyped(
30        &self,
31        target: GLenum,
32        size: GLsizeiptr,
33        data: *const GLvoid,
34        usage: GLenum,
35    ) {
36        unsafe {
37            self.ffi_gl_.BufferData(target, size, data, usage);
38        }
39    }
40
41    fn tex_buffer(&self, _target: GLenum, _internal_format: GLenum, _buffer: GLuint) {
42        panic!("not supported")
43    }
44
45    fn buffer_sub_data_untyped(
46        &self,
47        target: GLenum,
48        offset: isize,
49        size: GLsizeiptr,
50        data: *const GLvoid,
51    ) {
52        unsafe {
53            self.ffi_gl_.BufferSubData(target, offset, size, data);
54        }
55    }
56
57    fn map_buffer(&self,
58                  _target: GLenum,
59                  _access: GLbitfield) -> *mut c_void {
60        panic!("not supported")
61    }
62
63    fn map_buffer_range(&self,
64                        target: GLenum,
65                        offset: GLintptr,
66                        length: GLsizeiptr,
67                        access: GLbitfield) -> *mut c_void {
68        unsafe {
69            return self.ffi_gl_.MapBufferRange(target, offset, length, access);
70        }
71    }
72
73    fn unmap_buffer(&self, target: GLenum) -> GLboolean {
74        unsafe {
75            return self.ffi_gl_.UnmapBuffer(target);
76        }
77    }
78
79    fn shader_source(&self, shader: GLuint, strings: &[&[u8]]) {
80        let pointers: Vec<*const u8> = strings.iter().map(|string| (*string).as_ptr()).collect();
81        let lengths: Vec<GLint> = strings.iter().map(|string| string.len() as GLint).collect();
82        unsafe {
83            self.ffi_gl_.ShaderSource(
84                shader,
85                pointers.len() as GLsizei,
86                pointers.as_ptr() as *const *const GLchar,
87                lengths.as_ptr(),
88            );
89        }
90        drop(lengths);
91        drop(pointers);
92    }
93
94    #[allow(unused_variables)]
95    fn read_buffer(&self, mode: GLenum) {
96        panic!("not supported")
97    }
98
99    fn read_pixels_into_buffer(
100        &self,
101        x: GLint,
102        y: GLint,
103        width: GLsizei,
104        height: GLsizei,
105        format: GLenum,
106        pixel_type: GLenum,
107        dst_buffer: &mut [u8],
108    ) {
109        // Assumes that the user properly allocated the size for dst_buffer.
110        let mut row_length = 0;
111        unsafe {
112            self.ffi_gl_.GetIntegerv(ffi::PACK_ROW_LENGTH, &mut row_length as _);
113        }
114        if row_length == 0 {
115            row_length = width;
116        } else {
117            assert!(row_length >= width);
118        }
119        assert_eq!(calculate_length(row_length, height, format, pixel_type), dst_buffer.len());
120
121        unsafe {
122            // We don't want any alignment padding on pixel rows.
123            self.ffi_gl_.PixelStorei(ffi::PACK_ALIGNMENT, 1);
124            self.ffi_gl_.ReadPixels(
125                x,
126                y,
127                width,
128                height,
129                format,
130                pixel_type,
131                dst_buffer.as_mut_ptr() as *mut c_void,
132            );
133        }
134    }
135
136    fn read_pixels(
137        &self,
138        x: GLint,
139        y: GLint,
140        width: GLsizei,
141        height: GLsizei,
142        format: GLenum,
143        pixel_type: GLenum,
144    ) -> Vec<u8> {
145        let len = calculate_length(width, height, format, pixel_type);
146        let mut pixels: Vec<u8> = Vec::new();
147        pixels.reserve(len);
148        unsafe {
149            pixels.set_len(len);
150        }
151
152        self.read_pixels_into_buffer(
153            x,
154            y,
155            width,
156            height,
157            format,
158            pixel_type,
159            pixels.as_mut_slice(),
160        );
161
162        pixels
163    }
164
165    unsafe fn read_pixels_into_pbo(&self,
166                                   x: GLint,
167                                   y: GLint,
168                                   width: GLsizei,
169                                   height: GLsizei,
170                                   format: GLenum,
171                                   pixel_type: GLenum) {
172        self.ffi_gl_.ReadPixels(x, y, width, height, format, pixel_type, ptr::null_mut());
173    }
174
175    fn sample_coverage(&self, value: GLclampf, invert: bool) {
176        unsafe {
177            self.ffi_gl_.SampleCoverage(value, invert as GLboolean);
178        }
179    }
180
181    fn polygon_offset(&self, factor: GLfloat, units: GLfloat) {
182        unsafe {
183            self.ffi_gl_.PolygonOffset(factor, units);
184        }
185    }
186
187    fn pixel_store_i(&self, name: GLenum, param: GLint) {
188        unsafe {
189            self.ffi_gl_.PixelStorei(name, param);
190        }
191    }
192
193    fn gen_buffers(&self, n: GLsizei) -> Vec<GLuint> {
194        let mut result = vec![0 as GLuint; n as usize];
195        unsafe {
196            self.ffi_gl_.GenBuffers(n, result.as_mut_ptr());
197        }
198        result
199    }
200
201    fn gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint> {
202        let mut result = vec![0 as GLuint; n as usize];
203        unsafe {
204            self.ffi_gl_.GenRenderbuffers(n, result.as_mut_ptr());
205        }
206        result
207    }
208
209    fn gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint> {
210        let mut result = vec![0 as GLuint; n as usize];
211        unsafe {
212            self.ffi_gl_.GenFramebuffers(n, result.as_mut_ptr());
213        }
214        result
215    }
216
217    fn gen_textures(&self, n: GLsizei) -> Vec<GLuint> {
218        let mut result = vec![0 as GLuint; n as usize];
219        unsafe {
220            self.ffi_gl_.GenTextures(n, result.as_mut_ptr());
221        }
222        result
223    }
224
225    fn gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint> {
226        let mut result = vec![0 as GLuint; n as usize];
227        unsafe {
228            self.ffi_gl_.GenVertexArrays(n, result.as_mut_ptr());
229        }
230        result
231    }
232
233    fn gen_vertex_arrays_apple(&self, _n: GLsizei) -> Vec<GLuint> {
234        panic!("not supported")
235    }
236
237    fn gen_queries(&self, n: GLsizei) -> Vec<GLuint> {
238        if !self.ffi_gl_.GenQueriesEXT.is_loaded() {
239            return Vec::new();
240        }
241        let mut result = vec![0 as GLuint; n as usize];
242        unsafe {
243            self.ffi_gl_.GenQueriesEXT(n, result.as_mut_ptr());
244        }
245        result
246    }
247
248    fn begin_query(&self, target: GLenum, id: GLuint) {
249        if !self.ffi_gl_.BeginQueryEXT.is_loaded() {
250            return;
251        }
252        unsafe {
253            self.ffi_gl_.BeginQueryEXT(target, id);
254        }
255    }
256
257    fn end_query(&self, target: GLenum) {
258        if !self.ffi_gl_.EndQueryEXT.is_loaded() {
259            return;
260        }
261        unsafe {
262            self.ffi_gl_.EndQueryEXT(target);
263        }
264    }
265
266    fn query_counter(&self, id: GLuint, target: GLenum) {
267        if !self.ffi_gl_.QueryCounterEXT.is_loaded() {
268            return;
269        }
270        unsafe {
271            self.ffi_gl_.QueryCounterEXT(id, target);
272        }
273    }
274
275    fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32 {
276        if !self.ffi_gl_.GetQueryObjectivEXT.is_loaded() {
277            return 0;
278        }
279        let mut result = 0;
280        unsafe {
281            self.ffi_gl_.GetQueryObjectivEXT(id, pname, &mut result);
282        }
283        result
284    }
285
286    fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32 {
287        if !self.ffi_gl_.GetQueryObjectuivEXT.is_loaded() {
288            return 0;
289        }
290        let mut result = 0;
291        unsafe {
292            self.ffi_gl_.GetQueryObjectuivEXT(id, pname, &mut result);
293        }
294        result
295    }
296
297    fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64 {
298        if !self.ffi_gl_.GetQueryObjecti64vEXT.is_loaded() {
299            return 0;
300        }
301        let mut result = 0;
302        unsafe {
303            self.ffi_gl_.GetQueryObjecti64vEXT(id, pname, &mut result);
304        }
305        result
306    }
307
308    fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64 {
309        if !self.ffi_gl_.GetQueryObjectui64vEXT.is_loaded() {
310            return 0;
311        }
312        let mut result = 0;
313        unsafe {
314            self.ffi_gl_.GetQueryObjectui64vEXT(id, pname, &mut result);
315        }
316        result
317    }
318
319    fn delete_queries(&self, queries: &[GLuint]) {
320        if !self.ffi_gl_.DeleteQueriesEXT.is_loaded() {
321            return;
322        }
323        unsafe {
324            self.ffi_gl_
325                .DeleteQueriesEXT(queries.len() as GLsizei, queries.as_ptr());
326        }
327    }
328
329    fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]) {
330        unsafe {
331            self.ffi_gl_
332                .DeleteVertexArrays(vertex_arrays.len() as GLsizei, vertex_arrays.as_ptr());
333        }
334    }
335
336    fn delete_vertex_arrays_apple(&self, _vertex_arrays: &[GLuint]) {
337        panic!("not supported")
338    }
339
340    fn delete_buffers(&self, buffers: &[GLuint]) {
341        unsafe {
342            self.ffi_gl_
343                .DeleteBuffers(buffers.len() as GLsizei, buffers.as_ptr());
344        }
345    }
346
347    fn delete_renderbuffers(&self, renderbuffers: &[GLuint]) {
348        unsafe {
349            self.ffi_gl_
350                .DeleteRenderbuffers(renderbuffers.len() as GLsizei, renderbuffers.as_ptr());
351        }
352    }
353
354    fn delete_framebuffers(&self, framebuffers: &[GLuint]) {
355        unsafe {
356            self.ffi_gl_
357                .DeleteFramebuffers(framebuffers.len() as GLsizei, framebuffers.as_ptr());
358        }
359    }
360
361    fn delete_textures(&self, textures: &[GLuint]) {
362        unsafe {
363            self.ffi_gl_
364                .DeleteTextures(textures.len() as GLsizei, textures.as_ptr());
365        }
366    }
367
368    fn framebuffer_renderbuffer(
369        &self,
370        target: GLenum,
371        attachment: GLenum,
372        renderbuffertarget: GLenum,
373        renderbuffer: GLuint,
374    ) {
375        unsafe {
376            self.ffi_gl_.FramebufferRenderbuffer(
377                target,
378                attachment,
379                renderbuffertarget,
380                renderbuffer,
381            );
382        }
383    }
384
385    fn renderbuffer_storage(
386        &self,
387        target: GLenum,
388        internalformat: GLenum,
389        width: GLsizei,
390        height: GLsizei,
391    ) {
392        unsafe {
393            self.ffi_gl_
394                .RenderbufferStorage(target, internalformat, width, height);
395        }
396    }
397
398    fn depth_func(&self, func: GLenum) {
399        unsafe {
400            self.ffi_gl_.DepthFunc(func);
401        }
402    }
403
404    fn active_texture(&self, texture: GLenum) {
405        unsafe {
406            self.ffi_gl_.ActiveTexture(texture);
407        }
408    }
409
410    fn attach_shader(&self, program: GLuint, shader: GLuint) {
411        unsafe {
412            self.ffi_gl_.AttachShader(program, shader);
413        }
414    }
415
416    fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) {
417        let c_string = CString::new(name).unwrap();
418        unsafe {
419            self.ffi_gl_
420                .BindAttribLocation(program, index, c_string.as_ptr())
421        }
422    }
423
424    // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml
425    unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]) {
426        assert!(!result.is_empty());
427        self.ffi_gl_
428            .GetUniformiv(program, location, result.as_mut_ptr());
429    }
430
431    // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml
432    unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]) {
433        assert!(!result.is_empty());
434        self.ffi_gl_
435            .GetUniformfv(program, location, result.as_mut_ptr());
436    }
437
438    fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint {
439        let c_string = CString::new(name).unwrap();
440        unsafe {
441            self.ffi_gl_
442                .GetUniformBlockIndex(program, c_string.as_ptr())
443        }
444    }
445
446    fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec<GLuint> {
447        let c_strings: Vec<CString> = names.iter().map(|n| CString::new(*n).unwrap()).collect();
448        let pointers: Vec<*const GLchar> = c_strings.iter().map(|string| string.as_ptr()).collect();
449        let mut result = Vec::with_capacity(c_strings.len());
450        unsafe {
451            result.set_len(c_strings.len());
452            self.ffi_gl_.GetUniformIndices(
453                program,
454                pointers.len() as GLsizei,
455                pointers.as_ptr(),
456                result.as_mut_ptr(),
457            );
458        }
459        result
460    }
461
462    fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint) {
463        unsafe {
464            self.ffi_gl_.BindBufferBase(target, index, buffer);
465        }
466    }
467
468    fn bind_buffer_range(
469        &self,
470        target: GLenum,
471        index: GLuint,
472        buffer: GLuint,
473        offset: GLintptr,
474        size: GLsizeiptr,
475    ) {
476        unsafe {
477            self.ffi_gl_
478                .BindBufferRange(target, index, buffer, offset, size);
479        }
480    }
481
482    fn uniform_block_binding(
483        &self,
484        program: GLuint,
485        uniform_block_index: GLuint,
486        uniform_block_binding: GLuint,
487    ) {
488        unsafe {
489            self.ffi_gl_
490                .UniformBlockBinding(program, uniform_block_index, uniform_block_binding);
491        }
492    }
493
494    fn bind_buffer(&self, target: GLenum, buffer: GLuint) {
495        unsafe {
496            self.ffi_gl_.BindBuffer(target, buffer);
497        }
498    }
499
500    fn bind_vertex_array(&self, vao: GLuint) {
501        unsafe {
502            self.ffi_gl_.BindVertexArray(vao);
503        }
504    }
505
506    fn bind_vertex_array_apple(&self, _vao: GLuint) {
507        panic!("not supported")
508    }
509
510    fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) {
511        unsafe {
512            self.ffi_gl_.BindRenderbuffer(target, renderbuffer);
513        }
514    }
515
516    fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) {
517        unsafe {
518            self.ffi_gl_.BindFramebuffer(target, framebuffer);
519        }
520    }
521
522    fn bind_texture(&self, target: GLenum, texture: GLuint) {
523        unsafe {
524            self.ffi_gl_.BindTexture(target, texture);
525        }
526    }
527
528    fn bind_vertex_buffer(&self, binding_index: GLuint, buffer: GLuint, offset: GLintptr, stride: GLint) {
529        unsafe { self.ffi_gl_.BindVertexBuffer(binding_index, buffer, offset, stride) }
530    }
531
532    fn draw_buffers(&self, bufs: &[GLenum]) {
533        unsafe {
534            self.ffi_gl_
535                .DrawBuffers(bufs.len() as GLsizei, bufs.as_ptr());
536        }
537    }
538
539    // FIXME: Does not verify buffer size -- unsafe!
540    fn tex_image_2d(
541        &self,
542        target: GLenum,
543        level: GLint,
544        internal_format: GLint,
545        width: GLsizei,
546        height: GLsizei,
547        border: GLint,
548        format: GLenum,
549        ty: GLenum,
550        opt_data: Option<&[u8]>,
551    ) {
552        match opt_data {
553            Some(data) => unsafe {
554                self.ffi_gl_.TexImage2D(
555                    target,
556                    level,
557                    internal_format,
558                    width,
559                    height,
560                    border,
561                    format,
562                    ty,
563                    data.as_ptr() as *const GLvoid,
564                );
565            },
566            None => unsafe {
567                self.ffi_gl_.TexImage2D(
568                    target,
569                    level,
570                    internal_format,
571                    width,
572                    height,
573                    border,
574                    format,
575                    ty,
576                    ptr::null(),
577                );
578            },
579        }
580    }
581
582    fn compressed_tex_image_2d(
583        &self,
584        target: GLenum,
585        level: GLint,
586        internal_format: GLenum,
587        width: GLsizei,
588        height: GLsizei,
589        border: GLint,
590        data: &[u8],
591    ) {
592        unsafe {
593            self.ffi_gl_.CompressedTexImage2D(
594                target,
595                level,
596                internal_format,
597                width,
598                height,
599                border,
600                data.len() as GLsizei,
601                data.as_ptr() as *const GLvoid,
602            );
603        }
604    }
605
606    fn compressed_tex_sub_image_2d(
607        &self,
608        target: GLenum,
609        level: GLint,
610        xoffset: GLint,
611        yoffset: GLint,
612        width: GLsizei,
613        height: GLsizei,
614        format: GLenum,
615        data: &[u8],
616    ) {
617        unsafe {
618            self.ffi_gl_.CompressedTexSubImage2D(
619                target,
620                level,
621                xoffset,
622                yoffset,
623                width,
624                height,
625                format,
626                data.len() as GLsizei,
627                data.as_ptr() as *const GLvoid,
628            );
629        }
630    }
631
632    // FIXME: Does not verify buffer size -- unsafe!
633    fn tex_image_3d(
634        &self,
635        target: GLenum,
636        level: GLint,
637        internal_format: GLint,
638        width: GLsizei,
639        height: GLsizei,
640        depth: GLsizei,
641        border: GLint,
642        format: GLenum,
643        ty: GLenum,
644        opt_data: Option<&[u8]>,
645    ) {
646        unsafe {
647            let pdata = match opt_data {
648                Some(data) => mem::transmute(data.as_ptr()),
649                None => ptr::null(),
650            };
651            self.ffi_gl_.TexImage3D(
652                target,
653                level,
654                internal_format,
655                width,
656                height,
657                depth,
658                border,
659                format,
660                ty,
661                pdata,
662            );
663        }
664    }
665
666    fn copy_tex_image_2d(
667        &self,
668        target: GLenum,
669        level: GLint,
670        internal_format: GLenum,
671        x: GLint,
672        y: GLint,
673        width: GLsizei,
674        height: GLsizei,
675        border: GLint,
676    ) {
677        unsafe {
678            self.ffi_gl_.CopyTexImage2D(
679                target,
680                level,
681                internal_format,
682                x,
683                y,
684                width,
685                height,
686                border,
687            );
688        }
689    }
690
691    fn copy_tex_sub_image_2d(
692        &self,
693        target: GLenum,
694        level: GLint,
695        xoffset: GLint,
696        yoffset: GLint,
697        x: GLint,
698        y: GLint,
699        width: GLsizei,
700        height: GLsizei,
701    ) {
702        unsafe {
703            self.ffi_gl_
704                .CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
705        }
706    }
707
708    fn copy_tex_sub_image_3d(
709        &self,
710        target: GLenum,
711        level: GLint,
712        xoffset: GLint,
713        yoffset: GLint,
714        zoffset: GLint,
715        x: GLint,
716        y: GLint,
717        width: GLsizei,
718        height: GLsizei,
719    ) {
720        unsafe {
721            self.ffi_gl_.CopyTexSubImage3D(
722                target, level, xoffset, yoffset, zoffset, x, y, width, height,
723            );
724        }
725    }
726
727    fn tex_sub_image_2d(
728        &self,
729        target: GLenum,
730        level: GLint,
731        xoffset: GLint,
732        yoffset: GLint,
733        width: GLsizei,
734        height: GLsizei,
735        format: GLenum,
736        ty: GLenum,
737        data: &[u8],
738    ) {
739        unsafe {
740            self.ffi_gl_.TexSubImage2D(
741                target,
742                level,
743                xoffset,
744                yoffset,
745                width,
746                height,
747                format,
748                ty,
749                data.as_ptr() as *const c_void,
750            );
751        }
752    }
753
754    fn tex_sub_image_2d_pbo(
755        &self,
756        target: GLenum,
757        level: GLint,
758        xoffset: GLint,
759        yoffset: GLint,
760        width: GLsizei,
761        height: GLsizei,
762        format: GLenum,
763        ty: GLenum,
764        offset: usize,
765    ) {
766        unsafe {
767            self.ffi_gl_.TexSubImage2D(
768                target,
769                level,
770                xoffset,
771                yoffset,
772                width,
773                height,
774                format,
775                ty,
776                offset as *const c_void,
777            );
778        }
779    }
780
781    fn tex_sub_image_3d(
782        &self,
783        target: GLenum,
784        level: GLint,
785        xoffset: GLint,
786        yoffset: GLint,
787        zoffset: GLint,
788        width: GLsizei,
789        height: GLsizei,
790        depth: GLsizei,
791        format: GLenum,
792        ty: GLenum,
793        data: &[u8],
794    ) {
795        unsafe {
796            self.ffi_gl_.TexSubImage3D(
797                target,
798                level,
799                xoffset,
800                yoffset,
801                zoffset,
802                width,
803                height,
804                depth,
805                format,
806                ty,
807                data.as_ptr() as *const c_void,
808            );
809        }
810    }
811
812    fn tex_sub_image_3d_pbo(
813        &self,
814        target: GLenum,
815        level: GLint,
816        xoffset: GLint,
817        yoffset: GLint,
818        zoffset: GLint,
819        width: GLsizei,
820        height: GLsizei,
821        depth: GLsizei,
822        format: GLenum,
823        ty: GLenum,
824        offset: usize,
825    ) {
826        unsafe {
827            self.ffi_gl_.TexSubImage3D(
828                target,
829                level,
830                xoffset,
831                yoffset,
832                zoffset,
833                width,
834                height,
835                depth,
836                format,
837                ty,
838                offset as *const c_void,
839            );
840        }
841    }
842
843    fn tex_storage_2d(
844        &self,
845        target: GLenum,
846        levels: GLint,
847        internal_format: GLenum,
848        width: GLsizei,
849        height: GLsizei,
850    ) {
851        unsafe {
852            self.ffi_gl_
853                .TexStorage2D(target, levels, internal_format, width, height);
854        }
855    }
856
857    fn tex_storage_3d(
858        &self,
859        target: GLenum,
860        levels: GLint,
861        internal_format: GLenum,
862        width: GLsizei,
863        height: GLsizei,
864        depth: GLsizei,
865    ) {
866        unsafe {
867            self.ffi_gl_
868                .TexStorage3D(target, levels, internal_format, width, height, depth);
869        }
870    }
871
872    #[allow(unused_variables)]
873    fn get_tex_image_into_buffer(
874        &self,
875        target: GLenum,
876        level: GLint,
877        format: GLenum,
878        ty: GLenum,
879        output: &mut [u8],
880    ) {
881        panic!("not supported");
882    }
883
884    unsafe fn copy_image_sub_data(
885        &self,
886        src_name: GLuint,
887        src_target: GLenum,
888        src_level: GLint,
889        src_x: GLint,
890        src_y: GLint,
891        src_z: GLint,
892        dst_name: GLuint,
893        dst_target: GLenum,
894        dst_level: GLint,
895        dst_x: GLint,
896        dst_y: GLint,
897        dst_z: GLint,
898        src_width: GLsizei,
899        src_height: GLsizei,
900        src_depth: GLsizei,
901    ) {
902        self.ffi_gl_.CopyImageSubDataEXT(
903            src_name, src_target, src_level, src_x, src_y, src_z, dst_name, dst_target, dst_level,
904            dst_x, dst_y, dst_z, src_width, src_height, src_depth,
905        );
906    }
907
908    fn invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum]) {
909        unsafe {
910            self.ffi_gl_.InvalidateFramebuffer(
911                target,
912                attachments.len() as GLsizei,
913                attachments.as_ptr(),
914            );
915        }
916    }
917
918    fn invalidate_sub_framebuffer(
919        &self,
920        target: GLenum,
921        attachments: &[GLenum],
922        xoffset: GLint,
923        yoffset: GLint,
924        width: GLsizei,
925        height: GLsizei,
926    ) {
927        unsafe {
928            self.ffi_gl_.InvalidateSubFramebuffer(
929                target,
930                attachments.len() as GLsizei,
931                attachments.as_ptr(),
932                xoffset,
933                yoffset,
934                width,
935                height,
936            );
937        }
938    }
939
940    #[inline]
941    unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]) {
942        assert!(!result.is_empty());
943        self.ffi_gl_.GetIntegerv(name, result.as_mut_ptr());
944    }
945
946    #[inline]
947    unsafe fn get_integer_64v(&self, name: GLenum, result: &mut [GLint64]) {
948        assert!(!result.is_empty());
949        self.ffi_gl_.GetInteger64v(name, result.as_mut_ptr());
950    }
951
952    #[inline]
953    unsafe fn get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint]) {
954        assert!(!result.is_empty());
955        self.ffi_gl_.GetIntegeri_v(name, index, result.as_mut_ptr());
956    }
957
958    #[inline]
959    unsafe fn get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64]) {
960        assert!(!result.is_empty());
961        self.ffi_gl_
962            .GetInteger64i_v(name, index, result.as_mut_ptr());
963    }
964
965    #[inline]
966    unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]) {
967        assert!(!result.is_empty());
968        self.ffi_gl_.GetBooleanv(name, result.as_mut_ptr());
969    }
970
971    #[inline]
972    unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]) {
973        assert!(!result.is_empty());
974        self.ffi_gl_.GetFloatv(name, result.as_mut_ptr());
975    }
976
977    fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
978        let mut result: GLint = 0;
979        unsafe {
980            self.ffi_gl_
981                .GetRenderbufferParameteriv(target, pname, &mut result);
982        }
983        result
984    }
985
986    fn get_framebuffer_attachment_parameter_iv(
987        &self,
988        target: GLenum,
989        attachment: GLenum,
990        pname: GLenum,
991    ) -> GLint {
992        let mut result: GLint = 0;
993        unsafe {
994            self.ffi_gl_.GetFramebufferAttachmentParameteriv(
995                target,
996                attachment,
997                pname,
998                &mut result,
999            );
1000        }
1001        result
1002    }
1003
1004    fn get_tex_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
1005        let mut result: GLint = 0;
1006        unsafe {
1007            self.ffi_gl_.GetTexParameteriv(target, pname, &mut result);
1008        }
1009        result
1010    }
1011
1012    fn get_tex_parameter_fv(&self, target: GLenum, pname: GLenum) -> GLfloat {
1013        let mut result: GLfloat = 0.0;
1014        unsafe {
1015            self.ffi_gl_.GetTexParameterfv(target, pname, &mut result);
1016        }
1017        result
1018    }
1019
1020    fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) {
1021        unsafe {
1022            self.ffi_gl_.TexParameteri(target, pname, param);
1023        }
1024    }
1025
1026    fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) {
1027        unsafe {
1028            self.ffi_gl_.TexParameterf(target, pname, param);
1029        }
1030    }
1031
1032    fn framebuffer_texture_2d(
1033        &self,
1034        target: GLenum,
1035        attachment: GLenum,
1036        textarget: GLenum,
1037        texture: GLuint,
1038        level: GLint,
1039    ) {
1040        unsafe {
1041            self.ffi_gl_
1042                .FramebufferTexture2D(target, attachment, textarget, texture, level);
1043        }
1044    }
1045
1046    fn framebuffer_texture_layer(
1047        &self,
1048        target: GLenum,
1049        attachment: GLenum,
1050        texture: GLuint,
1051        level: GLint,
1052        layer: GLint,
1053    ) {
1054        unsafe {
1055            self.ffi_gl_
1056                .FramebufferTextureLayer(target, attachment, texture, level, layer);
1057        }
1058    }
1059
1060    fn blit_framebuffer(
1061        &self,
1062        src_x0: GLint,
1063        src_y0: GLint,
1064        src_x1: GLint,
1065        src_y1: GLint,
1066        dst_x0: GLint,
1067        dst_y0: GLint,
1068        dst_x1: GLint,
1069        dst_y1: GLint,
1070        mask: GLbitfield,
1071        filter: GLenum,
1072    ) {
1073        unsafe {
1074            self.ffi_gl_.BlitFramebuffer(
1075                src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter,
1076            );
1077        }
1078    }
1079
1080    fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
1081        unsafe { self.ffi_gl_.VertexAttrib4f(index, x, y, z, w) }
1082    }
1083
1084    fn vertex_attrib_binding(&self, attrib_index: GLuint, binding_index: GLuint) {
1085        unsafe { self.ffi_gl_.VertexAttribBinding(attrib_index, binding_index) }
1086    }
1087
1088    fn vertex_attrib_pointer_f32(
1089        &self,
1090        index: GLuint,
1091        size: GLint,
1092        normalized: bool,
1093        stride: GLsizei,
1094        offset: GLuint,
1095    ) {
1096        unsafe {
1097            self.ffi_gl_.VertexAttribPointer(
1098                index,
1099                size,
1100                ffi::FLOAT,
1101                normalized as GLboolean,
1102                stride,
1103                offset as *const GLvoid,
1104            )
1105        }
1106    }
1107
1108    fn vertex_attrib_pointer(
1109        &self,
1110        index: GLuint,
1111        size: GLint,
1112        type_: GLenum,
1113        normalized: bool,
1114        stride: GLsizei,
1115        offset: GLuint,
1116    ) {
1117        unsafe {
1118            self.ffi_gl_.VertexAttribPointer(
1119                index,
1120                size,
1121                type_,
1122                normalized as GLboolean,
1123                stride,
1124                offset as *const GLvoid,
1125            )
1126        }
1127    }
1128
1129    fn vertex_attrib_i_pointer(
1130        &self,
1131        index: GLuint,
1132        size: GLint,
1133        type_: GLenum,
1134        stride: GLsizei,
1135        offset: GLuint,
1136    ) {
1137        unsafe {
1138            self.ffi_gl_
1139                .VertexAttribIPointer(index, size, type_, stride, offset as *const GLvoid)
1140        }
1141    }
1142
1143    fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) {
1144        unsafe { self.ffi_gl_.VertexAttribDivisor(index, divisor) }
1145    }
1146
1147    fn vertex_attrib_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, normalized: bool, relative_offset: GLuint) {
1148        unsafe { self.ffi_gl_.VertexAttribFormat(attrib_index, size, type_, normalized as GLboolean, relative_offset) }
1149    }
1150
1151    fn vertex_attrib_i_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, relative_offset: GLuint) {
1152        unsafe { self.ffi_gl_.VertexAttribIFormat(attrib_index, size, type_, relative_offset) }
1153    }
1154
1155    fn vertex_binding_divisor(&self, binding_index: GLuint, divisor: GLuint) {
1156        unsafe { self.ffi_gl_.VertexBindingDivisor(binding_index, divisor) }
1157    }
1158
1159    fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
1160        unsafe {
1161            self.ffi_gl_.Viewport(x, y, width, height);
1162        }
1163    }
1164
1165    fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
1166        unsafe {
1167            self.ffi_gl_.Scissor(x, y, width, height);
1168        }
1169    }
1170
1171    fn line_width(&self, width: GLfloat) {
1172        unsafe {
1173            self.ffi_gl_.LineWidth(width);
1174        }
1175    }
1176
1177    fn use_program(&self, program: GLuint) {
1178        unsafe {
1179            self.ffi_gl_.UseProgram(program);
1180        }
1181    }
1182
1183    fn validate_program(&self, program: GLuint) {
1184        unsafe {
1185            self.ffi_gl_.ValidateProgram(program);
1186        }
1187    }
1188
1189    fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) {
1190        unsafe {
1191            return self.ffi_gl_.DrawArrays(mode, first, count);
1192        }
1193    }
1194
1195    fn draw_arrays_instanced(
1196        &self,
1197        mode: GLenum,
1198        first: GLint,
1199        count: GLsizei,
1200        primcount: GLsizei,
1201    ) {
1202        unsafe {
1203            return self
1204                .ffi_gl_
1205                .DrawArraysInstanced(mode, first, count, primcount);
1206        }
1207    }
1208
1209    fn draw_elements(
1210        &self,
1211        mode: GLenum,
1212        count: GLsizei,
1213        element_type: GLenum,
1214        indices_offset: GLuint,
1215    ) {
1216        unsafe {
1217            return self.ffi_gl_.DrawElements(
1218                mode,
1219                count,
1220                element_type,
1221                indices_offset as *const c_void,
1222            );
1223        }
1224    }
1225
1226    fn draw_elements_instanced(
1227        &self,
1228        mode: GLenum,
1229        count: GLsizei,
1230        element_type: GLenum,
1231        indices_offset: GLuint,
1232        primcount: GLsizei,
1233    ) {
1234        unsafe {
1235            return self.ffi_gl_.DrawElementsInstanced(
1236                mode,
1237                count,
1238                element_type,
1239                indices_offset as *const c_void,
1240                primcount,
1241            );
1242        }
1243    }
1244
1245    fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) {
1246        unsafe {
1247            self.ffi_gl_.BlendColor(r, g, b, a);
1248        }
1249    }
1250
1251    fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) {
1252        unsafe {
1253            self.ffi_gl_.BlendFunc(sfactor, dfactor);
1254        }
1255    }
1256
1257    fn blend_func_separate(
1258        &self,
1259        src_rgb: GLenum,
1260        dest_rgb: GLenum,
1261        src_alpha: GLenum,
1262        dest_alpha: GLenum,
1263    ) {
1264        unsafe {
1265            self.ffi_gl_
1266                .BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha);
1267        }
1268    }
1269
1270    fn blend_equation(&self, mode: GLenum) {
1271        unsafe {
1272            self.ffi_gl_.BlendEquation(mode);
1273        }
1274    }
1275
1276    fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) {
1277        unsafe {
1278            self.ffi_gl_.BlendEquationSeparate(mode_rgb, mode_alpha);
1279        }
1280    }
1281
1282    fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
1283        unsafe {
1284            self.ffi_gl_.ColorMask(
1285                r as GLboolean,
1286                g as GLboolean,
1287                b as GLboolean,
1288                a as GLboolean,
1289            );
1290        }
1291    }
1292
1293    fn cull_face(&self, mode: GLenum) {
1294        unsafe {
1295            self.ffi_gl_.CullFace(mode);
1296        }
1297    }
1298
1299    fn front_face(&self, mode: GLenum) {
1300        unsafe {
1301            self.ffi_gl_.FrontFace(mode);
1302        }
1303    }
1304
1305    fn enable(&self, cap: GLenum) {
1306        unsafe {
1307            self.ffi_gl_.Enable(cap);
1308        }
1309    }
1310
1311    fn disable(&self, cap: GLenum) {
1312        unsafe {
1313            self.ffi_gl_.Disable(cap);
1314        }
1315    }
1316
1317    fn hint(&self, param_name: GLenum, param_val: GLenum) {
1318        unsafe {
1319            self.ffi_gl_.Hint(param_name, param_val);
1320        }
1321    }
1322
1323    fn is_enabled(&self, cap: GLenum) -> GLboolean {
1324        unsafe { self.ffi_gl_.IsEnabled(cap) }
1325    }
1326
1327    fn is_shader(&self, shader: GLuint) -> GLboolean {
1328        unsafe { self.ffi_gl_.IsShader(shader) }
1329    }
1330
1331    fn is_texture(&self, texture: GLenum) -> GLboolean {
1332        unsafe { self.ffi_gl_.IsTexture(texture) }
1333    }
1334
1335    fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean {
1336        unsafe { self.ffi_gl_.IsFramebuffer(framebuffer) }
1337    }
1338
1339    fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean {
1340        unsafe { self.ffi_gl_.IsRenderbuffer(renderbuffer) }
1341    }
1342
1343    fn check_frame_buffer_status(&self, target: GLenum) -> GLenum {
1344        unsafe { self.ffi_gl_.CheckFramebufferStatus(target) }
1345    }
1346
1347    fn enable_vertex_attrib_array(&self, index: GLuint) {
1348        unsafe {
1349            self.ffi_gl_.EnableVertexAttribArray(index);
1350        }
1351    }
1352
1353    fn disable_vertex_attrib_array(&self, index: GLuint) {
1354        unsafe {
1355            self.ffi_gl_.DisableVertexAttribArray(index);
1356        }
1357    }
1358
1359    fn uniform_1f(&self, location: GLint, v0: GLfloat) {
1360        unsafe {
1361            self.ffi_gl_.Uniform1f(location, v0);
1362        }
1363    }
1364
1365    fn uniform_1fv(&self, location: GLint, values: &[f32]) {
1366        unsafe {
1367            self.ffi_gl_
1368                .Uniform1fv(location, values.len() as GLsizei, values.as_ptr());
1369        }
1370    }
1371
1372    fn uniform_1i(&self, location: GLint, v0: GLint) {
1373        unsafe {
1374            self.ffi_gl_.Uniform1i(location, v0);
1375        }
1376    }
1377
1378    fn uniform_1iv(&self, location: GLint, values: &[i32]) {
1379        unsafe {
1380            self.ffi_gl_
1381                .Uniform1iv(location, values.len() as GLsizei, values.as_ptr());
1382        }
1383    }
1384
1385    #[allow(unused_variables)]
1386    fn uniform_1ui(&self, location: GLint, v0: GLuint) {
1387        panic!("not supported")
1388    }
1389
1390    fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) {
1391        unsafe {
1392            self.ffi_gl_.Uniform2f(location, v0, v1);
1393        }
1394    }
1395
1396    fn uniform_2fv(&self, location: GLint, values: &[f32]) {
1397        unsafe {
1398            self.ffi_gl_
1399                .Uniform2fv(location, (values.len() / 2) as GLsizei, values.as_ptr());
1400        }
1401    }
1402
1403    fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) {
1404        unsafe {
1405            self.ffi_gl_.Uniform2i(location, v0, v1);
1406        }
1407    }
1408
1409    fn uniform_2iv(&self, location: GLint, values: &[i32]) {
1410        unsafe {
1411            self.ffi_gl_
1412                .Uniform2iv(location, (values.len() / 2) as GLsizei, values.as_ptr());
1413        }
1414    }
1415
1416    #[allow(unused_variables)]
1417    fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) {
1418        panic!("not supported")
1419    }
1420
1421    fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
1422        unsafe {
1423            self.ffi_gl_.Uniform3f(location, v0, v1, v2);
1424        }
1425    }
1426
1427    fn uniform_3fv(&self, location: GLint, values: &[f32]) {
1428        unsafe {
1429            self.ffi_gl_
1430                .Uniform3fv(location, (values.len() / 3) as GLsizei, values.as_ptr());
1431        }
1432    }
1433
1434    fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) {
1435        unsafe {
1436            self.ffi_gl_.Uniform3i(location, v0, v1, v2);
1437        }
1438    }
1439
1440    fn uniform_3iv(&self, location: GLint, values: &[i32]) {
1441        unsafe {
1442            self.ffi_gl_
1443                .Uniform3iv(location, (values.len() / 3) as GLsizei, values.as_ptr());
1444        }
1445    }
1446
1447    #[allow(unused_variables)]
1448    fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
1449        panic!("not supported")
1450    }
1451
1452    fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
1453        unsafe {
1454            self.ffi_gl_.Uniform4f(location, x, y, z, w);
1455        }
1456    }
1457
1458    fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) {
1459        unsafe {
1460            self.ffi_gl_.Uniform4i(location, x, y, z, w);
1461        }
1462    }
1463
1464    fn uniform_4iv(&self, location: GLint, values: &[i32]) {
1465        unsafe {
1466            self.ffi_gl_
1467                .Uniform4iv(location, (values.len() / 4) as GLsizei, values.as_ptr());
1468        }
1469    }
1470
1471    #[allow(unused_variables)]
1472    fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
1473        panic!("not supported")
1474    }
1475
1476    fn uniform_4fv(&self, location: GLint, values: &[f32]) {
1477        unsafe {
1478            self.ffi_gl_
1479                .Uniform4fv(location, (values.len() / 4) as GLsizei, values.as_ptr());
1480        }
1481    }
1482
1483    fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1484        unsafe {
1485            self.ffi_gl_.UniformMatrix2fv(
1486                location,
1487                (value.len() / 4) as GLsizei,
1488                transpose as GLboolean,
1489                value.as_ptr(),
1490            );
1491        }
1492    }
1493
1494    fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1495        unsafe {
1496            self.ffi_gl_.UniformMatrix3fv(
1497                location,
1498                (value.len() / 9) as GLsizei,
1499                transpose as GLboolean,
1500                value.as_ptr(),
1501            );
1502        }
1503    }
1504
1505    fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1506        unsafe {
1507            self.ffi_gl_.UniformMatrix4fv(
1508                location,
1509                (value.len() / 16) as GLsizei,
1510                transpose as GLboolean,
1511                value.as_ptr(),
1512            );
1513        }
1514    }
1515
1516    fn depth_mask(&self, flag: bool) {
1517        unsafe {
1518            self.ffi_gl_.DepthMask(flag as GLboolean);
1519        }
1520    }
1521
1522    fn depth_range(&self, near: f64, far: f64) {
1523        unsafe {
1524            self.ffi_gl_.DepthRangef(near as GLclampf, far as GLclampf);
1525        }
1526    }
1527
1528    fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1529        let mut buf_size = [0];
1530        unsafe {
1531            self.get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH, &mut buf_size);
1532        }
1533        let mut name = vec![0u8; buf_size[0] as usize];
1534        let mut length = 0 as GLsizei;
1535        let mut size = 0 as i32;
1536        let mut type_ = 0 as u32;
1537        unsafe {
1538            self.ffi_gl_.GetActiveAttrib(
1539                program,
1540                index,
1541                buf_size[0],
1542                &mut length,
1543                &mut size,
1544                &mut type_,
1545                name.as_mut_ptr() as *mut GLchar,
1546            );
1547        }
1548        name.truncate(if length > 0 { length as usize } else { 0 });
1549        (size, type_, String::from_utf8(name).unwrap())
1550    }
1551
1552    fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1553        let mut buf_size = [0];
1554        unsafe {
1555            self.get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH, &mut buf_size);
1556        }
1557        let mut name = vec![0 as u8; buf_size[0] as usize];
1558        let mut length: GLsizei = 0;
1559        let mut size: i32 = 0;
1560        let mut type_: u32 = 0;
1561
1562        unsafe {
1563            self.ffi_gl_.GetActiveUniform(
1564                program,
1565                index,
1566                buf_size[0],
1567                &mut length,
1568                &mut size,
1569                &mut type_,
1570                name.as_mut_ptr() as *mut GLchar,
1571            );
1572        }
1573
1574        name.truncate(if length > 0 { length as usize } else { 0 });
1575
1576        (size, type_, String::from_utf8(name).unwrap())
1577    }
1578
1579    fn get_active_uniforms_iv(
1580        &self,
1581        program: GLuint,
1582        indices: Vec<GLuint>,
1583        pname: GLenum,
1584    ) -> Vec<GLint> {
1585        let mut result = Vec::with_capacity(indices.len());
1586        unsafe {
1587            result.set_len(indices.len());
1588            self.ffi_gl_.GetActiveUniformsiv(
1589                program,
1590                indices.len() as GLsizei,
1591                indices.as_ptr(),
1592                pname,
1593                result.as_mut_ptr(),
1594            );
1595        }
1596        result
1597    }
1598
1599    fn get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint {
1600        let mut result = 0 as GLint;
1601        unsafe {
1602            self.ffi_gl_
1603                .GetActiveUniformBlockiv(program, index, pname, &mut result);
1604        }
1605        result
1606    }
1607
1608    fn get_active_uniform_block_iv(
1609        &self,
1610        program: GLuint,
1611        index: GLuint,
1612        pname: GLenum,
1613    ) -> Vec<GLint> {
1614        let count =
1615            self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_ACTIVE_UNIFORMS);
1616        let mut result = Vec::with_capacity(count as usize);
1617        unsafe {
1618            result.set_len(count as usize);
1619            self.ffi_gl_
1620                .GetActiveUniformBlockiv(program, index, pname, result.as_mut_ptr());
1621        }
1622        result
1623    }
1624
1625    fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String {
1626        let buf_size =
1627            self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_NAME_LENGTH);
1628        let mut name = vec![0 as u8; buf_size as usize];
1629        let mut length: GLsizei = 0;
1630        unsafe {
1631            self.ffi_gl_.GetActiveUniformBlockName(
1632                program,
1633                index,
1634                buf_size,
1635                &mut length,
1636                name.as_mut_ptr() as *mut GLchar,
1637            );
1638        }
1639        name.truncate(if length > 0 { length as usize } else { 0 });
1640
1641        String::from_utf8(name).unwrap()
1642    }
1643
1644    fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int {
1645        let name = CString::new(name).unwrap();
1646        unsafe { self.ffi_gl_.GetAttribLocation(program, name.as_ptr()) }
1647    }
1648
1649    #[allow(unused_variables)]
1650    fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int {
1651        panic!("not supported")
1652    }
1653
1654    fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int {
1655        let name = CString::new(name).unwrap();
1656        unsafe { self.ffi_gl_.GetUniformLocation(program, name.as_ptr()) }
1657    }
1658
1659    fn get_program_info_log(&self, program: GLuint) -> String {
1660        let mut max_len = [0];
1661        unsafe {
1662            self.get_program_iv(program, ffi::INFO_LOG_LENGTH, &mut max_len);
1663        }
1664        if max_len[0] == 0 {
1665            return String::new();
1666        }
1667        let mut result = vec![0u8; max_len[0] as usize];
1668        let mut result_len = 0 as GLsizei;
1669        unsafe {
1670            self.ffi_gl_.GetProgramInfoLog(
1671                program,
1672                max_len[0] as GLsizei,
1673                &mut result_len,
1674                result.as_mut_ptr() as *mut GLchar,
1675            );
1676        }
1677        result.truncate(if result_len > 0 {
1678            result_len as usize
1679        } else {
1680            0
1681        });
1682        String::from_utf8(result).unwrap()
1683    }
1684
1685    #[inline]
1686    unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]) {
1687        assert!(!result.is_empty());
1688        self.ffi_gl_
1689            .GetProgramiv(program, pname, result.as_mut_ptr());
1690    }
1691
1692    fn get_program_binary(&self, program: GLuint) -> (Vec<u8>, GLenum) {
1693        let mut len = [0];
1694        unsafe {
1695            self.get_program_iv(program, ffi::PROGRAM_BINARY_LENGTH, &mut len);
1696        }
1697        if len[0] <= 0 {
1698            return (Vec::new(), NONE);
1699        }
1700        let mut binary: Vec<u8> = Vec::with_capacity(len[0] as usize);
1701        let mut format = NONE;
1702        let mut out_len = 0;
1703        unsafe {
1704            binary.set_len(len[0] as usize);
1705            self.ffi_gl_.GetProgramBinary(
1706                program,
1707                len[0],
1708                &mut out_len as *mut GLsizei,
1709                &mut format,
1710                binary.as_mut_ptr() as *mut c_void,
1711            );
1712        }
1713        if len[0] != out_len {
1714            return (Vec::new(), NONE);
1715        }
1716
1717        (binary, format)
1718    }
1719
1720    fn program_binary(&self, program: GLuint, format: GLenum, binary: &[u8]) {
1721        unsafe {
1722            self.ffi_gl_.ProgramBinary(
1723                program,
1724                format,
1725                binary.as_ptr() as *const c_void,
1726                binary.len() as GLsizei,
1727            );
1728        }
1729    }
1730
1731    fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint) {
1732        unsafe {
1733            self.ffi_gl_.ProgramParameteri(program, pname, value);
1734        }
1735    }
1736
1737    #[inline]
1738    unsafe fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint]) {
1739        assert!(!result.is_empty());
1740        self.ffi_gl_
1741            .GetVertexAttribiv(index, pname, result.as_mut_ptr());
1742    }
1743
1744    #[inline]
1745    unsafe fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat]) {
1746        assert!(!result.is_empty());
1747        self.ffi_gl_
1748            .GetVertexAttribfv(index, pname, result.as_mut_ptr());
1749    }
1750
1751    fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr {
1752        let mut result = 0 as *mut GLvoid;
1753        unsafe {
1754            self.ffi_gl_
1755                .GetVertexAttribPointerv(index, pname, &mut result)
1756        }
1757        result as GLsizeiptr
1758    }
1759
1760    fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint {
1761        let mut result = 0 as GLint;
1762        unsafe {
1763            self.ffi_gl_
1764                .GetBufferParameteriv(target, pname, &mut result);
1765        }
1766        result
1767    }
1768
1769    fn get_shader_info_log(&self, shader: GLuint) -> String {
1770        let mut max_len = [0];
1771        unsafe {
1772            self.get_shader_iv(shader, ffi::INFO_LOG_LENGTH, &mut max_len);
1773        }
1774        if max_len[0] == 0 {
1775            return String::new();
1776        }
1777        let mut result = vec![0u8; max_len[0] as usize];
1778        let mut result_len = 0 as GLsizei;
1779        unsafe {
1780            self.ffi_gl_.GetShaderInfoLog(
1781                shader,
1782                max_len[0] as GLsizei,
1783                &mut result_len,
1784                result.as_mut_ptr() as *mut GLchar,
1785            );
1786        }
1787        result.truncate(if result_len > 0 {
1788            result_len as usize
1789        } else {
1790            0
1791        });
1792        String::from_utf8(result).unwrap()
1793    }
1794
1795    fn get_string(&self, which: GLenum) -> String {
1796        unsafe {
1797            let llstr = self.ffi_gl_.GetString(which);
1798            if !llstr.is_null() {
1799                return str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes())
1800                    .to_string();
1801            } else {
1802                return "".to_string();
1803            }
1804        }
1805    }
1806
1807    fn get_string_i(&self, which: GLenum, index: GLuint) -> String {
1808        unsafe {
1809            let llstr = self.ffi_gl_.GetStringi(which, index);
1810            if !llstr.is_null() {
1811                str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes())
1812                    .to_string()
1813            } else {
1814                "".to_string()
1815            }
1816        }
1817    }
1818
1819    unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]) {
1820        assert!(!result.is_empty());
1821        self.ffi_gl_.GetShaderiv(shader, pname, result.as_mut_ptr());
1822    }
1823
1824    fn get_shader_precision_format(
1825        &self,
1826        shader_type: GLuint,
1827        precision_type: GLuint,
1828    ) -> (GLint, GLint, GLint) {
1829        let (mut range, mut precision) = match precision_type {
1830            // These values are for a 32-bit twos-complement integer format.
1831            ffi::LOW_INT | ffi::MEDIUM_INT | ffi::HIGH_INT => ([31, 30], 0),
1832
1833            // These values are for an IEEE single-precision floating-point format.
1834            ffi::LOW_FLOAT | ffi::MEDIUM_FLOAT | ffi::HIGH_FLOAT => ([127, 127], 23),
1835
1836            _ => unreachable!("invalid precision"),
1837        };
1838        // This function is sometimes defined even though it's really just
1839        // a stub, so we need to set range and precision as if it weren't
1840        // defined before calling it. Suppress any error that might occur.
1841        unsafe {
1842            self.ffi_gl_.GetShaderPrecisionFormat(
1843                shader_type,
1844                precision_type,
1845                range.as_mut_ptr(),
1846                &mut precision,
1847            );
1848            let _ = self.ffi_gl_.GetError();
1849        }
1850
1851        (range[0], range[1], precision)
1852    }
1853
1854    fn compile_shader(&self, shader: GLuint) {
1855        unsafe {
1856            self.ffi_gl_.CompileShader(shader);
1857        }
1858    }
1859
1860    fn create_program(&self) -> GLuint {
1861        unsafe {
1862            return self.ffi_gl_.CreateProgram();
1863        }
1864    }
1865
1866    fn delete_program(&self, program: GLuint) {
1867        unsafe {
1868            self.ffi_gl_.DeleteProgram(program);
1869        }
1870    }
1871
1872    fn create_shader(&self, shader_type: GLenum) -> GLuint {
1873        unsafe {
1874            return self.ffi_gl_.CreateShader(shader_type);
1875        }
1876    }
1877
1878    fn delete_shader(&self, shader: GLuint) {
1879        unsafe {
1880            self.ffi_gl_.DeleteShader(shader);
1881        }
1882    }
1883
1884    fn detach_shader(&self, program: GLuint, shader: GLuint) {
1885        unsafe {
1886            self.ffi_gl_.DetachShader(program, shader);
1887        }
1888    }
1889
1890    fn link_program(&self, program: GLuint) {
1891        unsafe {
1892            return self.ffi_gl_.LinkProgram(program);
1893        }
1894    }
1895
1896    fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) {
1897        unsafe {
1898            self.ffi_gl_.ClearColor(r, g, b, a);
1899        }
1900    }
1901
1902    fn clear(&self, buffer_mask: GLbitfield) {
1903        unsafe {
1904            self.ffi_gl_.Clear(buffer_mask);
1905        }
1906    }
1907
1908    fn clear_depth(&self, depth: f64) {
1909        unsafe {
1910            self.ffi_gl_.ClearDepthf(depth as GLclampf);
1911        }
1912    }
1913
1914    fn clear_stencil(&self, s: GLint) {
1915        unsafe {
1916            self.ffi_gl_.ClearStencil(s);
1917        }
1918    }
1919
1920    fn flush(&self) {
1921        unsafe {
1922            self.ffi_gl_.Flush();
1923        }
1924    }
1925
1926    fn finish(&self) {
1927        unsafe {
1928            self.ffi_gl_.Finish();
1929        }
1930    }
1931
1932    fn get_error(&self) -> GLenum {
1933        unsafe { self.ffi_gl_.GetError() }
1934    }
1935
1936    fn stencil_mask(&self, mask: GLuint) {
1937        unsafe { self.ffi_gl_.StencilMask(mask) }
1938    }
1939
1940    fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) {
1941        unsafe { self.ffi_gl_.StencilMaskSeparate(face, mask) }
1942    }
1943
1944    fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint) {
1945        unsafe { self.ffi_gl_.StencilFunc(func, ref_, mask) }
1946    }
1947
1948    fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint) {
1949        unsafe { self.ffi_gl_.StencilFuncSeparate(face, func, ref_, mask) }
1950    }
1951
1952    fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
1953        unsafe { self.ffi_gl_.StencilOp(sfail, dpfail, dppass) }
1954    }
1955
1956    fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
1957        unsafe { self.ffi_gl_.StencilOpSeparate(face, sfail, dpfail, dppass) }
1958    }
1959
1960    fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
1961        unsafe {
1962            self.ffi_gl_.EGLImageTargetTexture2DOES(target, image);
1963        }
1964    }
1965
1966    fn egl_image_target_renderbuffer_storage_oes(&self, target: GLenum, image: GLeglImageOES) {
1967        unsafe {
1968            self.ffi_gl_.EGLImageTargetRenderbufferStorageOES(target, image);
1969        }
1970    }
1971
1972    fn generate_mipmap(&self, target: GLenum) {
1973        unsafe { self.ffi_gl_.GenerateMipmap(target) }
1974    }
1975
1976    fn insert_event_marker_ext(&self, message: &str) {
1977        if self.ffi_gl_.InsertEventMarkerEXT.is_loaded() {
1978            unsafe {
1979                self.ffi_gl_
1980                    .InsertEventMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
1981            }
1982        }
1983    }
1984
1985    fn push_group_marker_ext(&self, message: &str) {
1986        if self.ffi_gl_.PushGroupMarkerEXT.is_loaded() {
1987            unsafe {
1988                self.ffi_gl_
1989                    .PushGroupMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
1990            }
1991        }
1992    }
1993
1994    fn pop_group_marker_ext(&self) {
1995        if self.ffi_gl_.PopGroupMarkerEXT.is_loaded() {
1996            unsafe {
1997                self.ffi_gl_.PopGroupMarkerEXT();
1998            }
1999        }
2000    }
2001
2002    fn debug_message_insert_khr(&self, source: GLenum, type_: GLenum, id: GLuint, severity: GLenum, message: &str) {
2003        if self.ffi_gl_.DebugMessageInsertKHR.is_loaded() {
2004            unsafe {
2005                self.ffi_gl_
2006                    .DebugMessageInsertKHR(source, type_, id, severity, message.len() as GLsizei, message.as_ptr() as *const _);
2007            }
2008        }
2009    }
2010
2011    fn push_debug_group_khr(&self, source: GLenum, id: GLuint, message: &str) {
2012        if self.ffi_gl_.PushDebugGroupKHR.is_loaded() {
2013            unsafe {
2014                self.ffi_gl_
2015                    .PushDebugGroupKHR(source, id, message.len() as GLsizei, message.as_ptr() as *const _);
2016            }
2017        }
2018    }
2019
2020    fn pop_debug_group_khr(&self) {
2021        if self.ffi_gl_.PopDebugGroupKHR.is_loaded() {
2022            unsafe {
2023                self.ffi_gl_.PopDebugGroupKHR();
2024            }
2025        }
2026    }
2027
2028    fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync {
2029        unsafe { self.ffi_gl_.FenceSync(condition, flags) as *const _ }
2030    }
2031
2032    fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) -> GLenum {
2033        unsafe {
2034            self.ffi_gl_
2035                .ClientWaitSync(sync as *const _, flags, timeout)
2036        }
2037    }
2038
2039    fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) {
2040        unsafe {
2041            self.ffi_gl_.WaitSync(sync as *const _, flags, timeout);
2042        }
2043    }
2044
2045    fn delete_sync(&self, sync: GLsync) {
2046        unsafe {
2047            self.ffi_gl_.DeleteSync(sync as *const _);
2048        }
2049    }
2050
2051    fn texture_range_apple(&self, _target: GLenum, _data: &[u8]) {
2052        panic!("not supported")
2053    }
2054
2055    fn gen_fences_apple(&self, _n: GLsizei) -> Vec<GLuint> {
2056        panic!("not supported")
2057    }
2058
2059    fn delete_fences_apple(&self, _fences: &[GLuint]) {
2060        panic!("not supported")
2061    }
2062
2063    fn set_fence_apple(&self, _fence: GLuint) {
2064        panic!("not supported")
2065    }
2066
2067    fn finish_fence_apple(&self, _fence: GLuint) {
2068        panic!("not supported")
2069    }
2070
2071    fn test_fence_apple(&self, _fence: GLuint) {
2072        panic!("not supported")
2073    }
2074
2075    fn test_object_apple(&self, _object: GLenum, _name: GLuint) -> GLboolean {
2076        panic!("not supported")
2077    }
2078
2079    fn finish_object_apple(&self, _object: GLenum, _name: GLuint) {
2080        panic!("not supported")
2081    }
2082
2083
2084
2085    // GL_ARB_blend_func_extended
2086    fn bind_frag_data_location_indexed(
2087        &self,
2088        _program: GLuint,
2089        _color_number: GLuint,
2090        _index: GLuint,
2091        _name: &str,
2092    ) {
2093        panic!("not supported");
2094    }
2095
2096    fn get_frag_data_index(&self, _program: GLuint, _name: &str) -> GLint {
2097        panic!("not supported");
2098    }
2099
2100    // GL_KHR_debug
2101    fn get_debug_messages(&self) -> Vec<DebugMessage> {
2102        if !self.ffi_gl_.GetDebugMessageLog.is_loaded() {
2103            return Vec::new();
2104        }
2105
2106        let mut max_message_len = 0;
2107        unsafe {
2108            self.ffi_gl_
2109                .GetIntegerv(ffi::MAX_DEBUG_MESSAGE_LENGTH, &mut max_message_len)
2110        }
2111
2112        let mut output = Vec::new();
2113        const CAPACITY: usize = 5;
2114
2115        let mut msg_data = vec![0u8; CAPACITY * max_message_len as usize];
2116        let mut sources = [0 as GLenum; CAPACITY];
2117        let mut types = [0 as GLenum; CAPACITY];
2118        let mut severities = [0 as GLenum; CAPACITY];
2119        let mut ids = [0 as GLuint; CAPACITY];
2120        let mut lengths = [0 as GLsizei; CAPACITY];
2121
2122        loop {
2123            let count = unsafe {
2124                // ANGLE can return one more message than the count argument specifies,
2125                // so we deliberately request one less than the capacity of our buffers.
2126                // https://issues.angleproject.org/issues/425579207
2127                self.ffi_gl_.GetDebugMessageLog(
2128                    (CAPACITY - 1) as _,
2129                    msg_data.len() as _,
2130                    sources.as_mut_ptr(),
2131                    types.as_mut_ptr(),
2132                    ids.as_mut_ptr(),
2133                    severities.as_mut_ptr(),
2134                    lengths.as_mut_ptr(),
2135                    msg_data.as_mut_ptr() as *mut _,
2136                )
2137            };
2138            let count = CAPACITY.min(count as usize);
2139
2140            let mut offset = 0;
2141            output.extend((0..count).map(|i| {
2142                let len = lengths[i] as usize;
2143                let slice = &msg_data[offset..offset + len];
2144                offset += len;
2145                DebugMessage {
2146                    message: String::from_utf8_lossy(slice).to_string(),
2147                    source: sources[i],
2148                    ty: types[i],
2149                    id: ids[i],
2150                    severity: severities[i],
2151                }
2152            }));
2153
2154            if (count as usize) < CAPACITY {
2155                return output;
2156            }
2157        }
2158    }
2159
2160    fn provoking_vertex_angle(&self, mode: GLenum) {
2161        unsafe {
2162            self.ffi_gl_.ProvokingVertexANGLE(mode);
2163        }
2164    }
2165
2166    // GL_KHR_blend_equation_advanced
2167    fn blend_barrier_khr(&self) {
2168        if self.ffi_gl_.BlendBarrierKHR.is_loaded() {
2169            unsafe {
2170                self.ffi_gl_.BlendBarrierKHR();
2171            }
2172        }
2173    }
2174
2175    // GL_CHROMIUM_copy_texture
2176    fn copy_texture_chromium(&self,
2177        source_id: GLuint, source_level: GLint,
2178        dest_target: GLenum, dest_id: GLuint, dest_level: GLint,
2179        internal_format: GLint, dest_type: GLenum,
2180        unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean)
2181    {
2182        unsafe {
2183            self.ffi_gl_.CopyTextureCHROMIUM(source_id, source_level, dest_target, dest_id, dest_level,
2184                internal_format, dest_type,
2185                unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha,
2186            );
2187        }
2188    }
2189    fn copy_sub_texture_chromium(&self,
2190        source_id: GLuint, source_level: GLint,
2191        dest_target: GLenum, dest_id: GLuint, dest_level: GLint,
2192        x_offset: GLint, y_offset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei,
2193        unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean)
2194    {
2195        unsafe {
2196            self.ffi_gl_.CopySubTextureCHROMIUM(source_id, source_level, dest_target, dest_id, dest_level,
2197                x_offset, y_offset, x, y, width, height,
2198                unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha,
2199            );
2200        }
2201    }
2202
2203    // GL_ANGLE_copy_texture_3d
2204    fn copy_texture_3d_angle(
2205        &self,
2206        source_id: GLuint,
2207        source_level: GLint,
2208        dest_target: GLenum,
2209        dest_id: GLuint,
2210        dest_level: GLint,
2211        internal_format: GLint,
2212        dest_type: GLenum,
2213        unpack_flip_y: GLboolean,
2214        unpack_premultiply_alpha: GLboolean,
2215        unpack_unmultiply_alpha: GLboolean,
2216    ) {
2217        unsafe {
2218            self.ffi_gl_.CopyTexture3DANGLE(
2219                source_id,
2220                source_level,
2221                dest_target,
2222                dest_id,
2223                dest_level,
2224                internal_format,
2225                dest_type,
2226                unpack_flip_y,
2227                unpack_premultiply_alpha,
2228                unpack_unmultiply_alpha,
2229            );
2230        }
2231    }
2232
2233    fn copy_sub_texture_3d_angle(
2234        &self,
2235        source_id: GLuint,
2236        source_level: GLint,
2237        dest_target: GLenum,
2238        dest_id: GLuint,
2239        dest_level: GLint,
2240        x_offset: GLint,
2241        y_offset: GLint,
2242        z_offset: GLint,
2243        x: GLint,
2244        y: GLint,
2245        z: GLint,
2246        width: GLsizei,
2247        height: GLsizei,
2248        depth: GLsizei,
2249        unpack_flip_y: GLboolean,
2250        unpack_premultiply_alpha: GLboolean,
2251        unpack_unmultiply_alpha: GLboolean,
2252    ) {
2253        unsafe {
2254            self.ffi_gl_.CopySubTexture3DANGLE(
2255                source_id,
2256                source_level,
2257                dest_target,
2258                dest_id,
2259                dest_level,
2260                x_offset,
2261                y_offset,
2262                z_offset,
2263                x,
2264                y,
2265                z,
2266                width,
2267                height,
2268                depth,
2269                unpack_flip_y,
2270                unpack_premultiply_alpha,
2271                unpack_unmultiply_alpha,
2272            );
2273        }
2274    }
2275
2276    fn buffer_storage(
2277        &self,
2278        target: GLenum,
2279        size: GLsizeiptr,
2280        data: *const GLvoid,
2281        flags: GLbitfield,
2282    ) {
2283        unsafe {
2284            self.ffi_gl_.BufferStorageEXT(target, size, data, flags);
2285        }
2286    }
2287
2288    fn flush_mapped_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr) {
2289        unsafe {
2290            self.ffi_gl_.FlushMappedBufferRange(target, offset, length);
2291        }
2292    }
2293
2294    fn start_tiling_qcom(&self, x: GLuint, y: GLuint, width: GLuint, height: GLuint, preserve_mask: GLbitfield) {
2295        unsafe {
2296            self.ffi_gl_.StartTilingQCOM(x, y, width, height, preserve_mask);
2297        }
2298    }
2299
2300    fn end_tiling_qcom(&self, preserve_mask: GLbitfield) {
2301        unsafe {
2302            self.ffi_gl_.EndTilingQCOM(preserve_mask);
2303        }
2304    }
2305}