1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use UniformData;
use VertexData;
use OpenGL;
use std::{ rc::Rc, ops::Range };
use types::*;
use Topology;
static mut CURRENT_PROGRAM: GLuint = 0;
#[derive(Clone)] pub struct Program(pub(crate) Rc<ProgramContext>);
impl Program {
pub fn new(opengl: &OpenGL, vertex: &[u8], fragment: &[u8]) -> Self {
let v_shader = shader_new(opengl, 0x8B31, vertex);
let f_shader = shader_new(opengl, 0x8B30, fragment);
let program = gl!(opengl, (opengl.get().create_program)());
gl!(opengl, (opengl.get().attach_shader)(program, v_shader));
gl!(opengl, (opengl.get().attach_shader)(program, f_shader));
gl!(opengl, (opengl.get().link_program)(program));
gl!(opengl, (opengl.get().detach_shader)(program, v_shader));
gl!(opengl, (opengl.get().detach_shader)(program, f_shader));
Program(Rc::new(ProgramContext(program, opengl.clone())))
}
pub fn vertex_data(&self, name: &[u8]) -> VertexData {
VertexData::new(self, name)
}
pub fn uniform(&self, name: &[u8]) -> UniformData {
UniformData::new(self, name)
}
pub fn draw_arrays(&self, topology: Topology, range: Range<u32>) {
self.bind();
gl!((*self.0).1, ((*self.0).1.get().draw_arrays)(
topology as GLuint,
range.start as GLint, range.end as GLsizei));
}
pub(crate) fn bind(&self) {
let program = unsafe { self.get() };
if program != unsafe { CURRENT_PROGRAM } {
gl!(&(*self.0).1,
((*self.0).1.get().use_program)(program));
unsafe { CURRENT_PROGRAM = program; }
}
}
pub(crate) fn opengl(&self) -> OpenGL {
(*self.0).1.clone()
}
pub(crate) unsafe fn get(&self) -> GLuint {
(*self.0).0
}
}
pub(crate) struct ProgramContext(GLuint, OpenGL);
impl Drop for ProgramContext {
fn drop(&mut self) {
gl!(self.1, (self.1.get().delete_program)(self.0));
}
}
fn shader_new(opengl: &OpenGL, shader_type: GLenum, src: &[u8]) -> GLuint {
let shader = gl!(opengl, (opengl.get().create_shader)(shader_type));
gl!(opengl, (opengl.get().shader_source)(shader, 1 ,
[src.as_ptr() as *const _].as_ptr(), [src.len() as i32].as_ptr()
));
gl!(opengl, (opengl.get().compile_shader)(shader));
compile_errors(opengl, shader);
shader
}
fn compile_errors(_opengl: &OpenGL, _shader: GLuint) {
#[cfg(debug_assertions)] {
let mut value = unsafe { ::std::mem::uninitialized() };
gl!(_opengl, (_opengl.get().get_shader)(_shader,
0x8B81 , &mut value));
if value == 0 {
let mut value = unsafe { ::std::mem::uninitialized() };
gl!(_opengl, (_opengl.get().get_shader)(_shader,
0x8B84 ,
&mut value));
let mut buffer: Vec<u8> =
vec![unsafe { ::std::mem::uninitialized() };
value as usize];
gl!(_opengl, (_opengl.get().info_log)(_shader,
value as GLsizei, ::std::ptr::null_mut(),
buffer.as_mut_ptr() as *mut _));
panic!("Failed to compile: {}.",
::std::str::from_utf8(buffer.as_slice())
.unwrap());
}
}
}