1 use std::ffi::{CString, CStr};
2 use std::ptr;
3 
4 #[allow(dead_code)]
5 #[allow(non_camel_case_types)]
6 #[allow(non_upper_case_globals)]
7 mod bindings;
8 
9 pub enum ShaderType {
10     Vertex,
11     Fragment,
12 }
13 
14 pub enum Target {
15     OpenGl,
16     OpenGles20,
17     OpenGles30,
18     Metal,
19 }
20 
21 pub struct Context {
22     ctx: *mut bindings::glslopt_ctx,
23 }
24 
25 impl Context {
new(target: Target) -> Self26     pub fn new(target: Target) -> Self {
27         let target = match target {
28             Target::OpenGl => bindings::glslopt_target_kGlslTargetOpenGL,
29             Target::OpenGles20 => bindings::glslopt_target_kGlslTargetOpenGLES20,
30             Target::OpenGles30 => bindings::glslopt_target_kGlslTargetOpenGLES30,
31             Target::Metal => bindings::glslopt_target_kGlslTargetMetal,
32         };
33 
34         let ctx = unsafe { bindings::glslopt_initialize(target) };
35 
36         Self {
37             ctx,
38         }
39     }
40 
optimize(&self, shader_type: ShaderType, source: String) -> Shader41     pub fn optimize(&self, shader_type: ShaderType, source: String) -> Shader {
42         let shader_type = match shader_type {
43             ShaderType::Vertex => bindings::glslopt_shader_type_kGlslOptShaderVertex,
44             ShaderType::Fragment => bindings::glslopt_shader_type_kGlslOptShaderFragment,
45         };
46         let source = CString::new(source).unwrap();
47 
48         let shader = unsafe { bindings::glslopt_optimize(self.ctx, shader_type, source.as_ptr(), 0) };
49         assert_ne!(shader, ptr::null_mut());
50         Shader {
51             shader,
52         }
53     }
54 }
55 
56 impl Drop for Context {
drop(&mut self)57     fn drop(&mut self) {
58         unsafe {
59             bindings::glslopt_cleanup(self.ctx);
60         }
61     }
62 }
63 
64 pub struct Shader {
65     shader: *mut bindings::glslopt_shader,
66 }
67 
68 impl Shader {
get_status(&self) -> bool69     pub fn get_status(&self) -> bool {
70         unsafe { bindings::glslopt_get_status(self.shader) }
71     }
72 
get_output(&self) -> Result<&str, ()>73     pub fn get_output(&self) -> Result<&str, ()> {
74         unsafe {
75             let cstr = bindings::glslopt_get_output(self.shader);
76             if cstr == ptr::null() {
77                 Err(())
78             } else {
79                 Ok(CStr::from_ptr(cstr).to_str().unwrap())
80             }
81         }
82     }
83 
get_log(&self) -> &str84     pub fn get_log(&self) -> &str {
85         unsafe {
86             let cstr = bindings::glslopt_get_log(self.shader);
87             if cstr == ptr::null() {
88                 ""
89             } else {
90                 CStr::from_ptr(cstr).to_str().unwrap()
91             }
92         }
93     }
94 }
95 
96 impl Drop for Shader {
drop(&mut self)97     fn drop(&mut self) {
98         unsafe {
99             bindings::glslopt_shader_delete(self.shader);
100         }
101     }
102 }
103