glslopt/
lib.rs

1use std::ffi::{CString, CStr};
2use std::ptr;
3
4#[allow(dead_code)]
5#[allow(non_camel_case_types)]
6#[allow(non_upper_case_globals)]
7mod bindings;
8
9pub enum ShaderType {
10    Vertex,
11    Fragment,
12}
13
14pub enum Target {
15    OpenGl,
16    OpenGles20,
17    OpenGles30,
18    Metal,
19}
20
21pub struct Context {
22    ctx: *mut bindings::glslopt_ctx,
23}
24
25impl Context {
26    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
41    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
56impl Drop for Context {
57    fn drop(&mut self) {
58        unsafe {
59            bindings::glslopt_cleanup(self.ctx);
60        }
61    }
62}
63
64pub struct Shader {
65    shader: *mut bindings::glslopt_shader,
66}
67
68impl Shader {
69    pub fn get_status(&self) -> bool {
70        unsafe { bindings::glslopt_get_status(self.shader) }
71    }
72
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
84    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
96impl Drop for Shader {
97    fn drop(&mut self) {
98        unsafe {
99            bindings::glslopt_shader_delete(self.shader);
100        }
101    }
102}