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 
10 pub struct GlesFns {
11     ffi_gl_: GlesFfi,
12 }
13 
14 impl GlesFns {
load_with<'a, F>(loadfn: F) -> Rc<dyn Gl> where F: FnMut(&str) -> *const c_void,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 
24 impl Gl for GlesFns {
get_type(&self) -> GlType25     fn get_type(&self) -> GlType {
26         GlType::Gles
27     }
28 
buffer_data_untyped( &self, target: GLenum, size: GLsizeiptr, data: *const GLvoid, usage: GLenum, )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 
tex_buffer(&self, _target: GLenum, _internal_format: GLenum, _buffer: GLuint)41     fn tex_buffer(&self, _target: GLenum, _internal_format: GLenum, _buffer: GLuint) {
42         panic!("not supported")
43     }
44 
buffer_sub_data_untyped( &self, target: GLenum, offset: isize, size: GLsizeiptr, data: *const GLvoid, )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 
map_buffer(&self, _target: GLenum, _access: GLbitfield) -> *mut c_void57     fn map_buffer(&self,
58                   _target: GLenum,
59                   _access: GLbitfield) -> *mut c_void {
60         panic!("not supported")
61     }
62 
map_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr, access: GLbitfield) -> *mut c_void63     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 
unmap_buffer(&self, target: GLenum) -> GLboolean73     fn unmap_buffer(&self, target: GLenum) -> GLboolean {
74         unsafe {
75             return self.ffi_gl_.UnmapBuffer(target);
76         }
77     }
78 
shader_source(&self, shader: GLuint, strings: &[&[u8]])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)]
read_buffer(&self, mode: GLenum)95     fn read_buffer(&self, mode: GLenum) {
96         panic!("not supported")
97     }
98 
read_pixels_into_buffer( &self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum, dst_buffer: &mut [u8], )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 
read_pixels( &self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum, ) -> Vec<u8>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 
read_pixels_into_pbo(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum)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 
sample_coverage(&self, value: GLclampf, invert: bool)175     fn sample_coverage(&self, value: GLclampf, invert: bool) {
176         unsafe {
177             self.ffi_gl_.SampleCoverage(value, invert as GLboolean);
178         }
179     }
180 
polygon_offset(&self, factor: GLfloat, units: GLfloat)181     fn polygon_offset(&self, factor: GLfloat, units: GLfloat) {
182         unsafe {
183             self.ffi_gl_.PolygonOffset(factor, units);
184         }
185     }
186 
pixel_store_i(&self, name: GLenum, param: GLint)187     fn pixel_store_i(&self, name: GLenum, param: GLint) {
188         unsafe {
189             self.ffi_gl_.PixelStorei(name, param);
190         }
191     }
192 
gen_buffers(&self, n: GLsizei) -> Vec<GLuint>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 
gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint>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 
gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint>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 
gen_textures(&self, n: GLsizei) -> Vec<GLuint>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 
gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint>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 
gen_vertex_arrays_apple(&self, _n: GLsizei) -> Vec<GLuint>233     fn gen_vertex_arrays_apple(&self, _n: GLsizei) -> Vec<GLuint> {
234         panic!("not supported")
235     }
236 
gen_queries(&self, n: GLsizei) -> Vec<GLuint>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 
begin_query(&self, target: GLenum, id: GLuint)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 
end_query(&self, target: GLenum)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 
query_counter(&self, id: GLuint, target: GLenum)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 
get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32275     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 
get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32286     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 
get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64297     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 
get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64308     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 
delete_queries(&self, queries: &[GLuint])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 
delete_vertex_arrays(&self, vertex_arrays: &[GLuint])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 
delete_vertex_arrays_apple(&self, _vertex_arrays: &[GLuint])336     fn delete_vertex_arrays_apple(&self, _vertex_arrays: &[GLuint]) {
337         panic!("not supported")
338     }
339 
delete_buffers(&self, buffers: &[GLuint])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 
delete_renderbuffers(&self, renderbuffers: &[GLuint])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 
delete_framebuffers(&self, framebuffers: &[GLuint])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 
delete_textures(&self, textures: &[GLuint])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 
framebuffer_renderbuffer( &self, target: GLenum, attachment: GLenum, renderbuffertarget: GLenum, renderbuffer: GLuint, )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 
renderbuffer_storage( &self, target: GLenum, internalformat: GLenum, width: GLsizei, height: GLsizei, )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 
depth_func(&self, func: GLenum)398     fn depth_func(&self, func: GLenum) {
399         unsafe {
400             self.ffi_gl_.DepthFunc(func);
401         }
402     }
403 
active_texture(&self, texture: GLenum)404     fn active_texture(&self, texture: GLenum) {
405         unsafe {
406             self.ffi_gl_.ActiveTexture(texture);
407         }
408     }
409 
attach_shader(&self, program: GLuint, shader: GLuint)410     fn attach_shader(&self, program: GLuint, shader: GLuint) {
411         unsafe {
412             self.ffi_gl_.AttachShader(program, shader);
413         }
414     }
415 
bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str)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
get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint])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
get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat])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 
get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint438     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 
get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec<GLuint>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 
bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint)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 
bind_buffer_range( &self, target: GLenum, index: GLuint, buffer: GLuint, offset: GLintptr, size: GLsizeiptr, )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 
uniform_block_binding( &self, program: GLuint, uniform_block_index: GLuint, uniform_block_binding: GLuint, )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 
bind_buffer(&self, target: GLenum, buffer: GLuint)494     fn bind_buffer(&self, target: GLenum, buffer: GLuint) {
495         unsafe {
496             self.ffi_gl_.BindBuffer(target, buffer);
497         }
498     }
499 
bind_vertex_array(&self, vao: GLuint)500     fn bind_vertex_array(&self, vao: GLuint) {
501         unsafe {
502             self.ffi_gl_.BindVertexArray(vao);
503         }
504     }
505 
bind_vertex_array_apple(&self, _vao: GLuint)506     fn bind_vertex_array_apple(&self, _vao: GLuint) {
507         panic!("not supported")
508     }
509 
bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint)510     fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) {
511         unsafe {
512             self.ffi_gl_.BindRenderbuffer(target, renderbuffer);
513         }
514     }
515 
bind_framebuffer(&self, target: GLenum, framebuffer: GLuint)516     fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) {
517         unsafe {
518             self.ffi_gl_.BindFramebuffer(target, framebuffer);
519         }
520     }
521 
bind_texture(&self, target: GLenum, texture: GLuint)522     fn bind_texture(&self, target: GLenum, texture: GLuint) {
523         unsafe {
524             self.ffi_gl_.BindTexture(target, texture);
525         }
526     }
527 
draw_buffers(&self, bufs: &[GLenum])528     fn draw_buffers(&self, bufs: &[GLenum]) {
529         unsafe {
530             self.ffi_gl_
531                 .DrawBuffers(bufs.len() as GLsizei, bufs.as_ptr());
532         }
533     }
534 
535     // FIXME: Does not verify buffer size -- unsafe!
tex_image_2d( &self, target: GLenum, level: GLint, internal_format: GLint, width: GLsizei, height: GLsizei, border: GLint, format: GLenum, ty: GLenum, opt_data: Option<&[u8]>, )536     fn tex_image_2d(
537         &self,
538         target: GLenum,
539         level: GLint,
540         internal_format: GLint,
541         width: GLsizei,
542         height: GLsizei,
543         border: GLint,
544         format: GLenum,
545         ty: GLenum,
546         opt_data: Option<&[u8]>,
547     ) {
548         match opt_data {
549             Some(data) => unsafe {
550                 self.ffi_gl_.TexImage2D(
551                     target,
552                     level,
553                     internal_format,
554                     width,
555                     height,
556                     border,
557                     format,
558                     ty,
559                     data.as_ptr() as *const GLvoid,
560                 );
561             },
562             None => unsafe {
563                 self.ffi_gl_.TexImage2D(
564                     target,
565                     level,
566                     internal_format,
567                     width,
568                     height,
569                     border,
570                     format,
571                     ty,
572                     ptr::null(),
573                 );
574             },
575         }
576     }
577 
compressed_tex_image_2d( &self, target: GLenum, level: GLint, internal_format: GLenum, width: GLsizei, height: GLsizei, border: GLint, data: &[u8], )578     fn compressed_tex_image_2d(
579         &self,
580         target: GLenum,
581         level: GLint,
582         internal_format: GLenum,
583         width: GLsizei,
584         height: GLsizei,
585         border: GLint,
586         data: &[u8],
587     ) {
588         unsafe {
589             self.ffi_gl_.CompressedTexImage2D(
590                 target,
591                 level,
592                 internal_format,
593                 width,
594                 height,
595                 border,
596                 data.len() as GLsizei,
597                 data.as_ptr() as *const GLvoid,
598             );
599         }
600     }
601 
compressed_tex_sub_image_2d( &self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, format: GLenum, data: &[u8], )602     fn compressed_tex_sub_image_2d(
603         &self,
604         target: GLenum,
605         level: GLint,
606         xoffset: GLint,
607         yoffset: GLint,
608         width: GLsizei,
609         height: GLsizei,
610         format: GLenum,
611         data: &[u8],
612     ) {
613         unsafe {
614             self.ffi_gl_.CompressedTexSubImage2D(
615                 target,
616                 level,
617                 xoffset,
618                 yoffset,
619                 width,
620                 height,
621                 format,
622                 data.len() as GLsizei,
623                 data.as_ptr() as *const GLvoid,
624             );
625         }
626     }
627 
628     // FIXME: Does not verify buffer size -- unsafe!
tex_image_3d( &self, target: GLenum, level: GLint, internal_format: GLint, width: GLsizei, height: GLsizei, depth: GLsizei, border: GLint, format: GLenum, ty: GLenum, opt_data: Option<&[u8]>, )629     fn tex_image_3d(
630         &self,
631         target: GLenum,
632         level: GLint,
633         internal_format: GLint,
634         width: GLsizei,
635         height: GLsizei,
636         depth: GLsizei,
637         border: GLint,
638         format: GLenum,
639         ty: GLenum,
640         opt_data: Option<&[u8]>,
641     ) {
642         unsafe {
643             let pdata = match opt_data {
644                 Some(data) => mem::transmute(data.as_ptr()),
645                 None => ptr::null(),
646             };
647             self.ffi_gl_.TexImage3D(
648                 target,
649                 level,
650                 internal_format,
651                 width,
652                 height,
653                 depth,
654                 border,
655                 format,
656                 ty,
657                 pdata,
658             );
659         }
660     }
661 
copy_tex_image_2d( &self, target: GLenum, level: GLint, internal_format: GLenum, x: GLint, y: GLint, width: GLsizei, height: GLsizei, border: GLint, )662     fn copy_tex_image_2d(
663         &self,
664         target: GLenum,
665         level: GLint,
666         internal_format: GLenum,
667         x: GLint,
668         y: GLint,
669         width: GLsizei,
670         height: GLsizei,
671         border: GLint,
672     ) {
673         unsafe {
674             self.ffi_gl_.CopyTexImage2D(
675                 target,
676                 level,
677                 internal_format,
678                 x,
679                 y,
680                 width,
681                 height,
682                 border,
683             );
684         }
685     }
686 
copy_tex_sub_image_2d( &self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei, )687     fn copy_tex_sub_image_2d(
688         &self,
689         target: GLenum,
690         level: GLint,
691         xoffset: GLint,
692         yoffset: GLint,
693         x: GLint,
694         y: GLint,
695         width: GLsizei,
696         height: GLsizei,
697     ) {
698         unsafe {
699             self.ffi_gl_
700                 .CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
701         }
702     }
703 
copy_tex_sub_image_3d( &self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, zoffset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei, )704     fn copy_tex_sub_image_3d(
705         &self,
706         target: GLenum,
707         level: GLint,
708         xoffset: GLint,
709         yoffset: GLint,
710         zoffset: GLint,
711         x: GLint,
712         y: GLint,
713         width: GLsizei,
714         height: GLsizei,
715     ) {
716         unsafe {
717             self.ffi_gl_.CopyTexSubImage3D(
718                 target, level, xoffset, yoffset, zoffset, x, y, width, height,
719             );
720         }
721     }
722 
tex_sub_image_2d( &self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, format: GLenum, ty: GLenum, data: &[u8], )723     fn tex_sub_image_2d(
724         &self,
725         target: GLenum,
726         level: GLint,
727         xoffset: GLint,
728         yoffset: GLint,
729         width: GLsizei,
730         height: GLsizei,
731         format: GLenum,
732         ty: GLenum,
733         data: &[u8],
734     ) {
735         unsafe {
736             self.ffi_gl_.TexSubImage2D(
737                 target,
738                 level,
739                 xoffset,
740                 yoffset,
741                 width,
742                 height,
743                 format,
744                 ty,
745                 data.as_ptr() as *const c_void,
746             );
747         }
748     }
749 
tex_sub_image_2d_pbo( &self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, format: GLenum, ty: GLenum, offset: usize, )750     fn tex_sub_image_2d_pbo(
751         &self,
752         target: GLenum,
753         level: GLint,
754         xoffset: GLint,
755         yoffset: GLint,
756         width: GLsizei,
757         height: GLsizei,
758         format: GLenum,
759         ty: GLenum,
760         offset: usize,
761     ) {
762         unsafe {
763             self.ffi_gl_.TexSubImage2D(
764                 target,
765                 level,
766                 xoffset,
767                 yoffset,
768                 width,
769                 height,
770                 format,
771                 ty,
772                 offset as *const c_void,
773             );
774         }
775     }
776 
tex_sub_image_3d( &self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, zoffset: GLint, width: GLsizei, height: GLsizei, depth: GLsizei, format: GLenum, ty: GLenum, data: &[u8], )777     fn tex_sub_image_3d(
778         &self,
779         target: GLenum,
780         level: GLint,
781         xoffset: GLint,
782         yoffset: GLint,
783         zoffset: GLint,
784         width: GLsizei,
785         height: GLsizei,
786         depth: GLsizei,
787         format: GLenum,
788         ty: GLenum,
789         data: &[u8],
790     ) {
791         unsafe {
792             self.ffi_gl_.TexSubImage3D(
793                 target,
794                 level,
795                 xoffset,
796                 yoffset,
797                 zoffset,
798                 width,
799                 height,
800                 depth,
801                 format,
802                 ty,
803                 data.as_ptr() as *const c_void,
804             );
805         }
806     }
807 
tex_sub_image_3d_pbo( &self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, zoffset: GLint, width: GLsizei, height: GLsizei, depth: GLsizei, format: GLenum, ty: GLenum, offset: usize, )808     fn tex_sub_image_3d_pbo(
809         &self,
810         target: GLenum,
811         level: GLint,
812         xoffset: GLint,
813         yoffset: GLint,
814         zoffset: GLint,
815         width: GLsizei,
816         height: GLsizei,
817         depth: GLsizei,
818         format: GLenum,
819         ty: GLenum,
820         offset: usize,
821     ) {
822         unsafe {
823             self.ffi_gl_.TexSubImage3D(
824                 target,
825                 level,
826                 xoffset,
827                 yoffset,
828                 zoffset,
829                 width,
830                 height,
831                 depth,
832                 format,
833                 ty,
834                 offset as *const c_void,
835             );
836         }
837     }
838 
tex_storage_2d( &self, target: GLenum, levels: GLint, internal_format: GLenum, width: GLsizei, height: GLsizei, )839     fn tex_storage_2d(
840         &self,
841         target: GLenum,
842         levels: GLint,
843         internal_format: GLenum,
844         width: GLsizei,
845         height: GLsizei,
846     ) {
847         unsafe {
848             self.ffi_gl_
849                 .TexStorage2D(target, levels, internal_format, width, height);
850         }
851     }
852 
tex_storage_3d( &self, target: GLenum, levels: GLint, internal_format: GLenum, width: GLsizei, height: GLsizei, depth: GLsizei, )853     fn tex_storage_3d(
854         &self,
855         target: GLenum,
856         levels: GLint,
857         internal_format: GLenum,
858         width: GLsizei,
859         height: GLsizei,
860         depth: GLsizei,
861     ) {
862         unsafe {
863             self.ffi_gl_
864                 .TexStorage3D(target, levels, internal_format, width, height, depth);
865         }
866     }
867 
868     #[allow(unused_variables)]
get_tex_image_into_buffer( &self, target: GLenum, level: GLint, format: GLenum, ty: GLenum, output: &mut [u8], )869     fn get_tex_image_into_buffer(
870         &self,
871         target: GLenum,
872         level: GLint,
873         format: GLenum,
874         ty: GLenum,
875         output: &mut [u8],
876     ) {
877         panic!("not supported");
878     }
879 
copy_image_sub_data( &self, src_name: GLuint, src_target: GLenum, src_level: GLint, src_x: GLint, src_y: GLint, src_z: GLint, dst_name: GLuint, dst_target: GLenum, dst_level: GLint, dst_x: GLint, dst_y: GLint, dst_z: GLint, src_width: GLsizei, src_height: GLsizei, src_depth: GLsizei, )880     unsafe fn copy_image_sub_data(
881         &self,
882         src_name: GLuint,
883         src_target: GLenum,
884         src_level: GLint,
885         src_x: GLint,
886         src_y: GLint,
887         src_z: GLint,
888         dst_name: GLuint,
889         dst_target: GLenum,
890         dst_level: GLint,
891         dst_x: GLint,
892         dst_y: GLint,
893         dst_z: GLint,
894         src_width: GLsizei,
895         src_height: GLsizei,
896         src_depth: GLsizei,
897     ) {
898         self.ffi_gl_.CopyImageSubDataEXT(
899             src_name, src_target, src_level, src_x, src_y, src_z, dst_name, dst_target, dst_level,
900             dst_x, dst_y, dst_z, src_width, src_height, src_depth,
901         );
902     }
903 
invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum])904     fn invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum]) {
905         unsafe {
906             self.ffi_gl_.InvalidateFramebuffer(
907                 target,
908                 attachments.len() as GLsizei,
909                 attachments.as_ptr(),
910             );
911         }
912     }
913 
invalidate_sub_framebuffer( &self, target: GLenum, attachments: &[GLenum], xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, )914     fn invalidate_sub_framebuffer(
915         &self,
916         target: GLenum,
917         attachments: &[GLenum],
918         xoffset: GLint,
919         yoffset: GLint,
920         width: GLsizei,
921         height: GLsizei,
922     ) {
923         unsafe {
924             self.ffi_gl_.InvalidateSubFramebuffer(
925                 target,
926                 attachments.len() as GLsizei,
927                 attachments.as_ptr(),
928                 xoffset,
929                 yoffset,
930                 width,
931                 height,
932             );
933         }
934     }
935 
936     #[inline]
get_integer_v(&self, name: GLenum, result: &mut [GLint])937     unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]) {
938         assert!(!result.is_empty());
939         self.ffi_gl_.GetIntegerv(name, result.as_mut_ptr());
940     }
941 
942     #[inline]
get_integer_64v(&self, name: GLenum, result: &mut [GLint64])943     unsafe fn get_integer_64v(&self, name: GLenum, result: &mut [GLint64]) {
944         assert!(!result.is_empty());
945         self.ffi_gl_.GetInteger64v(name, result.as_mut_ptr());
946     }
947 
948     #[inline]
get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint])949     unsafe fn get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint]) {
950         assert!(!result.is_empty());
951         self.ffi_gl_.GetIntegeri_v(name, index, result.as_mut_ptr());
952     }
953 
954     #[inline]
get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64])955     unsafe fn get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64]) {
956         assert!(!result.is_empty());
957         self.ffi_gl_
958             .GetInteger64i_v(name, index, result.as_mut_ptr());
959     }
960 
961     #[inline]
get_boolean_v(&self, name: GLenum, result: &mut [GLboolean])962     unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]) {
963         assert!(!result.is_empty());
964         self.ffi_gl_.GetBooleanv(name, result.as_mut_ptr());
965     }
966 
967     #[inline]
get_float_v(&self, name: GLenum, result: &mut [GLfloat])968     unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]) {
969         assert!(!result.is_empty());
970         self.ffi_gl_.GetFloatv(name, result.as_mut_ptr());
971     }
972 
get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint973     fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
974         let mut result: GLint = 0;
975         unsafe {
976             self.ffi_gl_
977                 .GetRenderbufferParameteriv(target, pname, &mut result);
978         }
979         result
980     }
981 
get_framebuffer_attachment_parameter_iv( &self, target: GLenum, attachment: GLenum, pname: GLenum, ) -> GLint982     fn get_framebuffer_attachment_parameter_iv(
983         &self,
984         target: GLenum,
985         attachment: GLenum,
986         pname: GLenum,
987     ) -> GLint {
988         let mut result: GLint = 0;
989         unsafe {
990             self.ffi_gl_.GetFramebufferAttachmentParameteriv(
991                 target,
992                 attachment,
993                 pname,
994                 &mut result,
995             );
996         }
997         result
998     }
999 
get_tex_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint1000     fn get_tex_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
1001         let mut result: GLint = 0;
1002         unsafe {
1003             self.ffi_gl_.GetTexParameteriv(target, pname, &mut result);
1004         }
1005         result
1006     }
1007 
get_tex_parameter_fv(&self, target: GLenum, pname: GLenum) -> GLfloat1008     fn get_tex_parameter_fv(&self, target: GLenum, pname: GLenum) -> GLfloat {
1009         let mut result: GLfloat = 0.0;
1010         unsafe {
1011             self.ffi_gl_.GetTexParameterfv(target, pname, &mut result);
1012         }
1013         result
1014     }
1015 
tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint)1016     fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) {
1017         unsafe {
1018             self.ffi_gl_.TexParameteri(target, pname, param);
1019         }
1020     }
1021 
tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat)1022     fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) {
1023         unsafe {
1024             self.ffi_gl_.TexParameterf(target, pname, param);
1025         }
1026     }
1027 
framebuffer_texture_2d( &self, target: GLenum, attachment: GLenum, textarget: GLenum, texture: GLuint, level: GLint, )1028     fn framebuffer_texture_2d(
1029         &self,
1030         target: GLenum,
1031         attachment: GLenum,
1032         textarget: GLenum,
1033         texture: GLuint,
1034         level: GLint,
1035     ) {
1036         unsafe {
1037             self.ffi_gl_
1038                 .FramebufferTexture2D(target, attachment, textarget, texture, level);
1039         }
1040     }
1041 
framebuffer_texture_layer( &self, target: GLenum, attachment: GLenum, texture: GLuint, level: GLint, layer: GLint, )1042     fn framebuffer_texture_layer(
1043         &self,
1044         target: GLenum,
1045         attachment: GLenum,
1046         texture: GLuint,
1047         level: GLint,
1048         layer: GLint,
1049     ) {
1050         unsafe {
1051             self.ffi_gl_
1052                 .FramebufferTextureLayer(target, attachment, texture, level, layer);
1053         }
1054     }
1055 
blit_framebuffer( &self, src_x0: GLint, src_y0: GLint, src_x1: GLint, src_y1: GLint, dst_x0: GLint, dst_y0: GLint, dst_x1: GLint, dst_y1: GLint, mask: GLbitfield, filter: GLenum, )1056     fn blit_framebuffer(
1057         &self,
1058         src_x0: GLint,
1059         src_y0: GLint,
1060         src_x1: GLint,
1061         src_y1: GLint,
1062         dst_x0: GLint,
1063         dst_y0: GLint,
1064         dst_x1: GLint,
1065         dst_y1: GLint,
1066         mask: GLbitfield,
1067         filter: GLenum,
1068     ) {
1069         unsafe {
1070             self.ffi_gl_.BlitFramebuffer(
1071                 src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter,
1072             );
1073         }
1074     }
1075 
vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat)1076     fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
1077         unsafe { self.ffi_gl_.VertexAttrib4f(index, x, y, z, w) }
1078     }
1079 
vertex_attrib_pointer_f32( &self, index: GLuint, size: GLint, normalized: bool, stride: GLsizei, offset: GLuint, )1080     fn vertex_attrib_pointer_f32(
1081         &self,
1082         index: GLuint,
1083         size: GLint,
1084         normalized: bool,
1085         stride: GLsizei,
1086         offset: GLuint,
1087     ) {
1088         unsafe {
1089             self.ffi_gl_.VertexAttribPointer(
1090                 index,
1091                 size,
1092                 ffi::FLOAT,
1093                 normalized as GLboolean,
1094                 stride,
1095                 offset as *const GLvoid,
1096             )
1097         }
1098     }
1099 
vertex_attrib_pointer( &self, index: GLuint, size: GLint, type_: GLenum, normalized: bool, stride: GLsizei, offset: GLuint, )1100     fn vertex_attrib_pointer(
1101         &self,
1102         index: GLuint,
1103         size: GLint,
1104         type_: GLenum,
1105         normalized: bool,
1106         stride: GLsizei,
1107         offset: GLuint,
1108     ) {
1109         unsafe {
1110             self.ffi_gl_.VertexAttribPointer(
1111                 index,
1112                 size,
1113                 type_,
1114                 normalized as GLboolean,
1115                 stride,
1116                 offset as *const GLvoid,
1117             )
1118         }
1119     }
1120 
vertex_attrib_i_pointer( &self, index: GLuint, size: GLint, type_: GLenum, stride: GLsizei, offset: GLuint, )1121     fn vertex_attrib_i_pointer(
1122         &self,
1123         index: GLuint,
1124         size: GLint,
1125         type_: GLenum,
1126         stride: GLsizei,
1127         offset: GLuint,
1128     ) {
1129         unsafe {
1130             self.ffi_gl_
1131                 .VertexAttribIPointer(index, size, type_, stride, offset as *const GLvoid)
1132         }
1133     }
1134 
vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint)1135     fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) {
1136         unsafe { self.ffi_gl_.VertexAttribDivisor(index, divisor) }
1137     }
1138 
viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei)1139     fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
1140         unsafe {
1141             self.ffi_gl_.Viewport(x, y, width, height);
1142         }
1143     }
1144 
scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei)1145     fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
1146         unsafe {
1147             self.ffi_gl_.Scissor(x, y, width, height);
1148         }
1149     }
1150 
line_width(&self, width: GLfloat)1151     fn line_width(&self, width: GLfloat) {
1152         unsafe {
1153             self.ffi_gl_.LineWidth(width);
1154         }
1155     }
1156 
use_program(&self, program: GLuint)1157     fn use_program(&self, program: GLuint) {
1158         unsafe {
1159             self.ffi_gl_.UseProgram(program);
1160         }
1161     }
1162 
validate_program(&self, program: GLuint)1163     fn validate_program(&self, program: GLuint) {
1164         unsafe {
1165             self.ffi_gl_.ValidateProgram(program);
1166         }
1167     }
1168 
draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei)1169     fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) {
1170         unsafe {
1171             return self.ffi_gl_.DrawArrays(mode, first, count);
1172         }
1173     }
1174 
draw_arrays_instanced( &self, mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei, )1175     fn draw_arrays_instanced(
1176         &self,
1177         mode: GLenum,
1178         first: GLint,
1179         count: GLsizei,
1180         primcount: GLsizei,
1181     ) {
1182         unsafe {
1183             return self
1184                 .ffi_gl_
1185                 .DrawArraysInstanced(mode, first, count, primcount);
1186         }
1187     }
1188 
draw_elements( &self, mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint, )1189     fn draw_elements(
1190         &self,
1191         mode: GLenum,
1192         count: GLsizei,
1193         element_type: GLenum,
1194         indices_offset: GLuint,
1195     ) {
1196         unsafe {
1197             return self.ffi_gl_.DrawElements(
1198                 mode,
1199                 count,
1200                 element_type,
1201                 indices_offset as *const c_void,
1202             );
1203         }
1204     }
1205 
draw_elements_instanced( &self, mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint, primcount: GLsizei, )1206     fn draw_elements_instanced(
1207         &self,
1208         mode: GLenum,
1209         count: GLsizei,
1210         element_type: GLenum,
1211         indices_offset: GLuint,
1212         primcount: GLsizei,
1213     ) {
1214         unsafe {
1215             return self.ffi_gl_.DrawElementsInstanced(
1216                 mode,
1217                 count,
1218                 element_type,
1219                 indices_offset as *const c_void,
1220                 primcount,
1221             );
1222         }
1223     }
1224 
blend_color(&self, r: f32, g: f32, b: f32, a: f32)1225     fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) {
1226         unsafe {
1227             self.ffi_gl_.BlendColor(r, g, b, a);
1228         }
1229     }
1230 
blend_func(&self, sfactor: GLenum, dfactor: GLenum)1231     fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) {
1232         unsafe {
1233             self.ffi_gl_.BlendFunc(sfactor, dfactor);
1234         }
1235     }
1236 
blend_func_separate( &self, src_rgb: GLenum, dest_rgb: GLenum, src_alpha: GLenum, dest_alpha: GLenum, )1237     fn blend_func_separate(
1238         &self,
1239         src_rgb: GLenum,
1240         dest_rgb: GLenum,
1241         src_alpha: GLenum,
1242         dest_alpha: GLenum,
1243     ) {
1244         unsafe {
1245             self.ffi_gl_
1246                 .BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha);
1247         }
1248     }
1249 
blend_equation(&self, mode: GLenum)1250     fn blend_equation(&self, mode: GLenum) {
1251         unsafe {
1252             self.ffi_gl_.BlendEquation(mode);
1253         }
1254     }
1255 
blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum)1256     fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) {
1257         unsafe {
1258             self.ffi_gl_.BlendEquationSeparate(mode_rgb, mode_alpha);
1259         }
1260     }
1261 
color_mask(&self, r: bool, g: bool, b: bool, a: bool)1262     fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
1263         unsafe {
1264             self.ffi_gl_.ColorMask(
1265                 r as GLboolean,
1266                 g as GLboolean,
1267                 b as GLboolean,
1268                 a as GLboolean,
1269             );
1270         }
1271     }
1272 
cull_face(&self, mode: GLenum)1273     fn cull_face(&self, mode: GLenum) {
1274         unsafe {
1275             self.ffi_gl_.CullFace(mode);
1276         }
1277     }
1278 
front_face(&self, mode: GLenum)1279     fn front_face(&self, mode: GLenum) {
1280         unsafe {
1281             self.ffi_gl_.FrontFace(mode);
1282         }
1283     }
1284 
enable(&self, cap: GLenum)1285     fn enable(&self, cap: GLenum) {
1286         unsafe {
1287             self.ffi_gl_.Enable(cap);
1288         }
1289     }
1290 
disable(&self, cap: GLenum)1291     fn disable(&self, cap: GLenum) {
1292         unsafe {
1293             self.ffi_gl_.Disable(cap);
1294         }
1295     }
1296 
hint(&self, param_name: GLenum, param_val: GLenum)1297     fn hint(&self, param_name: GLenum, param_val: GLenum) {
1298         unsafe {
1299             self.ffi_gl_.Hint(param_name, param_val);
1300         }
1301     }
1302 
is_enabled(&self, cap: GLenum) -> GLboolean1303     fn is_enabled(&self, cap: GLenum) -> GLboolean {
1304         unsafe { self.ffi_gl_.IsEnabled(cap) }
1305     }
1306 
is_shader(&self, shader: GLuint) -> GLboolean1307     fn is_shader(&self, shader: GLuint) -> GLboolean {
1308         unsafe { self.ffi_gl_.IsShader(shader) }
1309     }
1310 
is_texture(&self, texture: GLenum) -> GLboolean1311     fn is_texture(&self, texture: GLenum) -> GLboolean {
1312         unsafe { self.ffi_gl_.IsTexture(texture) }
1313     }
1314 
is_framebuffer(&self, framebuffer: GLenum) -> GLboolean1315     fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean {
1316         unsafe { self.ffi_gl_.IsFramebuffer(framebuffer) }
1317     }
1318 
is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean1319     fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean {
1320         unsafe { self.ffi_gl_.IsRenderbuffer(renderbuffer) }
1321     }
1322 
check_frame_buffer_status(&self, target: GLenum) -> GLenum1323     fn check_frame_buffer_status(&self, target: GLenum) -> GLenum {
1324         unsafe { self.ffi_gl_.CheckFramebufferStatus(target) }
1325     }
1326 
enable_vertex_attrib_array(&self, index: GLuint)1327     fn enable_vertex_attrib_array(&self, index: GLuint) {
1328         unsafe {
1329             self.ffi_gl_.EnableVertexAttribArray(index);
1330         }
1331     }
1332 
disable_vertex_attrib_array(&self, index: GLuint)1333     fn disable_vertex_attrib_array(&self, index: GLuint) {
1334         unsafe {
1335             self.ffi_gl_.DisableVertexAttribArray(index);
1336         }
1337     }
1338 
uniform_1f(&self, location: GLint, v0: GLfloat)1339     fn uniform_1f(&self, location: GLint, v0: GLfloat) {
1340         unsafe {
1341             self.ffi_gl_.Uniform1f(location, v0);
1342         }
1343     }
1344 
uniform_1fv(&self, location: GLint, values: &[f32])1345     fn uniform_1fv(&self, location: GLint, values: &[f32]) {
1346         unsafe {
1347             self.ffi_gl_
1348                 .Uniform1fv(location, values.len() as GLsizei, values.as_ptr());
1349         }
1350     }
1351 
uniform_1i(&self, location: GLint, v0: GLint)1352     fn uniform_1i(&self, location: GLint, v0: GLint) {
1353         unsafe {
1354             self.ffi_gl_.Uniform1i(location, v0);
1355         }
1356     }
1357 
uniform_1iv(&self, location: GLint, values: &[i32])1358     fn uniform_1iv(&self, location: GLint, values: &[i32]) {
1359         unsafe {
1360             self.ffi_gl_
1361                 .Uniform1iv(location, values.len() as GLsizei, values.as_ptr());
1362         }
1363     }
1364 
1365     #[allow(unused_variables)]
uniform_1ui(&self, location: GLint, v0: GLuint)1366     fn uniform_1ui(&self, location: GLint, v0: GLuint) {
1367         panic!("not supported")
1368     }
1369 
uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat)1370     fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) {
1371         unsafe {
1372             self.ffi_gl_.Uniform2f(location, v0, v1);
1373         }
1374     }
1375 
uniform_2fv(&self, location: GLint, values: &[f32])1376     fn uniform_2fv(&self, location: GLint, values: &[f32]) {
1377         unsafe {
1378             self.ffi_gl_
1379                 .Uniform2fv(location, (values.len() / 2) as GLsizei, values.as_ptr());
1380         }
1381     }
1382 
uniform_2i(&self, location: GLint, v0: GLint, v1: GLint)1383     fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) {
1384         unsafe {
1385             self.ffi_gl_.Uniform2i(location, v0, v1);
1386         }
1387     }
1388 
uniform_2iv(&self, location: GLint, values: &[i32])1389     fn uniform_2iv(&self, location: GLint, values: &[i32]) {
1390         unsafe {
1391             self.ffi_gl_
1392                 .Uniform2iv(location, (values.len() / 2) as GLsizei, values.as_ptr());
1393         }
1394     }
1395 
1396     #[allow(unused_variables)]
uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint)1397     fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) {
1398         panic!("not supported")
1399     }
1400 
uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat)1401     fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
1402         unsafe {
1403             self.ffi_gl_.Uniform3f(location, v0, v1, v2);
1404         }
1405     }
1406 
uniform_3fv(&self, location: GLint, values: &[f32])1407     fn uniform_3fv(&self, location: GLint, values: &[f32]) {
1408         unsafe {
1409             self.ffi_gl_
1410                 .Uniform3fv(location, (values.len() / 3) as GLsizei, values.as_ptr());
1411         }
1412     }
1413 
uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint)1414     fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) {
1415         unsafe {
1416             self.ffi_gl_.Uniform3i(location, v0, v1, v2);
1417         }
1418     }
1419 
uniform_3iv(&self, location: GLint, values: &[i32])1420     fn uniform_3iv(&self, location: GLint, values: &[i32]) {
1421         unsafe {
1422             self.ffi_gl_
1423                 .Uniform3iv(location, (values.len() / 3) as GLsizei, values.as_ptr());
1424         }
1425     }
1426 
1427     #[allow(unused_variables)]
uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint)1428     fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
1429         panic!("not supported")
1430     }
1431 
uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat)1432     fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
1433         unsafe {
1434             self.ffi_gl_.Uniform4f(location, x, y, z, w);
1435         }
1436     }
1437 
uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint)1438     fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) {
1439         unsafe {
1440             self.ffi_gl_.Uniform4i(location, x, y, z, w);
1441         }
1442     }
1443 
uniform_4iv(&self, location: GLint, values: &[i32])1444     fn uniform_4iv(&self, location: GLint, values: &[i32]) {
1445         unsafe {
1446             self.ffi_gl_
1447                 .Uniform4iv(location, (values.len() / 4) as GLsizei, values.as_ptr());
1448         }
1449     }
1450 
1451     #[allow(unused_variables)]
uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint)1452     fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
1453         panic!("not supported")
1454     }
1455 
uniform_4fv(&self, location: GLint, values: &[f32])1456     fn uniform_4fv(&self, location: GLint, values: &[f32]) {
1457         unsafe {
1458             self.ffi_gl_
1459                 .Uniform4fv(location, (values.len() / 4) as GLsizei, values.as_ptr());
1460         }
1461     }
1462 
uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32])1463     fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1464         unsafe {
1465             self.ffi_gl_.UniformMatrix2fv(
1466                 location,
1467                 (value.len() / 4) as GLsizei,
1468                 transpose as GLboolean,
1469                 value.as_ptr(),
1470             );
1471         }
1472     }
1473 
uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32])1474     fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1475         unsafe {
1476             self.ffi_gl_.UniformMatrix3fv(
1477                 location,
1478                 (value.len() / 9) as GLsizei,
1479                 transpose as GLboolean,
1480                 value.as_ptr(),
1481             );
1482         }
1483     }
1484 
uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32])1485     fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1486         unsafe {
1487             self.ffi_gl_.UniformMatrix4fv(
1488                 location,
1489                 (value.len() / 16) as GLsizei,
1490                 transpose as GLboolean,
1491                 value.as_ptr(),
1492             );
1493         }
1494     }
1495 
depth_mask(&self, flag: bool)1496     fn depth_mask(&self, flag: bool) {
1497         unsafe {
1498             self.ffi_gl_.DepthMask(flag as GLboolean);
1499         }
1500     }
1501 
depth_range(&self, near: f64, far: f64)1502     fn depth_range(&self, near: f64, far: f64) {
1503         unsafe {
1504             self.ffi_gl_.DepthRangef(near as GLclampf, far as GLclampf);
1505         }
1506     }
1507 
get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String)1508     fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1509         let mut buf_size = [0];
1510         unsafe {
1511             self.get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH, &mut buf_size);
1512         }
1513         let mut name = vec![0u8; buf_size[0] as usize];
1514         let mut length = 0 as GLsizei;
1515         let mut size = 0 as i32;
1516         let mut type_ = 0 as u32;
1517         unsafe {
1518             self.ffi_gl_.GetActiveAttrib(
1519                 program,
1520                 index,
1521                 buf_size[0],
1522                 &mut length,
1523                 &mut size,
1524                 &mut type_,
1525                 name.as_mut_ptr() as *mut GLchar,
1526             );
1527         }
1528         name.truncate(if length > 0 { length as usize } else { 0 });
1529         (size, type_, String::from_utf8(name).unwrap())
1530     }
1531 
get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String)1532     fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1533         let mut buf_size = [0];
1534         unsafe {
1535             self.get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH, &mut buf_size);
1536         }
1537         let mut name = vec![0 as u8; buf_size[0] as usize];
1538         let mut length: GLsizei = 0;
1539         let mut size: i32 = 0;
1540         let mut type_: u32 = 0;
1541 
1542         unsafe {
1543             self.ffi_gl_.GetActiveUniform(
1544                 program,
1545                 index,
1546                 buf_size[0],
1547                 &mut length,
1548                 &mut size,
1549                 &mut type_,
1550                 name.as_mut_ptr() as *mut GLchar,
1551             );
1552         }
1553 
1554         name.truncate(if length > 0 { length as usize } else { 0 });
1555 
1556         (size, type_, String::from_utf8(name).unwrap())
1557     }
1558 
get_active_uniforms_iv( &self, program: GLuint, indices: Vec<GLuint>, pname: GLenum, ) -> Vec<GLint>1559     fn get_active_uniforms_iv(
1560         &self,
1561         program: GLuint,
1562         indices: Vec<GLuint>,
1563         pname: GLenum,
1564     ) -> Vec<GLint> {
1565         let mut result = Vec::with_capacity(indices.len());
1566         unsafe {
1567             result.set_len(indices.len());
1568             self.ffi_gl_.GetActiveUniformsiv(
1569                 program,
1570                 indices.len() as GLsizei,
1571                 indices.as_ptr(),
1572                 pname,
1573                 result.as_mut_ptr(),
1574             );
1575         }
1576         result
1577     }
1578 
get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint1579     fn get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint {
1580         let mut result = 0 as GLint;
1581         unsafe {
1582             self.ffi_gl_
1583                 .GetActiveUniformBlockiv(program, index, pname, &mut result);
1584         }
1585         result
1586     }
1587 
get_active_uniform_block_iv( &self, program: GLuint, index: GLuint, pname: GLenum, ) -> Vec<GLint>1588     fn get_active_uniform_block_iv(
1589         &self,
1590         program: GLuint,
1591         index: GLuint,
1592         pname: GLenum,
1593     ) -> Vec<GLint> {
1594         let count =
1595             self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_ACTIVE_UNIFORMS);
1596         let mut result = Vec::with_capacity(count as usize);
1597         unsafe {
1598             result.set_len(count as usize);
1599             self.ffi_gl_
1600                 .GetActiveUniformBlockiv(program, index, pname, result.as_mut_ptr());
1601         }
1602         result
1603     }
1604 
get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String1605     fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String {
1606         let buf_size =
1607             self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_NAME_LENGTH);
1608         let mut name = vec![0 as u8; buf_size as usize];
1609         let mut length: GLsizei = 0;
1610         unsafe {
1611             self.ffi_gl_.GetActiveUniformBlockName(
1612                 program,
1613                 index,
1614                 buf_size,
1615                 &mut length,
1616                 name.as_mut_ptr() as *mut GLchar,
1617             );
1618         }
1619         name.truncate(if length > 0 { length as usize } else { 0 });
1620 
1621         String::from_utf8(name).unwrap()
1622     }
1623 
get_attrib_location(&self, program: GLuint, name: &str) -> c_int1624     fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int {
1625         let name = CString::new(name).unwrap();
1626         unsafe { self.ffi_gl_.GetAttribLocation(program, name.as_ptr()) }
1627     }
1628 
1629     #[allow(unused_variables)]
get_frag_data_location(&self, program: GLuint, name: &str) -> c_int1630     fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int {
1631         panic!("not supported")
1632     }
1633 
get_uniform_location(&self, program: GLuint, name: &str) -> c_int1634     fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int {
1635         let name = CString::new(name).unwrap();
1636         unsafe { self.ffi_gl_.GetUniformLocation(program, name.as_ptr()) }
1637     }
1638 
get_program_info_log(&self, program: GLuint) -> String1639     fn get_program_info_log(&self, program: GLuint) -> String {
1640         let mut max_len = [0];
1641         unsafe {
1642             self.get_program_iv(program, ffi::INFO_LOG_LENGTH, &mut max_len);
1643         }
1644         if max_len[0] == 0 {
1645             return String::new();
1646         }
1647         let mut result = vec![0u8; max_len[0] as usize];
1648         let mut result_len = 0 as GLsizei;
1649         unsafe {
1650             self.ffi_gl_.GetProgramInfoLog(
1651                 program,
1652                 max_len[0] as GLsizei,
1653                 &mut result_len,
1654                 result.as_mut_ptr() as *mut GLchar,
1655             );
1656         }
1657         result.truncate(if result_len > 0 {
1658             result_len as usize
1659         } else {
1660             0
1661         });
1662         String::from_utf8(result).unwrap()
1663     }
1664 
1665     #[inline]
get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint])1666     unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]) {
1667         assert!(!result.is_empty());
1668         self.ffi_gl_
1669             .GetProgramiv(program, pname, result.as_mut_ptr());
1670     }
1671 
get_program_binary(&self, program: GLuint) -> (Vec<u8>, GLenum)1672     fn get_program_binary(&self, program: GLuint) -> (Vec<u8>, GLenum) {
1673         let mut len = [0];
1674         unsafe {
1675             self.get_program_iv(program, ffi::PROGRAM_BINARY_LENGTH, &mut len);
1676         }
1677         if len[0] <= 0 {
1678             return (Vec::new(), NONE);
1679         }
1680         let mut binary: Vec<u8> = Vec::with_capacity(len[0] as usize);
1681         let mut format = NONE;
1682         let mut out_len = 0;
1683         unsafe {
1684             binary.set_len(len[0] as usize);
1685             self.ffi_gl_.GetProgramBinary(
1686                 program,
1687                 len[0],
1688                 &mut out_len as *mut GLsizei,
1689                 &mut format,
1690                 binary.as_mut_ptr() as *mut c_void,
1691             );
1692         }
1693         if len[0] != out_len {
1694             return (Vec::new(), NONE);
1695         }
1696 
1697         (binary, format)
1698     }
1699 
program_binary(&self, program: GLuint, format: GLenum, binary: &[u8])1700     fn program_binary(&self, program: GLuint, format: GLenum, binary: &[u8]) {
1701         unsafe {
1702             self.ffi_gl_.ProgramBinary(
1703                 program,
1704                 format,
1705                 binary.as_ptr() as *const c_void,
1706                 binary.len() as GLsizei,
1707             );
1708         }
1709     }
1710 
program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint)1711     fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint) {
1712         unsafe {
1713             self.ffi_gl_.ProgramParameteri(program, pname, value);
1714         }
1715     }
1716 
1717     #[inline]
get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint])1718     unsafe fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint]) {
1719         assert!(!result.is_empty());
1720         self.ffi_gl_
1721             .GetVertexAttribiv(index, pname, result.as_mut_ptr());
1722     }
1723 
1724     #[inline]
get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat])1725     unsafe fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat]) {
1726         assert!(!result.is_empty());
1727         self.ffi_gl_
1728             .GetVertexAttribfv(index, pname, result.as_mut_ptr());
1729     }
1730 
get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr1731     fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr {
1732         let mut result = 0 as *mut GLvoid;
1733         unsafe {
1734             self.ffi_gl_
1735                 .GetVertexAttribPointerv(index, pname, &mut result)
1736         }
1737         result as GLsizeiptr
1738     }
1739 
get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint1740     fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint {
1741         let mut result = 0 as GLint;
1742         unsafe {
1743             self.ffi_gl_
1744                 .GetBufferParameteriv(target, pname, &mut result);
1745         }
1746         result
1747     }
1748 
get_shader_info_log(&self, shader: GLuint) -> String1749     fn get_shader_info_log(&self, shader: GLuint) -> String {
1750         let mut max_len = [0];
1751         unsafe {
1752             self.get_shader_iv(shader, ffi::INFO_LOG_LENGTH, &mut max_len);
1753         }
1754         if max_len[0] == 0 {
1755             return String::new();
1756         }
1757         let mut result = vec![0u8; max_len[0] as usize];
1758         let mut result_len = 0 as GLsizei;
1759         unsafe {
1760             self.ffi_gl_.GetShaderInfoLog(
1761                 shader,
1762                 max_len[0] as GLsizei,
1763                 &mut result_len,
1764                 result.as_mut_ptr() as *mut GLchar,
1765             );
1766         }
1767         result.truncate(if result_len > 0 {
1768             result_len as usize
1769         } else {
1770             0
1771         });
1772         String::from_utf8(result).unwrap()
1773     }
1774 
get_string(&self, which: GLenum) -> String1775     fn get_string(&self, which: GLenum) -> String {
1776         unsafe {
1777             let llstr = self.ffi_gl_.GetString(which);
1778             if !llstr.is_null() {
1779                 return str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes())
1780                     .to_string();
1781             } else {
1782                 return "".to_string();
1783             }
1784         }
1785     }
1786 
get_string_i(&self, which: GLenum, index: GLuint) -> String1787     fn get_string_i(&self, which: GLenum, index: GLuint) -> String {
1788         unsafe {
1789             let llstr = self.ffi_gl_.GetStringi(which, index);
1790             if !llstr.is_null() {
1791                 str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes())
1792                     .to_string()
1793             } else {
1794                 "".to_string()
1795             }
1796         }
1797     }
1798 
get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint])1799     unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]) {
1800         assert!(!result.is_empty());
1801         self.ffi_gl_.GetShaderiv(shader, pname, result.as_mut_ptr());
1802     }
1803 
get_shader_precision_format( &self, shader_type: GLuint, precision_type: GLuint, ) -> (GLint, GLint, GLint)1804     fn get_shader_precision_format(
1805         &self,
1806         shader_type: GLuint,
1807         precision_type: GLuint,
1808     ) -> (GLint, GLint, GLint) {
1809         let (mut range, mut precision) = match precision_type {
1810             // These values are for a 32-bit twos-complement integer format.
1811             ffi::LOW_INT | ffi::MEDIUM_INT | ffi::HIGH_INT => ([31, 30], 0),
1812 
1813             // These values are for an IEEE single-precision floating-point format.
1814             ffi::LOW_FLOAT | ffi::MEDIUM_FLOAT | ffi::HIGH_FLOAT => ([127, 127], 23),
1815 
1816             _ => unreachable!("invalid precision"),
1817         };
1818         // This function is sometimes defined even though it's really just
1819         // a stub, so we need to set range and precision as if it weren't
1820         // defined before calling it. Suppress any error that might occur.
1821         unsafe {
1822             self.ffi_gl_.GetShaderPrecisionFormat(
1823                 shader_type,
1824                 precision_type,
1825                 range.as_mut_ptr(),
1826                 &mut precision,
1827             );
1828             let _ = self.ffi_gl_.GetError();
1829         }
1830 
1831         (range[0], range[1], precision)
1832     }
1833 
compile_shader(&self, shader: GLuint)1834     fn compile_shader(&self, shader: GLuint) {
1835         unsafe {
1836             self.ffi_gl_.CompileShader(shader);
1837         }
1838     }
1839 
create_program(&self) -> GLuint1840     fn create_program(&self) -> GLuint {
1841         unsafe {
1842             return self.ffi_gl_.CreateProgram();
1843         }
1844     }
1845 
delete_program(&self, program: GLuint)1846     fn delete_program(&self, program: GLuint) {
1847         unsafe {
1848             self.ffi_gl_.DeleteProgram(program);
1849         }
1850     }
1851 
create_shader(&self, shader_type: GLenum) -> GLuint1852     fn create_shader(&self, shader_type: GLenum) -> GLuint {
1853         unsafe {
1854             return self.ffi_gl_.CreateShader(shader_type);
1855         }
1856     }
1857 
delete_shader(&self, shader: GLuint)1858     fn delete_shader(&self, shader: GLuint) {
1859         unsafe {
1860             self.ffi_gl_.DeleteShader(shader);
1861         }
1862     }
1863 
detach_shader(&self, program: GLuint, shader: GLuint)1864     fn detach_shader(&self, program: GLuint, shader: GLuint) {
1865         unsafe {
1866             self.ffi_gl_.DetachShader(program, shader);
1867         }
1868     }
1869 
link_program(&self, program: GLuint)1870     fn link_program(&self, program: GLuint) {
1871         unsafe {
1872             return self.ffi_gl_.LinkProgram(program);
1873         }
1874     }
1875 
clear_color(&self, r: f32, g: f32, b: f32, a: f32)1876     fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) {
1877         unsafe {
1878             self.ffi_gl_.ClearColor(r, g, b, a);
1879         }
1880     }
1881 
clear(&self, buffer_mask: GLbitfield)1882     fn clear(&self, buffer_mask: GLbitfield) {
1883         unsafe {
1884             self.ffi_gl_.Clear(buffer_mask);
1885         }
1886     }
1887 
clear_depth(&self, depth: f64)1888     fn clear_depth(&self, depth: f64) {
1889         unsafe {
1890             self.ffi_gl_.ClearDepthf(depth as GLclampf);
1891         }
1892     }
1893 
clear_stencil(&self, s: GLint)1894     fn clear_stencil(&self, s: GLint) {
1895         unsafe {
1896             self.ffi_gl_.ClearStencil(s);
1897         }
1898     }
1899 
flush(&self)1900     fn flush(&self) {
1901         unsafe {
1902             self.ffi_gl_.Flush();
1903         }
1904     }
1905 
finish(&self)1906     fn finish(&self) {
1907         unsafe {
1908             self.ffi_gl_.Finish();
1909         }
1910     }
1911 
get_error(&self) -> GLenum1912     fn get_error(&self) -> GLenum {
1913         unsafe { self.ffi_gl_.GetError() }
1914     }
1915 
stencil_mask(&self, mask: GLuint)1916     fn stencil_mask(&self, mask: GLuint) {
1917         unsafe { self.ffi_gl_.StencilMask(mask) }
1918     }
1919 
stencil_mask_separate(&self, face: GLenum, mask: GLuint)1920     fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) {
1921         unsafe { self.ffi_gl_.StencilMaskSeparate(face, mask) }
1922     }
1923 
stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint)1924     fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint) {
1925         unsafe { self.ffi_gl_.StencilFunc(func, ref_, mask) }
1926     }
1927 
stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint)1928     fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint) {
1929         unsafe { self.ffi_gl_.StencilFuncSeparate(face, func, ref_, mask) }
1930     }
1931 
stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum)1932     fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
1933         unsafe { self.ffi_gl_.StencilOp(sfail, dpfail, dppass) }
1934     }
1935 
stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum)1936     fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
1937         unsafe { self.ffi_gl_.StencilOpSeparate(face, sfail, dpfail, dppass) }
1938     }
1939 
egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES)1940     fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
1941         unsafe {
1942             self.ffi_gl_.EGLImageTargetTexture2DOES(target, image);
1943         }
1944     }
1945 
egl_image_target_renderbuffer_storage_oes(&self, target: GLenum, image: GLeglImageOES)1946     fn egl_image_target_renderbuffer_storage_oes(&self, target: GLenum, image: GLeglImageOES) {
1947         unsafe {
1948             self.ffi_gl_.EGLImageTargetRenderbufferStorageOES(target, image);
1949         }
1950     }
1951 
generate_mipmap(&self, target: GLenum)1952     fn generate_mipmap(&self, target: GLenum) {
1953         unsafe { self.ffi_gl_.GenerateMipmap(target) }
1954     }
1955 
insert_event_marker_ext(&self, message: &str)1956     fn insert_event_marker_ext(&self, message: &str) {
1957         if self.ffi_gl_.InsertEventMarkerEXT.is_loaded() {
1958             unsafe {
1959                 self.ffi_gl_
1960                     .InsertEventMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
1961             }
1962         }
1963     }
1964 
push_group_marker_ext(&self, message: &str)1965     fn push_group_marker_ext(&self, message: &str) {
1966         if self.ffi_gl_.PushGroupMarkerEXT.is_loaded() {
1967             unsafe {
1968                 self.ffi_gl_
1969                     .PushGroupMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
1970             }
1971         }
1972     }
1973 
pop_group_marker_ext(&self)1974     fn pop_group_marker_ext(&self) {
1975         if self.ffi_gl_.PopGroupMarkerEXT.is_loaded() {
1976             unsafe {
1977                 self.ffi_gl_.PopGroupMarkerEXT();
1978             }
1979         }
1980     }
1981 
debug_message_insert_khr(&self, source: GLenum, type_: GLenum, id: GLuint, severity: GLenum, message: &str)1982     fn debug_message_insert_khr(&self, source: GLenum, type_: GLenum, id: GLuint, severity: GLenum, message: &str) {
1983         if self.ffi_gl_.DebugMessageInsertKHR.is_loaded() {
1984             unsafe {
1985                 self.ffi_gl_
1986                     .DebugMessageInsertKHR(source, type_, id, severity, message.len() as GLsizei, message.as_ptr() as *const _);
1987             }
1988         }
1989     }
1990 
push_debug_group_khr(&self, source: GLenum, id: GLuint, message: &str)1991     fn push_debug_group_khr(&self, source: GLenum, id: GLuint, message: &str) {
1992         if self.ffi_gl_.PushDebugGroupKHR.is_loaded() {
1993             unsafe {
1994                 self.ffi_gl_
1995                     .PushDebugGroupKHR(source, id, message.len() as GLsizei, message.as_ptr() as *const _);
1996             }
1997         }
1998     }
1999 
pop_debug_group_khr(&self)2000     fn pop_debug_group_khr(&self) {
2001         if self.ffi_gl_.PopDebugGroupKHR.is_loaded() {
2002             unsafe {
2003                 self.ffi_gl_.PopDebugGroupKHR();
2004             }
2005         }
2006     }
2007 
fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync2008     fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync {
2009         unsafe { self.ffi_gl_.FenceSync(condition, flags) as *const _ }
2010     }
2011 
client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) -> GLenum2012     fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) -> GLenum {
2013         unsafe {
2014             self.ffi_gl_
2015                 .ClientWaitSync(sync as *const _, flags, timeout)
2016         }
2017     }
2018 
wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64)2019     fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) {
2020         unsafe {
2021             self.ffi_gl_.WaitSync(sync as *const _, flags, timeout);
2022         }
2023     }
2024 
delete_sync(&self, sync: GLsync)2025     fn delete_sync(&self, sync: GLsync) {
2026         unsafe {
2027             self.ffi_gl_.DeleteSync(sync as *const _);
2028         }
2029     }
2030 
texture_range_apple(&self, _target: GLenum, _data: &[u8])2031     fn texture_range_apple(&self, _target: GLenum, _data: &[u8]) {
2032         panic!("not supported")
2033     }
2034 
gen_fences_apple(&self, _n: GLsizei) -> Vec<GLuint>2035     fn gen_fences_apple(&self, _n: GLsizei) -> Vec<GLuint> {
2036         panic!("not supported")
2037     }
2038 
delete_fences_apple(&self, _fences: &[GLuint])2039     fn delete_fences_apple(&self, _fences: &[GLuint]) {
2040         panic!("not supported")
2041     }
2042 
set_fence_apple(&self, _fence: GLuint)2043     fn set_fence_apple(&self, _fence: GLuint) {
2044         panic!("not supported")
2045     }
2046 
finish_fence_apple(&self, _fence: GLuint)2047     fn finish_fence_apple(&self, _fence: GLuint) {
2048         panic!("not supported")
2049     }
2050 
test_fence_apple(&self, _fence: GLuint)2051     fn test_fence_apple(&self, _fence: GLuint) {
2052         panic!("not supported")
2053     }
2054 
test_object_apple(&self, _object: GLenum, _name: GLuint) -> GLboolean2055     fn test_object_apple(&self, _object: GLenum, _name: GLuint) -> GLboolean {
2056         panic!("not supported")
2057     }
2058 
finish_object_apple(&self, _object: GLenum, _name: GLuint)2059     fn finish_object_apple(&self, _object: GLenum, _name: GLuint) {
2060         panic!("not supported")
2061     }
2062 
2063 
2064 
2065     // GL_ARB_blend_func_extended
bind_frag_data_location_indexed( &self, _program: GLuint, _color_number: GLuint, _index: GLuint, _name: &str, )2066     fn bind_frag_data_location_indexed(
2067         &self,
2068         _program: GLuint,
2069         _color_number: GLuint,
2070         _index: GLuint,
2071         _name: &str,
2072     ) {
2073         panic!("not supported");
2074     }
2075 
get_frag_data_index(&self, _program: GLuint, _name: &str) -> GLint2076     fn get_frag_data_index(&self, _program: GLuint, _name: &str) -> GLint {
2077         panic!("not supported");
2078     }
2079 
2080     // GL_KHR_debug
get_debug_messages(&self) -> Vec<DebugMessage>2081     fn get_debug_messages(&self) -> Vec<DebugMessage> {
2082         if !self.ffi_gl_.GetDebugMessageLog.is_loaded() {
2083             return Vec::new();
2084         }
2085 
2086         let mut max_message_len = 0;
2087         unsafe {
2088             self.ffi_gl_
2089                 .GetIntegerv(ffi::MAX_DEBUG_MESSAGE_LENGTH, &mut max_message_len)
2090         }
2091 
2092         let mut output = Vec::new();
2093         const CAPACITY: usize = 4;
2094 
2095         let mut msg_data = vec![0u8; CAPACITY * max_message_len as usize];
2096         let mut sources = [0 as GLenum; CAPACITY];
2097         let mut types = [0 as GLenum; CAPACITY];
2098         let mut severities = [0 as GLenum; CAPACITY];
2099         let mut ids = [0 as GLuint; CAPACITY];
2100         let mut lengths = [0 as GLsizei; CAPACITY];
2101 
2102         loop {
2103             let count = unsafe {
2104                 self.ffi_gl_.GetDebugMessageLog(
2105                     CAPACITY as _,
2106                     msg_data.len() as _,
2107                     sources.as_mut_ptr(),
2108                     types.as_mut_ptr(),
2109                     ids.as_mut_ptr(),
2110                     severities.as_mut_ptr(),
2111                     lengths.as_mut_ptr(),
2112                     msg_data.as_mut_ptr() as *mut _,
2113                 )
2114             };
2115 
2116             let mut offset = 0;
2117             output.extend((0..count as usize).map(|i| {
2118                 let len = lengths[i] as usize;
2119                 let slice = &msg_data[offset..offset + len];
2120                 offset += len;
2121                 DebugMessage {
2122                     message: String::from_utf8_lossy(slice).to_string(),
2123                     source: sources[i],
2124                     ty: types[i],
2125                     id: ids[i],
2126                     severity: severities[i],
2127                 }
2128             }));
2129 
2130             if (count as usize) < CAPACITY {
2131                 return output;
2132             }
2133         }
2134     }
2135 
provoking_vertex_angle(&self, mode: GLenum)2136     fn provoking_vertex_angle(&self, mode: GLenum) {
2137         unsafe {
2138             self.ffi_gl_.ProvokingVertexANGLE(mode);
2139         }
2140     }
2141 
2142     // GL_KHR_blend_equation_advanced
blend_barrier_khr(&self)2143     fn blend_barrier_khr(&self) {
2144         if self.ffi_gl_.BlendBarrierKHR.is_loaded() {
2145             unsafe {
2146                 self.ffi_gl_.BlendBarrierKHR();
2147             }
2148         }
2149     }
2150 
2151     // GL_CHROMIUM_copy_texture
copy_texture_chromium(&self, source_id: GLuint, source_level: GLint, dest_target: GLenum, dest_id: GLuint, dest_level: GLint, internal_format: GLint, dest_type: GLenum, unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean)2152     fn copy_texture_chromium(&self,
2153         source_id: GLuint, source_level: GLint,
2154         dest_target: GLenum, dest_id: GLuint, dest_level: GLint,
2155         internal_format: GLint, dest_type: GLenum,
2156         unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean)
2157     {
2158         unsafe {
2159             self.ffi_gl_.CopyTextureCHROMIUM(source_id, source_level, dest_target, dest_id, dest_level,
2160                 internal_format, dest_type,
2161                 unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha,
2162             );
2163         }
2164     }
copy_sub_texture_chromium(&self, source_id: GLuint, source_level: GLint, dest_target: GLenum, dest_id: GLuint, dest_level: GLint, x_offset: GLint, y_offset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei, unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean)2165     fn copy_sub_texture_chromium(&self,
2166         source_id: GLuint, source_level: GLint,
2167         dest_target: GLenum, dest_id: GLuint, dest_level: GLint,
2168         x_offset: GLint, y_offset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei,
2169         unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean)
2170     {
2171         unsafe {
2172             self.ffi_gl_.CopySubTextureCHROMIUM(source_id, source_level, dest_target, dest_id, dest_level,
2173                 x_offset, y_offset, x, y, width, height,
2174                 unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha,
2175             );
2176         }
2177     }
2178 
2179     // GL_ANGLE_copy_texture_3d
copy_texture_3d_angle( &self, source_id: GLuint, source_level: GLint, dest_target: GLenum, dest_id: GLuint, dest_level: GLint, internal_format: GLint, dest_type: GLenum, unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean, )2180     fn copy_texture_3d_angle(
2181         &self,
2182         source_id: GLuint,
2183         source_level: GLint,
2184         dest_target: GLenum,
2185         dest_id: GLuint,
2186         dest_level: GLint,
2187         internal_format: GLint,
2188         dest_type: GLenum,
2189         unpack_flip_y: GLboolean,
2190         unpack_premultiply_alpha: GLboolean,
2191         unpack_unmultiply_alpha: GLboolean,
2192     ) {
2193         unsafe {
2194             self.ffi_gl_.CopyTexture3DANGLE(
2195                 source_id,
2196                 source_level,
2197                 dest_target,
2198                 dest_id,
2199                 dest_level,
2200                 internal_format,
2201                 dest_type,
2202                 unpack_flip_y,
2203                 unpack_premultiply_alpha,
2204                 unpack_unmultiply_alpha,
2205             );
2206         }
2207     }
2208 
copy_sub_texture_3d_angle( &self, source_id: GLuint, source_level: GLint, dest_target: GLenum, dest_id: GLuint, dest_level: GLint, x_offset: GLint, y_offset: GLint, z_offset: GLint, x: GLint, y: GLint, z: GLint, width: GLsizei, height: GLsizei, depth: GLsizei, unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean, )2209     fn copy_sub_texture_3d_angle(
2210         &self,
2211         source_id: GLuint,
2212         source_level: GLint,
2213         dest_target: GLenum,
2214         dest_id: GLuint,
2215         dest_level: GLint,
2216         x_offset: GLint,
2217         y_offset: GLint,
2218         z_offset: GLint,
2219         x: GLint,
2220         y: GLint,
2221         z: GLint,
2222         width: GLsizei,
2223         height: GLsizei,
2224         depth: GLsizei,
2225         unpack_flip_y: GLboolean,
2226         unpack_premultiply_alpha: GLboolean,
2227         unpack_unmultiply_alpha: GLboolean,
2228     ) {
2229         unsafe {
2230             self.ffi_gl_.CopySubTexture3DANGLE(
2231                 source_id,
2232                 source_level,
2233                 dest_target,
2234                 dest_id,
2235                 dest_level,
2236                 x_offset,
2237                 y_offset,
2238                 z_offset,
2239                 x,
2240                 y,
2241                 z,
2242                 width,
2243                 height,
2244                 depth,
2245                 unpack_flip_y,
2246                 unpack_premultiply_alpha,
2247                 unpack_unmultiply_alpha,
2248             );
2249         }
2250     }
2251 
buffer_storage( &self, target: GLenum, size: GLsizeiptr, data: *const GLvoid, flags: GLbitfield, )2252     fn buffer_storage(
2253         &self,
2254         target: GLenum,
2255         size: GLsizeiptr,
2256         data: *const GLvoid,
2257         flags: GLbitfield,
2258     ) {
2259         unsafe {
2260             self.ffi_gl_.BufferStorageEXT(target, size, data, flags);
2261         }
2262     }
2263 
flush_mapped_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr)2264     fn flush_mapped_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr) {
2265         unsafe {
2266             self.ffi_gl_.FlushMappedBufferRange(target, offset, length);
2267         }
2268     }
2269 }
2270