cognitive_graphics/
gl_tools.rs1use std;
9use gl;
10
11pub enum GlslVersion {
14 Unknown,
15 Glsl100,
16 Glsl300,
17}
18
19pub fn get_info_log(object: gl::types::GLuint) -> String {
23 unsafe {
24 let mut log_length: i32 = 0;
25 if gl::IsShader(object) == gl::TRUE {
26 gl::GetShaderiv(object, gl::INFO_LOG_LENGTH, &mut log_length);
27 } else if gl::IsProgram(object) == gl::TRUE {
28 gl::GetProgramiv(object, gl::INFO_LOG_LENGTH, &mut log_length);
29 } else {
30 return "GL: Not a shader or a program".to_owned();
31 }
32
33 let mut length: i32 = 0;
34 let mut buffer = [0u8; 512];
35 if gl::IsShader(object) == gl::TRUE {
36 gl::GetShaderInfoLog(object,
37 buffer.len() as i32,
38 &mut length,
39 buffer.as_mut_ptr() as *mut i8);
40 } else if gl::IsProgram(object) == gl::TRUE {
41 gl::GetProgramInfoLog(object,
42 buffer.len() as i32,
43 &mut length,
44 buffer.as_mut_ptr() as *mut i8);
45 }
46
47 let cstr = std::ffi::CStr::from_ptr(std::mem::transmute(&buffer));
48 format!("GL: {}", std::str::from_utf8(cstr.to_bytes()).expect("Info log is invalid"))
49 }
50}
51
52pub fn get_shading_lang_version() -> GlslVersion {
56 let version = unsafe {
57 let ptr = gl::GetString(gl::SHADING_LANGUAGE_VERSION);
58 let cstr: &std::ffi::CStr = std::ffi::CStr::from_ptr(ptr as *const i8);
59 std::str::from_utf8(cstr.to_bytes()).expect("Shading lang string is invalid")
60 };
61
62 if version.find("ES 3.").is_some() {
63 GlslVersion::Glsl300
64 } else if version.find("ES 1.").is_some() {
65 GlslVersion::Glsl100
66 } else {
67 GlslVersion::Unknown
68 }
69}
70
71pub fn create_shader(source: String,
75 shader_type: gl::types::GLenum)
76 -> Result<gl::types::GLuint, String> {
77 unsafe {
78 let shader = gl::CreateShader(shader_type);
79 let cstr = std::ffi::CString::new(source.as_bytes()).unwrap();
80 gl::ShaderSource(shader, 1, &cstr.as_ptr(), std::ptr::null());
81 gl::CompileShader(shader);
82
83 let mut status = gl::FALSE as gl::types::GLint;
84 gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
85 if status != (gl::TRUE as gl::types::GLint) {
86 let info_log = get_info_log(shader);
87 gl::DeleteShader(shader);
88 Err(info_log)
89 } else {
90 Ok(shader)
91 }
92 }
93}
94
95pub fn create_program(vertex_shader: gl::types::GLenum,
99 fragment_shader: gl::types::GLenum)
100 -> Result<gl::types::GLuint, String> {
101 unsafe {
102 let shader_program = gl::CreateProgram();
104
105 gl::AttachShader(shader_program, vertex_shader);
107 gl::AttachShader(shader_program, fragment_shader);
108 gl::LinkProgram(shader_program);
109
110 let mut link_ok = gl::FALSE as i32;
112 gl::GetProgramiv(shader_program, gl::LINK_STATUS, &mut link_ok);
113 if link_ok == gl::TRUE as i32 {
114 Ok(shader_program)
115 } else {
116 let info_log = get_info_log(shader_program);
117 gl::DeleteProgram(shader_program);
118 Err(info_log)
119 }
120 }
121}
122
123pub fn prepare_shader_program(vertex_source: String,
127 fragment_source: String)
128 -> Result<gl::types::GLuint, String> {
129 let vertex_shader = create_shader(vertex_source, gl::VERTEX_SHADER)?;
131
132 let fragment_shader = create_shader(fragment_source, gl::FRAGMENT_SHADER)?;
134
135 create_program(vertex_shader, fragment_shader)
137}
138
139pub fn get_attrib_location(program: gl::types::GLuint,
143 name: String)
144 -> Result<gl::types::GLint, String> {
145 let cstr = std::ffi::CString::new(name.as_bytes()).unwrap();
146 let location =
147 unsafe { gl::GetAttribLocation(program, cstr.as_bytes_with_nul().as_ptr() as *const i8) };
148
149 if location < 0 {
150 Err(format!("Could not get location for attribute '{}'", name))
151 } else {
152 Ok(location)
153 }
154}
155
156pub fn get_uniform_location(program: gl::types::GLuint,
160 name: String)
161 -> Result<gl::types::GLint, String> {
162 let cstr = std::ffi::CString::new(name.as_bytes()).unwrap();
163 let location =
164 unsafe { gl::GetUniformLocation(program, cstr.as_bytes_with_nul().as_ptr() as *const i8) };
165
166 if location < 0 {
167 Err(format!("Could not get location for uniform '{}'", name))
168 } else {
169 Ok(location)
170 }
171}
172
173