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