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