1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use gl;
use glfw::{self, Context, CursorMode, SwapInterval, Window, WindowMode};
use luminance::context::GraphicsContext;
use luminance::state::GraphicsState;
pub use luminance_windowing::{Surface, WindowDim, WindowOpt};
use std::cell::RefCell;
use std::os::raw::c_void;
use std::rc::Rc;
use std::sync::mpsc::Receiver;
pub use event::{Action, Key, MouseButton, WindowEvent};
pub use error::{InitError, GlfwSurfaceError, StateQueryError};
pub struct GlfwSurface {
window: Window,
events_rx: Receiver<(f64, WindowEvent)>,
gfx_state: Rc<RefCell<GraphicsState>>,
}
unsafe impl GraphicsContext for GlfwSurface {
fn state(&self) -> &Rc<RefCell<GraphicsState>> {
&self.gfx_state
}
fn swap_buffers(&mut self) {
self.window.swap_buffers();
}
}
impl Surface for GlfwSurface {
type Event = WindowEvent;
type Error = GlfwSurfaceError;
fn new(dim: WindowDim, title: &str, win_opt: WindowOpt) -> Result<Self, Self::Error> {
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).map_err(GlfwSurfaceError::InitError)?;
glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
glfw.window_hint(glfw::WindowHint::ContextVersionMajor(3));
glfw.window_hint(glfw::WindowHint::ContextVersionMinor(3));
let (mut window, events_rx) = match dim {
WindowDim::Windowed(w, h) => {
glfw.create_window(w,
h,
title,
WindowMode::Windowed).ok_or(GlfwSurfaceError::WindowCreationFailed)?
},
WindowDim::Fullscreen => {
glfw.with_primary_monitor(|glfw, monitor| {
let monitor = monitor.ok_or(GlfwSurfaceError::NoPrimaryMonitor)?;
let vmode = monitor.get_video_mode().ok_or(GlfwSurfaceError::NoVideoMode)?;
let (w, h) = (vmode.width, vmode.height);
Ok(glfw.create_window(w,
h,
title,
WindowMode::FullScreen(monitor)
).ok_or(GlfwSurfaceError::WindowCreationFailed)?)
})?
},
WindowDim::FullscreenRestricted(w, h) => {
glfw.with_primary_monitor(|glfw, monitor| {
let monitor = monitor.ok_or(GlfwSurfaceError::NoPrimaryMonitor)?;
Ok(glfw.create_window(w,
h,
title,
WindowMode::FullScreen(monitor)
).ok_or(GlfwSurfaceError::WindowCreationFailed)?)
})?
}
};
window.make_current();
if win_opt.is_cursor_hidden() {
window.set_cursor_mode(CursorMode::Disabled);
}
window.set_all_polling(true);
glfw.set_swap_interval(SwapInterval::Sync(1));
gl::load_with(|s| window.get_proc_address(s) as *const c_void);
let gfx_state = GraphicsState::new().map_err(GlfwSurfaceError::GraphicsStateError)?;
let surface = GlfwSurface {
window,
events_rx,
gfx_state: Rc::new(RefCell::new(gfx_state)),
};
Ok(surface)
}
fn size(&self) -> [u32; 2] {
let (x, y) = self.window.get_framebuffer_size();
[x as u32, y as u32]
}
fn wait_events<'a>(&'a mut self) -> Box<Iterator<Item = Self::Event> + 'a> {
self.window.glfw.wait_events();
Box::new(self.events_rx.iter().map(|(_, e)| e))
}
fn poll_events<'a>(&'a mut self) -> Box<Iterator<Item = Self::Event> + 'a> {
self.window.glfw.poll_events();
Box::new(self.events_rx.try_iter().map(|(_, e)| e))
}
}