1#![deny(missing_docs)]
4
5use gl;
6use glfw::{self, Glfw, InitError, Window, WindowEvent};
7use luminance::{
8 context::GraphicsContext,
9 framebuffer::{Framebuffer, FramebufferError},
10 texture::Dim2,
11};
12pub use luminance_gl::gl33::StateQueryError;
13use luminance_gl::GL33;
14use std::{error, fmt, os::raw::c_void, sync::mpsc::Receiver};
15
16#[non_exhaustive]
18#[derive(Debug)]
19pub enum GlfwSurfaceError<E> {
20 InitError(InitError),
24
25 UserError(E),
27
28 GraphicsStateError(StateQueryError),
33}
34
35impl<E> fmt::Display for GlfwSurfaceError<E>
36where
37 E: fmt::Display,
38{
39 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
40 match *self {
41 GlfwSurfaceError::InitError(ref e) => write!(f, "initialization error: {}", e),
42 GlfwSurfaceError::UserError(ref e) => write!(f, "user error: {}", e),
43 GlfwSurfaceError::GraphicsStateError(ref e) => {
44 write!(f, "failed to get graphics state: {}", e)
45 }
46 }
47 }
48}
49
50impl<E> From<InitError> for GlfwSurfaceError<E> {
51 fn from(e: InitError) -> Self {
52 GlfwSurfaceError::InitError(e)
53 }
54}
55
56impl<E> error::Error for GlfwSurfaceError<E>
57where
58 E: 'static + error::Error,
59{
60 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
61 match self {
62 GlfwSurfaceError::InitError(e) => Some(e),
63 GlfwSurfaceError::UserError(e) => Some(e),
64 GlfwSurfaceError::GraphicsStateError(e) => Some(e),
65 }
66 }
67}
68
69#[derive(Debug)]
74pub struct GlfwSurface {
75 pub events_rx: Receiver<(f64, WindowEvent)>,
77
78 pub context: GL33Context,
80}
81
82impl GlfwSurface {
83 pub fn new<E>(
85 create_window: impl FnOnce(
86 &mut Glfw,
87 )
88 -> Result<(Window, Receiver<(f64, WindowEvent)>), GlfwSurfaceError<E>>,
89 ) -> Result<Self, GlfwSurfaceError<E>> {
90 #[cfg(feature = "log-errors")]
91 let error_cbk = glfw::LOG_ERRORS;
92 #[cfg(not(feature = "log-errors"))]
93 let error_cbk = glfw::FAIL_ON_ERRORS;
94
95 let mut glfw = glfw::init(error_cbk)?;
96
97 glfw.window_hint(glfw::WindowHint::OpenGlProfile(
99 glfw::OpenGlProfileHint::Core,
100 ));
101 glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
102 glfw.window_hint(glfw::WindowHint::ContextVersionMajor(3));
103 glfw.window_hint(glfw::WindowHint::ContextVersionMinor(3));
104
105 let (mut window, events_rx) = create_window(&mut glfw)?;
106
107 gl::load_with(|s| window.get_proc_address(s) as *const c_void);
109
110 let gl = GL33::new().map_err(GlfwSurfaceError::GraphicsStateError)?;
111 let context = GL33Context { window, gl };
112 let surface = GlfwSurface { events_rx, context };
113
114 Ok(surface)
115 }
116}
117
118#[derive(Debug)]
122pub struct GL33Context {
123 pub window: Window,
125
126 gl: GL33,
128}
129
130impl GL33Context {
131 pub fn back_buffer(&mut self) -> Result<Framebuffer<GL33, Dim2, (), ()>, FramebufferError> {
133 let (w, h) = self.window.get_framebuffer_size();
134 Framebuffer::back_buffer(self, [w as u32, h as u32])
135 }
136}
137
138unsafe impl GraphicsContext for GL33Context {
139 type Backend = GL33;
140
141 fn backend(&mut self) -> &mut Self::Backend {
142 &mut self.gl
143 }
144}