nc_renderer/gles3/
renderer.rs

1//
2// Copyright 2021-Present (c) Raja Lehtihet & Wael El Oraiby
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its contributors
15// may be used to endorse or promote products derived from this software without
16// specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30use rs_ctypes::*;
31use gl::types::*;
32use crate::*;
33use crate::rs_math3d::*;
34use super::readback::*;
35
36use std::collections::{VecDeque};
37use core::ops::{Index};
38use core::sync::atomic::*;
39
40fn color4b_to_color4f(col: Color4b) -> Vec4f {
41    let r = col.x as f32 / 255.0;
42    let g = col.y as f32 / 255.0;
43    let b = col.z as f32 / 255.0;
44    let a = col.w as f32 / 255.0;
45    Vec4f::new(r, g, b, a)
46}
47
48unsafe fn alloc_string<'a>(size: usize) -> &'a mut str {
49    let l = std::alloc::Layout::array::<u8>(size as usize).unwrap();
50    let sptr = std::alloc::alloc(l);
51    let sl = std::slice::from_raw_parts_mut(sptr, size as usize);
52    std::str::from_utf8_unchecked_mut(sl)
53}
54
55unsafe fn free_string<'a>(s: &mut str, size: usize) {
56    let l = std::alloc::Layout::array::<u8>(size as usize).unwrap();
57    std::alloc::dealloc(s.as_mut_ptr(), l);
58}
59
60pub struct GLProgram {
61    prog_id     : GLuint,
62}
63
64impl Drop for GLProgram {
65    fn drop(&mut self) {
66        unsafe { gl::DeleteProgram(self.prog_id) };
67    }
68}
69
70trait GLUniformBlock {
71    fn setup(&self);
72}
73
74trait GLVertexFormat {
75    fn gl_elem_count(&self) -> GLuint;
76    fn gl_elem_type(&self) -> GLenum;
77    fn gl_is_normalized(&self) -> GLboolean;
78}
79
80impl GLVertexFormat for VertexFormat {
81    fn gl_elem_count(&self) -> GLuint {
82        match self {
83            VertexFormat::Byte      => 1,
84            VertexFormat::Byte2     => 2,
85            VertexFormat::Byte3     => 3,
86            VertexFormat::Byte4     => 4,
87
88            VertexFormat::SByte     => 1,
89            VertexFormat::SByte2    => 2,
90            VertexFormat::SByte3    => 3,
91            VertexFormat::SByte4    => 4,
92
93            VertexFormat::Int       => 1,
94            VertexFormat::Int2      => 2,
95            VertexFormat::Int3      => 3,
96            VertexFormat::Int4      => 4,
97
98            VertexFormat::UInt      => 1,
99            VertexFormat::UInt2     => 2,
100            VertexFormat::UInt3     => 3,
101            VertexFormat::UInt4     => 4,
102
103            VertexFormat::Short     => 1,
104            VertexFormat::Short2    => 2,
105            VertexFormat::Short3    => 3,
106            VertexFormat::Short4    => 4,
107
108            VertexFormat::Float     => 1,
109            VertexFormat::Float2    => 2,
110            VertexFormat::Float3    => 3,
111            VertexFormat::Float4    => 4,
112
113            VertexFormat::Float2x2  => 4,
114            VertexFormat::Float3x3  => 9,
115            VertexFormat::Float4x4  => 16,
116        }
117    }
118
119    fn gl_elem_type(&self) -> GLenum {
120        match self {
121            VertexFormat::Byte      => gl::UNSIGNED_BYTE,
122            VertexFormat::Byte2     => gl::UNSIGNED_BYTE,
123            VertexFormat::Byte3     => gl::UNSIGNED_BYTE,
124            VertexFormat::Byte4     => gl::UNSIGNED_BYTE,
125
126            VertexFormat::SByte     => gl::BYTE,
127            VertexFormat::SByte2    => gl::BYTE,
128            VertexFormat::SByte3    => gl::BYTE,
129            VertexFormat::SByte4    => gl::BYTE,
130
131            VertexFormat::Int       => gl::INT,
132            VertexFormat::Int2      => gl::INT,
133            VertexFormat::Int3      => gl::INT,
134            VertexFormat::Int4      => gl::INT,
135
136            VertexFormat::UInt      => gl::UNSIGNED_INT,
137            VertexFormat::UInt2     => gl::UNSIGNED_INT,
138            VertexFormat::UInt3     => gl::UNSIGNED_INT,
139            VertexFormat::UInt4     => gl::UNSIGNED_INT,
140
141            VertexFormat::Short     => gl::SHORT,
142            VertexFormat::Short2    => gl::SHORT,
143            VertexFormat::Short3    => gl::SHORT,
144            VertexFormat::Short4    => gl::SHORT,
145
146            VertexFormat::Float     => gl::FLOAT,
147            VertexFormat::Float2    => gl::FLOAT,
148            VertexFormat::Float3    => gl::FLOAT,
149            VertexFormat::Float4    => gl::FLOAT,
150
151            VertexFormat::Float2x2  => gl::FLOAT,
152            VertexFormat::Float3x3  => gl::FLOAT,
153            VertexFormat::Float4x4  => gl::FLOAT,
154        }
155    }
156
157    fn gl_is_normalized(&self) -> GLboolean {
158        let r = match self {
159            VertexFormat::Byte      => true,
160            VertexFormat::Byte2     => true,
161            VertexFormat::Byte3     => true,
162            VertexFormat::Byte4     => true,
163
164            VertexFormat::SByte     => true,
165            VertexFormat::SByte2    => true,
166            VertexFormat::SByte3    => true,
167            VertexFormat::SByte4    => true,
168
169            VertexFormat::Int       => false,
170            VertexFormat::Int2      => false,
171            VertexFormat::Int3      => false,
172            VertexFormat::Int4      => false,
173
174            VertexFormat::UInt      => false,
175            VertexFormat::UInt2     => false,
176            VertexFormat::UInt3     => false,
177            VertexFormat::UInt4     => false,
178
179            VertexFormat::Short     => false,
180            VertexFormat::Short2    => false,
181            VertexFormat::Short3    => false,
182            VertexFormat::Short4    => false,
183
184            VertexFormat::Float     => false,
185            VertexFormat::Float2    => false,
186            VertexFormat::Float3    => false,
187            VertexFormat::Float4    => false,
188
189            VertexFormat::Float2x2  => false,
190            VertexFormat::Float3x3  => false,
191            VertexFormat::Float4x4  => false,
192        };
193        r as GLboolean
194    }
195}
196
197fn uniform_ptr_to_slice<'a, T>(ptr: *const c_void, offset: usize, count: usize) -> &'a [T] {
198    let cptr = ptr as *const u8;
199    let _cptr = unsafe { cptr.offset(offset as isize) };
200    let tptr = _cptr as *const T;
201    unsafe { core::slice::from_raw_parts(tptr, count) }
202}
203
204fn setup_uniforms(uniforms: *const c_void, data_desc_layout: &[UniformDataDesc], prg_desc_layout: &[(String, GLuint)]) {
205    unsafe {
206        for i in 0..data_desc_layout.len() {
207            let offset = data_desc_layout[i].offset();
208            let location = prg_desc_layout[i].1 as GLint;
209            match &data_desc_layout[i].desc().format() {
210                UniformDataType::UInt => { let s : &[u32]     = uniform_ptr_to_slice(uniforms, offset, 1);  gl::Uniform1uiv(location, 1, s.as_ptr()); },
211                UniformDataType::UInt2=> { let s : &[u32]     = uniform_ptr_to_slice(uniforms, offset, 2);  gl::Uniform2uiv(location, 1, s.as_ptr()); },
212                UniformDataType::UInt3=> { let s : &[u32]     = uniform_ptr_to_slice(uniforms, offset, 3);  gl::Uniform3uiv(location, 1, s.as_ptr()); },
213                UniformDataType::UInt4=> { let s : &[u32]     = uniform_ptr_to_slice(uniforms, offset, 4);  gl::Uniform4uiv(location, 1, s.as_ptr()); },
214                UniformDataType::Int  => { let s : &[i32]     = uniform_ptr_to_slice(uniforms, offset, 1);  gl::Uniform1iv(location, 1, s.as_ptr()); },
215                UniformDataType::Int2 => { let s : &[i32]     = uniform_ptr_to_slice(uniforms, offset, 2);  gl::Uniform2iv(location, 1, s.as_ptr()); },
216                UniformDataType::Int3 => { let s : &[i32]     = uniform_ptr_to_slice(uniforms, offset, 3);  gl::Uniform3iv(location, 1, s.as_ptr()); },
217                UniformDataType::Int4 => { let s : &[i32]     = uniform_ptr_to_slice(uniforms, offset, 4);  gl::Uniform4iv(location, 1, s.as_ptr()); },
218                UniformDataType::Float  => { let s : &[f32]   = uniform_ptr_to_slice(uniforms, offset, 1);  gl::Uniform1fv(location, 1, s.as_ptr()); },
219                UniformDataType::Float2 => { let s : &[f32]   = uniform_ptr_to_slice(uniforms, offset, 2);  gl::Uniform2fv(location, 1, s.as_ptr()); },
220                UniformDataType::Float3 => { let s : &[f32]   = uniform_ptr_to_slice(uniforms, offset, 3);  gl::Uniform3fv(location, 1, s.as_ptr()); },
221                UniformDataType::Float4 => { let s : &[f32]   = uniform_ptr_to_slice(uniforms, offset, 4);  gl::Uniform4fv(location, 1, s.as_ptr()); },
222                UniformDataType::Float2x2 => { let s : &[f32] = uniform_ptr_to_slice(uniforms, offset, 4);  gl::UniformMatrix2fv(location, 1, false as GLboolean, s.as_ptr()); },
223                UniformDataType::Float3x3 => { let s : &[f32] = uniform_ptr_to_slice(uniforms, offset, 9);  gl::UniformMatrix3fv(location, 1, false as GLboolean, s.as_ptr()); },
224                UniformDataType::Float4x4 => { let s : &[f32] = uniform_ptr_to_slice(uniforms, offset, 16); gl::UniformMatrix4fv(location, 1, false as GLboolean, s.as_ptr()); },
225            }
226        }
227    }
228}
229
230struct GLDeviceBuffer {
231    gl_id           : GLuint,
232    desc            : DeviceBufferDesc,
233}
234
235impl Drop for GLDeviceBuffer {
236    fn drop(&mut self) {
237        unsafe { gl::DeleteBuffers(1, &self.gl_id as *const GLuint) };
238    }
239}
240
241struct GLTexture {
242    gl_id   : GLuint,
243}
244
245impl Drop for GLTexture {
246    fn drop(&mut self) {
247        unsafe {
248            gl::DeleteTextures(1, &self.gl_id as *const GLuint);
249        }
250    }
251}
252
253struct GLRenderTarget {
254    gl_id   : GLuint,
255}
256
257impl Drop for GLRenderTarget {
258    fn drop(&mut self) {
259        unsafe {
260            gl::DeleteRenderbuffers(1, &self.gl_id as *const GLuint);
261        }
262    }
263}
264
265trait GLPixelFormat {
266    fn gl_internal_format(&self) -> GLuint;
267    fn gl_format(&self) -> GLuint;
268    fn gl_elem_type(&self) -> GLenum;
269    fn gl_pixel_size(&self) -> usize;
270}
271
272impl GLPixelFormat for PixelFormat {
273    fn gl_internal_format(&self) -> GLenum {
274        match self {
275            PixelFormat::RGB8U  => gl::RGB8UI,
276            PixelFormat::RGBA8U => gl::RGBA8UI,
277            PixelFormat::R8U    => gl::R8UI,
278            PixelFormat::RGB32U => gl::RGB32UI,
279            PixelFormat::RGBA32U=> gl::RGBA32UI,
280            PixelFormat::R32U   => gl::R32UI,
281
282            PixelFormat::RGB32F => gl::RGB32F,
283            PixelFormat::RGBA32F=> gl::RGBA32F,
284            PixelFormat::R32F   => gl::R32F,
285
286            PixelFormat::D16    => gl::DEPTH_COMPONENT16,
287            PixelFormat::D32    => gl::DEPTH_COMPONENT32F,
288            PixelFormat::D24S8  => gl::DEPTH24_STENCIL8,
289            PixelFormat::D32S8  => gl::DEPTH32F_STENCIL8,
290
291            PixelFormat::RGB8(_)    => gl::RGB,
292            PixelFormat::RGBA8(_)   => gl::RGBA,
293            PixelFormat::R8(_)      => gl::RED,
294        }
295    }
296
297    fn gl_format(&self) -> GLenum {
298        match self {
299            PixelFormat::RGB8U  => gl::RGB_INTEGER,
300            PixelFormat::RGBA8U => gl::RGBA_INTEGER,
301            PixelFormat::R8U    => gl::RED_INTEGER,
302            PixelFormat::RGB32U => gl::RGB_INTEGER,
303            PixelFormat::RGBA32U=> gl::RGBA_INTEGER,
304            PixelFormat::R32U   => gl::RED_INTEGER,
305
306            PixelFormat::RGB32F => gl::RGB,
307            PixelFormat::RGBA32F=> gl::RGBA,
308            PixelFormat::R32F   => gl::RED,
309
310            PixelFormat::D16    => gl::DEPTH_COMPONENT,
311            PixelFormat::D32    => gl::DEPTH_COMPONENT,
312            PixelFormat::D24S8  => gl::DEPTH_STENCIL,
313            PixelFormat::D32S8  => gl::DEPTH_STENCIL,
314
315            PixelFormat::RGB8(_)    => gl::RGB,
316            PixelFormat::RGBA8(_)   => gl::RGBA,
317            PixelFormat::R8(_)      => gl::RED,
318        }
319    }
320
321    fn gl_elem_type(&self) -> GLenum {
322        match &self {
323            PixelFormat::RGB8U  => gl::UNSIGNED_BYTE,
324            PixelFormat::RGBA8U => gl::UNSIGNED_BYTE,
325            PixelFormat::R8U    => gl::UNSIGNED_BYTE,
326            PixelFormat::RGB32U => gl::UNSIGNED_INT,
327            PixelFormat::RGBA32U=> gl::UNSIGNED_INT,
328            PixelFormat::R32U   => gl::UNSIGNED_INT,
329
330            PixelFormat::RGB32F => gl::FLOAT,
331            PixelFormat::RGBA32F=> gl::FLOAT,
332            PixelFormat::R32F   => gl::FLOAT,
333
334            PixelFormat::D16    => gl::UNSIGNED_SHORT,
335            PixelFormat::D32    => gl::FLOAT,
336            PixelFormat::D24S8  => gl::UNSIGNED_INT_24_8,
337            PixelFormat::D32S8  => gl::FLOAT_32_UNSIGNED_INT_24_8_REV,
338
339            PixelFormat::RGB8(_)    => gl::UNSIGNED_BYTE,
340            PixelFormat::RGBA8(_)   => gl::UNSIGNED_BYTE,
341            PixelFormat::R8(_)      => gl::UNSIGNED_BYTE,
342        }
343    }
344
345    fn gl_pixel_size(&self) -> usize {
346        match &self {
347            PixelFormat::RGB8U  => 3,
348            PixelFormat::RGBA8U => 4,
349            PixelFormat::R8U    => 1,
350            PixelFormat::RGB32U => 3 * 4,
351            PixelFormat::RGBA32U=> 4 * 4,
352            PixelFormat::R32U   => 4,
353
354            PixelFormat::RGB32F => 3 * 4,
355            PixelFormat::RGBA32F=> 4 * 4,
356            PixelFormat::R32F   => 4,
357
358            PixelFormat::D16    => 2,
359            PixelFormat::D32    => 4,
360            PixelFormat::D24S8  => 4,
361            PixelFormat::D32S8  => 5,
362
363            PixelFormat::RGB8(_)    => 3,
364            PixelFormat::RGBA8(_)   => 4,
365            PixelFormat::R8(_)      => 1,
366        }
367    }
368}
369
370struct GLShader {
371    gl_id               : GLuint,
372
373    vertex_attributes   : Vec<Vec<(String, GLuint)>>,
374
375    vertex_uniforms     : Vec<(String, GLuint)>,
376    vertex_surfaces     : Vec<(String, GLuint)>,
377
378    pixel_uniforms      : Vec<(String, GLuint)>,
379    pixel_surfaces      : Vec<(String, GLuint)>,
380}
381
382impl Drop for GLShader {
383    fn drop(&mut self) {
384        unsafe { gl::DeleteProgram(self.gl_id) }
385    }
386}
387
388struct GLPipeline {
389    desc                : PipelineDesc,
390}
391
392struct GLFrameBuffer {
393    gl_id               : GLuint,
394    desc                : FrameBufferDesc,
395}
396
397impl Drop for GLFrameBuffer {
398    fn drop(&mut self) {
399        unsafe {
400            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint)
401        }
402    }
403}
404
405trait GLBlendFactor {
406    fn gl_blend_factor(&self) -> GLenum;
407}
408
409impl GLBlendFactor for BlendFactor {
410    fn gl_blend_factor(&self) -> GLenum {
411        match self {
412            BlendFactor::Zero               => gl::ZERO,
413            BlendFactor::One                => gl::ONE,
414            BlendFactor::SrcColor           => gl::SRC_COLOR,
415            BlendFactor::OneMinusSrcColor   => gl::ONE_MINUS_SRC_COLOR,
416            BlendFactor::SrcAlpha           => gl::SRC_ALPHA,
417            BlendFactor::OneMinusSrcAlpha   => gl::ONE_MINUS_SRC_ALPHA,
418            BlendFactor::DstColor           => gl::DST_COLOR,
419            BlendFactor::OneMinusDstColor   => gl::ONE_MINUS_DST_COLOR,
420            BlendFactor::DstAlpha           => gl::DST_ALPHA,
421            BlendFactor::OneMinusDstAlpha   => gl::ONE_MINUS_DST_ALPHA,
422            BlendFactor::SrcAlphaSaturate   => gl::SRC_ALPHA_SATURATE,
423            BlendFactor::ConstantColor         => gl::CONSTANT_COLOR,
424            BlendFactor::OneMinusConstantColor => gl::ONE_MINUS_CONSTANT_COLOR,
425            BlendFactor::ConstantAlpha         => gl::CONSTANT_ALPHA,
426            BlendFactor::OneMinusConstantAlpha => gl::ONE_MINUS_CONSTANT_ALPHA,
427        }
428    }
429}
430////////////////////////////////////////////////////////////////////////////////
431/// Resource Container
432////////////////////////////////////////////////////////////////////////////////
433
434struct ResourceContainer<T> {
435    res             : Vec<Option<T>>,
436    free_res        : VecDeque<usize>,
437}
438
439impl<T> ResourceContainer<T> {
440    fn new() -> Self { Self { res: Vec::new(), free_res: VecDeque::new() } }
441
442    fn add(&mut self, t: T) -> usize {
443        match self.free_res.len() {
444            0 => {
445                let idx = self.res.len();
446                self.res.push(Some(t));
447                idx
448            },
449            _ => {
450                let idx = self.free_res.pop_front().unwrap();
451                self.res[idx] = Some(t);
452                idx
453            }
454        }
455    }
456
457    fn remove(&mut self, idx: usize) {
458        match self.res[idx].as_ref() {
459            Some(_) => {
460                self.res[idx] = None;
461                self.free_res.push_back(idx);
462            },
463            None => panic!("Deleting an already deleted object")
464        }
465    }
466}
467
468impl<T> Index<usize> for ResourceContainer<T> {
469    type Output = T;
470
471    fn index(&self, idx: usize) -> &Self::Output {
472        match &self.res[idx] {
473            Some(t) => &t,
474            None => panic!("Accessing invalid object index")
475        }
476    }
477}
478
479pub struct NullPayload {
480    size            : usize,
481}
482
483impl Payload for NullPayload {
484    fn size(&self) -> usize { self.size }
485    fn ptr(&self) -> *const u8 { ::core::ptr::null() }
486}
487
488impl Drop for NullPayload {
489    fn drop(&mut self) {}
490}
491
492
493////////////////////////////////////////////////////////////////////////////////
494/// Driver
495////////////////////////////////////////////////////////////////////////////////
496pub struct Gles3Driver {
497    device_buffers  : ResourceContainer<GLDeviceBuffer>,
498    textures        : ResourceContainer<GLTexture>,
499    render_targets  : ResourceContainer<GLRenderTarget>,
500    shaders         : ResourceContainer<GLShader>,
501    pipelines       : ResourceContainer<GLPipeline>,
502    framebuffers    : ResourceContainer<GLFrameBuffer>,
503
504    read_back_state : Option<ReadbackState>,
505
506    rc              : AtomicIsize,
507
508    caps            : DriverCaps,
509}
510
511impl Gles3Driver {
512    fn new() -> Self {
513        let mut max_rt_size    = 0;
514        let mut max_tex_size   = 0;
515
516        unsafe {
517            gl::GetIntegerv(gl::MAX_RENDERBUFFER_SIZE, &mut max_rt_size as *mut GLint);
518            gl::GetIntegerv(gl::MAX_TEXTURE_SIZE, &mut max_tex_size as *mut GLint);
519        }
520
521        let min_surface_size    = std::cmp::min(4096, std::cmp::min(max_rt_size, max_tex_size));
522        Self {
523            device_buffers  : ResourceContainer::new(),
524            textures        : ResourceContainer::new(),
525            render_targets  : ResourceContainer::new(),
526            shaders         : ResourceContainer::new(),
527            pipelines       : ResourceContainer::new(),
528            framebuffers    : ResourceContainer::new(),
529            rc              : AtomicIsize::new(0),
530
531            read_back_state : None,
532
533            caps            : DriverCaps {
534                max_2d_surface_dimension    : Dimensioni::new(min_surface_size, min_surface_size),
535            }
536        }
537    }
538
539    pub fn get_framebuffer_gl_id(&self, fb_id: usize) -> GLuint {
540        self.framebuffers[fb_id].gl_id
541    }
542
543    fn initialize(mut self) -> DriverPtr {
544        self.read_back_state    = Some(ReadbackState::new(&mut self));
545        unsafe {
546            gl::Enable(gl::SCISSOR_TEST);
547            gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
548            IntrusivePtr::from_raw_no_increment(IntrusivePtr::new(self).into_raw_mut() as *mut dyn Driver)
549        }
550    }
551
552    fn buffer_type_to_gl(bt: &DeviceBufferDesc) -> GLenum {
553        match bt {
554            DeviceBufferDesc::Vertex(_)  => gl::ARRAY_BUFFER,
555            DeviceBufferDesc::Index(_)   => gl::ELEMENT_ARRAY_BUFFER,
556            DeviceBufferDesc::Pixel(_)   => gl::PIXEL_UNPACK_BUFFER,
557        }
558    }
559
560    fn buffer_usage_to_gl(bt: &DeviceBufferDesc) -> GLenum {
561        let usage =
562            match bt {
563                DeviceBufferDesc::Vertex(u) |
564                DeviceBufferDesc::Index(u)  |
565                DeviceBufferDesc::Pixel(u)  => u,
566            };
567
568        match usage {
569            Usage::Static(_)    => gl::STATIC_DRAW,
570            Usage::Streamed(_)  => gl::STREAM_DRAW,
571            Usage::Dynamic(_)   => gl::DYNAMIC_DRAW,
572        }
573    }
574
575    fn buffer_data(bt: &DeviceBufferDesc) -> Option<*const u8> {
576        let usage =
577            match bt {
578                DeviceBufferDesc::Vertex(u) |
579                DeviceBufferDesc::Index(u)  |
580                DeviceBufferDesc::Pixel(u)  => u,
581            };
582
583        match usage {
584            Usage::Static(b)    => Some(b.ptr()),
585            Usage::Streamed(_)  => None,
586            Usage::Dynamic(_)   => None,
587        }
588    }
589
590    fn erase_buffer_data(bt: &DeviceBufferDesc) -> DeviceBufferDesc {
591        let usage =
592            match bt {
593                DeviceBufferDesc::Vertex(u) |
594                DeviceBufferDesc::Index(u)  |
595                DeviceBufferDesc::Pixel(u)  => u,
596            };
597
598        let usage =
599            match usage {
600                Usage::Static(p)    => Usage::Static(Box::new(NullPayload{ size: p.size() })),
601                Usage::Streamed(s)  => Usage::Streamed(*s),
602                Usage::Dynamic (s)  => Usage::Dynamic(*s),
603            };
604
605        match bt {
606            DeviceBufferDesc::Vertex(_)  => DeviceBufferDesc::Vertex(usage),
607            DeviceBufferDesc::Index(_)   => DeviceBufferDesc::Index(usage),
608            DeviceBufferDesc::Pixel(_)   => DeviceBufferDesc::Pixel(usage),
609        }
610    }
611
612    fn erase_texture_data(desc: &TextureDesc) -> TextureDesc {
613        TextureDesc {
614            sampler_desc: desc.sampler_desc.clone(),
615            payload     : None,
616        }
617    }
618
619    fn upload_texture(res: GLuint, desc: &SamplerDesc, data: &Option<Box<dyn Payload>>) {
620        unsafe {
621            match &desc.image_type {
622                SamplerType::Sampler2D(pch_x, pch_y) => {
623                    gl::BindTexture(gl::TEXTURE_2D, res);
624                    gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
625                    gl::PixelStorei(gl::PACK_ALIGNMENT, 1);
626
627                    // TODO: if one day, we need to have device buffer, bind it here
628                    //gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, 0);
629
630                    let ptr = match data {
631                        Some(b) => b.ptr() as *const c_void,
632                        None => ::core::ptr::null()
633                    };
634
635                    gl::TexImage2D(gl::TEXTURE_2D,
636                        0,
637                        desc.pixel_format.gl_internal_format() as GLint,
638                        pch_x.size as GLsizei,
639                        pch_y.size as GLsizei,
640                        0,
641                        desc.pixel_format.gl_format(),
642                        desc.pixel_format.gl_elem_type(),
643                        ptr
644                    );
645
646                    Self::check_gl_error();
647
648                    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, Self::gl_wrap(&pch_x.wrap) as GLint);
649                    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, Self::gl_wrap(&pch_y.wrap) as GLint);
650                    match &desc.pixel_format {
651                        PixelFormat::R8(min_mag) | PixelFormat::RGB8(min_mag) | PixelFormat::RGBA8(min_mag) => {
652                            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, Self::gl_filter(&min_mag.min_filter) as GLint);
653                            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, Self::gl_filter(&min_mag.mag_filter) as GLint);
654                        },
655                        _ => {
656                            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
657                            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
658                        }
659                    }
660                }
661            }
662        }
663    }
664    fn create_texture(desc: &SamplerDesc, data: &Option<Box<dyn Payload>>) -> GLuint {
665        unsafe {
666
667            let mut res : GLuint = 0;
668            gl::GenTextures(1, &mut res);
669            Self::upload_texture(res, desc, data);
670            res
671        }
672    }
673
674    fn create_render_target(desc: &SamplerDesc, _sample_size: usize) -> GLuint {
675        unsafe {
676            let mut res : GLuint = 0;
677            gl::GenRenderbuffers(1, &mut res);
678            match &desc.image_type {
679                SamplerType::Sampler2D(pch_x, pch_y) => {
680                    gl::BindRenderbuffer(gl::RENDERBUFFER, res);
681                    gl::RenderbufferStorage(gl::RENDERBUFFER,
682                        desc.pixel_format.gl_internal_format(),
683                        pch_x.size as GLsizei,
684                        pch_y.size as GLsizei
685                    );
686                    if gl::GetError() != gl::NO_ERROR {
687                        panic!("Error creating render target");
688                    }
689                }
690            }
691            res
692        }
693    }
694
695    fn gl_wrap(wm: &WrapMode) -> GLenum {
696        match wm {
697            WrapMode::Repeat => gl::REPEAT,
698            WrapMode::ClampToEdge => gl::CLAMP_TO_EDGE,
699            WrapMode::ClampToBorder => panic!("unsupported wrap mode!"),
700            WrapMode::MirroredRepeat => gl::MIRRORED_REPEAT,
701        }
702    }
703
704    fn gl_filter(filter: &Filter) -> GLenum {
705        match filter {
706            Filter::Nearest => gl::NEAREST,
707            Filter::Linear => gl::LINEAR,
708            Filter::NearestMipmapNearest => gl::NEAREST_MIPMAP_NEAREST,
709            Filter::NearestMipmapLinear => gl::NEAREST_MIPMAP_LINEAR,
710            Filter::LinearMipmapNearest => gl::LINEAR_MIPMAP_NEAREST,
711            Filter::LinearMipmapLinear => gl::LINEAR_MIPMAP_LINEAR,
712        }
713    }
714
715    fn load_shader(src: &str, ty: GLenum) -> Option<GLuint> {
716        unsafe {
717            let shader = gl::CreateShader(ty);
718            if shader == 0 {
719                return None
720            }
721
722            let c_str = std::ffi::CString::new(src.as_bytes()).unwrap();
723            gl::ShaderSource(shader, 1, &(c_str.as_ptr() as *const i8), core::ptr::null());
724            gl::CompileShader(shader);
725
726            let mut compiled = 0;
727            gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut compiled);
728
729            let mut info_len = 0;
730            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut info_len);
731            if info_len > 1 {
732                let s = alloc_string(info_len as usize);
733                gl::GetShaderInfoLog(shader, info_len as GLsizei, core::ptr::null_mut(), s.as_ptr() as *mut GLchar);
734                let sht =
735                    match ty {
736                        gl::VERTEX_SHADER => "vertex shader",
737                        gl::FRAGMENT_SHADER => "fragment shader",
738                        _ => panic!("invalid shader type")
739                    };
740
741                println!("[{}] Compilation Log: {}", sht, s);
742                free_string(s, info_len as usize);
743            }
744
745            if compiled == 0 {
746                gl::DeleteShader(shader);
747                return None
748            }
749            Some(shader)
750        }
751    }
752
753    fn delete_device_buffer(&mut self, buff: usize) {
754        self.device_buffers.remove(buff)
755    }
756
757    fn delete_texture(&mut self, surf: usize) {
758        self.textures.remove(surf)
759    }
760
761    fn delete_render_target(&mut self, surf: usize) {
762        self.render_targets.remove(surf)
763    }
764
765    fn delete_shader(&mut self, shader: usize) {
766        self.shaders.remove(shader)
767    }
768
769    fn delete_pipeline(&mut self, pipe: usize) {
770        self.pipelines.remove(pipe)
771    }
772
773    fn delete_frame_buffer(&mut self, pass: usize) {
774        self.framebuffers.remove(pass)
775    }
776
777    pub fn check_gl_error() {
778        unsafe {
779            let error = gl::GetError();
780            if error != gl::NO_ERROR {
781                panic!("Error : {:#X}", error);
782            }
783        }
784    }
785
786    fn read_back_state(&mut self) -> &ReadbackState {
787        match &self.read_back_state {
788            Some(rb) => &rb,
789            _ => panic!("readback is None")
790        }
791    }
792}
793
794
795impl Driver for Gles3Driver {
796    fn get_caps(&self) -> &DriverCaps { &self.caps }
797
798    fn create_device_buffer(&mut self, desc: DeviceBufferDesc) -> Option<DeviceBufferPtr> {
799        unsafe {
800            let data = Self::buffer_data(&desc);
801            let mut buff = 0;
802            gl::GenBuffers(1, &mut buff);
803            gl::BindBuffer(Self::buffer_type_to_gl(&desc), buff);
804            let buff_data =
805                match data {
806                    Some(d) => d,
807                    None    => std::ptr::null(),
808                };
809
810            gl::BufferData(Self::buffer_type_to_gl(&desc), desc.size() as GLsizeiptr, buff_data as *const rs_ctypes::c_void, Self::buffer_usage_to_gl(&desc));
811
812            let gl_buff = GLDeviceBuffer { gl_id: buff, desc: Self::erase_buffer_data(&desc) };
813            let idx = self.device_buffers.add(gl_buff);
814
815            let iptr : IntrusivePtr<dyn Driver>= IntrusivePtr::from_raw_increment(self as *mut Self as *mut dyn Driver);
816
817            Some(DeviceBufferPtr::new(DeviceBuffer::new(ResourceType::DeviceBuffer, idx, desc, Some(iptr))))
818        }
819    }
820
821    fn create_texture(&mut self, desc: TextureDesc) -> Option<TexturePtr> {
822        let new_desc = Self::erase_texture_data(&desc);
823        let idx = Self::create_texture(&desc.sampler_desc, &desc.payload);
824        let img = GLTexture { gl_id: idx };
825        let idx = self.textures.add(img);
826
827        let iptr : IntrusivePtr<dyn Driver>= unsafe { IntrusivePtr::from_raw_increment(self as *mut Self as *mut dyn Driver) };
828
829        Some(TexturePtr::new(Texture::new(ResourceType::Texture, idx, new_desc, Some(iptr))))
830    }
831
832    fn create_render_target(&mut self, desc: RenderTargetDesc) -> Option<RenderTargetPtr> {
833        let idx = Self::create_render_target(&desc.sampler_desc, desc.sample_count);
834        let img = GLRenderTarget { gl_id: idx };
835        let idx = self.render_targets.add(img);
836
837        let iptr : IntrusivePtr<dyn Driver>= unsafe { IntrusivePtr::from_raw_increment(self as *mut Self as *mut dyn Driver) };
838
839        Some(RenderTargetPtr::new(RenderTarget::new(ResourceType::RenderTarget, idx, desc, Some(iptr))))
840    }
841
842    fn create_shader(&mut self, desc: ShaderDesc) -> Option<ShaderPtr> {
843        let desc_copy2 = desc.clone();
844        unsafe {
845            let program_object = gl::CreateProgram();
846            if program_object == 0 {
847                return None
848            }
849
850            let vertex_shader    = Self::load_shader(desc.vertex_shader.as_str(), gl::VERTEX_SHADER);
851            let fragment_shader  = Self::load_shader(desc.pixel_shader.as_str(), gl::FRAGMENT_SHADER);
852
853            match (vertex_shader, fragment_shader) {
854                (None, None) => (),
855                (None, Some(f)) => gl::DeleteShader(f),
856                (Some(v), None) => gl::DeleteShader(v),
857                (Some(v), Some(f)) => {
858                    gl::AttachShader(program_object, v);
859                    gl::AttachShader(program_object, f);
860                    gl::LinkProgram(program_object);
861
862                    let mut linked = 0;
863                    gl::GetProgramiv(program_object, gl::LINK_STATUS, &mut linked);
864                    let mut info_len = 0;
865                    gl::GetProgramiv(program_object, gl::INFO_LOG_LENGTH, &mut info_len);
866                    if info_len > 1 {
867                        let s = alloc_string(info_len as usize);
868                        gl::GetProgramInfoLog(program_object, info_len as GLsizei, core::ptr::null_mut(), s.as_ptr() as *mut GLchar);
869                        println!("Shader Linking: {}", s);
870                        free_string(s, info_len as usize);
871                    }
872
873
874                    // done with the shaders
875                    gl::DetachShader(program_object, v);
876                    gl::DetachShader(program_object, f);
877
878                    gl::DeleteShader(f);
879                    gl::DeleteShader(v);
880
881                    if linked == 0 {
882                        gl::DeleteProgram(program_object);
883                        return None
884                    }
885                }
886            }
887
888            let mut vertex_attributes = Vec::new();
889
890            for l in desc.vertex_attributes {
891                let mut vas = Vec::new();
892                for a in l {
893                    let mut s = a.clone();
894                    s.push('\0');
895
896                    let au = gl::GetAttribLocation(program_object, s.as_bytes().as_ptr() as *const GLchar);
897                    if au < 0 {
898                        println!("attribute {} not found in shader", s);
899                        return None // will leak shaders!
900                    }
901                    vas.push((s, au as GLuint));
902                }
903                vertex_attributes.push(vas);
904            }
905
906            let mut vertex_uniforms = Vec::new();
907
908            for u in desc.vertex_uniforms {
909                let mut s = u.clone();
910                s.push('\0');
911
912                let au = gl::GetUniformLocation(program_object, s.as_bytes().as_ptr() as *const GLchar);
913                if au < 0 {
914                    println!("uniform {} not found in shader", s);
915                    return None // will leak shaders!
916                }
917                vertex_uniforms.push((s, au as GLuint));
918            }
919
920            let mut vertex_surfaces = Vec::new();
921
922            for u in desc.vertex_surfaces {
923                let mut s = u.clone();
924                s.push('\0');
925
926                let au = gl::GetUniformLocation(program_object, s.as_bytes().as_ptr() as *const GLchar);
927                if au < 0 {
928                    println!("vertex texture {} not found in shader", s);
929                    return None // will leak shaders!
930                }
931                // TODO: use glGetActiveUniform to get sampler type
932                vertex_surfaces.push((s, au as GLuint));
933            }
934
935            let mut pixel_uniforms = Vec::new();
936
937            for u in desc.pixel_uniforms {
938                let mut s = u.clone();
939                s.push('\0');
940
941                let au = gl::GetUniformLocation(program_object, s.as_bytes().as_ptr() as *const GLchar);
942                if au < 0 {
943                    println!("uniform {} not found in shader", s);
944                    return None // will leak shaders!
945                }
946                pixel_uniforms.push((s, au as GLuint));
947            }
948
949            let mut pixel_surfaces = Vec::new();
950
951            for u in desc.pixel_surfaces {
952                let mut s = u.clone();
953                s.push('\0');
954
955                let au = gl::GetUniformLocation(program_object, s.as_bytes().as_ptr() as *const GLchar);
956                if au < 0 {
957                    println!("pixel texture {} not found in shader", s);
958                    return None // will leak shaders!
959                }
960                // TODO: use glGetActiveUniform to get sampler type
961                pixel_surfaces.push((s, au as GLuint));
962            }
963
964            let gl_shader =
965                GLShader {
966                    gl_id               : program_object,
967
968                    vertex_attributes   : vertex_attributes,
969
970                    vertex_uniforms     : vertex_uniforms,
971                    vertex_surfaces     : vertex_surfaces,
972
973                    pixel_uniforms      : pixel_uniforms,
974                    pixel_surfaces      : pixel_surfaces,
975                };
976
977            let idx = self.shaders.add(gl_shader);
978
979            let iptr : IntrusivePtr<dyn Driver>= IntrusivePtr::from_raw_increment(self as *mut Self as *mut dyn Driver);
980
981            Some(ShaderPtr::new(Shader::new(ResourceType::Shader, idx, desc_copy2, Some(iptr))))
982        }
983    }
984
985    fn create_pipeline(&mut self, desc: PipelineDesc) -> Option<PipelinePtr> {
986        let idx = self.pipelines.add(GLPipeline { desc: desc.clone() });
987
988        let iptr : IntrusivePtr<dyn Driver>= unsafe { IntrusivePtr::from_raw_increment(self as *mut Self as *mut dyn Driver) };
989
990        Some(PipelinePtr::new(Pipeline::new(ResourceType::Pipeline, idx, desc, Some(iptr))))
991    }
992
993    fn create_frame_buffer(&mut self, desc: FrameBufferDesc) -> Option<FrameBufferPtr> {
994        unsafe {
995            let mut res : GLuint = 0;
996            gl::GenFramebuffers(1, &mut res);
997            gl::BindFramebuffer(gl::FRAMEBUFFER, res);
998
999            let mut colors : [u32; 4] = [0; 4];
1000            for i in 0..4u32 {
1001                match &desc.color_attachements[i as usize] {
1002                    Some(SurfaceAttachment::Texture(ca)) => {
1003                        let gl_id = self.textures[ca.res_id()].gl_id;
1004                        colors[i as usize] = gl_id;
1005                        gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + i, gl::TEXTURE_2D, gl_id, 0);
1006                    },
1007                    Some(SurfaceAttachment::RenderTarget(ca)) => {
1008                        let gl_id = self.render_targets[ca.res_id()].gl_id;
1009                        colors[i as usize] = gl_id;
1010                        gl::FramebufferRenderbuffer(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + i, gl::RENDERBUFFER, gl_id);
1011                    },
1012                    _ => ()
1013                }
1014            }
1015
1016            match &desc.depth_stencil_attachement {
1017                SurfaceAttachment::RenderTarget(ca) =>  {
1018                    let gl_id = self.render_targets[ca.res_id()].gl_id;
1019                    gl::FramebufferRenderbuffer(gl::FRAMEBUFFER, gl::DEPTH_ATTACHMENT, gl::RENDERBUFFER, gl_id);
1020                },
1021                SurfaceAttachment::Texture(ca) => {
1022                    let gl_id = self.textures[ca.res_id()].gl_id;
1023                    gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::DEPTH_ATTACHMENT, gl::TEXTURE_2D, gl_id, 0);
1024                }
1025            }
1026
1027            if gl::CheckFramebufferStatus(gl::FRAMEBUFFER) != gl::FRAMEBUFFER_COMPLETE {
1028                println!("Framebuffer is not complete!");
1029                gl::DeleteFramebuffers(1, &mut res);
1030                return None
1031            }
1032
1033            let mut color0 = 0;
1034            gl::GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0 as GLenum, gl::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME as GLenum, &mut color0);
1035            assert_ne!(colors[0], 0);
1036            assert_eq!(colors[0], color0 as u32);
1037
1038            Self::check_gl_error();
1039
1040            let idx = self.framebuffers.add(GLFrameBuffer { desc: desc.clone(), gl_id: res });
1041
1042            let iptr : IntrusivePtr<dyn Driver>= IntrusivePtr::from_raw_increment(self as *mut Self as *mut dyn Driver);
1043
1044            gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
1045
1046            Some(FrameBufferPtr::new(FrameBuffer::new(ResourceType::FrameBuffer, idx, desc, Some(iptr))))
1047        }
1048    }
1049
1050    fn delete_resource(&mut self, resource_type: &ResourceType, res_id: usize) {
1051        match resource_type {
1052            ResourceType::DeviceBuffer  => self.delete_device_buffer(res_id),
1053            ResourceType::Texture       => self.delete_texture(res_id),
1054            ResourceType::RenderTarget  => self.delete_render_target(res_id),
1055            ResourceType::Shader        => self.delete_shader(res_id),
1056            ResourceType::Pipeline      => self.delete_pipeline(res_id),
1057            ResourceType::FrameBuffer   => self.delete_frame_buffer(res_id),
1058        }
1059    }
1060
1061    fn draw(&mut self, pipe: &Pipeline, bindings: &Bindings, uniforms: *const c_void, prim_count: u32, instance_count: u32) {
1062        unsafe {
1063            let gl_pipe = &self.pipelines[pipe.res_id()];
1064            let gl_prog = &self.shaders[gl_pipe.desc.shader.res_id()];
1065
1066            // blend
1067            match &gl_pipe.desc.blend {
1068                BlendOp::Add(blend) | BlendOp::Subtract(blend) => {
1069                    gl::Enable(gl::BLEND);
1070                    gl::BlendFuncSeparate(
1071                        blend.src_factor_rgb.gl_blend_factor(),
1072                        blend.dst_factor_rgb.gl_blend_factor(),
1073                        blend.src_factor_alpha.gl_blend_factor(),
1074                        blend.dst_factor_alpha.gl_blend_factor());
1075                },
1076                _ => gl::Disable(gl::BLEND),
1077            }
1078
1079            match &gl_pipe.desc.blend {
1080                BlendOp::Add(_) => gl::BlendEquationSeparate(gl::FUNC_ADD, gl::FUNC_ADD),
1081                BlendOp::Subtract(_) => gl::BlendEquationSeparate(gl::FUNC_SUBTRACT, gl::FUNC_SUBTRACT),
1082                BlendOp::ReverseSubtract(_) => gl::BlendEquationSeparate(gl::FUNC_REVERSE_SUBTRACT, gl::FUNC_REVERSE_SUBTRACT),
1083                _ => ()
1084            }
1085
1086            let (gl_prim, gl_elem_count) =
1087                match gl_pipe.desc.primitive_type {
1088                    PrimitiveType::Lines        => (gl::LINES, 2 * prim_count),
1089                    PrimitiveType::LineStrip    => (gl::LINE_STRIP, 1 + prim_count),
1090                    PrimitiveType::Points       => (gl::POINTS, prim_count),
1091                    PrimitiveType::Triangles    => (gl::TRIANGLES, 3 * prim_count),
1092                    PrimitiveType::TriangleStrip    => (gl::TRIANGLE_STRIP, 2 + prim_count)
1093                };
1094
1095            match gl_pipe.desc.cull_mode {
1096                CullMode::None => gl::Disable(gl::CULL_FACE),
1097                CullMode::Winding => gl::Enable(gl::CULL_FACE),
1098            }
1099
1100            match gl_pipe.desc.face_winding {
1101                FaceWinding::CCW => gl::CullFace(gl::BACK),
1102                FaceWinding::CW => gl::CullFace(gl::FRONT),
1103            }
1104
1105            if gl_pipe.desc.depth_test {
1106                gl::Enable(gl::DEPTH_TEST)
1107            } else {
1108                gl::Disable(gl::DEPTH_TEST)
1109            }
1110
1111            gl::DepthMask(if gl_pipe.desc.depth_write { gl::TRUE } else { gl::FALSE } as GLboolean);
1112
1113            gl::UseProgram(gl_prog.gl_id);
1114            for (l, layout) in gl_pipe.desc.buffer_layouts.iter().enumerate() {
1115                let gl_vb = &self.device_buffers[bindings.vertex_buffers[layout.buffer_id].res_id()];
1116                gl::BindBuffer(gl::ARRAY_BUFFER, gl_vb.gl_id);
1117                for (i, a) in layout.vertex_attributes.iter().enumerate() {
1118                    let aidx = &gl_prog.vertex_attributes[l][i];
1119                    gl::EnableVertexAttribArray(aidx.1);
1120                    match a.format() {
1121                        VertexFormat::Int |
1122                        VertexFormat::Int2 |
1123                        VertexFormat::Int3 |
1124                        VertexFormat::Int4 |
1125                        VertexFormat::UInt |
1126                        VertexFormat::UInt2 |
1127                        VertexFormat::UInt3 |
1128                        VertexFormat::UInt4  => {
1129                            gl::VertexAttribIPointer(aidx.1, a.format().gl_elem_count() as GLint, a.format().gl_elem_type(), layout.stride as GLint, a.offset() as *const c_void);
1130                        },
1131                        _ => {
1132                            gl::VertexAttribPointer(aidx.1, a.format().gl_elem_count() as GLint, a.format().gl_elem_type(), a.format().gl_is_normalized(), layout.stride as GLint, a.offset() as *const c_void);
1133                        }
1134                    }
1135                    gl::VertexAttribDivisor(aidx.1, layout.divisor as GLuint);
1136                }
1137            }
1138
1139            setup_uniforms(uniforms, gl_pipe.desc.uniform_descs.as_slice(), gl_prog.vertex_uniforms.as_slice());
1140
1141            for (i, t) in bindings.vertex_images.iter().enumerate() {
1142                let location = gl_prog.vertex_surfaces[i].1;
1143                gl::ActiveTexture(((gl::TEXTURE0 as usize) + i) as GLenum);
1144                gl::BindTexture(gl::TEXTURE_2D, self.textures[t.res_id()].gl_id as GLuint);
1145                gl::Uniform1i(location as GLint, i as GLint);
1146            }
1147
1148            let pixel_sampler_offset = bindings.vertex_images.len();
1149
1150            for (i, t) in bindings.pixel_images.iter().enumerate() {
1151                let location = gl_prog.pixel_surfaces[i].1;
1152                gl::ActiveTexture(((gl::TEXTURE0 as usize) + i + pixel_sampler_offset) as GLenum);
1153                gl::BindTexture(gl::TEXTURE_2D, self.textures[t.res_id()].gl_id as GLuint);
1154                gl::Uniform1i(location as GLint, (i + pixel_sampler_offset) as GLint);
1155            }
1156
1157            match &bindings.index_buffer {
1158                Some(ib) => {
1159                    gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.device_buffers[ib.res_id()].gl_id);
1160
1161                    let itype =
1162                        match gl_pipe.desc.index_type {
1163                            IndexType::None => panic!("attempt to bind an index buffer to a pipeline that doesn't support it"),
1164                            IndexType::UInt16 => gl::UNSIGNED_SHORT,
1165                            IndexType::UInt32 => gl::UNSIGNED_INT,
1166                        };
1167
1168                    gl::DrawElementsInstanced(gl_prim, gl_elem_count as GLsizei, itype, core::ptr::null() as *const rs_ctypes::c_void, instance_count as GLint);
1169                },
1170                None => {
1171                    if gl_pipe.desc.index_type != IndexType::None {
1172                        panic!("no index buffer bound but index type exist in pipeline")
1173                    }
1174                    gl::DrawArraysInstanced(gl_prim, 0, gl_elem_count as GLsizei, instance_count as GLint);
1175                }
1176            }
1177
1178            for l in &gl_prog.vertex_attributes {
1179                for v in l {
1180                    gl::DisableVertexAttribArray(v.1);
1181                }
1182            }
1183        }
1184    }
1185
1186    fn begin_pass(&mut self, pass: &Pass) {
1187        unsafe {
1188            gl::Flush();
1189            gl::Viewport(0, 0, pass.width as i32, pass.height as i32);
1190            gl::Scissor(0, 0, pass.width as i32, pass.height as i32);
1191
1192            match &pass.frame_buffer {
1193                None => {
1194                    gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
1195                    Self::check_gl_error();
1196                },
1197
1198                Some(fb) => {
1199                    gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffers[fb.res_id()].gl_id);
1200                    Self::check_gl_error();
1201                },
1202            }
1203
1204            // set the draw buffers
1205            match &pass.frame_buffer {
1206                Some(fb) => {
1207                    let fb_ref = &self.framebuffers[fb.res_id()];
1208                    let mut draw_buffer : [GLenum; 4] = [ gl::NONE, gl::NONE, gl::NONE, gl::NONE ];
1209                    for (idx, attach) in fb_ref.desc.color_attachements.iter().enumerate() {
1210                        match attach {
1211                            Some(_) => {
1212                                draw_buffer[idx] = gl::COLOR_ATTACHMENT0 + (idx as GLenum);
1213                            },
1214                            None => (),
1215                        };
1216                    }
1217
1218                    gl::DrawBuffers(4, &draw_buffer as *const GLenum);
1219                    Self::check_gl_error();
1220
1221                    for idx in 0..4 {
1222                        match pass.color_actions[idx] {
1223                            ColorPassAction::Clear(col) => {
1224                                let surf = &fb_ref.desc.color_attachements[idx];
1225                                match surf.as_ref() {
1226                                    Some(surf_ref) => {
1227                                        match surf_ref.pixel_format().to_orig_surface_type() {
1228                                            OrigSurfaceType::UInt => {
1229                                                let i_cols : [GLuint; 4] = [col.x as GLuint, col.y as GLuint, col.z as GLuint, col.w as GLuint];
1230                                                gl::ClearBufferuiv(gl::COLOR as GLenum, idx as GLint, i_cols.as_ptr() as *const GLuint);
1231                                            },
1232                                            OrigSurfaceType::Float => {
1233                                                let float_col = color4b_to_color4f(col);
1234                                                let f_cols : [GLfloat; 4] = [float_col.x, float_col.y, float_col.z, float_col.w];
1235                                                gl::ClearBufferfv(gl::COLOR as GLenum, idx as GLint, f_cols.as_ptr() as *const GLfloat);
1236                                            }
1237                                        }
1238                                    },
1239                                    _ => {  // assume that it's the default fixed point frame buffer
1240                                        let float_col = color4b_to_color4f(col);
1241                                        let f_cols : [GLfloat; 4] = [float_col.x, float_col.y, float_col.z, float_col.w];
1242                                        gl::ClearBufferfv(gl::COLOR as GLenum, idx as GLint, f_cols.as_ptr() as *const GLfloat);
1243                                    }
1244                                }
1245                                Self::check_gl_error();
1246                            },
1247                            _ => ()
1248                        }
1249                    }
1250
1251                    // clear the depth
1252                    match pass.depth_action {
1253                        DepthPassAction::Clear(f) => {
1254                            gl::ClearBufferfv(gl::DEPTH as GLenum, 0, &f as *const _ as *const GLfloat);
1255                            Self::check_gl_error();
1256
1257                        },
1258                        _ => ()
1259                    }
1260                },
1261                None => {
1262                    // TODO: does glClearBufferfv works here?
1263                    let mut bits    = 0;
1264                    for idx in 0..4 {
1265                        match pass.color_actions[idx] {
1266                            ColorPassAction::Clear(col) => {
1267                                let float_col = color4b_to_color4f(col);
1268                                let f_cols : [GLfloat; 4] = [float_col.x, float_col.y, float_col.z, float_col.w];
1269                                gl::ClearColor(f_cols[0], f_cols[1], f_cols[2], f_cols[3]);
1270
1271                                bits |= gl::COLOR_BUFFER_BIT;
1272                            },
1273                            _ => ()
1274                        }
1275                    }
1276
1277                    match pass.depth_action {
1278                        DepthPassAction::Clear(depth) => {
1279                            gl::ClearDepthf(depth);
1280                            bits   |= gl::DEPTH_BUFFER_BIT;
1281                        },
1282                        _ => ()
1283                    }
1284                    gl::Clear(bits);
1285                    Self::check_gl_error();
1286                }
1287            }
1288
1289        }
1290    }
1291
1292    fn end_pass(&mut self) {
1293    }
1294
1295    fn set_viewport(&mut self, x: u32, y: u32, w: u32, h: u32) {
1296        unsafe { gl::Viewport(x as GLint, y as GLint, w as GLsizei, h as GLsizei) }
1297    }
1298
1299    fn set_scissor(&mut self, x: u32, y: u32, w: u32, h: u32) {
1300        unsafe {
1301            gl::Scissor(x as GLint, y as GLint, w as GLsizei, h as GLsizei)
1302        }
1303    }
1304
1305    fn update_device_buffer(&mut self, dev_buf: &mut DeviceBufferPtr, offset: usize, pl: &dyn Payload) {
1306        unsafe {
1307            match self.device_buffers[dev_buf.res_id()].desc {
1308                DeviceBufferDesc::Vertex(Usage::Static(_))   |
1309                DeviceBufferDesc::Index(Usage::Static(_))    |
1310                DeviceBufferDesc::Pixel(Usage::Static(_))    => {
1311                    //return None
1312                    panic!("trying to update static buffer")
1313                },
1314                _ => (),    // TODO: Streamed can be done once per frame ?
1315            };
1316
1317            let buff_size   = self.device_buffers[dev_buf.res_id()].desc.size();
1318            if pl.size() + offset > buff_size {
1319                panic!("payload exceeds device buffer size")
1320            }
1321
1322            let target =
1323                match self.device_buffers[dev_buf.res_id()].desc {
1324                    DeviceBufferDesc::Vertex(_)  => gl::ARRAY_BUFFER,
1325                    DeviceBufferDesc::Index(_)   => gl::ELEMENT_ARRAY_BUFFER,
1326                    DeviceBufferDesc::Pixel(_)   => gl::PIXEL_UNPACK_BUFFER,
1327                };
1328            gl::BindBuffer(target, self.device_buffers[dev_buf.res_id()].gl_id as GLuint);
1329            let ptr = gl::MapBufferRange(target, offset as GLintptr, pl.size() as GLsizeiptr, gl::MAP_WRITE_BIT as GLbitfield) as *mut u8;
1330            Self::check_gl_error();
1331
1332            std::ptr::copy_nonoverlapping(pl.ptr() as *mut u8, ptr, pl.size());
1333
1334            assert_eq!(gl::UnmapBuffer(target), gl::TRUE as GLboolean);
1335            Self::check_gl_error();
1336        }
1337    }
1338
1339    fn update_texture(&mut self, dev_buf: &mut TexturePtr, pl: Box<dyn Payload>) {
1340        // TODO: check payload size and format
1341        let res_id  = dev_buf.res_id();
1342        let gl_id   = self.textures[res_id].gl_id;
1343        Self::upload_texture(gl_id, &dev_buf.desc().sampler_desc, &Some(pl));
1344    }
1345
1346    fn read_back(&mut self, surface: &TexturePtr, x: u32, y: u32, w: u32, h: u32) -> Option<ReadbackPayload> {
1347        unsafe {
1348            let rb = self.read_back_state() as *const ReadbackState as *mut ReadbackState;
1349            (&mut (*rb)).read_surface(self, surface, x, y, w, h)
1350        }
1351    }
1352}
1353
1354impl IntrusiveCounter for Gles3Driver {
1355    fn increment(&mut self) { self.rc.fetch_add(1, Ordering::SeqCst); }
1356    fn decrement(&mut self) -> isize {
1357        self.rc.fetch_sub(1, Ordering::SeqCst)
1358    }
1359}
1360
1361impl Drop for Gles3Driver {
1362    fn drop(&mut self) {
1363        println!("Gles3Driver dropped - All is good!")
1364    }
1365}
1366
1367pub fn get_driver() -> DriverPtr {
1368    unsafe {
1369        let mut range : [GLint; 2] = [0, 0];
1370        let mut precision = 0;
1371
1372        gl::GetShaderPrecisionFormat(gl::FRAGMENT_SHADER, gl::HIGH_FLOAT, range.as_mut_ptr(), &mut precision);
1373        println!("highp float range: {:?} - precision: {}", range, precision);
1374
1375        gl::GetShaderPrecisionFormat(gl::FRAGMENT_SHADER, gl::HIGH_INT, range.as_mut_ptr(), &mut precision);
1376        println!("highp int range: {:?} - precision: {}", range, precision);
1377
1378        gl::GetShaderPrecisionFormat(gl::FRAGMENT_SHADER, gl::MEDIUM_FLOAT, range.as_mut_ptr(), &mut precision);
1379        println!("mediump float range: {:?} - precision: {}", range, precision);
1380
1381        gl::GetShaderPrecisionFormat(gl::FRAGMENT_SHADER, gl::MEDIUM_INT, range.as_mut_ptr(), &mut precision);
1382        println!("mediump int range: {:?} - precision: {}", range, precision);
1383
1384        gl::GetShaderPrecisionFormat(gl::FRAGMENT_SHADER, gl::LOW_FLOAT, range.as_mut_ptr(), &mut precision);
1385        println!("lowp float range: {:?} - precision: {}", range, precision);
1386
1387        gl::GetShaderPrecisionFormat(gl::FRAGMENT_SHADER, gl::LOW_INT, range.as_mut_ptr(), &mut precision);
1388        println!("lowp int range: {:?} - precision: {}", range, precision);
1389
1390    }
1391    Gles3Driver::new().initialize()
1392}