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 use ffi;
11 use std::ffi::{CStr, CString};
12 use std::mem;
13 use std::mem::size_of;
14 use std::os::raw::{c_char, c_int, c_void};
15 use std::ptr;
16 use std::rc::Rc;
17 use std::str;
18 use std::time::{Duration, Instant};
19 
20 pub use ffi::types::*;
21 pub use ffi::*;
22 
23 pub use ffi_gl::Gl as GlFfi;
24 pub use ffi_gles::Gles2 as GlesFfi;
25 
26 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
27 pub enum GlType {
28     Gl,
29     Gles,
30 }
31 
32 impl Default for GlType {
33     #[cfg(any(target_os = "android", target_os = "ios"))]
default() -> GlType34     fn default() -> GlType {
35         GlType::Gles
36     }
37     #[cfg(not(any(target_os = "android", target_os = "ios")))]
default() -> GlType38     fn default() -> GlType {
39         GlType::Gl
40     }
41 }
42 
bpp(format: GLenum, pixel_type: GLenum) -> GLsizei43 fn bpp(format: GLenum, pixel_type: GLenum) -> GLsizei {
44     let colors = match format {
45         ffi::RED => 1,
46         ffi::RGB => 3,
47         ffi::BGR => 3,
48 
49         ffi::RGBA => 4,
50         ffi::BGRA => 4,
51 
52         ffi::ALPHA => 1,
53         ffi::R16 => 1,
54         ffi::LUMINANCE => 1,
55         ffi::DEPTH_COMPONENT => 1,
56         _ => panic!("unsupported format for read_pixels: {:?}", format),
57     };
58     let depth = match pixel_type {
59         ffi::UNSIGNED_BYTE => 1,
60         ffi::UNSIGNED_SHORT => 2,
61         ffi::SHORT => 2,
62         ffi::FLOAT => 4,
63         ffi::UNSIGNED_INT_8_8_8_8_REV => return 4,
64         _ => panic!("unsupported pixel_type for read_pixels: {:?}", pixel_type),
65     };
66     colors * depth
67 }
68 
calculate_length(width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> usize69 fn calculate_length(width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> usize {
70     (width * height * bpp(format, pixel_type)) as usize
71 }
72 
73 pub struct DebugMessage {
74     pub message: String,
75     pub source: GLenum,
76     pub ty: GLenum,
77     pub id: GLenum,
78     pub severity: GLenum,
79 }
80 
81 macro_rules! declare_gl_apis {
82     // garbo is a hack to handle unsafe methods.
83     ($($(unsafe $([$garbo:expr])*)* fn $name:ident(&self $(, $arg:ident: $t:ty)* $(,)*) $(-> $retty:ty)* ;)+) => {
84         pub trait Gl {
85             $($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* ;)+
86         }
87 
88         impl Gl for ErrorCheckingGl {
89             $($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* {
90                 let rv = self.gl.$name($($arg,)*);
91                 assert_eq!(self.gl.get_error(), 0);
92                 rv
93             })+
94         }
95 
96         impl<F: Fn(&dyn Gl, &str, GLenum)> Gl for ErrorReactingGl<F> {
97             $($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* {
98                 let rv = self.gl.$name($($arg,)*);
99                 let error = self.gl.get_error();
100                 if error != 0 {
101                     (self.callback)(&*self.gl, stringify!($name), error);
102                 }
103                 rv
104             })+
105         }
106 
107         impl<F: Fn(&str, Duration)> Gl for ProfilingGl<F> {
108             $($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* {
109                 let start = Instant::now();
110                 let rv = self.gl.$name($($arg,)*);
111                 let duration = Instant::now() - start;
112                 if duration > self.threshold {
113                     (self.callback)(stringify!($name), duration);
114                 }
115                 rv
116             })+
117         }
118     }
119 }
120 
121 declare_gl_apis! {
122     fn get_type(&self) -> GlType;
123     fn buffer_data_untyped(
124         &self,
125         target: GLenum,
126         size: GLsizeiptr,
127         data: *const GLvoid,
128         usage: GLenum,
129     );
130     fn buffer_sub_data_untyped(
131         &self,
132         target: GLenum,
133         offset: isize,
134         size: GLsizeiptr,
135         data: *const GLvoid,
136     );
137     fn map_buffer(&self, target: GLenum, access: GLbitfield) -> *mut c_void;
138     fn map_buffer_range(
139         &self,
140         target: GLenum,
141         offset: GLintptr,
142         length: GLsizeiptr,
143         access: GLbitfield,
144     ) -> *mut c_void;
145     fn unmap_buffer(&self, target: GLenum) -> GLboolean;
146     fn tex_buffer(&self, target: GLenum, internal_format: GLenum, buffer: GLuint);
147     fn shader_source(&self, shader: GLuint, strings: &[&[u8]]);
148     fn read_buffer(&self, mode: GLenum);
149     fn read_pixels_into_buffer(
150         &self,
151         x: GLint,
152         y: GLint,
153         width: GLsizei,
154         height: GLsizei,
155         format: GLenum,
156         pixel_type: GLenum,
157         dst_buffer: &mut [u8],
158     );
159     fn read_pixels(
160         &self,
161         x: GLint,
162         y: GLint,
163         width: GLsizei,
164         height: GLsizei,
165         format: GLenum,
166         pixel_type: GLenum,
167     ) -> Vec<u8>;
168     unsafe fn read_pixels_into_pbo(
169         &self,
170         x: GLint,
171         y: GLint,
172         width: GLsizei,
173         height: GLsizei,
174         format: GLenum,
175         pixel_type: GLenum,
176     );
177     fn sample_coverage(&self, value: GLclampf, invert: bool);
178     fn polygon_offset(&self, factor: GLfloat, units: GLfloat);
179     fn pixel_store_i(&self, name: GLenum, param: GLint);
180     fn gen_buffers(&self, n: GLsizei) -> Vec<GLuint>;
181     fn gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint>;
182     fn gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint>;
183     fn gen_textures(&self, n: GLsizei) -> Vec<GLuint>;
184     fn gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint>;
185     fn gen_vertex_arrays_apple(&self, n: GLsizei) -> Vec<GLuint>;
186     fn gen_queries(&self, n: GLsizei) -> Vec<GLuint>;
187     fn begin_query(&self, target: GLenum, id: GLuint);
188     fn end_query(&self, target: GLenum);
189     fn query_counter(&self, id: GLuint, target: GLenum);
190     fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32;
191     fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32;
192     fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64;
193     fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64;
194     fn delete_queries(&self, queries: &[GLuint]);
195     fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]);
196     fn delete_vertex_arrays_apple(&self, vertex_arrays: &[GLuint]);
197     fn delete_buffers(&self, buffers: &[GLuint]);
198     fn delete_renderbuffers(&self, renderbuffers: &[GLuint]);
199     fn delete_framebuffers(&self, framebuffers: &[GLuint]);
200     fn delete_textures(&self, textures: &[GLuint]);
201     fn framebuffer_renderbuffer(
202         &self,
203         target: GLenum,
204         attachment: GLenum,
205         renderbuffertarget: GLenum,
206         renderbuffer: GLuint,
207     );
208     fn renderbuffer_storage(
209         &self,
210         target: GLenum,
211         internalformat: GLenum,
212         width: GLsizei,
213         height: GLsizei,
214     );
215     fn depth_func(&self, func: GLenum);
216     fn active_texture(&self, texture: GLenum);
217     fn attach_shader(&self, program: GLuint, shader: GLuint);
218     fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str);
219     unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]);
220     unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]);
221     fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint;
222     fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec<GLuint>;
223     fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint);
224     fn bind_buffer_range(
225         &self,
226         target: GLenum,
227         index: GLuint,
228         buffer: GLuint,
229         offset: GLintptr,
230         size: GLsizeiptr,
231     );
232     fn uniform_block_binding(
233         &self,
234         program: GLuint,
235         uniform_block_index: GLuint,
236         uniform_block_binding: GLuint,
237     );
238     fn bind_buffer(&self, target: GLenum, buffer: GLuint);
239     fn bind_vertex_array(&self, vao: GLuint);
240     fn bind_vertex_array_apple(&self, vao: GLuint);
241     fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint);
242     fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint);
243     fn bind_texture(&self, target: GLenum, texture: GLuint);
244     fn draw_buffers(&self, bufs: &[GLenum]);
245     fn tex_image_2d(
246         &self,
247         target: GLenum,
248         level: GLint,
249         internal_format: GLint,
250         width: GLsizei,
251         height: GLsizei,
252         border: GLint,
253         format: GLenum,
254         ty: GLenum,
255         opt_data: Option<&[u8]>,
256     );
257     fn compressed_tex_image_2d(
258         &self,
259         target: GLenum,
260         level: GLint,
261         internal_format: GLenum,
262         width: GLsizei,
263         height: GLsizei,
264         border: GLint,
265         data: &[u8],
266     );
267     fn compressed_tex_sub_image_2d(
268         &self,
269         target: GLenum,
270         level: GLint,
271         xoffset: GLint,
272         yoffset: GLint,
273         width: GLsizei,
274         height: GLsizei,
275         format: GLenum,
276         data: &[u8],
277     );
278     fn tex_image_3d(
279         &self,
280         target: GLenum,
281         level: GLint,
282         internal_format: GLint,
283         width: GLsizei,
284         height: GLsizei,
285         depth: GLsizei,
286         border: GLint,
287         format: GLenum,
288         ty: GLenum,
289         opt_data: Option<&[u8]>,
290     );
291     fn copy_tex_image_2d(
292         &self,
293         target: GLenum,
294         level: GLint,
295         internal_format: GLenum,
296         x: GLint,
297         y: GLint,
298         width: GLsizei,
299         height: GLsizei,
300         border: GLint,
301     );
302     fn copy_tex_sub_image_2d(
303         &self,
304         target: GLenum,
305         level: GLint,
306         xoffset: GLint,
307         yoffset: GLint,
308         x: GLint,
309         y: GLint,
310         width: GLsizei,
311         height: GLsizei,
312     );
313     fn copy_tex_sub_image_3d(
314         &self,
315         target: GLenum,
316         level: GLint,
317         xoffset: GLint,
318         yoffset: GLint,
319         zoffset: GLint,
320         x: GLint,
321         y: GLint,
322         width: GLsizei,
323         height: GLsizei,
324     );
325     fn tex_sub_image_2d(
326         &self,
327         target: GLenum,
328         level: GLint,
329         xoffset: GLint,
330         yoffset: GLint,
331         width: GLsizei,
332         height: GLsizei,
333         format: GLenum,
334         ty: GLenum,
335         data: &[u8],
336     );
337     fn tex_sub_image_2d_pbo(
338         &self,
339         target: GLenum,
340         level: GLint,
341         xoffset: GLint,
342         yoffset: GLint,
343         width: GLsizei,
344         height: GLsizei,
345         format: GLenum,
346         ty: GLenum,
347         offset: usize,
348     );
349     fn tex_sub_image_3d(
350         &self,
351         target: GLenum,
352         level: GLint,
353         xoffset: GLint,
354         yoffset: GLint,
355         zoffset: GLint,
356         width: GLsizei,
357         height: GLsizei,
358         depth: GLsizei,
359         format: GLenum,
360         ty: GLenum,
361         data: &[u8],
362     );
363     fn tex_sub_image_3d_pbo(
364         &self,
365         target: GLenum,
366         level: GLint,
367         xoffset: GLint,
368         yoffset: GLint,
369         zoffset: GLint,
370         width: GLsizei,
371         height: GLsizei,
372         depth: GLsizei,
373         format: GLenum,
374         ty: GLenum,
375         offset: usize,
376     );
377     fn tex_storage_2d(
378         &self,
379         target: GLenum,
380         levels: GLint,
381         internal_format: GLenum,
382         width: GLsizei,
383         height: GLsizei,
384     );
385     fn tex_storage_3d(
386         &self,
387         target: GLenum,
388         levels: GLint,
389         internal_format: GLenum,
390         width: GLsizei,
391         height: GLsizei,
392         depth: GLsizei,
393     );
394     fn get_tex_image_into_buffer(
395         &self,
396         target: GLenum,
397         level: GLint,
398         format: GLenum,
399         ty: GLenum,
400         output: &mut [u8],
401     );
402     unsafe fn copy_image_sub_data(
403         &self,
404         src_name: GLuint,
405         src_target: GLenum,
406         src_level: GLint,
407         src_x: GLint,
408         src_y: GLint,
409         src_z: GLint,
410         dst_name: GLuint,
411         dst_target: GLenum,
412         dst_level: GLint,
413         dst_x: GLint,
414         dst_y: GLint,
415         dst_z: GLint,
416         src_width: GLsizei,
417         src_height: GLsizei,
418         src_depth: GLsizei,
419     );
420 
421     fn invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum]);
422     fn invalidate_sub_framebuffer(
423         &self,
424         target: GLenum,
425         attachments: &[GLenum],
426         xoffset: GLint,
427         yoffset: GLint,
428         width: GLsizei,
429         height: GLsizei,
430     );
431 
432     unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]);
433     unsafe fn get_integer_64v(&self, name: GLenum, result: &mut [GLint64]);
434     unsafe fn get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint]);
435     unsafe fn get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64]);
436     unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]);
437     unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]);
438 
439     fn get_framebuffer_attachment_parameter_iv(
440         &self,
441         target: GLenum,
442         attachment: GLenum,
443         pname: GLenum,
444     ) -> GLint;
445     fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint;
446     fn get_tex_parameter_iv(&self, target: GLenum, name: GLenum) -> GLint;
447     fn get_tex_parameter_fv(&self, target: GLenum, name: GLenum) -> GLfloat;
448     fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint);
449     fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat);
450     fn framebuffer_texture_2d(
451         &self,
452         target: GLenum,
453         attachment: GLenum,
454         textarget: GLenum,
455         texture: GLuint,
456         level: GLint,
457     );
458     fn framebuffer_texture_layer(
459         &self,
460         target: GLenum,
461         attachment: GLenum,
462         texture: GLuint,
463         level: GLint,
464         layer: GLint,
465     );
466     fn blit_framebuffer(
467         &self,
468         src_x0: GLint,
469         src_y0: GLint,
470         src_x1: GLint,
471         src_y1: GLint,
472         dst_x0: GLint,
473         dst_y0: GLint,
474         dst_x1: GLint,
475         dst_y1: GLint,
476         mask: GLbitfield,
477         filter: GLenum,
478     );
479     fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat);
480     fn vertex_attrib_pointer_f32(
481         &self,
482         index: GLuint,
483         size: GLint,
484         normalized: bool,
485         stride: GLsizei,
486         offset: GLuint,
487     );
488     fn vertex_attrib_pointer(
489         &self,
490         index: GLuint,
491         size: GLint,
492         type_: GLenum,
493         normalized: bool,
494         stride: GLsizei,
495         offset: GLuint,
496     );
497     fn vertex_attrib_i_pointer(
498         &self,
499         index: GLuint,
500         size: GLint,
501         type_: GLenum,
502         stride: GLsizei,
503         offset: GLuint,
504     );
505     fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint);
506     fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei);
507     fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei);
508     fn line_width(&self, width: GLfloat);
509     fn use_program(&self, program: GLuint);
510     fn validate_program(&self, program: GLuint);
511     fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei);
512     fn draw_arrays_instanced(&self, mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei);
513     fn draw_elements(
514         &self,
515         mode: GLenum,
516         count: GLsizei,
517         element_type: GLenum,
518         indices_offset: GLuint,
519     );
520     fn draw_elements_instanced(
521         &self,
522         mode: GLenum,
523         count: GLsizei,
524         element_type: GLenum,
525         indices_offset: GLuint,
526         primcount: GLsizei,
527     );
528     fn blend_color(&self, r: f32, g: f32, b: f32, a: f32);
529     fn blend_func(&self, sfactor: GLenum, dfactor: GLenum);
530     fn blend_func_separate(
531         &self,
532         src_rgb: GLenum,
533         dest_rgb: GLenum,
534         src_alpha: GLenum,
535         dest_alpha: GLenum,
536     );
537     fn blend_equation(&self, mode: GLenum);
538     fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum);
539     fn color_mask(&self, r: bool, g: bool, b: bool, a: bool);
540     fn cull_face(&self, mode: GLenum);
541     fn front_face(&self, mode: GLenum);
542     fn enable(&self, cap: GLenum);
543     fn disable(&self, cap: GLenum);
544     fn hint(&self, param_name: GLenum, param_val: GLenum);
545     fn is_enabled(&self, cap: GLenum) -> GLboolean;
546     fn is_shader(&self, shader: GLuint) -> GLboolean;
547     fn is_texture(&self, texture: GLenum) -> GLboolean;
548     fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean;
549     fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean;
550     fn check_frame_buffer_status(&self, target: GLenum) -> GLenum;
551     fn enable_vertex_attrib_array(&self, index: GLuint);
552     fn disable_vertex_attrib_array(&self, index: GLuint);
553     fn uniform_1f(&self, location: GLint, v0: GLfloat);
554     fn uniform_1fv(&self, location: GLint, values: &[f32]);
555     fn uniform_1i(&self, location: GLint, v0: GLint);
556     fn uniform_1iv(&self, location: GLint, values: &[i32]);
557     fn uniform_1ui(&self, location: GLint, v0: GLuint);
558     fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat);
559     fn uniform_2fv(&self, location: GLint, values: &[f32]);
560     fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint);
561     fn uniform_2iv(&self, location: GLint, values: &[i32]);
562     fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint);
563     fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat);
564     fn uniform_3fv(&self, location: GLint, values: &[f32]);
565     fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint);
566     fn uniform_3iv(&self, location: GLint, values: &[i32]);
567     fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint);
568     fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat);
569     fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint);
570     fn uniform_4iv(&self, location: GLint, values: &[i32]);
571     fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint);
572     fn uniform_4fv(&self, location: GLint, values: &[f32]);
573     fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]);
574     fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]);
575     fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]);
576     fn depth_mask(&self, flag: bool);
577     fn depth_range(&self, near: f64, far: f64);
578     fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String);
579     fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String);
580     fn get_active_uniforms_iv(
581         &self,
582         program: GLuint,
583         indices: Vec<GLuint>,
584         pname: GLenum,
585     ) -> Vec<GLint>;
586     fn get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint;
587     fn get_active_uniform_block_iv(
588         &self,
589         program: GLuint,
590         index: GLuint,
591         pname: GLenum,
592     ) -> Vec<GLint>;
593     fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String;
594     fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int;
595     fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int;
596     fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int;
597     fn get_program_info_log(&self, program: GLuint) -> String;
598     unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]);
599     fn get_program_binary(&self, program: GLuint) -> (Vec<u8>, GLenum);
600     fn program_binary(&self, program: GLuint, format: GLenum, binary: &[u8]);
601     fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint);
602     unsafe fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint]);
603     unsafe fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat]);
604     fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr;
605     fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint;
606     fn get_shader_info_log(&self, shader: GLuint) -> String;
607     fn get_string(&self, which: GLenum) -> String;
608     fn get_string_i(&self, which: GLenum, index: GLuint) -> String;
609     unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]);
610     fn get_shader_precision_format(
611         &self,
612         shader_type: GLuint,
613         precision_type: GLuint,
614     ) -> (GLint, GLint, GLint);
615     fn compile_shader(&self, shader: GLuint);
616     fn create_program(&self) -> GLuint;
617     fn delete_program(&self, program: GLuint);
618     fn create_shader(&self, shader_type: GLenum) -> GLuint;
619     fn delete_shader(&self, shader: GLuint);
620     fn detach_shader(&self, program: GLuint, shader: GLuint);
621     fn link_program(&self, program: GLuint);
622     fn clear_color(&self, r: f32, g: f32, b: f32, a: f32);
623     fn clear(&self, buffer_mask: GLbitfield);
624     fn clear_depth(&self, depth: f64);
625     fn clear_stencil(&self, s: GLint);
626     fn flush(&self);
627     fn finish(&self);
628     fn get_error(&self) -> GLenum;
629     fn stencil_mask(&self, mask: GLuint);
630     fn stencil_mask_separate(&self, face: GLenum, mask: GLuint);
631     fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint);
632     fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint);
633     fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum);
634     fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum);
635     fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES);
636     fn egl_image_target_renderbuffer_storage_oes(&self, target: GLenum, image: GLeglImageOES);
637     fn generate_mipmap(&self, target: GLenum);
638     fn insert_event_marker_ext(&self, message: &str);
639     fn push_group_marker_ext(&self, message: &str);
640     fn pop_group_marker_ext(&self);
641     fn debug_message_insert_khr(
642         &self,
643         source: GLenum,
644         type_: GLenum,
645         id: GLuint,
646         severity: GLenum,
647         message: &str,
648     );
649     fn push_debug_group_khr(&self, source: GLenum, id: GLuint, message: &str);
650     fn pop_debug_group_khr(&self);
651     fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync;
652     fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) -> GLenum;
653     fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64);
654     fn delete_sync(&self, sync: GLsync);
655     fn texture_range_apple(&self, target: GLenum, data: &[u8]);
656     fn gen_fences_apple(&self, n: GLsizei) -> Vec<GLuint>;
657     fn delete_fences_apple(&self, fences: &[GLuint]);
658     fn set_fence_apple(&self, fence: GLuint);
659     fn finish_fence_apple(&self, fence: GLuint);
660     fn test_fence_apple(&self, fence: GLuint);
661     fn test_object_apple(&self, object: GLenum, name: GLuint) -> GLboolean;
662     fn finish_object_apple(&self, object: GLenum, name: GLuint);
663     // GL_KHR_blend_equation_advanced
664     fn blend_barrier_khr(&self);
665 
666     // GL_ARB_blend_func_extended
667     fn bind_frag_data_location_indexed(
668         &self,
669         program: GLuint,
670         color_number: GLuint,
671         index: GLuint,
672         name: &str,
673     );
674     fn get_frag_data_index(&self, program: GLuint, name: &str) -> GLint;
675 
676     // GL_KHR_debug
677     fn get_debug_messages(&self) -> Vec<DebugMessage>;
678 
679     // GL_ANGLE_provoking_vertex
680     fn provoking_vertex_angle(&self, mode: GLenum);
681 
682     // GL_CHROMIUM_copy_texture
683     fn copy_texture_chromium(
684         &self,
685         source_id: GLuint,
686         source_level: GLint,
687         dest_target: GLenum,
688         dest_id: GLuint,
689         dest_level: GLint,
690         internal_format: GLint,
691         dest_type: GLenum,
692         unpack_flip_y: GLboolean,
693         unpack_premultiply_alpha: GLboolean,
694         unpack_unmultiply_alpha: GLboolean,
695     );
696     fn copy_sub_texture_chromium(
697         &self,
698         source_id: GLuint,
699         source_level: GLint,
700         dest_target: GLenum,
701         dest_id: GLuint,
702         dest_level: GLint,
703         x_offset: GLint,
704         y_offset: GLint,
705         x: GLint,
706         y: GLint,
707         width: GLsizei,
708         height: GLsizei,
709         unpack_flip_y: GLboolean,
710         unpack_premultiply_alpha: GLboolean,
711         unpack_unmultiply_alpha: GLboolean,
712     );
713 
714     // GL_ANGLE_copy_texture_3d
715     fn copy_texture_3d_angle(
716         &self,
717         source_id: GLuint,
718         source_level: GLint,
719         dest_target: GLenum,
720         dest_id: GLuint,
721         dest_level: GLint,
722         internal_format: GLint,
723         dest_type: GLenum,
724         unpack_flip_y: GLboolean,
725         unpack_premultiply_alpha: GLboolean,
726         unpack_unmultiply_alpha: GLboolean,
727     );
728 
729     fn copy_sub_texture_3d_angle(
730         &self,
731         source_id: GLuint,
732         source_level: GLint,
733         dest_target: GLenum,
734         dest_id: GLuint,
735         dest_level: GLint,
736         x_offset: GLint,
737         y_offset: GLint,
738         z_offset: GLint,
739         x: GLint,
740         y: GLint,
741         z: GLint,
742         width: GLsizei,
743         height: GLsizei,
744         depth: GLsizei,
745         unpack_flip_y: GLboolean,
746         unpack_premultiply_alpha: GLboolean,
747         unpack_unmultiply_alpha: GLboolean,
748     );
749 
750     fn buffer_storage(
751         &self,
752         target: GLenum,
753         size: GLsizeiptr,
754         data: *const GLvoid,
755         flags: GLbitfield,
756     );
757 
758     fn flush_mapped_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr);
759 }
760 
761 //#[deprecated(since = "0.6.11", note = "use ErrorReactingGl instead")]
762 pub struct ErrorCheckingGl {
763     gl: Rc<dyn Gl>,
764 }
765 
766 impl ErrorCheckingGl {
wrap(fns: Rc<dyn Gl>) -> Rc<dyn Gl>767     pub fn wrap(fns: Rc<dyn Gl>) -> Rc<dyn Gl> {
768         Rc::new(ErrorCheckingGl { gl: fns }) as Rc<dyn Gl>
769     }
770 }
771 
772 /// A wrapper around GL context that calls a specified callback on each GL error.
773 pub struct ErrorReactingGl<F> {
774     gl: Rc<dyn Gl>,
775     callback: F,
776 }
777 
778 impl<F: 'static + Fn(&dyn Gl, &str, GLenum)> ErrorReactingGl<F> {
wrap(fns: Rc<dyn Gl>, callback: F) -> Rc<dyn Gl>779     pub fn wrap(fns: Rc<dyn Gl>, callback: F) -> Rc<dyn Gl> {
780         Rc::new(ErrorReactingGl { gl: fns, callback }) as Rc<dyn Gl>
781     }
782 }
783 
784 /// A wrapper around GL context that times each call and invokes the callback
785 /// if the call takes longer than the threshold.
786 pub struct ProfilingGl<F> {
787     gl: Rc<dyn Gl>,
788     threshold: Duration,
789     callback: F,
790 }
791 
792 impl<F: 'static + Fn(&str, Duration)> ProfilingGl<F> {
wrap(fns: Rc<dyn Gl>, threshold: Duration, callback: F) -> Rc<dyn Gl>793     pub fn wrap(fns: Rc<dyn Gl>, threshold: Duration, callback: F) -> Rc<dyn Gl> {
794         Rc::new(ProfilingGl {
795             gl: fns,
796             threshold,
797             callback,
798         }) as Rc<dyn Gl>
799     }
800 }
801 
802 #[inline]
buffer_data<T>(gl_: &dyn Gl, target: GLenum, data: &[T], usage: GLenum)803 pub fn buffer_data<T>(gl_: &dyn Gl, target: GLenum, data: &[T], usage: GLenum) {
804     gl_.buffer_data_untyped(
805         target,
806         (data.len() * size_of::<T>()) as GLsizeiptr,
807         data.as_ptr() as *const GLvoid,
808         usage,
809     )
810 }
811 
812 #[inline]
buffer_data_raw<T>(gl_: &dyn Gl, target: GLenum, data: &T, usage: GLenum)813 pub fn buffer_data_raw<T>(gl_: &dyn Gl, target: GLenum, data: &T, usage: GLenum) {
814     gl_.buffer_data_untyped(
815         target,
816         size_of::<T>() as GLsizeiptr,
817         data as *const T as *const GLvoid,
818         usage,
819     )
820 }
821 
822 #[inline]
buffer_sub_data<T>(gl_: &dyn Gl, target: GLenum, offset: isize, data: &[T])823 pub fn buffer_sub_data<T>(gl_: &dyn Gl, target: GLenum, offset: isize, data: &[T]) {
824     gl_.buffer_sub_data_untyped(
825         target,
826         offset,
827         (data.len() * size_of::<T>()) as GLsizeiptr,
828         data.as_ptr() as *const GLvoid,
829     );
830 }
831 
832 include!("gl_fns.rs");
833 include!("gles_fns.rs");
834