#[macro_use] extern crate glium; use glium::Surface; use glium::index::PrimitiveType; mod support; #[test] fn color_mask() { let display = support::build_display(); let params = glium::DrawParameters { color_mask: (false, true, true, true), .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms).unwrap(); let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(0, 0, 0, 255)); } } display.assert_no_error(None); } #[test] fn viewport_too_large() { let display = support::build_display(); let params = glium::DrawParameters { viewport: Some(glium::Rect { left: 0, bottom: 0, width: 4294967295, height: 4294967295, }), .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let mut frame = display.draw(); match frame.draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms) { Err(glium::DrawError::ViewportTooLarge) => (), a => panic!("{:?}", a) }; frame.finish().unwrap(); display.assert_no_error(None); } #[test] fn wrong_depth_range() { let display = support::build_display(); let params = glium::DrawParameters { depth: glium::Depth { range: (-0.1, 1.0), .. Default::default() }, .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let mut frame = display.draw(); match frame.draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms) { Err(glium::DrawError::InvalidDepthRange) => (), a => panic!("{:?}", a) }; frame.finish().unwrap(); display.assert_no_error(None); } #[test] fn scissor() { let display = support::build_display(); let params = glium::DrawParameters { scissor: Some(glium::Rect { left: 0, bottom: 0, width: 1, height: 1, }), .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms).unwrap(); let data: Vec> = texture.read(); assert_eq!(data[0][0], (255, 0, 0, 255)); assert_eq!(data[1][0], (0, 0, 0, 0)); assert_eq!(data[0][1], (0, 0, 0, 0)); assert_eq!(data[1][1], (0, 0, 0, 0)); for row in data.iter().skip(1) { for pixel in row.iter().skip(1) { assert_eq!(pixel, &(0, 0, 0, 0)); } } display.assert_no_error(None); } #[test] fn scissor_followed_by_clear() { let display = support::build_display(); let params = glium::DrawParameters { scissor: Some(glium::Rect { left: 2, bottom: 2, width: 2, height: 2, }), .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms).unwrap(); texture.as_surface().clear_color(1.0, 0.0, 1.0, 1.0); let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(255, 0, 255, 255)); } } display.assert_no_error(None); } #[test] fn viewport_followed_by_clear() { let display = support::build_display(); let params = glium::DrawParameters { viewport: Some(glium::Rect { left: 2, bottom: 2, width: 2, height: 2, }), .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms).unwrap(); texture.as_surface().clear_color(1.0, 0.0, 1.0, 1.0); let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(255, 0, 255, 255)); } } display.assert_no_error(None); } #[test] fn viewport() { let display = support::build_display(); let params = glium::DrawParameters { viewport: Some(glium::Rect { left: 0, bottom: 0, width: 1, height: 1, }), .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms).unwrap(); let data: Vec> = texture.read(); assert_eq!(data[0][0], (255, 0, 0, 255)); assert_eq!(data[1][0], (0, 0, 0, 0)); assert_eq!(data[0][1], (0, 0, 0, 0)); assert_eq!(data[1][1], (0, 0, 0, 0)); for row in data.iter().skip(1) { for pixel in row.iter().skip(1) { assert_eq!(pixel, &(0, 0, 0, 0)); } } display.assert_no_error(None); } #[test] fn dont_draw_primitives() { let display = support::build_display(); let params = glium::DrawParameters { draw_primitives: false, .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 1.0, 0.0, 0.0); match texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms) { Ok(_) => (), Err(glium::DrawError::RasterizerDiscardNotSupported) => return, e => e.unwrap() } let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(0, 255, 0, 0)); } } display.assert_no_error(None); } #[test] fn dont_draw_primitives_then_draw() { let display = support::build_display(); let params = glium::DrawParameters { draw_primitives: false, .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 1.0, 0.0, 0.0); match texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms) { Ok(_) => (), Err(glium::DrawError::RasterizerDiscardNotSupported) => return, e => e.unwrap() } texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &Default::default()).unwrap(); let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(255, 0, 0, 255)); } } display.assert_no_error(None); } #[test] fn cull_clockwise() { let display = support::build_display(); let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, // top-left Vertex { position: [ 1.0, 1.0] }, // top-right Vertex { position: [-1.0, -1.0] }, // bottom-left Vertex { position: [ 1.0, -1.0] } // bottom-right ]).unwrap() }; // first triangle covers the top-left side of the screen and is clockwise // second triangle covers the bottom-right side of the screen and is ccw let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList, &[0u16, 1, 2, 1, 2, 3]).unwrap(); let program = program!(&display, 140 => { vertex: " #version 140 in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } " }, 110 => { vertex: " #version 110 attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, 100 => { vertex: " #version 100 attribute lowp vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, ).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vertex_buffer, &index_buffer, &program, &glium::uniforms::EmptyUniforms, &glium::DrawParameters { backface_culling: glium::BackfaceCullingMode::CullClockwise, .. Default::default() }).unwrap(); let read_back: Vec> = texture.read(); assert_eq!(read_back[0].last().unwrap(), &(255, 0, 0, 255)); assert_eq!(read_back.last().unwrap()[0], (0, 0, 0, 0)); display.assert_no_error(None); } #[test] fn cull_counterclockwise() { let display = support::build_display(); let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, // top-left Vertex { position: [ 1.0, 1.0] }, // top-right Vertex { position: [-1.0, -1.0] }, // bottom-left Vertex { position: [ 1.0, -1.0] } // bottom-right ]).unwrap() }; // first triangle covers the top-left side of the screen and is clockwise // second triangle covers the bottom-right side of the screen and is ccw let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList, &[0u16, 1, 2, 1, 2, 3]).unwrap(); let program = program!(&display, 140 => { vertex: " #version 140 in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } " }, 110 => { vertex: " #version 110 attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, 100 => { vertex: " #version 100 attribute lowp vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, ).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vertex_buffer, &index_buffer, &program, &glium::uniforms::EmptyUniforms, &glium::DrawParameters { backface_culling: glium::BackfaceCullingMode::CullCounterClockwise, .. Default::default() }).unwrap(); let read_back: Vec> = texture.read(); assert_eq!(read_back[0].last().unwrap(), &(0, 0, 0, 0)); assert_eq!(read_back.last().unwrap()[0], (255, 0, 0, 255)); display.assert_no_error(None); } #[test] fn cull_clockwise_trianglestrip() { let display = support::build_display(); let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, // top-left Vertex { position: [ 1.0, 1.0] }, // top-right Vertex { position: [-1.0, -1.0] }, // bottom-left Vertex { position: [ 1.0, -1.0] } // bottom-right ]).unwrap() }; // both triangles are clockwise let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[0u16, 1, 2, 3]).unwrap(); let program = program!(&display, 140 => { vertex: " #version 140 in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } " }, 110 => { vertex: " #version 110 attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, 100 => { vertex: " #version 100 attribute lowp vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, ).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vertex_buffer, &index_buffer, &program, &glium::uniforms::EmptyUniforms, &glium::DrawParameters { backface_culling: glium::BackfaceCullingMode::CullClockwise, .. Default::default() }).unwrap(); let read_back: Vec> = texture.read(); assert_eq!(read_back[0][0], (0, 0, 0, 0)); assert_eq!(read_back.last().unwrap().last().unwrap(), &(0, 0, 0, 0)); display.assert_no_error(None); } #[test] fn cull_counterclockwise_trianglestrip() { let display = support::build_display(); let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, // top-left Vertex { position: [ 1.0, 1.0] }, // top-right Vertex { position: [-1.0, -1.0] }, // bottom-left Vertex { position: [ 1.0, -1.0] } // bottom-right ]).unwrap() }; // both triangles are clockwise let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[0u16, 1, 2, 3]).unwrap(); let program = program!(&display, 140 => { vertex: " #version 140 in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } " }, 110 => { vertex: " #version 110 attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, 100 => { vertex: " #version 100 attribute lowp vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, ).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vertex_buffer, &index_buffer, &program, &glium::uniforms::EmptyUniforms, &glium::DrawParameters { backface_culling: glium::BackfaceCullingMode::CullCounterClockwise, .. Default::default() }).unwrap(); let read_back: Vec> = texture.read(); assert_eq!(read_back[0][0], (255, 0, 0, 255)); assert_eq!(read_back.last().unwrap().last().unwrap(), &(255, 0, 0, 255)); display.assert_no_error(None); } macro_rules! blending_test { ($name:ident, $func:expr, $source:expr, $dest:expr, $result:expr) => ( #[test] fn $name() { let display = support::build_display(); let params = glium::DrawParameters { blend: glium::Blend { color: $func, alpha: $func, constant_value: (1.0, 1.0, 1.0, 1.0) }, .. Default::default() }; let (vb, ib) = support::build_rectangle_vb_ib(&display); let program = program!(&display, 140 => { vertex: " #version 140 in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } " }, 110 => { vertex: " #version 110 attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, 100 => { vertex: " #version 100 attribute lowp vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, ).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear(None, Some($source), false, None, None); texture.as_surface().draw(&vb, &ib, &program, &uniform!{ color: $dest }, ¶ms).unwrap(); let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &$result); } } display.assert_no_error(None); } ) } blending_test!(min_blending, glium::BlendingFunction::Min, (0.0, 0.2, 0.3, 0.0), (1.0, 0.0, 0.0, 1.0), (0, 0, 0, 0)); blending_test!(max_blending, glium::BlendingFunction::Max, (0.4, 1.0, 1.0, 0.2), (1.0, 0.0, 0.0, 1.0), (255, 255, 255, 255)); blending_test!(one_plus_one, glium::BlendingFunction::Addition { source: glium::LinearBlendingFactor::One, destination: glium::LinearBlendingFactor::One, }, (0.0, 1.0, 1.0, 0.0), (1.0, 0.0, 0.0, 1.0), (255, 255, 255, 255)); #[test] fn provoking_vertex_last() { let display = support::build_display(); let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { value: (f32, f32), } implement_vertex!(Vertex, value); glium::VertexBuffer::new(&display, &[ Vertex { value: (-1.0, 1.0) }, Vertex { value: (1.0, -1.0) }, Vertex { value: (-1.0, -1.0) }, ]).unwrap() }; let program = glium::Program::from_source(&display, " #version 100 attribute lowp vec2 value; varying lowp flat float v_value; void main() { v_value = value.y; gl_Position = vec4(value, 0.0, 1.0); } ", " #version 100 varying lowp flat float v_value; void main() { gl_FragColor = vec4(1.0, (v_value + 1.0) * 0.5, 0.0, 1.0); } ", None); let program = match program { Err(_) => return, Ok(p) => p }; let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(&vertex_buffer, &glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList), &program, &glium::uniforms::EmptyUniforms, &glium::DrawParameters { provoking_vertex: glium::draw_parameters::ProvokingVertex::LastVertex, .. Default::default() }).unwrap(); let data: Vec> = texture.read(); // only the bottom-left half of the screen is filled for row in data.iter().take(256) { for pixel in row.iter().take(256) { assert_eq!(pixel, &(255, 0, 0, 255)); } } display.assert_no_error(None); } #[test] fn provoking_vertex_first() { let display = support::build_display(); let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { value: (f32, f32), } implement_vertex!(Vertex, value); glium::VertexBuffer::new(&display, &[ Vertex { value: (-1.0, 1.0) }, Vertex { value: (1.0, -1.0) }, Vertex { value: (-1.0, -1.0) }, ]).unwrap() }; let program = glium::Program::from_source(&display, " #version 100 attribute lowp vec2 value; varying lowp flat float v_value; void main() { v_value = value.y; gl_Position = vec4(value, 0.0, 1.0); } ", " #version 100 varying lowp flat float v_value; void main() { gl_FragColor = vec4(1.0, (v_value + 1.0) * 0.5, 0.0, 1.0); } ", None); let program = match program { Err(_) => return, Ok(p) => p }; let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); let res = texture.as_surface().draw(&vertex_buffer, &glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList), &program, &glium::uniforms::EmptyUniforms, &glium::DrawParameters { provoking_vertex: glium::draw_parameters::ProvokingVertex::FirstVertex, .. Default::default() }); match res { Ok(_) => (), Err(glium::DrawError::ProvokingVertexNotSupported) => { display.assert_no_error(None); return; }, e => e.unwrap(), } let data: Vec> = texture.read(); // only the bottom-left half of the screen is filled for row in data.iter().take(256) { for pixel in row.iter().take(256) { assert_eq!(pixel, &(255, 255, 0, 255)); } } display.assert_no_error(None); } #[test] fn depth_clamp_all() { let display = support::build_display(); let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: (f32, f32, f32), } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: (-1.0, 1.0, -3.0) }, Vertex { position: (1.0, 1.0, 3.0) }, Vertex { position: (-1.0, -1.0, -3.0) }, Vertex { position: (1.0, -1.0, 3.0) }, ]).unwrap() }; let program = program!(&display, 140 => { vertex: " #version 140 in vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } " }, 110 => { vertex: " #version 110 attribute vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, 100 => { vertex: " #version 100 attribute lowp vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, ).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); let res = texture.as_surface().draw(&vertex_buffer, &glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip), &program, &glium::uniforms::EmptyUniforms, &glium::DrawParameters { depth: glium::Depth { clamp: glium::draw_parameters::DepthClamp::Clamp, .. Default::default() }, .. Default::default() }); match res { Ok(_) => (), Err(glium::DrawError::DepthClampNotSupported) => { display.assert_no_error(None); return; }, e => e.unwrap(), } let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(255, 0, 0, 255)); } } display.assert_no_error(None); } #[test] fn depth_clamp_near() { let display = support::build_display(); let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: (f32, f32, f32), } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: (-1.0, 1.0, -3.0) }, Vertex { position: (1.0, 1.0, 3.0) }, Vertex { position: (-1.0, -1.0, -3.0) }, Vertex { position: (1.0, -1.0, 3.0) }, ]).unwrap() }; let program = program!(&display, 140 => { vertex: " #version 140 in vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } " }, 110 => { vertex: " #version 110 attribute vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, 100 => { vertex: " #version 100 attribute lowp vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, ).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); let res = texture.as_surface().draw(&vertex_buffer, &glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip), &program, &glium::uniforms::EmptyUniforms, &glium::DrawParameters { depth: glium::Depth { clamp: glium::draw_parameters::DepthClamp::ClampNear, .. Default::default() }, .. Default::default() }); match res { Ok(_) => (), Err(glium::DrawError::DepthClampNotSupported) => { display.assert_no_error(None); return; }, e => e.unwrap(), } let data: Vec> = texture.read(); // the left part of the texture is red for row in data.iter() { for pixel in row.iter().take(texture.get_width() as usize / 2) { assert_eq!(pixel, &(255, 0, 0, 255)); } } // the right part of the texture is black for row in data.iter() { for pixel in row.iter().skip(3 * texture.get_width() as usize / 4) { assert_eq!(pixel, &(0, 0, 0, 0)); } } display.assert_no_error(None); } #[test] fn depth_clamp_far() { let display = support::build_display(); let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: (f32, f32, f32), } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: (-1.0, 1.0, -3.0) }, Vertex { position: (1.0, 1.0, 3.0) }, Vertex { position: (-1.0, -1.0, -3.0) }, Vertex { position: (1.0, -1.0, 3.0) }, ]).unwrap() }; let program = program!(&display, 140 => { vertex: " #version 140 in vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } " }, 110 => { vertex: " #version 110 attribute vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, 100 => { vertex: " #version 100 attribute lowp vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, ).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); let res = texture.as_surface().draw(&vertex_buffer, &glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip), &program, &glium::uniforms::EmptyUniforms, &glium::DrawParameters { depth: glium::Depth { clamp: glium::draw_parameters::DepthClamp::ClampFar, .. Default::default() }, .. Default::default() }); match res { Ok(_) => (), Err(glium::DrawError::DepthClampNotSupported) => { display.assert_no_error(None); return; }, e => e.unwrap(), } let data: Vec> = texture.read(); // the left part of the texture is black for row in data.iter() { for pixel in row.iter().take(texture.get_width() as usize / 4) { assert_eq!(pixel, &(0, 0, 0, 0)); } } // the right part of the texture is red for row in data.iter() { for pixel in row.iter().skip(texture.get_width() as usize / 2) { assert_eq!(pixel, &(255, 0, 0, 255)); } } display.assert_no_error(None); } #[test] fn primitive_bounding_box() { let display = support::build_display(); let params = glium::DrawParameters { primitive_bounding_box: (0.0 .. 1.0, -0.2 .. 0.3, 0.0 .. 1.0, -1.0 .. 1.0), .. Default::default() }; let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface() .draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, ¶ms).unwrap(); display.assert_no_error(None); } #[test] fn primitive_restart_index() { let display = support::build_display(); // make two horizontal lines // on failure, they will connect like a z // on success, they will connect like a = let vertex_buffer = { #[derive(Copy, Clone)] struct Vertex { position: (f32, f32, f32), } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ // lower line Vertex { position: (-0.5, -0.5, 0.0) }, Vertex { position: ( 0.5, -0.5, 0.0) }, // upper line Vertex { position: (-0.5, 0.5, 0.0) }, Vertex { position: ( 0.5, 0.5, 0.0) }, ]).unwrap() }; let index_buffer = glium::IndexBuffer::::new(&display, glium::index::PrimitiveType::LineStrip, &[0, 1, 255, 2, 3]).unwrap(); let program = program!(&display, 140 => { vertex: " #version 140 in vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } " }, 110 => { vertex: " #version 110 attribute vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, 100 => { vertex: " #version 100 attribute lowp vec3 position; void main() { gl_Position = vec4(position, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } " }, ).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(1.0, 1.0, 1.0, 1.0); let options = glium::DrawParameters { primitive_restart_index: true, .. Default::default() }; let res = texture.as_surface().draw(&vertex_buffer, &index_buffer, &program, &glium::uniforms::EmptyUniforms, &options); match res { Ok(_) => (), Err(glium::DrawError::DepthClampNotSupported) => { display.assert_no_error(None); return; }, e => e.unwrap(), } let data: Vec> = texture.read(); let tex_w = texture.get_width() as usize; let tex_h = texture.get_height().unwrap() as usize; // midpoint of the texture should be white let mid_x = tex_w / 2; let mid_y = tex_h / 2; // sometimes the sampling can be a few pixels off for row in (mid_y - 2)..(mid_y + 2) { for pixel in (mid_x - 2)..(mid_x + 2){ assert_eq!(data[row][pixel], (255, 255, 255, 255)); } } display.assert_no_error(None); }