-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes to the Glium example #117
base: master
Are you sure you want to change the base?
Changes from all commits
8e43b45
9a0c023
62db5f3
d1a48c9
5a7ec50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,16 @@ use v4l::video::capture::Parameters; | |
use v4l::video::Capture; | ||
use v4l::{Format, FourCC}; | ||
|
||
use winit::application::ApplicationHandler; | ||
use winit::event::WindowEvent; | ||
use winit::event_loop::ActiveEventLoop; | ||
use winit::window::WindowId; | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
enum UserEvent { | ||
WakeUp, | ||
} | ||
|
||
fn main() -> io::Result<()> { | ||
let path = "/dev/video0"; | ||
println!("Using device: {}\n", path); | ||
|
@@ -54,8 +64,13 @@ fn main() -> io::Result<()> { | |
println!("Active parameters:\n{}", params); | ||
|
||
// Setup the GL display stuff | ||
let event_loop = winit::event_loop::EventLoop::new().map_err(io::Error::other)?; | ||
let (_window, display) = glium::backend::glutin::SimpleWindowBuilder::new().build(&event_loop); | ||
let event_loop = winit::event_loop::EventLoop::<UserEvent>::with_user_event() | ||
.build() | ||
.map_err(io::Error::other)?; | ||
let event_loop_proxy = event_loop.create_proxy(); | ||
let (_window, display) = glium::backend::glutin::SimpleWindowBuilder::new() | ||
.with_inner_size(format.width, format.height) | ||
.build(&event_loop); | ||
|
||
// building the vertex buffer, which contains all the vertices that we will draw | ||
let vertex_buffer = { | ||
|
@@ -142,61 +157,84 @@ fn main() -> io::Result<()> { | |
} | ||
_ => panic!("invalid buffer pixelformat"), | ||
}; | ||
let _ = event_loop_proxy.send_event(UserEvent::WakeUp); | ||
tx.send(data).unwrap(); | ||
} | ||
}); | ||
|
||
event_loop | ||
.run(move |event, elwt| { | ||
let t0 = Instant::now(); | ||
let data = rx.recv().unwrap(); | ||
let t1 = Instant::now(); | ||
|
||
let image = glium::texture::RawImage2d::from_raw_rgb_reversed( | ||
&data, | ||
(format.width, format.height), | ||
); | ||
let opengl_texture = glium::texture::Texture2d::new(&display, image).unwrap(); | ||
|
||
// building the uniforms | ||
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: &opengl_texture | ||
}; | ||
struct LoopHandler<F> { | ||
user_event: F, | ||
} | ||
|
||
// drawing a frame | ||
let mut target = display.draw(); | ||
target.clear_color(0.0, 0.0, 0.0, 0.0); | ||
target | ||
.draw( | ||
&vertex_buffer, | ||
&index_buffer, | ||
&program, | ||
&uniforms, | ||
&Default::default(), | ||
) | ||
.unwrap(); | ||
target.finish().unwrap(); | ||
impl<F: Fn(UserEvent)> ApplicationHandler<UserEvent> for LoopHandler<F> { | ||
fn resumed(&mut self, _event_loop: &ActiveEventLoop) {} | ||
|
||
fn window_event( | ||
&mut self, | ||
event_loop: &ActiveEventLoop, | ||
_window_id: WindowId, | ||
event: WindowEvent, | ||
) { | ||
// polling and handling the events received by the window | ||
if let winit::event::Event::WindowEvent { | ||
event: winit::event::WindowEvent::CloseRequested, | ||
.. | ||
} = event | ||
{ | ||
elwt.exit(); | ||
if let winit::event::WindowEvent::CloseRequested = event { | ||
event_loop.exit(); | ||
} | ||
} | ||
|
||
print!( | ||
"\rms: {}\t (buffer) + {}\t (UI)", | ||
t1.duration_since(t0).as_millis(), | ||
t0.elapsed().as_millis() | ||
); | ||
fn user_event(&mut self, _event_loop: &ActiveEventLoop, event: UserEvent) { | ||
(self.user_event)(event) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason to not inline the original There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The closure captures the environment. The struct would have to turn every captured variable into a field, so I just took the easiest path. |
||
} | ||
} | ||
|
||
event_loop | ||
.run_app(&mut LoopHandler { | ||
user_event: move |_event| { | ||
let t0 = Instant::now(); | ||
let mut data = rx.recv().unwrap(); | ||
while let Ok(frame) = rx.try_recv() { | ||
data = frame; | ||
} | ||
let data = data; | ||
let t1 = Instant::now(); | ||
|
||
let image = glium::texture::RawImage2d::from_raw_rgb_reversed( | ||
&data, | ||
(format.width, format.height), | ||
); | ||
let opengl_texture = glium::texture::Texture2d::new(&display, image).unwrap(); | ||
|
||
// building the uniforms | ||
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: &opengl_texture | ||
}; | ||
|
||
// drawing a frame | ||
|
||
let mut target = display.draw(); | ||
target.clear_color(0.0, 0.0, 0.0, 0.0); | ||
target | ||
.draw( | ||
&vertex_buffer, | ||
&index_buffer, | ||
&program, | ||
&uniforms, | ||
&Default::default(), | ||
) | ||
.unwrap(); | ||
target.finish().unwrap(); | ||
|
||
print!( | ||
"\rms: {}\t (buffer) + {}\t (UI)", | ||
t1.duration_since(t0).as_millis(), | ||
t1.elapsed().as_millis(), | ||
); | ||
}, | ||
}) | ||
.map_err(io::Error::other) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we send
data
though the proxy instead of needing a separate channel?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kinda, but I think that would make control flow even more complicated. Not every buffer will result in a rendered frame, some buffers will be dropped. Waking up on every buffer from a stream where we can't skip events means that every buffer will have to render, even if there's another one enqueued.
(I'll add the frame skipping next.)