Browse Source

Improve error handling with OpenGL functions

Johannes Hofmann 7 years ago
parent
commit
a7db860456
4 changed files with 208 additions and 198 deletions
  1. 0
    8
      src/buffer.rs
  2. 40
    5
      src/context.rs
  3. 42
    54
      src/map_view_gl.rs
  4. 126
    131
      src/program.rs

+ 0
- 8
src/buffer.rs View File

@@ -38,14 +38,6 @@ impl<'a> Buffer<'a> {
38 38
                              (vertex_data.len() * mem::size_of::<f32>()) as context::gl::types::GLsizeiptr,
39 39
                              vertex_data.as_ptr() as *const _,
40 40
                              context::gl::STATIC_DRAW);
41
-
42
-            //TODO call this only once
43
-            // VAOs are not OpenGL ES 2.0 compatible, but are required for rendering with a core context.
44
-            if cx.gl.BindVertexArray.is_loaded() {
45
-                let mut vao = mem::uninitialized();
46
-                cx.gl.GenVertexArrays(1, &mut vao);
47
-                cx.gl.BindVertexArray(vao);
48
-            }
49 41
         }
50 42
 
51 43
         Buffer {

+ 40
- 5
src/context.rs View File

@@ -1,4 +1,6 @@
1 1
 use glutin;
2
+use std::mem;
3
+use std::ffi::CStr;
2 4
 
3 5
 pub(crate) mod gl {
4 6
     #![allow(unknown_lints)]
@@ -15,7 +17,7 @@ pub struct Context {
15 17
 impl ::std::fmt::Debug for Context {
16 18
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
17 19
         let version = unsafe {
18
-            let data = ::std::ffi::CStr::from_ptr(self.gl.GetString(gl::VERSION) as *const _).to_bytes().to_vec();
20
+            let data = CStr::from_ptr(self.gl.GetString(gl::VERSION) as *const _).to_bytes().to_vec();
19 21
             String::from_utf8(data).unwrap_or_else(|_| "".into())
20 22
         };
21 23
         write!(f, "Context {{ version: {:?} }}", version)
@@ -31,7 +33,17 @@ macro_rules! check_gl_errors {
31 33
 impl Context {
32 34
     pub fn from_window(window: &glutin::Window) -> Context {
33 35
         let gl = gl::Gl::load_with(|ptr| window.get_proc_address(ptr) as *const _);
34
-        let cx = Context {gl: gl};
36
+        let cx = Context { gl: gl };
37
+
38
+        // Initialize a vertex array object (VAO) if the current OpenGL context supports it. VAOs are
39
+        // not OpenGL ES 2.0 compatible, but are required for rendering with a core context.
40
+        if cx.gl.BindVertexArray.is_loaded() {
41
+            unsafe {
42
+                let mut vao = mem::uninitialized();
43
+                cx.gl.GenVertexArrays(1, &mut vao);
44
+                cx.gl.BindVertexArray(vao);
45
+            }
46
+        }
35 47
 
36 48
         info!("OpenGL version: {}", cx.gl_version());
37 49
         debug!("MAX_TEXTURE_SIZE: {}", cx.max_texture_size());
@@ -41,7 +53,7 @@ impl Context {
41 53
 
42 54
     pub fn gl_version(&self) -> String {
43 55
         unsafe {
44
-            let data = ::std::ffi::CStr::from_ptr(self.gl.GetString(gl::VERSION) as *const _).to_bytes().to_vec();
56
+            let data = CStr::from_ptr(self.gl.GetString(gl::VERSION) as *const _).to_bytes().to_vec();
45 57
             String::from_utf8(data).unwrap_or_else(|_| "".into())
46 58
         }
47 59
     }
@@ -54,30 +66,42 @@ impl Context {
54 66
         }
55 67
     }
56 68
 
57
-    pub unsafe fn check_errors(&self, file: &str, line: u32) {
69
+    pub fn check_errors(&self, file: &str, line: u32) {
70
+        let mut fail = false;
71
+
58 72
         loop {
59
-            match self.gl.GetError() {
73
+            match unsafe { self.gl.GetError() } {
60 74
                 gl::NO_ERROR => break,
61 75
                 gl::INVALID_VALUE => {
62 76
                     error!("{}:{}, invalid value error", file, line);
77
+                    fail = true;
63 78
                 },
64 79
                 gl::INVALID_ENUM => {
65 80
                     error!("{}:{}, invalid enum error", file, line);
81
+                    fail = true;
66 82
                 },
67 83
                 gl::INVALID_OPERATION => {
68 84
                     error!("{}:{}, invalid operation error", file, line);
85
+                    fail = true;
69 86
                 },
70 87
                 gl::INVALID_FRAMEBUFFER_OPERATION => {
71 88
                     error!("{}:{}, invalid framebuffer operation error", file, line);
89
+                    fail = true;
72 90
                 },
73 91
                 gl::OUT_OF_MEMORY => {
74 92
                     error!("{}:{}, out of memory error", file, line);
93
+                    fail = true;
75 94
                 },
76 95
                 x => {
77 96
                     error!("{}:{}, unknown error {}", file, line, x);
97
+                    fail = true;
78 98
                 },
79 99
             }
80 100
         }
101
+
102
+        if fail {
103
+            panic!("OpenGL error");
104
+        }
81 105
     }
82 106
 
83 107
     pub fn clear_color(&self, color: (f32, f32, f32, f32)) {
@@ -86,4 +110,15 @@ impl Context {
86 110
             self.gl.Clear(gl::COLOR_BUFFER_BIT);
87 111
         }
88 112
     }
113
+
114
+    pub fn set_viewport(&self, x: i32, y: i32, width: u32, height: u32) {
115
+        unsafe {
116
+            self.gl.Viewport(
117
+                x,
118
+                y,
119
+                width as gl::types::GLsizei,
120
+                height as gl::types::GLsizei,
121
+            );
122
+        }
123
+    }
89 124
 }

+ 42
- 54
src/map_view_gl.rs View File

@@ -1,4 +1,3 @@
1
-use ::context;
2 1
 use ::std::ffi::CStr;
3 2
 use buffer::{Buffer, DrawMode};
4 3
 use context::Context;
@@ -32,76 +31,65 @@ impl<'a> MapViewGl<'a> {
32 31
         ) -> MapViewGl
33 32
         where F: Fn() + Sync + Send + 'static,
34 33
     {
35
-        unsafe {
36
-            let mut program = Program::from_paths(cx, "shader/map.vert", "shader/map.frag");
37
-            check_gl_errors!(cx);
38
-
39
-            let tile_size = 256;
40
-
41
-            let atlas_size = {
42
-                let default_size = 2048;
43
-                let max_size = cx.max_texture_size() as u32;
44
-                if default_size <= max_size {
45
-                    default_size
46
-                } else {
47
-                    if tile_size * 3 > max_size {
48
-                        error!("maximal tile size ({}) is too small", max_size);
49
-                    }
34
+        let mut program = Program::from_paths(cx, "shader/map.vert", "shader/map.frag").unwrap();
35
+        check_gl_errors!(cx);
36
+
37
+        let tile_size = 256;
50 38
 
51
-                    max_size
39
+        let atlas_size = {
40
+            let default_size = 2048;
41
+            let max_size = cx.max_texture_size() as u32;
42
+            if default_size <= max_size {
43
+                default_size
44
+            } else {
45
+                if tile_size * 3 > max_size {
46
+                    error!("maximal tile size ({}) is too small", max_size);
52 47
                 }
53
-            };
54 48
 
55
-            let tex = Texture::empty(cx, atlas_size, atlas_size, TextureFormat::Rgb8);
56
-            check_gl_errors!(cx);
49
+                max_size
50
+            }
51
+        };
57 52
 
58
-            let buf = Buffer::new(cx, &[], 0);
53
+        let tex = Texture::empty(cx, atlas_size, atlas_size, TextureFormat::Rgb8);
54
+        check_gl_errors!(cx);
59 55
 
60
-            check_gl_errors!(cx);
56
+        let buf = Buffer::new(cx, &[], 0);
57
+        check_gl_errors!(cx);
61 58
 
62
-            program.add_texture(&tex, CStr::from_bytes_with_nul(b"tex_map\0").unwrap());
63
-            check_gl_errors!(cx);
59
+        program.add_texture(&tex, CStr::from_bytes_with_nul(b"tex_map\0").unwrap());
60
+        check_gl_errors!(cx);
64 61
 
65
-            program.add_attribute(CStr::from_bytes_with_nul(b"position\0").unwrap(), 2, 8, 0);
66
-            check_gl_errors!(cx);
67
-            program.add_attribute(CStr::from_bytes_with_nul(b"tex_coord\0").unwrap(), 2, 8, 2);
68
-            check_gl_errors!(cx);
69
-            program.add_attribute(CStr::from_bytes_with_nul(b"tex_minmax\0").unwrap(), 4, 8, 4);
70
-            check_gl_errors!(cx);
62
+        program.add_attribute(CStr::from_bytes_with_nul(b"position\0").unwrap(), 2, 8, 0);
63
+        program.add_attribute(CStr::from_bytes_with_nul(b"tex_coord\0").unwrap(), 2, 8, 2);
64
+        program.add_attribute(CStr::from_bytes_with_nul(b"tex_minmax\0").unwrap(), 4, 8, 4);
65
+        check_gl_errors!(cx);
71 66
 
72
-            program.before_render();
67
+        program.before_render();
73 68
 
74
-            let mut map_view = MapView::new(f64::from(initial_size.0), f64::from(initial_size.1), tile_size);
69
+        let mut map_view = MapView::new(f64::from(initial_size.0), f64::from(initial_size.1), tile_size);
75 70
 
76
-            // set initial zoom
77
-            {
78
-                let min_dimension = f64::from(initial_size.0.min(initial_size.1));
79
-                let zoom = (min_dimension / f64::from(tile_size)).log2().ceil();
80
-                map_view.set_zoom(zoom);
81
-            }
71
+        // set initial zoom
72
+        {
73
+            let min_dimension = f64::from(initial_size.0.min(initial_size.1));
74
+            let zoom = (min_dimension / f64::from(tile_size)).log2().ceil();
75
+            map_view.set_zoom(zoom);
76
+        }
82 77
 
83
-            MapViewGl {
84
-                cx: cx,
85
-                program: program,
86
-                buf: buf,
87
-                viewport_size: initial_size,
88
-                map_view: map_view,
89
-                tile_cache: TileCache::new(move |_tile| update_func(), use_network),
90
-                tile_atlas: TileAtlas::new(tex, 256, use_async),
91
-            }
78
+        MapViewGl {
79
+            cx: cx,
80
+            program: program,
81
+            buf: buf,
82
+            viewport_size: initial_size,
83
+            map_view: map_view,
84
+            tile_cache: TileCache::new(move |_tile| update_func(), use_network),
85
+            tile_atlas: TileAtlas::new(tex, 256, use_async),
92 86
         }
93 87
     }
94 88
 
95 89
     pub fn set_viewport_size(&mut self, width: u32, height: u32) {
96 90
         self.viewport_size = (width, height);
97 91
         self.map_view.set_size(f64::from(width), f64::from(height));
98
-        unsafe {
99
-            self.cx.gl.Viewport(
100
-                0,
101
-                0,
102
-                width as context::gl::types::GLsizei,
103
-                height as context::gl::types::GLsizei);
104
-        }
92
+        self.cx.set_viewport(0, 0, width, height);
105 93
     }
106 94
 
107 95
     pub fn increase_atlas_size(&mut self) -> Result<(), ()> {

+ 126
- 131
src/program.rs View File

@@ -1,5 +1,6 @@
1 1
 use ::context;
2 2
 use context::Context;
3
+use std::error::Error;
3 4
 use std::ffi::CStr;
4 5
 use std::fs::File;
5 6
 use std::io::BufReader;
@@ -8,6 +9,7 @@ use std::mem;
8 9
 use std::path::Path;
9 10
 use texture::{Texture, TextureId};
10 11
 
12
+
11 13
 #[derive(Clone, Debug)]
12 14
 pub struct Program<'a> {
13 15
     cx: &'a ::context::Context,
@@ -24,110 +26,118 @@ pub struct ProgramId {
24 26
 }
25 27
 
26 28
 impl<'a> Program<'a> {
27
-    pub unsafe fn from_paths<P: AsRef<Path>>(cx: &'a Context, vert_path: P, frag_path: P) -> Program<'a> {
29
+    pub fn from_paths<P: AsRef<Path>>(cx: &'a Context, vert_path: P, frag_path: P) -> Result<Program<'a>, String> {
28 30
         let vert_src = {
29
-            let file = File::open(&vert_path).unwrap();
31
+            let file = File::open(&vert_path)
32
+                .map_err(|e| e.description().to_string())?;
30 33
             let mut reader = BufReader::new(file);
31 34
             let mut buf: Vec<u8> = vec![];
32
-            reader.read_to_end(&mut buf).unwrap();
35
+            reader.read_to_end(&mut buf)
36
+                .map_err(|e| e.description().to_string())?;
33 37
             buf
34 38
         };
35 39
 
36 40
         let frag_src = {
37
-            let file = File::open(&frag_path).unwrap();
41
+            let file = File::open(&frag_path)
42
+                .map_err(|e| e.description().to_string())?;
38 43
             let mut reader = BufReader::new(file);
39 44
             let mut buf: Vec<u8> = vec![];
40
-            reader.read_to_end(&mut buf).unwrap();
45
+            reader.read_to_end(&mut buf)
46
+                .map_err(|e| e.description().to_string())?;
41 47
             buf
42 48
         };
43 49
 
44 50
         Self::new(cx, &vert_src, &frag_src)
45 51
     }
46 52
 
47
-    pub unsafe fn new(cx: &'a Context, vert_src: &[u8], frag_src: &[u8]) -> Program<'a> {
48
-        let vert_obj = {
49
-            let vert_obj = cx.gl.CreateShader(context::gl::VERTEX_SHADER);
50
-            let vert_len = vert_src.len() as i32;
51
-            cx.gl.ShaderSource(
52
-                vert_obj,
53
-                1,
54
-                [vert_src.as_ptr() as *const _].as_ptr(),
55
-                &vert_len as *const _);
56
-            cx.gl.CompileShader(vert_obj);
57
-            check_compile_errors(cx, vert_obj);
58
-            check_gl_errors!(cx);
59
-            vert_obj
60
-        };
61
-
62
-        let frag_obj = {
63
-            let frag_obj = cx.gl.CreateShader(context::gl::FRAGMENT_SHADER);
64
-            let frag_len = frag_src.len() as i32;
65
-            cx.gl.ShaderSource(
66
-                frag_obj,
67
-                1,
68
-                [frag_src.as_ptr() as *const _].as_ptr(),
69
-                &frag_len as *const _);
70
-            cx.gl.CompileShader(frag_obj);
71
-            check_compile_errors(cx, frag_obj);
72
-            check_gl_errors!(cx);
73
-            frag_obj
74
-        };
75
-
76
-        let program_obj = {
77
-            let prog = cx.gl.CreateProgram();
78
-            cx.gl.AttachShader(prog, vert_obj);
79
-            cx.gl.AttachShader(prog, frag_obj);
80
-            cx.gl.LinkProgram(prog);
81
-            check_link_errors(cx, prog);
82
-
83
-            cx.gl.UseProgram(prog);
84
-            check_gl_errors!(cx);
85
-            prog
86
-        };
87
-
88
-        Program {
89
-            cx: cx,
90
-            vert_obj: vert_obj,
91
-            frag_obj: frag_obj,
92
-            program_obj: program_obj,
93
-            tex_ids: vec![],
94
-            tex_locations: vec![],
53
+    pub fn new(cx: &'a Context, vert_src: &[u8], frag_src: &[u8]) -> Result<Program<'a>, String> {
54
+        unsafe {
55
+            let vert_obj = {
56
+                let vert_obj = cx.gl.CreateShader(context::gl::VERTEX_SHADER);
57
+                let vert_len = vert_src.len() as i32;
58
+                cx.gl.ShaderSource(
59
+                    vert_obj,
60
+                    1,
61
+                    [vert_src.as_ptr() as *const _].as_ptr(),
62
+                    &vert_len as *const _);
63
+                cx.gl.CompileShader(vert_obj);
64
+                check_compile_errors(cx, vert_obj)?;
65
+                check_gl_errors!(cx);
66
+                vert_obj
67
+            };
68
+
69
+            let frag_obj = {
70
+                let frag_obj = cx.gl.CreateShader(context::gl::FRAGMENT_SHADER);
71
+                let frag_len = frag_src.len() as i32;
72
+                cx.gl.ShaderSource(
73
+                    frag_obj,
74
+                    1,
75
+                    [frag_src.as_ptr() as *const _].as_ptr(),
76
+                    &frag_len as *const _);
77
+                cx.gl.CompileShader(frag_obj);
78
+                check_compile_errors(cx, frag_obj)?;
79
+                check_gl_errors!(cx);
80
+                frag_obj
81
+            };
82
+
83
+            let program_obj = {
84
+                let prog = cx.gl.CreateProgram();
85
+                cx.gl.AttachShader(prog, vert_obj);
86
+                cx.gl.AttachShader(prog, frag_obj);
87
+                cx.gl.LinkProgram(prog);
88
+                check_link_errors(cx, prog)?;
89
+
90
+                cx.gl.UseProgram(prog);
91
+                check_gl_errors!(cx);
92
+                prog
93
+            };
94
+
95
+            Ok(Program {
96
+                cx: cx,
97
+                vert_obj: vert_obj,
98
+                frag_obj: frag_obj,
99
+                program_obj: program_obj,
100
+                tex_ids: vec![],
101
+                tex_locations: vec![],
102
+            })
95 103
         }
96 104
     }
97 105
 
98
-    pub unsafe fn add_texture(&mut self, texture: &Texture, uniform_name: &CStr) {
106
+    pub fn add_texture(&mut self, texture: &Texture, uniform_name: &CStr) {
99 107
         //TODO store reference to texture
100
-        let tex_loc = self.cx.gl.GetUniformLocation(self.program_obj, uniform_name.as_ptr() as *const _);
101
-        check_gl_errors!(self.cx);
102
-
103
-        self.tex_ids.push(texture.id());
104
-        self.tex_locations.push(tex_loc);
108
+        unsafe {
109
+            let tex_loc = self.cx.gl.GetUniformLocation(self.program_obj, uniform_name.as_ptr() as *const _);
110
+            check_gl_errors!(self.cx);
105 111
 
112
+            self.tex_ids.push(texture.id());
113
+            self.tex_locations.push(tex_loc);
114
+        }
106 115
     }
107 116
 
108
-    pub unsafe fn add_attribute(&mut self, name: &CStr, number_components: u32, stride: usize, offset: usize) {
109
-        let attrib_id = self.cx.gl.GetAttribLocation(self.program_obj, name.as_ptr() as *const _);
110
-        check_gl_errors!(self.cx);
111
-        self.cx.gl.VertexAttribPointer(
112
-            attrib_id as u32,
113
-            number_components as i32, // size
114
-            context::gl::FLOAT, // type
115
-            0, // normalized
116
-            (stride * mem::size_of::<f32>()) as context::gl::types::GLsizei,
117
-            (offset * mem::size_of::<f32>()) as *const () as *const _);
118
-        check_gl_errors!(self.cx);
119
-        self.cx.gl.EnableVertexAttribArray(attrib_id as u32);
117
+    pub fn add_attribute(&mut self, name: &CStr, number_components: u32, stride: usize, offset: usize) {
118
+        unsafe {
119
+            let attrib_id = self.cx.gl.GetAttribLocation(self.program_obj, name.as_ptr() as *const _);
120
+            self.cx.gl.VertexAttribPointer(
121
+                attrib_id as u32,
122
+                number_components as i32, // size
123
+                context::gl::FLOAT, // type
124
+                0, // normalized
125
+                (stride * mem::size_of::<f32>()) as context::gl::types::GLsizei,
126
+                (offset * mem::size_of::<f32>()) as *const () as *const _);
127
+            self.cx.gl.EnableVertexAttribArray(attrib_id as u32);
128
+        }
120 129
         check_gl_errors!(self.cx);
121 130
     }
122 131
 
123
-    pub unsafe fn before_render(&self) {
124
-        check_gl_errors!(self.cx);
125
-        //self.cx.gl.UseProgram(self.program_obj);
126
-        //TODO check max texture number
127
-        for (i, (tex_id, &tex_loc)) in self.tex_ids.iter().zip(&self.tex_locations).enumerate() {
128
-            self.cx.gl.ActiveTexture(context::gl::TEXTURE0 + i as u32);
129
-            self.cx.gl.BindTexture(context::gl::TEXTURE_2D, tex_id.id);
130
-            self.cx.gl.Uniform1i(tex_loc, i as i32);
132
+    pub fn before_render(&self) {
133
+        unsafe {
134
+            //self.cx.gl.UseProgram(self.program_obj);
135
+            //TODO check max texture number
136
+            for (i, (tex_id, &tex_loc)) in self.tex_ids.iter().zip(&self.tex_locations).enumerate() {
137
+                self.cx.gl.ActiveTexture(context::gl::TEXTURE0 + i as u32);
138
+                self.cx.gl.BindTexture(context::gl::TEXTURE_2D, tex_id.id);
139
+                self.cx.gl.Uniform1i(tex_loc, i as i32);
140
+            }
131 141
         }
132 142
     }
133 143
 
@@ -138,66 +148,51 @@ impl<'a> Program<'a> {
138 148
     }
139 149
 }
140 150
 
141
-unsafe fn check_link_errors(cx: &Context, program_obj: u32)
142
-{
143
-    let mut link_success: i32 = mem::uninitialized();
144
-
145
-    cx.gl.GetProgramiv(program_obj, context::gl::LINK_STATUS, &mut link_success);
146
-
147
-    if link_success == 0 {
148
-
149
-        match cx.gl.GetError() {
150
-            context::gl::NO_ERROR => (),
151
-            context::gl::INVALID_VALUE => {
152
-                error!("invalid value");
153
-                return;
154
-            },
155
-            context::gl::INVALID_OPERATION => {
156
-                error!("invalid operation");
157
-                return;
158
-            },
159
-            _ => {
160
-                error!("unknown error");
161
-                return;
162
-            }
163
-        };
164
-
165
-        let mut error_log_size: i32 = mem::uninitialized();
151
+fn check_link_errors(cx: &Context, program_obj: u32) -> Result<(), String> {
152
+    unsafe {
153
+        let mut link_success: i32 = mem::uninitialized();
166 154
 
167
-        cx.gl.GetProgramiv(program_obj, context::gl::INFO_LOG_LENGTH, &mut error_log_size);
155
+        cx.gl.GetProgramiv(program_obj, context::gl::LINK_STATUS, &mut link_success);
168 156
 
169
-        let mut error_log: Vec<u8> = Vec::with_capacity(error_log_size as usize);
157
+        if link_success == 0 {
158
+            let mut error_log_size: i32 = mem::uninitialized();
159
+            cx.gl.GetProgramiv(program_obj, context::gl::INFO_LOG_LENGTH, &mut error_log_size);
170 160
 
171
-        cx.gl.GetProgramInfoLog(program_obj, error_log_size, &mut error_log_size,
172
-                             error_log.as_mut_ptr() as *mut context::gl::types::GLchar);
161
+            let mut error_log: Vec<u8> = Vec::with_capacity(error_log_size as usize);
162
+            cx.gl.GetProgramInfoLog(program_obj, error_log_size, &mut error_log_size,
163
+                                    error_log.as_mut_ptr() as *mut context::gl::types::GLchar);
173 164
 
174
-        error_log.set_len(error_log_size as usize);
165
+            error_log.set_len(error_log_size as usize);
175 166
 
176
-        let msg = String::from_utf8(error_log).unwrap();
177
-        error!("{}", msg);
167
+            Err(String::from_utf8_lossy(&error_log).into())
168
+        } else {
169
+            Ok(())
170
+        }
178 171
     }
179 172
 }
180 173
 
181
-unsafe fn check_compile_errors(cx: &Context, shader_obj: u32) {
182
-    // checking compilation success by reading a flag on the shader
183
-    let compilation_success = {
184
-        let mut compilation_success: i32 = mem::uninitialized();
185
-        cx.gl.GetShaderiv(shader_obj, context::gl::COMPILE_STATUS, &mut compilation_success);
186
-        compilation_success
187
-    };
188
-
189
-    if compilation_success != 1 {
190
-        // compilation error
191
-        let mut error_log_size: i32 = mem::uninitialized();
192
-        cx.gl.GetShaderiv(shader_obj, context::gl::INFO_LOG_LENGTH, &mut error_log_size);
193
-        let mut error_log: Vec<u8> = Vec::with_capacity(error_log_size as usize);
194
-
195
-        cx.gl.GetShaderInfoLog(shader_obj, error_log_size, &mut error_log_size,
196
-                                 error_log.as_mut_ptr() as *mut _);
197
-        error_log.set_len(error_log_size as usize);
198
-
199
-        if let Ok(msg) = String::from_utf8(error_log) {
200
-            error!("{}", msg);
174
+fn check_compile_errors(cx: &Context, shader_obj: u32) -> Result<(), String> {
175
+    unsafe {
176
+        // checking compilation success by reading a flag on the shader
177
+        let compilation_success = {
178
+            let mut compilation_success: i32 = mem::uninitialized();
179
+            cx.gl.GetShaderiv(shader_obj, context::gl::COMPILE_STATUS, &mut compilation_success);
180
+            compilation_success
181
+        };
182
+
183
+        if compilation_success != 1 {
184
+            // compilation error
185
+            let mut error_log_size: i32 = mem::uninitialized();
186
+            cx.gl.GetShaderiv(shader_obj, context::gl::INFO_LOG_LENGTH, &mut error_log_size);
187
+            let mut error_log: Vec<u8> = Vec::with_capacity(error_log_size as usize);
188
+
189
+            cx.gl.GetShaderInfoLog(shader_obj, error_log_size, &mut error_log_size,
190
+                                     error_log.as_mut_ptr() as *mut _);
191
+            error_log.set_len(error_log_size as usize);
192
+
193
+            Err(String::from_utf8_lossy(&error_log).into())
194
+        } else {
195
+            Ok(())
201 196
         }
202 197
     }
203 198
 }