1use crate::gl;
5use crate::gl::types::{GLboolean, GLchar, GLenum, GLint, GLsizeiptr, GLuint};
6use std::ffi::CString;
7use std::{ptr, mem};
8
9pub struct DynamicAttribute {
11 vbo: GLuint,
13 size: i32,
15 location: GLuint,
17 normalize: GLboolean,
19 ty: GLenum,
21}
22
23impl Drop for DynamicAttribute {
24 fn drop(&mut self) {
25 unsafe {
26 gl::DeleteBuffers(1, &self.vbo);
27 }
28 }
29}
30
31impl DynamicAttribute {
32 pub fn bind_vao(&self, vao: GLuint) {
36 let stride = 0;
37 unsafe {
38 gl::BindVertexArray(vao);
39 gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
40 gl::VertexAttribPointer(self.location,
41 self.size,
42 self.ty,
43 self.normalize,
44 stride,
45 ptr::null());
46 }
47 }
48
49 fn new(program: GLuint,
50 name: &str,
51 size: i32,
52 normalize: GLboolean,
53 ty: GLenum)
54 -> Result<Self, String> {
55 let location = attribute_location(program, name)?;
56 let mut vbo = 0;
57 unsafe {
58 gl::GenBuffers(1, &mut vbo);
59 }
60 let res = DynamicAttribute {
61 vbo: vbo,
62 size: size,
63 location: location,
64 normalize: normalize,
65 ty: ty,
66 };
67 Ok(res)
68 }
69
70 pub fn xyz(program: GLuint, name: &str) -> Result<DynamicAttribute, String> {
72 DynamicAttribute::new(program, name, 3, gl::FALSE, gl::FLOAT)
73 }
74
75 pub fn xy(program: GLuint, name: &str) -> Result<DynamicAttribute, String> {
77 DynamicAttribute::new(program, name, 2, gl::FALSE, gl::FLOAT)
78 }
79
80 pub fn rgb(program: GLuint, name: &str) -> Result<DynamicAttribute, String> {
82 DynamicAttribute::new(program, name, 3, gl::FALSE, gl::FLOAT)
83 }
84
85 pub fn rgba(program: GLuint, name: &str) -> Result<DynamicAttribute, String> {
87 DynamicAttribute::new(program, name, 4, gl::FALSE, gl::FLOAT)
88 }
89
90 pub fn uv(program: GLuint, name: &str) -> Result<DynamicAttribute, String> {
92 DynamicAttribute::new(program, name, 2, gl::FALSE, gl::FLOAT)
93 }
94
95 pub unsafe fn set<T>(&self, data: &[T]) {
97 gl::EnableVertexAttribArray(self.location);
98 gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
99 gl::BufferData(gl::ARRAY_BUFFER,
100 data.len() as GLsizeiptr * mem::size_of::<T>() as GLsizeiptr,
101 mem::transmute(data.as_ptr()),
102 gl::DYNAMIC_DRAW);
103 }
104}
105
106pub fn compile_shader(shader_type: GLenum, source: &str) -> Result<GLuint, String> {
110 unsafe {
111 let shader = gl::CreateShader(shader_type);
112 let c_source = match CString::new(source) {
113 Ok(x) => x,
114 Err(err) => return Err(format!("compile_shader: {}", err)),
115 };
116 gl::ShaderSource(shader, 1, &c_source.as_ptr(), ptr::null());
117 drop(source);
118 gl::CompileShader(shader);
119 let mut status = gl::FALSE as GLint;
120 gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
121 if status == (gl::TRUE as GLint) {
122 Ok(shader)
123 } else {
124 let mut len = 0;
125 gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
126
127 if len == 0 {
128 Err("Compilation failed with no log. \
129 The OpenGL context might have been created on another thread, \
130 or not have been created."
131 .to_string())
132 } else {
133 let mut buf = vec![0; len as usize - 1];
135 gl::GetShaderInfoLog(shader,
136 len,
137 ptr::null_mut(),
138 buf.as_mut_ptr() as *mut GLchar);
139
140 gl::DeleteShader(shader);
141
142 Err(String::from_utf8(buf).ok().expect("ShaderInfoLog not valid utf8"))
143 }
144 }
145 }
146}
147
148pub fn attribute_location(program: GLuint, name: &str) -> Result<GLuint, String> {
152 unsafe {
153 let c_name = match CString::new(name) {
154 Ok(x) => x,
155 Err(err) => return Err(format!("attribute_location: {}", err)),
156 };
157 let id = gl::GetAttribLocation(program, c_name.as_ptr());
158 drop(c_name);
159 if id < 0 {
160 Err(format!("Attribute '{}' does not exists in shader", name))
161 } else {
162 Ok(id as GLuint)
163 }
164 }
165}
166
167pub fn uniform_location(program: GLuint, name: &str) -> Result<GLuint, String> {
171 unsafe {
172 let c_name = match CString::new(name) {
173 Ok(x) => x,
174 Err(err) => return Err(format!("uniform_location: {}", err)),
175 };
176 let id = gl::GetUniformLocation(program, c_name.as_ptr());
177 drop(c_name);
178 if id < 0 {
179 Err(format!("Uniform '{}' does not exists in shader", name))
180 } else {
181 Ok(id as GLuint)
182 }
183 }
184}