1use super::*;
2use crate::{gl46 as native_gl, version::Version};
3use std::ffi::CStr;
4use std::ptr;
5use std::{collections::HashSet, ffi::CString, num::NonZeroU32};
6
7#[derive(Default)]
8struct Constants {
9 max_label_length: i32,
10}
11
12struct DebugCallbackRawPtr {
19 callback: *mut std::os::raw::c_void,
20}
21
22unsafe impl Send for DebugCallbackRawPtr {}
23unsafe impl Sync for DebugCallbackRawPtr {}
24
25impl Drop for DebugCallbackRawPtr {
26 fn drop(&mut self) {
27 unsafe {
28 let thin_ptr = Box::from_raw(self.callback as *mut DebugCallback);
30 let callback = *thin_ptr;
31 drop(callback);
32 }
33 }
34}
35
36pub struct Context {
37 raw: native_gl::GlFns,
38 extensions: HashSet<String>,
39 constants: Constants,
40 version: Version,
41 debug_callback: Option<DebugCallbackRawPtr>,
42}
43
44impl Context {
45 pub unsafe fn from_loader_function_cstr<F>(mut loader_function: F) -> Self
46 where
47 F: FnMut(&CStr) -> *const std::os::raw::c_void,
48 {
49 let raw: native_gl::GlFns =
50 native_gl::GlFns::load_with(|p: *const std::os::raw::c_char| {
51 let c_str = std::ffi::CStr::from_ptr(p);
52 loader_function(c_str) as *mut std::os::raw::c_void
53 });
54
55 let raw_string = raw.GetString(VERSION);
57
58 if raw_string.is_null() {
59 panic!("Reading GL_VERSION failed. Make sure there is a valid GL context currently active.")
60 }
61
62 let raw_version = std::ffi::CStr::from_ptr(raw_string as *const native_gl::GLchar)
63 .to_str()
64 .unwrap()
65 .to_owned();
66 let version = Version::parse(&raw_version).unwrap();
67
68 let mut context = Self {
70 raw,
71 extensions: HashSet::new(),
72 constants: Constants::default(),
73 version,
74 debug_callback: None,
75 };
76
77 if (context.version >= Version::new(3, 0, None, String::from("")))
79 || (context.version >= Version::new_embedded(3, 0, String::from("")))
80 {
81 let num_extensions = context.get_parameter_i32(NUM_EXTENSIONS);
82 for i in 0..num_extensions {
83 let extension_name = context.get_parameter_indexed_string(EXTENSIONS, i as u32);
84 context.extensions.insert(extension_name);
85 }
86 } else {
87 context.extensions.extend(
89 context
90 .get_parameter_string(EXTENSIONS)
91 .split(' ')
92 .map(|s| s.to_string()),
93 );
94 };
95
96 context.constants.max_label_length = if context.supports_debug() {
99 context.get_parameter_i32(MAX_LABEL_LENGTH)
100 } else {
101 0
102 };
103
104 context
105 }
106
107 pub unsafe fn from_loader_function<F>(mut loader_function: F) -> Self
108 where
109 F: FnMut(&str) -> *const std::os::raw::c_void,
110 {
111 Self::from_loader_function_cstr(move |name| loader_function(name.to_str().unwrap()))
112 }
113
114 #[deprecated = "Use the NativeTexture constructor instead"]
119 pub unsafe fn create_texture_from_gl_name(gl_name: native_gl::GLuint) -> NativeTexture {
120 NativeTexture(non_zero_gl_name(gl_name))
121 }
122
123 #[deprecated = "Use the NativeFramebuffer constructor instead"]
128 pub unsafe fn create_framebuffer_from_gl_name(gl_name: native_gl::GLuint) -> NativeFramebuffer {
129 NativeFramebuffer(non_zero_gl_name(gl_name))
130 }
131
132 unsafe fn get_parameter_gl_name(&self, parameter: u32) -> Option<NonZeroU32> {
133 let value = self.get_parameter_i32(parameter) as u32;
134 if value == 0 {
135 None
136 } else {
137 Some(non_zero_gl_name(value))
138 }
139 }
140}
141
142impl std::fmt::Debug for Context {
143 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
144 write!(f, "Native_GL_Context")
145 }
146}
147
148fn non_zero_gl_name(value: native_gl::GLuint) -> NonZeroU32 {
149 NonZeroU32::new(value as u32).expect("expected non-zero GL name")
150}
151
152#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
153pub struct NativeShader(pub NonZeroU32);
154
155#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
156pub struct NativeProgram(pub NonZeroU32);
157
158#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
159pub struct NativeBuffer(pub NonZeroU32);
160
161#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
162pub struct NativeVertexArray(pub NonZeroU32);
163
164#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
165pub struct NativeTexture(pub NonZeroU32);
166
167#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
168pub struct NativeSampler(pub NonZeroU32);
169
170#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
171pub struct NativeFence(pub native_gl::GLsync);
172
173#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
174pub struct NativeFramebuffer(pub NonZeroU32);
175
176#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
177pub struct NativeRenderbuffer(pub NonZeroU32);
178
179#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
180pub struct NativeQuery(pub NonZeroU32);
181
182#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
183pub struct NativeUniformLocation(pub native_gl::GLuint);
184
185#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
186pub struct NativeTransformFeedback(pub NonZeroU32);
187
188impl crate::__private::Sealed for Context {}
189
190impl HasContext for Context {
191 type Shader = NativeShader;
192 type Program = NativeProgram;
193 type Buffer = NativeBuffer;
194 type VertexArray = NativeVertexArray;
195 type Texture = NativeTexture;
196 type Sampler = NativeSampler;
197 type Fence = NativeFence;
198 type Framebuffer = NativeFramebuffer;
199 type Renderbuffer = NativeRenderbuffer;
200 type Query = NativeQuery;
201 type UniformLocation = NativeUniformLocation;
202 type TransformFeedback = NativeTransformFeedback;
203
204 fn supported_extensions(&self) -> &HashSet<String> {
205 &self.extensions
206 }
207
208 fn supports_debug(&self) -> bool {
209 if self.extensions.contains("GL_KHR_debug") {
210 true
212 } else if self.version.is_embedded {
213 self.version.major == 3 && self.version.minor >= 2
215 } else {
216 self.version.major == 4 && self.version.minor >= 3
218 }
219 }
220
221 fn version(&self) -> &Version {
222 &self.version
223 }
224
225 unsafe fn create_framebuffer(&self) -> Result<Self::Framebuffer, String> {
226 let gl = &self.raw;
227 let mut name = 0;
228 gl.GenFramebuffers(1, &mut name);
229 NonZeroU32::new(name)
230 .map(NativeFramebuffer)
231 .ok_or_else(|| String::from("Unable to create Framebuffer object"))
232 }
233
234 unsafe fn create_named_framebuffer(&self) -> Result<Self::Framebuffer, String> {
235 let gl = &self.raw;
236 let mut name = 0;
237 gl.CreateFramebuffers(1, &mut name);
238 NonZeroU32::new(name)
239 .map(NativeFramebuffer)
240 .ok_or_else(|| String::from("Unable to create Framebuffer object"))
241 }
242
243 unsafe fn is_framebuffer(&self, framebuffer: Self::Framebuffer) -> bool {
244 let gl = &self.raw;
245 gl.IsFramebuffer(framebuffer.0.get()) != 0
246 }
247
248 unsafe fn create_query(&self) -> Result<Self::Query, String> {
249 let gl = &self.raw;
250 let mut name = 0;
251 if gl.GenQueries_is_loaded() {
252 gl.GenQueries(1, &mut name);
253 } else {
254 gl.GenQueriesEXT(1, &mut name);
255 }
256 NonZeroU32::new(name)
257 .map(NativeQuery)
258 .ok_or_else(|| String::from("Unable to create Query object"))
259 }
260
261 unsafe fn create_renderbuffer(&self) -> Result<Self::Renderbuffer, String> {
262 let gl = &self.raw;
263 let mut name = 0;
264 gl.GenRenderbuffers(1, &mut name);
265 NonZeroU32::new(name)
266 .map(NativeRenderbuffer)
267 .ok_or_else(|| String::from("Unable to create Renderbuffer object"))
268 }
269
270 unsafe fn is_renderbuffer(&self, renderbuffer: Self::Renderbuffer) -> bool {
271 let gl = &self.raw;
272 gl.IsRenderbuffer(renderbuffer.0.get()) != 0
273 }
274
275 unsafe fn create_sampler(&self) -> Result<Self::Sampler, String> {
276 let gl = &self.raw;
277 let mut name = 0;
278 gl.GenSamplers(1, &mut name);
279 NonZeroU32::new(name)
280 .map(NativeSampler)
281 .ok_or_else(|| String::from("Unable to create Sampler object"))
282 }
283
284 unsafe fn create_shader(&self, shader_type: u32) -> Result<Self::Shader, String> {
285 let gl = &self.raw;
286 NonZeroU32::new(gl.CreateShader(shader_type as u32))
287 .map(NativeShader)
288 .ok_or_else(|| String::from("Unable to create Shader object"))
289 }
290
291 unsafe fn is_shader(&self, shader: Self::Shader) -> bool {
292 let gl = &self.raw;
293 gl.IsShader(shader.0.get()) != 0
294 }
295
296 unsafe fn create_texture(&self) -> Result<Self::Texture, String> {
297 let gl = &self.raw;
298 let mut name = 0;
299 gl.GenTextures(1, &mut name);
300 NonZeroU32::new(name)
301 .map(NativeTexture)
302 .ok_or_else(|| String::from("Unable to create Texture object"))
303 }
304
305 unsafe fn create_named_texture(&self, target: u32) -> Result<Self::Texture, String> {
306 let gl = &self.raw;
307 let mut name = 0;
308 gl.CreateTextures(target, 1, &mut name);
309 NonZeroU32::new(name)
310 .map(NativeTexture)
311 .ok_or_else(|| String::from("Unable to create Texture object"))
312 }
313
314 unsafe fn is_texture(&self, texture: Self::Texture) -> bool {
315 let gl = &self.raw;
316 gl.IsTexture(texture.0.get()) != 0
317 }
318
319 unsafe fn delete_shader(&self, shader: Self::Shader) {
320 let gl = &self.raw;
321 gl.DeleteShader(shader.0.get());
322 }
323
324 unsafe fn shader_source(&self, shader: Self::Shader, source: &str) {
325 let gl = &self.raw;
326 gl.ShaderSource(
327 shader.0.get(),
328 1,
329 &(source.as_ptr() as *const native_gl::GLchar),
330 &(source.len() as native_gl::GLint),
331 );
332 }
333
334 unsafe fn compile_shader(&self, shader: Self::Shader) {
335 let gl = &self.raw;
336 gl.CompileShader(shader.0.get());
337 }
338
339 unsafe fn get_shader_completion_status(&self, shader: Self::Shader) -> bool {
340 let gl = &self.raw;
341 let mut status = 0;
342 gl.GetShaderiv(shader.0.get(), COMPLETION_STATUS, &mut status);
343 1 == status
344 }
345
346 unsafe fn get_shader_compile_status(&self, shader: Self::Shader) -> bool {
347 let gl = &self.raw;
348 let mut status = 0;
349 gl.GetShaderiv(shader.0.get(), COMPILE_STATUS, &mut status);
350 1 == status
351 }
352
353 unsafe fn get_shader_info_log(&self, shader: Self::Shader) -> String {
354 let gl = &self.raw;
355 let mut length = 0;
356 gl.GetShaderiv(shader.0.get(), INFO_LOG_LENGTH, &mut length);
357 if length > 0 {
358 let mut log = String::with_capacity(length as usize);
359 log.extend(std::iter::repeat('\0').take(length as usize));
360 gl.GetShaderInfoLog(
361 shader.0.get(),
362 length,
363 &mut length,
364 (&log[..]).as_ptr() as *mut native_gl::GLchar,
365 );
366 log.truncate(length as usize);
367 log
368 } else {
369 String::from("")
370 }
371 }
372
373 unsafe fn get_shader_precision_format(
374 &self,
375 shader_type: u32,
376 precision_type: u32,
377 ) -> Option<ShaderPrecisionFormat> {
378 let gl = &self.raw;
379
380 if gl.GetShaderPrecisionFormat_is_loaded() {
381 let mut range = [0, 0];
382 let mut precision = 0;
383 gl.GetShaderPrecisionFormat(
384 shader_type,
385 precision_type,
386 range.as_mut_ptr(),
387 &mut precision,
388 );
389 if range[1] != 0 {
392 return Some(ShaderPrecisionFormat {
393 range_min: range[0],
394 range_max: range[1],
395 precision,
396 });
397 }
398 }
399
400 None
401 }
402
403 unsafe fn get_tex_image(
404 &self,
405 target: u32,
406 level: i32,
407 format: u32,
408 ty: u32,
409 pixels: PixelPackData,
410 ) {
411 let gl = &self.raw;
412 gl.GetTexImage(
413 target,
414 level,
415 format,
416 ty,
417 match pixels {
418 PixelPackData::BufferOffset(offset) => offset as *mut std::ffi::c_void,
419 PixelPackData::Slice(Some(data)) => data.as_mut_ptr() as *mut std::ffi::c_void,
420 PixelPackData::Slice(None) => ptr::null_mut(),
421 },
422 );
423 }
424
425 unsafe fn create_program(&self) -> Result<Self::Program, String> {
426 let gl = &self.raw;
427 NonZeroU32::new(gl.CreateProgram())
428 .map(NativeProgram)
429 .ok_or_else(|| String::from("Unable to create Program object"))
430 }
431
432 unsafe fn is_program(&self, program: Self::Program) -> bool {
433 let gl = &self.raw;
434 gl.IsProgram(program.0.get()) != 0
435 }
436
437 unsafe fn delete_program(&self, program: Self::Program) {
438 let gl = &self.raw;
439 gl.DeleteProgram(program.0.get());
440 }
441
442 unsafe fn attach_shader(&self, program: Self::Program, shader: Self::Shader) {
443 let gl = &self.raw;
444 gl.AttachShader(program.0.get(), shader.0.get());
445 }
446
447 unsafe fn detach_shader(&self, program: Self::Program, shader: Self::Shader) {
448 let gl = &self.raw;
449 gl.DetachShader(program.0.get(), shader.0.get());
450 }
451
452 unsafe fn link_program(&self, program: Self::Program) {
453 let gl = &self.raw;
454 gl.LinkProgram(program.0.get());
455 }
456
457 unsafe fn validate_program(&self, program: Self::Program) {
458 let gl = &self.raw;
459 gl.ValidateProgram(program.0.get());
460 }
461
462 unsafe fn get_program_completion_status(&self, program: Self::Program) -> bool {
463 let gl = &self.raw;
464 let mut status = 0;
465 gl.GetProgramiv(program.0.get(), COMPLETION_STATUS, &mut status);
466 1 == status
467 }
468
469 unsafe fn get_program_link_status(&self, program: Self::Program) -> bool {
470 let gl = &self.raw;
471 let mut status = 0;
472 gl.GetProgramiv(program.0.get(), LINK_STATUS, &mut status);
473 1 == status
474 }
475
476 unsafe fn get_program_validate_status(&self, program: Self::Program) -> bool {
477 let gl = &self.raw;
478 let mut status = 0;
479 gl.GetProgramiv(program.0.get(), VALIDATE_STATUS, &mut status);
480 status == 1
481 }
482
483 unsafe fn get_program_parameter_i32(&self, program: Self::Program, parameter: u32) -> i32 {
484 let gl = &self.raw;
485 let mut value = 0;
486 gl.GetProgramiv(program.0.get(), parameter, &mut value);
487 value
488 }
489
490 unsafe fn get_program_info_log(&self, program: Self::Program) -> String {
491 let gl = &self.raw;
492 let mut length = 0;
493 gl.GetProgramiv(program.0.get(), INFO_LOG_LENGTH, &mut length);
494 if length > 0 {
495 let mut log = String::with_capacity(length as usize);
496 log.extend(std::iter::repeat('\0').take(length as usize));
497 gl.GetProgramInfoLog(
498 program.0.get(),
499 length,
500 &mut length,
501 (&log[..]).as_ptr() as *mut native_gl::GLchar,
502 );
503 log.truncate(length as usize);
504 log
505 } else {
506 String::from("")
507 }
508 }
509
510 unsafe fn get_program_resource_i32(
511 &self,
512 program: Self::Program,
513 interface: u32,
514 index: u32,
515 properties: &[u32],
516 ) -> Vec<i32> {
517 let gl = &self.raw;
518 let mut length = 0i32;
520 gl.GetProgramResourceiv(
521 program.0.get(),
522 interface,
523 index,
524 properties.len() as i32,
525 properties.as_ptr(),
526 0,
527 &mut length,
528 ptr::null_mut(),
529 );
530 let mut params = vec![0i32; length as usize];
532 gl.GetProgramResourceiv(
533 program.0.get(),
534 interface,
535 index,
536 properties.len() as i32,
537 properties.as_ptr(),
538 length,
539 &mut length,
540 params.as_mut_ptr(),
541 );
542 params
543 }
544
545 unsafe fn program_uniform_1_i32(
546 &self,
547 program: Self::Program,
548 location: Option<&Self::UniformLocation>,
549 x: i32,
550 ) {
551 let gl = &self.raw;
552 if let Some(loc) = location {
553 gl.ProgramUniform1i(program.0.get(), loc.0 as i32, x);
554 }
555 }
556
557 unsafe fn program_uniform_2_i32(
558 &self,
559 program: Self::Program,
560 location: Option<&Self::UniformLocation>,
561 x: i32,
562 y: i32,
563 ) {
564 let gl = &self.raw;
565 if let Some(loc) = location {
566 gl.ProgramUniform2i(program.0.get(), loc.0 as i32, x, y);
567 }
568 }
569
570 unsafe fn program_uniform_3_i32(
571 &self,
572 program: Self::Program,
573 location: Option<&Self::UniformLocation>,
574 x: i32,
575 y: i32,
576 z: i32,
577 ) {
578 let gl = &self.raw;
579 if let Some(loc) = location {
580 gl.ProgramUniform3i(program.0.get(), loc.0 as i32, x, y, z);
581 }
582 }
583
584 unsafe fn program_uniform_4_i32(
585 &self,
586 program: Self::Program,
587 location: Option<&Self::UniformLocation>,
588 x: i32,
589 y: i32,
590 z: i32,
591 w: i32,
592 ) {
593 let gl = &self.raw;
594 if let Some(loc) = location {
595 gl.ProgramUniform4i(program.0.get(), loc.0 as i32, x, y, z, w);
596 }
597 }
598
599 unsafe fn program_uniform_1_i32_slice(
600 &self,
601 program: Self::Program,
602 location: Option<&Self::UniformLocation>,
603 v: &[i32],
604 ) {
605 let gl = &self.raw;
606 if let Some(loc) = location {
607 gl.ProgramUniform1iv(program.0.get(), loc.0 as i32, v.len() as i32, v.as_ptr());
608 }
609 }
610
611 unsafe fn program_uniform_2_i32_slice(
612 &self,
613 program: Self::Program,
614 location: Option<&Self::UniformLocation>,
615 v: &[i32],
616 ) {
617 let gl = &self.raw;
618 if let Some(loc) = location {
619 gl.ProgramUniform2iv(
620 program.0.get(),
621 loc.0 as i32,
622 v.len() as i32 / 2,
623 v.as_ptr(),
624 );
625 }
626 }
627
628 unsafe fn program_uniform_3_i32_slice(
629 &self,
630 program: Self::Program,
631 location: Option<&Self::UniformLocation>,
632 v: &[i32],
633 ) {
634 let gl = &self.raw;
635 if let Some(loc) = location {
636 gl.ProgramUniform3iv(
637 program.0.get(),
638 loc.0 as i32,
639 v.len() as i32 / 3,
640 v.as_ptr(),
641 );
642 }
643 }
644
645 unsafe fn program_uniform_4_i32_slice(
646 &self,
647 program: Self::Program,
648 location: Option<&Self::UniformLocation>,
649 v: &[i32],
650 ) {
651 let gl = &self.raw;
652 if let Some(loc) = location {
653 gl.ProgramUniform4iv(
654 program.0.get(),
655 loc.0 as i32,
656 v.len() as i32 / 4,
657 v.as_ptr(),
658 );
659 }
660 }
661
662 unsafe fn program_uniform_1_u32(
663 &self,
664 program: Self::Program,
665 location: Option<&Self::UniformLocation>,
666 x: u32,
667 ) {
668 let gl = &self.raw;
669 if let Some(loc) = location {
670 gl.ProgramUniform1ui(program.0.get(), loc.0 as i32, x);
671 }
672 }
673
674 unsafe fn program_uniform_2_u32(
675 &self,
676 program: Self::Program,
677 location: Option<&Self::UniformLocation>,
678 x: u32,
679 y: u32,
680 ) {
681 let gl = &self.raw;
682 if let Some(loc) = location {
683 gl.ProgramUniform2ui(program.0.get(), loc.0 as i32, x, y);
684 }
685 }
686
687 unsafe fn program_uniform_3_u32(
688 &self,
689 program: Self::Program,
690 location: Option<&Self::UniformLocation>,
691 x: u32,
692 y: u32,
693 z: u32,
694 ) {
695 let gl = &self.raw;
696 if let Some(loc) = location {
697 gl.ProgramUniform3ui(program.0.get(), loc.0 as i32, x, y, z);
698 }
699 }
700
701 unsafe fn program_uniform_4_u32(
702 &self,
703 program: Self::Program,
704 location: Option<&Self::UniformLocation>,
705 x: u32,
706 y: u32,
707 z: u32,
708 w: u32,
709 ) {
710 let gl = &self.raw;
711 if let Some(loc) = location {
712 gl.ProgramUniform4ui(program.0.get(), loc.0 as i32, x, y, z, w);
713 }
714 }
715
716 unsafe fn program_uniform_1_u32_slice(
717 &self,
718 program: Self::Program,
719 location: Option<&Self::UniformLocation>,
720 v: &[u32],
721 ) {
722 let gl = &self.raw;
723 if let Some(loc) = location {
724 gl.ProgramUniform1uiv(program.0.get(), loc.0 as i32, v.len() as i32, v.as_ptr());
725 }
726 }
727
728 unsafe fn program_uniform_2_u32_slice(
729 &self,
730 program: Self::Program,
731 location: Option<&Self::UniformLocation>,
732 v: &[u32],
733 ) {
734 let gl = &self.raw;
735 if let Some(loc) = location {
736 gl.ProgramUniform2uiv(
737 program.0.get(),
738 loc.0 as i32,
739 v.len() as i32 / 2,
740 v.as_ptr(),
741 );
742 }
743 }
744
745 unsafe fn program_uniform_3_u32_slice(
746 &self,
747 program: Self::Program,
748 location: Option<&Self::UniformLocation>,
749 v: &[u32],
750 ) {
751 let gl = &self.raw;
752 if let Some(loc) = location {
753 gl.ProgramUniform3uiv(
754 program.0.get(),
755 loc.0 as i32,
756 v.len() as i32 / 3,
757 v.as_ptr(),
758 );
759 }
760 }
761
762 unsafe fn program_uniform_4_u32_slice(
763 &self,
764 program: Self::Program,
765 location: Option<&Self::UniformLocation>,
766 v: &[u32],
767 ) {
768 let gl = &self.raw;
769 if let Some(loc) = location {
770 gl.ProgramUniform4uiv(
771 program.0.get(),
772 loc.0 as i32,
773 v.len() as i32 / 4,
774 v.as_ptr(),
775 );
776 }
777 }
778
779 unsafe fn program_uniform_1_f32(
780 &self,
781 program: Self::Program,
782 location: Option<&Self::UniformLocation>,
783 x: f32,
784 ) {
785 let gl = &self.raw;
786 if let Some(loc) = location {
787 gl.ProgramUniform1f(program.0.get(), loc.0 as i32, x);
788 }
789 }
790
791 unsafe fn program_uniform_2_f32(
792 &self,
793 program: Self::Program,
794 location: Option<&Self::UniformLocation>,
795 x: f32,
796 y: f32,
797 ) {
798 let gl = &self.raw;
799 if let Some(loc) = location {
800 gl.ProgramUniform2f(program.0.get(), loc.0 as i32, x, y);
801 }
802 }
803
804 unsafe fn program_uniform_3_f32(
805 &self,
806 program: Self::Program,
807 location: Option<&Self::UniformLocation>,
808 x: f32,
809 y: f32,
810 z: f32,
811 ) {
812 let gl = &self.raw;
813 if let Some(loc) = location {
814 gl.ProgramUniform3f(program.0.get(), loc.0 as i32, x, y, z);
815 }
816 }
817
818 unsafe fn program_uniform_4_f32(
819 &self,
820 program: Self::Program,
821 location: Option<&Self::UniformLocation>,
822 x: f32,
823 y: f32,
824 z: f32,
825 w: f32,
826 ) {
827 let gl = &self.raw;
828 if let Some(loc) = location {
829 gl.ProgramUniform4f(program.0.get(), loc.0 as i32, x, y, z, w);
830 }
831 }
832
833 unsafe fn program_uniform_1_f32_slice(
834 &self,
835 program: Self::Program,
836 location: Option<&Self::UniformLocation>,
837 v: &[f32],
838 ) {
839 let gl = &self.raw;
840 if let Some(loc) = location {
841 gl.ProgramUniform1fv(program.0.get(), loc.0 as i32, v.len() as i32, v.as_ptr());
842 }
843 }
844
845 unsafe fn program_uniform_2_f32_slice(
846 &self,
847 program: Self::Program,
848 location: Option<&Self::UniformLocation>,
849 v: &[f32],
850 ) {
851 let gl = &self.raw;
852 if let Some(loc) = location {
853 gl.ProgramUniform2fv(
854 program.0.get(),
855 loc.0 as i32,
856 v.len() as i32 / 2,
857 v.as_ptr(),
858 );
859 }
860 }
861
862 unsafe fn program_uniform_3_f32_slice(
863 &self,
864 program: Self::Program,
865 location: Option<&Self::UniformLocation>,
866 v: &[f32],
867 ) {
868 let gl = &self.raw;
869 if let Some(loc) = location {
870 gl.ProgramUniform3fv(
871 program.0.get(),
872 loc.0 as i32,
873 v.len() as i32 / 3,
874 v.as_ptr(),
875 );
876 }
877 }
878
879 unsafe fn program_uniform_4_f32_slice(
880 &self,
881 program: Self::Program,
882 location: Option<&Self::UniformLocation>,
883 v: &[f32],
884 ) {
885 let gl = &self.raw;
886 if let Some(loc) = location {
887 gl.ProgramUniform4fv(
888 program.0.get(),
889 loc.0 as i32,
890 v.len() as i32 / 4,
891 v.as_ptr(),
892 );
893 }
894 }
895
896 unsafe fn program_uniform_matrix_2_f32_slice(
897 &self,
898 program: Self::Program,
899 location: Option<&Self::UniformLocation>,
900 transpose: bool,
901 v: &[f32],
902 ) {
903 let gl = &self.raw;
904 if let Some(loc) = location {
905 gl.ProgramUniformMatrix2fv(
906 program.0.get(),
907 loc.0 as i32,
908 v.len() as i32 / 4,
909 transpose as u8,
910 v.as_ptr(),
911 );
912 }
913 }
914
915 unsafe fn program_uniform_matrix_2x3_f32_slice(
916 &self,
917 program: Self::Program,
918 location: Option<&Self::UniformLocation>,
919 transpose: bool,
920 v: &[f32],
921 ) {
922 let gl = &self.raw;
923 if let Some(loc) = location {
924 gl.ProgramUniformMatrix2x3fv(
925 program.0.get(),
926 loc.0 as i32,
927 v.len() as i32 / 6,
928 transpose as u8,
929 v.as_ptr(),
930 );
931 }
932 }
933
934 unsafe fn program_uniform_matrix_2x4_f32_slice(
935 &self,
936 program: Self::Program,
937 location: Option<&Self::UniformLocation>,
938 transpose: bool,
939 v: &[f32],
940 ) {
941 let gl = &self.raw;
942 if let Some(loc) = location {
943 gl.ProgramUniformMatrix2x4fv(
944 program.0.get(),
945 loc.0 as i32,
946 v.len() as i32 / 8,
947 transpose as u8,
948 v.as_ptr(),
949 );
950 }
951 }
952
953 unsafe fn program_uniform_matrix_3x2_f32_slice(
954 &self,
955 program: Self::Program,
956 location: Option<&Self::UniformLocation>,
957 transpose: bool,
958 v: &[f32],
959 ) {
960 let gl = &self.raw;
961 if let Some(loc) = location {
962 gl.ProgramUniformMatrix3x2fv(
963 program.0.get(),
964 loc.0 as i32,
965 v.len() as i32 / 6,
966 transpose as u8,
967 v.as_ptr(),
968 );
969 }
970 }
971
972 unsafe fn program_uniform_matrix_3_f32_slice(
973 &self,
974 program: Self::Program,
975 location: Option<&Self::UniformLocation>,
976 transpose: bool,
977 v: &[f32],
978 ) {
979 let gl = &self.raw;
980 if let Some(loc) = location {
981 gl.ProgramUniformMatrix3fv(
982 program.0.get(),
983 loc.0 as i32,
984 v.len() as i32 / 9,
985 transpose as u8,
986 v.as_ptr(),
987 );
988 }
989 }
990
991 unsafe fn program_uniform_matrix_3x4_f32_slice(
992 &self,
993 program: Self::Program,
994 location: Option<&Self::UniformLocation>,
995 transpose: bool,
996 v: &[f32],
997 ) {
998 let gl = &self.raw;
999 if let Some(loc) = location {
1000 gl.ProgramUniformMatrix3x4fv(
1001 program.0.get(),
1002 loc.0 as i32,
1003 v.len() as i32 / 12,
1004 transpose as u8,
1005 v.as_ptr(),
1006 );
1007 }
1008 }
1009
1010 unsafe fn program_uniform_matrix_4x2_f32_slice(
1011 &self,
1012 program: Self::Program,
1013 location: Option<&Self::UniformLocation>,
1014 transpose: bool,
1015 v: &[f32],
1016 ) {
1017 let gl = &self.raw;
1018 if let Some(loc) = location {
1019 gl.ProgramUniformMatrix4x2fv(
1020 program.0.get(),
1021 loc.0 as i32,
1022 v.len() as i32 / 8,
1023 transpose as u8,
1024 v.as_ptr(),
1025 );
1026 }
1027 }
1028
1029 unsafe fn program_uniform_matrix_4x3_f32_slice(
1030 &self,
1031 program: Self::Program,
1032 location: Option<&Self::UniformLocation>,
1033 transpose: bool,
1034 v: &[f32],
1035 ) {
1036 let gl = &self.raw;
1037 if let Some(loc) = location {
1038 gl.ProgramUniformMatrix4x3fv(
1039 program.0.get(),
1040 loc.0 as i32,
1041 v.len() as i32 / 12,
1042 transpose as u8,
1043 v.as_ptr(),
1044 );
1045 }
1046 }
1047
1048 unsafe fn program_uniform_matrix_4_f32_slice(
1049 &self,
1050 program: Self::Program,
1051 location: Option<&Self::UniformLocation>,
1052 transpose: bool,
1053 v: &[f32],
1054 ) {
1055 let gl = &self.raw;
1056 if let Some(loc) = location {
1057 gl.ProgramUniformMatrix4fv(
1058 program.0.get(),
1059 loc.0 as i32,
1060 v.len() as i32 / 16,
1061 transpose as u8,
1062 v.as_ptr(),
1063 );
1064 }
1065 }
1066
1067 unsafe fn program_binary_retrievable_hint(&self, program: Self::Program, value: bool) {
1068 let gl = &self.raw;
1069 gl.ProgramParameteri(
1070 program.0.get(),
1071 crate::PROGRAM_BINARY_RETRIEVABLE_HINT,
1072 value as i32,
1073 )
1074 }
1075
1076 unsafe fn get_program_binary(&self, program: Self::Program) -> Option<ProgramBinary> {
1077 let gl = &self.raw;
1078
1079 let mut len = 0;
1081 gl.GetProgramiv(program.0.get(), crate::PROGRAM_BINARY_LENGTH, &mut len);
1082
1083 let mut format = 0;
1084 let mut buffer = vec![0u8; len as usize];
1085
1086 gl.GetProgramBinary(
1087 program.0.get(),
1088 len,
1089 ptr::null_mut(),
1090 &mut format,
1091 buffer.as_mut_ptr() as *mut core::ffi::c_void,
1092 );
1093
1094 if gl.GetError() == crate::NO_ERROR {
1095 Some(ProgramBinary { buffer, format })
1096 } else {
1097 None
1098 }
1099 }
1100
1101 unsafe fn program_binary(&self, program: Self::Program, binary: &ProgramBinary) {
1102 let gl = &self.raw;
1103
1104 gl.ProgramBinary(
1105 program.0.get(),
1106 binary.format,
1107 binary.buffer.as_ptr() as *const core::ffi::c_void,
1108 binary.buffer.len() as native_gl::types::GLsizei,
1109 )
1110 }
1111
1112 unsafe fn get_active_uniforms(&self, program: Self::Program) -> u32 {
1113 let gl = &self.raw;
1114 let mut count = 0;
1115 gl.GetProgramiv(program.0.get(), ACTIVE_UNIFORMS, &mut count);
1116 count as u32
1117 }
1118
1119 unsafe fn get_active_uniforms_parameter(
1120 &self,
1121 program: Self::Program,
1122 uniforms: &[u32],
1123 pname: u32,
1124 ) -> Vec<i32> {
1125 let gl = &self.raw;
1126 let mut results = vec![0; uniforms.len()];
1127 gl.GetActiveUniformsiv(
1128 program.0.get(),
1129 uniforms.len() as _,
1130 uniforms.as_ptr(),
1131 pname,
1132 results.as_mut_ptr(),
1133 );
1134 results
1135 }
1136
1137 unsafe fn get_active_uniform(
1138 &self,
1139 program: Self::Program,
1140 index: u32,
1141 ) -> Option<ActiveUniform> {
1142 let gl = &self.raw;
1143 let mut uniform_max_size = 0;
1144 gl.GetProgramiv(
1145 program.0.get(),
1146 ACTIVE_UNIFORM_MAX_LENGTH,
1147 &mut uniform_max_size,
1148 );
1149
1150 let mut name = String::with_capacity(uniform_max_size as usize);
1151 name.extend(std::iter::repeat('\0').take(uniform_max_size as usize));
1152 let mut length = 0;
1153 let mut size = 0;
1154 let mut utype = 0;
1155 gl.GetActiveUniform(
1156 program.0.get(),
1157 index,
1158 uniform_max_size,
1159 &mut length,
1160 &mut size,
1161 &mut utype,
1162 name.as_ptr() as *mut native_gl::GLchar,
1163 );
1164 name.truncate(length as usize);
1165
1166 Some(ActiveUniform { size, utype, name })
1167 }
1168
1169 unsafe fn use_program(&self, program: Option<Self::Program>) {
1170 let gl = &self.raw;
1171 gl.UseProgram(program.map(|p| p.0.get()).unwrap_or(0));
1172 }
1173
1174 unsafe fn create_buffer(&self) -> Result<Self::Buffer, String> {
1175 let gl = &self.raw;
1176 let mut buffer = 0;
1177 gl.GenBuffers(1, &mut buffer);
1178 NonZeroU32::new(buffer)
1179 .map(NativeBuffer)
1180 .ok_or_else(|| String::from("Unable to create Buffer object"))
1181 }
1182
1183 unsafe fn create_named_buffer(&self) -> Result<Self::Buffer, String> {
1184 let gl = &self.raw;
1185 let mut buffer = 0;
1186 gl.CreateBuffers(1, &mut buffer);
1187 NonZeroU32::new(buffer)
1188 .map(NativeBuffer)
1189 .ok_or_else(|| String::from("Unable to create Buffer object"))
1190 }
1191
1192 unsafe fn is_buffer(&self, buffer: Self::Buffer) -> bool {
1193 let gl = &self.raw;
1194 gl.IsBuffer(buffer.0.get()) != 0
1195 }
1196
1197 unsafe fn bind_buffer(&self, target: u32, buffer: Option<Self::Buffer>) {
1198 let gl = &self.raw;
1199 gl.BindBuffer(target, buffer.map(|b| b.0.get()).unwrap_or(0));
1200 }
1201
1202 unsafe fn bind_buffer_base(&self, target: u32, index: u32, buffer: Option<Self::Buffer>) {
1203 let gl = &self.raw;
1204 gl.BindBufferBase(target, index, buffer.map(|b| b.0.get()).unwrap_or(0));
1205 }
1206
1207 unsafe fn bind_buffer_range(
1208 &self,
1209 target: u32,
1210 index: u32,
1211 buffer: Option<Self::Buffer>,
1212 offset: i32,
1213 size: i32,
1214 ) {
1215 let gl = &self.raw;
1216 gl.BindBufferRange(
1217 target,
1218 index,
1219 buffer.map(|b| b.0.get()).unwrap_or(0),
1220 offset as isize,
1221 size as isize,
1222 );
1223 }
1224
1225 unsafe fn bind_vertex_buffer(
1226 &self,
1227 binding_index: u32,
1228 buffer: Option<Buffer>,
1229 offset: i32,
1230 stride: i32,
1231 ) {
1232 let gl = &self.raw;
1233 gl.BindVertexBuffer(
1234 binding_index,
1235 buffer.map(|b| b.0.get()).unwrap_or(0),
1236 offset as isize,
1237 stride,
1238 );
1239 }
1240
1241 unsafe fn bind_framebuffer(&self, target: u32, framebuffer: Option<Self::Framebuffer>) {
1242 let gl = &self.raw;
1243 gl.BindFramebuffer(target, framebuffer.map(|fb| fb.0.get()).unwrap_or(0));
1244 }
1245
1246 unsafe fn bind_renderbuffer(&self, target: u32, renderbuffer: Option<Self::Renderbuffer>) {
1247 let gl = &self.raw;
1248 gl.BindRenderbuffer(target, renderbuffer.map(|rb| rb.0.get()).unwrap_or(0));
1249 }
1250
1251 unsafe fn blit_framebuffer(
1252 &self,
1253 src_x0: i32,
1254 src_y0: i32,
1255 src_x1: i32,
1256 src_y1: i32,
1257 dst_x0: i32,
1258 dst_y0: i32,
1259 dst_x1: i32,
1260 dst_y1: i32,
1261 mask: u32,
1262 filter: u32,
1263 ) {
1264 let gl = &self.raw;
1265 gl.BlitFramebuffer(
1266 src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter,
1267 );
1268 }
1269
1270 unsafe fn blit_named_framebuffer(
1271 &self,
1272 read_buffer: Option<Self::Framebuffer>,
1273 draw_buffer: Option<Self::Framebuffer>,
1274 src_x0: i32,
1275 src_y0: i32,
1276 src_x1: i32,
1277 src_y1: i32,
1278 dst_x0: i32,
1279 dst_y0: i32,
1280 dst_x1: i32,
1281 dst_y1: i32,
1282 mask: u32,
1283 filter: u32,
1284 ) {
1285 let gl = &self.raw;
1286 gl.BlitNamedFramebuffer(
1287 read_buffer.map(|f| f.0.get()).unwrap_or(0),
1288 draw_buffer.map(|f| f.0.get()).unwrap_or(0),
1289 src_x0,
1290 src_y0,
1291 src_x1,
1292 src_y1,
1293 dst_x0,
1294 dst_y0,
1295 dst_x1,
1296 dst_y1,
1297 mask,
1298 filter,
1299 );
1300 }
1301
1302 unsafe fn create_vertex_array(&self) -> Result<Self::VertexArray, String> {
1303 let gl = &self.raw;
1304 let mut vertex_array = 0;
1305 if gl.GenVertexArrays_is_loaded() {
1306 gl.GenVertexArrays(1, &mut vertex_array);
1307 } else {
1308 #[cfg(not(target_vendor = "apple"))]
1309 gl.GenVertexArraysOES(1, &mut vertex_array);
1310 #[cfg(target_vendor = "apple")]
1311 gl.GenVertexArraysAPPLE(1, &mut vertex_array);
1312 }
1313 NonZeroU32::new(vertex_array)
1314 .map(NativeVertexArray)
1315 .ok_or_else(|| String::from("Unable to create VertexArray object"))
1316 }
1317
1318 unsafe fn create_named_vertex_array(&self) -> Result<Self::VertexArray, String> {
1319 let gl = &self.raw;
1320 let mut vertex_array = 0;
1321 gl.CreateVertexArrays(1, &mut vertex_array);
1322 NonZeroU32::new(vertex_array)
1323 .map(NativeVertexArray)
1324 .ok_or_else(|| String::from("Unable to create VertexArray object"))
1325 }
1326
1327 unsafe fn delete_vertex_array(&self, vertex_array: Self::VertexArray) {
1328 let gl = &self.raw;
1329 if gl.DeleteVertexArrays_is_loaded() {
1330 gl.DeleteVertexArrays(1, &vertex_array.0.get());
1331 } else {
1332 #[cfg(not(target_vendor = "apple"))]
1333 gl.DeleteVertexArraysOES(1, &vertex_array.0.get());
1334 #[cfg(target_vendor = "apple")]
1335 gl.DeleteVertexArraysAPPLE(1, &vertex_array.0.get());
1336 }
1337 }
1338
1339 unsafe fn bind_vertex_array(&self, vertex_array: Option<Self::VertexArray>) {
1340 let gl = &self.raw;
1341 if gl.BindVertexArray_is_loaded() {
1342 gl.BindVertexArray(vertex_array.map(|va| va.0.get()).unwrap_or(0));
1343 } else {
1344 #[cfg(not(target_vendor = "apple"))]
1345 gl.BindVertexArrayOES(vertex_array.map(|va| va.0.get()).unwrap_or(0));
1346 #[cfg(target_vendor = "apple")]
1347 gl.BindVertexArrayAPPLE(vertex_array.map(|va| va.0.get()).unwrap_or(0));
1348 }
1349 }
1350
1351 unsafe fn clear_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
1352 let gl = &self.raw;
1353 gl.ClearColor(red, green, blue, alpha);
1354 }
1355
1356 unsafe fn supports_f64_precision(&self) -> bool {
1357 !self.version.is_embedded
1358 }
1359
1360 unsafe fn clear_depth_f64(&self, depth: f64) {
1361 let gl = &self.raw;
1362 gl.ClearDepth(depth);
1363 }
1364
1365 unsafe fn clear_depth_f32(&self, depth: f32) {
1366 let gl = &self.raw;
1367 gl.ClearDepthf(depth);
1368 }
1369
1370 unsafe fn clear_depth(&self, depth: f64) {
1371 if self.supports_f64_precision() {
1372 self.clear_depth_f64(depth);
1373 } else {
1374 self.clear_depth_f32(depth as f32);
1375 }
1376 }
1377
1378 unsafe fn clear_stencil(&self, stencil: i32) {
1379 let gl = &self.raw;
1380 gl.ClearStencil(stencil);
1381 }
1382
1383 unsafe fn clear(&self, mask: u32) {
1384 let gl = &self.raw;
1385 gl.Clear(mask);
1386 }
1387
1388 unsafe fn patch_parameter_i32(&self, parameter: u32, value: i32) {
1389 let gl = &self.raw;
1390 gl.PatchParameteri(parameter, value);
1391 }
1392
1393 unsafe fn pixel_store_i32(&self, parameter: u32, value: i32) {
1394 let gl = &self.raw;
1395 gl.PixelStorei(parameter, value);
1396 }
1397
1398 unsafe fn pixel_store_bool(&self, parameter: u32, value: bool) {
1399 let gl = &self.raw;
1400 gl.PixelStorei(parameter, value as i32);
1401 }
1402
1403 unsafe fn get_frag_data_location(&self, program: Self::Program, name: &str) -> i32 {
1404 let gl = &self.raw;
1405 let name = CString::new(name).unwrap();
1406 gl.GetFragDataLocation(program.0.get(), name.as_ptr() as *const native_gl::GLchar)
1407 }
1408
1409 unsafe fn bind_frag_data_location(
1410 &self,
1411 program: Self::Program,
1412 color_number: u32,
1413 name: &str,
1414 ) {
1415 let gl = &self.raw;
1416 let name = CString::new(name).unwrap();
1417 gl.BindFragDataLocation(
1418 program.0.get(),
1419 color_number,
1420 name.as_ptr() as *const native_gl::GLchar,
1421 );
1422 }
1423
1424 unsafe fn buffer_data_size(&self, target: u32, size: i32, usage: u32) {
1425 let gl = &self.raw;
1426 gl.BufferData(target, size as isize, std::ptr::null(), usage);
1427 }
1428
1429 unsafe fn named_buffer_data_size(&self, buffer: Self::Buffer, size: i32, usage: u32) {
1430 let gl = &self.raw;
1431 gl.NamedBufferData(buffer.0.get(), size as isize, std::ptr::null(), usage);
1432 }
1433
1434 unsafe fn buffer_data_u8_slice(&self, target: u32, data: &[u8], usage: u32) {
1435 let gl = &self.raw;
1436 gl.BufferData(
1437 target,
1438 data.len() as isize,
1439 data.as_ptr() as *const std::ffi::c_void,
1440 usage,
1441 );
1442 }
1443
1444 unsafe fn named_buffer_data_u8_slice(&self, buffer: Self::Buffer, data: &[u8], usage: u32) {
1445 let gl = &self.raw;
1446 gl.NamedBufferData(
1447 buffer.0.get(),
1448 data.len() as isize,
1449 data.as_ptr() as *const std::ffi::c_void,
1450 usage,
1451 );
1452 }
1453
1454 unsafe fn buffer_sub_data_u8_slice(&self, target: u32, offset: i32, src_data: &[u8]) {
1455 let gl = &self.raw;
1456 gl.BufferSubData(
1457 target,
1458 offset as isize,
1459 src_data.len() as isize,
1460 src_data.as_ptr() as *const std::ffi::c_void,
1461 );
1462 }
1463
1464 unsafe fn named_buffer_sub_data_u8_slice(
1465 &self,
1466 buffer: Self::Buffer,
1467 offset: i32,
1468 src_data: &[u8],
1469 ) {
1470 let gl = &self.raw;
1471 gl.NamedBufferSubData(
1472 buffer.0.get(),
1473 offset as isize,
1474 src_data.len() as isize,
1475 src_data.as_ptr() as *const std::ffi::c_void,
1476 );
1477 }
1478
1479 unsafe fn get_buffer_sub_data(&self, target: u32, offset: i32, dst_data: &mut [u8]) {
1480 let gl = &self.raw;
1481 gl.GetBufferSubData(
1482 target,
1483 offset as isize,
1484 dst_data.len() as isize,
1485 dst_data.as_mut_ptr() as *mut std::ffi::c_void,
1486 );
1487 }
1488
1489 unsafe fn buffer_storage(&self, target: u32, size: i32, data: Option<&[u8]>, flags: u32) {
1490 let gl = &self.raw;
1491 let size = size as isize;
1492 let data = data.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void;
1493 if gl.BufferStorage_is_loaded() {
1494 gl.BufferStorage(target, size, data, flags);
1495 } else {
1496 gl.BufferStorageEXT(target, size, data, flags);
1497 }
1498 }
1499
1500 unsafe fn check_framebuffer_status(&self, target: u32) -> u32 {
1501 let gl = &self.raw;
1502 gl.CheckFramebufferStatus(target)
1503 }
1504
1505 unsafe fn check_named_framebuffer_status(
1506 &self,
1507 framebuffer: Option<Self::Framebuffer>,
1508 target: u32,
1509 ) -> u32 {
1510 let gl = &self.raw;
1511 gl.CheckNamedFramebufferStatus(framebuffer.map(|f| f.0.get()).unwrap_or(0), target)
1512 }
1513
1514 unsafe fn clear_buffer_i32_slice(&self, target: u32, draw_buffer: u32, values: &[i32]) {
1515 let gl = &self.raw;
1516 gl.ClearBufferiv(target, draw_buffer as i32, values.as_ptr());
1517 }
1518
1519 unsafe fn clear_buffer_u32_slice(&self, target: u32, draw_buffer: u32, values: &[u32]) {
1520 let gl = &self.raw;
1521 gl.ClearBufferuiv(target, draw_buffer as i32, values.as_ptr());
1522 }
1523
1524 unsafe fn clear_buffer_f32_slice(&self, target: u32, draw_buffer: u32, values: &[f32]) {
1525 let gl = &self.raw;
1526 gl.ClearBufferfv(target, draw_buffer as i32, values.as_ptr());
1527 }
1528
1529 unsafe fn clear_buffer_depth_stencil(
1530 &self,
1531 target: u32,
1532 draw_buffer: u32,
1533 depth: f32,
1534 stencil: i32,
1535 ) {
1536 let gl = &self.raw;
1537 gl.ClearBufferfi(target, draw_buffer as i32, depth, stencil);
1538 }
1539
1540 unsafe fn clear_named_framebuffer_i32_slice(
1541 &self,
1542 framebuffer: Option<Self::Framebuffer>,
1543 target: u32,
1544 draw_buffer: u32,
1545 values: &[i32],
1546 ) {
1547 let gl = &self.raw;
1548 gl.ClearNamedFramebufferiv(
1549 framebuffer.map(|f| f.0.get()).unwrap_or(0),
1550 target,
1551 draw_buffer as i32,
1552 values.as_ptr(),
1553 );
1554 }
1555
1556 unsafe fn clear_named_framebuffer_u32_slice(
1557 &self,
1558 framebuffer: Option<Self::Framebuffer>,
1559 target: u32,
1560 draw_buffer: u32,
1561 values: &[u32],
1562 ) {
1563 let gl = &self.raw;
1564 gl.ClearNamedFramebufferuiv(
1565 framebuffer.map(|f| f.0.get()).unwrap_or(0),
1566 target,
1567 draw_buffer as i32,
1568 values.as_ptr(),
1569 );
1570 }
1571
1572 unsafe fn clear_named_framebuffer_f32_slice(
1573 &self,
1574 framebuffer: Option<Self::Framebuffer>,
1575 target: u32,
1576 draw_buffer: u32,
1577 values: &[f32],
1578 ) {
1579 let gl = &self.raw;
1580 gl.ClearNamedFramebufferfv(
1581 framebuffer.map(|f| f.0.get()).unwrap_or(0),
1582 target,
1583 draw_buffer as i32,
1584 values.as_ptr(),
1585 );
1586 }
1587
1588 unsafe fn clear_named_framebuffer_depth_stencil(
1589 &self,
1590 framebuffer: Option<Self::Framebuffer>,
1591 target: u32,
1592 draw_buffer: u32,
1593 depth: f32,
1594 stencil: i32,
1595 ) {
1596 let gl = &self.raw;
1597 gl.ClearNamedFramebufferfi(
1598 framebuffer.map(|f| f.0.get()).unwrap_or(0),
1599 target,
1600 draw_buffer as i32,
1601 depth,
1602 stencil,
1603 );
1604 }
1605
1606 unsafe fn client_wait_sync(&self, fence: Self::Fence, flags: u32, timeout: i32) -> u32 {
1607 let gl = &self.raw;
1608 gl.ClientWaitSync(fence.0, flags, timeout as u64)
1609 }
1610
1611 unsafe fn get_sync_parameter_i32(&self, fence: Self::Fence, parameter: u32) -> i32 {
1612 let gl = &self.raw;
1613 let mut v = 0;
1614 gl.GetSynciv(fence.0, parameter, 1, ptr::null_mut(), &mut v);
1615 v
1616 }
1617
1618 unsafe fn wait_sync(&self, fence: Self::Fence, flags: u32, timeout: u64) {
1619 let gl = &self.raw;
1620 gl.WaitSync(fence.0, flags, timeout)
1621 }
1622
1623 unsafe fn copy_buffer_sub_data(
1624 &self,
1625 src_target: u32,
1626 dst_target: u32,
1627 src_offset: i32,
1628 dst_offset: i32,
1629 size: i32,
1630 ) {
1631 let gl = &self.raw;
1632 gl.CopyBufferSubData(
1633 src_target,
1634 dst_target,
1635 src_offset as isize,
1636 dst_offset as isize,
1637 size as isize,
1638 );
1639 }
1640
1641 unsafe fn copy_image_sub_data(
1642 &self,
1643 src_name: Self::Texture,
1644 src_target: u32,
1645 src_level: i32,
1646 src_x: i32,
1647 src_y: i32,
1648 src_z: i32,
1649 dst_name: Self::Texture,
1650 dst_target: u32,
1651 dst_level: i32,
1652 dst_x: i32,
1653 dst_y: i32,
1654 dst_z: i32,
1655 src_width: i32,
1656 src_height: i32,
1657 src_depth: i32,
1658 ) {
1659 let gl = &self.raw;
1660 gl.CopyImageSubData(
1661 src_name.0.get(),
1662 src_target,
1663 src_level,
1664 src_x,
1665 src_y,
1666 src_z,
1667 dst_name.0.get(),
1668 dst_target,
1669 dst_level,
1670 dst_x,
1671 dst_y,
1672 dst_z,
1673 src_width,
1674 src_height,
1675 src_depth,
1676 );
1677 }
1678
1679 unsafe fn copy_tex_image_2d(
1680 &self,
1681 target: u32,
1682 level: i32,
1683 internal_format: u32,
1684 x: i32,
1685 y: i32,
1686 width: i32,
1687 height: i32,
1688 border: i32,
1689 ) {
1690 let gl = &self.raw;
1691 gl.CopyTexImage2D(target, level, internal_format, x, y, width, height, border);
1692 }
1693
1694 unsafe fn copy_tex_sub_image_2d(
1695 &self,
1696 target: u32,
1697 level: i32,
1698 x_offset: i32,
1699 y_offset: i32,
1700 x: i32,
1701 y: i32,
1702 width: i32,
1703 height: i32,
1704 ) {
1705 let gl = &self.raw;
1706 gl.CopyTexSubImage2D(target, level, x_offset, y_offset, x, y, width, height);
1707 }
1708
1709 unsafe fn copy_tex_sub_image_3d(
1710 &self,
1711 target: u32,
1712 level: i32,
1713 x_offset: i32,
1714 y_offset: i32,
1715 z_offset: i32,
1716 x: i32,
1717 y: i32,
1718 width: i32,
1719 height: i32,
1720 ) {
1721 let gl = &self.raw;
1722 gl.CopyTexSubImage3D(
1723 target, level, x_offset, y_offset, z_offset, x, y, width, height,
1724 );
1725 }
1726
1727 unsafe fn delete_buffer(&self, buffer: Self::Buffer) {
1728 let gl = &self.raw;
1729 gl.DeleteBuffers(1, &buffer.0.get());
1730 }
1731
1732 unsafe fn delete_framebuffer(&self, framebuffer: Self::Framebuffer) {
1733 let gl = &self.raw;
1734 gl.DeleteFramebuffers(1, &framebuffer.0.get());
1735 }
1736
1737 unsafe fn delete_query(&self, query: Self::Query) {
1738 let gl = &self.raw;
1739 if gl.DeleteQueries_is_loaded() {
1740 gl.DeleteQueries(1, &query.0.get());
1741 } else {
1742 gl.DeleteQueriesEXT(1, &query.0.get());
1743 }
1744 }
1745
1746 unsafe fn delete_renderbuffer(&self, renderbuffer: Self::Renderbuffer) {
1747 let gl = &self.raw;
1748 gl.DeleteRenderbuffers(1, &renderbuffer.0.get());
1749 }
1750
1751 unsafe fn delete_sampler(&self, sampler: Self::Sampler) {
1752 let gl = &self.raw;
1753 gl.DeleteSamplers(1, &sampler.0.get());
1754 }
1755
1756 unsafe fn delete_sync(&self, fence: Self::Fence) {
1757 let gl = &self.raw;
1758 gl.DeleteSync(fence.0);
1759 }
1760
1761 unsafe fn delete_texture(&self, texture: Self::Texture) {
1762 let gl = &self.raw;
1763 gl.DeleteTextures(1, &texture.0.get());
1764 }
1765
1766 unsafe fn disable(&self, parameter: u32) {
1767 let gl = &self.raw;
1768 gl.Disable(parameter);
1769 }
1770
1771 unsafe fn disable_draw_buffer(&self, parameter: u32, draw_buffer: u32) {
1772 let gl = &self.raw;
1773 gl.Disablei(parameter, draw_buffer);
1774 }
1775
1776 unsafe fn disable_vertex_attrib_array(&self, index: u32) {
1777 let gl = &self.raw;
1778 gl.DisableVertexAttribArray(index);
1779 }
1780
1781 unsafe fn dispatch_compute(&self, groups_x: u32, groups_y: u32, groups_z: u32) {
1782 let gl = &self.raw;
1783 gl.DispatchCompute(groups_x, groups_y, groups_z);
1784 }
1785
1786 unsafe fn dispatch_compute_indirect(&self, offset: i32) {
1787 let gl = &self.raw;
1788 gl.DispatchComputeIndirect(offset as isize);
1789 }
1790
1791 unsafe fn draw_arrays(&self, mode: u32, first: i32, count: i32) {
1792 let gl = &self.raw;
1793 gl.DrawArrays(mode as u32, first, count);
1794 }
1795
1796 unsafe fn draw_arrays_instanced(&self, mode: u32, first: i32, count: i32, instance_count: i32) {
1797 let gl = &self.raw;
1798 gl.DrawArraysInstanced(mode as u32, first, count, instance_count);
1799 }
1800
1801 unsafe fn draw_arrays_instanced_base_instance(
1802 &self,
1803 mode: u32,
1804 first: i32,
1805 count: i32,
1806 instance_count: i32,
1807 base_instance: u32,
1808 ) {
1809 let gl = &self.raw;
1810 gl.DrawArraysInstancedBaseInstance(
1811 mode as u32,
1812 first,
1813 count,
1814 instance_count,
1815 base_instance,
1816 );
1817 }
1818
1819 unsafe fn draw_arrays_indirect_offset(&self, mode: u32, offset: i32) {
1820 let gl = &self.raw;
1821 gl.DrawArraysIndirect(mode, offset as *const std::ffi::c_void);
1822 }
1823
1824 unsafe fn draw_buffer(&self, draw_buffer: u32) {
1825 let gl = &self.raw;
1826 gl.DrawBuffer(draw_buffer);
1827 }
1828
1829 unsafe fn named_framebuffer_draw_buffer(
1830 &self,
1831 framebuffer: Option<Self::Framebuffer>,
1832 draw_buffer: u32,
1833 ) {
1834 let gl = &self.raw;
1835 gl.NamedFramebufferDrawBuffer(framebuffer.map(|f| f.0.get()).unwrap_or(0), draw_buffer);
1836 }
1837
1838 unsafe fn draw_buffers(&self, buffers: &[u32]) {
1839 let gl = &self.raw;
1840 gl.DrawBuffers(buffers.len() as i32, buffers.as_ptr());
1841 }
1842
1843 unsafe fn named_framebuffer_draw_buffers(
1844 &self,
1845 framebuffer: Option<Self::Framebuffer>,
1846 buffers: &[u32],
1847 ) {
1848 let gl = &self.raw;
1849 gl.NamedFramebufferDrawBuffers(
1850 framebuffer.map(|f| f.0.get()).unwrap_or(0),
1851 buffers.len() as i32,
1852 buffers.as_ptr(),
1853 );
1854 }
1855
1856 unsafe fn draw_elements(&self, mode: u32, count: i32, element_type: u32, offset: i32) {
1857 let gl = &self.raw;
1858 gl.DrawElements(
1859 mode as u32,
1860 count,
1861 element_type as u32,
1862 offset as *const std::ffi::c_void,
1863 );
1864 }
1865
1866 unsafe fn draw_elements_base_vertex(
1867 &self,
1868 mode: u32,
1869 count: i32,
1870 element_type: u32,
1871 offset: i32,
1872 base_vertex: i32,
1873 ) {
1874 let gl = &self.raw;
1875 gl.DrawElementsBaseVertex(
1876 mode as u32,
1877 count,
1878 element_type as u32,
1879 offset as *const std::ffi::c_void,
1880 base_vertex,
1881 );
1882 }
1883
1884 unsafe fn draw_elements_instanced(
1885 &self,
1886 mode: u32,
1887 count: i32,
1888 element_type: u32,
1889 offset: i32,
1890 instance_count: i32,
1891 ) {
1892 let gl = &self.raw;
1893 gl.DrawElementsInstanced(
1894 mode as u32,
1895 count,
1896 element_type as u32,
1897 offset as *const std::ffi::c_void,
1898 instance_count,
1899 );
1900 }
1901
1902 unsafe fn draw_elements_instanced_base_vertex(
1903 &self,
1904 mode: u32,
1905 count: i32,
1906 element_type: u32,
1907 offset: i32,
1908 instance_count: i32,
1909 base_vertex: i32,
1910 ) {
1911 let gl = &self.raw;
1912 gl.DrawElementsInstancedBaseVertex(
1913 mode as u32,
1914 count,
1915 element_type as u32,
1916 offset as *const std::ffi::c_void,
1917 instance_count,
1918 base_vertex,
1919 );
1920 }
1921
1922 unsafe fn draw_elements_instanced_base_vertex_base_instance(
1923 &self,
1924 mode: u32,
1925 count: i32,
1926 element_type: u32,
1927 offset: i32,
1928 instance_count: i32,
1929 base_vertex: i32,
1930 base_instance: u32,
1931 ) {
1932 let gl = &self.raw;
1933 gl.DrawElementsInstancedBaseVertexBaseInstance(
1934 mode as u32,
1935 count,
1936 element_type as u32,
1937 offset as *const std::ffi::c_void,
1938 instance_count,
1939 base_vertex,
1940 base_instance,
1941 );
1942 }
1943
1944 unsafe fn draw_elements_indirect_offset(&self, mode: u32, element_type: u32, offset: i32) {
1945 let gl = &self.raw;
1946 gl.DrawElementsIndirect(mode, element_type, offset as *const std::ffi::c_void);
1947 }
1948
1949 unsafe fn enable(&self, parameter: u32) {
1950 let gl = &self.raw;
1951 gl.Enable(parameter);
1952 }
1953
1954 unsafe fn is_enabled(&self, parameter: u32) -> bool {
1955 let gl = &self.raw;
1956 gl.IsEnabled(parameter) != 0
1957 }
1958
1959 unsafe fn enable_draw_buffer(&self, parameter: u32, draw_buffer: u32) {
1960 let gl = &self.raw;
1961 gl.Enablei(parameter, draw_buffer);
1962 }
1963
1964 unsafe fn enable_vertex_array_attrib(&self, vao: Self::VertexArray, index: u32) {
1965 let gl = &self.raw;
1966 gl.EnableVertexArrayAttrib(vao.0.get(), index);
1967 }
1968
1969 unsafe fn enable_vertex_attrib_array(&self, index: u32) {
1970 let gl = &self.raw;
1971 gl.EnableVertexAttribArray(index);
1972 }
1973
1974 unsafe fn flush(&self) {
1975 let gl = &self.raw;
1976 gl.Flush();
1977 }
1978
1979 unsafe fn framebuffer_renderbuffer(
1980 &self,
1981 target: u32,
1982 attachment: u32,
1983 renderbuffer_target: u32,
1984 renderbuffer: Option<Self::Renderbuffer>,
1985 ) {
1986 let gl = &self.raw;
1987 gl.FramebufferRenderbuffer(
1988 target,
1989 attachment,
1990 renderbuffer_target,
1991 renderbuffer.map(|rb| rb.0.get()).unwrap_or(0),
1992 );
1993 }
1994
1995 unsafe fn framebuffer_texture(
1996 &self,
1997 target: u32,
1998 attachment: u32,
1999 texture: Option<Self::Texture>,
2000 level: i32,
2001 ) {
2002 let gl = &self.raw;
2003 gl.FramebufferTexture(
2004 target,
2005 attachment,
2006 texture.map(|t| t.0.get()).unwrap_or(0),
2007 level,
2008 );
2009 }
2010
2011 unsafe fn framebuffer_texture_2d(
2012 &self,
2013 target: u32,
2014 attachment: u32,
2015 texture_target: u32,
2016 texture: Option<Self::Texture>,
2017 level: i32,
2018 ) {
2019 let gl = &self.raw;
2020 gl.FramebufferTexture2D(
2021 target,
2022 attachment,
2023 texture_target,
2024 texture.map(|t| t.0.get()).unwrap_or(0),
2025 level,
2026 );
2027 }
2028
2029 unsafe fn framebuffer_texture_3d(
2030 &self,
2031 target: u32,
2032 attachment: u32,
2033 texture_target: u32,
2034 texture: Option<Self::Texture>,
2035 level: i32,
2036 layer: i32,
2037 ) {
2038 let gl = &self.raw;
2039 gl.FramebufferTexture3D(
2040 target,
2041 attachment,
2042 texture_target,
2043 texture.map(|t| t.0.get()).unwrap_or(0),
2044 level,
2045 layer,
2046 );
2047 }
2048
2049 unsafe fn framebuffer_texture_layer(
2050 &self,
2051 target: u32,
2052 attachment: u32,
2053 texture: Option<Self::Texture>,
2054 level: i32,
2055 layer: i32,
2056 ) {
2057 let gl = &self.raw;
2058 gl.FramebufferTextureLayer(
2059 target,
2060 attachment,
2061 texture.map(|t| t.0.get()).unwrap_or(0),
2062 level,
2063 layer,
2064 );
2065 }
2066
2067 unsafe fn named_framebuffer_renderbuffer(
2068 &self,
2069 framebuffer: Option<Self::Framebuffer>,
2070 attachment: u32,
2071 renderbuffer_target: u32,
2072 renderbuffer: Option<Self::Renderbuffer>,
2073 ) {
2074 let gl = &self.raw;
2075 gl.NamedFramebufferRenderbuffer(
2076 framebuffer.map(|f| f.0.get()).unwrap_or(0),
2077 attachment,
2078 renderbuffer_target,
2079 renderbuffer.map(|rb| rb.0.get()).unwrap_or(0),
2080 );
2081 }
2082
2083 unsafe fn named_framebuffer_texture(
2084 &self,
2085 framebuffer: Option<Self::Framebuffer>,
2086 attachment: u32,
2087 texture: Option<Self::Texture>,
2088 level: i32,
2089 ) {
2090 let gl = &self.raw;
2091 gl.NamedFramebufferTexture(
2092 framebuffer.map(|f| f.0.get()).unwrap_or(0),
2093 attachment,
2094 texture.map(|t| t.0.get()).unwrap_or(0),
2095 level,
2096 );
2097 }
2098
2099 unsafe fn named_framebuffer_texture_layer(
2100 &self,
2101 framebuffer: Option<Self::Framebuffer>,
2102 attachment: u32,
2103 texture: Option<Self::Texture>,
2104 level: i32,
2105 layer: i32,
2106 ) {
2107 let gl = &self.raw;
2108 gl.NamedFramebufferTextureLayer(
2109 framebuffer.map(|f| f.0.get()).unwrap_or(0),
2110 attachment,
2111 texture.map(|t| t.0.get()).unwrap_or(0),
2112 level,
2113 layer,
2114 );
2115 }
2116
2117 unsafe fn front_face(&self, value: u32) {
2118 let gl = &self.raw;
2119 gl.FrontFace(value as u32);
2120 }
2121
2122 unsafe fn get_error(&self) -> u32 {
2123 let gl = &self.raw;
2124 gl.GetError()
2125 }
2126
2127 unsafe fn get_tex_parameter_i32(&self, target: u32, parameter: u32) -> i32 {
2128 let gl = &self.raw;
2129 let mut value = 0;
2130 gl.GetTexParameteriv(target, parameter, &mut value);
2131 value
2132 }
2133
2134 unsafe fn get_tex_parameter_f32(&self, target: u32, parameter: u32) -> f32 {
2135 let gl = &self.raw;
2136 let mut value = 0.;
2137 gl.GetTexParameterfv(target, parameter, &mut value);
2138 value
2139 }
2140
2141 unsafe fn get_buffer_parameter_i32(&self, target: u32, parameter: u32) -> i32 {
2142 let gl = &self.raw;
2143 let mut value = 0;
2144 gl.GetBufferParameteriv(target, parameter, &mut value);
2145 value
2146 }
2147
2148 unsafe fn get_parameter_bool(&self, parameter: u32) -> bool {
2149 let gl = &self.raw;
2150 let mut value = 0;
2151 gl.GetBooleanv(parameter, &mut value);
2152 value != FALSE
2153 }
2154
2155 unsafe fn get_parameter_bool_array<const N: usize>(&self, parameter: u32) -> [bool; N] {
2156 let gl = &self.raw;
2157 let mut value = [0; N];
2158 gl.GetBooleanv(parameter, &mut value[0]);
2159 value.map(|v| v != FALSE)
2160 }
2161
2162 unsafe fn get_parameter_i32(&self, parameter: u32) -> i32 {
2163 let gl = &self.raw;
2164 let mut value = 0;
2165 gl.GetIntegerv(parameter, &mut value);
2166 value
2167 }
2168
2169 unsafe fn get_parameter_i32_slice(&self, parameter: u32, out: &mut [i32]) {
2170 let gl = &self.raw;
2171 gl.GetIntegerv(parameter, &mut out[0]);
2172 }
2173
2174 unsafe fn get_parameter_i64(&self, parameter: u32) -> i64 {
2175 let gl = &self.raw;
2176 let mut value = 0;
2177 gl.GetInteger64v(parameter, &mut value);
2178 value
2179 }
2180
2181 unsafe fn get_parameter_i64_slice(&self, parameter: u32, out: &mut [i64]) {
2182 let gl = &self.raw;
2183 gl.GetInteger64v(parameter, &mut out[0]);
2184 }
2185
2186 unsafe fn get_parameter_indexed_i64(&self, parameter: u32, index: u32) -> i64 {
2187 let gl = &self.raw;
2188 let mut value = 0;
2189 gl.GetInteger64i_v(parameter, index, &mut value);
2190 value
2191 }
2192
2193 unsafe fn get_parameter_f32(&self, parameter: u32) -> f32 {
2194 let gl = &self.raw;
2195 let mut value: f32 = 0.0;
2196 gl.GetFloatv(parameter, &mut value);
2197 value
2198 }
2199
2200 unsafe fn get_parameter_f32_slice(&self, parameter: u32, out: &mut [f32]) {
2201 let gl = &self.raw;
2202 gl.GetFloatv(parameter, &mut out[0]);
2203 }
2204
2205 unsafe fn get_parameter_indexed_i32(&self, parameter: u32, index: u32) -> i32 {
2206 let gl = &self.raw;
2207 let mut value = 0;
2208 gl.GetIntegeri_v(parameter, index, &mut value);
2209 value
2210 }
2211
2212 unsafe fn get_parameter_indexed_string(&self, parameter: u32, index: u32) -> String {
2213 let gl = &self.raw;
2214 let raw_ptr = gl.GetStringi(parameter, index);
2215 std::ffi::CStr::from_ptr(raw_ptr as *const native_gl::GLchar)
2216 .to_str()
2217 .unwrap()
2218 .to_owned()
2219 }
2220
2221 unsafe fn get_parameter_string(&self, parameter: u32) -> String {
2222 let gl = &self.raw;
2223 let raw_ptr = gl.GetString(parameter);
2224 if raw_ptr.is_null() {
2225 panic!(
2226 "Get parameter string 0x{:X} failed. Maybe your GL context version is too outdated.",
2227 parameter
2228 )
2229 }
2230 std::ffi::CStr::from_ptr(raw_ptr as *const native_gl::GLchar)
2231 .to_str()
2232 .unwrap()
2233 .to_owned()
2234 }
2235
2236 unsafe fn get_parameter_buffer(&self, parameter: u32) -> Option<Self::Buffer> {
2237 self.get_parameter_gl_name(parameter).map(NativeBuffer)
2238 }
2239
2240 unsafe fn get_parameter_framebuffer(&self, parameter: u32) -> Option<Self::Framebuffer> {
2241 self.get_parameter_gl_name(parameter).map(NativeFramebuffer)
2242 }
2243
2244 unsafe fn get_parameter_program(&self, parameter: u32) -> Option<Self::Program> {
2245 self.get_parameter_gl_name(parameter).map(NativeProgram)
2246 }
2247
2248 unsafe fn get_parameter_renderbuffer(&self, parameter: u32) -> Option<Self::Renderbuffer> {
2249 self.get_parameter_gl_name(parameter)
2250 .map(NativeRenderbuffer)
2251 }
2252
2253 unsafe fn get_parameter_sampler(&self, parameter: u32) -> Option<Self::Sampler> {
2254 self.get_parameter_gl_name(parameter).map(NativeSampler)
2255 }
2256
2257 unsafe fn get_parameter_texture(&self, parameter: u32) -> Option<Self::Texture> {
2258 self.get_parameter_gl_name(parameter).map(NativeTexture)
2259 }
2260
2261 unsafe fn get_parameter_transform_feedback(
2262 &self,
2263 parameter: u32,
2264 ) -> Option<Self::TransformFeedback> {
2265 self.get_parameter_gl_name(parameter)
2266 .map(NativeTransformFeedback)
2267 }
2268
2269 unsafe fn get_parameter_vertex_array(&self, parameter: u32) -> Option<Self::VertexArray> {
2270 self.get_parameter_gl_name(parameter).map(NativeVertexArray)
2271 }
2272
2273 unsafe fn get_renderbuffer_parameter_i32(&self, target: u32, parameter: u32) -> i32 {
2274 let gl = &self.raw;
2275 let mut value = 0;
2276 gl.GetRenderbufferParameteriv(target, parameter, &mut value);
2277 value
2278 }
2279
2280 unsafe fn get_framebuffer_parameter_i32(&self, target: u32, parameter: u32) -> i32 {
2281 let gl = &self.raw;
2282 let mut value = 0;
2283 gl.GetFramebufferParameteriv(target, parameter, &mut value);
2284 value
2285 }
2286
2287 unsafe fn get_named_framebuffer_parameter_i32(
2288 &self,
2289 framebuffer: Option<Self::Framebuffer>,
2290 parameter: u32,
2291 ) -> i32 {
2292 let gl = &self.raw;
2293 let mut value = 0;
2294 gl.GetNamedFramebufferParameteriv(
2295 framebuffer.map(|f| f.0.get()).unwrap_or(0),
2296 parameter,
2297 &mut value,
2298 );
2299 value
2300 }
2301
2302 unsafe fn get_framebuffer_attachment_parameter_i32(
2303 &self,
2304 target: u32,
2305 attachment: u32,
2306 parameter: u32,
2307 ) -> i32 {
2308 let gl = &self.raw;
2309 let mut value = 0;
2310 gl.GetFramebufferAttachmentParameteriv(target, attachment, parameter, &mut value);
2311 value
2312 }
2313
2314 unsafe fn get_named_framebuffer_attachment_parameter_i32(
2315 &self,
2316 framebuffer: Option<Self::Framebuffer>,
2317 attachment: u32,
2318 parameter: u32,
2319 ) -> i32 {
2320 let gl = &self.raw;
2321 let mut value = 0;
2322 gl.GetNamedFramebufferAttachmentParameteriv(
2323 framebuffer.map(|f| f.0.get()).unwrap_or(0),
2324 attachment,
2325 parameter,
2326 &mut value,
2327 );
2328 value
2329 }
2330
2331 unsafe fn get_uniform_location(
2332 &self,
2333 program: Self::Program,
2334 name: &str,
2335 ) -> Option<Self::UniformLocation> {
2336 let gl = &self.raw;
2337 let name = CString::new(name).unwrap();
2338 let uniform_location =
2339 gl.GetUniformLocation(program.0.get(), name.as_ptr() as *const native_gl::GLchar);
2340 if uniform_location < 0 {
2341 None
2342 } else {
2343 Some(NativeUniformLocation(uniform_location as u32))
2344 }
2345 }
2346
2347 unsafe fn get_attrib_location(&self, program: Self::Program, name: &str) -> Option<u32> {
2348 let gl = &self.raw;
2349 let name = CString::new(name).unwrap();
2350 let attrib_location =
2351 gl.GetAttribLocation(program.0.get(), name.as_ptr() as *const native_gl::GLchar);
2352 if attrib_location < 0 {
2353 None
2354 } else {
2355 Some(attrib_location as u32)
2356 }
2357 }
2358
2359 unsafe fn bind_attrib_location(&self, program: Self::Program, index: u32, name: &str) {
2360 let gl = &self.raw;
2361 let name = CString::new(name).unwrap();
2362 gl.BindAttribLocation(
2363 program.0.get(),
2364 index,
2365 name.as_ptr() as *const native_gl::GLchar,
2366 );
2367 }
2368
2369 unsafe fn get_active_attributes(&self, program: Self::Program) -> u32 {
2370 let gl = &self.raw;
2371 let mut count = 0;
2372 gl.GetProgramiv(program.0.get(), ACTIVE_ATTRIBUTES, &mut count);
2373 count as u32
2374 }
2375
2376 unsafe fn get_active_attribute(
2377 &self,
2378 program: Self::Program,
2379 index: u32,
2380 ) -> Option<ActiveAttribute> {
2381 let gl = &self.raw;
2382 let mut attribute_max_size = 0;
2383 gl.GetProgramiv(
2384 program.0.get(),
2385 ACTIVE_ATTRIBUTE_MAX_LENGTH,
2386 &mut attribute_max_size,
2387 );
2388 let mut name = String::with_capacity(attribute_max_size as usize);
2389 name.extend(std::iter::repeat('\0').take(attribute_max_size as usize));
2390 let mut length = 0;
2391 let mut size = 0;
2392 let mut atype = 0;
2393 gl.GetActiveAttrib(
2394 program.0.get(),
2395 index,
2396 attribute_max_size,
2397 &mut length,
2398 &mut size,
2399 &mut atype,
2400 name.as_ptr() as *mut native_gl::GLchar,
2401 );
2402
2403 name.truncate(length as usize);
2404
2405 Some(ActiveAttribute { name, size, atype })
2406 }
2407
2408 unsafe fn get_sync_status(&self, fence: Self::Fence) -> u32 {
2409 let gl = &self.raw;
2410 let mut len = 0;
2411 let mut values = [UNSIGNALED as i32];
2412 gl.GetSynciv(
2413 fence.0,
2414 SYNC_STATUS,
2415 values.len() as i32,
2416 &mut len,
2417 values.as_mut_ptr(),
2418 );
2419 values[0] as u32
2420 }
2421
2422 unsafe fn is_sync(&self, fence: Self::Fence) -> bool {
2423 let gl = &self.raw;
2424 1 == gl.IsSync(fence.0)
2425 }
2426
2427 unsafe fn renderbuffer_storage(
2428 &self,
2429 target: u32,
2430 internal_format: u32,
2431 width: i32,
2432 height: i32,
2433 ) {
2434 let gl = &self.raw;
2435 gl.RenderbufferStorage(target, internal_format, width, height);
2436 }
2437
2438 unsafe fn renderbuffer_storage_multisample(
2439 &self,
2440 target: u32,
2441 samples: i32,
2442 internal_format: u32,
2443 width: i32,
2444 height: i32,
2445 ) {
2446 let gl = &self.raw;
2447 gl.RenderbufferStorageMultisample(target, samples, internal_format, width, height);
2448 }
2449
2450 unsafe fn sampler_parameter_f32(&self, sampler: Self::Sampler, name: u32, value: f32) {
2451 let gl = &self.raw;
2452 gl.SamplerParameterf(sampler.0.get(), name, value);
2453 }
2454
2455 unsafe fn sampler_parameter_f32_slice(&self, sampler: Self::Sampler, name: u32, value: &[f32]) {
2456 let gl = &self.raw;
2457 gl.SamplerParameterfv(sampler.0.get(), name, value.as_ptr());
2458 }
2459
2460 unsafe fn sampler_parameter_i32(&self, sampler: Self::Sampler, name: u32, value: i32) {
2461 let gl = &self.raw;
2462 gl.SamplerParameteri(sampler.0.get(), name, value);
2463 }
2464
2465 unsafe fn get_sampler_parameter_i32(&self, sampler: Self::Sampler, name: u32) -> i32 {
2466 let gl = &self.raw;
2467 let mut value = 0;
2468 gl.GetSamplerParameteriv(sampler.0.get(), name, &mut value);
2469 value
2470 }
2471
2472 unsafe fn get_sampler_parameter_f32(&self, sampler: Self::Sampler, name: u32) -> f32 {
2473 let gl = &self.raw;
2474 let mut value = 0.;
2475 gl.GetSamplerParameterfv(sampler.0.get(), name, &mut value);
2476 value
2477 }
2478
2479 unsafe fn generate_mipmap(&self, target: u32) {
2480 let gl = &self.raw;
2481 gl.GenerateMipmap(target);
2482 }
2483
2484 unsafe fn generate_texture_mipmap(&self, texture: Self::Texture) {
2485 let gl = &self.raw;
2486 gl.GenerateTextureMipmap(texture.0.get());
2487 }
2488
2489 unsafe fn tex_image_1d(
2490 &self,
2491 target: u32,
2492 level: i32,
2493 internal_format: i32,
2494 width: i32,
2495 border: i32,
2496 format: u32,
2497 ty: u32,
2498 pixels: PixelUnpackData,
2499 ) {
2500 let gl = &self.raw;
2501 gl.TexImage1D(
2502 target,
2503 level,
2504 internal_format,
2505 width,
2506 border,
2507 format,
2508 ty,
2509 match pixels {
2510 PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
2511 PixelUnpackData::Slice(Some(data)) => data.as_ptr() as *const std::ffi::c_void,
2512 PixelUnpackData::Slice(None) => ptr::null(),
2513 },
2514 );
2515 }
2516
2517 unsafe fn compressed_tex_image_1d(
2518 &self,
2519 target: u32,
2520 level: i32,
2521 internal_format: i32,
2522 width: i32,
2523 border: i32,
2524 image_size: i32,
2525 pixels: &[u8],
2526 ) {
2527 let gl = &self.raw;
2528 gl.CompressedTexImage1D(
2529 target,
2530 level,
2531 internal_format as u32,
2532 width,
2533 border,
2534 image_size,
2535 pixels.as_ptr() as *const std::ffi::c_void,
2536 );
2537 }
2538
2539 unsafe fn tex_image_2d(
2540 &self,
2541 target: u32,
2542 level: i32,
2543 internal_format: i32,
2544 width: i32,
2545 height: i32,
2546 border: i32,
2547 format: u32,
2548 ty: u32,
2549 pixels: PixelUnpackData,
2550 ) {
2551 let gl = &self.raw;
2552 gl.TexImage2D(
2553 target,
2554 level,
2555 internal_format,
2556 width,
2557 height,
2558 border,
2559 format,
2560 ty,
2561 match pixels {
2562 PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
2563 PixelUnpackData::Slice(Some(data)) => data.as_ptr() as *const std::ffi::c_void,
2564 PixelUnpackData::Slice(None) => ptr::null(),
2565 },
2566 );
2567 }
2568
2569 unsafe fn tex_image_2d_multisample(
2570 &self,
2571 target: u32,
2572 samples: i32,
2573 internal_format: i32,
2574 width: i32,
2575 height: i32,
2576 fixed_sample_locations: bool,
2577 ) {
2578 let gl = &self.raw;
2579 gl.TexImage2DMultisample(
2580 target,
2581 samples,
2582 internal_format as u32,
2583 width,
2584 height,
2585 if fixed_sample_locations { 1 } else { 0 },
2586 );
2587 }
2588
2589 unsafe fn compressed_tex_image_2d(
2590 &self,
2591 target: u32,
2592 level: i32,
2593 internal_format: i32,
2594 width: i32,
2595 height: i32,
2596 border: i32,
2597 image_size: i32,
2598 pixels: &[u8],
2599 ) {
2600 let gl = &self.raw;
2601 gl.CompressedTexImage2D(
2602 target,
2603 level,
2604 internal_format as u32,
2605 width,
2606 height,
2607 border,
2608 image_size,
2609 pixels.as_ptr() as *const std::ffi::c_void,
2610 );
2611 }
2612
2613 unsafe fn tex_image_3d(
2614 &self,
2615 target: u32,
2616 level: i32,
2617 internal_format: i32,
2618 width: i32,
2619 height: i32,
2620 depth: i32,
2621 border: i32,
2622 format: u32,
2623 ty: u32,
2624 pixels: PixelUnpackData,
2625 ) {
2626 let gl = &self.raw;
2627 gl.TexImage3D(
2628 target,
2629 level,
2630 internal_format,
2631 width,
2632 height,
2633 depth,
2634 border,
2635 format,
2636 ty,
2637 match pixels {
2638 PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
2639 PixelUnpackData::Slice(Some(data)) => data.as_ptr() as *const std::ffi::c_void,
2640 PixelUnpackData::Slice(None) => ptr::null(),
2641 },
2642 );
2643 }
2644
2645 unsafe fn compressed_tex_image_3d(
2646 &self,
2647 target: u32,
2648 level: i32,
2649 internal_format: i32,
2650 width: i32,
2651 height: i32,
2652 depth: i32,
2653 border: i32,
2654 image_size: i32,
2655 pixels: &[u8],
2656 ) {
2657 let gl = &self.raw;
2658 gl.CompressedTexImage3D(
2659 target,
2660 level,
2661 internal_format as u32,
2662 width,
2663 height,
2664 depth,
2665 border,
2666 image_size,
2667 pixels.as_ptr() as *const std::ffi::c_void,
2668 );
2669 }
2670
2671 unsafe fn tex_storage_1d(&self, target: u32, levels: i32, internal_format: u32, width: i32) {
2672 let gl = &self.raw;
2673 gl.TexStorage1D(target, levels, internal_format, width);
2674 }
2675
2676 unsafe fn tex_storage_2d(
2677 &self,
2678 target: u32,
2679 levels: i32,
2680 internal_format: u32,
2681 width: i32,
2682 height: i32,
2683 ) {
2684 let gl = &self.raw;
2685 gl.TexStorage2D(target, levels, internal_format, width, height);
2686 }
2687
2688 unsafe fn texture_storage_2d(
2689 &self,
2690 texture: Self::Texture,
2691 levels: i32,
2692 internal_format: u32,
2693 width: i32,
2694 height: i32,
2695 ) {
2696 let gl = &self.raw;
2697 gl.TextureStorage2D(texture.0.get(), levels, internal_format, width, height);
2698 }
2699
2700 unsafe fn tex_storage_2d_multisample(
2701 &self,
2702 target: u32,
2703 samples: i32,
2704 internal_format: u32,
2705 width: i32,
2706 height: i32,
2707 fixed_sample_locations: bool,
2708 ) {
2709 let gl = &self.raw;
2710 gl.TexStorage2DMultisample(
2711 target,
2712 samples,
2713 internal_format,
2714 width,
2715 height,
2716 if fixed_sample_locations { 1 } else { 0 },
2717 );
2718 }
2719
2720 unsafe fn tex_storage_3d(
2721 &self,
2722 target: u32,
2723 levels: i32,
2724 internal_format: u32,
2725 width: i32,
2726 height: i32,
2727 depth: i32,
2728 ) {
2729 let gl = &self.raw;
2730 gl.TexStorage3D(target, levels, internal_format, width, height, depth);
2731 }
2732
2733 unsafe fn texture_storage_3d(
2734 &self,
2735 texture: Self::Texture,
2736 levels: i32,
2737 internal_format: u32,
2738 width: i32,
2739 height: i32,
2740 depth: i32,
2741 ) {
2742 let gl = &self.raw;
2743 gl.TextureStorage3D(
2744 texture.0.get(),
2745 levels,
2746 internal_format,
2747 width,
2748 height,
2749 depth,
2750 );
2751 }
2752
2753 unsafe fn get_uniform_i32(
2754 &self,
2755 program: Self::Program,
2756 location: &Self::UniformLocation,
2757 v: &mut [i32],
2758 ) {
2759 let gl = &self.raw;
2760 gl.GetUniformiv(program.0.get(), location.0 as i32, v.as_mut_ptr())
2761 }
2762
2763 unsafe fn get_uniform_u32(
2764 &self,
2765 program: Self::Program,
2766 location: &Self::UniformLocation,
2767 v: &mut [u32],
2768 ) {
2769 let gl = &self.raw;
2770 gl.GetUniformuiv(program.0.get(), location.0 as i32, v.as_mut_ptr())
2771 }
2772
2773 unsafe fn get_uniform_f32(
2774 &self,
2775 program: Self::Program,
2776 location: &Self::UniformLocation,
2777 v: &mut [f32],
2778 ) {
2779 let gl = &self.raw;
2780 gl.GetUniformfv(program.0.get(), location.0 as i32, v.as_mut_ptr())
2781 }
2782
2783 unsafe fn uniform_1_i32(&self, location: Option<&Self::UniformLocation>, x: i32) {
2784 let gl = &self.raw;
2785 if let Some(loc) = location {
2786 gl.Uniform1i(loc.0 as i32, x);
2787 }
2788 }
2789
2790 unsafe fn uniform_2_i32(&self, location: Option<&Self::UniformLocation>, x: i32, y: i32) {
2791 let gl = &self.raw;
2792 if let Some(loc) = location {
2793 gl.Uniform2i(loc.0 as i32, x, y);
2794 }
2795 }
2796
2797 unsafe fn uniform_3_i32(
2798 &self,
2799 location: Option<&Self::UniformLocation>,
2800 x: i32,
2801 y: i32,
2802 z: i32,
2803 ) {
2804 let gl = &self.raw;
2805 if let Some(loc) = location {
2806 gl.Uniform3i(loc.0 as i32, x, y, z);
2807 }
2808 }
2809
2810 unsafe fn uniform_4_i32(
2811 &self,
2812 location: Option<&Self::UniformLocation>,
2813 x: i32,
2814 y: i32,
2815 z: i32,
2816 w: i32,
2817 ) {
2818 let gl = &self.raw;
2819 if let Some(loc) = location {
2820 gl.Uniform4i(loc.0 as i32, x, y, z, w);
2821 }
2822 }
2823
2824 unsafe fn uniform_1_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
2825 let gl = &self.raw;
2826 if let Some(loc) = location {
2827 gl.Uniform1iv(loc.0 as i32, v.len() as i32, v.as_ptr());
2828 }
2829 }
2830
2831 unsafe fn uniform_2_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
2832 let gl = &self.raw;
2833 if let Some(loc) = location {
2834 gl.Uniform2iv(loc.0 as i32, v.len() as i32 / 2, v.as_ptr());
2835 }
2836 }
2837
2838 unsafe fn uniform_3_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
2839 let gl = &self.raw;
2840 if let Some(loc) = location {
2841 gl.Uniform3iv(loc.0 as i32, v.len() as i32 / 3, v.as_ptr());
2842 }
2843 }
2844
2845 unsafe fn uniform_4_i32_slice(&self, location: Option<&Self::UniformLocation>, v: &[i32]) {
2846 let gl = &self.raw;
2847 if let Some(loc) = location {
2848 gl.Uniform4iv(loc.0 as i32, v.len() as i32 / 4, v.as_ptr());
2849 }
2850 }
2851
2852 unsafe fn uniform_1_u32(&self, location: Option<&Self::UniformLocation>, x: u32) {
2853 let gl = &self.raw;
2854 if let Some(loc) = location {
2855 gl.Uniform1ui(loc.0 as i32, x);
2856 }
2857 }
2858
2859 unsafe fn uniform_2_u32(&self, location: Option<&Self::UniformLocation>, x: u32, y: u32) {
2860 let gl = &self.raw;
2861 if let Some(loc) = location {
2862 gl.Uniform2ui(loc.0 as i32, x, y);
2863 }
2864 }
2865
2866 unsafe fn uniform_3_u32(
2867 &self,
2868 location: Option<&Self::UniformLocation>,
2869 x: u32,
2870 y: u32,
2871 z: u32,
2872 ) {
2873 let gl = &self.raw;
2874 if let Some(loc) = location {
2875 gl.Uniform3ui(loc.0 as i32, x, y, z);
2876 }
2877 }
2878
2879 unsafe fn uniform_4_u32(
2880 &self,
2881 location: Option<&Self::UniformLocation>,
2882 x: u32,
2883 y: u32,
2884 z: u32,
2885 w: u32,
2886 ) {
2887 let gl = &self.raw;
2888 if let Some(loc) = location {
2889 gl.Uniform4ui(loc.0 as i32, x, y, z, w);
2890 }
2891 }
2892
2893 unsafe fn uniform_1_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
2894 let gl = &self.raw;
2895 if let Some(loc) = location {
2896 gl.Uniform1uiv(loc.0 as i32, v.len() as i32, v.as_ptr());
2897 }
2898 }
2899
2900 unsafe fn uniform_2_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
2901 let gl = &self.raw;
2902 if let Some(loc) = location {
2903 gl.Uniform2uiv(loc.0 as i32, v.len() as i32 / 2, v.as_ptr());
2904 }
2905 }
2906
2907 unsafe fn uniform_3_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
2908 let gl = &self.raw;
2909 if let Some(loc) = location {
2910 gl.Uniform3uiv(loc.0 as i32, v.len() as i32 / 3, v.as_ptr());
2911 }
2912 }
2913
2914 unsafe fn uniform_4_u32_slice(&self, location: Option<&Self::UniformLocation>, v: &[u32]) {
2915 let gl = &self.raw;
2916 if let Some(loc) = location {
2917 gl.Uniform4uiv(loc.0 as i32, v.len() as i32 / 4, v.as_ptr());
2918 }
2919 }
2920
2921 unsafe fn uniform_1_f32(&self, location: Option<&Self::UniformLocation>, x: f32) {
2922 let gl = &self.raw;
2923 if let Some(loc) = location {
2924 gl.Uniform1f(loc.0 as i32, x);
2925 }
2926 }
2927
2928 unsafe fn uniform_2_f32(&self, location: Option<&Self::UniformLocation>, x: f32, y: f32) {
2929 let gl = &self.raw;
2930 if let Some(loc) = location {
2931 gl.Uniform2f(loc.0 as i32, x, y);
2932 }
2933 }
2934
2935 unsafe fn uniform_3_f32(
2936 &self,
2937 location: Option<&Self::UniformLocation>,
2938 x: f32,
2939 y: f32,
2940 z: f32,
2941 ) {
2942 let gl = &self.raw;
2943 if let Some(loc) = location {
2944 gl.Uniform3f(loc.0 as i32, x, y, z);
2945 }
2946 }
2947
2948 unsafe fn uniform_4_f32(
2949 &self,
2950 location: Option<&Self::UniformLocation>,
2951 x: f32,
2952 y: f32,
2953 z: f32,
2954 w: f32,
2955 ) {
2956 let gl = &self.raw;
2957 if let Some(loc) = location {
2958 gl.Uniform4f(loc.0 as i32, x, y, z, w);
2959 }
2960 }
2961
2962 unsafe fn uniform_1_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
2963 let gl = &self.raw;
2964 if let Some(loc) = location {
2965 gl.Uniform1fv(loc.0 as i32, v.len() as i32, v.as_ptr());
2966 }
2967 }
2968
2969 unsafe fn uniform_2_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
2970 let gl = &self.raw;
2971 if let Some(loc) = location {
2972 gl.Uniform2fv(loc.0 as i32, v.len() as i32 / 2, v.as_ptr());
2973 }
2974 }
2975
2976 unsafe fn uniform_3_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
2977 let gl = &self.raw;
2978 if let Some(loc) = location {
2979 gl.Uniform3fv(loc.0 as i32, v.len() as i32 / 3, v.as_ptr());
2980 }
2981 }
2982
2983 unsafe fn uniform_4_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
2984 let gl = &self.raw;
2985 if let Some(loc) = location {
2986 gl.Uniform4fv(loc.0 as i32, v.len() as i32 / 4, v.as_ptr());
2987 }
2988 }
2989
2990 unsafe fn uniform_matrix_2_f32_slice(
2991 &self,
2992 location: Option<&Self::UniformLocation>,
2993 transpose: bool,
2994 v: &[f32],
2995 ) {
2996 let gl = &self.raw;
2997 if let Some(loc) = location {
2998 gl.UniformMatrix2fv(
2999 loc.0 as i32,
3000 v.len() as i32 / 4,
3001 transpose as u8,
3002 v.as_ptr(),
3003 );
3004 }
3005 }
3006
3007 unsafe fn uniform_matrix_2x3_f32_slice(
3008 &self,
3009 location: Option<&Self::UniformLocation>,
3010 transpose: bool,
3011 v: &[f32],
3012 ) {
3013 let gl = &self.raw;
3014 if let Some(loc) = location {
3015 gl.UniformMatrix2x3fv(
3016 loc.0 as i32,
3017 v.len() as i32 / 6,
3018 transpose as u8,
3019 v.as_ptr(),
3020 );
3021 }
3022 }
3023
3024 unsafe fn uniform_matrix_2x4_f32_slice(
3025 &self,
3026 location: Option<&Self::UniformLocation>,
3027 transpose: bool,
3028 v: &[f32],
3029 ) {
3030 let gl = &self.raw;
3031 if let Some(loc) = location {
3032 gl.UniformMatrix2x4fv(
3033 loc.0 as i32,
3034 v.len() as i32 / 8,
3035 transpose as u8,
3036 v.as_ptr(),
3037 );
3038 }
3039 }
3040
3041 unsafe fn uniform_matrix_3x2_f32_slice(
3042 &self,
3043 location: Option<&Self::UniformLocation>,
3044 transpose: bool,
3045 v: &[f32],
3046 ) {
3047 let gl = &self.raw;
3048 if let Some(loc) = location {
3049 gl.UniformMatrix3x2fv(
3050 loc.0 as i32,
3051 v.len() as i32 / 6,
3052 transpose as u8,
3053 v.as_ptr(),
3054 );
3055 }
3056 }
3057
3058 unsafe fn uniform_matrix_3_f32_slice(
3059 &self,
3060 location: Option<&Self::UniformLocation>,
3061 transpose: bool,
3062 v: &[f32],
3063 ) {
3064 let gl = &self.raw;
3065 if let Some(loc) = location {
3066 gl.UniformMatrix3fv(
3067 loc.0 as i32,
3068 v.len() as i32 / 9,
3069 transpose as u8,
3070 v.as_ptr(),
3071 );
3072 }
3073 }
3074
3075 unsafe fn uniform_matrix_3x4_f32_slice(
3076 &self,
3077 location: Option<&Self::UniformLocation>,
3078 transpose: bool,
3079 v: &[f32],
3080 ) {
3081 let gl = &self.raw;
3082 if let Some(loc) = location {
3083 gl.UniformMatrix3x4fv(
3084 loc.0 as i32,
3085 v.len() as i32 / 12,
3086 transpose as u8,
3087 v.as_ptr(),
3088 );
3089 }
3090 }
3091
3092 unsafe fn uniform_matrix_4x2_f32_slice(
3093 &self,
3094 location: Option<&Self::UniformLocation>,
3095 transpose: bool,
3096 v: &[f32],
3097 ) {
3098 let gl = &self.raw;
3099 if let Some(loc) = location {
3100 gl.UniformMatrix4x2fv(
3101 loc.0 as i32,
3102 v.len() as i32 / 8,
3103 transpose as u8,
3104 v.as_ptr(),
3105 );
3106 }
3107 }
3108
3109 unsafe fn uniform_matrix_4x3_f32_slice(
3110 &self,
3111 location: Option<&Self::UniformLocation>,
3112 transpose: bool,
3113 v: &[f32],
3114 ) {
3115 let gl = &self.raw;
3116 if let Some(loc) = location {
3117 gl.UniformMatrix4x3fv(
3118 loc.0 as i32,
3119 v.len() as i32 / 12,
3120 transpose as u8,
3121 v.as_ptr(),
3122 );
3123 }
3124 }
3125
3126 unsafe fn uniform_matrix_4_f32_slice(
3127 &self,
3128 location: Option<&Self::UniformLocation>,
3129 transpose: bool,
3130 v: &[f32],
3131 ) {
3132 let gl = &self.raw;
3133 if let Some(loc) = location {
3134 gl.UniformMatrix4fv(
3135 loc.0 as i32,
3136 v.len() as i32 / 16,
3137 transpose as u8,
3138 v.as_ptr(),
3139 );
3140 }
3141 }
3142
3143 unsafe fn unmap_buffer(&self, target: u32) {
3144 let gl = &self.raw;
3145 gl.UnmapBuffer(target);
3146 }
3147
3148 unsafe fn cull_face(&self, value: u32) {
3149 let gl = &self.raw;
3150 gl.CullFace(value as u32);
3151 }
3152
3153 unsafe fn color_mask(&self, red: bool, green: bool, blue: bool, alpha: bool) {
3154 let gl = &self.raw;
3155 gl.ColorMask(red as u8, green as u8, blue as u8, alpha as u8);
3156 }
3157
3158 unsafe fn color_mask_draw_buffer(
3159 &self,
3160 draw_buffer: u32,
3161 red: bool,
3162 green: bool,
3163 blue: bool,
3164 alpha: bool,
3165 ) {
3166 let gl = &self.raw;
3167 gl.ColorMaski(draw_buffer, red as u8, green as u8, blue as u8, alpha as u8);
3168 }
3169
3170 unsafe fn depth_mask(&self, value: bool) {
3171 let gl = &self.raw;
3172 gl.DepthMask(value as u8);
3173 }
3174
3175 unsafe fn blend_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
3176 let gl = &self.raw;
3177 gl.BlendColor(red, green, blue, alpha);
3178 }
3179
3180 unsafe fn line_width(&self, width: f32) {
3181 let gl = &self.raw;
3182 gl.LineWidth(width);
3183 }
3184
3185 unsafe fn map_buffer_range(
3186 &self,
3187 target: u32,
3188 offset: i32,
3189 length: i32,
3190 access: u32,
3191 ) -> *mut u8 {
3192 let gl = &self.raw;
3193 gl.MapBufferRange(target, offset as isize, length as isize, access) as *mut u8
3194 }
3195
3196 unsafe fn flush_mapped_buffer_range(&self, target: u32, offset: i32, length: i32) {
3197 let gl = &self.raw;
3198 gl.FlushMappedBufferRange(target, offset as isize, length as isize)
3199 }
3200
3201 unsafe fn invalidate_buffer_sub_data(&self, target: u32, offset: i32, length: i32) {
3202 let gl = &self.raw;
3203 gl.InvalidateBufferSubData(target, offset as isize, length as isize)
3204 }
3205
3206 unsafe fn invalidate_framebuffer(&self, target: u32, attachments: &[u32]) {
3207 let gl = &self.raw;
3208 gl.InvalidateFramebuffer(target, attachments.len() as i32, attachments.as_ptr());
3209 }
3210
3211 unsafe fn invalidate_sub_framebuffer(
3212 &self,
3213 target: u32,
3214 attachments: &[u32],
3215 x: i32,
3216 y: i32,
3217 width: i32,
3218 height: i32,
3219 ) {
3220 let gl = &self.raw;
3221 gl.InvalidateSubFramebuffer(
3222 target,
3223 attachments.len() as i32,
3224 attachments.as_ptr(),
3225 x,
3226 y,
3227 width,
3228 height,
3229 );
3230 }
3231
3232 unsafe fn polygon_offset(&self, factor: f32, units: f32) {
3233 let gl = &self.raw;
3234 gl.PolygonOffset(factor, units);
3235 }
3236
3237 unsafe fn polygon_mode(&self, face: u32, mode: u32) {
3238 let gl = &self.raw;
3239 gl.PolygonMode(face as u32, mode as u32);
3240 }
3241
3242 unsafe fn finish(&self) {
3243 let gl = &self.raw;
3244 gl.Finish();
3245 }
3246
3247 unsafe fn bind_texture(&self, target: u32, texture: Option<Self::Texture>) {
3248 let gl = &self.raw;
3249 gl.BindTexture(target, texture.map(|t| t.0.get()).unwrap_or(0));
3250 }
3251
3252 unsafe fn bind_texture_unit(&self, unit: u32, texture: Option<Self::Texture>) {
3253 let gl = &self.raw;
3254 gl.BindTextureUnit(unit, texture.map(|t| t.0.get()).unwrap_or(0));
3255 }
3256
3257 unsafe fn bind_sampler(&self, unit: u32, sampler: Option<Self::Sampler>) {
3258 let gl = &self.raw;
3259 gl.BindSampler(unit, sampler.map(|s| s.0.get()).unwrap_or(0));
3260 }
3261
3262 unsafe fn active_texture(&self, unit: u32) {
3263 let gl = &self.raw;
3264 gl.ActiveTexture(unit);
3265 }
3266
3267 unsafe fn fence_sync(&self, condition: u32, flags: u32) -> Result<Self::Fence, String> {
3268 let gl = &self.raw;
3269 Ok(NativeFence(gl.FenceSync(condition as u32, flags)))
3270 }
3271
3272 unsafe fn tex_parameter_f32(&self, target: u32, parameter: u32, value: f32) {
3273 let gl = &self.raw;
3274 gl.TexParameterf(target, parameter, value);
3275 }
3276
3277 unsafe fn tex_parameter_i32(&self, target: u32, parameter: u32, value: i32) {
3278 let gl = &self.raw;
3279 gl.TexParameteri(target, parameter, value);
3280 }
3281
3282 unsafe fn texture_parameter_i32(&self, texture: Self::Texture, parameter: u32, value: i32) {
3283 let gl = &self.raw;
3284 gl.TextureParameteri(texture.0.get(), parameter, value);
3285 }
3286
3287 unsafe fn tex_parameter_f32_slice(&self, target: u32, parameter: u32, values: &[f32]) {
3288 let gl = &self.raw;
3289 gl.TexParameterfv(target, parameter, values.as_ptr());
3290 }
3291
3292 unsafe fn tex_parameter_i32_slice(&self, target: u32, parameter: u32, values: &[i32]) {
3293 let gl = &self.raw;
3294 gl.TexParameteriv(target, parameter, values.as_ptr());
3295 }
3296
3297 unsafe fn tex_sub_image_2d(
3298 &self,
3299 target: u32,
3300 level: i32,
3301 x_offset: i32,
3302 y_offset: i32,
3303 width: i32,
3304 height: i32,
3305 format: u32,
3306 ty: u32,
3307 pixels: PixelUnpackData,
3308 ) {
3309 let gl = &self.raw;
3310 gl.TexSubImage2D(
3311 target,
3312 level,
3313 x_offset,
3314 y_offset,
3315 width,
3316 height,
3317 format,
3318 ty,
3319 match pixels {
3320 PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
3321 PixelUnpackData::Slice(Some(data)) => data.as_ptr() as *const std::ffi::c_void,
3322 PixelUnpackData::Slice(None) => ptr::null(),
3323 },
3324 );
3325 }
3326
3327 unsafe fn texture_sub_image_2d(
3328 &self,
3329 texture: Self::Texture,
3330 level: i32,
3331 x_offset: i32,
3332 y_offset: i32,
3333 width: i32,
3334 height: i32,
3335 format: u32,
3336 ty: u32,
3337 pixels: PixelUnpackData,
3338 ) {
3339 let gl = &self.raw;
3340 gl.TextureSubImage2D(
3341 texture.0.get(),
3342 level,
3343 x_offset,
3344 y_offset,
3345 width,
3346 height,
3347 format,
3348 ty,
3349 match pixels {
3350 PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
3351 PixelUnpackData::Slice(Some(data)) => data.as_ptr() as *const std::ffi::c_void,
3352 PixelUnpackData::Slice(None) => ptr::null(),
3353 },
3354 );
3355 }
3356
3357 unsafe fn compressed_tex_sub_image_2d(
3358 &self,
3359 target: u32,
3360 level: i32,
3361 x_offset: i32,
3362 y_offset: i32,
3363 width: i32,
3364 height: i32,
3365 format: u32,
3366 pixels: CompressedPixelUnpackData,
3367 ) {
3368 let gl = &self.raw;
3369 let (data, image_size) = match pixels {
3370 CompressedPixelUnpackData::BufferRange(ref range) => (
3371 range.start as *const std::ffi::c_void,
3372 (range.end - range.start) as i32,
3373 ),
3374 CompressedPixelUnpackData::Slice(data) => {
3375 (data.as_ptr() as *const std::ffi::c_void, data.len() as i32)
3376 }
3377 };
3378
3379 gl.CompressedTexSubImage2D(
3380 target, level, x_offset, y_offset, width, height, format, image_size, data,
3381 );
3382 }
3383
3384 unsafe fn tex_sub_image_3d(
3385 &self,
3386 target: u32,
3387 level: i32,
3388 x_offset: i32,
3389 y_offset: i32,
3390 z_offset: i32,
3391 width: i32,
3392 height: i32,
3393 depth: i32,
3394 format: u32,
3395 ty: u32,
3396 pixels: PixelUnpackData,
3397 ) {
3398 let gl = &self.raw;
3399 gl.TexSubImage3D(
3400 target,
3401 level,
3402 x_offset,
3403 y_offset,
3404 z_offset,
3405 width,
3406 height,
3407 depth,
3408 format,
3409 ty,
3410 match pixels {
3411 PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
3412 PixelUnpackData::Slice(Some(data)) => data.as_ptr() as *const std::ffi::c_void,
3413 PixelUnpackData::Slice(None) => ptr::null(),
3414 },
3415 );
3416 }
3417
3418 unsafe fn texture_sub_image_3d(
3419 &self,
3420 texture: Self::Texture,
3421 level: i32,
3422 x_offset: i32,
3423 y_offset: i32,
3424 z_offset: i32,
3425 width: i32,
3426 height: i32,
3427 depth: i32,
3428 format: u32,
3429 ty: u32,
3430 pixels: PixelUnpackData,
3431 ) {
3432 let gl = &self.raw;
3433 gl.TextureSubImage3D(
3434 texture.0.get(),
3435 level,
3436 x_offset,
3437 y_offset,
3438 z_offset,
3439 width,
3440 height,
3441 depth,
3442 format,
3443 ty,
3444 match pixels {
3445 PixelUnpackData::BufferOffset(offset) => offset as *const std::ffi::c_void,
3446 PixelUnpackData::Slice(Some(data)) => data.as_ptr() as *const std::ffi::c_void,
3447 PixelUnpackData::Slice(None) => ptr::null(),
3448 },
3449 );
3450 }
3451
3452 unsafe fn compressed_tex_sub_image_3d(
3453 &self,
3454 target: u32,
3455 level: i32,
3456 x_offset: i32,
3457 y_offset: i32,
3458 z_offset: i32,
3459 width: i32,
3460 height: i32,
3461 depth: i32,
3462 format: u32,
3463 pixels: CompressedPixelUnpackData,
3464 ) {
3465 let gl = &self.raw;
3466 let (data, image_size) = match pixels {
3467 CompressedPixelUnpackData::BufferRange(ref range) => (
3468 range.start as *const std::ffi::c_void,
3469 (range.end - range.start) as i32,
3470 ),
3471 CompressedPixelUnpackData::Slice(data) => {
3472 (data.as_ptr() as *const std::ffi::c_void, data.len() as i32)
3473 }
3474 };
3475
3476 gl.CompressedTexSubImage3D(
3477 target, level, x_offset, y_offset, z_offset, width, height, depth, format, image_size,
3478 data,
3479 );
3480 }
3481
3482 unsafe fn depth_func(&self, func: u32) {
3483 let gl = &self.raw;
3484 gl.DepthFunc(func as u32);
3485 }
3486
3487 unsafe fn depth_range_f32(&self, near: f32, far: f32) {
3488 let gl = &self.raw;
3489 gl.DepthRangef(near, far);
3490 }
3491
3492 unsafe fn depth_range_f64(&self, near: f64, far: f64) {
3493 let gl = &self.raw;
3494 gl.DepthRange(near, far);
3495 }
3496
3497 unsafe fn depth_range(&self, near: f64, far: f64) {
3498 if self.supports_f64_precision() {
3499 self.depth_range_f64(near, far);
3500 } else {
3501 self.depth_range_f32(near as f32, far as f32);
3502 }
3503 }
3504
3505 unsafe fn depth_range_f64_slice(&self, first: u32, count: i32, values: &[[f64; 2]]) {
3506 let gl = &self.raw;
3507 gl.DepthRangeArrayv(first, count, values.as_ptr() as *const f64);
3508 }
3509
3510 unsafe fn scissor(&self, x: i32, y: i32, width: i32, height: i32) {
3511 let gl = &self.raw;
3512 gl.Scissor(x, y, width, height);
3513 }
3514
3515 unsafe fn scissor_slice(&self, first: u32, count: i32, scissors: &[[i32; 4]]) {
3516 let gl = &self.raw;
3517 gl.ScissorArrayv(first, count, scissors.as_ptr() as *const i32);
3518 }
3519
3520 unsafe fn vertex_array_attrib_binding_f32(
3521 &self,
3522 vao: Self::VertexArray,
3523 index: u32,
3524 binding_index: u32,
3525 ) {
3526 let gl = &self.raw;
3527 gl.VertexArrayAttribBinding(vao.0.get(), index, binding_index);
3528 }
3529
3530 unsafe fn vertex_array_attrib_format_f32(
3531 &self,
3532 vao: Self::VertexArray,
3533 index: u32,
3534 size: i32,
3535 data_type: u32,
3536 normalized: bool,
3537 relative_offset: u32,
3538 ) {
3539 let gl = &self.raw;
3540 gl.VertexArrayAttribFormat(
3541 vao.0.get(),
3542 index,
3543 size,
3544 data_type,
3545 normalized as u8,
3546 relative_offset,
3547 );
3548 }
3549
3550 unsafe fn vertex_array_attrib_format_i32(
3551 &self,
3552 vao: Self::VertexArray,
3553 index: u32,
3554 size: i32,
3555 data_type: u32,
3556 relative_offset: u32,
3557 ) {
3558 let gl = &self.raw;
3559 gl.VertexArrayAttribIFormat(vao.0.get(), index, size, data_type, relative_offset);
3560 }
3561
3562 unsafe fn vertex_array_attrib_format_f64(
3563 &self,
3564 vao: Self::VertexArray,
3565 index: u32,
3566 size: i32,
3567 data_type: u32,
3568 relative_offset: u32,
3569 ) {
3570 let gl = &self.raw;
3571 gl.VertexArrayAttribLFormat(vao.0.get(), index, size, data_type, relative_offset);
3572 }
3573
3574 unsafe fn vertex_array_element_buffer(
3575 &self,
3576 vao: Self::VertexArray,
3577 buffer: Option<Self::Buffer>,
3578 ) {
3579 let gl = &self.raw;
3580 gl.VertexArrayElementBuffer(vao.0.get(), buffer.map(|b| b.0.get()).unwrap_or(0));
3581 }
3582
3583 unsafe fn vertex_array_vertex_buffer(
3584 &self,
3585 vao: Self::VertexArray,
3586 binding_index: u32,
3587 buffer: Option<Self::Buffer>,
3588 offset: i32,
3589 stride: i32,
3590 ) {
3591 let gl = &self.raw;
3592 gl.VertexArrayVertexBuffer(
3593 vao.0.get(),
3594 binding_index,
3595 buffer.map(|b| b.0.get()).unwrap_or(0),
3596 offset as isize,
3597 stride,
3598 );
3599 }
3600
3601 unsafe fn vertex_attrib_divisor(&self, index: u32, divisor: u32) {
3602 let gl = &self.raw;
3603 gl.VertexAttribDivisor(index, divisor);
3604 }
3605
3606 unsafe fn get_vertex_attrib_parameter_f32_slice(
3607 &self,
3608 index: u32,
3609 pname: u32,
3610 result: &mut [f32],
3611 ) {
3612 let gl = &self.raw;
3613 gl.GetVertexAttribfv(index, pname, result.as_mut_ptr());
3614 }
3615
3616 unsafe fn vertex_attrib_pointer_f32(
3617 &self,
3618 index: u32,
3619 size: i32,
3620 data_type: u32,
3621 normalized: bool,
3622 stride: i32,
3623 offset: i32,
3624 ) {
3625 let gl = &self.raw;
3626 gl.VertexAttribPointer(
3627 index,
3628 size,
3629 data_type,
3630 normalized as u8,
3631 stride,
3632 offset as *const std::ffi::c_void,
3633 );
3634 }
3635
3636 unsafe fn vertex_attrib_pointer_i32(
3637 &self,
3638 index: u32,
3639 size: i32,
3640 data_type: u32,
3641 stride: i32,
3642 offset: i32,
3643 ) {
3644 let gl = &self.raw;
3645 gl.VertexAttribIPointer(
3646 index,
3647 size,
3648 data_type,
3649 stride,
3650 offset as *const std::ffi::c_void,
3651 );
3652 }
3653
3654 unsafe fn vertex_attrib_pointer_f64(
3655 &self,
3656 index: u32,
3657 size: i32,
3658 data_type: u32,
3659 stride: i32,
3660 offset: i32,
3661 ) {
3662 let gl = &self.raw;
3663 gl.VertexAttribLPointer(
3664 index,
3665 size,
3666 data_type,
3667 stride,
3668 offset as *const std::ffi::c_void,
3669 );
3670 }
3671
3672 unsafe fn vertex_attrib_format_f32(
3673 &self,
3674 index: u32,
3675 size: i32,
3676 data_type: u32,
3677 normalized: bool,
3678 relative_offset: u32,
3679 ) {
3680 let gl = &self.raw;
3681 gl.VertexAttribFormat(index, size, data_type, normalized as u8, relative_offset);
3682 }
3683
3684 unsafe fn vertex_attrib_format_i32(
3685 &self,
3686 index: u32,
3687 size: i32,
3688 data_type: u32,
3689 relative_offset: u32,
3690 ) {
3691 let gl = &self.raw;
3692 gl.VertexAttribIFormat(index, size, data_type, relative_offset);
3693 }
3694
3695 unsafe fn vertex_attrib_format_f64(
3696 &self,
3697 index: u32,
3698 size: i32,
3699 data_type: u32,
3700 relative_offset: u32,
3701 ) {
3702 let gl = &self.raw;
3703 gl.VertexAttribLFormat(index, size, data_type, relative_offset);
3704 }
3705
3706 unsafe fn vertex_attrib_1_f32(&self, index: u32, x: f32) {
3707 let gl = &self.raw;
3708 gl.VertexAttrib1f(index, x);
3709 }
3710
3711 unsafe fn vertex_attrib_2_f32(&self, index: u32, x: f32, y: f32) {
3712 let gl = &self.raw;
3713 gl.VertexAttrib2f(index, x, y);
3714 }
3715
3716 unsafe fn vertex_attrib_3_f32(&self, index: u32, x: f32, y: f32, z: f32) {
3717 let gl = &self.raw;
3718 gl.VertexAttrib3f(index, x, y, z);
3719 }
3720
3721 unsafe fn vertex_attrib_4_f32(&self, index: u32, x: f32, y: f32, z: f32, w: f32) {
3722 let gl = &self.raw;
3723 gl.VertexAttrib4f(index, x, y, z, w);
3724 }
3725
3726 unsafe fn vertex_attrib_4_i32(&self, index: u32, x: i32, y: i32, z: i32, w: i32) {
3727 let gl = &self.raw;
3728 gl.VertexAttribI4i(index, x, y, z, w);
3729 }
3730
3731 unsafe fn vertex_attrib_4_u32(&self, index: u32, x: u32, y: u32, z: u32, w: u32) {
3732 let gl = &self.raw;
3733 gl.VertexAttribI4ui(index, x, y, z, w);
3734 }
3735
3736 unsafe fn vertex_attrib_1_f32_slice(&self, index: u32, v: &[f32]) {
3737 let gl = &self.raw;
3738 gl.VertexAttrib1fv(index, v.as_ptr());
3739 }
3740
3741 unsafe fn vertex_attrib_2_f32_slice(&self, index: u32, v: &[f32]) {
3742 let gl = &self.raw;
3743 gl.VertexAttrib2fv(index, v.as_ptr());
3744 }
3745
3746 unsafe fn vertex_attrib_3_f32_slice(&self, index: u32, v: &[f32]) {
3747 let gl = &self.raw;
3748 gl.VertexAttrib3fv(index, v.as_ptr());
3749 }
3750
3751 unsafe fn vertex_attrib_4_f32_slice(&self, index: u32, v: &[f32]) {
3752 let gl = &self.raw;
3753 gl.VertexAttrib4fv(index, v.as_ptr());
3754 }
3755
3756 unsafe fn vertex_attrib_binding(&self, attrib_index: u32, binding_index: u32) {
3757 let gl = &self.raw;
3758 gl.VertexAttribBinding(attrib_index, binding_index);
3759 }
3760
3761 unsafe fn vertex_binding_divisor(&self, binding_index: u32, divisor: u32) {
3762 let gl = &self.raw;
3763 gl.VertexBindingDivisor(binding_index, divisor);
3764 }
3765
3766 unsafe fn viewport(&self, x: i32, y: i32, width: i32, height: i32) {
3767 let gl = &self.raw;
3768 gl.Viewport(x, y, width, height);
3769 }
3770
3771 unsafe fn viewport_f32_slice(&self, first: u32, count: i32, values: &[[f32; 4]]) {
3772 let gl = &self.raw;
3773 gl.ViewportArrayv(first, count, values.as_ptr() as *const f32);
3774 }
3775
3776 unsafe fn blend_equation(&self, mode: u32) {
3777 let gl = &self.raw;
3778 gl.BlendEquation(mode as u32);
3779 }
3780
3781 unsafe fn blend_equation_draw_buffer(&self, draw_buffer: u32, mode: u32) {
3782 let gl = &self.raw;
3783 gl.BlendEquationi(draw_buffer, mode as u32);
3784 }
3785
3786 unsafe fn blend_equation_separate(&self, mode_rgb: u32, mode_alpha: u32) {
3787 let gl = &self.raw;
3788 gl.BlendEquationSeparate(mode_rgb as u32, mode_alpha as u32);
3789 }
3790
3791 unsafe fn blend_equation_separate_draw_buffer(
3792 &self,
3793 draw_buffer: u32,
3794 mode_rgb: u32,
3795 mode_alpha: u32,
3796 ) {
3797 let gl = &self.raw;
3798 gl.BlendEquationSeparatei(draw_buffer, mode_rgb as u32, mode_alpha as u32);
3799 }
3800
3801 unsafe fn blend_func(&self, src: u32, dst: u32) {
3802 let gl = &self.raw;
3803 gl.BlendFunc(src as u32, dst as u32);
3804 }
3805
3806 unsafe fn blend_func_draw_buffer(&self, draw_buffer: u32, src: u32, dst: u32) {
3807 let gl = &self.raw;
3808 gl.BlendFunci(draw_buffer, src as u32, dst as u32);
3809 }
3810
3811 unsafe fn blend_func_separate(
3812 &self,
3813 src_rgb: u32,
3814 dst_rgb: u32,
3815 src_alpha: u32,
3816 dst_alpha: u32,
3817 ) {
3818 let gl = &self.raw;
3819 gl.BlendFuncSeparate(
3820 src_rgb as u32,
3821 dst_rgb as u32,
3822 src_alpha as u32,
3823 dst_alpha as u32,
3824 );
3825 }
3826
3827 unsafe fn blend_func_separate_draw_buffer(
3828 &self,
3829 draw_buffer: u32,
3830 src_rgb: u32,
3831 dst_rgb: u32,
3832 src_alpha: u32,
3833 dst_alpha: u32,
3834 ) {
3835 let gl = &self.raw;
3836 gl.BlendFuncSeparatei(
3837 draw_buffer,
3838 src_rgb as u32,
3839 dst_rgb as u32,
3840 src_alpha as u32,
3841 dst_alpha as u32,
3842 );
3843 }
3844
3845 unsafe fn stencil_func(&self, func: u32, reference: i32, mask: u32) {
3846 let gl = &self.raw;
3847 gl.StencilFunc(func as u32, reference, mask);
3848 }
3849
3850 unsafe fn stencil_func_separate(&self, face: u32, func: u32, reference: i32, mask: u32) {
3851 let gl = &self.raw;
3852 gl.StencilFuncSeparate(face as u32, func as u32, reference, mask);
3853 }
3854
3855 unsafe fn stencil_mask(&self, mask: u32) {
3856 let gl = &self.raw;
3857 gl.StencilMask(mask);
3858 }
3859
3860 unsafe fn stencil_mask_separate(&self, face: u32, mask: u32) {
3861 let gl = &self.raw;
3862 gl.StencilMaskSeparate(face as u32, mask);
3863 }
3864
3865 unsafe fn stencil_op(&self, stencil_fail: u32, depth_fail: u32, pass: u32) {
3866 let gl = &self.raw;
3867 gl.StencilOp(stencil_fail as u32, depth_fail as u32, pass as u32);
3868 }
3869
3870 unsafe fn stencil_op_separate(&self, face: u32, stencil_fail: u32, depth_fail: u32, pass: u32) {
3871 let gl = &self.raw;
3872 gl.StencilOpSeparate(
3873 face as u32,
3874 stencil_fail as u32,
3875 depth_fail as u32,
3876 pass as u32,
3877 );
3878 }
3879
3880 unsafe fn debug_message_control(
3881 &self,
3882 source: u32,
3883 msg_type: u32,
3884 severity: u32,
3885 ids: &[u32],
3886 enabled: bool,
3887 ) {
3888 let gl = &self.raw;
3889
3890 let ids_ptr = if ids.is_empty() {
3891 std::ptr::null()
3892 } else {
3893 ids.as_ptr()
3894 };
3895
3896 gl.DebugMessageControl(
3897 source,
3898 msg_type,
3899 severity,
3900 ids.len() as i32,
3901 ids_ptr,
3902 enabled as u8,
3903 );
3904 }
3905
3906 unsafe fn debug_message_insert<S>(
3907 &self,
3908 source: u32,
3909 msg_type: u32,
3910 id: u32,
3911 severity: u32,
3912 msg: S,
3913 ) where
3914 S: AsRef<str>,
3915 {
3916 let gl = &self.raw;
3917 let message = msg.as_ref().as_bytes();
3918 let length = message.len() as i32;
3919 gl.DebugMessageInsert(
3920 source,
3921 msg_type,
3922 id,
3923 severity,
3924 length,
3925 message.as_ptr() as *const native_gl::GLchar,
3926 );
3927 }
3928
3929 unsafe fn debug_message_callback<F>(&mut self, callback: F)
3930 where
3931 F: Fn(u32, u32, u32, u32, &str) + Send + Sync + 'static,
3932 {
3933 match self.debug_callback {
3934 Some(_) => {
3935 panic!("Debug callback already set");
3936 }
3937 None => {
3938 let trait_object: DebugCallback = Box::new(callback);
3939 let thin_ptr = Box::new(trait_object);
3940 let raw_ptr = Box::into_raw(thin_ptr) as *mut _ as *mut std::ffi::c_void;
3941
3942 let gl = &self.raw;
3943
3944 if gl.DebugMessageCallback_is_loaded() {
3945 gl.DebugMessageCallback(Some(raw_debug_message_callback), raw_ptr);
3946 } else {
3947 gl.DebugMessageCallbackKHR(Some(raw_debug_message_callback), raw_ptr);
3949 }
3950
3951 self.debug_callback = Some(DebugCallbackRawPtr { callback: raw_ptr });
3952 }
3953 }
3954 }
3955
3956 unsafe fn get_debug_message_log(&self, count: u32) -> Vec<DebugMessageLogEntry> {
3957 let ct = count as usize;
3958 let mut sources = Vec::with_capacity(ct);
3959 let mut types = Vec::with_capacity(ct);
3960 let mut ids = Vec::with_capacity(ct);
3961 let mut severities = Vec::with_capacity(ct);
3962 let mut lengths = Vec::with_capacity(ct);
3963 let buf_size = (count * MAX_DEBUG_MESSAGE_LENGTH) as i32;
3964 let mut message_log = Vec::with_capacity(buf_size as usize);
3965
3966 let gl = &self.raw;
3967 let received = gl.GetDebugMessageLog(
3968 count,
3969 buf_size,
3970 sources.as_mut_ptr(),
3971 types.as_mut_ptr(),
3972 ids.as_mut_ptr(),
3973 severities.as_mut_ptr(),
3974 lengths.as_mut_ptr(),
3975 message_log.as_mut_ptr(),
3976 ) as usize;
3977
3978 sources.set_len(received);
3979 types.set_len(received);
3980 ids.set_len(received);
3981 severities.set_len(received);
3982 lengths.set_len(received);
3983 message_log.set_len(buf_size as usize);
3984
3985 let mut entries = Vec::new();
3986 let mut offset = 0;
3987 for i in 0..received {
3988 let message =
3989 std::ffi::CStr::from_ptr(message_log[offset..].as_ptr()).to_string_lossy();
3990 offset += lengths[i] as usize;
3991 entries.push(DebugMessageLogEntry {
3992 source: sources[i],
3993 msg_type: types[i],
3994 id: ids[i],
3995 severity: severities[i],
3996 message: message.to_string(),
3997 });
3998 }
3999
4000 entries
4001 }
4002
4003 unsafe fn push_debug_group<S>(&self, source: u32, id: u32, message: S)
4004 where
4005 S: AsRef<str>,
4006 {
4007 let gl = &self.raw;
4008 let msg = message.as_ref().as_bytes();
4009 let length = msg.len() as i32;
4010 gl.PushDebugGroup(source, id, length, msg.as_ptr() as *const native_gl::GLchar);
4011 }
4012
4013 unsafe fn pop_debug_group(&self) {
4014 let gl = &self.raw;
4015 gl.PopDebugGroup();
4016 }
4017
4018 unsafe fn object_label<S>(&self, identifier: u32, name: u32, label: Option<S>)
4019 where
4020 S: AsRef<str>,
4021 {
4022 let gl = &self.raw;
4023
4024 match label {
4025 Some(l) => {
4026 let lbl = l.as_ref().as_bytes();
4027 let length = lbl.len() as i32;
4028 gl.ObjectLabel(
4029 identifier,
4030 name,
4031 length,
4032 lbl.as_ptr() as *const native_gl::GLchar,
4033 );
4034 }
4035 None => gl.ObjectLabel(identifier, name, 0, std::ptr::null()),
4036 }
4037 }
4038
4039 unsafe fn get_object_label(&self, identifier: u32, name: u32) -> String {
4040 let gl = &self.raw;
4041 let mut len = 0;
4042 let mut label_buf = Vec::with_capacity(self.constants.max_label_length as usize);
4043 gl.GetObjectLabel(
4044 identifier,
4045 name,
4046 self.constants.max_label_length,
4047 &mut len,
4048 label_buf.as_mut_ptr(),
4049 );
4050 label_buf.set_len(len as usize);
4051 std::ffi::CStr::from_ptr(label_buf.as_ptr())
4052 .to_str()
4053 .unwrap()
4054 .to_owned()
4055 }
4056
4057 unsafe fn object_ptr_label<S>(&self, sync: Self::Fence, label: Option<S>)
4058 where
4059 S: AsRef<str>,
4060 {
4061 let gl = &self.raw;
4062
4063 match label {
4064 Some(l) => {
4065 let lbl = l.as_ref().as_bytes();
4066 let length = lbl.len() as i32;
4067 gl.ObjectPtrLabel(
4068 sync.0 as *mut std::ffi::c_void,
4069 length,
4070 lbl.as_ptr() as *const native_gl::GLchar,
4071 );
4072 }
4073 None => gl.ObjectPtrLabel(sync.0 as *mut std::ffi::c_void, 0, std::ptr::null()),
4074 }
4075 }
4076
4077 unsafe fn get_object_ptr_label(&self, sync: Self::Fence) -> String {
4078 let gl = &self.raw;
4079 let mut len = 0;
4080 let mut label_buf = Vec::with_capacity(self.constants.max_label_length as usize);
4081 gl.GetObjectPtrLabel(
4082 sync.0 as *mut std::ffi::c_void,
4083 self.constants.max_label_length,
4084 &mut len,
4085 label_buf.as_mut_ptr(),
4086 );
4087 label_buf.set_len(len as usize);
4088 std::ffi::CStr::from_ptr(label_buf.as_ptr())
4089 .to_str()
4090 .unwrap()
4091 .to_owned()
4092 }
4093
4094 unsafe fn get_uniform_block_index(&self, program: Self::Program, name: &str) -> Option<u32> {
4095 let gl = &self.raw;
4096 let name = CString::new(name).unwrap();
4097 let index = gl.GetUniformBlockIndex(program.0.get(), name.as_ptr());
4098 if index == INVALID_INDEX {
4099 None
4100 } else {
4101 Some(index)
4102 }
4103 }
4104
4105 unsafe fn get_uniform_indices(
4106 &self,
4107 program: Self::Program,
4108 names: &[&str],
4109 ) -> Vec<Option<u32>> {
4110 let gl = &self.raw;
4111 let c_names = names
4112 .iter()
4113 .map(|&name| CString::new(name).unwrap())
4114 .collect::<Vec<_>>();
4115 let c_name_ptrs = c_names.iter().map(|name| name.as_ptr()).collect::<Vec<_>>();
4116
4117 let count = names.len();
4118 let mut indices = vec![0; count];
4119 gl.GetUniformIndices(
4120 program.0.get(),
4121 count as _,
4122 c_name_ptrs.as_ptr(),
4123 indices.as_mut_ptr(),
4124 );
4125 indices
4126 .iter()
4127 .map(|&index| {
4128 if index == INVALID_INDEX {
4129 None
4130 } else {
4131 Some(index)
4132 }
4133 })
4134 .collect()
4135 }
4136
4137 unsafe fn uniform_block_binding(&self, program: Self::Program, index: u32, binding: u32) {
4138 let gl = &self.raw;
4139 gl.UniformBlockBinding(program.0.get(), index, binding);
4140 }
4141
4142 unsafe fn get_shader_storage_block_index(
4143 &self,
4144 program: Self::Program,
4145 name: &str,
4146 ) -> Option<u32> {
4147 let gl = &self.raw;
4148 let name = CString::new(name).unwrap();
4149 let index =
4150 gl.GetProgramResourceIndex(program.0.get(), SHADER_STORAGE_BLOCK, name.as_ptr());
4151 if index == INVALID_INDEX {
4152 None
4153 } else {
4154 Some(index)
4155 }
4156 }
4157
4158 unsafe fn shader_storage_block_binding(
4159 &self,
4160 program: Self::Program,
4161 index: u32,
4162 binding: u32,
4163 ) {
4164 let gl = &self.raw;
4165 gl.ShaderStorageBlockBinding(program.0.get(), index, binding);
4166 }
4167
4168 unsafe fn read_buffer(&self, src: u32) {
4169 let gl = &self.raw;
4170 gl.ReadBuffer(src);
4171 }
4172
4173 unsafe fn named_framebuffer_read_buffer(
4174 &self,
4175 framebuffer: Option<Self::Framebuffer>,
4176 src: u32,
4177 ) {
4178 let gl = &self.raw;
4179 gl.NamedFramebufferReadBuffer(framebuffer.map(|f| f.0.get()).unwrap_or(0), src);
4180 }
4181
4182 unsafe fn read_pixels(
4183 &self,
4184 x: i32,
4185 y: i32,
4186 width: i32,
4187 height: i32,
4188 format: u32,
4189 gltype: u32,
4190 pixels: PixelPackData,
4191 ) {
4192 let gl = &self.raw;
4193 gl.ReadPixels(
4194 x,
4195 y,
4196 width,
4197 height,
4198 format,
4199 gltype,
4200 match pixels {
4201 PixelPackData::BufferOffset(offset) => offset as *mut std::ffi::c_void,
4202 PixelPackData::Slice(Some(data)) => data.as_mut_ptr() as *mut std::ffi::c_void,
4203 PixelPackData::Slice(None) => ptr::null_mut(),
4204 },
4205 );
4206 }
4207
4208 unsafe fn begin_query(&self, target: u32, query: Self::Query) {
4209 let gl = &self.raw;
4210 if gl.BeginQuery_is_loaded() {
4211 gl.BeginQuery(target, query.0.get());
4212 } else {
4213 gl.BeginQueryEXT(target, query.0.get());
4214 }
4215 }
4216
4217 unsafe fn end_query(&self, target: u32) {
4218 let gl = &self.raw;
4219 if gl.EndQuery_is_loaded() {
4220 gl.EndQuery(target);
4221 } else {
4222 gl.EndQueryEXT(target);
4223 }
4224 }
4225
4226 unsafe fn query_counter(&self, query: Self::Query, target: u32) {
4227 let gl = &self.raw;
4228 if gl.QueryCounter_is_loaded() {
4229 gl.QueryCounter(query.0.get(), target);
4230 } else {
4231 gl.QueryCounterEXT(query.0.get(), target);
4232 }
4233 }
4234
4235 unsafe fn get_query_parameter_u32(&self, query: Self::Query, parameter: u32) -> u32 {
4236 let gl = &self.raw;
4237 let mut value = 0;
4238 if gl.GetQueryBufferObjectiv_is_loaded() {
4239 gl.GetQueryObjectuiv(query.0.get(), parameter, &mut value);
4240 } else {
4241 gl.GetQueryObjectuivEXT(query.0.get(), parameter, &mut value);
4242 }
4243 value
4244 }
4245
4246 unsafe fn get_query_parameter_u64_with_offset(
4247 &self,
4248 query: Self::Query,
4249 parameter: u32,
4250 offset: usize,
4251 ) {
4252 let gl = &self.raw;
4253 if gl.GetQueryObjectui64v_is_loaded() {
4254 gl.GetQueryObjectui64v(query.0.get(), parameter, offset as *mut _);
4255 } else {
4256 gl.GetQueryObjectui64vEXT(query.0.get(), parameter, offset as *mut _);
4257 }
4258 }
4259
4260 unsafe fn create_transform_feedback(&self) -> Result<Self::TransformFeedback, String> {
4261 let gl = &self.raw;
4262 let mut name = 0;
4263 gl.GenTransformFeedbacks(1, &mut name);
4264 NonZeroU32::new(name)
4265 .map(NativeTransformFeedback)
4266 .ok_or_else(|| String::from("Unable to create TransformFeedback object"))
4267 }
4268
4269 unsafe fn is_transform_feedback(&self, transform_feedback: Self::TransformFeedback) -> bool {
4270 let gl = &self.raw;
4271 gl.IsTransformFeedback(transform_feedback.0.get()) != 0
4272 }
4273
4274 unsafe fn delete_transform_feedback(&self, transform_feedback: Self::TransformFeedback) {
4275 let gl = &self.raw;
4276 gl.DeleteTransformFeedbacks(1, &transform_feedback.0.get());
4277 }
4278
4279 unsafe fn bind_transform_feedback(
4280 &self,
4281 target: u32,
4282 transform_feedback: Option<Self::TransformFeedback>,
4283 ) {
4284 let gl = &self.raw;
4285 gl.BindTransformFeedback(target, transform_feedback.map(|tf| tf.0.get()).unwrap_or(0));
4286 }
4287
4288 unsafe fn begin_transform_feedback(&self, primitive_mode: u32) {
4289 let gl = &self.raw;
4290 gl.BeginTransformFeedback(primitive_mode);
4291 }
4292
4293 unsafe fn end_transform_feedback(&self) {
4294 let gl = &self.raw;
4295 gl.EndTransformFeedback();
4296 }
4297
4298 unsafe fn pause_transform_feedback(&self) {
4299 let gl = &self.raw;
4300 gl.PauseTransformFeedback();
4301 }
4302
4303 unsafe fn resume_transform_feedback(&self) {
4304 let gl = &self.raw;
4305 gl.ResumeTransformFeedback();
4306 }
4307
4308 unsafe fn transform_feedback_varyings(
4309 &self,
4310 program: Self::Program,
4311 varyings: &[&str],
4312 buffer_mode: u32,
4313 ) {
4314 let gl = &self.raw;
4315
4316 let strings: Vec<CString> = varyings
4317 .iter()
4318 .copied()
4319 .map(CString::new)
4320 .collect::<Result<_, _>>()
4321 .unwrap();
4322 let varyings: Vec<_> = strings.iter().map(|c_str| c_str.as_ptr()).collect();
4323
4324 gl.TransformFeedbackVaryings(
4325 program.0.get(),
4326 varyings.len() as i32,
4327 varyings.as_ptr(),
4328 buffer_mode,
4329 );
4330 }
4331
4332 unsafe fn get_transform_feedback_varying(
4333 &self,
4334 program: Self::Program,
4335 index: u32,
4336 ) -> Option<ActiveTransformFeedback> {
4337 let gl = &self.raw;
4338
4339 const max_name_size: usize = 256;
4340 let mut name_bytes = [0; max_name_size];
4341
4342 let mut size = 0;
4343 let mut tftype = 0;
4344
4345 gl.GetTransformFeedbackVarying(
4346 program.0.get(),
4347 index,
4348 name_bytes.len() as i32,
4349 std::ptr::null_mut(),
4350 &mut size,
4351 &mut tftype,
4352 name_bytes.as_mut_ptr(),
4353 );
4354
4355 let name = CStr::from_ptr(name_bytes.as_mut_ptr())
4356 .to_string_lossy()
4357 .into_owned();
4358
4359 Some(ActiveTransformFeedback { size, tftype, name })
4360 }
4361
4362 unsafe fn memory_barrier(&self, barriers: u32) {
4363 let gl = &self.raw;
4364 gl.MemoryBarrier(barriers);
4365 }
4366
4367 unsafe fn memory_barrier_by_region(&self, barriers: u32) {
4368 let gl = &self.raw;
4369 gl.MemoryBarrierByRegion(barriers);
4370 }
4371
4372 unsafe fn bind_image_texture(
4373 &self,
4374 unit: u32,
4375 texture: Option<Self::Texture>,
4376 level: i32,
4377 layered: bool,
4378 layer: i32,
4379 access: u32,
4380 format: u32,
4381 ) {
4382 let gl = &self.raw;
4383 gl.BindImageTexture(
4384 unit,
4385 texture.map(|tex| tex.0.get()).unwrap_or(0),
4386 level,
4387 layered as u8,
4388 layer,
4389 access,
4390 format,
4391 );
4392 }
4393 unsafe fn get_active_uniform_block_parameter_i32(
4394 &self,
4395 program: Self::Program,
4396 uniform_block_index: u32,
4397 parameter: u32,
4398 ) -> i32 {
4399 let gl = &self.raw;
4400 let mut value = 0;
4401 gl.GetActiveUniformBlockiv(program.0.get(), uniform_block_index, parameter, &mut value);
4402 value
4403 }
4404
4405 unsafe fn get_active_uniform_block_parameter_i32_slice(
4406 &self,
4407 program: Self::Program,
4408 uniform_block_index: u32,
4409 parameter: u32,
4410 out: &mut [i32],
4411 ) {
4412 let gl = &self.raw;
4413 gl.GetActiveUniformBlockiv(
4414 program.0.get(),
4415 uniform_block_index,
4416 parameter,
4417 out.as_mut_ptr(),
4418 );
4419 }
4420 unsafe fn get_active_uniform_block_name(
4421 &self,
4422 program: Self::Program,
4423 uniform_block_index: u32,
4424 ) -> String {
4425 let gl = &self.raw;
4426
4427 let len = self.get_active_uniform_block_parameter_i32(
4432 program,
4433 uniform_block_index,
4434 crate::UNIFORM_BLOCK_NAME_LENGTH,
4435 );
4436 let len = if gl.GetError() == crate::NO_ERROR && len > 0 {
4437 len as usize
4438 } else {
4439 256
4440 };
4441
4442 let mut buffer = vec![0; len];
4443 let mut length = 0;
4444 gl.GetActiveUniformBlockName(
4445 program.0.get(),
4446 uniform_block_index,
4447 buffer.len() as _,
4448 &mut length,
4449 buffer.as_mut_ptr(),
4450 );
4451
4452 if length > 0 {
4453 assert_eq!(
4454 std::mem::size_of::<u8>(),
4455 std::mem::size_of::<native_gl::GLchar>(),
4456 "This operation is only safe in systems in which the length of \
4457 a GLchar is the same as that of an u8"
4458 );
4459 assert_eq!(
4460 std::mem::align_of::<u8>(),
4461 std::mem::align_of::<native_gl::GLchar>(),
4462 "This operation is only safe in systems in which the alignment \
4463 of a GLchar is the same as that of an u8"
4464 );
4465 let buffer = std::slice::from_raw_parts(
4466 buffer.as_ptr() as *const u8,
4467 (length as usize + 1).min(buffer.len()),
4468 );
4469
4470 let name = CStr::from_bytes_with_nul(&buffer[..])
4471 .unwrap()
4472 .to_str()
4473 .unwrap()
4474 .to_owned();
4475
4476 name
4477 } else {
4478 String::from("")
4479 }
4480 }
4481
4482 unsafe fn max_shader_compiler_threads(&self, count: u32) {
4483 let gl = &self.raw;
4484 if gl.MaxShaderCompilerThreadsKHR_is_loaded() {
4485 gl.MaxShaderCompilerThreadsKHR(count);
4486 } else {
4487 gl.MaxShaderCompilerThreadsARB(count);
4488 }
4489 }
4490
4491 unsafe fn hint(&self, target: u32, mode: u32) {
4492 let gl = &self.raw;
4493 gl.Hint(target, mode);
4494 }
4495
4496 unsafe fn sample_coverage(&self, value: f32, invert: bool) {
4497 let gl = &self.raw;
4498 gl.SampleCoverage(value, invert as u8);
4499 }
4500
4501 unsafe fn get_internal_format_i32_slice(
4502 &self,
4503 target: u32,
4504 internal_format: u32,
4505 pname: u32,
4506 result: &mut [i32],
4507 ) {
4508 let gl = &self.raw;
4509 gl.GetInternalformativ(
4510 target,
4511 internal_format,
4512 pname,
4513 result.len() as _,
4514 result.as_mut_ptr(),
4515 )
4516 }
4517}
4518
4519impl Drop for Context {
4520 fn drop(&mut self) {
4521 match self.debug_callback.take() {
4522 Some(_) => {
4523 unsafe {
4525 let gl = &self.raw;
4526 if gl.DebugMessageCallback_is_loaded() {
4527 gl.DebugMessageCallback(None, std::ptr::null());
4528 } else {
4529 gl.DebugMessageCallbackKHR(None, std::ptr::null());
4530 }
4531 }
4532 }
4533 None => {}
4534 }
4535 }
4536}
4537
4538extern "system" fn raw_debug_message_callback(
4539 source: u32,
4540 gltype: u32,
4541 id: u32,
4542 severity: u32,
4543 length: i32,
4544 message: *const native_gl::GLchar,
4545 user_param: *mut std::ffi::c_void,
4546) {
4547 let _result = std::panic::catch_unwind(move || unsafe {
4548 let callback: &DebugCallback = &*(user_param as *const DebugCallback);
4549 let slice = std::slice::from_raw_parts(message as *const u8, length as usize);
4550 let msg = String::from_utf8_lossy(slice);
4551 (callback)(source, gltype, id, severity, &msg);
4552 });
4553}
4554
4555#[cfg(test)]
4556mod tests {
4557 use super::*;
4558
4559 #[test]
4560 fn test_send() {
4561 fn assert_send<T: Send>() {}
4562 assert_send::<Context>();
4563 }
4564
4565 #[test]
4566 fn test_sync() {
4567 fn assert_sync<T: Sync>() {}
4568 assert_sync::<Context>();
4569 }
4570}