#[macro_use] extern crate glium; mod support; use glium::Surface; use glium::buffer::BufferMode; use std::mem; #[test] fn buffer_immutable_creation() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [f32; 3], field2: [f32; 3], } implement_vertex!(Vertex, field1, field2); glium::VertexBuffer::new(&display, &[ Vertex { field1: [-0.5, -0.5, 0.0], field2: [0.0, 1.0, 0.0] }, Vertex { field1: [ 0.0, 0.5, 1.0], field2: [0.0, 0.0, 1.0] }, Vertex { field1: [ 0.5, -0.5, 0.0], field2: [1.0, 0.0, 0.0] }, ] ).unwrap(); display.assert_no_error(None); } #[test] fn buffer_dynamic_creation() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [f32; 3], field2: [f32; 3], } implement_vertex!(Vertex, field1, field2); glium::VertexBuffer::dynamic(&display, &[ Vertex { field1: [-0.5, -0.5, 0.0], field2: [0.0, 1.0, 0.0] }, Vertex { field1: [ 0.0, 0.5, 1.0], field2: [0.0, 0.0, 1.0] }, Vertex { field1: [ 0.5, -0.5, 0.0], field2: [1.0, 0.0, 0.0] }, ] ).unwrap(); display.assert_no_error(None); } #[test] fn buffer_immutable_empty_creation() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [f32; 3], field2: [f32; 3], } implement_vertex!(Vertex, field1, field2); let vb: glium::VertexBuffer = glium::VertexBuffer::empty(&display, 12).unwrap(); assert_eq!(vb.len(), 12); display.assert_no_error(None); } #[test] fn buffer_dynamic_empty_creation() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [f32; 3], field2: [f32; 3], } implement_vertex!(Vertex, field1, field2); let vb: glium::VertexBuffer = glium::VertexBuffer::empty_dynamic(&display, 12).unwrap(); assert_eq!(vb.len(), 12); display.assert_no_error(None); } #[test] fn buffer_immutable_mapping_read() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let mut vb = glium::VertexBuffer::new(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] }, ] ).unwrap(); let mapping = vb.map(); assert_eq!(mapping[0].field1, [2, 3]); assert_eq!(mapping[1].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_dynamic_mapping_read() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let mut vb = glium::VertexBuffer::dynamic(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] }, ] ).unwrap(); let mapping = vb.map(); assert_eq!(mapping[0].field1, [2, 3]); assert_eq!(mapping[1].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_immutable_mapping_write() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let mut vb = glium::VertexBuffer::new(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] }, ] ).unwrap(); { let mut mapping = vb.map(); mapping[0].field1 = [0, 1]; } let mapping = vb.map(); assert_eq!(mapping[0].field1, [0, 1]); assert_eq!(mapping[1].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_dynamic_mapping_write() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let mut vb = glium::VertexBuffer::dynamic(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] }, ] ).unwrap(); { let mut mapping = vb.map(); mapping[0].field1 = [0, 1]; } let mapping = vb.map(); assert_eq!(mapping[0].field1, [0, 1]); assert_eq!(mapping[1].field2, [15, 17]); display.assert_no_error(None); } // TODO: uncomment after std::thread::scoped has been stabilized /*#[test] fn buffer_mapping_multithread() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let mut vb = glium::VertexBuffer::empty(&display, 2).unwrap(); { let mut mapping = vb.map(); std::thread::scoped(|| { mapping[0].field1 = [0, 1]; mapping[1].field2 = [15, 17]; }); } let mapping = vb.map(); assert_eq!(mapping[0].field1, [0, 1]); assert_eq!(mapping[1].field2, [15, 17]); display.assert_no_error(None); }*/ #[test] fn buffer_immutable_read() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let vb = glium::VertexBuffer::new(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] }, ] ).unwrap(); let data = match vb.read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[0].field1, [2, 3]); assert_eq!(data[1].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_dynamic_read() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let vb = glium::VertexBuffer::dynamic(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] }, ] ).unwrap(); let data = match vb.read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[0].field1, [2, 3]); assert_eq!(data[1].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_immutable_read_slice() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let vb = glium::VertexBuffer::new(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] }, ] ).unwrap(); let data = match vb.slice(1 .. 2).unwrap().read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[0].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_dynamic_read_slice() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let vb = glium::VertexBuffer::dynamic(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] }, ] ).unwrap(); let data = match vb.slice(1 .. 2).unwrap().read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[0].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_slice_out_of_bounds() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let vb = glium::VertexBuffer::new(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] }, ] ).unwrap(); assert!(vb.slice(0 .. 3).is_none()); display.assert_no_error(None); } #[test] fn buffer_immutable_write() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let vb = glium::VertexBuffer::new(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [ 0, 0], field2: [ 0, 0] }, ] ).unwrap(); vb.write(&[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] } ]); let data = match vb.read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[0].field1, [2, 3]); assert_eq!(data[0].field2, [5, 7]); assert_eq!(data[1].field1, [12, 13]); assert_eq!(data[1].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_dynamic_write() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let vb = glium::VertexBuffer::dynamic(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [ 0, 0], field2: [ 0, 0] }, ] ).unwrap(); vb.write(&[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [12, 13], field2: [15, 17] } ]); let data = match vb.read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[0].field1, [2, 3]); assert_eq!(data[0].field2, [5, 7]); assert_eq!(data[1].field1, [12, 13]); assert_eq!(data[1].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_immutable_write_slice() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let vb = glium::VertexBuffer::new(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [ 0, 0], field2: [ 0, 0] }, ] ).unwrap(); vb.slice(1 .. 2).unwrap().write(&[Vertex { field1: [12, 13], field2: [15, 17] }]); let data = match vb.read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[0].field1, [2, 3]); assert_eq!(data[0].field2, [5, 7]); assert_eq!(data[1].field1, [12, 13]); assert_eq!(data[1].field2, [15, 17]); display.assert_no_error(None); } #[test] fn buffer_dynamic_write_slice() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [u8; 2], field2: [u8; 2], } implement_vertex!(Vertex, field1, field2); let vb = glium::VertexBuffer::dynamic(&display, &[ Vertex { field1: [ 2, 3], field2: [ 5, 7] }, Vertex { field1: [ 0, 0], field2: [ 0, 0] }, ] ).unwrap(); vb.slice(1 .. 2).unwrap().write(&[Vertex { field1: [12, 13], field2: [15, 17] }]); let data = match vb.read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[0].field1, [2, 3]); assert_eq!(data[0].field2, [5, 7]); assert_eq!(data[1].field1, [12, 13]); assert_eq!(data[1].field2, [15, 17]); display.assert_no_error(None); } #[test] fn zero_sized_immutable_buffer() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [f32; 3], field2: [f32; 3], } implement_vertex!(Vertex, field1, field2); glium::VertexBuffer::new(&display, &Vec::::new()).unwrap(); display.assert_no_error(None); } #[test] fn zero_sized_dynamic_buffer() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field1: [f32; 3], field2: [f32; 3], } implement_vertex!(Vertex, field1, field2); glium::VertexBuffer::new(&display, &Vec::::new()).unwrap(); display.assert_no_error(None); } #[test] fn invalidate() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field: f32 } implement_vertex!(Vertex, field); let buffer = glium::VertexBuffer::new(&display, &[ Vertex { field: 2.0 } ] ).unwrap(); buffer.invalidate(); display.assert_no_error(None); } #[test] fn invalidate_range() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { field: f32 } implement_vertex!(Vertex, field); let buffer = glium::VertexBuffer::new(&display, &[ Vertex { field: 1.0 }, Vertex { field: 2.0 }, Vertex { field: 3.0 } ] ).unwrap(); buffer.slice(1 .. 2).unwrap().invalidate(); display.assert_no_error(None); } #[test] fn immutable_mapping_forget_then_remap() { let display = support::build_display(); let mut buf = glium::buffer::BufferView::new(&display, &[1, 2, 3], glium::buffer::BufferType::ArrayBuffer, BufferMode::Immutable) .unwrap(); { let mut mapping = buf.map(); mapping[0] = 3; mem::forget(mapping); } let mapping = buf.map(); assert_eq!(mapping[1], 2); assert_eq!(mapping[2], 3); display.assert_no_error(None); } #[test] fn immutable_mapping_forget_then_read() { let display = support::build_display(); let mut buf = glium::buffer::BufferView::new(&display, &[1, 2, 3], glium::buffer::BufferType::ArrayBuffer, BufferMode::Immutable) .unwrap(); { let mut mapping = buf.map(); mapping[0] = 3; mem::forget(mapping); } let data = match buf.read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[1], 2); assert_eq!(data[2], 3); display.assert_no_error(None); } #[test] fn immutable_mapping_forget_then_invalidate() { let display = support::build_display(); let mut buf = glium::buffer::BufferView::new(&display, &[1, 2, 3], glium::buffer::BufferType::ArrayBuffer, BufferMode::Immutable) .unwrap(); { let mut mapping = buf.map(); mapping[0] = 3; mem::forget(mapping); } buf.invalidate(); display.assert_no_error(None); } #[test] fn immutable_mapping_forget_then_draw() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { position: [f32; 2] } implement_vertex!(Vertex, position); let mut vb = glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, Vertex { position: [ 1.0, 1.0] }, Vertex { position: [-1.0, -1.0] }, Vertex { position: [ 1.0, -1.0] }, ] ).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 mapping = vb.map(); mem::forget(mapping); } 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, &glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip), &program, &uniform!{}, &Default::default()).unwrap(); let data: Vec> = texture.read(); for pixel in data.iter().flat_map(|e| e.iter()) { assert_eq!(*pixel, (255, 0, 0, 255)); } display.assert_no_error(None); } #[test] fn persistent_mapping_forget_then_remap() { let display = support::build_display(); let mut buf = glium::buffer::BufferView::new(&display, &[1, 2, 3], glium::buffer::BufferType::ArrayBuffer, BufferMode::Persistent) .unwrap(); { let mut mapping = buf.map(); mapping[0] = 3; mem::forget(mapping); } let mapping = buf.map(); assert_eq!(mapping[1], 2); assert_eq!(mapping[2], 3); display.assert_no_error(None); } #[test] fn persistent_mapping_forget_then_read() { let display = support::build_display(); let mut buf = glium::buffer::BufferView::new(&display, &[1, 2, 3], glium::buffer::BufferType::ArrayBuffer, BufferMode::Persistent) .unwrap(); { let mut mapping = buf.map(); mapping[0] = 3; mem::forget(mapping); } let data = match buf.read() { Ok(r) => r, Err(glium::buffer::ReadError::NotSupported) => return, e => e.unwrap() }; assert_eq!(data[1], 2); assert_eq!(data[2], 3); display.assert_no_error(None); } #[test] fn persistent_mapping_forget_then_invalidate() { let display = support::build_display(); let mut buf = glium::buffer::BufferView::new(&display, &[1, 2, 3], glium::buffer::BufferType::ArrayBuffer, BufferMode::Persistent) .unwrap(); { let mut mapping = buf.map(); mapping[0] = 3; mem::forget(mapping); } buf.invalidate(); display.assert_no_error(None); } #[test] fn dynamic_mapping_forget_then_draw() { let display = support::build_display(); #[derive(Copy, Clone)] struct Vertex { position: [f32; 2] } implement_vertex!(Vertex, position); let mut vb = glium::VertexBuffer::dynamic(&display, &[ Vertex { position: [-1.0, 1.0] }, Vertex { position: [ 1.0, 1.0] }, Vertex { position: [-1.0, -1.0] }, Vertex { position: [ 1.0, -1.0] }, ] ).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 mapping = vb.map(); mem::forget(mapping); } 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, &glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip), &program, &uniform!{}, &Default::default()).unwrap(); let data: Vec> = texture.read(); for pixel in data.iter().flat_map(|e| e.iter()) { assert_eq!(*pixel, (255, 0, 0, 255)); } display.assert_no_error(None); } #[test] fn copy_to() { let display = support::build_display(); let buf1 = glium::buffer::BufferView::new(&display, &[1, 2, 3], glium::buffer::BufferType::ArrayBuffer, BufferMode::Persistent); let buf1 = if let Ok(buf) = buf1 { buf } else { return }; let buf2 = glium::buffer::BufferView::new(&display, &[0, 0, 0], glium::buffer::BufferType::ArrayBuffer, BufferMode::Persistent); let buf2 = if let Ok(buf) = buf2 { buf } else { return }; if buf1.copy_to(buf2.as_slice()).is_err() { return; } let result = match buf2.read() { Ok(r) => r, Err(_) => return }; assert_eq!(result, [1, 2, 3]); display.assert_no_error(None); } #[test] fn copy_to_slice() { let display = support::build_display(); let buf1 = glium::buffer::BufferView::<[u8]>::new(&display, &[1, 2], glium::buffer::BufferType::ArrayBuffer, BufferMode::Persistent); let buf1 = if let Ok(buf) = buf1 { buf } else { return }; let buf2 = glium::buffer::BufferView::<[u8]>::new(&display, &[0, 0, 0], glium::buffer::BufferType::ArrayBuffer, BufferMode::Persistent); let buf2 = if let Ok(buf) = buf2 { buf } else { return }; if buf1.copy_to(buf2.slice(1 .. 3).unwrap()).is_err() { return; } let result = match buf2.read() { Ok(r) => r, Err(_) => return }; assert_eq!(result, [0, 1, 2]); display.assert_no_error(None); }