1#![deny(missing_docs)]
4
5use gl;
6use glutin::{
7 event_loop::EventLoop, window::WindowBuilder, Api, ContextBuilder, ContextError, CreationError,
8 GlProfile, GlRequest, NotCurrent, PossiblyCurrent, WindowedContext,
9};
10use luminance::context::GraphicsContext;
11use luminance::framebuffer::{Framebuffer, FramebufferError};
12use luminance::texture::Dim2;
13pub use luminance_gl::gl33::StateQueryError;
14use luminance_gl::GL33;
15use std::error;
16use std::fmt;
17use std::os::raw::c_void;
18
19#[derive(Debug)]
21pub enum GlutinError {
22 CreationError(CreationError),
25 ContextError(ContextError),
27 GraphicsStateError(StateQueryError),
29}
30
31impl fmt::Display for GlutinError {
32 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
33 match *self {
34 GlutinError::CreationError(ref e) => write!(f, "Glutin surface creation error: {}", e),
35 GlutinError::ContextError(ref e) => write!(f, "Glutin OpenGL context creation error: {}", e),
36 GlutinError::GraphicsStateError(ref e) => {
37 write!(f, "OpenGL graphics state initialization error: {}", e)
38 }
39 }
40 }
41}
42
43impl error::Error for GlutinError {
44 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
45 match self {
46 GlutinError::CreationError(e) => Some(e),
47 GlutinError::ContextError(e) => Some(e),
48 GlutinError::GraphicsStateError(e) => Some(e),
49 }
50 }
51}
52
53impl From<CreationError> for GlutinError {
54 fn from(e: CreationError) -> Self {
55 GlutinError::CreationError(e)
56 }
57}
58
59impl From<ContextError> for GlutinError {
60 fn from(e: ContextError) -> Self {
61 GlutinError::ContextError(e)
62 }
63}
64
65impl From<StateQueryError> for GlutinError {
66 fn from(e: StateQueryError) -> Self {
67 GlutinError::GraphicsStateError(e)
68 }
69}
70
71pub struct GlutinSurface {
77 pub ctx: WindowedContext<PossiblyCurrent>,
79 gl: GL33,
81}
82
83unsafe impl GraphicsContext for GlutinSurface {
84 type Backend = GL33;
85
86 fn backend(&mut self) -> &mut Self::Backend {
87 &mut self.gl
88 }
89}
90
91impl GlutinSurface {
92 pub fn new_gl33_from_builders<'a, WB, CB>(
102 window_builder: WB,
103 ctx_builder: CB,
104 ) -> Result<(Self, EventLoop<()>), GlutinError>
105 where
106 WB: FnOnce(&mut EventLoop<()>, WindowBuilder) -> WindowBuilder,
107 CB:
108 FnOnce(&mut EventLoop<()>, ContextBuilder<'a, NotCurrent>) -> ContextBuilder<'a, NotCurrent>,
109 {
110 let mut event_loop = EventLoop::new();
111
112 let window_builder = window_builder(&mut event_loop, WindowBuilder::new());
113
114 let windowed_ctx = ctx_builder(
115 &mut event_loop,
116 ContextBuilder::new()
117 .with_gl(GlRequest::Specific(Api::OpenGl, (3, 3)))
118 .with_gl_profile(GlProfile::Core),
119 )
120 .build_windowed(window_builder, &event_loop)?;
121
122 let ctx = unsafe { windowed_ctx.make_current().map_err(|(_, e)| e)? };
123
124 gl::load_with(|s| ctx.get_proc_address(s) as *const c_void);
126
127 ctx.window().set_visible(true);
128
129 let gl = GL33::new().map_err(GlutinError::GraphicsStateError)?;
130 let surface = GlutinSurface { ctx, gl };
131
132 Ok((surface, event_loop))
133 }
134
135 pub fn new_gl33(
137 window_builder: WindowBuilder,
138 samples: u16,
139 ) -> Result<(Self, EventLoop<()>), GlutinError> {
140 let event_loop = EventLoop::new();
141
142 let windowed_ctx = ContextBuilder::new()
143 .with_gl(GlRequest::Specific(Api::OpenGl, (3, 3)))
144 .with_gl_profile(GlProfile::Core)
145 .with_multisampling(samples)
146 .with_double_buffer(Some(true))
147 .build_windowed(window_builder, &event_loop)?;
148
149 let ctx = unsafe { windowed_ctx.make_current().map_err(|(_, e)| e)? };
150
151 gl::load_with(|s| ctx.get_proc_address(s) as *const c_void);
153
154 ctx.window().set_visible(true);
155
156 let gl = GL33::new().map_err(GlutinError::GraphicsStateError)?;
157 let surface = GlutinSurface { ctx, gl };
158
159 Ok((surface, event_loop))
160 }
161
162 pub fn size(&self) -> [u32; 2] {
167 let size = self.ctx.window().inner_size();
168 [size.width, size.height]
169 }
170
171 pub fn back_buffer(&mut self) -> Result<Framebuffer<GL33, Dim2, (), ()>, FramebufferError> {
173 Framebuffer::back_buffer(self, self.size())
174 }
175
176 pub fn swap_buffers(&mut self) {
178 let _ = self.ctx.swap_buffers();
179 }
180}