Skip to main content

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