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