diff --git a/demo/common/src/device.rs b/demo/common/src/device.rs index 9e252435..16ffd0de 100644 --- a/demo/common/src/device.rs +++ b/demo/common/src/device.rs @@ -13,55 +13,6 @@ use crate::GRIDLINE_COUNT; 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 { - 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 where D: Device { pub program: D::Program, pub transform_uniform: D::Uniform, diff --git a/gl/src/device.rs b/gl/src/device.rs index a80d6168..f2c314a5 100644 --- a/gl/src/device.rs +++ b/gl/src/device.rs @@ -30,10 +30,14 @@ impl GLDevice { fn set_texture_parameters(&self, texture: &GLTexture) { self.bind_texture(texture, 0); unsafe { - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE 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); ck(); + gl::TexParameteri(gl::TEXTURE_2D, + 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 { // Set blend. match render_state.blend { - BlendState::Off => gl::Disable(gl::BLEND), + BlendState::Off => { + gl::Disable(gl::BLEND); ck(); + } BlendState::RGBOneAlphaOneMinusSrcAlpha => { - gl::BlendFuncSeparate(gl::ONE, gl::ONE_MINUS_SRC_ALPHA, gl::ONE, gl::ONE); - gl::Enable(gl::BLEND); + gl::BlendFuncSeparate(gl::ONE, + gl::ONE_MINUS_SRC_ALPHA, + gl::ONE, + gl::ONE); ck(); + gl::Enable(gl::BLEND); ck(); } BlendState::RGBOneAlphaOne => { - gl::BlendFunc(gl::ONE, gl::ONE); - gl::Enable(gl::BLEND); + gl::BlendFunc(gl::ONE, gl::ONE); ck(); + gl::Enable(gl::BLEND); ck(); } } // Set depth. match render_state.depth { - None => gl::Disable(gl::DEPTH_TEST), + None => { + gl::Disable(gl::DEPTH_TEST); ck(); + } Some(ref state) => { - gl::Enable(gl::DEPTH_TEST); - gl::DepthFunc(state.func.to_gl_depth_func()); - gl::DepthMask(state.write as GLboolean); + gl::Enable(gl::DEPTH_TEST); ck(); + gl::DepthFunc(state.func.to_gl_depth_func()); ck(); + gl::DepthMask(state.write as GLboolean); ck(); } } // Set stencil. match render_state.stencil { - None => gl::Disable(gl::STENCIL_TEST), + None => { + gl::Disable(gl::STENCIL_TEST); ck(); + } Some(ref state) => { gl::StencilFunc(state.func.to_gl_stencil_func(), state.reference as GLint, - state.mask); + state.mask); ck(); let pass_action = if state.pass_replace { gl::REPLACE } else { gl::KEEP }; - gl::StencilOp(gl::KEEP, gl::KEEP, pass_action); - gl::Enable(gl::STENCIL_TEST); + gl::StencilOp(gl::KEEP, gl::KEEP, pass_action); ck(); + gl::Enable(gl::STENCIL_TEST); ck(); } } // Set color mask. 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 { BlendState::Off => {} BlendState::RGBOneAlphaOneMinusSrcAlpha | BlendState::RGBOneAlphaOne => { - gl::Disable(gl::BLEND); + gl::Disable(gl::BLEND); ck(); } } if render_state.depth.is_some() { - gl::Disable(gl::DEPTH_TEST); + gl::Disable(gl::DEPTH_TEST); ck(); } 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 }; unsafe { - gl::GenTextures(1, &mut texture.gl_texture); + gl::GenTextures(1, &mut texture.gl_texture); ck(); self.bind_texture(&texture, 0); gl::TexImage2D(gl::TEXTURE_2D, 0, @@ -141,7 +154,7 @@ impl Device for GLDevice { 0, gl_format, gl_type, - ptr::null()); + ptr::null()); ck(); } self.set_texture_parameters(&texture); @@ -153,7 +166,7 @@ impl Device for GLDevice { let mut texture = GLTexture { gl_texture: 0, size }; unsafe { - gl::GenTextures(1, &mut texture.gl_texture); + gl::GenTextures(1, &mut texture.gl_texture); ck(); self.bind_texture(&texture, 0); gl::TexImage2D(gl::TEXTURE_2D, 0, @@ -163,7 +176,7 @@ impl Device for GLDevice { 0, gl::RED, gl::UNSIGNED_BYTE, - data.as_ptr() as *const GLvoid); + data.as_ptr() as *const GLvoid); ck(); } self.set_texture_parameters(&texture); @@ -177,23 +190,23 @@ impl Device for GLDevice { }; unsafe { - let gl_shader = gl::CreateShader(gl_shader_kind); + let gl_shader = gl::CreateShader(gl_shader_kind); ck(); gl::ShaderSource(gl_shader, 1, [source.as_ptr() as *const GLchar].as_ptr(), - [source.len() as GLint].as_ptr()); - gl::CompileShader(gl_shader); + [source.len() as GLint].as_ptr()); ck(); + gl::CompileShader(gl_shader); ck(); 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 { 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]; gl::GetShaderInfoLog(gl_shader, info_log.len() as GLint, 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)); panic!("{:?} shader '{}' compilation failed", kind, name); } @@ -209,21 +222,21 @@ impl Device for GLDevice { -> GLProgram { let gl_program; unsafe { - gl_program = gl::CreateProgram(); - gl::AttachShader(gl_program, vertex_shader.gl_shader); - gl::AttachShader(gl_program, fragment_shader.gl_shader); - gl::LinkProgram(gl_program); + gl_program = gl::CreateProgram(); ck(); + gl::AttachShader(gl_program, vertex_shader.gl_shader); ck(); + gl::AttachShader(gl_program, fragment_shader.gl_shader); ck(); + gl::LinkProgram(gl_program); ck(); 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 { 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]; gl::GetProgramInfoLog(gl_program, info_log.len() as GLint, 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)); panic!("Program '{}' linking failed", name); } @@ -236,7 +249,7 @@ impl Device for GLDevice { fn create_vertex_array(&self) -> GLVertexArray { unsafe { 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 } } @@ -245,7 +258,7 @@ impl Device for GLDevice { let name = CString::new(format!("a{}", name)).unwrap(); let attr = unsafe { gl::GetAttribLocation(program.gl_program, name.as_ptr() as *const GLchar) as GLuint - }; + }; ck(); GLVertexAttr { attr } } @@ -253,13 +266,13 @@ impl Device for GLDevice { let name = CString::new(format!("u{}", name)).unwrap(); let location = unsafe { gl::GetUniformLocation(program.gl_program, name.as_ptr() as *const GLchar) - }; + }; ck(); GLUniform { location } } fn use_program(&self, program: &Self::Program) { 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(), if normalized { gl::TRUE } else { gl::FALSE }, stride as GLint, - offset as *const GLvoid); - gl::VertexAttribDivisor(attr.attr, divisor); - gl::EnableVertexAttribArray(attr.attr); + offset as *const GLvoid); ck(); + gl::VertexAttribDivisor(attr.attr, divisor); ck(); + gl::EnableVertexAttribArray(attr.attr); ck(); } } @@ -295,20 +308,24 @@ impl Device for GLDevice { size as GLint, attr_type.to_gl_type(), stride as GLint, - offset as *const GLvoid); - gl::VertexAttribDivisor(attr.attr, divisor); - gl::EnableVertexAttribArray(attr.attr); + offset as *const GLvoid); ck(); + gl::VertexAttribDivisor(attr.attr, divisor); ck(); + gl::EnableVertexAttribArray(attr.attr); ck(); } } fn set_uniform(&self, uniform: &Self::Uniform, data: UniformData) { unsafe { match data { - UniformData::Vec2(data) => gl::Uniform2f(uniform.location, data.x(), data.y()), - UniformData::Vec4(data) => { - gl::Uniform4f(uniform.location, data.x(), data.y(), data.z(), data.w()); + UniformData::Vec2(data) => { + gl::Uniform2f(uniform.location, data.x(), data.y()); ck(); + } + 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 { let mut gl_framebuffer = 0; unsafe { - gl::GenFramebuffers(1, &mut gl_framebuffer); + gl::GenFramebuffers(1, &mut gl_framebuffer); ck(); 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); gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, texture.gl_texture, - 0); + 0); ck(); assert_eq!(gl::CheckFramebufferStatus(gl::FRAMEBUFFER), gl::FRAMEBUFFER_COMPLETE); } @@ -334,7 +351,7 @@ impl Device for GLDevice { fn create_buffer(&self) -> GLBuffer { unsafe { let mut gl_buffer = 0; - gl::GenBuffers(1, &mut gl_buffer); + gl::GenBuffers(1, &mut gl_buffer); ck(); GLBuffer { gl_buffer } } } @@ -353,11 +370,11 @@ impl Device for GLDevice { BufferUploadMode::Dynamic => gl::DYNAMIC_DRAW, }; unsafe { - gl::BindBuffer(target, buffer.gl_buffer); + gl::BindBuffer(target, buffer.gl_buffer); ck(); gl::BufferData(target, (data.len() * mem::size_of::()) as GLsizeiptr, data.as_ptr() as *const GLvoid, - mode); + mode); ck(); } } @@ -383,7 +400,7 @@ impl Device for GLDevice { 0, gl::RGBA, gl::UNSIGNED_BYTE, - data.as_ptr() as *const GLvoid); + data.as_ptr() as *const GLvoid); ck(); } self.set_texture_parameters(texture); @@ -392,14 +409,14 @@ impl Device for GLDevice { fn read_pixels_from_default_framebuffer(&self, size: Point2DI32) -> Vec { let mut pixels = vec![0; size.x() as usize * size.y() as usize * 4]; unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, 0); + gl::BindFramebuffer(gl::FRAMEBUFFER, 0); ck(); gl::ReadPixels(0, 0, size.x() as GLsizei, size.y() as GLsizei, gl::RGBA, gl::UNSIGNED_BYTE, - pixels.as_mut_ptr() as *mut GLvoid); + pixels.as_mut_ptr() as *mut GLvoid); ck(); } // Flip right-side-up. @@ -419,19 +436,19 @@ impl Device for GLDevice { unsafe { let mut flags = 0; 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; } if let Some(depth) = depth { - gl::ClearDepth(depth as GLdouble); + gl::ClearDepth(depth as GLdouble); ck(); flags |= gl::DEPTH_BUFFER_BIT; } if let Some(stencil) = stencil { - gl::ClearStencil(stencil as GLint); + gl::ClearStencil(stencil as GLint); ck(); flags |= gl::STENCIL_BUFFER_BIT; } 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) { self.set_render_state(render_state); 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); } @@ -450,7 +467,7 @@ impl Device for GLDevice { gl::DrawElements(primitive.to_gl_primitive(), index_count as GLsizei, gl::UNSIGNED_INT, - ptr::null()); + ptr::null()); ck(); } self.reset_render_state(render_state); } @@ -465,7 +482,7 @@ impl Device for GLDevice { gl::DrawArraysInstanced(primitive.to_gl_primitive(), 0, index_count as GLsizei, - instance_count as GLsizei); + instance_count as GLsizei); ck(); } self.reset_render_state(render_state); } @@ -474,7 +491,7 @@ impl Device for GLDevice { fn create_timer_query(&self) -> GLTimerQuery { let mut query = GLTimerQuery { gl_query: 0 }; unsafe { - gl::GenQueries(1, &mut query.gl_query); + gl::GenQueries(1, &mut query.gl_query); ck(); } query } @@ -482,14 +499,14 @@ impl Device for GLDevice { #[inline] fn begin_timer_query(&self, query: &Self::TimerQuery) { unsafe { - gl::BeginQuery(gl::TIME_ELAPSED, query.gl_query); + gl::BeginQuery(gl::TIME_ELAPSED, query.gl_query); ck(); } } #[inline] fn end_timer_query(&self, _: &Self::TimerQuery) { 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 { unsafe { 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 } } @@ -506,7 +523,7 @@ impl Device for GLDevice { fn get_timer_query(&self, query: &Self::TimerQuery) -> Duration { unsafe { 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) } } @@ -514,38 +531,38 @@ impl Device for GLDevice { #[inline] fn bind_vertex_array(&self, vertex_array: &GLVertexArray) { unsafe { - gl::BindVertexArray(vertex_array.gl_vertex_array); + gl::BindVertexArray(vertex_array.gl_vertex_array); ck(); } } #[inline] fn bind_buffer(&self, buffer: &GLBuffer, target: BufferTarget) { unsafe { - gl::BindBuffer(target.to_gl_target(), buffer.gl_buffer); + gl::BindBuffer(target.to_gl_target(), buffer.gl_buffer); ck(); } } #[inline] fn bind_default_framebuffer(&self, size: Point2DI32) { unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, 0); - gl::Viewport(0, 0, size.x(), size.y()); + gl::BindFramebuffer(gl::FRAMEBUFFER, 0); ck(); + gl::Viewport(0, 0, size.x(), size.y()); ck(); } } #[inline] fn bind_framebuffer(&self, framebuffer: &GLFramebuffer) { unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.gl_framebuffer); - gl::Viewport(0, 0, framebuffer.texture.size.x(), framebuffer.texture.size.y()); + gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.gl_framebuffer); ck(); + gl::Viewport(0, 0, framebuffer.texture.size.x(), framebuffer.texture.size.y()); ck(); } } #[inline] fn bind_texture(&self, texture: &GLTexture, unit: u32) { unsafe { - gl::ActiveTexture(gl::TEXTURE0 + unit); - gl::BindTexture(gl::TEXTURE_2D, texture.gl_texture); + gl::ActiveTexture(gl::TEXTURE0 + unit); ck(); + gl::BindTexture(gl::TEXTURE_2D, texture.gl_texture); ck(); } } } @@ -558,7 +575,7 @@ impl Drop for GLVertexArray { #[inline] fn drop(&mut self) { 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, if normalized { gl::TRUE } else { gl::FALSE }, stride, - offset as *const GLvoid); - gl::VertexAttribDivisor(self.attr, divisor); - gl::EnableVertexAttribArray(self.attr); + offset as *const GLvoid); ck(); + gl::VertexAttribDivisor(self.attr, divisor); ck(); + gl::EnableVertexAttribArray(self.attr); ck(); } } @@ -594,9 +611,13 @@ impl GLVertexAttr { offset: usize, divisor: GLuint) { unsafe { - gl::VertexAttribIPointer(self.attr, size, gl_type, stride, offset as *const GLvoid); - gl::VertexAttribDivisor(self.attr, divisor); - gl::EnableVertexAttribArray(self.attr); + gl::VertexAttribIPointer(self.attr, + size, + 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 { fn drop(&mut self) { 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 { fn drop(&mut self) { 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 { fn drop(&mut self) { unsafe { - gl::DeleteProgram(self.gl_program) + gl::DeleteProgram(self.gl_program); ck(); } } } @@ -654,7 +675,7 @@ pub struct GLShader { impl Drop for GLShader { fn drop(&mut self) { unsafe { - gl::DeleteShader(self.gl_shader) + gl::DeleteShader(self.gl_shader); ck(); } } } @@ -672,7 +693,7 @@ impl Drop for GLTimerQuery { #[inline] fn drop(&mut self) { 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() {}