azul_core/
gl.rs

1#![allow(unused_variables)]
2use alloc::{
3    boxed::Box,
4    rc::Rc,
5    string::{String, ToString},
6    vec::Vec,
7};
8use core::{
9    ffi, fmt,
10    hash::{Hash, Hasher},
11    sync::atomic::{AtomicUsize, Ordering as AtomicOrdering},
12};
13
14use azul_css::{AzString, ColorF, ColorU, StringVec, U8Vec};
15pub use gl_context_loader::{
16    ctypes::*, GLbitfield, GLboolean, GLchar, GLclampd, GLclampf, GLeglImageOES, GLenum, GLfloat,
17    GLint, GLint64, GLintptr, GLsizei, GLsizeiptr, GLsync, GLubyte, GLuint, GLuint64, GLvoid,
18};
19use gl_context_loader::{gl, GenericGlContext, GlType};
20
21use crate::{
22    app_resources::{
23        Epoch, ExternalImageId, ImageDescriptor, ImageDescriptorFlags, RawImageFormat,
24    },
25    callbacks::DocumentId,
26    svg::{TessellatedGPUSvgNode, TessellatedSvgNode},
27    window::{PhysicalSizeU32, RendererType},
28    FastHashMap,
29};
30
31pub const GL_RESTART_INDEX: u32 = core::u32::MAX;
32
33/// Passing *const c_void is not easily possible when generating APIs,
34/// so this wrapper struct is for easier API generation
35#[repr(C)]
36#[derive(Debug)]
37pub struct GlVoidPtrConst {
38    pub ptr: *const GLvoid,
39    pub run_destructor: bool,
40}
41
42impl Clone for GlVoidPtrConst {
43    fn clone(&self) -> Self {
44        Self {
45            ptr: self.ptr,
46            run_destructor: true,
47        }
48    }
49}
50
51impl Drop for GlVoidPtrConst {
52    fn drop(&mut self) {
53        self.run_destructor = false;
54    }
55}
56
57/// Struct returned from the C API
58///
59/// Because of Python, every object has to be clone-able,
60/// so yes there may exist more than one mutable reference
61#[repr(C)]
62#[derive(Debug)]
63pub struct GlVoidPtrMut {
64    pub ptr: *mut GLvoid,
65}
66
67impl Clone for GlVoidPtrMut {
68    fn clone(&self) -> Self {
69        Self { ptr: self.ptr }
70    }
71}
72
73// &str
74#[repr(C)]
75pub struct Refstr {
76    pub ptr: *const u8,
77    pub len: usize,
78}
79
80impl Clone for Refstr {
81    fn clone(&self) -> Self {
82        Self {
83            ptr: self.ptr,
84            len: self.len,
85        }
86    }
87}
88
89impl core::fmt::Debug for Refstr {
90    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
91        self.as_str().fmt(f)
92    }
93}
94
95impl Refstr {
96    pub fn as_str(&self) -> &str {
97        unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(self.ptr, self.len)) }
98    }
99}
100
101impl From<&str> for Refstr {
102    fn from(s: &str) -> Self {
103        Self {
104            ptr: s.as_ptr(),
105            len: s.len(),
106        }
107    }
108}
109
110// &[&str]
111#[repr(C)]
112pub struct RefstrVecRef {
113    pub ptr: *const Refstr,
114    pub len: usize,
115}
116
117impl Clone for RefstrVecRef {
118    fn clone(&self) -> Self {
119        Self {
120            ptr: self.ptr,
121            len: self.len,
122        }
123    }
124}
125
126impl core::fmt::Debug for RefstrVecRef {
127    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
128        self.as_slice().fmt(f)
129    }
130}
131
132impl RefstrVecRef {
133    pub fn as_slice(&self) -> &[Refstr] {
134        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
135    }
136}
137
138impl From<&[Refstr]> for RefstrVecRef {
139    fn from(s: &[Refstr]) -> Self {
140        Self {
141            ptr: s.as_ptr(),
142            len: s.len(),
143        }
144    }
145}
146
147// &mut [GLint64]
148#[repr(C)]
149pub struct GLint64VecRefMut {
150    pub ptr: *mut i64,
151    pub len: usize,
152}
153
154impl Clone for GLint64VecRefMut {
155    fn clone(&self) -> Self {
156        Self {
157            ptr: self.ptr,
158            len: self.len,
159        }
160    }
161}
162
163impl core::fmt::Debug for GLint64VecRefMut {
164    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
165        self.as_slice().fmt(f)
166    }
167}
168
169impl From<&mut [GLint64]> for GLint64VecRefMut {
170    fn from(s: &mut [GLint64]) -> Self {
171        Self {
172            ptr: s.as_mut_ptr(),
173            len: s.len(),
174        }
175    }
176}
177
178impl GLint64VecRefMut {
179    pub fn as_slice(&self) -> &[GLint64] {
180        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
181    }
182    fn as_mut_slice(&mut self) -> &mut [GLint64] {
183        unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) }
184    }
185}
186
187// &mut [GLfloat]
188#[repr(C)]
189pub struct GLfloatVecRefMut {
190    pub ptr: *mut f32,
191    pub len: usize,
192}
193
194impl Clone for GLfloatVecRefMut {
195    fn clone(&self) -> Self {
196        Self {
197            ptr: self.ptr,
198            len: self.len,
199        }
200    }
201}
202
203impl core::fmt::Debug for GLfloatVecRefMut {
204    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
205        self.as_slice().fmt(f)
206    }
207}
208
209impl From<&mut [GLfloat]> for GLfloatVecRefMut {
210    fn from(s: &mut [GLfloat]) -> Self {
211        Self {
212            ptr: s.as_mut_ptr(),
213            len: s.len(),
214        }
215    }
216}
217
218impl GLfloatVecRefMut {
219    pub fn as_slice(&self) -> &[GLfloat] {
220        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
221    }
222    fn as_mut_slice(&mut self) -> &mut [GLfloat] {
223        unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) }
224    }
225}
226
227// &mut [GLint]
228#[repr(C)]
229pub struct GLintVecRefMut {
230    pub ptr: *mut i32,
231    pub len: usize,
232}
233
234impl Clone for GLintVecRefMut {
235    fn clone(&self) -> Self {
236        Self {
237            ptr: self.ptr,
238            len: self.len,
239        }
240    }
241}
242
243impl core::fmt::Debug for GLintVecRefMut {
244    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
245        self.as_slice().fmt(f)
246    }
247}
248
249impl From<&mut [GLint]> for GLintVecRefMut {
250    fn from(s: &mut [GLint]) -> Self {
251        Self {
252            ptr: s.as_mut_ptr(),
253            len: s.len(),
254        }
255    }
256}
257
258impl GLintVecRefMut {
259    pub fn as_slice(&self) -> &[GLint] {
260        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
261    }
262    fn as_mut_slice(&mut self) -> &mut [GLint] {
263        unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) }
264    }
265}
266
267// &[GLuint]
268#[repr(C)]
269pub struct GLuintVecRef {
270    pub ptr: *const u32,
271    pub len: usize,
272}
273
274impl Clone for GLuintVecRef {
275    fn clone(&self) -> Self {
276        Self {
277            ptr: self.ptr,
278            len: self.len,
279        }
280    }
281}
282
283impl core::fmt::Debug for GLuintVecRef {
284    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
285        self.as_slice().fmt(f)
286    }
287}
288
289impl From<&[GLuint]> for GLuintVecRef {
290    fn from(s: &[GLuint]) -> Self {
291        Self {
292            ptr: s.as_ptr(),
293            len: s.len(),
294        }
295    }
296}
297
298impl GLuintVecRef {
299    pub fn as_slice(&self) -> &[GLuint] {
300        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
301    }
302}
303
304// &[GLenum]
305#[repr(C)]
306pub struct GLenumVecRef {
307    pub ptr: *const u32,
308    pub len: usize,
309}
310
311impl Clone for GLenumVecRef {
312    fn clone(&self) -> Self {
313        Self {
314            ptr: self.ptr,
315            len: self.len,
316        }
317    }
318}
319
320impl core::fmt::Debug for GLenumVecRef {
321    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
322        self.as_slice().fmt(f)
323    }
324}
325
326impl From<&[GLenum]> for GLenumVecRef {
327    fn from(s: &[GLenum]) -> Self {
328        Self {
329            ptr: s.as_ptr(),
330            len: s.len(),
331        }
332    }
333}
334
335impl GLenumVecRef {
336    pub fn as_slice(&self) -> &[GLenum] {
337        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
338    }
339}
340
341// &[u8]
342#[repr(C)]
343pub struct U8VecRef {
344    pub ptr: *const u8,
345    pub len: usize,
346}
347
348impl Clone for U8VecRef {
349    fn clone(&self) -> Self {
350        Self {
351            ptr: self.ptr,
352            len: self.len,
353        }
354    }
355}
356
357impl From<&[u8]> for U8VecRef {
358    fn from(s: &[u8]) -> Self {
359        Self {
360            ptr: s.as_ptr(),
361            len: s.len(),
362        }
363    }
364}
365
366impl U8VecRef {
367    pub fn as_slice(&self) -> &[u8] {
368        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
369    }
370}
371
372impl fmt::Debug for U8VecRef {
373    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
374        self.as_slice().fmt(f)
375    }
376}
377
378impl PartialOrd for U8VecRef {
379    fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
380        self.as_slice().partial_cmp(rhs.as_slice())
381    }
382}
383
384impl Ord for U8VecRef {
385    fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
386        self.as_slice().cmp(rhs.as_slice())
387    }
388}
389
390impl PartialEq for U8VecRef {
391    fn eq(&self, rhs: &Self) -> bool {
392        self.as_slice().eq(rhs.as_slice())
393    }
394}
395
396impl Eq for U8VecRef {}
397
398impl core::hash::Hash for U8VecRef {
399    fn hash<H>(&self, state: &mut H)
400    where
401        H: core::hash::Hasher,
402    {
403        self.as_slice().hash(state)
404    }
405}
406
407// &[f32]
408#[repr(C)]
409pub struct F32VecRef {
410    pub ptr: *const f32,
411    pub len: usize,
412}
413
414impl Clone for F32VecRef {
415    fn clone(&self) -> Self {
416        Self {
417            ptr: self.ptr,
418            len: self.len,
419        }
420    }
421}
422
423impl core::fmt::Debug for F32VecRef {
424    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
425        self.as_slice().fmt(f)
426    }
427}
428
429impl From<&[f32]> for F32VecRef {
430    fn from(s: &[f32]) -> Self {
431        Self {
432            ptr: s.as_ptr(),
433            len: s.len(),
434        }
435    }
436}
437
438impl F32VecRef {
439    pub fn as_slice(&self) -> &[f32] {
440        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
441    }
442}
443
444// &[i32]
445#[repr(C)]
446pub struct I32VecRef {
447    pub ptr: *const i32,
448    pub len: usize,
449}
450
451impl Clone for I32VecRef {
452    fn clone(&self) -> Self {
453        Self {
454            ptr: self.ptr,
455            len: self.len,
456        }
457    }
458}
459
460impl core::fmt::Debug for I32VecRef {
461    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
462        self.as_slice().fmt(f)
463    }
464}
465
466impl From<&[i32]> for I32VecRef {
467    fn from(s: &[i32]) -> Self {
468        Self {
469            ptr: s.as_ptr(),
470            len: s.len(),
471        }
472    }
473}
474
475impl I32VecRef {
476    pub fn as_slice(&self) -> &[i32] {
477        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
478    }
479}
480
481// &mut [u8]
482#[repr(C)]
483pub struct GLbooleanVecRefMut {
484    pub ptr: *mut u8,
485    pub len: usize,
486}
487
488impl Clone for GLbooleanVecRefMut {
489    fn clone(&self) -> Self {
490        Self {
491            ptr: self.ptr,
492            len: self.len,
493        }
494    }
495}
496
497impl core::fmt::Debug for GLbooleanVecRefMut {
498    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
499        self.as_slice().fmt(f)
500    }
501}
502
503impl From<&mut [GLboolean]> for GLbooleanVecRefMut {
504    fn from(s: &mut [GLboolean]) -> Self {
505        Self {
506            ptr: s.as_mut_ptr(),
507            len: s.len(),
508        }
509    }
510}
511
512impl GLbooleanVecRefMut {
513    pub fn as_slice(&self) -> &[GLboolean] {
514        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
515    }
516    fn as_mut_slice(&mut self) -> &mut [GLboolean] {
517        unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) }
518    }
519}
520
521// &mut [u8]
522#[repr(C)]
523pub struct U8VecRefMut {
524    pub ptr: *mut u8,
525    pub len: usize,
526}
527
528impl Clone for U8VecRefMut {
529    fn clone(&self) -> Self {
530        Self {
531            ptr: self.ptr,
532            len: self.len,
533        }
534    }
535}
536
537impl core::fmt::Debug for U8VecRefMut {
538    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
539        self.as_slice().fmt(f)
540    }
541}
542
543impl From<&mut [u8]> for U8VecRefMut {
544    fn from(s: &mut [u8]) -> Self {
545        Self {
546            ptr: s.as_mut_ptr(),
547            len: s.len(),
548        }
549    }
550}
551
552impl U8VecRefMut {
553    pub fn as_slice(&self) -> &[u8] {
554        unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
555    }
556    fn as_mut_slice(&mut self) -> &mut [u8] {
557        unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) }
558    }
559}
560
561impl_option!(
562    U8VecRef,
563    OptionU8VecRef,
564    copy = false,
565    [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
566);
567
568#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
569#[repr(C)]
570pub struct AzDebugMessage {
571    pub message: AzString,
572    pub source: GLenum,
573    pub ty: GLenum,
574    pub id: GLenum,
575    pub severity: GLenum,
576}
577
578impl_vec!(
579    AzDebugMessage,
580    AzDebugMessageVec,
581    AzDebugMessageVecDestructor
582);
583impl_vec_debug!(AzDebugMessage, AzDebugMessageVec);
584impl_vec_partialord!(AzDebugMessage, AzDebugMessageVec);
585impl_vec_ord!(AzDebugMessage, AzDebugMessageVec);
586impl_vec_clone!(
587    AzDebugMessage,
588    AzDebugMessageVec,
589    AzDebugMessageVecDestructor
590);
591impl_vec_partialeq!(AzDebugMessage, AzDebugMessageVec);
592impl_vec_eq!(AzDebugMessage, AzDebugMessageVec);
593impl_vec_hash!(AzDebugMessage, AzDebugMessageVec);
594
595impl_vec!(GLint, GLintVec, GLintVecDestructor);
596impl_vec_debug!(GLint, GLintVec);
597impl_vec_partialord!(GLint, GLintVec);
598impl_vec_ord!(GLint, GLintVec);
599impl_vec_clone!(GLint, GLintVec, GLintVecDestructor);
600impl_vec_partialeq!(GLint, GLintVec);
601impl_vec_eq!(GLint, GLintVec);
602impl_vec_hash!(GLint, GLintVec);
603
604impl_vec!(GLuint, GLuintVec, GLuintVecDestructor);
605impl_vec_debug!(GLuint, GLuintVec);
606impl_vec_partialord!(GLuint, GLuintVec);
607impl_vec_ord!(GLuint, GLuintVec);
608impl_vec_clone!(GLuint, GLuintVec, GLuintVecDestructor);
609impl_vec_partialeq!(GLuint, GLuintVec);
610impl_vec_eq!(GLuint, GLuintVec);
611impl_vec_hash!(GLuint, GLuintVec);
612
613#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
614#[repr(C)]
615pub enum AzGlType {
616    Gl,
617    Gles,
618}
619
620impl From<GlType> for AzGlType {
621    fn from(a: GlType) -> AzGlType {
622        match a {
623            GlType::Gl => AzGlType::Gl,
624            GlType::GlEs => AzGlType::Gles,
625        }
626    }
627}
628
629// (U8Vec, u32)
630#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
631#[repr(C)]
632pub struct GetProgramBinaryReturn {
633    pub _0: U8Vec,
634    pub _1: u32,
635}
636
637// (i32, u32, AzString)
638#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
639#[repr(C)]
640pub struct GetActiveAttribReturn {
641    pub _0: i32,
642    pub _1: u32,
643    pub _2: AzString,
644}
645
646// (i32, u32, AzString)
647#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
648#[repr(C)]
649pub struct GetActiveUniformReturn {
650    pub _0: i32,
651    pub _1: u32,
652    pub _2: AzString,
653}
654
655#[repr(C)]
656pub struct GLsyncPtr {
657    pub ptr: *const c_void, /* *const __GLsync */
658    pub run_destructor: bool,
659}
660
661impl Clone for GLsyncPtr {
662    fn clone(&self) -> Self {
663        Self {
664            ptr: self.ptr,
665            run_destructor: true,
666        }
667    }
668}
669
670impl core::fmt::Debug for GLsyncPtr {
671    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
672        write!(f, "0x{:0x}", self.ptr as usize)
673    }
674}
675
676impl GLsyncPtr {
677    pub fn new(p: GLsync) -> Self {
678        Self {
679            ptr: p as *const c_void,
680            run_destructor: true,
681        }
682    }
683    pub fn get(self) -> GLsync {
684        self.ptr as GLsync
685    }
686}
687
688impl Drop for GLsyncPtr {
689    fn drop(&mut self) {
690        self.run_destructor = false;
691    }
692}
693
694/// Each pipeline (window) has its own OpenGL textures. GL Textures can technically
695/// be shared across pipelines, however this turns out to be very difficult in practice.
696pub(crate) type GlTextureStorage = FastHashMap<Epoch, FastHashMap<ExternalImageId, Texture>>;
697
698/// Non-cleaned up textures. When a GlTexture is registered, it has to stay active as long
699/// as WebRender needs it for drawing. To transparently do this, we store the epoch that the
700/// texture was originally created with, and check, **after we have drawn the frame**,
701/// if there are any textures that need cleanup.
702///
703/// Because the Texture2d is wrapped in an Rc, the destructor (which cleans up the OpenGL
704/// texture) does not run until we remove the textures
705///
706/// Note: Because textures could be used after the current draw call (ex. for scrolling),
707/// the ACTIVE_GL_TEXTURES are indexed by their epoch. Use `renderer.flush_pipeline_info()`
708/// to see which textures are still active and which ones can be safely removed.
709///
710/// See: https://github.com/servo/webrender/issues/2940
711///
712/// WARNING: Not thread-safe (however, the Texture itself is thread-unsafe, so it's unlikely to ever
713/// be misused)
714static mut ACTIVE_GL_TEXTURES: Option<FastHashMap<DocumentId, GlTextureStorage>> = None;
715
716/// Inserts a new texture into the OpenGL texture cache, returns a new image ID
717/// for the inserted texture
718///
719/// This function exists so azul doesn't have to use `lazy_static` as a dependency
720pub fn insert_into_active_gl_textures(
721    document_id: DocumentId,
722    epoch: Epoch,
723    texture: Texture,
724) -> ExternalImageId {
725    let external_image_id = ExternalImageId::new();
726
727    unsafe {
728        if ACTIVE_GL_TEXTURES.is_none() {
729            ACTIVE_GL_TEXTURES = Some(FastHashMap::new());
730        }
731        let active_textures = ACTIVE_GL_TEXTURES.as_mut().unwrap();
732        let active_epochs = active_textures
733            .entry(document_id)
734            .or_insert_with(|| FastHashMap::new());
735        let active_textures_for_epoch = active_epochs
736            .entry(epoch)
737            .or_insert_with(|| FastHashMap::new());
738        active_textures_for_epoch.insert(external_image_id, texture);
739    }
740
741    external_image_id
742}
743
744/// Destroys all textures from the given `document_id`
745/// where the texture is **older** than the given `epoch`.
746pub fn gl_textures_remove_epochs_from_pipeline(document_id: &DocumentId, epoch: Epoch) {
747    // TODO: Handle overflow of Epochs correctly (low priority)
748    unsafe {
749        let active_textures = match ACTIVE_GL_TEXTURES.as_mut() {
750            Some(s) => s,
751            None => return,
752        };
753
754        let active_epochs = match active_textures.get_mut(document_id) {
755            Some(s) => s,
756            None => return,
757        };
758
759        // NOTE: original code used retain() but that
760        // doesn't work on no_std
761        let mut epochs_to_remove = Vec::new();
762
763        for (gl_texture_epoch, _) in active_epochs.iter() {
764            if *gl_texture_epoch < epoch {
765                epochs_to_remove.push(*gl_texture_epoch);
766            }
767        }
768
769        for epoch in epochs_to_remove {
770            active_epochs.remove(&epoch);
771        }
772    }
773}
774
775// document_id, epoch, external_image_id
776pub fn remove_single_texture_from_active_gl_textures(
777    document_id: &DocumentId,
778    epoch: &Epoch,
779    external_image_id: &ExternalImageId,
780) -> Option<()> {
781    let mut active_textures = unsafe { ACTIVE_GL_TEXTURES.as_mut()? };
782    let mut epochs = active_textures.get_mut(document_id)?;
783    let mut images_in_epoch = epochs.get_mut(epoch)?;
784    images_in_epoch.remove(external_image_id);
785    Some(())
786}
787
788/// Removes a DocumentId from the active epochs
789pub fn gl_textures_remove_active_pipeline(document_id: &DocumentId) {
790    unsafe {
791        let active_textures = match ACTIVE_GL_TEXTURES.as_mut() {
792            Some(s) => s,
793            None => return,
794        };
795        active_textures.remove(document_id);
796    }
797}
798
799/// Destroys all textures, usually done before destroying the OpenGL context
800pub fn gl_textures_clear_opengl_cache() {
801    unsafe {
802        ACTIVE_GL_TEXTURES = None;
803    }
804}
805
806// Search all epoch hash maps for the given key
807// There does not seem to be a way to get the epoch for the key,
808// so we simply have to search all active epochs
809//
810// NOTE: Invalid textures can be generated on minimize / maximize
811// Luckily, webrender simply ignores an invalid texture, so we don't
812// need to check whether a window is maximized or minimized - if
813// we encounter an invalid ID, webrender simply won't draw anything,
814// but at least it won't crash. Usually invalid textures are also 0x0
815// pixels large - so it's not like we had anything to draw anyway.
816pub fn get_opengl_texture(image_key: &ExternalImageId) -> Option<(GLuint, (f32, f32))> {
817    let active_textures = unsafe { ACTIVE_GL_TEXTURES.as_ref()? };
818    active_textures
819        .values()
820        .flat_map(|active_document| active_document.values())
821        .find_map(|active_epoch| active_epoch.get(image_key))
822        .map(|tex| {
823            (
824                tex.texture_id,
825                (tex.size.width as f32, tex.size.height as f32),
826            )
827        })
828}
829
830/// For .get_gl_precision_format(), but ABI-safe - returning an array or a tuple is not ABI-safe
831#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
832#[repr(C)]
833pub struct GlShaderPrecisionFormatReturn {
834    pub _0: GLint,
835    pub _1: GLint,
836    pub _2: GLint,
837}
838
839#[repr(C)]
840pub struct GlContextPtr {
841    pub ptr: Box<Rc<GlContextPtrInner>>,
842    /// Whether to force a hardware or software renderer
843    pub renderer_type: RendererType,
844    pub run_destructor: bool,
845}
846
847impl Clone for GlContextPtr {
848    fn clone(&self) -> Self {
849        Self {
850            ptr: self.ptr.clone(),
851            renderer_type: self.renderer_type.clone(),
852            run_destructor: true,
853        }
854    }
855}
856
857impl Drop for GlContextPtr {
858    fn drop(&mut self) {
859        self.run_destructor = false;
860    }
861}
862
863impl GlContextPtr {
864    pub fn get_svg_shader(&self) -> GLuint {
865        self.ptr.svg_shader
866    }
867    pub fn get_fxaa_shader(&self) -> GLuint {
868        self.ptr.fxaa_shader
869    }
870}
871
872#[repr(C)]
873pub struct GlContextPtrInner {
874    pub ptr: Rc<GenericGlContext>,
875    /// SVG shader program (library-internal use)
876    pub svg_shader: GLuint,
877    /// SVG multicolor shader program (library-internal use)
878    pub svg_multicolor_shader: GLuint,
879    /// FXAA shader program (library-internal use)
880    pub fxaa_shader: GLuint,
881}
882
883impl Drop for GlContextPtrInner {
884    fn drop(&mut self) {
885        self.ptr.delete_program(self.svg_shader);
886        self.ptr.delete_program(self.svg_multicolor_shader);
887        self.ptr.delete_program(self.fxaa_shader);
888    }
889}
890
891impl_option!(
892    GlContextPtr,
893    OptionGlContextPtr,
894    copy = false,
895    [Debug, Clone, PartialEq, Eq, PartialOrd, Ord]
896);
897
898impl core::fmt::Debug for GlContextPtr {
899    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
900        write!(f, "0x{:0x}", self.as_usize())
901    }
902}
903
904static SVG_VERTEX_SHADER: &[u8] = b"#version 150
905
906#if __VERSION__ != 100
907    #define varying out
908    #define attribute in
909#endif
910
911uniform vec2 vBboxSize;
912uniform mat4 vTransformMatrix;
913
914attribute vec2 vAttrXY;
915
916void main() {
917    vec4 vTransposed = vec4(vAttrXY, 1.0, 1.0) * vTransformMatrix;
918    vec2 vTransposedInScreen = vTransposed.xy / vBboxSize;
919    vec2 vCalcFinal = (vTransposedInScreen * vec2(2.0)) - vec2(1.0);
920    gl_Position = vec4(vCalcFinal, 1.0, 1.0);
921}";
922
923static SVG_FRAGMENT_SHADER: &[u8] = b"#version 150
924
925precision highp float;
926
927uniform vec4 fDrawColor;
928
929#if __VERSION__ == 100
930    #define oFragColor gl_FragColor
931#else
932    out vec4 oFragColor;
933#endif
934
935void main() {
936    oFragColor = fDrawColor;
937}";
938
939static SVG_MULTICOLOR_VERTEX_SHADER: &[u8] = b"#version 150
940
941#if __VERSION__ != 100
942    #define varying out
943    #define attribute in
944#endif
945
946uniform vec2 vBboxSize;
947uniform mat4 vTransformMatrix;
948
949attribute vec3 vAttrXY;
950attribute vec4 vColor;
951varying vec4 fColor;
952
953void main() {
954    vec4 vTransposed = vec4(vAttrXY.xy, 1.0, 1.0) * vTransformMatrix;
955    vec2 vTransposedInScreen = vTransposed.xy / vBboxSize;
956    vec2 vCalcFinal = (vTransposedInScreen * vec2(2.0)) - vec2(1.0);
957    gl_Position = vec4(vCalcFinal, vAttrXY.z, 1.0);
958    fColor = vColor;
959}";
960
961static SVG_MULTICOLOR_FRAGMENT_SHADER: &[u8] = b"#version 150
962
963precision highp float;
964
965#if __VERSION__ != 100
966    #define varying out
967    #define attribute in
968#endif
969
970#if __VERSION__ == 100
971    #define oFragColor gl_FragColor
972#else
973    out vec4 oFragColor;
974#endif
975
976attribute vec4 fColor;
977
978void main() {
979    oFragColor = fColor;
980}";
981
982impl GlContextPtr {
983    pub fn new(renderer_type: RendererType, gl_context: Rc<GenericGlContext>) -> Self {
984        // Compile basic shader
985        let vertex_shader_object = gl_context.create_shader(gl::VERTEX_SHADER);
986        gl_context.shader_source(vertex_shader_object, &[SVG_VERTEX_SHADER]);
987        gl_context.compile_shader(vertex_shader_object);
988
989        let fragment_shader_object = gl_context.create_shader(gl::FRAGMENT_SHADER);
990        gl_context.shader_source(fragment_shader_object, &[SVG_FRAGMENT_SHADER]);
991        gl_context.compile_shader(fragment_shader_object);
992
993        let svg_program_id = gl_context.create_program();
994
995        gl_context.attach_shader(svg_program_id, vertex_shader_object);
996        gl_context.attach_shader(svg_program_id, fragment_shader_object);
997        gl_context.bind_attrib_location(svg_program_id, 0, "vAttrXY".into());
998        gl_context.link_program(svg_program_id);
999
1000        gl_context.delete_shader(vertex_shader_object);
1001        gl_context.delete_shader(fragment_shader_object);
1002
1003        // Compile multi-color SVG shader
1004        let vertex_shader_object = gl_context.create_shader(gl::VERTEX_SHADER);
1005        gl_context.shader_source(vertex_shader_object, &[SVG_MULTICOLOR_VERTEX_SHADER]);
1006        gl_context.compile_shader(vertex_shader_object);
1007
1008        let fragment_shader_object = gl_context.create_shader(gl::FRAGMENT_SHADER);
1009        gl_context.shader_source(fragment_shader_object, &[SVG_MULTICOLOR_FRAGMENT_SHADER]);
1010        gl_context.compile_shader(fragment_shader_object);
1011
1012        let svg_multicolor_program_id = gl_context.create_program();
1013
1014        gl_context.attach_shader(svg_multicolor_program_id, vertex_shader_object);
1015        gl_context.attach_shader(svg_multicolor_program_id, fragment_shader_object);
1016        gl_context.bind_attrib_location(svg_multicolor_program_id, 0, "vAttrXY".into());
1017        gl_context.bind_attrib_location(svg_multicolor_program_id, 1, "vColor".into());
1018        gl_context.link_program(svg_multicolor_program_id);
1019
1020        gl_context.delete_shader(vertex_shader_object);
1021        gl_context.delete_shader(fragment_shader_object);
1022
1023        Self {
1024            ptr: Box::new(Rc::new(GlContextPtrInner {
1025                svg_shader: svg_program_id,
1026                svg_multicolor_shader: svg_multicolor_program_id,
1027                fxaa_shader: 0, // TODO
1028                ptr: gl_context,
1029            })),
1030            renderer_type,
1031            run_destructor: true,
1032        }
1033    }
1034
1035    pub fn get<'a>(&'a self) -> &'a Rc<GenericGlContext> {
1036        &self.ptr.ptr
1037    }
1038    fn as_usize(&self) -> usize {
1039        (Rc::as_ptr(&self.ptr.ptr) as *const c_void) as usize
1040    }
1041}
1042
1043impl GlContextPtr {
1044    pub fn get_type(&self) -> AzGlType {
1045        self.get().get_type().into()
1046    }
1047    pub fn buffer_data_untyped(
1048        &self,
1049        target: GLenum,
1050        size: GLsizeiptr,
1051        data: GlVoidPtrConst,
1052        usage: GLenum,
1053    ) {
1054        self.get()
1055            .buffer_data_untyped(target, size, data.ptr, usage)
1056    }
1057    pub fn buffer_sub_data_untyped(
1058        &self,
1059        target: GLenum,
1060        offset: isize,
1061        size: GLsizeiptr,
1062        data: GlVoidPtrConst,
1063    ) {
1064        self.get()
1065            .buffer_sub_data_untyped(target, offset, size, data.ptr)
1066    }
1067    pub fn map_buffer(&self, target: GLenum, access: GLbitfield) -> GlVoidPtrMut {
1068        GlVoidPtrMut {
1069            ptr: self.get().map_buffer(target, access),
1070        }
1071    }
1072    pub fn map_buffer_range(
1073        &self,
1074        target: GLenum,
1075        offset: GLintptr,
1076        length: GLsizeiptr,
1077        access: GLbitfield,
1078    ) -> GlVoidPtrMut {
1079        GlVoidPtrMut {
1080            ptr: self.get().map_buffer_range(target, offset, length, access),
1081        }
1082    }
1083    pub fn unmap_buffer(&self, target: GLenum) -> GLboolean {
1084        self.get().unmap_buffer(target)
1085    }
1086    pub fn tex_buffer(&self, target: GLenum, internal_format: GLenum, buffer: GLuint) {
1087        self.get().tex_buffer(target, internal_format, buffer)
1088    }
1089    pub fn shader_source(&self, shader: GLuint, strings: StringVec) {
1090        fn str_to_bytes(input: &str) -> Vec<u8> {
1091            let mut v: Vec<u8> = input.into();
1092            v.push(0);
1093            v
1094        }
1095        let shaders_as_bytes = strings
1096            .iter()
1097            .map(|s| str_to_bytes(s.as_str()))
1098            .collect::<Vec<_>>();
1099        let shaders_as_bytes = shaders_as_bytes
1100            .iter()
1101            .map(|s| s.as_ref())
1102            .collect::<Vec<_>>();
1103        self.get().shader_source(shader, &shaders_as_bytes)
1104    }
1105    pub fn read_buffer(&self, mode: GLenum) {
1106        self.get().read_buffer(mode)
1107    }
1108    pub fn read_pixels_into_buffer(
1109        &self,
1110        x: GLint,
1111        y: GLint,
1112        width: GLsizei,
1113        height: GLsizei,
1114        format: GLenum,
1115        pixel_type: GLenum,
1116        mut dst_buffer: U8VecRefMut,
1117    ) {
1118        self.get().read_pixels_into_buffer(
1119            x,
1120            y,
1121            width,
1122            height,
1123            format,
1124            pixel_type,
1125            dst_buffer.as_mut_slice(),
1126        )
1127    }
1128    pub fn read_pixels(
1129        &self,
1130        x: GLint,
1131        y: GLint,
1132        width: GLsizei,
1133        height: GLsizei,
1134        format: GLenum,
1135        pixel_type: GLenum,
1136    ) -> U8Vec {
1137        self.get()
1138            .read_pixels(x, y, width, height, format, pixel_type)
1139            .into()
1140    }
1141    pub fn read_pixels_into_pbo(
1142        &self,
1143        x: GLint,
1144        y: GLint,
1145        width: GLsizei,
1146        height: GLsizei,
1147        format: GLenum,
1148        pixel_type: GLenum,
1149    ) {
1150        unsafe {
1151            self.get()
1152                .read_pixels_into_pbo(x, y, width, height, format, pixel_type)
1153        }
1154    }
1155    pub fn sample_coverage(&self, value: GLclampf, invert: bool) {
1156        self.get().sample_coverage(value, invert)
1157    }
1158    pub fn polygon_offset(&self, factor: GLfloat, units: GLfloat) {
1159        self.get().polygon_offset(factor, units)
1160    }
1161    pub fn pixel_store_i(&self, name: GLenum, param: GLint) {
1162        self.get().pixel_store_i(name, param)
1163    }
1164    pub fn gen_buffers(&self, n: GLsizei) -> GLuintVec {
1165        self.get().gen_buffers(n).into()
1166    }
1167    pub fn gen_renderbuffers(&self, n: GLsizei) -> GLuintVec {
1168        self.get().gen_renderbuffers(n).into()
1169    }
1170    pub fn gen_framebuffers(&self, n: GLsizei) -> GLuintVec {
1171        self.get().gen_framebuffers(n).into()
1172    }
1173    pub fn gen_textures(&self, n: GLsizei) -> GLuintVec {
1174        self.get().gen_textures(n).into()
1175    }
1176    pub fn gen_vertex_arrays(&self, n: GLsizei) -> GLuintVec {
1177        self.get().gen_vertex_arrays(n).into()
1178    }
1179    pub fn gen_queries(&self, n: GLsizei) -> GLuintVec {
1180        self.get().gen_queries(n).into()
1181    }
1182    pub fn begin_query(&self, target: GLenum, id: GLuint) {
1183        self.get().begin_query(target, id)
1184    }
1185    pub fn end_query(&self, target: GLenum) {
1186        self.get().end_query(target)
1187    }
1188    pub fn query_counter(&self, id: GLuint, target: GLenum) {
1189        self.get().query_counter(id, target)
1190    }
1191    pub fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32 {
1192        self.get().get_query_object_iv(id, pname)
1193    }
1194    pub fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32 {
1195        self.get().get_query_object_uiv(id, pname)
1196    }
1197    pub fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64 {
1198        self.get().get_query_object_i64v(id, pname)
1199    }
1200    pub fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64 {
1201        self.get().get_query_object_ui64v(id, pname)
1202    }
1203    pub fn delete_queries(&self, queries: GLuintVecRef) {
1204        self.get().delete_queries(queries.as_slice())
1205    }
1206    pub fn delete_vertex_arrays(&self, vertex_arrays: GLuintVecRef) {
1207        self.get().delete_vertex_arrays(vertex_arrays.as_slice())
1208    }
1209    pub fn delete_buffers(&self, buffers: GLuintVecRef) {
1210        self.get().delete_buffers(buffers.as_slice())
1211    }
1212    pub fn delete_renderbuffers(&self, renderbuffers: GLuintVecRef) {
1213        self.get().delete_renderbuffers(renderbuffers.as_slice())
1214    }
1215    pub fn delete_framebuffers(&self, framebuffers: GLuintVecRef) {
1216        self.get().delete_framebuffers(framebuffers.as_slice())
1217    }
1218    pub fn delete_textures(&self, textures: GLuintVecRef) {
1219        self.get().delete_textures(textures.as_slice())
1220    }
1221    pub fn framebuffer_renderbuffer(
1222        &self,
1223        target: GLenum,
1224        attachment: GLenum,
1225        renderbuffertarget: GLenum,
1226        renderbuffer: GLuint,
1227    ) {
1228        self.get()
1229            .framebuffer_renderbuffer(target, attachment, renderbuffertarget, renderbuffer)
1230    }
1231    pub fn renderbuffer_storage(
1232        &self,
1233        target: GLenum,
1234        internalformat: GLenum,
1235        width: GLsizei,
1236        height: GLsizei,
1237    ) {
1238        self.get()
1239            .renderbuffer_storage(target, internalformat, width, height)
1240    }
1241    pub fn depth_func(&self, func: GLenum) {
1242        self.get().depth_func(func)
1243    }
1244    pub fn active_texture(&self, texture: GLenum) {
1245        self.get().active_texture(texture)
1246    }
1247    pub fn attach_shader(&self, program: GLuint, shader: GLuint) {
1248        self.get().attach_shader(program, shader)
1249    }
1250    pub fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: Refstr) {
1251        self.get()
1252            .bind_attrib_location(program, index, name.as_str())
1253    }
1254    pub fn get_uniform_iv(&self, program: GLuint, location: GLint, mut result: GLintVecRefMut) {
1255        unsafe {
1256            self.get()
1257                .get_uniform_iv(program, location, result.as_mut_slice())
1258        }
1259    }
1260    pub fn get_uniform_fv(&self, program: GLuint, location: GLint, mut result: GLfloatVecRefMut) {
1261        unsafe {
1262            self.get()
1263                .get_uniform_fv(program, location, result.as_mut_slice())
1264        }
1265    }
1266    pub fn get_uniform_block_index(&self, program: GLuint, name: Refstr) -> GLuint {
1267        self.get().get_uniform_block_index(program, name.as_str())
1268    }
1269    pub fn get_uniform_indices(&self, program: GLuint, names: RefstrVecRef) -> GLuintVec {
1270        let names_vec = names
1271            .as_slice()
1272            .iter()
1273            .map(|n| n.as_str())
1274            .collect::<Vec<_>>();
1275        self.get().get_uniform_indices(program, &names_vec).into()
1276    }
1277    pub fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint) {
1278        self.get().bind_buffer_base(target, index, buffer)
1279    }
1280    pub fn bind_buffer_range(
1281        &self,
1282        target: GLenum,
1283        index: GLuint,
1284        buffer: GLuint,
1285        offset: GLintptr,
1286        size: GLsizeiptr,
1287    ) {
1288        self.get()
1289            .bind_buffer_range(target, index, buffer, offset, size)
1290    }
1291    pub fn uniform_block_binding(
1292        &self,
1293        program: GLuint,
1294        uniform_block_index: GLuint,
1295        uniform_block_binding: GLuint,
1296    ) {
1297        self.get()
1298            .uniform_block_binding(program, uniform_block_index, uniform_block_binding)
1299    }
1300    pub fn bind_buffer(&self, target: GLenum, buffer: GLuint) {
1301        self.get().bind_buffer(target, buffer)
1302    }
1303    pub fn bind_vertex_array(&self, vao: GLuint) {
1304        self.get().bind_vertex_array(vao)
1305    }
1306    pub fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) {
1307        self.get().bind_renderbuffer(target, renderbuffer)
1308    }
1309    pub fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) {
1310        self.get().bind_framebuffer(target, framebuffer)
1311    }
1312    pub fn bind_texture(&self, target: GLenum, texture: GLuint) {
1313        self.get().bind_texture(target, texture)
1314    }
1315    pub fn draw_buffers(&self, bufs: GLenumVecRef) {
1316        self.get().draw_buffers(bufs.as_slice())
1317    }
1318    pub fn tex_image_2d(
1319        &self,
1320        target: GLenum,
1321        level: GLint,
1322        internal_format: GLint,
1323        width: GLsizei,
1324        height: GLsizei,
1325        border: GLint,
1326        format: GLenum,
1327        ty: GLenum,
1328        opt_data: OptionU8VecRef,
1329    ) {
1330        let opt_data = opt_data.as_option();
1331        let opt_data: Option<&[u8]> = opt_data.map(|o| o.as_slice());
1332        self.get().tex_image_2d(
1333            target,
1334            level,
1335            internal_format,
1336            width,
1337            height,
1338            border,
1339            format,
1340            ty,
1341            opt_data,
1342        )
1343    }
1344    pub fn compressed_tex_image_2d(
1345        &self,
1346        target: GLenum,
1347        level: GLint,
1348        internal_format: GLenum,
1349        width: GLsizei,
1350        height: GLsizei,
1351        border: GLint,
1352        data: U8VecRef,
1353    ) {
1354        self.get().compressed_tex_image_2d(
1355            target,
1356            level,
1357            internal_format,
1358            width,
1359            height,
1360            border,
1361            data.as_slice(),
1362        )
1363    }
1364    pub fn compressed_tex_sub_image_2d(
1365        &self,
1366        target: GLenum,
1367        level: GLint,
1368        xoffset: GLint,
1369        yoffset: GLint,
1370        width: GLsizei,
1371        height: GLsizei,
1372        format: GLenum,
1373        data: U8VecRef,
1374    ) {
1375        self.get().compressed_tex_sub_image_2d(
1376            target,
1377            level,
1378            xoffset,
1379            yoffset,
1380            width,
1381            height,
1382            format,
1383            data.as_slice(),
1384        )
1385    }
1386    pub fn tex_image_3d(
1387        &self,
1388        target: GLenum,
1389        level: GLint,
1390        internal_format: GLint,
1391        width: GLsizei,
1392        height: GLsizei,
1393        depth: GLsizei,
1394        border: GLint,
1395        format: GLenum,
1396        ty: GLenum,
1397        opt_data: OptionU8VecRef,
1398    ) {
1399        let opt_data = opt_data.as_option();
1400        let opt_data: Option<&[u8]> = opt_data.map(|o| o.as_slice());
1401        self.get().tex_image_3d(
1402            target,
1403            level,
1404            internal_format,
1405            width,
1406            height,
1407            depth,
1408            border,
1409            format,
1410            ty,
1411            opt_data,
1412        )
1413    }
1414    pub fn copy_tex_image_2d(
1415        &self,
1416        target: GLenum,
1417        level: GLint,
1418        internal_format: GLenum,
1419        x: GLint,
1420        y: GLint,
1421        width: GLsizei,
1422        height: GLsizei,
1423        border: GLint,
1424    ) {
1425        self.get()
1426            .copy_tex_image_2d(target, level, internal_format, x, y, width, height, border)
1427    }
1428    pub fn copy_tex_sub_image_2d(
1429        &self,
1430        target: GLenum,
1431        level: GLint,
1432        xoffset: GLint,
1433        yoffset: GLint,
1434        x: GLint,
1435        y: GLint,
1436        width: GLsizei,
1437        height: GLsizei,
1438    ) {
1439        self.get()
1440            .copy_tex_sub_image_2d(target, level, xoffset, yoffset, x, y, width, height)
1441    }
1442    pub fn copy_tex_sub_image_3d(
1443        &self,
1444        target: GLenum,
1445        level: GLint,
1446        xoffset: GLint,
1447        yoffset: GLint,
1448        zoffset: GLint,
1449        x: GLint,
1450        y: GLint,
1451        width: GLsizei,
1452        height: GLsizei,
1453    ) {
1454        self.get().copy_tex_sub_image_3d(
1455            target, level, xoffset, yoffset, zoffset, x, y, width, height,
1456        )
1457    }
1458    pub fn tex_sub_image_2d(
1459        &self,
1460        target: GLenum,
1461        level: GLint,
1462        xoffset: GLint,
1463        yoffset: GLint,
1464        width: GLsizei,
1465        height: GLsizei,
1466        format: GLenum,
1467        ty: GLenum,
1468        data: U8VecRef,
1469    ) {
1470        self.get().tex_sub_image_2d(
1471            target,
1472            level,
1473            xoffset,
1474            yoffset,
1475            width,
1476            height,
1477            format,
1478            ty,
1479            data.as_slice(),
1480        )
1481    }
1482    pub fn tex_sub_image_2d_pbo(
1483        &self,
1484        target: GLenum,
1485        level: GLint,
1486        xoffset: GLint,
1487        yoffset: GLint,
1488        width: GLsizei,
1489        height: GLsizei,
1490        format: GLenum,
1491        ty: GLenum,
1492        offset: usize,
1493    ) {
1494        self.get().tex_sub_image_2d_pbo(
1495            target, level, xoffset, yoffset, width, height, format, ty, offset,
1496        )
1497    }
1498    pub fn tex_sub_image_3d(
1499        &self,
1500        target: GLenum,
1501        level: GLint,
1502        xoffset: GLint,
1503        yoffset: GLint,
1504        zoffset: GLint,
1505        width: GLsizei,
1506        height: GLsizei,
1507        depth: GLsizei,
1508        format: GLenum,
1509        ty: GLenum,
1510        data: U8VecRef,
1511    ) {
1512        self.get().tex_sub_image_3d(
1513            target,
1514            level,
1515            xoffset,
1516            yoffset,
1517            zoffset,
1518            width,
1519            height,
1520            depth,
1521            format,
1522            ty,
1523            data.as_slice(),
1524        )
1525    }
1526    pub fn tex_sub_image_3d_pbo(
1527        &self,
1528        target: GLenum,
1529        level: GLint,
1530        xoffset: GLint,
1531        yoffset: GLint,
1532        zoffset: GLint,
1533        width: GLsizei,
1534        height: GLsizei,
1535        depth: GLsizei,
1536        format: GLenum,
1537        ty: GLenum,
1538        offset: usize,
1539    ) {
1540        self.get().tex_sub_image_3d_pbo(
1541            target, level, xoffset, yoffset, zoffset, width, height, depth, format, ty, offset,
1542        )
1543    }
1544    pub fn tex_storage_2d(
1545        &self,
1546        target: GLenum,
1547        levels: GLint,
1548        internal_format: GLenum,
1549        width: GLsizei,
1550        height: GLsizei,
1551    ) {
1552        self.get()
1553            .tex_storage_2d(target, levels, internal_format, width, height)
1554    }
1555    pub fn tex_storage_3d(
1556        &self,
1557        target: GLenum,
1558        levels: GLint,
1559        internal_format: GLenum,
1560        width: GLsizei,
1561        height: GLsizei,
1562        depth: GLsizei,
1563    ) {
1564        self.get()
1565            .tex_storage_3d(target, levels, internal_format, width, height, depth)
1566    }
1567    pub fn get_tex_image_into_buffer(
1568        &self,
1569        target: GLenum,
1570        level: GLint,
1571        format: GLenum,
1572        ty: GLenum,
1573        mut output: U8VecRefMut,
1574    ) {
1575        self.get()
1576            .get_tex_image_into_buffer(target, level, format, ty, output.as_mut_slice())
1577    }
1578    pub fn copy_image_sub_data(
1579        &self,
1580        src_name: GLuint,
1581        src_target: GLenum,
1582        src_level: GLint,
1583        src_x: GLint,
1584        src_y: GLint,
1585        src_z: GLint,
1586        dst_name: GLuint,
1587        dst_target: GLenum,
1588        dst_level: GLint,
1589        dst_x: GLint,
1590        dst_y: GLint,
1591        dst_z: GLint,
1592        src_width: GLsizei,
1593        src_height: GLsizei,
1594        src_depth: GLsizei,
1595    ) {
1596        unsafe {
1597            self.get().copy_image_sub_data(
1598                src_name, src_target, src_level, src_x, src_y, src_z, dst_name, dst_target,
1599                dst_level, dst_x, dst_y, dst_z, src_width, src_height, src_depth,
1600            )
1601        }
1602    }
1603    pub fn invalidate_framebuffer(&self, target: GLenum, attachments: GLenumVecRef) {
1604        self.get()
1605            .invalidate_framebuffer(target, attachments.as_slice())
1606    }
1607    pub fn invalidate_sub_framebuffer(
1608        &self,
1609        target: GLenum,
1610        attachments: GLenumVecRef,
1611        xoffset: GLint,
1612        yoffset: GLint,
1613        width: GLsizei,
1614        height: GLsizei,
1615    ) {
1616        self.get().invalidate_sub_framebuffer(
1617            target,
1618            attachments.as_slice(),
1619            xoffset,
1620            yoffset,
1621            width,
1622            height,
1623        )
1624    }
1625    pub fn get_integer_v(&self, name: GLenum, mut result: GLintVecRefMut) {
1626        unsafe { self.get().get_integer_v(name, result.as_mut_slice()) }
1627    }
1628    pub fn get_integer_64v(&self, name: GLenum, mut result: GLint64VecRefMut) {
1629        unsafe { self.get().get_integer_64v(name, result.as_mut_slice()) }
1630    }
1631    pub fn get_integer_iv(&self, name: GLenum, index: GLuint, mut result: GLintVecRefMut) {
1632        unsafe {
1633            self.get()
1634                .get_integer_iv(name, index, result.as_mut_slice())
1635        }
1636    }
1637    pub fn get_integer_64iv(&self, name: GLenum, index: GLuint, mut result: GLint64VecRefMut) {
1638        unsafe {
1639            self.get()
1640                .get_integer_64iv(name, index, result.as_mut_slice())
1641        }
1642    }
1643    pub fn get_boolean_v(&self, name: GLenum, mut result: GLbooleanVecRefMut) {
1644        unsafe { self.get().get_boolean_v(name, result.as_mut_slice()) }
1645    }
1646    pub fn get_float_v(&self, name: GLenum, mut result: GLfloatVecRefMut) {
1647        unsafe { self.get().get_float_v(name, result.as_mut_slice()) }
1648    }
1649    pub fn get_framebuffer_attachment_parameter_iv(
1650        &self,
1651        target: GLenum,
1652        attachment: GLenum,
1653        pname: GLenum,
1654    ) -> GLint {
1655        self.get()
1656            .get_framebuffer_attachment_parameter_iv(target, attachment, pname)
1657    }
1658    pub fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
1659        self.get().get_renderbuffer_parameter_iv(target, pname)
1660    }
1661    pub fn get_tex_parameter_iv(&self, target: GLenum, name: GLenum) -> GLint {
1662        self.get().get_tex_parameter_iv(target, name)
1663    }
1664    pub fn get_tex_parameter_fv(&self, target: GLenum, name: GLenum) -> GLfloat {
1665        self.get().get_tex_parameter_fv(target, name)
1666    }
1667    pub fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) {
1668        self.get().tex_parameter_i(target, pname, param)
1669    }
1670    pub fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) {
1671        self.get().tex_parameter_f(target, pname, param)
1672    }
1673    pub fn framebuffer_texture_2d(
1674        &self,
1675        target: GLenum,
1676        attachment: GLenum,
1677        textarget: GLenum,
1678        texture: GLuint,
1679        level: GLint,
1680    ) {
1681        self.get()
1682            .framebuffer_texture_2d(target, attachment, textarget, texture, level)
1683    }
1684    pub fn framebuffer_texture_layer(
1685        &self,
1686        target: GLenum,
1687        attachment: GLenum,
1688        texture: GLuint,
1689        level: GLint,
1690        layer: GLint,
1691    ) {
1692        self.get()
1693            .framebuffer_texture_layer(target, attachment, texture, level, layer)
1694    }
1695    pub fn blit_framebuffer(
1696        &self,
1697        src_x0: GLint,
1698        src_y0: GLint,
1699        src_x1: GLint,
1700        src_y1: GLint,
1701        dst_x0: GLint,
1702        dst_y0: GLint,
1703        dst_x1: GLint,
1704        dst_y1: GLint,
1705        mask: GLbitfield,
1706        filter: GLenum,
1707    ) {
1708        self.get().blit_framebuffer(
1709            src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter,
1710        )
1711    }
1712    pub fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
1713        self.get().vertex_attrib_4f(index, x, y, z, w)
1714    }
1715    pub fn vertex_attrib_pointer_f32(
1716        &self,
1717        index: GLuint,
1718        size: GLint,
1719        normalized: bool,
1720        stride: GLsizei,
1721        offset: GLuint,
1722    ) {
1723        self.get()
1724            .vertex_attrib_pointer_f32(index, size, normalized, stride, offset)
1725    }
1726    pub fn vertex_attrib_pointer(
1727        &self,
1728        index: GLuint,
1729        size: GLint,
1730        type_: GLenum,
1731        normalized: bool,
1732        stride: GLsizei,
1733        offset: GLuint,
1734    ) {
1735        self.get()
1736            .vertex_attrib_pointer(index, size, type_, normalized, stride, offset)
1737    }
1738    pub fn vertex_attrib_i_pointer(
1739        &self,
1740        index: GLuint,
1741        size: GLint,
1742        type_: GLenum,
1743        stride: GLsizei,
1744        offset: GLuint,
1745    ) {
1746        self.get()
1747            .vertex_attrib_i_pointer(index, size, type_, stride, offset)
1748    }
1749    pub fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) {
1750        self.get().vertex_attrib_divisor(index, divisor)
1751    }
1752    pub fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
1753        self.get().viewport(x, y, width, height)
1754    }
1755    pub fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
1756        self.get().scissor(x, y, width, height)
1757    }
1758    pub fn line_width(&self, width: GLfloat) {
1759        self.get().line_width(width)
1760    }
1761    pub fn use_program(&self, program: GLuint) {
1762        self.get().use_program(program)
1763    }
1764    pub fn validate_program(&self, program: GLuint) {
1765        self.get().validate_program(program)
1766    }
1767    pub fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) {
1768        self.get().draw_arrays(mode, first, count)
1769    }
1770    pub fn draw_arrays_instanced(
1771        &self,
1772        mode: GLenum,
1773        first: GLint,
1774        count: GLsizei,
1775        primcount: GLsizei,
1776    ) {
1777        self.get()
1778            .draw_arrays_instanced(mode, first, count, primcount)
1779    }
1780    pub fn draw_elements(
1781        &self,
1782        mode: GLenum,
1783        count: GLsizei,
1784        element_type: GLenum,
1785        indices_offset: GLuint,
1786    ) {
1787        self.get()
1788            .draw_elements(mode, count, element_type, indices_offset)
1789    }
1790    pub fn draw_elements_instanced(
1791        &self,
1792        mode: GLenum,
1793        count: GLsizei,
1794        element_type: GLenum,
1795        indices_offset: GLuint,
1796        primcount: GLsizei,
1797    ) {
1798        self.get()
1799            .draw_elements_instanced(mode, count, element_type, indices_offset, primcount)
1800    }
1801    pub fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) {
1802        self.get().blend_color(r, g, b, a)
1803    }
1804    pub fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) {
1805        self.get().blend_func(sfactor, dfactor)
1806    }
1807    pub fn blend_func_separate(
1808        &self,
1809        src_rgb: GLenum,
1810        dest_rgb: GLenum,
1811        src_alpha: GLenum,
1812        dest_alpha: GLenum,
1813    ) {
1814        self.get()
1815            .blend_func_separate(src_rgb, dest_rgb, src_alpha, dest_alpha)
1816    }
1817    pub fn blend_equation(&self, mode: GLenum) {
1818        self.get().blend_equation(mode)
1819    }
1820    pub fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) {
1821        self.get().blend_equation_separate(mode_rgb, mode_alpha)
1822    }
1823    pub fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
1824        self.get().color_mask(r, g, b, a)
1825    }
1826    pub fn cull_face(&self, mode: GLenum) {
1827        self.get().cull_face(mode)
1828    }
1829    pub fn front_face(&self, mode: GLenum) {
1830        self.get().front_face(mode)
1831    }
1832    pub fn enable(&self, cap: GLenum) {
1833        self.get().enable(cap)
1834    }
1835    pub fn disable(&self, cap: GLenum) {
1836        self.get().disable(cap)
1837    }
1838    pub fn hint(&self, param_name: GLenum, param_val: GLenum) {
1839        self.get().hint(param_name, param_val)
1840    }
1841    pub fn is_enabled(&self, cap: GLenum) -> GLboolean {
1842        self.get().is_enabled(cap)
1843    }
1844    pub fn is_shader(&self, shader: GLuint) -> GLboolean {
1845        self.get().is_shader(shader)
1846    }
1847    pub fn is_texture(&self, texture: GLenum) -> GLboolean {
1848        self.get().is_texture(texture)
1849    }
1850    pub fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean {
1851        self.get().is_framebuffer(framebuffer)
1852    }
1853    pub fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean {
1854        self.get().is_renderbuffer(renderbuffer)
1855    }
1856    pub fn check_frame_buffer_status(&self, target: GLenum) -> GLenum {
1857        self.get().check_frame_buffer_status(target)
1858    }
1859    pub fn enable_vertex_attrib_array(&self, index: GLuint) {
1860        self.get().enable_vertex_attrib_array(index)
1861    }
1862    pub fn disable_vertex_attrib_array(&self, index: GLuint) {
1863        self.get().disable_vertex_attrib_array(index)
1864    }
1865    pub fn uniform_1f(&self, location: GLint, v0: GLfloat) {
1866        self.get().uniform_1f(location, v0)
1867    }
1868    pub fn uniform_1fv(&self, location: GLint, values: F32VecRef) {
1869        self.get().uniform_1fv(location, values.as_slice())
1870    }
1871    pub fn uniform_1i(&self, location: GLint, v0: GLint) {
1872        self.get().uniform_1i(location, v0)
1873    }
1874    pub fn uniform_1iv(&self, location: GLint, values: I32VecRef) {
1875        self.get().uniform_1iv(location, values.as_slice())
1876    }
1877    pub fn uniform_1ui(&self, location: GLint, v0: GLuint) {
1878        self.get().uniform_1ui(location, v0)
1879    }
1880    pub fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) {
1881        self.get().uniform_2f(location, v0, v1)
1882    }
1883    pub fn uniform_2fv(&self, location: GLint, values: F32VecRef) {
1884        self.get().uniform_2fv(location, values.as_slice())
1885    }
1886    pub fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) {
1887        self.get().uniform_2i(location, v0, v1)
1888    }
1889    pub fn uniform_2iv(&self, location: GLint, values: I32VecRef) {
1890        self.get().uniform_2iv(location, values.as_slice())
1891    }
1892    pub fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) {
1893        self.get().uniform_2ui(location, v0, v1)
1894    }
1895    pub fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
1896        self.get().uniform_3f(location, v0, v1, v2)
1897    }
1898    pub fn uniform_3fv(&self, location: GLint, values: F32VecRef) {
1899        self.get().uniform_3fv(location, values.as_slice())
1900    }
1901    pub fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) {
1902        self.get().uniform_3i(location, v0, v1, v2)
1903    }
1904    pub fn uniform_3iv(&self, location: GLint, values: I32VecRef) {
1905        self.get().uniform_3iv(location, values.as_slice())
1906    }
1907    pub fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
1908        self.get().uniform_3ui(location, v0, v1, v2)
1909    }
1910    pub fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
1911        self.get().uniform_4f(location, x, y, z, w)
1912    }
1913    pub fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) {
1914        self.get().uniform_4i(location, x, y, z, w)
1915    }
1916    pub fn uniform_4iv(&self, location: GLint, values: I32VecRef) {
1917        self.get().uniform_4iv(location, values.as_slice())
1918    }
1919    pub fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
1920        self.get().uniform_4ui(location, x, y, z, w)
1921    }
1922    pub fn uniform_4fv(&self, location: GLint, values: F32VecRef) {
1923        self.get().uniform_4fv(location, values.as_slice())
1924    }
1925    pub fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: F32VecRef) {
1926        self.get()
1927            .uniform_matrix_2fv(location, transpose, value.as_slice())
1928    }
1929    pub fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: F32VecRef) {
1930        self.get()
1931            .uniform_matrix_3fv(location, transpose, value.as_slice())
1932    }
1933    pub fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: F32VecRef) {
1934        self.get()
1935            .uniform_matrix_4fv(location, transpose, value.as_slice())
1936    }
1937    pub fn depth_mask(&self, flag: bool) {
1938        self.get().depth_mask(flag)
1939    }
1940    pub fn depth_range(&self, near: f64, far: f64) {
1941        self.get().depth_range(near, far)
1942    }
1943    pub fn get_active_attrib(&self, program: GLuint, index: GLuint) -> GetActiveAttribReturn {
1944        let r = self.get().get_active_attrib(program, index);
1945        GetActiveAttribReturn {
1946            _0: r.0,
1947            _1: r.1,
1948            _2: r.2.into(),
1949        }
1950    }
1951    pub fn get_active_uniform(&self, program: GLuint, index: GLuint) -> GetActiveUniformReturn {
1952        let r = self.get().get_active_uniform(program, index);
1953        GetActiveUniformReturn {
1954            _0: r.0,
1955            _1: r.1,
1956            _2: r.2.into(),
1957        }
1958    }
1959    pub fn get_active_uniforms_iv(
1960        &self,
1961        program: GLuint,
1962        indices: GLuintVec,
1963        pname: GLenum,
1964    ) -> GLintVec {
1965        self.get()
1966            .get_active_uniforms_iv(program, indices.into_library_owned_vec(), pname)
1967            .into()
1968    }
1969    pub fn get_active_uniform_block_i(
1970        &self,
1971        program: GLuint,
1972        index: GLuint,
1973        pname: GLenum,
1974    ) -> GLint {
1975        self.get().get_active_uniform_block_i(program, index, pname)
1976    }
1977    pub fn get_active_uniform_block_iv(
1978        &self,
1979        program: GLuint,
1980        index: GLuint,
1981        pname: GLenum,
1982    ) -> GLintVec {
1983        self.get()
1984            .get_active_uniform_block_iv(program, index, pname)
1985            .into()
1986    }
1987    pub fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> AzString {
1988        self.get()
1989            .get_active_uniform_block_name(program, index)
1990            .into()
1991    }
1992    pub fn get_attrib_location(&self, program: GLuint, name: Refstr) -> c_int {
1993        self.get().get_attrib_location(program, name.as_str())
1994    }
1995    pub fn get_frag_data_location(&self, program: GLuint, name: Refstr) -> c_int {
1996        self.get().get_frag_data_location(program, name.as_str())
1997    }
1998    pub fn get_uniform_location(&self, program: GLuint, name: Refstr) -> c_int {
1999        self.get().get_uniform_location(program, name.as_str())
2000    }
2001    pub fn get_program_info_log(&self, program: GLuint) -> AzString {
2002        self.get().get_program_info_log(program).into()
2003    }
2004    pub fn get_program_iv(&self, program: GLuint, pname: GLenum, mut result: GLintVecRefMut) {
2005        unsafe {
2006            self.get()
2007                .get_program_iv(program, pname, result.as_mut_slice())
2008        }
2009    }
2010    pub fn get_program_binary(&self, program: GLuint) -> GetProgramBinaryReturn {
2011        let r = self.get().get_program_binary(program);
2012        GetProgramBinaryReturn {
2013            _0: r.0.into(),
2014            _1: r.1,
2015        }
2016    }
2017    pub fn program_binary(&self, program: GLuint, format: GLenum, binary: U8VecRef) {
2018        self.get()
2019            .program_binary(program, format, binary.as_slice())
2020    }
2021    pub fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint) {
2022        self.get().program_parameter_i(program, pname, value)
2023    }
2024    pub fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, mut result: GLintVecRefMut) {
2025        unsafe {
2026            self.get()
2027                .get_vertex_attrib_iv(index, pname, result.as_mut_slice())
2028        }
2029    }
2030    pub fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, mut result: GLfloatVecRefMut) {
2031        unsafe {
2032            self.get()
2033                .get_vertex_attrib_fv(index, pname, result.as_mut_slice())
2034        }
2035    }
2036    pub fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr {
2037        self.get().get_vertex_attrib_pointer_v(index, pname)
2038    }
2039    pub fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint {
2040        self.get().get_buffer_parameter_iv(target, pname)
2041    }
2042    pub fn get_shader_info_log(&self, shader: GLuint) -> AzString {
2043        self.get().get_shader_info_log(shader).into()
2044    }
2045    pub fn get_string(&self, which: GLenum) -> AzString {
2046        self.get().get_string(which).into()
2047    }
2048    pub fn get_string_i(&self, which: GLenum, index: GLuint) -> AzString {
2049        self.get().get_string_i(which, index).into()
2050    }
2051    pub fn get_shader_iv(&self, shader: GLuint, pname: GLenum, mut result: GLintVecRefMut) {
2052        unsafe {
2053            self.get()
2054                .get_shader_iv(shader, pname, result.as_mut_slice())
2055        }
2056    }
2057    pub fn get_shader_precision_format(
2058        &self,
2059        shader_type: GLuint,
2060        precision_type: GLuint,
2061    ) -> GlShaderPrecisionFormatReturn {
2062        let r = self
2063            .get()
2064            .get_shader_precision_format(shader_type, precision_type);
2065        GlShaderPrecisionFormatReturn {
2066            _0: r.0,
2067            _1: r.1,
2068            _2: r.2,
2069        }
2070    }
2071    pub fn compile_shader(&self, shader: GLuint) {
2072        self.get().compile_shader(shader)
2073    }
2074    pub fn create_program(&self) -> GLuint {
2075        self.get().create_program()
2076    }
2077    pub fn delete_program(&self, program: GLuint) {
2078        self.get().delete_program(program)
2079    }
2080    pub fn create_shader(&self, shader_type: GLenum) -> GLuint {
2081        self.get().create_shader(shader_type)
2082    }
2083    pub fn delete_shader(&self, shader: GLuint) {
2084        self.get().delete_shader(shader)
2085    }
2086    pub fn detach_shader(&self, program: GLuint, shader: GLuint) {
2087        self.get().detach_shader(program, shader)
2088    }
2089    pub fn link_program(&self, program: GLuint) {
2090        self.get().link_program(program)
2091    }
2092    pub fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) {
2093        self.get().clear_color(r, g, b, a)
2094    }
2095    pub fn clear(&self, buffer_mask: GLbitfield) {
2096        self.get().clear(buffer_mask)
2097    }
2098    pub fn clear_depth(&self, depth: f64) {
2099        self.get().clear_depth(depth)
2100    }
2101    pub fn clear_stencil(&self, s: GLint) {
2102        self.get().clear_stencil(s)
2103    }
2104    pub fn flush(&self) {
2105        self.get().flush()
2106    }
2107    pub fn finish(&self) {
2108        self.get().finish()
2109    }
2110    pub fn get_error(&self) -> GLenum {
2111        self.get().get_error()
2112    }
2113    pub fn stencil_mask(&self, mask: GLuint) {
2114        self.get().stencil_mask(mask)
2115    }
2116    pub fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) {
2117        self.get().stencil_mask_separate(face, mask)
2118    }
2119    pub fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint) {
2120        self.get().stencil_func(func, ref_, mask)
2121    }
2122    pub fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint) {
2123        self.get().stencil_func_separate(face, func, ref_, mask)
2124    }
2125    pub fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
2126        self.get().stencil_op(sfail, dpfail, dppass)
2127    }
2128    pub fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
2129        self.get().stencil_op_separate(face, sfail, dpfail, dppass)
2130    }
2131    pub fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GlVoidPtrConst) {
2132        self.get()
2133            .egl_image_target_texture2d_oes(target, image.ptr as *const gl_context_loader::c_void)
2134    }
2135    pub fn generate_mipmap(&self, target: GLenum) {
2136        self.get().generate_mipmap(target)
2137    }
2138    pub fn insert_event_marker_ext(&self, message: Refstr) {
2139        self.get().insert_event_marker_ext(message.as_str())
2140    }
2141    pub fn push_group_marker_ext(&self, message: Refstr) {
2142        self.get().push_group_marker_ext(message.as_str())
2143    }
2144    pub fn pop_group_marker_ext(&self) {
2145        self.get().pop_group_marker_ext()
2146    }
2147    pub fn debug_message_insert_khr(
2148        &self,
2149        source: GLenum,
2150        type_: GLenum,
2151        id: GLuint,
2152        severity: GLenum,
2153        message: Refstr,
2154    ) {
2155        self.get()
2156            .debug_message_insert_khr(source, type_, id, severity, message.as_str())
2157    }
2158    pub fn push_debug_group_khr(&self, source: GLenum, id: GLuint, message: Refstr) {
2159        self.get()
2160            .push_debug_group_khr(source, id, message.as_str())
2161    }
2162    pub fn pop_debug_group_khr(&self) {
2163        self.get().pop_debug_group_khr()
2164    }
2165    pub fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsyncPtr {
2166        GLsyncPtr::new(self.get().fence_sync(condition, flags))
2167    }
2168    pub fn client_wait_sync(&self, sync: GLsyncPtr, flags: GLbitfield, timeout: GLuint64) -> u32 {
2169        self.get().client_wait_sync(sync.get(), flags, timeout)
2170    }
2171    pub fn wait_sync(&self, sync: GLsyncPtr, flags: GLbitfield, timeout: GLuint64) {
2172        self.get().wait_sync(sync.get(), flags, timeout)
2173    }
2174    pub fn delete_sync(&self, sync: GLsyncPtr) {
2175        self.get().delete_sync(sync.get())
2176    }
2177    pub fn texture_range_apple(&self, target: GLenum, data: U8VecRef) {
2178        self.get().texture_range_apple(target, data.as_slice())
2179    }
2180    pub fn gen_fences_apple(&self, n: GLsizei) -> GLuintVec {
2181        self.get().gen_fences_apple(n).into()
2182    }
2183    pub fn delete_fences_apple(&self, fences: GLuintVecRef) {
2184        self.get().delete_fences_apple(fences.as_slice())
2185    }
2186    pub fn set_fence_apple(&self, fence: GLuint) {
2187        self.get().set_fence_apple(fence)
2188    }
2189    pub fn finish_fence_apple(&self, fence: GLuint) {
2190        self.get().finish_fence_apple(fence)
2191    }
2192    pub fn test_fence_apple(&self, fence: GLuint) {
2193        self.get().test_fence_apple(fence)
2194    }
2195    pub fn test_object_apple(&self, object: GLenum, name: GLuint) -> GLboolean {
2196        self.get().test_object_apple(object, name)
2197    }
2198    pub fn finish_object_apple(&self, object: GLenum, name: GLuint) {
2199        self.get().finish_object_apple(object, name)
2200    }
2201    pub fn get_frag_data_index(&self, program: GLuint, name: Refstr) -> GLint {
2202        self.get().get_frag_data_index(program, name.as_str())
2203    }
2204    pub fn blend_barrier_khr(&self) {
2205        self.get().blend_barrier_khr()
2206    }
2207    pub fn bind_frag_data_location_indexed(
2208        &self,
2209        program: GLuint,
2210        color_number: GLuint,
2211        index: GLuint,
2212        name: Refstr,
2213    ) {
2214        self.get()
2215            .bind_frag_data_location_indexed(program, color_number, index, name.as_str())
2216    }
2217    pub fn get_debug_messages(&self) -> AzDebugMessageVec {
2218        let dmv: Vec<AzDebugMessage> = self
2219            .get()
2220            .get_debug_messages()
2221            .into_iter()
2222            .map(|d| AzDebugMessage {
2223                message: d.message.into(),
2224                source: d.source,
2225                ty: d.ty,
2226                id: d.ty,
2227                severity: d.severity,
2228            })
2229            .collect();
2230        dmv.into()
2231    }
2232    pub fn provoking_vertex_angle(&self, mode: GLenum) {
2233        self.get().provoking_vertex_angle(mode)
2234    }
2235    pub fn gen_vertex_arrays_apple(&self, n: GLsizei) -> GLuintVec {
2236        self.get().gen_vertex_arrays_apple(n).into()
2237    }
2238    pub fn bind_vertex_array_apple(&self, vao: GLuint) {
2239        self.get().bind_vertex_array_apple(vao)
2240    }
2241    pub fn delete_vertex_arrays_apple(&self, vertex_arrays: GLuintVecRef) {
2242        self.get()
2243            .delete_vertex_arrays_apple(vertex_arrays.as_slice())
2244    }
2245    pub fn copy_texture_chromium(
2246        &self,
2247        source_id: GLuint,
2248        source_level: GLint,
2249        dest_target: GLenum,
2250        dest_id: GLuint,
2251        dest_level: GLint,
2252        internal_format: GLint,
2253        dest_type: GLenum,
2254        unpack_flip_y: GLboolean,
2255        unpack_premultiply_alpha: GLboolean,
2256        unpack_unmultiply_alpha: GLboolean,
2257    ) {
2258        self.get().copy_texture_chromium(
2259            source_id,
2260            source_level,
2261            dest_target,
2262            dest_id,
2263            dest_level,
2264            internal_format,
2265            dest_type,
2266            unpack_flip_y,
2267            unpack_premultiply_alpha,
2268            unpack_unmultiply_alpha,
2269        )
2270    }
2271    pub fn copy_sub_texture_chromium(
2272        &self,
2273        source_id: GLuint,
2274        source_level: GLint,
2275        dest_target: GLenum,
2276        dest_id: GLuint,
2277        dest_level: GLint,
2278        x_offset: GLint,
2279        y_offset: GLint,
2280        x: GLint,
2281        y: GLint,
2282        width: GLsizei,
2283        height: GLsizei,
2284        unpack_flip_y: GLboolean,
2285        unpack_premultiply_alpha: GLboolean,
2286        unpack_unmultiply_alpha: GLboolean,
2287    ) {
2288        self.get().copy_sub_texture_chromium(
2289            source_id,
2290            source_level,
2291            dest_target,
2292            dest_id,
2293            dest_level,
2294            x_offset,
2295            y_offset,
2296            x,
2297            y,
2298            width,
2299            height,
2300            unpack_flip_y,
2301            unpack_premultiply_alpha,
2302            unpack_unmultiply_alpha,
2303        )
2304    }
2305    pub fn egl_image_target_renderbuffer_storage_oes(&self, target: u32, image: GlVoidPtrConst) {
2306        self.get().egl_image_target_renderbuffer_storage_oes(
2307            target,
2308            image.ptr as *const gl_context_loader::c_void,
2309        )
2310    }
2311    pub fn copy_texture_3d_angle(
2312        &self,
2313        source_id: GLuint,
2314        source_level: GLint,
2315        dest_target: GLenum,
2316        dest_id: GLuint,
2317        dest_level: GLint,
2318        internal_format: GLint,
2319        dest_type: GLenum,
2320        unpack_flip_y: GLboolean,
2321        unpack_premultiply_alpha: GLboolean,
2322        unpack_unmultiply_alpha: GLboolean,
2323    ) {
2324        self.get().copy_texture_3d_angle(
2325            source_id,
2326            source_level,
2327            dest_target,
2328            dest_id,
2329            dest_level,
2330            internal_format,
2331            dest_type,
2332            unpack_flip_y,
2333            unpack_premultiply_alpha,
2334            unpack_unmultiply_alpha,
2335        )
2336    }
2337    pub fn copy_sub_texture_3d_angle(
2338        &self,
2339        source_id: GLuint,
2340        source_level: GLint,
2341        dest_target: GLenum,
2342        dest_id: GLuint,
2343        dest_level: GLint,
2344        x_offset: GLint,
2345        y_offset: GLint,
2346        z_offset: GLint,
2347        x: GLint,
2348        y: GLint,
2349        z: GLint,
2350        width: GLsizei,
2351        height: GLsizei,
2352        depth: GLsizei,
2353        unpack_flip_y: GLboolean,
2354        unpack_premultiply_alpha: GLboolean,
2355        unpack_unmultiply_alpha: GLboolean,
2356    ) {
2357        self.get().copy_sub_texture_3d_angle(
2358            source_id,
2359            source_level,
2360            dest_target,
2361            dest_id,
2362            dest_level,
2363            x_offset,
2364            y_offset,
2365            z_offset,
2366            x,
2367            y,
2368            z,
2369            width,
2370            height,
2371            depth,
2372            unpack_flip_y,
2373            unpack_premultiply_alpha,
2374            unpack_unmultiply_alpha,
2375        )
2376    }
2377    pub fn buffer_storage(
2378        &self,
2379        target: GLenum,
2380        size: GLsizeiptr,
2381        data: GlVoidPtrConst,
2382        flags: GLbitfield,
2383    ) {
2384        self.get().buffer_storage(target, size, data.ptr, flags)
2385    }
2386    pub fn flush_mapped_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr) {
2387        self.get().flush_mapped_buffer_range(target, offset, length)
2388    }
2389}
2390
2391impl PartialEq for GlContextPtr {
2392    fn eq(&self, rhs: &Self) -> bool {
2393        self.as_usize().eq(&rhs.as_usize())
2394    }
2395}
2396
2397impl Eq for GlContextPtr {}
2398
2399impl PartialOrd for GlContextPtr {
2400    fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
2401        self.as_usize().partial_cmp(&rhs.as_usize())
2402    }
2403}
2404
2405impl Ord for GlContextPtr {
2406    fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
2407        self.as_usize().cmp(&rhs.as_usize())
2408    }
2409}
2410
2411/// OpenGL texture, use `ReadOnlyWindow::create_texture` to create a texture
2412#[repr(C)]
2413pub struct Texture {
2414    /// Raw OpenGL texture ID
2415    pub texture_id: GLuint,
2416    /// Hints and flags for optimization purposes
2417    pub flags: TextureFlags,
2418    /// Size of this texture (in pixels)
2419    pub size: PhysicalSizeU32,
2420    /// Background color of this texture
2421    pub background_color: ColorU,
2422    /// A reference-counted pointer to the OpenGL context (so that the texture can be deleted in
2423    /// the destructor)
2424    pub gl_context: GlContextPtr,
2425    /// Format of the texture (rgba8, brga8, etc.)
2426    pub format: RawImageFormat,
2427    /// Reference count, shared across
2428    pub refcount: *const AtomicUsize,
2429    pub run_destructor: bool,
2430}
2431
2432impl Clone for Texture {
2433    fn clone(&self) -> Self {
2434        unsafe {
2435            (*self.refcount).fetch_add(1, AtomicOrdering::SeqCst);
2436        }
2437        Self {
2438            texture_id: self.texture_id.clone(),
2439            flags: self.flags.clone(),
2440            size: self.size.clone(),
2441            background_color: self.background_color.clone(),
2442            gl_context: self.gl_context.clone(),
2443            format: self.format.clone(),
2444            refcount: self.refcount,
2445            run_destructor: true,
2446        }
2447    }
2448}
2449
2450impl_option!(
2451    Texture,
2452    OptionTexture,
2453    copy = false,
2454    [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
2455);
2456
2457impl Texture {
2458    pub fn new(
2459        texture_id: GLuint,
2460        flags: TextureFlags,
2461        size: PhysicalSizeU32,
2462        background_color: ColorU,
2463        gl_context: GlContextPtr,
2464        format: RawImageFormat,
2465    ) -> Self {
2466        Self {
2467            texture_id,
2468            flags,
2469            size,
2470            background_color,
2471            gl_context,
2472            format,
2473            refcount: Box::into_raw(Box::new(AtomicUsize::new(1))),
2474            run_destructor: true,
2475        }
2476    }
2477
2478    pub fn allocate_rgba8(
2479        gl_context: GlContextPtr,
2480        size: PhysicalSizeU32,
2481        background: ColorU,
2482    ) -> Self {
2483        let textures = gl_context.gen_textures(1);
2484        let texture_id = textures.as_ref()[0];
2485
2486        let mut current_texture_2d = [0_i32];
2487        gl_context.get_integer_v(gl::TEXTURE_2D, (&mut current_texture_2d[..]).into());
2488
2489        gl_context.bind_texture(gl::TEXTURE_2D, texture_id);
2490        gl_context.tex_image_2d(
2491            gl::TEXTURE_2D,
2492            0,
2493            gl::RGBA as i32,
2494            size.width as i32,
2495            size.height as i32,
2496            0,
2497            gl::RGBA,
2498            gl::UNSIGNED_BYTE,
2499            None.into(),
2500        );
2501        gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32);
2502        gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
2503        gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
2504        gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
2505        gl_context.bind_texture(gl::TEXTURE_2D, current_texture_2d[0] as u32);
2506
2507        Self::new(
2508            texture_id,
2509            TextureFlags {
2510                is_opaque: false,
2511                is_video_texture: false,
2512            },
2513            size,
2514            background,
2515            gl_context,
2516            RawImageFormat::BGRA8,
2517        )
2518    }
2519
2520    pub fn clear(&mut self) {
2521        // save the OpenGL state
2522        let mut current_multisample = [0_u8];
2523        let mut current_index_buffer = [0_i32];
2524        let mut current_vertex_buffer = [0_i32];
2525        let mut current_vertex_array_object = [0_i32];
2526        let mut current_program = [0_i32];
2527        let mut current_framebuffers = [0_i32];
2528        let mut current_renderbuffers = [0_i32];
2529        let mut current_texture_2d = [0_i32];
2530
2531        self.gl_context
2532            .get_boolean_v(gl::MULTISAMPLE, (&mut current_multisample[..]).into());
2533        self.gl_context.get_integer_v(
2534            gl::ARRAY_BUFFER_BINDING,
2535            (&mut current_vertex_buffer[..]).into(),
2536        );
2537        self.gl_context.get_integer_v(
2538            gl::ELEMENT_ARRAY_BUFFER_BINDING,
2539            (&mut current_index_buffer[..]).into(),
2540        );
2541        self.gl_context
2542            .get_integer_v(gl::CURRENT_PROGRAM, (&mut current_program[..]).into());
2543        self.gl_context.get_integer_v(
2544            gl::VERTEX_ARRAY_BINDING,
2545            (&mut current_vertex_array_object[..]).into(),
2546        );
2547        self.gl_context
2548            .get_integer_v(gl::RENDERBUFFER, (&mut current_renderbuffers[..]).into());
2549        self.gl_context
2550            .get_integer_v(gl::FRAMEBUFFER, (&mut current_framebuffers[..]).into());
2551        self.gl_context
2552            .get_integer_v(gl::TEXTURE_2D, (&mut current_texture_2d[..]).into());
2553
2554        let framebuffers = self.gl_context.gen_framebuffers(1);
2555        let framebuffer_id = framebuffers.get(0).unwrap();
2556        self.gl_context
2557            .bind_framebuffer(gl::FRAMEBUFFER, *framebuffer_id);
2558
2559        let depthbuffers = self.gl_context.gen_renderbuffers(1);
2560        let depthbuffer_id = depthbuffers.get(0).unwrap();
2561
2562        self.gl_context
2563            .bind_texture(gl::TEXTURE_2D, self.texture_id);
2564        self.gl_context.tex_image_2d(
2565            gl::TEXTURE_2D,
2566            0,
2567            gl::RGBA as i32, // NOT RGBA8 - will generate INVALID_ENUM!
2568            self.size.width as i32,
2569            self.size.height as i32,
2570            0,
2571            gl::RGBA, // gl::BRGA?
2572            gl::UNSIGNED_BYTE,
2573            None.into(),
2574        );
2575        self.gl_context
2576            .tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32);
2577        self.gl_context
2578            .tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
2579        self.gl_context.tex_parameter_i(
2580            gl::TEXTURE_2D,
2581            gl::TEXTURE_WRAP_S,
2582            gl::CLAMP_TO_EDGE as i32,
2583        );
2584        self.gl_context.tex_parameter_i(
2585            gl::TEXTURE_2D,
2586            gl::TEXTURE_WRAP_T,
2587            gl::CLAMP_TO_EDGE as i32,
2588        );
2589
2590        self.gl_context
2591            .bind_renderbuffer(gl::RENDERBUFFER, *depthbuffer_id);
2592        self.gl_context.renderbuffer_storage(
2593            gl::RENDERBUFFER,
2594            gl::DEPTH_COMPONENT,
2595            self.size.width as i32,
2596            self.size.height as i32,
2597        );
2598        self.gl_context.framebuffer_renderbuffer(
2599            gl::FRAMEBUFFER,
2600            gl::DEPTH_ATTACHMENT,
2601            gl::RENDERBUFFER,
2602            *depthbuffer_id,
2603        );
2604
2605        self.gl_context.framebuffer_texture_2d(
2606            gl::FRAMEBUFFER,
2607            gl::COLOR_ATTACHMENT0,
2608            gl::TEXTURE_2D,
2609            self.texture_id,
2610            0,
2611        );
2612        self.gl_context
2613            .draw_buffers([gl::COLOR_ATTACHMENT0][..].into());
2614
2615        let clear_color: ColorF = self.background_color.into();
2616        self.gl_context
2617            .clear_color(clear_color.r, clear_color.g, clear_color.b, clear_color.a);
2618        self.gl_context.clear_depth(0.0);
2619        self.gl_context
2620            .clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
2621
2622        // Reset the OpenGL state
2623        if u32::from(current_multisample[0]) == gl::TRUE {
2624            self.gl_context.enable(gl::MULTISAMPLE);
2625        }
2626        self.gl_context
2627            .bind_framebuffer(gl::FRAMEBUFFER, current_framebuffers[0] as u32);
2628        self.gl_context
2629            .bind_texture(gl::TEXTURE_2D, current_texture_2d[0] as u32);
2630        self.gl_context
2631            .bind_buffer(gl::RENDERBUFFER, current_renderbuffers[0] as u32);
2632        self.gl_context
2633            .bind_vertex_array(current_vertex_array_object[0] as u32);
2634        self.gl_context
2635            .bind_buffer(gl::ELEMENT_ARRAY_BUFFER, current_index_buffer[0] as u32);
2636        self.gl_context
2637            .bind_buffer(gl::ARRAY_BUFFER, current_vertex_buffer[0] as u32);
2638        self.gl_context.use_program(current_program[0] as u32);
2639
2640        self.gl_context
2641            .delete_framebuffers((&[*framebuffer_id])[..].into());
2642        self.gl_context
2643            .delete_renderbuffers((&[*depthbuffer_id])[..].into());
2644
2645        self.gl_context
2646            .bind_texture(gl::TEXTURE_2D, current_texture_2d[0] as u32);
2647    }
2648
2649    pub fn get_descriptor(&self) -> ImageDescriptor {
2650        ImageDescriptor {
2651            format: self.format,
2652            width: self.size.width as usize,
2653            height: self.size.height as usize,
2654            stride: None.into(),
2655            offset: 0,
2656            flags: ImageDescriptorFlags {
2657                is_opaque: self.flags.is_opaque,
2658                // The texture gets mapped 1:1 onto the display, so there is no need for mipmaps
2659                allow_mipmaps: false,
2660            },
2661        }
2662    }
2663}
2664
2665#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2666#[repr(C)]
2667pub struct TextureFlags {
2668    /// Whether this texture contains an alpha component
2669    pub is_opaque: bool,
2670    /// Optimization: use the compositor instead of OpenGL for energy optimization
2671    pub is_video_texture: bool,
2672}
2673
2674impl ::core::fmt::Display for Texture {
2675    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
2676        write!(
2677            f,
2678            "Texture {{ id: {}, {}x{} }}",
2679            self.texture_id, self.size.width, self.size.height
2680        )
2681    }
2682}
2683
2684macro_rules! impl_traits_for_gl_object {
2685    ($struct_name:ident, $gl_id_field:ident) => {
2686        impl ::core::fmt::Debug for $struct_name {
2687            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
2688                write!(f, "{}", self)
2689            }
2690        }
2691
2692        impl Hash for $struct_name {
2693            fn hash<H: Hasher>(&self, state: &mut H) {
2694                self.$gl_id_field.hash(state);
2695            }
2696        }
2697
2698        impl PartialEq for $struct_name {
2699            fn eq(&self, other: &$struct_name) -> bool {
2700                self.$gl_id_field == other.$gl_id_field
2701            }
2702        }
2703
2704        impl Eq for $struct_name {}
2705
2706        impl PartialOrd for $struct_name {
2707            fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
2708                Some((self.$gl_id_field).cmp(&(other.$gl_id_field)))
2709            }
2710        }
2711
2712        impl Ord for $struct_name {
2713            fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
2714                (self.$gl_id_field).cmp(&(other.$gl_id_field))
2715            }
2716        }
2717    };
2718    ($struct_name:ident < $lt:lifetime > , $gl_id_field:ident) => {
2719        impl<$lt> ::core::fmt::Debug for $struct_name<$lt> {
2720            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
2721                write!(f, "{}", self)
2722            }
2723        }
2724
2725        impl<$lt> Hash for $struct_name<$lt> {
2726            fn hash<H: Hasher>(&self, state: &mut H) {
2727                self.$gl_id_field.hash(state);
2728            }
2729        }
2730
2731        impl<$lt> PartialEq for $struct_name<$lt> {
2732            fn eq(&self, other: &$struct_name) -> bool {
2733                self.$gl_id_field == other.$gl_id_field
2734            }
2735        }
2736
2737        impl<$lt> Eq for $struct_name<$lt> {}
2738
2739        impl<$lt> PartialOrd for $struct_name<$lt> {
2740            fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
2741                Some((self.$gl_id_field).cmp(&(other.$gl_id_field)))
2742            }
2743        }
2744
2745        impl<$lt> Ord for $struct_name<$lt> {
2746            fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
2747                (self.$gl_id_field).cmp(&(other.$gl_id_field))
2748            }
2749        }
2750    };
2751    ($struct_name:ident < $t:ident : $constraint:ident > , $gl_id_field:ident) => {
2752        impl<$t: $constraint> ::core::fmt::Debug for $struct_name<$t> {
2753            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
2754                write!(f, "{}", self)
2755            }
2756        }
2757
2758        impl<$t: $constraint> Hash for $struct_name<$t> {
2759            fn hash<H: Hasher>(&self, state: &mut H) {
2760                self.$gl_id_field.hash(state);
2761            }
2762        }
2763
2764        impl<$t: $constraint> PartialEq for $struct_name<$t> {
2765            fn eq(&self, other: &$struct_name<$t>) -> bool {
2766                self.$gl_id_field == other.$gl_id_field
2767            }
2768        }
2769
2770        impl<$t: $constraint> Eq for $struct_name<$t> {}
2771
2772        impl<$t: $constraint> PartialOrd for $struct_name<$t> {
2773            fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
2774                Some((self.$gl_id_field).cmp(&(other.$gl_id_field)))
2775            }
2776        }
2777
2778        impl<$t: $constraint> Ord for $struct_name<$t> {
2779            fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
2780                (self.$gl_id_field).cmp(&(other.$gl_id_field))
2781            }
2782        }
2783    };
2784}
2785
2786impl_traits_for_gl_object!(Texture, texture_id);
2787
2788impl Drop for Texture {
2789    fn drop(&mut self) {
2790        self.run_destructor = false;
2791        let copies = unsafe { (*self.refcount).fetch_sub(1, AtomicOrdering::SeqCst) };
2792        if copies == 1 {
2793            let _ = unsafe { Box::from_raw(self.refcount as *mut AtomicUsize) };
2794            self.gl_context
2795                .delete_textures((&[self.texture_id])[..].into());
2796        }
2797    }
2798}
2799
2800/// Describes the vertex layout and offsets
2801#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2802#[repr(C)]
2803pub struct VertexLayout {
2804    pub fields: VertexAttributeVec,
2805}
2806
2807impl_vec!(
2808    VertexAttribute,
2809    VertexAttributeVec,
2810    VertexAttributeVecDestructor
2811);
2812impl_vec_debug!(VertexAttribute, VertexAttributeVec);
2813impl_vec_partialord!(VertexAttribute, VertexAttributeVec);
2814impl_vec_ord!(VertexAttribute, VertexAttributeVec);
2815impl_vec_clone!(
2816    VertexAttribute,
2817    VertexAttributeVec,
2818    VertexAttributeVecDestructor
2819);
2820impl_vec_partialeq!(VertexAttribute, VertexAttributeVec);
2821impl_vec_eq!(VertexAttribute, VertexAttributeVec);
2822impl_vec_hash!(VertexAttribute, VertexAttributeVec);
2823
2824impl VertexLayout {
2825    /// Submits the vertex buffer description to OpenGL
2826    pub fn bind(&self, gl_context: &Rc<GenericGlContext>, program_id: GLuint) {
2827        const VERTICES_ARE_NORMALIZED: bool = false;
2828
2829        let mut offset = 0;
2830
2831        let stride_between_vertices: usize =
2832            self.fields.iter().map(VertexAttribute::get_stride).sum();
2833
2834        for vertex_attribute in self.fields.iter() {
2835            let attribute_location = vertex_attribute
2836                .layout_location
2837                .as_option()
2838                .map(|ll| *ll as i32)
2839                .unwrap_or_else(|| {
2840                    gl_context
2841                        .get_attrib_location(program_id, vertex_attribute.name.as_str().into())
2842                });
2843
2844            gl_context.vertex_attrib_pointer(
2845                attribute_location as u32,
2846                vertex_attribute.item_count as i32,
2847                vertex_attribute.attribute_type.get_gl_id(),
2848                VERTICES_ARE_NORMALIZED,
2849                stride_between_vertices as i32,
2850                offset as u32,
2851            );
2852            gl_context.enable_vertex_attrib_array(attribute_location as u32);
2853            offset += vertex_attribute.get_stride();
2854        }
2855    }
2856
2857    /// Unsets the vertex buffer description
2858    pub fn unbind(&self, gl_context: &Rc<GenericGlContext>, program_id: GLuint) {
2859        for vertex_attribute in self.fields.iter() {
2860            let attribute_location = vertex_attribute
2861                .layout_location
2862                .as_option()
2863                .map(|ll| *ll as i32)
2864                .unwrap_or_else(|| {
2865                    gl_context
2866                        .get_attrib_location(program_id, vertex_attribute.name.as_str().into())
2867                });
2868            gl_context.disable_vertex_attrib_array(attribute_location as u32);
2869        }
2870    }
2871}
2872
2873#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2874#[repr(C)]
2875pub struct VertexAttribute {
2876    /// Attribute name of the vertex attribute in the vertex shader, i.e. `"vAttrXY"`
2877    pub name: AzString,
2878    /// If the vertex shader has a specific location, (like `layout(location = 2) vAttrXY`),
2879    /// use this instead of the name to look up the uniform location.
2880    pub layout_location: OptionUsize,
2881    /// Type of items of this attribute (i.e. for a `FloatVec2`, would be
2882    /// `VertexAttributeType::Float`)
2883    pub attribute_type: VertexAttributeType,
2884    /// Number of items of this attribute (i.e. for a `FloatVec2`, would be `2` (= 2 consecutive
2885    /// f32 values))
2886    pub item_count: usize,
2887}
2888
2889impl_option!(
2890    usize,
2891    OptionUsize,
2892    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
2893);
2894
2895impl VertexAttribute {
2896    pub fn get_stride(&self) -> usize {
2897        self.attribute_type.get_mem_size() * self.item_count
2898    }
2899}
2900
2901#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2902#[repr(C)]
2903pub enum VertexAttributeType {
2904    /// Vertex attribute has type `f32`
2905    Float,
2906    /// Vertex attribute has type `f64`
2907    Double,
2908    /// Vertex attribute has type `u8`
2909    UnsignedByte,
2910    /// Vertex attribute has type `u16`
2911    UnsignedShort,
2912    /// Vertex attribute has type `u32`
2913    UnsignedInt,
2914}
2915
2916impl VertexAttributeType {
2917    /// Returns the OpenGL id for the vertex attribute type, ex. `gl::UNSIGNED_BYTE` for
2918    /// `VertexAttributeType::UnsignedByte`.
2919    pub fn get_gl_id(&self) -> GLuint {
2920        use self::VertexAttributeType::*;
2921        match self {
2922            Float => gl::FLOAT,
2923            Double => gl::DOUBLE,
2924            UnsignedByte => gl::UNSIGNED_BYTE,
2925            UnsignedShort => gl::UNSIGNED_SHORT,
2926            UnsignedInt => gl::UNSIGNED_INT,
2927        }
2928    }
2929
2930    pub fn get_mem_size(&self) -> usize {
2931        use core::mem;
2932
2933        use self::VertexAttributeType::*;
2934        match self {
2935            Float => mem::size_of::<f32>(),
2936            Double => mem::size_of::<f64>(),
2937            UnsignedByte => mem::size_of::<u8>(),
2938            UnsignedShort => mem::size_of::<u16>(),
2939            UnsignedInt => mem::size_of::<u32>(),
2940        }
2941    }
2942}
2943
2944pub trait VertexLayoutDescription {
2945    fn get_description() -> VertexLayout;
2946}
2947
2948#[derive(Debug, PartialEq, PartialOrd)]
2949#[repr(C)]
2950pub struct VertexArrayObject {
2951    pub vertex_layout: VertexLayout,
2952    pub vao_id: GLuint,
2953    pub gl_context: GlContextPtr,
2954    pub refcount: *const AtomicUsize,
2955    pub run_destructor: bool,
2956}
2957
2958impl VertexArrayObject {
2959    pub fn new(vertex_layout: VertexLayout, vao_id: GLuint, gl_context: GlContextPtr) -> Self {
2960        Self {
2961            vertex_layout,
2962            vao_id,
2963            gl_context,
2964            refcount: Box::into_raw(Box::new(AtomicUsize::new(1))),
2965            run_destructor: true,
2966        }
2967    }
2968}
2969
2970impl Clone for VertexArrayObject {
2971    fn clone(&self) -> Self {
2972        unsafe { (*self.refcount).fetch_add(1, AtomicOrdering::SeqCst) };
2973        Self {
2974            vertex_layout: self.vertex_layout.clone(),
2975            vao_id: self.vao_id,
2976            gl_context: self.gl_context.clone(),
2977            refcount: self.refcount,
2978            run_destructor: true,
2979        }
2980    }
2981}
2982
2983impl Drop for VertexArrayObject {
2984    fn drop(&mut self) {
2985        self.run_destructor = false;
2986        let copies = unsafe { (*self.refcount).fetch_sub(1, AtomicOrdering::SeqCst) };
2987        if copies == 1 {
2988            let _ = unsafe { Box::from_raw(self.refcount as *mut AtomicUsize) };
2989            self.gl_context
2990                .delete_vertex_arrays((&[self.vao_id])[..].into());
2991        }
2992    }
2993}
2994
2995#[repr(C)]
2996pub struct VertexBuffer {
2997    pub vertex_buffer_id: GLuint,
2998    pub vertex_buffer_len: usize,
2999    pub vao: VertexArrayObject,
3000    pub index_buffer_id: GLuint,
3001    pub index_buffer_len: usize,
3002    pub index_buffer_format: IndexBufferFormat,
3003    pub refcount: *const AtomicUsize,
3004    pub run_destructor: bool,
3005}
3006
3007impl core::fmt::Display for VertexBuffer {
3008    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
3009        write!(
3010            f,
3011            "VertexBuffer {{ buffer: {} (length: {}) }})",
3012            self.vertex_buffer_id, self.vertex_buffer_len
3013        )
3014    }
3015}
3016
3017impl_traits_for_gl_object!(VertexBuffer, vertex_buffer_id);
3018
3019impl Clone for VertexBuffer {
3020    fn clone(&self) -> Self {
3021        unsafe { (*self.refcount).fetch_add(1, AtomicOrdering::SeqCst) };
3022        Self {
3023            vertex_buffer_id: self.vertex_buffer_id.clone(),
3024            vertex_buffer_len: self.vertex_buffer_len.clone(),
3025            vao: self.vao.clone(),
3026            index_buffer_id: self.index_buffer_id.clone(),
3027            index_buffer_len: self.index_buffer_len.clone(),
3028            index_buffer_format: self.index_buffer_format.clone(),
3029            refcount: self.refcount,
3030            run_destructor: true,
3031        }
3032    }
3033}
3034
3035impl Drop for VertexBuffer {
3036    fn drop(&mut self) {
3037        self.run_destructor = false;
3038        let copies = unsafe { (*self.refcount).fetch_sub(1, AtomicOrdering::SeqCst) };
3039        if copies == 1 {
3040            self.vao.vertex_layout = VertexLayout {
3041                fields: VertexAttributeVec::from_const_slice(&[]),
3042            };
3043            let _ = unsafe { Box::from_raw(self.refcount as *mut AtomicUsize) };
3044            self.vao
3045                .gl_context
3046                .delete_buffers((&[self.vertex_buffer_id, self.index_buffer_id])[..].into());
3047        }
3048    }
3049}
3050
3051impl VertexBuffer {
3052    pub fn new<T: VertexLayoutDescription>(
3053        gl_context: GlContextPtr,
3054        shader_program_id: GLuint,
3055        vertices: &[T],
3056        indices: &[u32],
3057        index_buffer_format: IndexBufferFormat,
3058    ) -> Self {
3059        use core::mem;
3060
3061        // Save the OpenGL state
3062        let mut current_vertex_array = [0_i32];
3063        // let mut current_vertex_buffer = [0_i32];
3064        // let mut current_index_buffer = [0_i32];
3065
3066        gl_context.get_integer_v(gl::VERTEX_ARRAY, (&mut current_vertex_array[..]).into());
3067        // gl_context.get_integer_v(gl::ARRAY_BUFFER, (&mut current_vertex_buffer[..]).into());
3068        // gl_context.get_integer_v(gl::ELEMENT_ARRAY_BUFFER, (&mut
3069        // current_index_buffer[..]).into());
3070
3071        let vertex_array_object = gl_context.gen_vertex_arrays(1);
3072        let vertex_array_object = vertex_array_object.get(0).unwrap();
3073
3074        let vertex_buffer_id = gl_context.gen_buffers(1);
3075        let vertex_buffer_id = vertex_buffer_id.get(0).unwrap();
3076
3077        let index_buffer_id = gl_context.gen_buffers(1);
3078        let index_buffer_id = index_buffer_id.get(0).unwrap();
3079
3080        gl_context.bind_vertex_array(*vertex_array_object);
3081
3082        // Upload vertex data to GPU
3083        gl_context.bind_buffer(gl::ARRAY_BUFFER, *vertex_buffer_id);
3084        gl_context.buffer_data_untyped(
3085            gl::ARRAY_BUFFER,
3086            (mem::size_of::<T>() * vertices.len()) as isize,
3087            GlVoidPtrConst {
3088                ptr: vertices.as_ptr() as *const core::ffi::c_void,
3089                run_destructor: true,
3090            },
3091            gl::STATIC_DRAW,
3092        );
3093
3094        // Generate the index buffer + upload data
3095        gl_context.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, *index_buffer_id);
3096        gl_context.buffer_data_untyped(
3097            gl::ELEMENT_ARRAY_BUFFER,
3098            (mem::size_of::<u32>() * indices.len()) as isize,
3099            GlVoidPtrConst {
3100                ptr: indices.as_ptr() as *const core::ffi::c_void,
3101                run_destructor: true,
3102            },
3103            gl::STATIC_DRAW,
3104        );
3105
3106        let vertex_description = T::get_description();
3107        vertex_description.bind(&gl_context.ptr.ptr, shader_program_id);
3108
3109        // Reset the OpenGL state
3110        // gl_context.bind_buffer(gl::ARRAY_BUFFER, current_vertex_buffer[0] as u32);
3111        // gl_context.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, current_index_buffer[0] as u32);
3112        gl_context.bind_vertex_array(current_vertex_array[0] as u32);
3113
3114        Self::new_raw(
3115            *vertex_buffer_id,
3116            vertices.len(),
3117            VertexArrayObject::new(vertex_description, *vertex_array_object, gl_context),
3118            *index_buffer_id,
3119            indices.len(),
3120            index_buffer_format,
3121        )
3122    }
3123
3124    pub fn new_raw(
3125        vertex_buffer_id: GLuint,
3126        vertex_buffer_len: usize,
3127        vao: VertexArrayObject,
3128        index_buffer_id: GLuint,
3129        index_buffer_len: usize,
3130        index_buffer_format: IndexBufferFormat,
3131    ) -> Self {
3132        Self {
3133            vertex_buffer_id,
3134            vertex_buffer_len,
3135            vao,
3136            index_buffer_id,
3137            index_buffer_len,
3138            index_buffer_format,
3139            refcount: Box::into_raw(Box::new(AtomicUsize::new(1))),
3140            run_destructor: true,
3141        }
3142    }
3143}
3144
3145#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
3146pub enum GlApiVersion {
3147    Gl { major: usize, minor: usize },
3148    GlEs { major: usize, minor: usize },
3149}
3150
3151impl GlApiVersion {
3152    /// Returns the OpenGL version of the context
3153    pub fn get(gl_context: &GlContextPtr) -> Self {
3154        let mut major = [0];
3155        gl_context.get_integer_v(gl::MAJOR_VERSION, (&mut major[..]).into());
3156        let mut minor = [0];
3157        gl_context.get_integer_v(gl::MINOR_VERSION, (&mut minor[..]).into());
3158
3159        GlApiVersion::Gl {
3160            major: major[0] as usize,
3161            minor: minor[0] as usize,
3162        }
3163    }
3164}
3165
3166#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
3167#[repr(C)]
3168pub enum IndexBufferFormat {
3169    Points,
3170    Lines,
3171    LineStrip,
3172    Triangles,
3173    TriangleStrip,
3174    TriangleFan,
3175}
3176
3177impl IndexBufferFormat {
3178    /// Returns the `gl::TRIANGLE_STRIP` / `gl::POINTS`, etc.
3179    pub fn get_gl_id(&self) -> GLuint {
3180        use self::IndexBufferFormat::*;
3181        match self {
3182            Points => gl::POINTS,
3183            Lines => gl::LINES,
3184            LineStrip => gl::LINE_STRIP,
3185            Triangles => gl::TRIANGLES,
3186            TriangleStrip => gl::TRIANGLE_STRIP,
3187            TriangleFan => gl::TRIANGLE_FAN,
3188        }
3189    }
3190}
3191
3192#[derive(Debug, Clone, PartialEq, PartialOrd)]
3193#[repr(C)]
3194pub struct Uniform {
3195    pub name: AzString,
3196    pub uniform_type: UniformType,
3197}
3198
3199impl Uniform {
3200    pub fn new<S: Into<AzString>>(name: S, uniform_type: UniformType) -> Self {
3201        Self {
3202            name: name.into(),
3203            uniform_type,
3204        }
3205    }
3206}
3207
3208#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
3209#[repr(C, u8)]
3210pub enum UniformType {
3211    Float(f32),
3212    FloatVec2([f32; 2]),
3213    FloatVec3([f32; 3]),
3214    FloatVec4([f32; 4]),
3215    Int(i32),
3216    IntVec2([i32; 2]),
3217    IntVec3([i32; 3]),
3218    IntVec4([i32; 4]),
3219    UnsignedInt(u32),
3220    UnsignedIntVec2([u32; 2]),
3221    UnsignedIntVec3([u32; 3]),
3222    UnsignedIntVec4([u32; 4]),
3223    Matrix2 {
3224        transpose: bool,
3225        matrix: [f32; 2 * 2],
3226    },
3227    Matrix3 {
3228        transpose: bool,
3229        matrix: [f32; 3 * 3],
3230    },
3231    Matrix4 {
3232        transpose: bool,
3233        matrix: [f32; 4 * 4],
3234    },
3235}
3236
3237impl UniformType {
3238    /// Set a specific uniform
3239    pub fn set(self, gl_context: &Rc<GenericGlContext>, location: GLint) {
3240        use self::UniformType::*;
3241        match self {
3242            Float(r) => gl_context.uniform_1f(location, r),
3243            FloatVec2([r, g]) => gl_context.uniform_2f(location, r, g),
3244            FloatVec3([r, g, b]) => gl_context.uniform_3f(location, r, g, b),
3245            FloatVec4([r, g, b, a]) => gl_context.uniform_4f(location, r, g, b, a),
3246            Int(r) => gl_context.uniform_1i(location, r),
3247            IntVec2([r, g]) => gl_context.uniform_2i(location, r, g),
3248            IntVec3([r, g, b]) => gl_context.uniform_3i(location, r, g, b),
3249            IntVec4([r, g, b, a]) => gl_context.uniform_4i(location, r, g, b, a),
3250            UnsignedInt(r) => gl_context.uniform_1ui(location, r),
3251            UnsignedIntVec2([r, g]) => gl_context.uniform_2ui(location, r, g),
3252            UnsignedIntVec3([r, g, b]) => gl_context.uniform_3ui(location, r, g, b),
3253            UnsignedIntVec4([r, g, b, a]) => gl_context.uniform_4ui(location, r, g, b, a),
3254            Matrix2 { transpose, matrix } => {
3255                gl_context.uniform_matrix_2fv(location, transpose, &matrix[..])
3256            }
3257            Matrix3 { transpose, matrix } => {
3258                gl_context.uniform_matrix_3fv(location, transpose, &matrix[..])
3259            }
3260            Matrix4 { transpose, matrix } => {
3261                gl_context.uniform_matrix_4fv(location, transpose, &matrix[..])
3262            }
3263        }
3264    }
3265}
3266
3267#[repr(C)]
3268pub struct GlShader {
3269    pub program_id: GLuint,
3270    pub gl_context: GlContextPtr,
3271}
3272
3273impl ::core::fmt::Display for GlShader {
3274    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
3275        write!(f, "GlShader {{ program_id: {} }}", self.program_id)
3276    }
3277}
3278
3279impl_traits_for_gl_object!(GlShader, program_id);
3280
3281impl Drop for GlShader {
3282    fn drop(&mut self) {
3283        self.gl_context.delete_program(self.program_id);
3284    }
3285}
3286
3287#[repr(C)]
3288#[derive(Clone)]
3289pub struct VertexShaderCompileError {
3290    pub error_id: i32,
3291    pub info_log: AzString,
3292}
3293
3294impl_traits_for_gl_object!(VertexShaderCompileError, error_id);
3295
3296impl ::core::fmt::Display for VertexShaderCompileError {
3297    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
3298        write!(f, "E{}: {}", self.error_id, self.info_log)
3299    }
3300}
3301
3302#[repr(C)]
3303#[derive(Clone)]
3304pub struct FragmentShaderCompileError {
3305    pub error_id: i32,
3306    pub info_log: AzString,
3307}
3308
3309impl_traits_for_gl_object!(FragmentShaderCompileError, error_id);
3310
3311impl ::core::fmt::Display for FragmentShaderCompileError {
3312    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
3313        write!(f, "E{}: {}", self.error_id, self.info_log)
3314    }
3315}
3316
3317#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
3318pub enum GlShaderCompileError {
3319    Vertex(VertexShaderCompileError),
3320    Fragment(FragmentShaderCompileError),
3321}
3322
3323impl ::core::fmt::Display for GlShaderCompileError {
3324    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
3325        use self::GlShaderCompileError::*;
3326        match self {
3327            Vertex(vert_err) => write!(f, "Failed to compile vertex shader: {}", vert_err),
3328            Fragment(frag_err) => write!(f, "Failed to compile fragment shader: {}", frag_err),
3329        }
3330    }
3331}
3332
3333impl ::core::fmt::Debug for GlShaderCompileError {
3334    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
3335        write!(f, "{}", self)
3336    }
3337}
3338
3339#[repr(C)]
3340#[derive(Clone)]
3341pub struct GlShaderLinkError {
3342    pub error_id: i32,
3343    pub info_log: AzString,
3344}
3345
3346impl_traits_for_gl_object!(GlShaderLinkError, error_id);
3347
3348impl ::core::fmt::Display for GlShaderLinkError {
3349    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
3350        write!(f, "E{}: {}", self.error_id, self.info_log)
3351    }
3352}
3353
3354#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
3355pub enum GlShaderCreateError {
3356    Compile(GlShaderCompileError),
3357    Link(GlShaderLinkError),
3358    NoShaderCompiler,
3359}
3360
3361impl ::core::fmt::Display for GlShaderCreateError {
3362    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
3363        use self::GlShaderCreateError::*;
3364        match self {
3365            Compile(compile_err) => write!(f, "Shader compile error: {}", compile_err),
3366            Link(link_err) => write!(f, "Shader linking error: {}", link_err),
3367            NoShaderCompiler => {
3368                write!(f, "OpenGL implementation doesn't include a shader compiler")
3369            }
3370        }
3371    }
3372}
3373
3374impl ::core::fmt::Debug for GlShaderCreateError {
3375    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
3376        write!(f, "{}", self)
3377    }
3378}
3379
3380impl GlShader {
3381    /// Compiles and creates a new OpenGL shader, created from a vertex and a fragment shader
3382    /// string.
3383    ///
3384    /// If the shader fails to compile, the shader object gets automatically deleted, no cleanup
3385    /// necessary.
3386    pub fn new(
3387        gl_context: &GlContextPtr,
3388        vertex_shader: &str,
3389        fragment_shader: &str,
3390    ) -> Result<Self, GlShaderCreateError> {
3391        // Check whether the OpenGL implementation supports a shader compiler...
3392        let mut shader_compiler_supported = [gl::FALSE as u8];
3393        gl_context.get_boolean_v(
3394            gl::SHADER_COMPILER,
3395            (&mut shader_compiler_supported[..]).into(),
3396        );
3397        if u32::from(shader_compiler_supported[0]) == gl::FALSE {
3398            // Implementation only supports binary shaders
3399            return Err(GlShaderCreateError::NoShaderCompiler);
3400        }
3401
3402        // Compile vertex shader
3403
3404        let vertex_shader_object = gl_context.create_shader(gl::VERTEX_SHADER);
3405        gl_context.shader_source(
3406            vertex_shader_object,
3407            vec![AzString::from(vertex_shader.to_string())].into(),
3408        );
3409        gl_context.compile_shader(vertex_shader_object);
3410
3411        if let Some(error_id) = get_gl_shader_error(&gl_context, vertex_shader_object) {
3412            let info_log = gl_context.get_shader_info_log(vertex_shader_object);
3413            gl_context.delete_shader(vertex_shader_object);
3414            return Err(GlShaderCreateError::Compile(GlShaderCompileError::Vertex(
3415                VertexShaderCompileError {
3416                    error_id,
3417                    info_log: info_log.into(),
3418                },
3419            )));
3420        }
3421
3422        // Compile fragment shader
3423
3424        let fragment_shader_object = gl_context.create_shader(gl::FRAGMENT_SHADER);
3425        gl_context.shader_source(
3426            fragment_shader_object,
3427            vec![AzString::from(fragment_shader.to_string())].into(),
3428        );
3429        gl_context.compile_shader(fragment_shader_object);
3430
3431        if let Some(error_id) = get_gl_shader_error(&gl_context, fragment_shader_object) {
3432            let info_log = gl_context.get_shader_info_log(fragment_shader_object);
3433            gl_context.delete_shader(vertex_shader_object);
3434            gl_context.delete_shader(fragment_shader_object);
3435            return Err(GlShaderCreateError::Compile(
3436                GlShaderCompileError::Fragment(FragmentShaderCompileError {
3437                    error_id,
3438                    info_log: info_log.into(),
3439                }),
3440            ));
3441        }
3442
3443        // Link program
3444
3445        let program_id = gl_context.create_program();
3446        gl_context.attach_shader(program_id, vertex_shader_object);
3447        gl_context.attach_shader(program_id, fragment_shader_object);
3448        gl_context.link_program(program_id);
3449
3450        if let Some(error_id) = get_gl_program_error(&gl_context, program_id) {
3451            let info_log = gl_context.get_program_info_log(program_id);
3452            gl_context.delete_shader(vertex_shader_object);
3453            gl_context.delete_shader(fragment_shader_object);
3454            gl_context.delete_program(program_id);
3455            return Err(GlShaderCreateError::Link(GlShaderLinkError {
3456                error_id,
3457                info_log: info_log.into(),
3458            }));
3459        }
3460
3461        gl_context.delete_shader(vertex_shader_object);
3462        gl_context.delete_shader(fragment_shader_object);
3463
3464        Ok(GlShader {
3465            program_id,
3466            gl_context: gl_context.clone(),
3467        })
3468    }
3469
3470    /// Draws vertex buffers, index buffers + uniforms to the texture
3471    pub fn draw(
3472        // shader to use for drawing
3473        shader_program_id: GLuint,
3474        // note: texture is &mut so the texture is reusable -
3475        texture: &mut Texture,
3476        // buffers + uniforms to draw
3477        buffers: &[(&VertexBuffer, &[Uniform])],
3478    ) {
3479        use alloc::collections::btree_map::BTreeMap;
3480
3481        const INDEX_TYPE: GLuint = gl::UNSIGNED_INT;
3482
3483        let texture_size = texture.size;
3484
3485        let gl_context = &texture.gl_context;
3486
3487        // save the OpenGL state
3488        let mut current_multisample = [0_u8];
3489        let mut current_index_buffer = [0_i32];
3490        let mut current_vertex_buffer = [0_i32];
3491        let mut current_vertex_array_object = [0_i32];
3492        let mut current_program = [0_i32];
3493        let mut current_framebuffers = [0_i32];
3494        let mut current_renderbuffers = [0_i32];
3495        let mut current_texture_2d = [0_i32];
3496        let mut current_blend_enabled = [0_u8];
3497        let mut current_primitive_restart_fixed_index_enabled = [0_u8];
3498
3499        gl_context.get_boolean_v(gl::MULTISAMPLE, (&mut current_multisample[..]).into());
3500        gl_context.get_integer_v(
3501            gl::ARRAY_BUFFER_BINDING,
3502            (&mut current_vertex_buffer[..]).into(),
3503        );
3504        gl_context.get_integer_v(
3505            gl::ELEMENT_ARRAY_BUFFER_BINDING,
3506            (&mut current_index_buffer[..]).into(),
3507        );
3508        gl_context.get_integer_v(gl::CURRENT_PROGRAM, (&mut current_program[..]).into());
3509        gl_context.get_integer_v(
3510            gl::VERTEX_ARRAY_BINDING,
3511            (&mut current_vertex_array_object[..]).into(),
3512        );
3513        gl_context.get_integer_v(gl::RENDERBUFFER, (&mut current_renderbuffers[..]).into());
3514        gl_context.get_integer_v(gl::FRAMEBUFFER, (&mut current_framebuffers[..]).into());
3515        gl_context.get_integer_v(gl::TEXTURE_2D, (&mut current_texture_2d[..]).into());
3516        gl_context.get_boolean_v(gl::BLEND, (&mut current_blend_enabled[..]).into());
3517        gl_context.get_boolean_v(
3518            gl::PRIMITIVE_RESTART_FIXED_INDEX,
3519            (&mut current_primitive_restart_fixed_index_enabled[..]).into(),
3520        );
3521
3522        // 1. Create the framebuffer
3523        let framebuffers = gl_context.gen_framebuffers(1);
3524        let framebuffer_id = framebuffers.get(0).unwrap();
3525        gl_context.bind_framebuffer(gl::FRAMEBUFFER, *framebuffer_id);
3526
3527        let depthbuffers = gl_context.gen_renderbuffers(1);
3528        let depthbuffer_id = depthbuffers.get(0).unwrap();
3529
3530        gl_context.bind_texture(gl::TEXTURE_2D, texture.texture_id);
3531        gl_context.tex_image_2d(
3532            gl::TEXTURE_2D,
3533            0,
3534            gl::RGBA as i32, // NOT RGBA8 - will generate INVALID_ENUM!
3535            texture_size.width as i32,
3536            texture_size.height as i32,
3537            0,
3538            gl::RGBA, // gl::BRGA?
3539            gl::UNSIGNED_BYTE,
3540            None.into(),
3541        );
3542        gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32);
3543        gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
3544        gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
3545        gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
3546
3547        gl_context.bind_renderbuffer(gl::RENDERBUFFER, *depthbuffer_id);
3548        gl_context.renderbuffer_storage(
3549            gl::RENDERBUFFER,
3550            gl::DEPTH_COMPONENT,
3551            texture_size.width as i32,
3552            texture_size.height as i32,
3553        );
3554        gl_context.framebuffer_renderbuffer(
3555            gl::FRAMEBUFFER,
3556            gl::DEPTH_ATTACHMENT,
3557            gl::RENDERBUFFER,
3558            *depthbuffer_id,
3559        );
3560
3561        gl_context.framebuffer_texture_2d(
3562            gl::FRAMEBUFFER,
3563            gl::COLOR_ATTACHMENT0,
3564            gl::TEXTURE_2D,
3565            texture.texture_id,
3566            0,
3567        );
3568        gl_context.draw_buffers([gl::COLOR_ATTACHMENT0][..].into());
3569
3570        #[cfg(feature = "std")]
3571        {
3572            let fb_check = gl_context.check_frame_buffer_status(gl::FRAMEBUFFER);
3573            match fb_check {
3574                gl::FRAMEBUFFER_COMPLETE => {}
3575                gl::FRAMEBUFFER_UNDEFINED => {
3576                    println!("GL_FRAMEBUFFER_UNDEFINED");
3577                }
3578                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
3579                    println!("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
3580                }
3581                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
3582                    println!("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
3583                }
3584                gl::FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER => {
3585                    println!("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER");
3586                }
3587                gl::FRAMEBUFFER_INCOMPLETE_READ_BUFFER => {
3588                    println!("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER");
3589                }
3590                gl::FRAMEBUFFER_UNSUPPORTED => {
3591                    println!("GL_FRAMEBUFFER_UNSUPPORTED");
3592                }
3593                gl::FRAMEBUFFER_INCOMPLETE_MULTISAMPLE => {
3594                    println!("GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE");
3595                }
3596                gl::FRAMEBUFFER_INCOMPLETE_MULTISAMPLE => {
3597                    println!("GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE");
3598                }
3599                gl::FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS => {
3600                    println!("GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS");
3601                }
3602                o => {
3603                    println!("glFramebufferStatus returned unknown return code: {}", o);
3604                }
3605            }
3606        }
3607
3608        gl_context.viewport(0, 0, texture_size.width as i32, texture_size.height as i32);
3609        gl_context.enable(gl::BLEND);
3610        gl_context.enable(gl::PRIMITIVE_RESTART_FIXED_INDEX);
3611        gl_context.disable(gl::MULTISAMPLE);
3612        gl_context.blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); // TODO: enable / disable
3613        gl_context.use_program(shader_program_id);
3614
3615        // Avoid multiple calls to get_uniform_location by caching the uniform locations
3616        let mut uniform_locations: BTreeMap<AzString, i32> = BTreeMap::new();
3617        let mut max_uniform_len = 0;
3618        for (_, uniforms) in buffers {
3619            for uniform in uniforms.iter() {
3620                if !uniform_locations.contains_key(&uniform.name) {
3621                    uniform_locations.insert(
3622                        uniform.name.clone(),
3623                        gl_context
3624                            .get_uniform_location(shader_program_id, uniform.name.as_str().into()),
3625                    );
3626                }
3627            }
3628            max_uniform_len = max_uniform_len.max(uniforms.len());
3629        }
3630        let mut current_uniforms = vec![None; max_uniform_len];
3631
3632        // Since the description of the vertex buffers is always the same,
3633        // only the first layer needs to bind its VAO
3634
3635        // Draw the actual layers
3636        for (vertex_index_buffer, uniforms) in buffers {
3637            gl_context.bind_vertex_array(vertex_index_buffer.vao.vao_id);
3638            gl_context.bind_buffer(gl::ARRAY_BUFFER, vertex_index_buffer.vertex_buffer_id);
3639            gl_context.bind_buffer(
3640                gl::ELEMENT_ARRAY_BUFFER,
3641                vertex_index_buffer.index_buffer_id,
3642            );
3643
3644            // Only set the uniform if the value has changed
3645            for (uniform_index, uniform) in uniforms.iter().enumerate() {
3646                if current_uniforms[uniform_index] != Some(uniform.uniform_type) {
3647                    let uniform_location = uniform_locations[&uniform.name];
3648                    uniform.uniform_type.set(gl_context.get(), uniform_location);
3649                    current_uniforms[uniform_index] = Some(uniform.uniform_type);
3650                }
3651            }
3652
3653            gl_context.draw_elements(
3654                vertex_index_buffer.index_buffer_format.get_gl_id(),
3655                vertex_index_buffer.index_buffer_len as i32,
3656                INDEX_TYPE,
3657                0,
3658            );
3659        }
3660
3661        // Reset the OpenGL state
3662        if u32::from(current_multisample[0]) == gl::TRUE {
3663            gl_context.enable(gl::MULTISAMPLE);
3664        }
3665        if u32::from(current_blend_enabled[0]) == gl::FALSE {
3666            gl_context.disable(gl::BLEND);
3667        }
3668        if u32::from(current_primitive_restart_fixed_index_enabled[0]) == gl::FALSE {
3669            gl_context.disable(gl::PRIMITIVE_RESTART_FIXED_INDEX);
3670        }
3671        gl_context.bind_framebuffer(gl::FRAMEBUFFER, current_framebuffers[0] as u32);
3672        gl_context.bind_texture(gl::TEXTURE_2D, current_texture_2d[0] as u32);
3673        gl_context.bind_buffer(gl::RENDERBUFFER, current_renderbuffers[0] as u32);
3674        gl_context.bind_vertex_array(current_vertex_array_object[0] as u32);
3675        gl_context.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, current_index_buffer[0] as u32);
3676        gl_context.bind_buffer(gl::ARRAY_BUFFER, current_vertex_buffer[0] as u32);
3677        gl_context.use_program(current_program[0] as u32);
3678
3679        gl_context.delete_framebuffers((&[*framebuffer_id])[..].into());
3680        gl_context.delete_renderbuffers((&[*depthbuffer_id])[..].into());
3681
3682        texture.format = RawImageFormat::RGBA8;
3683        texture.flags = TextureFlags {
3684            is_opaque: false,
3685            is_video_texture: false,
3686        };
3687    }
3688}
3689
3690fn get_gl_shader_error(context: &GlContextPtr, shader_object: GLuint) -> Option<i32> {
3691    let mut err = [0];
3692    context.get_shader_iv(shader_object, gl::COMPILE_STATUS, (&mut err[..]).into());
3693    let err_code = err[0];
3694    if err_code == gl::TRUE as i32 {
3695        None
3696    } else {
3697        Some(err_code)
3698    }
3699}
3700
3701fn get_gl_program_error(context: &GlContextPtr, shader_object: GLuint) -> Option<i32> {
3702    let mut err = [0];
3703    context.get_program_iv(shader_object, gl::LINK_STATUS, (&mut err[..]).into());
3704    let err_code = err[0];
3705    if err_code == gl::TRUE as i32 {
3706        None
3707    } else {
3708        Some(err_code)
3709    }
3710}