luminance_glfw/
lib.rs

1//! [GLFW](https://crates.io/crates/glfw) backend for [luminance](https://crates.io/crates/luminance).
2
3#![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/// Error that can be risen while creating a surface.
17#[non_exhaustive]
18#[derive(Debug)]
19pub enum GlfwSurfaceError<E> {
20  /// Initialization of the surface went wrong.
21  ///
22  /// This variant exposes a **glfw** error for further information about what went wrong.
23  InitError(InitError),
24
25  /// User error.
26  UserError(E),
27
28  /// The graphics state is not available.
29  ///
30  /// This error is generated when the initialization code is called on a thread on which the
31  /// graphics state has already been acquired.
32  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/// GLFW surface.
70///
71/// This type is a helper that exposes two important concepts: the GLFW event receiver that you can use it with to
72/// poll events and the [`GL33Context`], which allows you to perform the rendering part.
73#[derive(Debug)]
74pub struct GlfwSurface {
75  /// Wrapped GLFW events queue.
76  pub events_rx: Receiver<(f64, WindowEvent)>,
77
78  /// Wrapped luminance context.
79  pub context: GL33Context,
80}
81
82impl GlfwSurface {
83  /// Initialize GLFW to provide a luminance environment.
84  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    // OpenGL hints
98    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    // init OpenGL
108    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/// Luminance OpenGL 3.3 context.
119///
120/// This type also re-exports the GLFW window, if you need access to it.
121#[derive(Debug)]
122pub struct GL33Context {
123  /// Wrapped GLFW window.
124  pub window: Window,
125
126  /// OpenGL 3.3 state.
127  gl: GL33,
128}
129
130impl GL33Context {
131  /// Get the back buffer.
132  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}