use image; use glium; use glium::{DisplayBuild, Surface}; use glium::backend::glutin_backend::GlutinFacade; use glium::index::PrimitiveType; use glium::glutin::{Event, VirtualKeyCode}; use glium::glutin; #[derive(Copy,Clone)] struct Vertex { position: [f32; 2], tex_coords: [f32; 2], } implement_vertex!(Vertex, position, tex_coords); /// Shows a image with help of opengl (glium) pub struct ImgWindow { texture: Option, pub facade: GlutinFacade, vertex_buffer: glium::VertexBuffer, index_buffer: glium::IndexBuffer, program: glium::Program, } pub trait EventHandler { fn close_event(&mut self); fn key_event(&mut self, inp: Option); } impl ImgWindow { pub fn new>(title: T) -> ImgWindow { // let display = glium::glutin::WindowBuilder::new().with_vsync().with_title(title.into()).build_glium().unwrap(); let display = glium::glutin::WindowBuilder::new().with_title(title.into()).build_glium().unwrap(); let vertex_buffer = glium::VertexBuffer::new(&display, &[Vertex { position: [-1.0, -1.0], tex_coords: [0.0, 0.0], }, Vertex { position: [-1.0, 1.0], tex_coords: [0.0, 1.0], }, Vertex { position: [1.0, 1.0], tex_coords: [1.0, 1.0], }, Vertex { position: [1.0, -1.0], tex_coords: [1.0, 0.0], }]) .unwrap(); let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]) .unwrap(); let program = program!(&display, 140 => { vertex: " #version 140 uniform lowp mat4 matrix; in vec2 position; in vec2 tex_coords; out vec2 v_tex_coords; void main(){ gl_Position = matrix * vec4(position, 0.0, 1.0); v_tex_coords = tex_coords; } ", fragment: " #version 140 uniform sampler2D tex; in vec2 v_tex_coords; out vec4 f_color; void main(){ f_color = texture(tex, v_tex_coords); } " },) .unwrap(); ImgWindow { texture: None, facade: display, vertex_buffer: vertex_buffer, index_buffer: index_buffer, program: program, } } pub fn set_img(&mut self, img: image::RgbaImage) { let dim = img.dimensions(); let text = glium::texture::RawImage2d::from_raw_rgba_reversed(img.into_raw(), dim); self.texture = glium::texture::CompressedSrgbTexture2d::new(&self.facade, text).ok(); } /// Redraws using opengl pub fn redraw(&self) { let mut target = self.facade.draw(); target.clear_color(0.0, 0.0, 0.0, 0.0); if let Some(ref texture) = self.texture { let uniforms = uniform! { matrix: [ [1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0f32] ], tex: texture }; target.draw(&self.vertex_buffer, &self.index_buffer, &self.program, &uniforms, &Default::default()) .unwrap(); } target.finish().unwrap(); // self.facade.swap_buffers().unwrap(); } pub fn check_for_event(&self, handler: &mut T) { for event in self.facade.poll_events() { match event { Event::Closed => { handler.close_event(); return; } Event::KeyboardInput(glutin::ElementState::Pressed, _, code) => { handler.key_event(code) } _ => (), } } } } use std::time::{Instant, Duration}; use std::thread; /// Saves the time when created and let the current thread /// sleep on drop such that at least duration time has passed /// from creation until drop returns. pub struct FixWaitTimer { begin: Instant, duration: Duration, } impl FixWaitTimer { pub fn new(duration: Duration) -> FixWaitTimer { FixWaitTimer { begin: Instant::now(), duration: duration, } } } impl Drop for FixWaitTimer { fn drop(&mut self) { let passed_time = Instant::now() - self.begin; if passed_time < self.duration { thread::sleep(self.duration - passed_time); } } }