1pub struct GlFns {
11 ffi_gl_: GlFfi,
12}
13
14impl GlFns {
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
24impl Gl for GlFns {
25 fn get_type(&self) -> GlType {
26 GlType::Gl
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 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
53 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
61 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
71 fn unmap_buffer(&self, target: GLenum) -> GLboolean {
72 unsafe {
73 return self.ffi_gl_.UnmapBuffer(target);
74 }
75 }
76
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
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
98 fn read_buffer(&self, mode: GLenum) {
99 unsafe {
100 self.ffi_gl_.ReadBuffer(mode);
101 }
102 }
103
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 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 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
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
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
180 fn sample_coverage(&self, value: GLclampf, invert: bool) {
181 unsafe {
182 self.ffi_gl_.SampleCoverage(value, invert as GLboolean);
183 }
184 }
185
186 fn polygon_offset(&self, factor: GLfloat, units: GLfloat) {
187 unsafe {
188 self.ffi_gl_.PolygonOffset(factor, units);
189 }
190 }
191
192 fn pixel_store_i(&self, name: GLenum, param: GLint) {
193 unsafe {
194 self.ffi_gl_.PixelStorei(name, param);
195 }
196 }
197
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
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
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
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
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
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
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
254 fn begin_query(&self, target: GLenum, id: GLuint) {
255 unsafe {
256 self.ffi_gl_.BeginQuery(target, id);
257 }
258 }
259
260 fn end_query(&self, target: GLenum) {
261 unsafe {
262 self.ffi_gl_.EndQuery(target);
263 }
264 }
265
266 fn query_counter(&self, id: GLuint, target: GLenum) {
267 unsafe {
268 self.ffi_gl_.QueryCounter(id, target);
269 }
270 }
271
272 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
280 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
288 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
296 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
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
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
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
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
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
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
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
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
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
383 fn depth_func(&self, func: GLenum) {
384 unsafe {
385 self.ffi_gl_.DepthFunc(func);
386 }
387 }
388
389 fn active_texture(&self, texture: GLenum) {
390 unsafe {
391 self.ffi_gl_.ActiveTexture(texture);
392 }
393 }
394
395 fn attach_shader(&self, program: GLuint, shader: GLuint) {
396 unsafe {
397 self.ffi_gl_.AttachShader(program, shader);
398 }
399 }
400
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 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 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
423 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
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
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
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
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
479 fn bind_buffer(&self, target: GLenum, buffer: GLuint) {
480 unsafe {
481 self.ffi_gl_.BindBuffer(target, buffer);
482 }
483 }
484
485 fn bind_vertex_array(&self, vao: GLuint) {
486 unsafe {
487 self.ffi_gl_.BindVertexArray(vao);
488 }
489 }
490
491 fn bind_vertex_array_apple(&self, vao: GLuint) {
492 unsafe {
493 self.ffi_gl_.BindVertexArrayAPPLE(vao)
494 }
495 }
496
497 fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) {
498 unsafe {
499 self.ffi_gl_.BindRenderbuffer(target, renderbuffer);
500 }
501 }
502
503 fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) {
504 unsafe {
505 self.ffi_gl_.BindFramebuffer(target, framebuffer);
506 }
507 }
508
509 fn bind_texture(&self, target: GLenum, texture: GLuint) {
510 unsafe {
511 self.ffi_gl_.BindTexture(target, texture);
512 }
513 }
514
515 fn bind_vertex_buffer(&self, binding_index: GLuint, buffer: GLuint, offset: GLintptr, stride: GLint) {
516 unsafe { self.ffi_gl_.BindVertexBuffer(binding_index, buffer, offset, stride) }
517 }
518
519 fn draw_buffers(&self, bufs: &[GLenum]) {
520 unsafe {
521 self.ffi_gl_
522 .DrawBuffers(bufs.len() as GLsizei, bufs.as_ptr());
523 }
524 }
525
526 fn tex_image_2d(
528 &self,
529 target: GLenum,
530 level: GLint,
531 internal_format: GLint,
532 width: GLsizei,
533 height: GLsizei,
534 border: GLint,
535 format: GLenum,
536 ty: GLenum,
537 opt_data: Option<&[u8]>,
538 ) {
539 match opt_data {
540 Some(data) => unsafe {
541 self.ffi_gl_.TexImage2D(
542 target,
543 level,
544 internal_format,
545 width,
546 height,
547 border,
548 format,
549 ty,
550 data.as_ptr() as *const GLvoid,
551 );
552 },
553 None => unsafe {
554 self.ffi_gl_.TexImage2D(
555 target,
556 level,
557 internal_format,
558 width,
559 height,
560 border,
561 format,
562 ty,
563 ptr::null(),
564 );
565 },
566 }
567 }
568
569 fn compressed_tex_image_2d(
570 &self,
571 target: GLenum,
572 level: GLint,
573 internal_format: GLenum,
574 width: GLsizei,
575 height: GLsizei,
576 border: GLint,
577 data: &[u8],
578 ) {
579 unsafe {
580 self.ffi_gl_.CompressedTexImage2D(
581 target,
582 level,
583 internal_format,
584 width,
585 height,
586 border,
587 data.len() as GLsizei,
588 data.as_ptr() as *const GLvoid,
589 );
590 }
591 }
592
593 fn compressed_tex_sub_image_2d(
594 &self,
595 target: GLenum,
596 level: GLint,
597 xoffset: GLint,
598 yoffset: GLint,
599 width: GLsizei,
600 height: GLsizei,
601 format: GLenum,
602 data: &[u8],
603 ) {
604 unsafe {
605 self.ffi_gl_.CompressedTexSubImage2D(
606 target,
607 level,
608 xoffset,
609 yoffset,
610 width,
611 height,
612 format,
613 data.len() as GLsizei,
614 data.as_ptr() as *const GLvoid,
615 );
616 }
617 }
618
619 fn tex_image_3d(
621 &self,
622 target: GLenum,
623 level: GLint,
624 internal_format: GLint,
625 width: GLsizei,
626 height: GLsizei,
627 depth: GLsizei,
628 border: GLint,
629 format: GLenum,
630 ty: GLenum,
631 opt_data: Option<&[u8]>,
632 ) {
633 unsafe {
634 let pdata = match opt_data {
635 Some(data) => mem::transmute(data.as_ptr()),
636 None => ptr::null(),
637 };
638 self.ffi_gl_.TexImage3D(
639 target,
640 level,
641 internal_format,
642 width,
643 height,
644 depth,
645 border,
646 format,
647 ty,
648 pdata,
649 );
650 }
651 }
652
653 fn copy_tex_image_2d(
654 &self,
655 target: GLenum,
656 level: GLint,
657 internal_format: GLenum,
658 x: GLint,
659 y: GLint,
660 width: GLsizei,
661 height: GLsizei,
662 border: GLint,
663 ) {
664 unsafe {
665 self.ffi_gl_.CopyTexImage2D(
666 target,
667 level,
668 internal_format,
669 x,
670 y,
671 width,
672 height,
673 border,
674 );
675 }
676 }
677
678 fn copy_tex_sub_image_2d(
679 &self,
680 target: GLenum,
681 level: GLint,
682 xoffset: GLint,
683 yoffset: GLint,
684 x: GLint,
685 y: GLint,
686 width: GLsizei,
687 height: GLsizei,
688 ) {
689 unsafe {
690 self.ffi_gl_
691 .CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
692 }
693 }
694
695 fn copy_tex_sub_image_3d(
696 &self,
697 target: GLenum,
698 level: GLint,
699 xoffset: GLint,
700 yoffset: GLint,
701 zoffset: GLint,
702 x: GLint,
703 y: GLint,
704 width: GLsizei,
705 height: GLsizei,
706 ) {
707 unsafe {
708 self.ffi_gl_.CopyTexSubImage3D(
709 target, level, xoffset, yoffset, zoffset, x, y, width, height,
710 );
711 }
712 }
713
714 fn tex_sub_image_2d(
715 &self,
716 target: GLenum,
717 level: GLint,
718 xoffset: GLint,
719 yoffset: GLint,
720 width: GLsizei,
721 height: GLsizei,
722 format: GLenum,
723 ty: GLenum,
724 data: &[u8],
725 ) {
726 unsafe {
727 self.ffi_gl_.TexSubImage2D(
728 target,
729 level,
730 xoffset,
731 yoffset,
732 width,
733 height,
734 format,
735 ty,
736 data.as_ptr() as *const c_void,
737 );
738 }
739 }
740
741 fn tex_sub_image_2d_pbo(
742 &self,
743 target: GLenum,
744 level: GLint,
745 xoffset: GLint,
746 yoffset: GLint,
747 width: GLsizei,
748 height: GLsizei,
749 format: GLenum,
750 ty: GLenum,
751 offset: usize,
752 ) {
753 unsafe {
754 self.ffi_gl_.TexSubImage2D(
755 target,
756 level,
757 xoffset,
758 yoffset,
759 width,
760 height,
761 format,
762 ty,
763 offset as *const c_void,
764 );
765 }
766 }
767
768 fn tex_sub_image_3d(
769 &self,
770 target: GLenum,
771 level: GLint,
772 xoffset: GLint,
773 yoffset: GLint,
774 zoffset: GLint,
775 width: GLsizei,
776 height: GLsizei,
777 depth: GLsizei,
778 format: GLenum,
779 ty: GLenum,
780 data: &[u8],
781 ) {
782 unsafe {
783 self.ffi_gl_.TexSubImage3D(
784 target,
785 level,
786 xoffset,
787 yoffset,
788 zoffset,
789 width,
790 height,
791 depth,
792 format,
793 ty,
794 data.as_ptr() as *const c_void,
795 );
796 }
797 }
798
799 fn tex_sub_image_3d_pbo(
800 &self,
801 target: GLenum,
802 level: GLint,
803 xoffset: GLint,
804 yoffset: GLint,
805 zoffset: GLint,
806 width: GLsizei,
807 height: GLsizei,
808 depth: GLsizei,
809 format: GLenum,
810 ty: GLenum,
811 offset: usize,
812 ) {
813 unsafe {
814 self.ffi_gl_.TexSubImage3D(
815 target,
816 level,
817 xoffset,
818 yoffset,
819 zoffset,
820 width,
821 height,
822 depth,
823 format,
824 ty,
825 offset as *const c_void,
826 );
827 }
828 }
829
830 fn tex_storage_2d(
831 &self,
832 target: GLenum,
833 levels: GLint,
834 internal_format: GLenum,
835 width: GLsizei,
836 height: GLsizei,
837 ) {
838 if self.ffi_gl_.TexStorage2D.is_loaded() {
839 unsafe {
840 self.ffi_gl_
841 .TexStorage2D(target, levels, internal_format, width, height);
842 }
843 }
844 }
845
846 fn tex_storage_3d(
847 &self,
848 target: GLenum,
849 levels: GLint,
850 internal_format: GLenum,
851 width: GLsizei,
852 height: GLsizei,
853 depth: GLsizei,
854 ) {
855 if self.ffi_gl_.TexStorage3D.is_loaded() {
856 unsafe {
857 self.ffi_gl_
858 .TexStorage3D(target, levels, internal_format, width, height, depth);
859 }
860 }
861 }
862
863 fn get_tex_image_into_buffer(
864 &self,
865 target: GLenum,
866 level: GLint,
867 format: GLenum,
868 ty: GLenum,
869 output: &mut [u8],
870 ) {
871 unsafe {
872 self.ffi_gl_
873 .GetTexImage(target, level, format, ty, output.as_mut_ptr() as *mut _);
874 }
875 }
876
877 unsafe fn copy_image_sub_data(
878 &self,
879 src_name: GLuint,
880 src_target: GLenum,
881 src_level: GLint,
882 src_x: GLint,
883 src_y: GLint,
884 src_z: GLint,
885 dst_name: GLuint,
886 dst_target: GLenum,
887 dst_level: GLint,
888 dst_x: GLint,
889 dst_y: GLint,
890 dst_z: GLint,
891 src_width: GLsizei,
892 src_height: GLsizei,
893 src_depth: GLsizei,
894 ) {
895 self.ffi_gl_.CopyImageSubData(
896 src_name, src_target, src_level, src_x, src_y, src_z, dst_name, dst_target, dst_level,
897 dst_x, dst_y, dst_z, src_width, src_height, src_depth,
898 );
899 }
900
901 fn invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum]) {
902 if self.ffi_gl_.InvalidateFramebuffer.is_loaded() {
903 unsafe {
904 self.ffi_gl_.InvalidateFramebuffer(
905 target,
906 attachments.len() as GLsizei,
907 attachments.as_ptr(),
908 );
909 }
910 }
911 }
912
913 fn invalidate_sub_framebuffer(
914 &self,
915 target: GLenum,
916 attachments: &[GLenum],
917 xoffset: GLint,
918 yoffset: GLint,
919 width: GLsizei,
920 height: GLsizei,
921 ) {
922 if self.ffi_gl_.InvalidateSubFramebuffer.is_loaded() {
923 unsafe {
924 self.ffi_gl_.InvalidateSubFramebuffer(
925 target,
926 attachments.len() as GLsizei,
927 attachments.as_ptr(),
928 xoffset,
929 yoffset,
930 width,
931 height,
932 );
933 }
934 }
935 }
936
937 #[inline]
938 unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]) {
939 assert!(!result.is_empty());
940 self.ffi_gl_.GetIntegerv(name, result.as_mut_ptr());
941 }
942
943 #[inline]
944 unsafe fn get_integer_64v(&self, name: GLenum, result: &mut [GLint64]) {
945 assert!(!result.is_empty());
946 self.ffi_gl_.GetInteger64v(name, result.as_mut_ptr());
947 }
948
949 #[inline]
950 unsafe fn get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint]) {
951 assert!(!result.is_empty());
952 self.ffi_gl_.GetIntegeri_v(name, index, result.as_mut_ptr());
953 }
954
955 #[inline]
956 unsafe fn get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64]) {
957 assert!(!result.is_empty());
958 self.ffi_gl_
959 .GetInteger64i_v(name, index, result.as_mut_ptr());
960 }
961
962 #[inline]
963 unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]) {
964 assert!(!result.is_empty());
965 self.ffi_gl_.GetBooleanv(name, result.as_mut_ptr());
966 }
967
968 #[inline]
969 unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]) {
970 assert!(!result.is_empty());
971 self.ffi_gl_.GetFloatv(name, result.as_mut_ptr());
972 }
973
974 fn get_framebuffer_attachment_parameter_iv(
975 &self,
976 target: GLenum,
977 attachment: GLenum,
978 pname: GLenum,
979 ) -> GLint {
980 let mut result: GLint = 0;
981 unsafe {
982 self.ffi_gl_.GetFramebufferAttachmentParameteriv(
983 target,
984 attachment,
985 pname,
986 &mut result,
987 );
988 }
989 result
990 }
991
992 fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
993 let mut result: GLint = 0;
994 unsafe {
995 self.ffi_gl_
996 .GetRenderbufferParameteriv(target, pname, &mut result);
997 }
998 result
999 }
1000
1001 fn get_tex_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
1002 let mut result: GLint = 0;
1003 unsafe {
1004 self.ffi_gl_.GetTexParameteriv(target, pname, &mut result);
1005 }
1006 result
1007 }
1008
1009 fn get_tex_parameter_fv(&self, target: GLenum, pname: GLenum) -> GLfloat {
1010 let mut result: GLfloat = 0.0;
1011 unsafe {
1012 self.ffi_gl_.GetTexParameterfv(target, pname, &mut result);
1013 }
1014 result
1015 }
1016
1017 fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) {
1018 unsafe {
1019 self.ffi_gl_.TexParameteri(target, pname, param);
1020 }
1021 }
1022
1023 fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) {
1024 unsafe {
1025 self.ffi_gl_.TexParameterf(target, pname, param);
1026 }
1027 }
1028
1029 fn framebuffer_texture_2d(
1030 &self,
1031 target: GLenum,
1032 attachment: GLenum,
1033 textarget: GLenum,
1034 texture: GLuint,
1035 level: GLint,
1036 ) {
1037 unsafe {
1038 self.ffi_gl_
1039 .FramebufferTexture2D(target, attachment, textarget, texture, level);
1040 }
1041 }
1042
1043 fn framebuffer_texture_layer(
1044 &self,
1045 target: GLenum,
1046 attachment: GLenum,
1047 texture: GLuint,
1048 level: GLint,
1049 layer: GLint,
1050 ) {
1051 unsafe {
1052 self.ffi_gl_
1053 .FramebufferTextureLayer(target, attachment, texture, level, layer);
1054 }
1055 }
1056
1057 fn blit_framebuffer(
1058 &self,
1059 src_x0: GLint,
1060 src_y0: GLint,
1061 src_x1: GLint,
1062 src_y1: GLint,
1063 dst_x0: GLint,
1064 dst_y0: GLint,
1065 dst_x1: GLint,
1066 dst_y1: GLint,
1067 mask: GLbitfield,
1068 filter: GLenum,
1069 ) {
1070 unsafe {
1071 self.ffi_gl_.BlitFramebuffer(
1072 src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter,
1073 );
1074 }
1075 }
1076
1077 fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
1078 unsafe { self.ffi_gl_.VertexAttrib4f(index, x, y, z, w) }
1079 }
1080
1081 fn vertex_attrib_binding(&self, attrib_index: GLuint, binding_index: GLuint) {
1082 unsafe { self.ffi_gl_.VertexAttribBinding(attrib_index, binding_index) }
1083 }
1084
1085 fn vertex_attrib_pointer_f32(
1086 &self,
1087 index: GLuint,
1088 size: GLint,
1089 normalized: bool,
1090 stride: GLsizei,
1091 offset: GLuint,
1092 ) {
1093 unsafe {
1094 self.ffi_gl_.VertexAttribPointer(
1095 index,
1096 size,
1097 ffi::FLOAT,
1098 normalized as GLboolean,
1099 stride,
1100 offset as *const GLvoid,
1101 )
1102 }
1103 }
1104
1105 fn vertex_attrib_pointer(
1106 &self,
1107 index: GLuint,
1108 size: GLint,
1109 type_: GLenum,
1110 normalized: bool,
1111 stride: GLsizei,
1112 offset: GLuint,
1113 ) {
1114 unsafe {
1115 self.ffi_gl_.VertexAttribPointer(
1116 index,
1117 size,
1118 type_,
1119 normalized as GLboolean,
1120 stride,
1121 offset as *const GLvoid,
1122 )
1123 }
1124 }
1125
1126 fn vertex_attrib_i_pointer(
1127 &self,
1128 index: GLuint,
1129 size: GLint,
1130 type_: GLenum,
1131 stride: GLsizei,
1132 offset: GLuint,
1133 ) {
1134 unsafe {
1135 self.ffi_gl_
1136 .VertexAttribIPointer(index, size, type_, stride, offset as *const GLvoid)
1137 }
1138 }
1139
1140 fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) {
1141 unsafe { self.ffi_gl_.VertexAttribDivisor(index, divisor) }
1142 }
1143
1144 fn vertex_attrib_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, normalized: bool, relative_offset: GLuint) {
1145 unsafe { self.ffi_gl_.VertexAttribFormat(attrib_index, size, type_, normalized as GLboolean, relative_offset) }
1146 }
1147
1148 fn vertex_attrib_i_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, relative_offset: GLuint) {
1149 unsafe { self.ffi_gl_.VertexAttribIFormat(attrib_index, size, type_, relative_offset) }
1150 }
1151
1152 fn vertex_binding_divisor(&self, binding_index: GLuint, divisor: GLuint) {
1153 unsafe { self.ffi_gl_.VertexBindingDivisor(binding_index, divisor) }
1154 }
1155
1156 fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
1157 unsafe {
1158 self.ffi_gl_.Viewport(x, y, width, height);
1159 }
1160 }
1161
1162 fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
1163 unsafe {
1164 self.ffi_gl_.Scissor(x, y, width, height);
1165 }
1166 }
1167
1168 fn line_width(&self, width: GLfloat) {
1169 unsafe {
1170 self.ffi_gl_.LineWidth(width);
1171 }
1172 }
1173
1174 fn use_program(&self, program: GLuint) {
1175 unsafe {
1176 self.ffi_gl_.UseProgram(program);
1177 }
1178 }
1179
1180 fn validate_program(&self, program: GLuint) {
1181 unsafe {
1182 self.ffi_gl_.ValidateProgram(program);
1183 }
1184 }
1185
1186 fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) {
1187 unsafe {
1188 return self.ffi_gl_.DrawArrays(mode, first, count);
1189 }
1190 }
1191
1192 fn draw_arrays_instanced(
1193 &self,
1194 mode: GLenum,
1195 first: GLint,
1196 count: GLsizei,
1197 primcount: GLsizei,
1198 ) {
1199 unsafe {
1200 return self
1201 .ffi_gl_
1202 .DrawArraysInstanced(mode, first, count, primcount);
1203 }
1204 }
1205
1206 fn draw_elements(
1207 &self,
1208 mode: GLenum,
1209 count: GLsizei,
1210 element_type: GLenum,
1211 indices_offset: GLuint,
1212 ) {
1213 unsafe {
1214 return self.ffi_gl_.DrawElements(
1215 mode,
1216 count,
1217 element_type,
1218 indices_offset as *const c_void,
1219 );
1220 }
1221 }
1222
1223 fn draw_elements_instanced(
1224 &self,
1225 mode: GLenum,
1226 count: GLsizei,
1227 element_type: GLenum,
1228 indices_offset: GLuint,
1229 primcount: GLsizei,
1230 ) {
1231 unsafe {
1232 return self.ffi_gl_.DrawElementsInstanced(
1233 mode,
1234 count,
1235 element_type,
1236 indices_offset as *const c_void,
1237 primcount,
1238 );
1239 }
1240 }
1241
1242 fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) {
1243 unsafe {
1244 self.ffi_gl_.BlendColor(r, g, b, a);
1245 }
1246 }
1247
1248 fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) {
1249 unsafe {
1250 self.ffi_gl_.BlendFunc(sfactor, dfactor);
1251 }
1252 }
1253
1254 fn blend_func_separate(
1255 &self,
1256 src_rgb: GLenum,
1257 dest_rgb: GLenum,
1258 src_alpha: GLenum,
1259 dest_alpha: GLenum,
1260 ) {
1261 unsafe {
1262 self.ffi_gl_
1263 .BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha);
1264 }
1265 }
1266
1267 fn blend_equation(&self, mode: GLenum) {
1268 unsafe {
1269 self.ffi_gl_.BlendEquation(mode);
1270 }
1271 }
1272
1273 fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) {
1274 unsafe {
1275 self.ffi_gl_.BlendEquationSeparate(mode_rgb, mode_alpha);
1276 }
1277 }
1278
1279 fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
1280 unsafe {
1281 self.ffi_gl_.ColorMask(
1282 r as GLboolean,
1283 g as GLboolean,
1284 b as GLboolean,
1285 a as GLboolean,
1286 );
1287 }
1288 }
1289
1290 fn cull_face(&self, mode: GLenum) {
1291 unsafe {
1292 self.ffi_gl_.CullFace(mode);
1293 }
1294 }
1295
1296 fn front_face(&self, mode: GLenum) {
1297 unsafe {
1298 self.ffi_gl_.FrontFace(mode);
1299 }
1300 }
1301
1302 fn enable(&self, cap: GLenum) {
1303 unsafe {
1304 self.ffi_gl_.Enable(cap);
1305 }
1306 }
1307
1308 fn disable(&self, cap: GLenum) {
1309 unsafe {
1310 self.ffi_gl_.Disable(cap);
1311 }
1312 }
1313
1314 fn hint(&self, param_name: GLenum, param_val: GLenum) {
1315 unsafe {
1316 self.ffi_gl_.Hint(param_name, param_val);
1317 }
1318 }
1319
1320 fn is_enabled(&self, cap: GLenum) -> GLboolean {
1321 unsafe { self.ffi_gl_.IsEnabled(cap) }
1322 }
1323
1324 fn is_shader(&self, shader: GLuint) -> GLboolean {
1325 unsafe { self.ffi_gl_.IsShader(shader) }
1326 }
1327
1328 fn is_texture(&self, texture: GLenum) -> GLboolean {
1329 unsafe { self.ffi_gl_.IsTexture(texture) }
1330 }
1331
1332 fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean {
1333 unsafe { self.ffi_gl_.IsFramebuffer(framebuffer) }
1334 }
1335
1336 fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean {
1337 unsafe { self.ffi_gl_.IsRenderbuffer(renderbuffer) }
1338 }
1339
1340 fn check_frame_buffer_status(&self, target: GLenum) -> GLenum {
1341 unsafe { self.ffi_gl_.CheckFramebufferStatus(target) }
1342 }
1343
1344 fn enable_vertex_attrib_array(&self, index: GLuint) {
1345 unsafe {
1346 self.ffi_gl_.EnableVertexAttribArray(index);
1347 }
1348 }
1349
1350 fn disable_vertex_attrib_array(&self, index: GLuint) {
1351 unsafe {
1352 self.ffi_gl_.DisableVertexAttribArray(index);
1353 }
1354 }
1355
1356 fn uniform_1f(&self, location: GLint, v0: GLfloat) {
1357 unsafe {
1358 self.ffi_gl_.Uniform1f(location, v0);
1359 }
1360 }
1361
1362 fn uniform_1fv(&self, location: GLint, values: &[f32]) {
1363 unsafe {
1364 self.ffi_gl_
1365 .Uniform1fv(location, values.len() as GLsizei, values.as_ptr());
1366 }
1367 }
1368
1369 fn uniform_1i(&self, location: GLint, v0: GLint) {
1370 unsafe {
1371 self.ffi_gl_.Uniform1i(location, v0);
1372 }
1373 }
1374
1375 fn uniform_1iv(&self, location: GLint, values: &[i32]) {
1376 unsafe {
1377 self.ffi_gl_
1378 .Uniform1iv(location, values.len() as GLsizei, values.as_ptr());
1379 }
1380 }
1381
1382 fn uniform_1ui(&self, location: GLint, v0: GLuint) {
1383 unsafe {
1384 self.ffi_gl_.Uniform1ui(location, v0);
1385 }
1386 }
1387
1388 fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) {
1389 unsafe {
1390 self.ffi_gl_.Uniform2f(location, v0, v1);
1391 }
1392 }
1393
1394 fn uniform_2fv(&self, location: GLint, values: &[f32]) {
1395 unsafe {
1396 self.ffi_gl_
1397 .Uniform2fv(location, (values.len() / 2) as GLsizei, values.as_ptr());
1398 }
1399 }
1400
1401 fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) {
1402 unsafe {
1403 self.ffi_gl_.Uniform2i(location, v0, v1);
1404 }
1405 }
1406
1407 fn uniform_2iv(&self, location: GLint, values: &[i32]) {
1408 unsafe {
1409 self.ffi_gl_
1410 .Uniform2iv(location, (values.len() / 2) as GLsizei, values.as_ptr());
1411 }
1412 }
1413
1414 fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) {
1415 unsafe {
1416 self.ffi_gl_.Uniform2ui(location, v0, v1);
1417 }
1418 }
1419
1420 fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
1421 unsafe {
1422 self.ffi_gl_.Uniform3f(location, v0, v1, v2);
1423 }
1424 }
1425
1426 fn uniform_3fv(&self, location: GLint, values: &[f32]) {
1427 unsafe {
1428 self.ffi_gl_
1429 .Uniform3fv(location, (values.len() / 3) as GLsizei, values.as_ptr());
1430 }
1431 }
1432
1433 fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) {
1434 unsafe {
1435 self.ffi_gl_.Uniform3i(location, v0, v1, v2);
1436 }
1437 }
1438
1439 fn uniform_3iv(&self, location: GLint, values: &[i32]) {
1440 unsafe {
1441 self.ffi_gl_
1442 .Uniform3iv(location, (values.len() / 3) as GLsizei, values.as_ptr());
1443 }
1444 }
1445
1446 fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
1447 unsafe {
1448 self.ffi_gl_.Uniform3ui(location, v0, v1, v2);
1449 }
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 fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
1472 unsafe {
1473 self.ffi_gl_.Uniform4ui(location, x, y, z, w);
1474 }
1475 }
1476
1477 fn uniform_4fv(&self, location: GLint, values: &[f32]) {
1478 unsafe {
1479 self.ffi_gl_
1480 .Uniform4fv(location, (values.len() / 4) as GLsizei, values.as_ptr());
1481 }
1482 }
1483
1484 fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1485 unsafe {
1486 self.ffi_gl_.UniformMatrix2fv(
1487 location,
1488 (value.len() / 4) as GLsizei,
1489 transpose as GLboolean,
1490 value.as_ptr(),
1491 );
1492 }
1493 }
1494
1495 fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1496 unsafe {
1497 self.ffi_gl_.UniformMatrix3fv(
1498 location,
1499 (value.len() / 9) as GLsizei,
1500 transpose as GLboolean,
1501 value.as_ptr(),
1502 );
1503 }
1504 }
1505
1506 fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]) {
1507 unsafe {
1508 self.ffi_gl_.UniformMatrix4fv(
1509 location,
1510 (value.len() / 16) as GLsizei,
1511 transpose as GLboolean,
1512 value.as_ptr(),
1513 );
1514 }
1515 }
1516
1517 fn depth_mask(&self, flag: bool) {
1518 unsafe {
1519 self.ffi_gl_.DepthMask(flag as GLboolean);
1520 }
1521 }
1522
1523 fn depth_range(&self, near: f64, far: f64) {
1524 unsafe {
1525 self.ffi_gl_.DepthRange(near as GLclampd, far as GLclampd);
1526 }
1527 }
1528
1529 fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1530 let mut buf_size = [0];
1531 unsafe {
1532 self.get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH, &mut buf_size);
1533 }
1534 let mut name = vec![0u8; buf_size[0] as usize];
1535 let mut length = 0 as GLsizei;
1536 let mut size = 0 as i32;
1537 let mut type_ = 0 as u32;
1538 unsafe {
1539 self.ffi_gl_.GetActiveAttrib(
1540 program,
1541 index,
1542 buf_size[0],
1543 &mut length,
1544 &mut size,
1545 &mut type_,
1546 name.as_mut_ptr() as *mut GLchar,
1547 );
1548 }
1549 name.truncate(if length > 0 { length as usize } else { 0 });
1550 (size, type_, String::from_utf8(name).unwrap())
1551 }
1552
1553 fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
1554 let mut buf_size = [0];
1555 unsafe {
1556 self.get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH, &mut buf_size);
1557 }
1558 let mut name = vec![0 as u8; buf_size[0] as usize];
1559 let mut length: GLsizei = 0;
1560 let mut size: i32 = 0;
1561 let mut type_: u32 = 0;
1562
1563 unsafe {
1564 self.ffi_gl_.GetActiveUniform(
1565 program,
1566 index,
1567 buf_size[0],
1568 &mut length,
1569 &mut size,
1570 &mut type_,
1571 name.as_mut_ptr() as *mut GLchar,
1572 );
1573 }
1574
1575 name.truncate(if length > 0 { length as usize } else { 0 });
1576
1577 (size, type_, String::from_utf8(name).unwrap())
1578 }
1579
1580 fn get_active_uniforms_iv(
1581 &self,
1582 program: GLuint,
1583 indices: Vec<GLuint>,
1584 pname: GLenum,
1585 ) -> Vec<GLint> {
1586 let mut result = Vec::with_capacity(indices.len());
1587 unsafe {
1588 result.set_len(indices.len());
1589 self.ffi_gl_.GetActiveUniformsiv(
1590 program,
1591 indices.len() as GLsizei,
1592 indices.as_ptr(),
1593 pname,
1594 result.as_mut_ptr(),
1595 );
1596 }
1597 result
1598 }
1599
1600 fn get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint {
1601 let mut result = 0;
1602 unsafe {
1603 self.ffi_gl_
1604 .GetActiveUniformBlockiv(program, index, pname, &mut result);
1605 }
1606 result
1607 }
1608
1609 fn get_active_uniform_block_iv(
1610 &self,
1611 program: GLuint,
1612 index: GLuint,
1613 pname: GLenum,
1614 ) -> Vec<GLint> {
1615 let count =
1616 self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_ACTIVE_UNIFORMS);
1617 let mut result = Vec::with_capacity(count as usize);
1618 unsafe {
1619 result.set_len(count as usize);
1620 self.ffi_gl_
1621 .GetActiveUniformBlockiv(program, index, pname, result.as_mut_ptr());
1622 }
1623 result
1624 }
1625
1626 fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String {
1627 let buf_size =
1628 self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_NAME_LENGTH);
1629 let mut name = vec![0 as u8; buf_size as usize];
1630 let mut length: GLsizei = 0;
1631 unsafe {
1632 self.ffi_gl_.GetActiveUniformBlockName(
1633 program,
1634 index,
1635 buf_size,
1636 &mut length,
1637 name.as_mut_ptr() as *mut GLchar,
1638 );
1639 }
1640 name.truncate(if length > 0 { length as usize } else { 0 });
1641
1642 String::from_utf8(name).unwrap()
1643 }
1644
1645 fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int {
1646 let name = CString::new(name).unwrap();
1647 unsafe { self.ffi_gl_.GetAttribLocation(program, name.as_ptr()) }
1648 }
1649
1650 fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int {
1651 let name = CString::new(name).unwrap();
1652 unsafe { self.ffi_gl_.GetFragDataLocation(program, name.as_ptr()) }
1653 }
1654
1655 fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int {
1656 let name = CString::new(name).unwrap();
1657 unsafe { self.ffi_gl_.GetUniformLocation(program, name.as_ptr()) }
1658 }
1659
1660 fn get_program_info_log(&self, program: GLuint) -> String {
1661 let mut max_len = [0];
1662 unsafe {
1663 self.get_program_iv(program, ffi::INFO_LOG_LENGTH, &mut max_len);
1664 }
1665 if max_len[0] == 0 {
1666 return String::new();
1667 }
1668 let mut result = vec![0u8; max_len[0] as usize];
1669 let mut result_len = 0 as GLsizei;
1670 unsafe {
1671 self.ffi_gl_.GetProgramInfoLog(
1672 program,
1673 max_len[0] as GLsizei,
1674 &mut result_len,
1675 result.as_mut_ptr() as *mut GLchar,
1676 );
1677 }
1678 result.truncate(if result_len > 0 {
1679 result_len as usize
1680 } else {
1681 0
1682 });
1683 String::from_utf8(result).unwrap()
1684 }
1685
1686 #[inline]
1687 unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]) {
1688 assert!(!result.is_empty());
1689 self.ffi_gl_
1690 .GetProgramiv(program, pname, result.as_mut_ptr());
1691 }
1692
1693 fn get_program_binary(&self, program: GLuint) -> (Vec<u8>, GLenum) {
1694 if !self.ffi_gl_.GetProgramBinary.is_loaded() {
1695 return (Vec::new(), NONE);
1696 }
1697 let mut len = [0];
1698 unsafe {
1699 self.get_program_iv(program, ffi::PROGRAM_BINARY_LENGTH, &mut len);
1700 }
1701 if len[0] <= 0 {
1702 return (Vec::new(), NONE);
1703 }
1704 let mut binary: Vec<u8> = Vec::with_capacity(len[0] as usize);
1705 let mut format = NONE;
1706 let mut out_len = 0;
1707 unsafe {
1708 binary.set_len(len[0] as usize);
1709 self.ffi_gl_.GetProgramBinary(
1710 program,
1711 len[0],
1712 &mut out_len as *mut GLsizei,
1713 &mut format,
1714 binary.as_mut_ptr() as *mut c_void,
1715 );
1716 }
1717 if len[0] != out_len {
1718 return (Vec::new(), NONE);
1719 }
1720
1721 (binary, format)
1722 }
1723
1724 fn program_binary(&self, program: GLuint, format: GLenum, binary: &[u8]) {
1725 if !self.ffi_gl_.ProgramBinary.is_loaded() {
1726 return;
1727 }
1728 unsafe {
1729 self.ffi_gl_.ProgramBinary(
1730 program,
1731 format,
1732 binary.as_ptr() as *const c_void,
1733 binary.len() as GLsizei,
1734 );
1735 }
1736 }
1737
1738 fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint) {
1739 if !self.ffi_gl_.ProgramParameteri.is_loaded() {
1740 return;
1741 }
1742 unsafe {
1743 self.ffi_gl_.ProgramParameteri(program, pname, value);
1744 }
1745 }
1746
1747 #[inline]
1748 unsafe fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint]) {
1749 assert!(!result.is_empty());
1750 self.ffi_gl_
1751 .GetVertexAttribiv(index, pname, result.as_mut_ptr());
1752 }
1753
1754 #[inline]
1755 unsafe fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat]) {
1756 assert!(!result.is_empty());
1757 self.ffi_gl_
1758 .GetVertexAttribfv(index, pname, result.as_mut_ptr());
1759 }
1760
1761 fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr {
1762 let mut result = 0 as *mut GLvoid;
1763 unsafe {
1764 self.ffi_gl_
1765 .GetVertexAttribPointerv(index, pname, &mut result)
1766 }
1767 result as GLsizeiptr
1768 }
1769
1770 fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint {
1771 let mut result = 0 as GLint;
1772 unsafe {
1773 self.ffi_gl_
1774 .GetBufferParameteriv(target, pname, &mut result);
1775 }
1776 result
1777 }
1778
1779 fn get_shader_info_log(&self, shader: GLuint) -> String {
1780 let mut max_len = [0];
1781 unsafe {
1782 self.get_shader_iv(shader, ffi::INFO_LOG_LENGTH, &mut max_len);
1783 }
1784 if max_len[0] == 0 {
1785 return String::new();
1786 }
1787 let mut result = vec![0u8; max_len[0] as usize];
1788 let mut result_len = 0 as GLsizei;
1789 unsafe {
1790 self.ffi_gl_.GetShaderInfoLog(
1791 shader,
1792 max_len[0] as GLsizei,
1793 &mut result_len,
1794 result.as_mut_ptr() as *mut GLchar,
1795 );
1796 }
1797 result.truncate(if result_len > 0 {
1798 result_len as usize
1799 } else {
1800 0
1801 });
1802 String::from_utf8(result).unwrap()
1803 }
1804
1805 fn get_string(&self, which: GLenum) -> String {
1806 unsafe {
1807 let llstr = self.ffi_gl_.GetString(which);
1808 if !llstr.is_null() {
1809 return str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes())
1810 .to_string();
1811 } else {
1812 return "".to_string();
1813 }
1814 }
1815 }
1816
1817 fn get_string_i(&self, which: GLenum, index: GLuint) -> String {
1818 unsafe {
1819 let llstr = self.ffi_gl_.GetStringi(which, index);
1820 if !llstr.is_null() {
1821 str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes())
1822 .to_string()
1823 } else {
1824 "".to_string()
1825 }
1826 }
1827 }
1828
1829 unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]) {
1830 assert!(!result.is_empty());
1831 self.ffi_gl_.GetShaderiv(shader, pname, result.as_mut_ptr());
1832 }
1833
1834 fn get_shader_precision_format(
1835 &self,
1836 _shader_type: GLuint,
1837 precision_type: GLuint,
1838 ) -> (GLint, GLint, GLint) {
1839 match precision_type {
1842 ffi::LOW_FLOAT | ffi::MEDIUM_FLOAT | ffi::HIGH_FLOAT => {
1843 (127, 127, 23)
1847 }
1848 ffi::LOW_INT | ffi::MEDIUM_INT | ffi::HIGH_INT => {
1849 (24, 24, 0)
1853 }
1854 _ => (0, 0, 0),
1855 }
1856 }
1857
1858 fn compile_shader(&self, shader: GLuint) {
1859 unsafe {
1860 self.ffi_gl_.CompileShader(shader);
1861 }
1862 }
1863
1864 fn create_program(&self) -> GLuint {
1865 unsafe {
1866 return self.ffi_gl_.CreateProgram();
1867 }
1868 }
1869
1870 fn delete_program(&self, program: GLuint) {
1871 unsafe {
1872 self.ffi_gl_.DeleteProgram(program);
1873 }
1874 }
1875
1876 fn create_shader(&self, shader_type: GLenum) -> GLuint {
1877 unsafe {
1878 return self.ffi_gl_.CreateShader(shader_type);
1879 }
1880 }
1881
1882 fn delete_shader(&self, shader: GLuint) {
1883 unsafe {
1884 self.ffi_gl_.DeleteShader(shader);
1885 }
1886 }
1887
1888 fn detach_shader(&self, program: GLuint, shader: GLuint) {
1889 unsafe {
1890 self.ffi_gl_.DetachShader(program, shader);
1891 }
1892 }
1893
1894 fn link_program(&self, program: GLuint) {
1895 unsafe {
1896 return self.ffi_gl_.LinkProgram(program);
1897 }
1898 }
1899
1900 fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) {
1901 unsafe {
1902 self.ffi_gl_.ClearColor(r, g, b, a);
1903 }
1904 }
1905
1906 fn clear(&self, buffer_mask: GLbitfield) {
1907 unsafe {
1908 self.ffi_gl_.Clear(buffer_mask);
1909 }
1910 }
1911
1912 fn clear_depth(&self, depth: f64) {
1913 unsafe {
1914 self.ffi_gl_.ClearDepth(depth as GLclampd);
1915 }
1916 }
1917
1918 fn clear_stencil(&self, s: GLint) {
1919 unsafe {
1920 self.ffi_gl_.ClearStencil(s);
1921 }
1922 }
1923
1924 fn flush(&self) {
1925 unsafe {
1926 self.ffi_gl_.Flush();
1927 }
1928 }
1929
1930 fn finish(&self) {
1931 unsafe {
1932 self.ffi_gl_.Finish();
1933 }
1934 }
1935
1936 fn get_error(&self) -> GLenum {
1937 unsafe { self.ffi_gl_.GetError() }
1938 }
1939
1940 fn stencil_mask(&self, mask: GLuint) {
1941 unsafe { self.ffi_gl_.StencilMask(mask) }
1942 }
1943
1944 fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) {
1945 unsafe { self.ffi_gl_.StencilMaskSeparate(face, mask) }
1946 }
1947
1948 fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint) {
1949 unsafe { self.ffi_gl_.StencilFunc(func, ref_, mask) }
1950 }
1951
1952 fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint) {
1953 unsafe { self.ffi_gl_.StencilFuncSeparate(face, func, ref_, mask) }
1954 }
1955
1956 fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
1957 unsafe { self.ffi_gl_.StencilOp(sfail, dpfail, dppass) }
1958 }
1959
1960 fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
1961 unsafe { self.ffi_gl_.StencilOpSeparate(face, sfail, dpfail, dppass) }
1962 }
1963
1964 #[allow(unused_variables)]
1965 fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
1966 panic!("not supported")
1967 }
1968
1969 #[allow(unused_variables)]
1970 fn egl_image_target_renderbuffer_storage_oes(&self, target: GLenum, image: GLeglImageOES) {
1971 panic!("not supported")
1972 }
1973
1974 fn generate_mipmap(&self, target: GLenum) {
1975 unsafe { self.ffi_gl_.GenerateMipmap(target) }
1976 }
1977
1978 fn insert_event_marker_ext(&self, message: &str) {
1979 if self.ffi_gl_.InsertEventMarkerEXT.is_loaded() {
1980 unsafe {
1981 self.ffi_gl_
1982 .InsertEventMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
1983 }
1984 }
1985 }
1986
1987 fn push_group_marker_ext(&self, message: &str) {
1988 if self.ffi_gl_.PushGroupMarkerEXT.is_loaded() {
1989 unsafe {
1990 self.ffi_gl_
1991 .PushGroupMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
1992 }
1993 }
1994 }
1995
1996 fn pop_group_marker_ext(&self) {
1997 if self.ffi_gl_.PopGroupMarkerEXT.is_loaded() {
1998 unsafe {
1999 self.ffi_gl_.PopGroupMarkerEXT();
2000 }
2001 }
2002 }
2003
2004 fn debug_message_insert_khr(&self, source: GLenum, type_: GLenum, id: GLuint, severity: GLenum, message: &str) {
2005 if self.ffi_gl_.DebugMessageInsertKHR.is_loaded() {
2006 unsafe {
2007 self.ffi_gl_
2008 .DebugMessageInsertKHR(source, type_, id, severity, message.len() as GLsizei, message.as_ptr() as *const _);
2009 }
2010 }
2011 }
2012
2013 fn push_debug_group_khr(&self, source: GLenum, id: GLuint, message: &str) {
2014 if self.ffi_gl_.PushDebugGroupKHR.is_loaded() {
2015 unsafe {
2016 self.ffi_gl_
2017 .PushDebugGroupKHR(source, id, message.len() as GLsizei, message.as_ptr() as *const _);
2018 }
2019 }
2020 }
2021
2022 fn pop_debug_group_khr(&self) {
2023 if self.ffi_gl_.PopDebugGroupKHR.is_loaded() {
2024 unsafe {
2025 self.ffi_gl_.PopDebugGroupKHR();
2026 }
2027 }
2028 }
2029
2030 fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync {
2031 unsafe { self.ffi_gl_.FenceSync(condition, flags) as *const _ }
2032 }
2033
2034 fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) -> GLenum {
2035 unsafe {
2036 self.ffi_gl_
2037 .ClientWaitSync(sync as *const _, flags, timeout)
2038 }
2039 }
2040
2041 fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) {
2042 unsafe {
2043 self.ffi_gl_.WaitSync(sync as *const _, flags, timeout);
2044 }
2045 }
2046
2047 fn texture_range_apple(&self, target: GLenum, data: &[u8]) {
2048 unsafe {
2049 self.ffi_gl_.TextureRangeAPPLE(
2050 target,
2051 data.len() as GLsizei,
2052 data.as_ptr() as *const c_void,
2053 );
2054 }
2055 }
2056
2057 fn delete_sync(&self, sync: GLsync) {
2058 unsafe {
2059 self.ffi_gl_.DeleteSync(sync as *const _);
2060 }
2061 }
2062
2063 fn gen_fences_apple(&self, n: GLsizei) -> Vec<GLuint> {
2064 let mut result = vec![0 as GLuint; n as usize];
2065 unsafe {
2066 self.ffi_gl_.GenFencesAPPLE(n, result.as_mut_ptr());
2067 }
2068 result
2069 }
2070
2071 fn delete_fences_apple(&self, fences: &[GLuint]) {
2072 unsafe {
2073 self.ffi_gl_
2074 .DeleteFencesAPPLE(fences.len() as GLsizei, fences.as_ptr());
2075 }
2076 }
2077
2078 fn set_fence_apple(&self, fence: GLuint) {
2079 unsafe {
2080 self.ffi_gl_.SetFenceAPPLE(fence);
2081 }
2082 }
2083
2084 fn finish_fence_apple(&self, fence: GLuint) {
2085 unsafe {
2086 self.ffi_gl_.FinishFenceAPPLE(fence);
2087 }
2088 }
2089
2090 fn test_fence_apple(&self, fence: GLuint) {
2091 unsafe {
2092 self.ffi_gl_.TestFenceAPPLE(fence);
2093 }
2094 }
2095
2096 fn test_object_apple(&self, object: GLenum, name: GLuint) -> GLboolean {
2097 unsafe {
2098 self.ffi_gl_.TestObjectAPPLE(object, name)
2099 }
2100 }
2101
2102 fn finish_object_apple(&self, object: GLenum, name: GLuint) {
2103 unsafe {
2104 self.ffi_gl_.FinishObjectAPPLE(object, name as GLint);
2106 }
2107 }
2108
2109 fn bind_frag_data_location_indexed(
2111 &self,
2112 program: GLuint,
2113 color_number: GLuint,
2114 index: GLuint,
2115 name: &str,
2116 ) {
2117 if !self.ffi_gl_.BindFragDataLocationIndexed.is_loaded() {
2118 return;
2119 }
2120
2121 let c_string = CString::new(name).unwrap();
2122
2123 unsafe {
2124 self.ffi_gl_.BindFragDataLocationIndexed(
2125 program,
2126 color_number,
2127 index,
2128 c_string.as_ptr(),
2129 )
2130 }
2131 }
2132
2133 fn get_frag_data_index(&self, program: GLuint, name: &str) -> GLint {
2134 if !self.ffi_gl_.GetFragDataIndex.is_loaded() {
2135 return -1;
2136 }
2137
2138 let c_string = CString::new(name).unwrap();
2139
2140 unsafe { self.ffi_gl_.GetFragDataIndex(program, c_string.as_ptr()) }
2141 }
2142
2143 fn get_debug_messages(&self) -> Vec<DebugMessage> {
2145 if !self.ffi_gl_.GetDebugMessageLog.is_loaded() {
2146 return Vec::new();
2147 }
2148
2149 let mut max_message_len = 0;
2150 unsafe {
2151 self.ffi_gl_
2152 .GetIntegerv(ffi::MAX_DEBUG_MESSAGE_LENGTH, &mut max_message_len)
2153 }
2154
2155 let mut output = Vec::new();
2156 const CAPACITY: usize = 5;
2157
2158 let mut msg_data = vec![0u8; CAPACITY * max_message_len as usize];
2159 let mut sources = [0 as GLenum; CAPACITY];
2160 let mut types = [0 as GLenum; CAPACITY];
2161 let mut severities = [0 as GLenum; CAPACITY];
2162 let mut ids = [0 as GLuint; CAPACITY];
2163 let mut lengths = [0 as GLsizei; CAPACITY];
2164
2165 loop {
2166 let count = unsafe {
2167 self.ffi_gl_.GetDebugMessageLog(
2171 (CAPACITY - 1) as _,
2172 msg_data.len() as _,
2173 sources.as_mut_ptr(),
2174 types.as_mut_ptr(),
2175 ids.as_mut_ptr(),
2176 severities.as_mut_ptr(),
2177 lengths.as_mut_ptr(),
2178 msg_data.as_mut_ptr() as *mut _,
2179 )
2180 };
2181 let count = CAPACITY.min(count as usize);
2182
2183 let mut offset = 0;
2184 output.extend((0..count).map(|i| {
2185 let len = lengths[i] as usize;
2186 let slice = &msg_data[offset..offset + len];
2187 offset += len;
2188 DebugMessage {
2189 message: String::from_utf8_lossy(slice).to_string(),
2190 source: sources[i],
2191 ty: types[i],
2192 id: ids[i],
2193 severity: severities[i],
2194 }
2195 }));
2196
2197 if (count as usize) < CAPACITY {
2198 return output;
2199 }
2200 }
2201 }
2202
2203 fn provoking_vertex_angle(&self, _mode: GLenum) {
2204 unimplemented!("This extension is GLES only");
2205 }
2206
2207 fn blend_barrier_khr(&self) {
2209 if self.ffi_gl_.BlendBarrierKHR.is_loaded() {
2210 unsafe {
2211 self.ffi_gl_.BlendBarrierKHR();
2212 }
2213 }
2214 }
2215
2216 fn copy_texture_chromium(&self,
2218 _source_id: GLuint, _source_level: GLint,
2219 _dest_target: GLenum, _dest_id: GLuint, _dest_level: GLint,
2220 _internal_format: GLint, _dest_type: GLenum,
2221 _unpack_flip_y: GLboolean, _unpack_premultiply_alpha: GLboolean, _unpack_unmultiply_alpha: GLboolean)
2222 {
2223 unimplemented!("This extension is GLES only");
2224 }
2225 fn copy_sub_texture_chromium(&self,
2226 _source_id: GLuint, _source_level: GLint,
2227 _dest_target: GLenum, _dest_id: GLuint, _dest_level: GLint,
2228 _x_offset: GLint, _y_offset: GLint, _x: GLint, _y: GLint, _width: GLsizei, _height: GLsizei,
2229 _unpack_flip_y: GLboolean, _unpack_premultiply_alpha: GLboolean, _unpack_unmultiply_alpha: GLboolean)
2230 {
2231 unimplemented!("This extension is GLES only");
2232 }
2233
2234 fn copy_texture_3d_angle(
2236 &self,
2237 _source_id: GLuint,
2238 _source_level: GLint,
2239 _dest_target: GLenum,
2240 _dest_id: GLuint,
2241 _dest_level: GLint,
2242 _internal_format: GLint,
2243 _dest_type: GLenum,
2244 _unpack_flip_y: GLboolean,
2245 _unpack_premultiply_alpha: GLboolean,
2246 _unpack_unmultiply_alpha: GLboolean,
2247 ) {
2248 unimplemented!("This extension is ANGLE only");
2249 }
2250
2251 fn copy_sub_texture_3d_angle(
2252 &self,
2253 _source_id: GLuint,
2254 _source_level: GLint,
2255 _dest_target: GLenum,
2256 _dest_id: GLuint,
2257 _dest_level: GLint,
2258 _x_offset: GLint,
2259 _y_offset: GLint,
2260 _z_offset: GLint,
2261 _x: GLint,
2262 _y: GLint,
2263 _z: GLint,
2264 _width: GLsizei,
2265 _height: GLsizei,
2266 _depth: GLsizei,
2267 _unpack_flip_y: GLboolean,
2268 _unpack_premultiply_alpha: GLboolean,
2269 _unpack_unmultiply_alpha: GLboolean,
2270 ) {
2271 unimplemented!("This extension is ANGLE only");
2272 }
2273
2274 fn buffer_storage(
2275 &self,
2276 target: GLenum,
2277 size: GLsizeiptr,
2278 data: *const GLvoid,
2279 flags: GLbitfield,
2280 ) {
2281 unsafe {
2282 self.ffi_gl_.BufferStorage(target, size, data, flags);
2283 }
2284 }
2285
2286 fn flush_mapped_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr) {
2287 unsafe {
2288 self.ffi_gl_.FlushMappedBufferRange(target, offset, length);
2289 }
2290 }
2291
2292 fn start_tiling_qcom(&self, _x: GLuint, _y: GLuint, _width: GLuint, _height: GLuint, _preserve_mask: GLbitfield) {
2293 }
2294
2295 fn end_tiling_qcom(&self, _preserve_mask: GLbitfield) {
2296 }
2297}