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