Do GL error checks

This commit is contained in:
Patrick Walton 2019-03-04 19:43:13 -08:00
parent ae450b063e
commit 8b4c06fe2a
2 changed files with 130 additions and 143 deletions

View File

@ -13,55 +13,6 @@
use crate::GRIDLINE_COUNT; use crate::GRIDLINE_COUNT;
use pathfinder_gpu::{BufferTarget, BufferUploadMode, Device, Resources, VertexAttrType}; use pathfinder_gpu::{BufferTarget, BufferUploadMode, Device, Resources, VertexAttrType};
/*
pub struct DemoDevice {
#[allow(dead_code)]
device: Device,
}
impl DemoDevice {
pub fn new(device: Device) -> DemoDevice {
DemoDevice { device }
}
pub fn clear(&self, color: ColorU) {
let color = color.to_f32();
unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
gl::ClearColor(color.r(), color.g(), color.b(), color.a());
gl::ClearDepth(1.0);
gl::ClearStencil(0);
gl::DepthMask(gl::TRUE);
gl::StencilMask(!0);
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
}
}
pub fn readback_pixels(&self, width: u32, height: u32) -> Vec<u8> {
let mut pixels = vec![0; width as usize * height as usize * 4];
unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
gl::ReadPixels(0, 0,
width as GLsizei, height as GLsizei,
gl::RGBA,
gl::UNSIGNED_BYTE,
pixels.as_mut_ptr() as *mut GLvoid);
}
// Flip right-side-up.
let stride = width as usize * 4;
for y in 0..(height as usize / 2) {
let (index_a, index_b) = (y * stride, (height as usize - y - 1) * stride);
for offset in 0..stride {
pixels.swap(index_a + offset, index_b + offset);
}
}
pixels
}
}
*/
pub struct GroundProgram<D> where D: Device { pub struct GroundProgram<D> where D: Device {
pub program: D::Program, pub program: D::Program,
pub transform_uniform: D::Uniform, pub transform_uniform: D::Uniform,

View File

@ -30,10 +30,14 @@ impl GLDevice {
fn set_texture_parameters(&self, texture: &GLTexture) { fn set_texture_parameters(&self, texture: &GLTexture) {
self.bind_texture(texture, 0); self.bind_texture(texture, 0);
unsafe { unsafe {
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint); gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint); ck();
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint); gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint); ck();
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint); gl::TexParameteri(gl::TEXTURE_2D,
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint); gl::TEXTURE_WRAP_S,
gl::CLAMP_TO_EDGE as GLint); ck();
gl::TexParameteri(gl::TEXTURE_2D,
gl::TEXTURE_WRAP_T,
gl::CLAMP_TO_EDGE as GLint); ck();
} }
} }
@ -41,43 +45,52 @@ impl GLDevice {
unsafe { unsafe {
// Set blend. // Set blend.
match render_state.blend { match render_state.blend {
BlendState::Off => gl::Disable(gl::BLEND), BlendState::Off => {
gl::Disable(gl::BLEND); ck();
}
BlendState::RGBOneAlphaOneMinusSrcAlpha => { BlendState::RGBOneAlphaOneMinusSrcAlpha => {
gl::BlendFuncSeparate(gl::ONE, gl::ONE_MINUS_SRC_ALPHA, gl::ONE, gl::ONE); gl::BlendFuncSeparate(gl::ONE,
gl::Enable(gl::BLEND); gl::ONE_MINUS_SRC_ALPHA,
gl::ONE,
gl::ONE); ck();
gl::Enable(gl::BLEND); ck();
} }
BlendState::RGBOneAlphaOne => { BlendState::RGBOneAlphaOne => {
gl::BlendFunc(gl::ONE, gl::ONE); gl::BlendFunc(gl::ONE, gl::ONE); ck();
gl::Enable(gl::BLEND); gl::Enable(gl::BLEND); ck();
} }
} }
// Set depth. // Set depth.
match render_state.depth { match render_state.depth {
None => gl::Disable(gl::DEPTH_TEST), None => {
gl::Disable(gl::DEPTH_TEST); ck();
}
Some(ref state) => { Some(ref state) => {
gl::Enable(gl::DEPTH_TEST); gl::Enable(gl::DEPTH_TEST); ck();
gl::DepthFunc(state.func.to_gl_depth_func()); gl::DepthFunc(state.func.to_gl_depth_func()); ck();
gl::DepthMask(state.write as GLboolean); gl::DepthMask(state.write as GLboolean); ck();
} }
} }
// Set stencil. // Set stencil.
match render_state.stencil { match render_state.stencil {
None => gl::Disable(gl::STENCIL_TEST), None => {
gl::Disable(gl::STENCIL_TEST); ck();
}
Some(ref state) => { Some(ref state) => {
gl::StencilFunc(state.func.to_gl_stencil_func(), gl::StencilFunc(state.func.to_gl_stencil_func(),
state.reference as GLint, state.reference as GLint,
state.mask); state.mask); ck();
let pass_action = if state.pass_replace { gl::REPLACE } else { gl::KEEP }; let pass_action = if state.pass_replace { gl::REPLACE } else { gl::KEEP };
gl::StencilOp(gl::KEEP, gl::KEEP, pass_action); gl::StencilOp(gl::KEEP, gl::KEEP, pass_action); ck();
gl::Enable(gl::STENCIL_TEST); gl::Enable(gl::STENCIL_TEST); ck();
} }
} }
// Set color mask. // Set color mask.
let color_mask = render_state.color_mask as GLboolean; let color_mask = render_state.color_mask as GLboolean;
gl::ColorMask(color_mask, color_mask, color_mask, color_mask); gl::ColorMask(color_mask, color_mask, color_mask, color_mask); ck();
} }
} }
@ -86,19 +99,19 @@ impl GLDevice {
match render_state.blend { match render_state.blend {
BlendState::Off => {} BlendState::Off => {}
BlendState::RGBOneAlphaOneMinusSrcAlpha | BlendState::RGBOneAlphaOne => { BlendState::RGBOneAlphaOneMinusSrcAlpha | BlendState::RGBOneAlphaOne => {
gl::Disable(gl::BLEND); gl::Disable(gl::BLEND); ck();
} }
} }
if render_state.depth.is_some() { if render_state.depth.is_some() {
gl::Disable(gl::DEPTH_TEST); gl::Disable(gl::DEPTH_TEST); ck();
} }
if render_state.stencil.is_some() { if render_state.stencil.is_some() {
gl::Disable(gl::STENCIL_TEST); gl::Disable(gl::STENCIL_TEST); ck();
} }
gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); ck();
} }
} }
} }
@ -131,7 +144,7 @@ impl Device for GLDevice {
let mut texture = GLTexture { gl_texture: 0, size }; let mut texture = GLTexture { gl_texture: 0, size };
unsafe { unsafe {
gl::GenTextures(1, &mut texture.gl_texture); gl::GenTextures(1, &mut texture.gl_texture); ck();
self.bind_texture(&texture, 0); self.bind_texture(&texture, 0);
gl::TexImage2D(gl::TEXTURE_2D, gl::TexImage2D(gl::TEXTURE_2D,
0, 0,
@ -141,7 +154,7 @@ impl Device for GLDevice {
0, 0,
gl_format, gl_format,
gl_type, gl_type,
ptr::null()); ptr::null()); ck();
} }
self.set_texture_parameters(&texture); self.set_texture_parameters(&texture);
@ -153,7 +166,7 @@ impl Device for GLDevice {
let mut texture = GLTexture { gl_texture: 0, size }; let mut texture = GLTexture { gl_texture: 0, size };
unsafe { unsafe {
gl::GenTextures(1, &mut texture.gl_texture); gl::GenTextures(1, &mut texture.gl_texture); ck();
self.bind_texture(&texture, 0); self.bind_texture(&texture, 0);
gl::TexImage2D(gl::TEXTURE_2D, gl::TexImage2D(gl::TEXTURE_2D,
0, 0,
@ -163,7 +176,7 @@ impl Device for GLDevice {
0, 0,
gl::RED, gl::RED,
gl::UNSIGNED_BYTE, gl::UNSIGNED_BYTE,
data.as_ptr() as *const GLvoid); data.as_ptr() as *const GLvoid); ck();
} }
self.set_texture_parameters(&texture); self.set_texture_parameters(&texture);
@ -177,23 +190,23 @@ impl Device for GLDevice {
}; };
unsafe { unsafe {
let gl_shader = gl::CreateShader(gl_shader_kind); let gl_shader = gl::CreateShader(gl_shader_kind); ck();
gl::ShaderSource(gl_shader, gl::ShaderSource(gl_shader,
1, 1,
[source.as_ptr() as *const GLchar].as_ptr(), [source.as_ptr() as *const GLchar].as_ptr(),
[source.len() as GLint].as_ptr()); [source.len() as GLint].as_ptr()); ck();
gl::CompileShader(gl_shader); gl::CompileShader(gl_shader); ck();
let mut compile_status = 0; let mut compile_status = 0;
gl::GetShaderiv(gl_shader, gl::COMPILE_STATUS, &mut compile_status); gl::GetShaderiv(gl_shader, gl::COMPILE_STATUS, &mut compile_status); ck();
if compile_status != gl::TRUE as GLint { if compile_status != gl::TRUE as GLint {
let mut info_log_length = 0; let mut info_log_length = 0;
gl::GetShaderiv(gl_shader, gl::INFO_LOG_LENGTH, &mut info_log_length); gl::GetShaderiv(gl_shader, gl::INFO_LOG_LENGTH, &mut info_log_length); ck();
let mut info_log = vec![0; info_log_length as usize]; let mut info_log = vec![0; info_log_length as usize];
gl::GetShaderInfoLog(gl_shader, gl::GetShaderInfoLog(gl_shader,
info_log.len() as GLint, info_log.len() as GLint,
ptr::null_mut(), ptr::null_mut(),
info_log.as_mut_ptr() as *mut GLchar); info_log.as_mut_ptr() as *mut GLchar); ck();
eprintln!("Shader info log:\n{}", String::from_utf8_lossy(&info_log)); eprintln!("Shader info log:\n{}", String::from_utf8_lossy(&info_log));
panic!("{:?} shader '{}' compilation failed", kind, name); panic!("{:?} shader '{}' compilation failed", kind, name);
} }
@ -209,21 +222,21 @@ impl Device for GLDevice {
-> GLProgram { -> GLProgram {
let gl_program; let gl_program;
unsafe { unsafe {
gl_program = gl::CreateProgram(); gl_program = gl::CreateProgram(); ck();
gl::AttachShader(gl_program, vertex_shader.gl_shader); gl::AttachShader(gl_program, vertex_shader.gl_shader); ck();
gl::AttachShader(gl_program, fragment_shader.gl_shader); gl::AttachShader(gl_program, fragment_shader.gl_shader); ck();
gl::LinkProgram(gl_program); gl::LinkProgram(gl_program); ck();
let mut link_status = 0; let mut link_status = 0;
gl::GetProgramiv(gl_program, gl::LINK_STATUS, &mut link_status); gl::GetProgramiv(gl_program, gl::LINK_STATUS, &mut link_status); ck();
if link_status != gl::TRUE as GLint { if link_status != gl::TRUE as GLint {
let mut info_log_length = 0; let mut info_log_length = 0;
gl::GetProgramiv(gl_program, gl::INFO_LOG_LENGTH, &mut info_log_length); gl::GetProgramiv(gl_program, gl::INFO_LOG_LENGTH, &mut info_log_length); ck();
let mut info_log = vec![0; info_log_length as usize]; let mut info_log = vec![0; info_log_length as usize];
gl::GetProgramInfoLog(gl_program, gl::GetProgramInfoLog(gl_program,
info_log.len() as GLint, info_log.len() as GLint,
ptr::null_mut(), ptr::null_mut(),
info_log.as_mut_ptr() as *mut GLchar); info_log.as_mut_ptr() as *mut GLchar); ck();
eprintln!("Program info log:\n{}", String::from_utf8_lossy(&info_log)); eprintln!("Program info log:\n{}", String::from_utf8_lossy(&info_log));
panic!("Program '{}' linking failed", name); panic!("Program '{}' linking failed", name);
} }
@ -236,7 +249,7 @@ impl Device for GLDevice {
fn create_vertex_array(&self) -> GLVertexArray { fn create_vertex_array(&self) -> GLVertexArray {
unsafe { unsafe {
let mut array = GLVertexArray { gl_vertex_array: 0 }; let mut array = GLVertexArray { gl_vertex_array: 0 };
gl::GenVertexArrays(1, &mut array.gl_vertex_array); gl::GenVertexArrays(1, &mut array.gl_vertex_array); ck();
array array
} }
} }
@ -245,7 +258,7 @@ impl Device for GLDevice {
let name = CString::new(format!("a{}", name)).unwrap(); let name = CString::new(format!("a{}", name)).unwrap();
let attr = unsafe { let attr = unsafe {
gl::GetAttribLocation(program.gl_program, name.as_ptr() as *const GLchar) as GLuint gl::GetAttribLocation(program.gl_program, name.as_ptr() as *const GLchar) as GLuint
}; }; ck();
GLVertexAttr { attr } GLVertexAttr { attr }
} }
@ -253,13 +266,13 @@ impl Device for GLDevice {
let name = CString::new(format!("u{}", name)).unwrap(); let name = CString::new(format!("u{}", name)).unwrap();
let location = unsafe { let location = unsafe {
gl::GetUniformLocation(program.gl_program, name.as_ptr() as *const GLchar) gl::GetUniformLocation(program.gl_program, name.as_ptr() as *const GLchar)
}; }; ck();
GLUniform { location } GLUniform { location }
} }
fn use_program(&self, program: &Self::Program) { fn use_program(&self, program: &Self::Program) {
unsafe { unsafe {
gl::UseProgram(program.gl_program); gl::UseProgram(program.gl_program); ck();
} }
} }
@ -277,9 +290,9 @@ impl Device for GLDevice {
attr_type.to_gl_type(), attr_type.to_gl_type(),
if normalized { gl::TRUE } else { gl::FALSE }, if normalized { gl::TRUE } else { gl::FALSE },
stride as GLint, stride as GLint,
offset as *const GLvoid); offset as *const GLvoid); ck();
gl::VertexAttribDivisor(attr.attr, divisor); gl::VertexAttribDivisor(attr.attr, divisor); ck();
gl::EnableVertexAttribArray(attr.attr); gl::EnableVertexAttribArray(attr.attr); ck();
} }
} }
@ -295,20 +308,24 @@ impl Device for GLDevice {
size as GLint, size as GLint,
attr_type.to_gl_type(), attr_type.to_gl_type(),
stride as GLint, stride as GLint,
offset as *const GLvoid); offset as *const GLvoid); ck();
gl::VertexAttribDivisor(attr.attr, divisor); gl::VertexAttribDivisor(attr.attr, divisor); ck();
gl::EnableVertexAttribArray(attr.attr); gl::EnableVertexAttribArray(attr.attr); ck();
} }
} }
fn set_uniform(&self, uniform: &Self::Uniform, data: UniformData) { fn set_uniform(&self, uniform: &Self::Uniform, data: UniformData) {
unsafe { unsafe {
match data { match data {
UniformData::Vec2(data) => gl::Uniform2f(uniform.location, data.x(), data.y()), UniformData::Vec2(data) => {
UniformData::Vec4(data) => { gl::Uniform2f(uniform.location, data.x(), data.y()); ck();
gl::Uniform4f(uniform.location, data.x(), data.y(), data.z(), data.w()); }
UniformData::Vec4(data) => {
gl::Uniform4f(uniform.location, data.x(), data.y(), data.z(), data.w()); ck();
}
UniformData::TextureUnit(unit) => {
gl::Uniform1i(uniform.location, unit as GLint); ck();
} }
UniformData::TextureUnit(unit) => gl::Uniform1i(uniform.location, unit as GLint),
} }
} }
} }
@ -316,15 +333,15 @@ impl Device for GLDevice {
fn create_framebuffer(&self, texture: GLTexture) -> GLFramebuffer { fn create_framebuffer(&self, texture: GLTexture) -> GLFramebuffer {
let mut gl_framebuffer = 0; let mut gl_framebuffer = 0;
unsafe { unsafe {
gl::GenFramebuffers(1, &mut gl_framebuffer); gl::GenFramebuffers(1, &mut gl_framebuffer); ck();
assert_eq!(gl::GetError(), gl::NO_ERROR); assert_eq!(gl::GetError(), gl::NO_ERROR);
gl::BindFramebuffer(gl::FRAMEBUFFER, gl_framebuffer); gl::BindFramebuffer(gl::FRAMEBUFFER, gl_framebuffer); ck();
self.bind_texture(&texture, 0); self.bind_texture(&texture, 0);
gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::FramebufferTexture2D(gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0, gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D, gl::TEXTURE_2D,
texture.gl_texture, texture.gl_texture,
0); 0); ck();
assert_eq!(gl::CheckFramebufferStatus(gl::FRAMEBUFFER), gl::FRAMEBUFFER_COMPLETE); assert_eq!(gl::CheckFramebufferStatus(gl::FRAMEBUFFER), gl::FRAMEBUFFER_COMPLETE);
} }
@ -334,7 +351,7 @@ impl Device for GLDevice {
fn create_buffer(&self) -> GLBuffer { fn create_buffer(&self) -> GLBuffer {
unsafe { unsafe {
let mut gl_buffer = 0; let mut gl_buffer = 0;
gl::GenBuffers(1, &mut gl_buffer); gl::GenBuffers(1, &mut gl_buffer); ck();
GLBuffer { gl_buffer } GLBuffer { gl_buffer }
} }
} }
@ -353,11 +370,11 @@ impl Device for GLDevice {
BufferUploadMode::Dynamic => gl::DYNAMIC_DRAW, BufferUploadMode::Dynamic => gl::DYNAMIC_DRAW,
}; };
unsafe { unsafe {
gl::BindBuffer(target, buffer.gl_buffer); gl::BindBuffer(target, buffer.gl_buffer); ck();
gl::BufferData(target, gl::BufferData(target,
(data.len() * mem::size_of::<T>()) as GLsizeiptr, (data.len() * mem::size_of::<T>()) as GLsizeiptr,
data.as_ptr() as *const GLvoid, data.as_ptr() as *const GLvoid,
mode); mode); ck();
} }
} }
@ -383,7 +400,7 @@ impl Device for GLDevice {
0, 0,
gl::RGBA, gl::RGBA,
gl::UNSIGNED_BYTE, gl::UNSIGNED_BYTE,
data.as_ptr() as *const GLvoid); data.as_ptr() as *const GLvoid); ck();
} }
self.set_texture_parameters(texture); self.set_texture_parameters(texture);
@ -392,14 +409,14 @@ impl Device for GLDevice {
fn read_pixels_from_default_framebuffer(&self, size: Point2DI32) -> Vec<u8> { fn read_pixels_from_default_framebuffer(&self, size: Point2DI32) -> Vec<u8> {
let mut pixels = vec![0; size.x() as usize * size.y() as usize * 4]; let mut pixels = vec![0; size.x() as usize * size.y() as usize * 4];
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, 0); gl::BindFramebuffer(gl::FRAMEBUFFER, 0); ck();
gl::ReadPixels(0, gl::ReadPixels(0,
0, 0,
size.x() as GLsizei, size.x() as GLsizei,
size.y() as GLsizei, size.y() as GLsizei,
gl::RGBA, gl::RGBA,
gl::UNSIGNED_BYTE, gl::UNSIGNED_BYTE,
pixels.as_mut_ptr() as *mut GLvoid); pixels.as_mut_ptr() as *mut GLvoid); ck();
} }
// Flip right-side-up. // Flip right-side-up.
@ -419,19 +436,19 @@ impl Device for GLDevice {
unsafe { unsafe {
let mut flags = 0; let mut flags = 0;
if let Some(color) = color { if let Some(color) = color {
gl::ClearColor(color.x(), color.y(), color.z(), color.w()); gl::ClearColor(color.x(), color.y(), color.z(), color.w()); ck();
flags |= gl::COLOR_BUFFER_BIT; flags |= gl::COLOR_BUFFER_BIT;
} }
if let Some(depth) = depth { if let Some(depth) = depth {
gl::ClearDepth(depth as GLdouble); gl::ClearDepth(depth as GLdouble); ck();
flags |= gl::DEPTH_BUFFER_BIT; flags |= gl::DEPTH_BUFFER_BIT;
} }
if let Some(stencil) = stencil { if let Some(stencil) = stencil {
gl::ClearStencil(stencil as GLint); gl::ClearStencil(stencil as GLint); ck();
flags |= gl::STENCIL_BUFFER_BIT; flags |= gl::STENCIL_BUFFER_BIT;
} }
if flags != 0 { if flags != 0 {
gl::Clear(flags); gl::Clear(flags); ck();
} }
} }
} }
@ -439,7 +456,7 @@ impl Device for GLDevice {
fn draw_arrays(&self, primitive: Primitive, index_count: u32, render_state: &RenderState) { fn draw_arrays(&self, primitive: Primitive, index_count: u32, render_state: &RenderState) {
self.set_render_state(render_state); self.set_render_state(render_state);
unsafe { unsafe {
gl::DrawArrays(primitive.to_gl_primitive(), 0, index_count as GLsizei); gl::DrawArrays(primitive.to_gl_primitive(), 0, index_count as GLsizei); ck();
} }
self.reset_render_state(render_state); self.reset_render_state(render_state);
} }
@ -450,7 +467,7 @@ impl Device for GLDevice {
gl::DrawElements(primitive.to_gl_primitive(), gl::DrawElements(primitive.to_gl_primitive(),
index_count as GLsizei, index_count as GLsizei,
gl::UNSIGNED_INT, gl::UNSIGNED_INT,
ptr::null()); ptr::null()); ck();
} }
self.reset_render_state(render_state); self.reset_render_state(render_state);
} }
@ -465,7 +482,7 @@ impl Device for GLDevice {
gl::DrawArraysInstanced(primitive.to_gl_primitive(), gl::DrawArraysInstanced(primitive.to_gl_primitive(),
0, 0,
index_count as GLsizei, index_count as GLsizei,
instance_count as GLsizei); instance_count as GLsizei); ck();
} }
self.reset_render_state(render_state); self.reset_render_state(render_state);
} }
@ -474,7 +491,7 @@ impl Device for GLDevice {
fn create_timer_query(&self) -> GLTimerQuery { fn create_timer_query(&self) -> GLTimerQuery {
let mut query = GLTimerQuery { gl_query: 0 }; let mut query = GLTimerQuery { gl_query: 0 };
unsafe { unsafe {
gl::GenQueries(1, &mut query.gl_query); gl::GenQueries(1, &mut query.gl_query); ck();
} }
query query
} }
@ -482,14 +499,14 @@ impl Device for GLDevice {
#[inline] #[inline]
fn begin_timer_query(&self, query: &Self::TimerQuery) { fn begin_timer_query(&self, query: &Self::TimerQuery) {
unsafe { unsafe {
gl::BeginQuery(gl::TIME_ELAPSED, query.gl_query); gl::BeginQuery(gl::TIME_ELAPSED, query.gl_query); ck();
} }
} }
#[inline] #[inline]
fn end_timer_query(&self, _: &Self::TimerQuery) { fn end_timer_query(&self, _: &Self::TimerQuery) {
unsafe { unsafe {
gl::EndQuery(gl::TIME_ELAPSED); gl::EndQuery(gl::TIME_ELAPSED); ck();
} }
} }
@ -497,7 +514,7 @@ impl Device for GLDevice {
fn timer_query_is_available(&self, query: &Self::TimerQuery) -> bool { fn timer_query_is_available(&self, query: &Self::TimerQuery) -> bool {
unsafe { unsafe {
let mut result = 0; let mut result = 0;
gl::GetQueryObjectiv(query.gl_query, gl::QUERY_RESULT_AVAILABLE, &mut result); gl::GetQueryObjectiv(query.gl_query, gl::QUERY_RESULT_AVAILABLE, &mut result); ck();
result != gl::FALSE as GLint result != gl::FALSE as GLint
} }
} }
@ -506,7 +523,7 @@ impl Device for GLDevice {
fn get_timer_query(&self, query: &Self::TimerQuery) -> Duration { fn get_timer_query(&self, query: &Self::TimerQuery) -> Duration {
unsafe { unsafe {
let mut result = 0; let mut result = 0;
gl::GetQueryObjectui64v(query.gl_query, gl::QUERY_RESULT, &mut result); gl::GetQueryObjectui64v(query.gl_query, gl::QUERY_RESULT, &mut result); ck();
Duration::from_nanos(result) Duration::from_nanos(result)
} }
} }
@ -514,38 +531,38 @@ impl Device for GLDevice {
#[inline] #[inline]
fn bind_vertex_array(&self, vertex_array: &GLVertexArray) { fn bind_vertex_array(&self, vertex_array: &GLVertexArray) {
unsafe { unsafe {
gl::BindVertexArray(vertex_array.gl_vertex_array); gl::BindVertexArray(vertex_array.gl_vertex_array); ck();
} }
} }
#[inline] #[inline]
fn bind_buffer(&self, buffer: &GLBuffer, target: BufferTarget) { fn bind_buffer(&self, buffer: &GLBuffer, target: BufferTarget) {
unsafe { unsafe {
gl::BindBuffer(target.to_gl_target(), buffer.gl_buffer); gl::BindBuffer(target.to_gl_target(), buffer.gl_buffer); ck();
} }
} }
#[inline] #[inline]
fn bind_default_framebuffer(&self, size: Point2DI32) { fn bind_default_framebuffer(&self, size: Point2DI32) {
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, 0); gl::BindFramebuffer(gl::FRAMEBUFFER, 0); ck();
gl::Viewport(0, 0, size.x(), size.y()); gl::Viewport(0, 0, size.x(), size.y()); ck();
} }
} }
#[inline] #[inline]
fn bind_framebuffer(&self, framebuffer: &GLFramebuffer) { fn bind_framebuffer(&self, framebuffer: &GLFramebuffer) {
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.gl_framebuffer); gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.gl_framebuffer); ck();
gl::Viewport(0, 0, framebuffer.texture.size.x(), framebuffer.texture.size.y()); gl::Viewport(0, 0, framebuffer.texture.size.x(), framebuffer.texture.size.y()); ck();
} }
} }
#[inline] #[inline]
fn bind_texture(&self, texture: &GLTexture, unit: u32) { fn bind_texture(&self, texture: &GLTexture, unit: u32) {
unsafe { unsafe {
gl::ActiveTexture(gl::TEXTURE0 + unit); gl::ActiveTexture(gl::TEXTURE0 + unit); ck();
gl::BindTexture(gl::TEXTURE_2D, texture.gl_texture); gl::BindTexture(gl::TEXTURE_2D, texture.gl_texture); ck();
} }
} }
} }
@ -558,7 +575,7 @@ impl Drop for GLVertexArray {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
gl::DeleteVertexArrays(1, &mut self.gl_vertex_array); gl::DeleteVertexArrays(1, &mut self.gl_vertex_array); ck();
} }
} }
} }
@ -581,9 +598,9 @@ impl GLVertexAttr {
gl_type, gl_type,
if normalized { gl::TRUE } else { gl::FALSE }, if normalized { gl::TRUE } else { gl::FALSE },
stride, stride,
offset as *const GLvoid); offset as *const GLvoid); ck();
gl::VertexAttribDivisor(self.attr, divisor); gl::VertexAttribDivisor(self.attr, divisor); ck();
gl::EnableVertexAttribArray(self.attr); gl::EnableVertexAttribArray(self.attr); ck();
} }
} }
@ -594,9 +611,13 @@ impl GLVertexAttr {
offset: usize, offset: usize,
divisor: GLuint) { divisor: GLuint) {
unsafe { unsafe {
gl::VertexAttribIPointer(self.attr, size, gl_type, stride, offset as *const GLvoid); gl::VertexAttribIPointer(self.attr,
gl::VertexAttribDivisor(self.attr, divisor); size,
gl::EnableVertexAttribArray(self.attr); gl_type,
stride,
offset as *const GLvoid); ck();
gl::VertexAttribDivisor(self.attr, divisor); ck();
gl::EnableVertexAttribArray(self.attr); ck();
} }
} }
} }
@ -609,7 +630,7 @@ pub struct GLFramebuffer {
impl Drop for GLFramebuffer { impl Drop for GLFramebuffer {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
gl::DeleteFramebuffers(1, &mut self.gl_framebuffer) gl::DeleteFramebuffers(1, &mut self.gl_framebuffer); ck();
} }
} }
} }
@ -621,7 +642,7 @@ pub struct GLBuffer {
impl Drop for GLBuffer { impl Drop for GLBuffer {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
gl::DeleteBuffers(1, &mut self.gl_buffer) gl::DeleteBuffers(1, &mut self.gl_buffer); ck();
} }
} }
} }
@ -642,7 +663,7 @@ pub struct GLProgram {
impl Drop for GLProgram { impl Drop for GLProgram {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
gl::DeleteProgram(self.gl_program) gl::DeleteProgram(self.gl_program); ck();
} }
} }
} }
@ -654,7 +675,7 @@ pub struct GLShader {
impl Drop for GLShader { impl Drop for GLShader {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
gl::DeleteShader(self.gl_shader) gl::DeleteShader(self.gl_shader); ck();
} }
} }
} }
@ -672,7 +693,7 @@ impl Drop for GLTimerQuery {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
gl::DeleteQueries(1, &mut self.gl_query); gl::DeleteQueries(1, &mut self.gl_query); ck();
} }
} }
} }
@ -745,3 +766,18 @@ impl VertexAttrTypeExt for VertexAttrType {
} }
} }
} }
// Error checking
#[cfg(debug)]
fn ck() {
unsafe {
let err = gl::GetError();
if err != 0 {
panic!("GL error: 0x{:x}", err);
}
}
}
#[cfg(not(debug))]
fn ck() {}