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
15 {
load_with<'a, F>(loadfn: F) -> Rc<Gl> where F: FnMut(&str) -> *const c_void16     pub unsafe fn load_with<'a, F>(loadfn: F) -> Rc<Gl> where F: FnMut(&str) -> *const c_void {
17         let ffi_gl_ = GlesFfi::load_with(loadfn);
18         Rc::new(GlesFns {
19             ffi_gl_: ffi_gl_,
20         }) as Rc<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(&self, target: GLenum, size: GLsizeiptr, data: *const GLvoid, usage: GLenum) {
30         unsafe {
31             self.ffi_gl_.BufferData(target,
32                                     size,
33                                     data,
34                                     usage);
35         }
36     }
37 
tex_buffer(&self, _target: GLenum, _internal_format: GLenum, _buffer: GLuint)38     fn tex_buffer(&self, _target: GLenum, _internal_format: GLenum, _buffer: GLuint) {
39         panic!("not supported")
40     }
41 
buffer_sub_data_untyped(&self, target: GLenum, offset: isize, size: GLsizeiptr, data: *const GLvoid)42     fn buffer_sub_data_untyped(&self, target: GLenum, offset: isize, size: GLsizeiptr, data: *const GLvoid) {
43         unsafe {
44             self.ffi_gl_.BufferSubData(target,
45                                        offset,
46                                        size,
47                                        data);
48         }
49     }
50 
shader_source(&self, shader: GLuint, strings: &[&[u8]])51     fn shader_source(&self, shader: GLuint, strings: &[&[u8]]) {
52         let pointers: Vec<*const u8> = strings.iter().map(|string| (*string).as_ptr()).collect();
53         let lengths: Vec<GLint> = strings.iter().map(|string| string.len() as GLint).collect();
54         unsafe {
55             self.ffi_gl_.ShaderSource(shader, pointers.len() as GLsizei,
56                                       pointers.as_ptr() as *const *const GLchar, lengths.as_ptr());
57         }
58         drop(lengths);
59         drop(pointers);
60     }
61 
62     #[allow(unused_variables)]
read_buffer(&self, mode: GLenum)63     fn read_buffer(&self, mode: GLenum) {
64         panic!("not supported")
65     }
66 
read_pixels_into_buffer(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum, dst_buffer: &mut [u8])67     fn read_pixels_into_buffer(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei,
68                                format: GLenum, pixel_type: GLenum, dst_buffer: &mut [u8]) {
69         // Assumes that the user properly allocated the size for dst_buffer.
70         assert!(calculate_length(width, height, format, pixel_type) == dst_buffer.len());
71 
72         unsafe {
73             // We don't want any alignment padding on pixel rows.
74             self.ffi_gl_.PixelStorei(ffi::PACK_ALIGNMENT, 1);
75             self.ffi_gl_.ReadPixels(x, y, width, height, format, pixel_type, dst_buffer.as_mut_ptr() as *mut c_void);
76         }
77     }
78 
read_pixels(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> Vec<u8>79     fn read_pixels(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> Vec<u8> {
80         let len = calculate_length(width, height, format, pixel_type);
81         let mut pixels: Vec<u8> = Vec::new();
82         pixels.reserve(len);
83         unsafe { pixels.set_len(len); }
84 
85         self.read_pixels_into_buffer(x, y, width, height, format, pixel_type, pixels.as_mut_slice());
86 
87         pixels
88     }
89 
sample_coverage(&self, value: GLclampf, invert: bool)90     fn sample_coverage(&self, value: GLclampf, invert: bool) {
91         unsafe {
92             self.ffi_gl_.SampleCoverage(value, invert as GLboolean);
93         }
94     }
95 
polygon_offset(&self, factor: GLfloat, units: GLfloat)96     fn polygon_offset(&self, factor: GLfloat, units: GLfloat) {
97         unsafe {
98             self.ffi_gl_.PolygonOffset(factor, units);
99         }
100     }
101 
pixel_store_i(&self, name: GLenum, param: GLint)102     fn pixel_store_i(&self, name: GLenum, param: GLint) {
103         unsafe {
104             self.ffi_gl_.PixelStorei(name, param);
105         }
106     }
107 
gen_buffers(&self, n: GLsizei) -> Vec<GLuint>108     fn gen_buffers(&self, n: GLsizei) -> Vec<GLuint> {
109         let mut result = vec![0 as GLuint; n as usize];
110         unsafe {
111             self.ffi_gl_.GenBuffers(n, result.as_mut_ptr());
112         }
113         result
114     }
115 
gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint>116     fn gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint> {
117         let mut result = vec![0 as GLuint; n as usize];
118         unsafe {
119             self.ffi_gl_.GenRenderbuffers(n, result.as_mut_ptr());
120         }
121         result
122     }
123 
gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint>124     fn gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint> {
125         let mut result = vec![0 as GLuint; n as usize];
126         unsafe {
127             self.ffi_gl_.GenFramebuffers(n, result.as_mut_ptr());
128         }
129         result
130     }
131 
gen_textures(&self, n: GLsizei) -> Vec<GLuint>132     fn gen_textures(&self, n: GLsizei) -> Vec<GLuint> {
133         let mut result = vec![0 as GLuint; n as usize];
134         unsafe {
135             self.ffi_gl_.GenTextures(n, result.as_mut_ptr());
136         }
137         result
138     }
139 
gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint>140     fn gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint> {
141         let mut result = vec![0 as GLuint; n as usize];
142         unsafe {
143             self.ffi_gl_.GenVertexArrays(n, result.as_mut_ptr());
144         }
145         result
146     }
147 
gen_queries(&self, n: GLsizei) -> Vec<GLuint>148     fn gen_queries(&self, n: GLsizei) -> Vec<GLuint> {
149         if !self.ffi_gl_.GenQueriesEXT.is_loaded() {
150             return Vec::new();
151         }
152         let mut result = vec![0 as GLuint; n as usize];
153         unsafe {
154             self.ffi_gl_.GenQueriesEXT(n, result.as_mut_ptr());
155         }
156         result
157     }
158 
begin_query(&self, target: GLenum, id: GLuint)159     fn begin_query(&self, target: GLenum, id: GLuint) {
160         if !self.ffi_gl_.BeginQueryEXT.is_loaded() {
161             return;
162         }
163         unsafe {
164             self.ffi_gl_.BeginQueryEXT(target, id);
165         }
166     }
167 
end_query(&self, target: GLenum)168     fn end_query(&self, target: GLenum) {
169         if !self.ffi_gl_.EndQueryEXT.is_loaded() {
170             return;
171         }
172         unsafe {
173             self.ffi_gl_.EndQueryEXT(target);
174         }
175     }
176 
query_counter(&self, id: GLuint, target: GLenum)177     fn query_counter(&self, id: GLuint, target: GLenum) {
178         if !self.ffi_gl_.QueryCounterEXT.is_loaded() {
179             return;
180         }
181         unsafe {
182             self.ffi_gl_.QueryCounterEXT(id, target);
183         }
184     }
185 
get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32186     fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32 {
187         if !self.ffi_gl_.GetQueryObjectivEXT.is_loaded() {
188             return 0;
189         }
190         let mut result = 0;
191         unsafe {
192             self.ffi_gl_.GetQueryObjectivEXT(id, pname, &mut result);
193         }
194         result
195     }
196 
get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32197     fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32 {
198         if !self.ffi_gl_.GetQueryObjectuivEXT.is_loaded() {
199             return 0;
200         }
201         let mut result = 0;
202         unsafe {
203             self.ffi_gl_.GetQueryObjectuivEXT(id, pname, &mut result);
204         }
205         result
206     }
207 
get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64208     fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64 {
209         if !self.ffi_gl_.GetQueryObjecti64vEXT.is_loaded() {
210             return 0;
211         }
212         let mut result = 0;
213         unsafe {
214             self.ffi_gl_.GetQueryObjecti64vEXT(id, pname, &mut result);
215         }
216         result
217     }
218 
get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64219     fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64 {
220         if !self.ffi_gl_.GetQueryObjectui64vEXT.is_loaded() {
221             return 0;
222         }
223         let mut result = 0;
224         unsafe {
225             self.ffi_gl_.GetQueryObjectui64vEXT(id, pname, &mut result);
226         }
227         result
228     }
229 
delete_queries(&self, queries: &[GLuint])230     fn delete_queries(&self, queries: &[GLuint]) {
231         if !self.ffi_gl_.DeleteQueriesEXT.is_loaded() {
232             return;
233         }
234         unsafe {
235             self.ffi_gl_.DeleteQueriesEXT(queries.len() as GLsizei, queries.as_ptr());
236         }
237     }
238 
delete_vertex_arrays(&self, vertex_arrays: &[GLuint])239     fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]) {
240         unsafe {
241             self.ffi_gl_.DeleteVertexArrays(vertex_arrays.len() as GLsizei, vertex_arrays.as_ptr());
242         }
243     }
244 
delete_buffers(&self, buffers: &[GLuint])245     fn delete_buffers(&self, buffers: &[GLuint]) {
246         unsafe {
247             self.ffi_gl_.DeleteBuffers(buffers.len() as GLsizei, buffers.as_ptr());
248         }
249     }
250 
delete_renderbuffers(&self, renderbuffers: &[GLuint])251     fn delete_renderbuffers(&self, renderbuffers: &[GLuint]) {
252         unsafe {
253             self.ffi_gl_.DeleteRenderbuffers(renderbuffers.len() as GLsizei, renderbuffers.as_ptr());
254         }
255     }
256 
delete_framebuffers(&self, framebuffers: &[GLuint])257     fn delete_framebuffers(&self, framebuffers: &[GLuint]) {
258         unsafe {
259             self.ffi_gl_.DeleteFramebuffers(framebuffers.len() as GLsizei, framebuffers.as_ptr());
260         }
261     }
262 
delete_textures(&self, textures: &[GLuint])263     fn delete_textures(&self, textures: &[GLuint]) {
264         unsafe {
265             self.ffi_gl_.DeleteTextures(textures.len() as GLsizei, textures.as_ptr());
266         }
267     }
268 
framebuffer_renderbuffer(&self, target: GLenum, attachment: GLenum, renderbuffertarget: GLenum, renderbuffer: GLuint)269     fn framebuffer_renderbuffer(&self,
270                                 target: GLenum,
271                                 attachment: GLenum,
272                                 renderbuffertarget: GLenum,
273                                 renderbuffer: GLuint) {
274         unsafe {
275             self.ffi_gl_.FramebufferRenderbuffer(target,
276                                                  attachment,
277                                                  renderbuffertarget,
278                                                  renderbuffer);
279         }
280     }
281 
renderbuffer_storage(&self, target: GLenum, internalformat: GLenum, width: GLsizei, height: GLsizei)282     fn renderbuffer_storage(&self,
283                                 target: GLenum,
284                                 internalformat: GLenum,
285                                 width: GLsizei,
286                                 height: GLsizei) {
287         unsafe {
288             self.ffi_gl_.RenderbufferStorage(target,
289                                              internalformat,
290                                              width,
291                                              height);
292         }
293     }
294 
depth_func(&self, func: GLenum)295     fn depth_func(&self, func: GLenum) {
296         unsafe {
297             self.ffi_gl_.DepthFunc(func);
298         }
299     }
300 
active_texture(&self, texture: GLenum)301     fn active_texture(&self, texture: GLenum) {
302         unsafe {
303             self.ffi_gl_.ActiveTexture(texture);
304         }
305     }
306 
attach_shader(&self, program: GLuint, shader: GLuint)307     fn attach_shader(&self, program: GLuint, shader: GLuint) {
308         unsafe {
309             self.ffi_gl_.AttachShader(program, shader);
310         }
311     }
312 
bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str)313     fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) {
314         let c_string = CString::new(name).unwrap();
315         unsafe {
316             self.ffi_gl_.BindAttribLocation(program, index, c_string.as_ptr())
317         }
318     }
319 
320     // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml
get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint])321     unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]) {
322         assert!(!result.is_empty());
323         self.ffi_gl_.GetUniformiv(program, location, result.as_mut_ptr());
324     }
325 
326     // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml
get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat])327     unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]) {
328         assert!(!result.is_empty());
329         self.ffi_gl_.GetUniformfv(program, location, result.as_mut_ptr());
330     }
331 
get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint332     fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint {
333         let c_string = CString::new(name).unwrap();
334         unsafe {
335             self.ffi_gl_.GetUniformBlockIndex(program, c_string.as_ptr())
336         }
337     }
338 
get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec<GLuint>339     fn get_uniform_indices(&self,  program: GLuint, names: &[&str]) -> Vec<GLuint> {
340         let c_strings: Vec<CString> = names.iter().map(|n| CString::new(*n).unwrap()).collect();
341         let pointers: Vec<*const GLchar> = c_strings.iter().map(|string| string.as_ptr()).collect();
342         let mut result = Vec::with_capacity(c_strings.len());
343         unsafe {
344             result.set_len(c_strings.len());
345             self.ffi_gl_.GetUniformIndices(program,
346                                            pointers.len() as GLsizei,
347                                            pointers.as_ptr(),
348                                            result.as_mut_ptr());
349         }
350         result
351     }
352 
bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint)353     fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint) {
354         unsafe {
355             self.ffi_gl_.BindBufferBase(target, index, buffer);
356         }
357     }
358 
bind_buffer_range(&self, target: GLenum, index: GLuint, buffer: GLuint, offset: GLintptr, size: GLsizeiptr)359     fn bind_buffer_range(&self, target: GLenum, index: GLuint, buffer: GLuint, offset: GLintptr, size: GLsizeiptr) {
360         unsafe {
361             self.ffi_gl_.BindBufferRange(target, index, buffer, offset, size);
362         }
363     }
364 
uniform_block_binding(&self, program: GLuint, uniform_block_index: GLuint, uniform_block_binding: GLuint)365     fn uniform_block_binding(&self, program: GLuint, uniform_block_index: GLuint, uniform_block_binding: GLuint) {
366         unsafe {
367             self.ffi_gl_.UniformBlockBinding(program, uniform_block_index, uniform_block_binding);
368         }
369     }
370 
bind_buffer(&self, target: GLenum, buffer: GLuint)371     fn bind_buffer(&self, target: GLenum, buffer: GLuint) {
372         unsafe {
373             self.ffi_gl_.BindBuffer(target, buffer);
374         }
375     }
376 
bind_vertex_array(&self, vao: GLuint)377     fn bind_vertex_array(&self, vao: GLuint) {
378         unsafe {
379             self.ffi_gl_.BindVertexArray(vao);
380         }
381     }
382 
bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint)383     fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) {
384         unsafe {
385             self.ffi_gl_.BindRenderbuffer(target, renderbuffer);
386         }
387     }
388 
bind_framebuffer(&self, target: GLenum, framebuffer: GLuint)389     fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) {
390         unsafe {
391             self.ffi_gl_.BindFramebuffer(target, framebuffer);
392         }
393     }
394 
bind_texture(&self, target: GLenum, texture: GLuint)395     fn bind_texture(&self, target: GLenum, texture: GLuint) {
396         unsafe {
397             self.ffi_gl_.BindTexture(target, texture);
398         }
399     }
400 
draw_buffers(&self, bufs: &[GLenum])401     fn draw_buffers(&self, bufs: &[GLenum]) {
402         unsafe {
403             self.ffi_gl_.DrawBuffers(bufs.len() as GLsizei, bufs.as_ptr());
404         }
405     }
406 
407     // 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]>)408     fn tex_image_2d(&self,
409                     target: GLenum,
410                     level: GLint,
411                     internal_format: GLint,
412                     width: GLsizei,
413                     height: GLsizei,
414                     border: GLint,
415                     format: GLenum,
416                     ty: GLenum,
417                     opt_data: Option<&[u8]>) {
418         match opt_data {
419             Some(data) => {
420                 unsafe {
421                     self.ffi_gl_.TexImage2D(target, level, internal_format, width, height, border, format, ty,
422                                             data.as_ptr() as *const GLvoid);
423                 }
424             }
425             None => {
426                 unsafe {
427                     self.ffi_gl_.TexImage2D(target, level, internal_format, width, height, border, format, ty,
428                                             ptr::null());
429                 }
430             }
431         }
432     }
433 
compressed_tex_image_2d(&self, target: GLenum, level: GLint, internal_format: GLenum, width: GLsizei, height: GLsizei, border: GLint, data: &[u8])434     fn compressed_tex_image_2d(&self,
435                                target: GLenum,
436                                level: GLint,
437                                internal_format: GLenum,
438                                width: GLsizei,
439                                height: GLsizei,
440                                border: GLint,
441                                data: &[u8]) {
442         unsafe {
443             self.ffi_gl_.CompressedTexImage2D(target, level, internal_format, width, height, border,
444                                               data.len() as GLsizei, data.as_ptr() as *const GLvoid);
445         }
446     }
447 
compressed_tex_sub_image_2d(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, format: GLenum, data: &[u8])448     fn compressed_tex_sub_image_2d(&self,
449                                    target: GLenum,
450                                    level: GLint,
451                                    xoffset: GLint,
452                                    yoffset: GLint,
453                                    width: GLsizei,
454                                    height: GLsizei,
455                                    format: GLenum,
456                                    data: &[u8]) {
457         unsafe {
458             self.ffi_gl_.CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
459                                                  data.len() as GLsizei, data.as_ptr() as *const GLvoid);
460         }
461     }
462 
463     // 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]>)464     fn tex_image_3d(&self,
465                     target: GLenum,
466                     level: GLint,
467                     internal_format: GLint,
468                     width: GLsizei,
469                     height: GLsizei,
470                     depth: GLsizei,
471                     border: GLint,
472                     format: GLenum,
473                     ty: GLenum,
474                     opt_data: Option<&[u8]>) {
475         unsafe {
476             let pdata = match opt_data {
477                 Some(data) => mem::transmute(data.as_ptr()),
478                 None => ptr::null(),
479             };
480             self.ffi_gl_.TexImage3D(target,
481                                     level,
482                                     internal_format,
483                                     width,
484                                     height,
485                                     depth,
486                                     border,
487                                     format,
488                                     ty,
489                                     pdata);
490         }
491     }
492 
copy_tex_image_2d(&self, target: GLenum, level: GLint, internal_format: GLenum, x: GLint, y: GLint, width: GLsizei, height: GLsizei, border: GLint)493     fn copy_tex_image_2d(&self,
494                          target: GLenum,
495                          level: GLint,
496                          internal_format: GLenum,
497                          x: GLint,
498                          y: GLint,
499                          width: GLsizei,
500                          height: GLsizei,
501                          border: GLint) {
502         unsafe {
503             self.ffi_gl_.CopyTexImage2D(target,
504                                         level,
505                                         internal_format,
506                                         x,
507                                         y,
508                                         width,
509                                         height,
510                                         border);
511         }
512     }
513 
copy_tex_sub_image_2d(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei)514     fn copy_tex_sub_image_2d(&self,
515                              target: GLenum,
516                              level: GLint,
517                              xoffset: GLint,
518                              yoffset: GLint,
519                              x: GLint,
520                              y: GLint,
521                              width: GLsizei,
522                              height: GLsizei) {
523         unsafe {
524             self.ffi_gl_.CopyTexSubImage2D(target,
525                                            level,
526                                            xoffset,
527                                            yoffset,
528                                            x,
529                                            y,
530                                            width,
531                                            height);
532         }
533     }
534 
copy_tex_sub_image_3d(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, zoffset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei)535     fn copy_tex_sub_image_3d(&self,
536                              target: GLenum,
537                              level: GLint,
538                              xoffset: GLint,
539                              yoffset: GLint,
540                              zoffset: GLint,
541                              x: GLint,
542                              y: GLint,
543                              width: GLsizei,
544                              height: GLsizei) {
545         unsafe {
546             self.ffi_gl_.CopyTexSubImage3D(target,
547                                            level,
548                                            xoffset,
549                                            yoffset,
550                                            zoffset,
551                                            x,
552                                            y,
553                                            width,
554                                            height);
555         }
556     }
557 
tex_sub_image_2d(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, format: GLenum, ty: GLenum, data: &[u8])558     fn tex_sub_image_2d(&self,
559                         target: GLenum,
560                         level: GLint,
561                         xoffset: GLint,
562                         yoffset: GLint,
563                         width: GLsizei,
564                         height: GLsizei,
565                         format: GLenum,
566                         ty: GLenum,
567                         data: &[u8]) {
568         unsafe {
569             self.ffi_gl_.TexSubImage2D(target, level, xoffset, yoffset, width, height, format, ty, data.as_ptr() as *const c_void);
570         }
571     }
572 
tex_sub_image_2d_pbo(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, format: GLenum, ty: GLenum, offset: usize)573     fn tex_sub_image_2d_pbo(&self,
574                             target: GLenum,
575                             level: GLint,
576                             xoffset: GLint,
577                             yoffset: GLint,
578                             width: GLsizei,
579                             height: GLsizei,
580                             format: GLenum,
581                             ty: GLenum,
582                             offset: usize) {
583         unsafe {
584             self.ffi_gl_.TexSubImage2D(target, level, xoffset, yoffset, width, height, format, ty, offset as *const c_void);
585         }
586     }
587 
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])588     fn tex_sub_image_3d(&self,
589                         target: GLenum,
590                         level: GLint,
591                         xoffset: GLint,
592                         yoffset: GLint,
593                         zoffset: GLint,
594                         width: GLsizei,
595                         height: GLsizei,
596                         depth: GLsizei,
597                         format: GLenum,
598                         ty: GLenum,
599                         data: &[u8]) {
600         unsafe {
601             self.ffi_gl_.TexSubImage3D(target,
602                                        level,
603                                        xoffset,
604                                        yoffset,
605                                        zoffset,
606                                        width,
607                                        height,
608                                        depth,
609                                        format,
610                                        ty,
611                                        data.as_ptr() as *const c_void);
612         }
613     }
614 
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)615     fn tex_sub_image_3d_pbo(&self,
616                             target: GLenum,
617                             level: GLint,
618                             xoffset: GLint,
619                             yoffset: GLint,
620                             zoffset: GLint,
621                             width: GLsizei,
622                             height: GLsizei,
623                             depth: GLsizei,
624                             format: GLenum,
625                             ty: GLenum,
626                             offset: usize) {
627         unsafe {
628             self.ffi_gl_.TexSubImage3D(target,
629                                        level,
630                                        xoffset,
631                                        yoffset,
632                                        zoffset,
633                                        width,
634                                        height,
635                                        depth,
636                                        format,
637                                        ty,
638                                        offset as *const c_void);
639         }
640     }
641 
tex_storage_2d(&self, target: GLenum, levels: GLint, internal_format: GLenum, width: GLsizei, height: GLsizei)642     fn tex_storage_2d(&self,
643                       target: GLenum,
644                       levels: GLint,
645                       internal_format: GLenum,
646                       width: GLsizei,
647                       height: GLsizei) {
648         unsafe {
649             self.ffi_gl_.TexStorage2D(target,
650                                       levels,
651                                       internal_format,
652                                       width,
653                                       height);
654         }
655     }
656 
tex_storage_3d(&self, target: GLenum, levels: GLint, internal_format: GLenum, width: GLsizei, height: GLsizei, depth: GLsizei)657     fn tex_storage_3d(&self,
658                       target: GLenum,
659                       levels: GLint,
660                       internal_format: GLenum,
661                       width: GLsizei,
662                       height: GLsizei,
663                       depth: GLsizei) {
664         unsafe {
665             self.ffi_gl_.TexStorage3D(target,
666                                       levels,
667                                       internal_format,
668                                       width,
669                                       height,
670                                       depth);
671         }
672     }
673 
674     #[allow(unused_variables)]
get_tex_image_into_buffer(&self, target: GLenum, level: GLint, format: GLenum, ty: GLenum, output: &mut [u8])675     fn get_tex_image_into_buffer(&self,
676                                  target: GLenum,
677                                  level: GLint,
678                                  format: GLenum,
679                                  ty: GLenum,
680                                  output: &mut [u8]) {
681         panic!("not supported");
682     }
683 
invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum])684     fn invalidate_framebuffer(&self,
685                               target: GLenum,
686                               attachments: &[GLenum]) {
687         unsafe {
688             self.ffi_gl_.InvalidateFramebuffer(
689                 target,
690                 attachments.len() as GLsizei,
691                 attachments.as_ptr(),
692             );
693         }
694     }
695 
invalidate_sub_framebuffer(&self, target: GLenum, attachments: &[GLenum], xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei)696     fn invalidate_sub_framebuffer(&self,
697                                   target: GLenum,
698                                   attachments: &[GLenum],
699                                   xoffset: GLint,
700                                   yoffset: GLint,
701                                   width: GLsizei,
702                                   height: GLsizei) {
703         unsafe {
704             self.ffi_gl_.InvalidateSubFramebuffer(
705                 target,
706                 attachments.len() as GLsizei,
707                 attachments.as_ptr(),
708                 xoffset,
709                 yoffset,
710                 width,
711                 height,
712             );
713         }
714     }
715 
716     #[inline]
get_integer_v(&self, name: GLenum, result: &mut [GLint])717     unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]) {
718         assert!(!result.is_empty());
719         self.ffi_gl_.GetIntegerv(name, result.as_mut_ptr());
720     }
721 
722     #[inline]
get_integer_64v(&self, name: GLenum, result: &mut [GLint64])723     unsafe fn get_integer_64v(&self, name: GLenum, result: &mut [GLint64]) {
724         assert!(!result.is_empty());
725         self.ffi_gl_.GetInteger64v(name, result.as_mut_ptr());
726     }
727 
728     #[inline]
get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint])729     unsafe fn get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint]) {
730         assert!(!result.is_empty());
731         self.ffi_gl_.GetIntegeri_v(name, index, result.as_mut_ptr());
732     }
733 
734     #[inline]
get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64])735     unsafe fn get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64]) {
736         assert!(!result.is_empty());
737         self.ffi_gl_.GetInteger64i_v(name, index, result.as_mut_ptr());
738     }
739 
740     #[inline]
get_boolean_v(&self, name: GLenum, result: &mut [GLboolean])741     unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]) {
742         assert!(!result.is_empty());
743         self.ffi_gl_.GetBooleanv(name, result.as_mut_ptr());
744     }
745 
746     #[inline]
get_float_v(&self, name: GLenum, result: &mut [GLfloat])747     unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]) {
748         assert!(!result.is_empty());
749         self.ffi_gl_.GetFloatv(name, result.as_mut_ptr());
750     }
751 
get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint752     fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
753         let mut result: GLint = 0;
754         unsafe {
755             self.ffi_gl_.GetRenderbufferParameteriv(target, pname, &mut result);
756         }
757         result
758     }
759 
get_framebuffer_attachment_parameter_iv(&self, target: GLenum, attachment: GLenum, pname: GLenum) -> GLint760     fn get_framebuffer_attachment_parameter_iv(&self, target: GLenum, attachment: GLenum, pname: GLenum) -> GLint {
761         let mut result: GLint = 0;
762         unsafe {
763             self.ffi_gl_.GetFramebufferAttachmentParameteriv(target, attachment, pname, &mut result);
764         }
765         result
766     }
767 
get_tex_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint768     fn get_tex_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
769         let mut result: GLint = 0;
770         unsafe {
771             self.ffi_gl_.GetTexParameteriv(target, pname, &mut result);
772         }
773         result
774     }
775 
get_tex_parameter_fv(&self, target: GLenum, pname: GLenum) -> GLfloat776     fn get_tex_parameter_fv(&self, target: GLenum, pname: GLenum) -> GLfloat {
777         let mut result: GLfloat = 0.0;
778         unsafe {
779             self.ffi_gl_.GetTexParameterfv(target, pname, &mut result);
780         }
781         result
782     }
783 
tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint)784     fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) {
785         unsafe {
786             self.ffi_gl_.TexParameteri(target, pname, param);
787         }
788     }
789 
tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat)790     fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) {
791         unsafe {
792             self.ffi_gl_.TexParameterf(target, pname, param);
793         }
794     }
795 
framebuffer_texture_2d(&self, target: GLenum, attachment: GLenum, textarget: GLenum, texture: GLuint, level: GLint)796     fn framebuffer_texture_2d(&self,
797                               target: GLenum,
798                               attachment: GLenum,
799                               textarget: GLenum,
800                               texture: GLuint,
801                               level: GLint) {
802         unsafe {
803             self.ffi_gl_.FramebufferTexture2D(target, attachment, textarget, texture, level);
804         }
805     }
806 
framebuffer_texture_layer(&self, target: GLenum, attachment: GLenum, texture: GLuint, level: GLint, layer: GLint)807     fn framebuffer_texture_layer(&self,
808                                  target: GLenum,
809                                  attachment: GLenum,
810                                  texture: GLuint,
811                                  level: GLint,
812                                  layer: GLint) {
813         unsafe {
814             self.ffi_gl_.FramebufferTextureLayer(target, attachment, texture, level, layer);
815         }
816     }
817 
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)818     fn blit_framebuffer(&self,
819                         src_x0: GLint,
820                         src_y0: GLint,
821                         src_x1: GLint,
822                         src_y1: GLint,
823                         dst_x0: GLint,
824                         dst_y0: GLint,
825                         dst_x1: GLint,
826                         dst_y1: GLint,
827                         mask: GLbitfield,
828                         filter: GLenum) {
829         unsafe {
830             self.ffi_gl_.BlitFramebuffer(src_x0,
831                                          src_y0,
832                                          src_x1,
833                                          src_y1,
834                                          dst_x0,
835                                          dst_y0,
836                                          dst_x1,
837                                          dst_y1,
838                                          mask,
839                                          filter);
840         }
841     }
842 
vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat)843     fn vertex_attrib_4f(&self,
844                         index: GLuint,
845                         x: GLfloat,
846                         y: GLfloat,
847                         z: GLfloat,
848                         w: GLfloat) {
849         unsafe {
850             self.ffi_gl_.VertexAttrib4f(index, x, y, z, w)
851         }
852     }
853 
vertex_attrib_pointer_f32(&self, index: GLuint, size: GLint, normalized: bool, stride: GLsizei, offset: GLuint)854     fn vertex_attrib_pointer_f32(&self,
855                                  index: GLuint,
856                                  size: GLint,
857                                  normalized: bool,
858                                  stride: GLsizei,
859                                  offset: GLuint) {
860         unsafe {
861             self.ffi_gl_.VertexAttribPointer(index,
862                                              size,
863                                              ffi::FLOAT,
864                                              normalized as GLboolean,
865                                              stride,
866                                              offset as *const GLvoid)
867         }
868     }
869 
vertex_attrib_pointer(&self, index: GLuint, size: GLint, type_: GLenum, normalized: bool, stride: GLsizei, offset: GLuint)870     fn vertex_attrib_pointer(&self,
871                                  index: GLuint,
872                                  size: GLint,
873                                  type_: GLenum,
874                                  normalized: bool,
875                                  stride: GLsizei,
876                                  offset: GLuint) {
877         unsafe {
878             self.ffi_gl_.VertexAttribPointer(index,
879                                              size,
880                                              type_,
881                                              normalized as GLboolean,
882                                              stride,
883                                              offset as *const GLvoid)
884         }
885     }
886 
vertex_attrib_i_pointer(&self, index: GLuint, size: GLint, type_: GLenum, stride: GLsizei, offset: GLuint)887     fn vertex_attrib_i_pointer(&self,
888                                index: GLuint,
889                                size: GLint,
890                                type_: GLenum,
891                                stride: GLsizei,
892                                offset: GLuint) {
893         unsafe {
894             self.ffi_gl_.VertexAttribIPointer(index,
895                                               size,
896                                               type_,
897                                               stride,
898                                               offset as *const GLvoid)
899         }
900     }
901 
vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint)902     fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) {
903         unsafe {
904             self.ffi_gl_.VertexAttribDivisor(index, divisor)
905         }
906     }
907 
viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei)908     fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
909         unsafe {
910             self.ffi_gl_.Viewport(x, y, width, height);
911         }
912     }
913 
scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei)914     fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
915         unsafe {
916             self.ffi_gl_.Scissor(x, y, width, height);
917         }
918     }
919 
line_width(&self, width: GLfloat)920     fn line_width(&self, width: GLfloat) {
921         unsafe {
922             self.ffi_gl_.LineWidth(width);
923         }
924     }
925 
use_program(&self, program: GLuint)926     fn use_program(&self, program: GLuint) {
927         unsafe {
928             self.ffi_gl_.UseProgram(program);
929         }
930     }
931 
validate_program(&self, program: GLuint)932     fn validate_program(&self, program: GLuint) {
933         unsafe {
934             self.ffi_gl_.ValidateProgram(program);
935         }
936     }
937 
draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei)938     fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) {
939         unsafe {
940             return self.ffi_gl_.DrawArrays(mode, first, count);
941         }
942     }
943 
draw_arrays_instanced(&self, mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei)944     fn draw_arrays_instanced(&self, mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei) {
945         unsafe {
946             return self.ffi_gl_.DrawArraysInstanced(mode, first, count, primcount);
947         }
948     }
949 
draw_elements(&self, mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint)950     fn draw_elements(&self, mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint) {
951         unsafe {
952             return self.ffi_gl_.DrawElements(mode, count, element_type, indices_offset as *const c_void)
953         }
954     }
955 
draw_elements_instanced(&self, mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint, primcount: GLsizei)956     fn draw_elements_instanced(&self,
957                                    mode: GLenum,
958                                    count: GLsizei,
959                                    element_type: GLenum,
960                                    indices_offset: GLuint,
961                                    primcount: GLsizei) {
962         unsafe {
963             return self.ffi_gl_.DrawElementsInstanced(mode,
964                                                       count,
965                                                       element_type,
966                                                       indices_offset as *const c_void,
967                                                       primcount)
968         }
969     }
970 
blend_color(&self, r: f32, g: f32, b: f32, a: f32)971     fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) {
972         unsafe {
973             self.ffi_gl_.BlendColor(r, g, b, a);
974         }
975     }
976 
blend_func(&self, sfactor: GLenum, dfactor: GLenum)977     fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) {
978         unsafe {
979             self.ffi_gl_.BlendFunc(sfactor, dfactor);
980         }
981     }
982 
blend_func_separate(&self, src_rgb: GLenum, dest_rgb: GLenum, src_alpha: GLenum, dest_alpha: GLenum)983     fn blend_func_separate(&self, src_rgb: GLenum, dest_rgb: GLenum, src_alpha: GLenum, dest_alpha: GLenum) {
984         unsafe {
985             self.ffi_gl_.BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha);
986         }
987     }
988 
blend_equation(&self, mode: GLenum)989     fn blend_equation(&self, mode: GLenum) {
990         unsafe {
991             self.ffi_gl_.BlendEquation(mode);
992         }
993     }
994 
blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum)995     fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) {
996         unsafe {
997             self.ffi_gl_.BlendEquationSeparate(mode_rgb, mode_alpha);
998         }
999     }
1000 
color_mask(&self, r: bool, g: bool, b: bool, a: bool)1001     fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
1002         unsafe {
1003             self.ffi_gl_.ColorMask(r as GLboolean, g as GLboolean, b as GLboolean, a as GLboolean);
1004         }
1005     }
1006 
cull_face(&self, mode: GLenum)1007     fn cull_face(&self, mode: GLenum) {
1008         unsafe {
1009             self.ffi_gl_.CullFace(mode);
1010         }
1011     }
1012 
front_face(&self, mode: GLenum)1013     fn front_face(&self, mode: GLenum) {
1014         unsafe {
1015             self.ffi_gl_.FrontFace(mode);
1016         }
1017     }
1018 
enable(&self, cap: GLenum)1019     fn enable(&self, cap: GLenum) {
1020         unsafe {
1021             self.ffi_gl_.Enable(cap);
1022         }
1023     }
1024 
disable(&self, cap: GLenum)1025     fn disable(&self, cap: GLenum) {
1026         unsafe {
1027             self.ffi_gl_.Disable(cap);
1028         }
1029     }
1030 
hint(&self, param_name: GLenum, param_val: GLenum)1031     fn hint(&self, param_name: GLenum, param_val: GLenum) {
1032         unsafe {
1033             self.ffi_gl_.Hint(param_name, param_val);
1034         }
1035     }
1036 
is_enabled(&self, cap: GLenum) -> GLboolean1037     fn is_enabled(&self, cap: GLenum) -> GLboolean {
1038         unsafe {
1039             self.ffi_gl_.IsEnabled(cap)
1040         }
1041     }
1042 
is_shader(&self, shader: GLuint) -> GLboolean1043     fn is_shader(&self, shader: GLuint) -> GLboolean {
1044         unsafe {
1045             self.ffi_gl_.IsShader(shader)
1046         }
1047     }
1048 
is_texture(&self, texture: GLenum) -> GLboolean1049     fn is_texture(&self, texture: GLenum) -> GLboolean {
1050         unsafe {
1051             self.ffi_gl_.IsTexture(texture)
1052         }
1053     }
1054 
is_framebuffer(&self, framebuffer: GLenum) -> GLboolean1055     fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean {
1056         unsafe {
1057             self.ffi_gl_.IsFramebuffer(framebuffer)
1058         }
1059     }
1060 
is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean1061     fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean {
1062         unsafe {
1063             self.ffi_gl_.IsRenderbuffer(renderbuffer)
1064         }
1065     }
1066 
check_frame_buffer_status(&self, target: GLenum) -> GLenum1067     fn check_frame_buffer_status(&self, target: GLenum) -> GLenum {
1068         unsafe {
1069             self.ffi_gl_.CheckFramebufferStatus(target)
1070         }
1071     }
1072 
enable_vertex_attrib_array(&self, index: GLuint)1073     fn enable_vertex_attrib_array(&self, index: GLuint) {
1074         unsafe {
1075             self.ffi_gl_.EnableVertexAttribArray(index);
1076         }
1077     }
1078 
disable_vertex_attrib_array(&self, index: GLuint)1079     fn disable_vertex_attrib_array(&self, index: GLuint) {
1080         unsafe {
1081             self.ffi_gl_.DisableVertexAttribArray(index);
1082         }
1083     }
1084 
uniform_1f(&self, location: GLint, v0: GLfloat)1085     fn uniform_1f(&self, location: GLint, v0: GLfloat) {
1086         unsafe {
1087             self.ffi_gl_.Uniform1f(location, v0);
1088         }
1089     }
1090 
uniform_1fv(&self, location: GLint, values: &[f32])1091     fn uniform_1fv(&self, location: GLint, values: &[f32]) {
1092         unsafe {
1093             self.ffi_gl_.Uniform1fv(location,
1094                                     values.len() as GLsizei,
1095                                     values.as_ptr());
1096         }
1097     }
1098 
uniform_1i(&self, location: GLint, v0: GLint)1099     fn uniform_1i(&self, location: GLint, v0: GLint) {
1100         unsafe {
1101             self.ffi_gl_.Uniform1i(location, v0);
1102         }
1103     }
1104 
uniform_1iv(&self, location: GLint, values: &[i32])1105     fn uniform_1iv(&self, location: GLint, values: &[i32]) {
1106         unsafe {
1107             self.ffi_gl_.Uniform1iv(location,
1108                                     values.len() as GLsizei,
1109                                     values.as_ptr());
1110         }
1111     }
1112 
1113     #[allow(unused_variables)]
uniform_1ui(&self, location: GLint, v0: GLuint)1114     fn uniform_1ui(&self, location: GLint, v0: GLuint) {
1115         panic!("not supported")
1116     }
1117 
uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat)1118     fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) {
1119         unsafe {
1120             self.ffi_gl_.Uniform2f(location, v0, v1);
1121         }
1122     }
1123 
uniform_2fv(&self, location: GLint, values: &[f32])1124     fn uniform_2fv(&self, location: GLint, values: &[f32]) {
1125         unsafe {
1126             self.ffi_gl_.Uniform2fv(location,
1127                                     (values.len() / 2) as GLsizei,
1128                                     values.as_ptr());
1129         }
1130     }
1131 
uniform_2i(&self, location: GLint, v0: GLint, v1: GLint)1132     fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) {
1133         unsafe {
1134             self.ffi_gl_.Uniform2i(location, v0, v1);
1135         }
1136     }
1137 
uniform_2iv(&self, location: GLint, values: &[i32])1138     fn uniform_2iv(&self, location: GLint, values: &[i32]) {
1139         unsafe {
1140             self.ffi_gl_.Uniform2iv(location,
1141                                     (values.len() / 2) as GLsizei,
1142                                     values.as_ptr());
1143         }
1144     }
1145 
1146     #[allow(unused_variables)]
uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint)1147     fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) {
1148         panic!("not supported")
1149     }
1150 
uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat)1151     fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
1152         unsafe {
1153             self.ffi_gl_.Uniform3f(location, v0, v1, v2);
1154         }
1155     }
1156 
uniform_3fv(&self, location: GLint, values: &[f32])1157     fn uniform_3fv(&self, location: GLint, values: &[f32]) {
1158         unsafe {
1159             self.ffi_gl_.Uniform3fv(location,
1160                                     (values.len() / 3) as GLsizei,
1161                                     values.as_ptr());
1162         }
1163     }
1164 
uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint)1165     fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) {
1166         unsafe {
1167             self.ffi_gl_.Uniform3i(location, v0, v1, v2);
1168         }
1169     }
1170 
uniform_3iv(&self, location: GLint, values: &[i32])1171     fn uniform_3iv(&self, location: GLint, values: &[i32]) {
1172         unsafe {
1173             self.ffi_gl_.Uniform3iv(location,
1174                                     (values.len() / 3) as GLsizei,
1175                                     values.as_ptr());
1176         }
1177     }
1178 
1179     #[allow(unused_variables)]
uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint)1180     fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
1181         panic!("not supported")
1182     }
1183 
uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat)1184     fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
1185         unsafe {
1186             self.ffi_gl_.Uniform4f(location, x, y, z, w);
1187         }
1188     }
1189 
uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint)1190     fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) {
1191         unsafe {
1192             self.ffi_gl_.Uniform4i(location, x, y, z, w);
1193         }
1194     }
1195 
uniform_4iv(&self, location: GLint, values: &[i32])1196     fn uniform_4iv(&self, location: GLint, values: &[i32]) {
1197         unsafe {
1198             self.ffi_gl_.Uniform4iv(location,
1199                                     (values.len() / 4) as GLsizei,
1200                                     values.as_ptr());
1201         }
1202     }
1203 
1204     #[allow(unused_variables)]
uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint)1205     fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
1206         panic!("not supported")
1207     }
1208 
uniform_4fv(&self, location: GLint, values: &[f32])1209     fn uniform_4fv(&self, location: GLint, values: &[f32]) {
1210         unsafe {
1211             self.ffi_gl_.Uniform4fv(location,
1212                                     (values.len() / 4) as GLsizei,
1213                                     values.as_ptr());
1214         }
1215     }
1216 
uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32])1217     fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1218         unsafe {
1219             self.ffi_gl_.UniformMatrix2fv(location,
1220                                           (value.len() / 4) as GLsizei,
1221                                           transpose as GLboolean,
1222                                           value.as_ptr());
1223         }
1224     }
1225 
uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32])1226     fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1227         unsafe {
1228             self.ffi_gl_.UniformMatrix3fv(location,
1229                                           (value.len() / 9) as GLsizei,
1230                                           transpose as GLboolean,
1231                                           value.as_ptr());
1232         }
1233     }
1234 
uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32])1235     fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1236         unsafe {
1237             self.ffi_gl_.UniformMatrix4fv(location,
1238                                           (value.len() / 16) as GLsizei,
1239                                           transpose as GLboolean,
1240                                           value.as_ptr());
1241         }
1242     }
1243 
depth_mask(&self, flag: bool)1244     fn depth_mask(&self, flag: bool) {
1245         unsafe {
1246             self.ffi_gl_.DepthMask(flag as GLboolean);
1247         }
1248     }
1249 
depth_range(&self, near: f64, far: f64)1250     fn depth_range(&self, near: f64, far: f64) {
1251         unsafe {
1252             self.ffi_gl_.DepthRangef(near as GLclampf, far as GLclampf);
1253         }
1254     }
1255 
get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String)1256     fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1257         let mut buf_size = [0];
1258         unsafe {
1259             self.get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH, &mut buf_size);
1260         }
1261         let mut name = vec![0u8; buf_size[0] as usize];
1262         let mut length = 0 as GLsizei;
1263         let mut size = 0 as i32;
1264         let mut type_ = 0 as u32;
1265         unsafe {
1266             self.ffi_gl_.GetActiveAttrib(
1267                 program,
1268                 index,
1269                 buf_size[0],
1270                 &mut length,
1271                 &mut size,
1272                 &mut type_,
1273                 name.as_mut_ptr() as *mut GLchar,
1274             );
1275         }
1276         name.truncate(if length > 0 {length as usize} else {0});
1277         (size, type_, String::from_utf8(name).unwrap())
1278     }
1279 
get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String)1280     fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1281         let mut buf_size = [0];
1282         unsafe {
1283             self.get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH, &mut buf_size);
1284         }
1285         let mut name = vec![0 as u8; buf_size[0] as usize];
1286         let mut length: GLsizei = 0;
1287         let mut size: i32 = 0;
1288         let mut type_: u32 = 0;
1289 
1290         unsafe {
1291             self.ffi_gl_.GetActiveUniform(
1292                 program,
1293                 index,
1294                 buf_size[0],
1295                 &mut length,
1296                 &mut size,
1297                 &mut type_,
1298                 name.as_mut_ptr() as *mut GLchar,
1299             );
1300         }
1301 
1302         name.truncate(if length > 0 { length as usize } else { 0 });
1303 
1304         (size, type_, String::from_utf8(name).unwrap())
1305     }
1306 
get_active_uniforms_iv(&self, program: GLuint, indices: Vec<GLuint>, pname: GLenum) -> Vec<GLint>1307     fn get_active_uniforms_iv(&self, program: GLuint, indices: Vec<GLuint>, pname: GLenum) -> Vec<GLint> {
1308         let mut result = Vec::with_capacity(indices.len());
1309         unsafe {
1310             result.set_len(indices.len());
1311             self.ffi_gl_.GetActiveUniformsiv(program,
1312                                              indices.len() as GLsizei,
1313                                              indices.as_ptr(),
1314                                              pname,
1315                                              result.as_mut_ptr());
1316         }
1317         result
1318     }
1319 
get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint1320     fn get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint {
1321         let mut result = 0 as GLint;
1322         unsafe {
1323             self.ffi_gl_.GetActiveUniformBlockiv(program, index, pname, &mut result);
1324         }
1325         result
1326     }
1327 
get_active_uniform_block_iv(&self, program: GLuint, index: GLuint, pname: GLenum) -> Vec<GLint>1328     fn get_active_uniform_block_iv(&self, program: GLuint, index: GLuint, pname: GLenum) -> Vec<GLint> {
1329         let count = self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_ACTIVE_UNIFORMS);
1330         let mut result = Vec::with_capacity(count as usize);
1331         unsafe {
1332             result.set_len(count as usize);
1333             self.ffi_gl_.GetActiveUniformBlockiv(program, index, pname, result.as_mut_ptr());
1334         }
1335         result
1336     }
1337 
get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String1338     fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String {
1339         let buf_size = self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_NAME_LENGTH);
1340         let mut name = vec![0 as u8; buf_size as usize];
1341         let mut length: GLsizei = 0;
1342         unsafe {
1343             self.ffi_gl_.GetActiveUniformBlockName(program,
1344                                                    index,
1345                                                    buf_size,
1346                                                    &mut length,
1347                                                    name.as_mut_ptr() as *mut GLchar);
1348         }
1349         name.truncate(if length > 0 { length as usize } else { 0 });
1350 
1351         String::from_utf8(name).unwrap()
1352     }
1353 
get_attrib_location(&self, program: GLuint, name: &str) -> c_int1354     fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int {
1355         let name = CString::new(name).unwrap();
1356         unsafe {
1357             self.ffi_gl_.GetAttribLocation(program, name.as_ptr())
1358         }
1359     }
1360 
1361     #[allow(unused_variables)]
get_frag_data_location(&self, program: GLuint, name: &str) -> c_int1362     fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int {
1363         panic!("not supported")
1364     }
1365 
get_uniform_location(&self, program: GLuint, name: &str) -> c_int1366     fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int {
1367         let name = CString::new(name).unwrap();
1368         unsafe {
1369             self.ffi_gl_.GetUniformLocation(program, name.as_ptr())
1370         }
1371     }
1372 
get_program_info_log(&self, program: GLuint) -> String1373     fn get_program_info_log(&self, program: GLuint) -> String {
1374         let mut max_len = [0];
1375         unsafe {
1376             self.get_program_iv(program, ffi::INFO_LOG_LENGTH, &mut max_len);
1377         }
1378         let mut result = vec![0u8; max_len[0] as usize];
1379         let mut result_len = 0 as GLsizei;
1380         unsafe {
1381             self.ffi_gl_.GetProgramInfoLog(
1382                 program,
1383                 max_len[0] as GLsizei,
1384                 &mut result_len,
1385                 result.as_mut_ptr() as *mut GLchar,
1386             );
1387         }
1388         result.truncate(if result_len > 0 {result_len as usize} else {0});
1389         String::from_utf8(result).unwrap()
1390     }
1391 
1392     #[inline]
get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint])1393     unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]) {
1394         assert!(!result.is_empty());
1395         self.ffi_gl_.GetProgramiv(program, pname, result.as_mut_ptr());
1396     }
1397 
get_program_binary(&self, program: GLuint) -> (Vec<u8>, GLenum)1398     fn get_program_binary(&self, program: GLuint) -> (Vec<u8>, GLenum) {
1399         let mut len = [0];
1400         unsafe {
1401             self.get_program_iv(program, ffi::PROGRAM_BINARY_LENGTH, &mut len);
1402         }
1403         if len[0] <= 0 {
1404             return (Vec::new(), NONE);
1405         }
1406         let mut binary: Vec<u8> = Vec::with_capacity(len[0] as usize);
1407         let mut format = NONE;
1408         let mut out_len = 0;
1409         unsafe {
1410             binary.set_len(len[0] as usize);
1411             self.ffi_gl_.GetProgramBinary(
1412                 program,
1413                 len[0],
1414                 &mut out_len as *mut GLsizei,
1415                 &mut format,
1416                 binary.as_mut_ptr() as *mut c_void,
1417             );
1418         }
1419         if len[0] != out_len {
1420             return (Vec::new(), NONE);
1421         }
1422 
1423         (binary, format)
1424     }
1425 
program_binary(&self, program: GLuint, format: GLenum, binary: &[u8])1426     fn program_binary(&self, program: GLuint, format: GLenum, binary: &[u8]) {
1427         unsafe {
1428             self.ffi_gl_.ProgramBinary(program,
1429                                        format,
1430                                        binary.as_ptr() as *const c_void,
1431                                        binary.len() as GLsizei);
1432         }
1433     }
1434 
program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint)1435     fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint) {
1436         unsafe {
1437             self.ffi_gl_.ProgramParameteri(program, pname, value);
1438         }
1439     }
1440 
1441     #[inline]
get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint])1442     unsafe fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint]) {
1443         assert!(!result.is_empty());
1444         self.ffi_gl_.GetVertexAttribiv(index, pname, result.as_mut_ptr());
1445     }
1446 
1447     #[inline]
get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat])1448     unsafe fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat]) {
1449         assert!(!result.is_empty());
1450         self.ffi_gl_.GetVertexAttribfv(index, pname, result.as_mut_ptr());
1451     }
1452 
get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr1453     fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr {
1454         let mut result = 0 as *mut GLvoid;
1455         unsafe {
1456             self.ffi_gl_.GetVertexAttribPointerv(index, pname, &mut result)
1457         }
1458         result as GLsizeiptr
1459     }
1460 
get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint1461     fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint {
1462         let mut result = 0 as GLint;
1463         unsafe {
1464             self.ffi_gl_.GetBufferParameteriv(target, pname, &mut result);
1465         }
1466         result
1467     }
1468 
get_shader_info_log(&self, shader: GLuint) -> String1469     fn get_shader_info_log(&self, shader: GLuint) -> String {
1470         let mut max_len = [0];
1471         unsafe {
1472             self.get_shader_iv(shader, ffi::INFO_LOG_LENGTH, &mut max_len);
1473         }
1474         let mut result = vec![0u8; max_len[0] as usize];
1475         let mut result_len = 0 as GLsizei;
1476         unsafe {
1477             self.ffi_gl_.GetShaderInfoLog(
1478                 shader,
1479                 max_len[0] as GLsizei,
1480                 &mut result_len,
1481                 result.as_mut_ptr() as *mut GLchar,
1482             );
1483         }
1484         result.truncate(if result_len > 0 {result_len as usize} else {0});
1485         String::from_utf8(result).unwrap()
1486     }
1487 
get_string(&self, which: GLenum) -> String1488     fn get_string(&self, which: GLenum) -> String {
1489         unsafe {
1490             let llstr = self.ffi_gl_.GetString(which);
1491             if !llstr.is_null() {
1492                 return str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()).to_string();
1493             } else {
1494                 return "".to_string();
1495             }
1496         }
1497     }
1498 
get_string_i(&self, which: GLenum, index: GLuint) -> String1499     fn get_string_i(&self, which: GLenum, index: GLuint) -> String {
1500         unsafe {
1501             let llstr = self.ffi_gl_.GetStringi(which, index);
1502             if !llstr.is_null() {
1503                 str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()).to_string()
1504             } else {
1505                 "".to_string()
1506             }
1507         }
1508     }
1509 
get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint])1510     unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]) {
1511         assert!(!result.is_empty());
1512         self.ffi_gl_.GetShaderiv(shader, pname, result.as_mut_ptr());
1513     }
1514 
get_shader_precision_format(&self, shader_type: GLuint, precision_type: GLuint) -> (GLint, GLint, GLint)1515     fn get_shader_precision_format(&self,
1516                                    shader_type: GLuint,
1517                                    precision_type: GLuint)
1518                                    -> (GLint, GLint, GLint) {
1519         let (mut range, mut precision) = match precision_type {
1520             // These values are for a 32-bit twos-complement integer format.
1521             ffi::LOW_INT |
1522             ffi::MEDIUM_INT |
1523             ffi::HIGH_INT => ([31, 30], 0),
1524 
1525             // These values are for an IEEE single-precision floating-point format.
1526             ffi::LOW_FLOAT |
1527             ffi::MEDIUM_FLOAT |
1528             ffi::HIGH_FLOAT => ([127, 127], 23),
1529 
1530             _ => unreachable!("invalid precision"),
1531         };
1532         // This function is sometimes defined even though it's really just
1533         // a stub, so we need to set range and precision as if it weren't
1534         // defined before calling it. Suppress any error that might occur.
1535         unsafe {
1536             self.ffi_gl_.GetShaderPrecisionFormat(shader_type,
1537                                                   precision_type,
1538                                                   range.as_mut_ptr(),
1539                                                   &mut precision);
1540             let _ = self.ffi_gl_.GetError();
1541         }
1542 
1543         (range[0], range[1], precision)
1544     }
1545 
compile_shader(&self, shader: GLuint)1546     fn compile_shader(&self, shader: GLuint) {
1547         unsafe {
1548             self.ffi_gl_.CompileShader(shader);
1549         }
1550     }
1551 
create_program(&self) -> GLuint1552     fn create_program(&self) -> GLuint {
1553         unsafe {
1554             return self.ffi_gl_.CreateProgram();
1555         }
1556     }
1557 
delete_program(&self, program: GLuint)1558     fn delete_program(&self, program: GLuint) {
1559         unsafe {
1560             self.ffi_gl_.DeleteProgram(program);
1561         }
1562     }
1563 
create_shader(&self, shader_type: GLenum) -> GLuint1564     fn create_shader(&self, shader_type: GLenum) -> GLuint {
1565         unsafe {
1566             return self.ffi_gl_.CreateShader(shader_type);
1567         }
1568     }
1569 
delete_shader(&self, shader: GLuint)1570     fn delete_shader(&self, shader: GLuint) {
1571         unsafe {
1572             self.ffi_gl_.DeleteShader(shader);
1573         }
1574     }
1575 
detach_shader(&self, program: GLuint, shader: GLuint)1576     fn detach_shader(&self, program: GLuint, shader: GLuint) {
1577         unsafe {
1578             self.ffi_gl_.DetachShader(program, shader);
1579         }
1580     }
1581 
link_program(&self, program: GLuint)1582     fn link_program(&self, program: GLuint) {
1583         unsafe {
1584             return self.ffi_gl_.LinkProgram(program);
1585         }
1586     }
1587 
clear_color(&self, r: f32, g: f32, b: f32, a: f32)1588     fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) {
1589         unsafe {
1590             self.ffi_gl_.ClearColor(r, g, b, a);
1591         }
1592     }
1593 
clear(&self, buffer_mask: GLbitfield)1594     fn clear(&self, buffer_mask: GLbitfield) {
1595         unsafe {
1596             self.ffi_gl_.Clear(buffer_mask);
1597         }
1598     }
1599 
clear_depth(&self, depth: f64)1600     fn clear_depth(&self, depth: f64) {
1601         unsafe {
1602             self.ffi_gl_.ClearDepthf(depth as GLclampf);
1603         }
1604     }
1605 
clear_stencil(&self, s: GLint)1606     fn clear_stencil(&self, s: GLint) {
1607         unsafe {
1608             self.ffi_gl_.ClearStencil(s);
1609         }
1610     }
1611 
flush(&self)1612     fn flush(&self) {
1613         unsafe {
1614             self.ffi_gl_.Flush();
1615         }
1616     }
1617 
finish(&self)1618     fn finish(&self) {
1619         unsafe {
1620             self.ffi_gl_.Finish();
1621         }
1622     }
1623 
get_error(&self) -> GLenum1624     fn get_error(&self) -> GLenum {
1625         unsafe {
1626             self.ffi_gl_.GetError()
1627         }
1628     }
1629 
stencil_mask(&self, mask: GLuint)1630     fn stencil_mask(&self, mask: GLuint) {
1631         unsafe {
1632             self.ffi_gl_.StencilMask(mask)
1633         }
1634     }
1635 
stencil_mask_separate(&self, face: GLenum, mask: GLuint)1636     fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) {
1637         unsafe {
1638             self.ffi_gl_.StencilMaskSeparate(face, mask)
1639         }
1640     }
1641 
stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint)1642     fn stencil_func(&self,
1643                     func: GLenum,
1644                     ref_: GLint,
1645                     mask: GLuint) {
1646         unsafe {
1647             self.ffi_gl_.StencilFunc(func, ref_, mask)
1648         }
1649     }
1650 
stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint)1651     fn stencil_func_separate(&self,
1652                              face: GLenum,
1653                              func: GLenum,
1654                              ref_: GLint,
1655                              mask: GLuint) {
1656         unsafe {
1657             self.ffi_gl_.StencilFuncSeparate(face, func, ref_, mask)
1658         }
1659     }
1660 
stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum)1661     fn stencil_op(&self,
1662                   sfail: GLenum,
1663                   dpfail: GLenum,
1664                   dppass: GLenum) {
1665         unsafe {
1666             self.ffi_gl_.StencilOp(sfail, dpfail, dppass)
1667         }
1668     }
1669 
stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum)1670     fn stencil_op_separate(&self,
1671                            face: GLenum,
1672                            sfail: GLenum,
1673                            dpfail: GLenum,
1674                            dppass: GLenum) {
1675         unsafe {
1676             self.ffi_gl_.StencilOpSeparate(face, sfail, dpfail, dppass)
1677         }
1678     }
1679 
egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES)1680     fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
1681         unsafe {
1682             self.ffi_gl_.EGLImageTargetTexture2DOES(target, image);
1683         }
1684     }
1685 
generate_mipmap(&self, target: GLenum)1686     fn generate_mipmap(&self, target: GLenum) {
1687         unsafe {
1688             self.ffi_gl_.GenerateMipmap(target)
1689         }
1690     }
1691 
insert_event_marker_ext(&self, message: &str)1692     fn insert_event_marker_ext(&self, message: &str) {
1693         if self.ffi_gl_.InsertEventMarkerEXT.is_loaded() {
1694             unsafe {
1695                 self.ffi_gl_.InsertEventMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
1696             }
1697         }
1698     }
1699 
push_group_marker_ext(&self, message: &str)1700     fn push_group_marker_ext(&self, message: &str) {
1701         if self.ffi_gl_.PushGroupMarkerEXT.is_loaded() {
1702             unsafe {
1703                 self.ffi_gl_.PushGroupMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
1704             }
1705         }
1706     }
1707 
pop_group_marker_ext(&self)1708     fn pop_group_marker_ext(&self) {
1709         if self.ffi_gl_.PopGroupMarkerEXT.is_loaded() {
1710             unsafe {
1711                 self.ffi_gl_.PopGroupMarkerEXT();
1712             }
1713         }
1714     }
1715 
fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync1716     fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync {
1717         unsafe {
1718            self.ffi_gl_.FenceSync(condition, flags) as *const _
1719         }
1720     }
1721 
client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64)1722     fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) {
1723         unsafe {
1724             self.ffi_gl_.ClientWaitSync(sync as *const _, flags, timeout);
1725         }
1726     }
1727 
wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64)1728     fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) {
1729         unsafe {
1730             self.ffi_gl_.WaitSync(sync as *const _, flags, timeout);
1731         }
1732     }
1733 
delete_sync(&self, sync: GLsync)1734     fn delete_sync(&self, sync: GLsync) {
1735         unsafe {
1736             self.ffi_gl_.DeleteSync(sync as *const _);
1737         }
1738     }
1739 
texture_range_apple(&self, _target: GLenum, _data: &[u8])1740     fn texture_range_apple(&self, _target: GLenum, _data: &[u8]) {
1741         panic!("not supported")
1742     }
1743 
gen_fences_apple(&self, _n: GLsizei) -> Vec<GLuint>1744     fn gen_fences_apple(&self, _n: GLsizei) -> Vec<GLuint> {
1745         panic!("not supported")
1746     }
1747 
delete_fences_apple(&self, _fences: &[GLuint])1748     fn delete_fences_apple(&self, _fences: &[GLuint]) {
1749         panic!("not supported")
1750     }
1751 
set_fence_apple(&self, _fence: GLuint)1752     fn set_fence_apple(&self, _fence: GLuint) {
1753         panic!("not supported")
1754     }
1755 
finish_fence_apple(&self, _fence: GLuint)1756     fn finish_fence_apple(&self, _fence: GLuint) {
1757         panic!("not supported")
1758     }
1759 
test_fence_apple(&self, _fence: GLuint)1760     fn test_fence_apple(&self, _fence: GLuint) {
1761         panic!("not supported")
1762     }
1763 
1764     // GL_ARB_blend_func_extended
bind_frag_data_location_indexed( &self, _program: GLuint, _color_number: GLuint, _index: GLuint, _name: &str, )1765     fn bind_frag_data_location_indexed(
1766         &self,
1767         _program: GLuint,
1768         _color_number: GLuint,
1769         _index: GLuint,
1770         _name: &str,
1771     ) {
1772         panic!("not supported");
1773     }
1774 
get_frag_data_index( &self, _program: GLuint, _name: &str, ) -> GLint1775     fn get_frag_data_index(
1776         &self,
1777         _program: GLuint,
1778         _name: &str,
1779     ) -> GLint {
1780         panic!("not supported");
1781     }
1782 
1783     // GL_KHR_debug
get_debug_messages(&self) -> Vec<DebugMessage>1784     fn get_debug_messages(&self) -> Vec<DebugMessage> {
1785         if !self.ffi_gl_.GetDebugMessageLog.is_loaded() {
1786             return Vec::new();
1787         }
1788 
1789         let mut max_message_len = 0;
1790         unsafe {
1791             self.ffi_gl_.GetIntegerv(
1792                 ffi::MAX_DEBUG_MESSAGE_LENGTH,
1793                 &mut max_message_len
1794             )
1795         }
1796 
1797         let mut output = Vec::new();
1798         const CAPACITY: usize = 4;
1799 
1800         let mut msg_data = vec![0u8; CAPACITY * max_message_len as usize];
1801         let mut sources = [0 as GLenum; CAPACITY];
1802         let mut types = [0 as GLenum; CAPACITY];
1803         let mut severities = [0 as GLenum; CAPACITY];
1804         let mut ids = [0 as GLuint; CAPACITY];
1805         let mut lengths = [0 as GLsizei; CAPACITY];
1806 
1807         loop {
1808             let count = unsafe {
1809                 self.ffi_gl_.GetDebugMessageLog(
1810                     CAPACITY as _,
1811                     msg_data.len() as _,
1812                     sources.as_mut_ptr(),
1813                     types.as_mut_ptr(),
1814                     ids.as_mut_ptr(),
1815                     severities.as_mut_ptr(),
1816                     lengths.as_mut_ptr(),
1817                     msg_data.as_mut_ptr() as *mut _,
1818                 )
1819             };
1820 
1821             let mut offset = 0;
1822             output.extend((0 .. count as usize).map(|i| {
1823                 let len = lengths[i] as usize;
1824                 let slice = &msg_data[offset .. offset + len];
1825                 offset += len;
1826                 DebugMessage {
1827                     message: String::from_utf8_lossy(slice).to_string(),
1828                     source: sources[i],
1829                     ty: types[i],
1830                     id: ids[i],
1831                     severity: severities[i],
1832                 }
1833             }));
1834 
1835             if (count as usize) < CAPACITY {
1836                 return output
1837             }
1838         }
1839     }
1840 }
1841 
1842