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