1#![deny(missing_docs)]
4
5use luminance::context::GraphicsContext;
6use luminance::framebuffer::Framebuffer;
7use luminance::framebuffer::FramebufferError;
8use luminance::texture::Dim2;
9pub use luminance_gl::gl33::StateQueryError;
10use luminance_gl::GL33;
11pub use sdl2;
12use std::fmt;
13use std::os::raw::c_void;
14
15#[non_exhaustive]
17#[derive(Debug)]
18pub enum Sdl2SurfaceError {
19 InitError(String),
21 WindowCreationFailed(sdl2::video::WindowBuildError),
23 GlContextInitFailed(String),
25 VideoInitError(String),
27 GraphicsStateError(StateQueryError),
32}
33
34impl fmt::Display for Sdl2SurfaceError {
35 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
36 match *self {
37 Sdl2SurfaceError::InitError(ref e) => write!(f, "initialization error: {}", e),
38 Sdl2SurfaceError::WindowCreationFailed(ref e) => write!(f, "failed to create window: {}", e),
39 Sdl2SurfaceError::GlContextInitFailed(ref e) => {
40 write!(f, "failed to create OpenGL context: {}", e)
41 }
42 Sdl2SurfaceError::VideoInitError(ref e) => {
43 write!(f, "failed to initialize video system: {}", e)
44 }
45 Sdl2SurfaceError::GraphicsStateError(ref e) => {
46 write!(f, "failed to get graphics state: {}", e)
47 }
48 }
49 }
50}
51
52pub struct GL33Surface {
65 sdl: sdl2::Sdl,
66 window: sdl2::video::Window,
67 gl: GL33,
68 _gl_context: sdl2::video::GLContext,
70}
71
72impl GL33Surface {
73 pub fn build_with<WB>(window_builder: WB) -> Result<Self, Sdl2SurfaceError>
94 where
95 WB: FnOnce(&sdl2::VideoSubsystem) -> sdl2::video::WindowBuilder,
96 {
97 let sdl = sdl2::init().map_err(Sdl2SurfaceError::InitError)?;
98
99 let video_system = sdl.video().map_err(Sdl2SurfaceError::VideoInitError)?;
100
101 let gl_attr = video_system.gl_attr();
102
103 gl_attr.set_context_profile(sdl2::video::GLProfile::Core);
104 gl_attr.set_context_flags().forward_compatible().set();
105 gl_attr.set_context_major_version(3);
106 gl_attr.set_context_minor_version(3);
107
108 let window = window_builder(&video_system)
109 .opengl()
110 .build()
111 .map_err(Sdl2SurfaceError::WindowCreationFailed)?;
112
113 let _gl_context = window
114 .gl_create_context()
115 .map_err(Sdl2SurfaceError::GlContextInitFailed)?;
116
117 gl::load_with(|s| video_system.gl_get_proc_address(s) as *const c_void);
118
119 let gl = GL33::new().map_err(Sdl2SurfaceError::GraphicsStateError)?;
120 let surface = GL33Surface {
121 sdl,
122 window,
123 gl,
124 _gl_context,
125 };
126
127 Ok(surface)
128 }
129
130 pub fn sdl(&self) -> &sdl2::Sdl {
132 &self.sdl
133 }
134
135 pub fn window(&self) -> &sdl2::video::Window {
137 &self.window
138 }
139
140 pub fn window_mut(&mut self) -> &mut sdl2::video::Window {
142 &mut self.window
143 }
144
145 pub fn back_buffer(&mut self) -> Result<Framebuffer<GL33, Dim2, (), ()>, FramebufferError> {
147 let (w, h) = self.window.drawable_size();
148 Framebuffer::back_buffer(self, [w, h])
149 }
150}
151
152unsafe impl GraphicsContext for GL33Surface {
153 type Backend = GL33;
154
155 fn backend(&mut self) -> &mut Self::Backend {
156 &mut self.gl
157 }
158}