e2rcore/implement/render/
util_gl.rs1extern crate gl;
2extern crate pretty_env_logger;
3
4use std::str;
5
6#[derive(Clone)]
7#[derive(Copy)]
8pub enum ShaderType {
9 VERTEX,
10 FRAGMENT,
11}
12
13pub fn load_and_compile_shader( shader_src : &str, shader_type: ShaderType ) -> Result< gl::types::GLuint, String > {
16 unsafe {
17 let handle = match shader_type {
18 ShaderType::VERTEX => gl::CreateShader( gl::VERTEX_SHADER ),
19 ShaderType::FRAGMENT => gl::CreateShader( gl::FRAGMENT_SHADER ),
20 };
21 assert!( handle != 0 );
22 let shader_src_arr = [ shader_src.as_ptr() as * const i8 ];
23 let shader_src_len_arr = [ shader_src.len() as i32 ];
24 gl::ShaderSource( handle, shader_src_arr.len() as i32, shader_src_arr.as_ptr(), &shader_src_len_arr[0] );
25 gl::CompileShader( handle );
26 let mut result = -1;
27 gl::GetShaderiv( handle, gl::COMPILE_STATUS, & mut result );
28 if 0 == result {
29 let mut log_len = 0;
30 gl::GetShaderiv( handle, gl::INFO_LOG_LENGTH, & mut log_len );
31 let log = vec![ 0i8; log_len as usize ];
32 if log_len > 0 {
33 let mut written = 0;
34 gl::GetShaderInfoLog( handle, log_len, & mut written, log.as_ptr() as * mut i8 );
35 let log_u8 = log.iter().map(|&x| x as u8 ).collect::<Vec<u8> >();
36 let log_str = str::from_utf8( &log_u8[..] ).unwrap();
37 return Err( String::from( log_str ) )
38 }else{
39 return Err( String::from( "unknown error during shader compilation" ) )
40 }
41 }
42 return Ok( handle )
43 }
44}
45
46pub fn check_program_link( handle: gl::types::GLuint ) -> Result< (), String > {
47 let mut status = -1;
48 unsafe {
49 gl::GetProgramiv( handle, gl::LINK_STATUS, & mut status );
50 if gl::FALSE as i32 == status {
51 let mut log_len = -1;
52 info!("get link status log length");
53 gl::GetProgramiv( handle, gl::INFO_LOG_LENGTH, & mut log_len );
54 info!( "log length: {}", log_len );
55 check_last_op();
56 let log = vec![ 0i8; log_len as usize ];
57 if log_len > 0 {
58 let mut written = 0;
59 info!("get link status log");
60 gl::GetProgramInfoLog( handle, log_len, & mut written, log.as_ptr() as * mut i8 );
61 check_last_op();
62 let log_u8 = log.iter().map(|&x| x as u8 ).collect::<Vec<u8> >();
63 let log_str = str::from_utf8( &log_u8[..] ).unwrap();
64 return Err( String::from( log_str ) )
65 } else {
66 return Err( String::from("unknown error during program linkage") )
67 }
68 }else{
69 return Ok(())
70 }
71 }
72}
73
74pub fn check_last_op() {
75 unsafe {
76 let err = gl::GetError();
77 match err {
78 gl::NO_ERROR => (),
79 gl::INVALID_ENUM => panic!("invalid_enum"),
80 gl::INVALID_VALUE => panic!("invalid_value"),
81 gl::INVALID_OPERATION => panic!("invalid_operation"),
82 gl::INVALID_FRAMEBUFFER_OPERATION => panic!("invalid_framebuffer_operation"),
83 gl::OUT_OF_MEMORY => panic!("out_of_memory"),
84 gl::STACK_OVERFLOW => panic!("stack_overflow"),
85 _ => panic!("unknown error"),
86 }
87 }
88}
89
90pub fn create_program_from_shaders( shader_handles: &[ gl::types::GLuint ] ) -> gl::types::GLuint {
91 create_program_from_shaders_with( shader_handles, | _program, _shader_handles | () ) }
93
94pub fn create_program_from_shaders_with< F >( shader_handles: &[ gl::types::GLuint ], f: F ) -> gl::types::GLuint where F: Fn( gl::types::GLuint, &[ gl::types::GLuint ] )->() {
95 unsafe {
96 let gl_program = gl::CreateProgram();
97 if gl_program == 0 {
98 panic!("gl_program creation failed");
99 }
100 for i in shader_handles.into_iter() {
101 gl::AttachShader( gl_program, *i );
102 }
103 f( gl_program, shader_handles );
105 gl::LinkProgram( gl_program );
106 match check_program_link( gl_program ) {
107 Err( o ) => panic!( "{}", o ),
108 _ => ()
109 }
110 return gl_program
111 }
112}
113
114pub fn delete_shader_program( handle: i64 ){
115 unsafe {
116 gl::DeleteProgram( handle as gl::types::GLuint );
117 }
118}
119pub fn query_uniform_float_array( program: gl::types::GLuint, name: String ){
120 unsafe {
121 let loc = gl::GetUniformLocation( program, name.as_ptr() as * const i8 );
122 trace!("uniform location: {:?}", loc );
123 let mut query_val = vec![0f32;32];
124 gl::GetUniformfv( program, loc, query_val.as_mut_ptr() );
125 check_last_op();
126 trace!("query uniform float array: {:?}", query_val );
127 }
128}
129
130pub fn load_texture( program: gl::types::GLuint, texture_number: gl::types::GLuint, image: &[u8], w: usize, h: usize ) -> Result< gl::types::GLuint, String > {
131 let mut tex : gl::types::GLuint = 0;
132 unsafe {
134 gl::GenTextures(1, & mut tex);
135 gl::ActiveTexture(gl::TEXTURE0 + texture_number);
136 gl::BindTexture( gl::TEXTURE_2D, tex );
137 gl::TexImage2D( gl::TEXTURE_2D, 0, gl::RGB as _, w as _, h as _, 0, gl::RGB, gl::UNSIGNED_BYTE, image.as_ptr() as _ );
138 gl::Uniform1i( gl::GetUniformLocation( program, b"tex\0".as_ptr() as _ ), 0 );
139 gl::TexParameteri( gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as _ );
140 gl::TexParameteri( gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as _ );
141 gl::TexParameteri( gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as _ );
142 gl::TexParameteri( gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as _ );
143 }
144 Ok( tex )
145}
146
147pub fn delete_texture( handle: gl::types::GLuint ) -> Result< (), String > {
148 unsafe {
149 gl::DeleteTextures(1, &handle);
150 }
151 Ok( () )
152}