#![deny(missing_docs)]
use luminance::context::GraphicsContext;
use luminance::framebuffer::Framebuffer;
use luminance::framebuffer::FramebufferError;
use luminance::texture::Dim2;
pub use luminance_gl::gl33::StateQueryError;
use luminance_gl::GL33;
pub use sdl2;
use std::fmt;
use std::os::raw::c_void;
#[non_exhaustive]
#[derive(Debug)]
pub enum Sdl2SurfaceError {
InitError(String),
WindowCreationFailed(sdl2::video::WindowBuildError),
GlContextInitFailed(String),
VideoInitError(String),
GraphicsStateError(StateQueryError),
}
impl fmt::Display for Sdl2SurfaceError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Sdl2SurfaceError::InitError(ref e) => write!(f, "initialization error: {}", e),
Sdl2SurfaceError::WindowCreationFailed(ref e) => write!(f, "failed to create window: {}", e),
Sdl2SurfaceError::GlContextInitFailed(ref e) => {
write!(f, "failed to create OpenGL context: {}", e)
}
Sdl2SurfaceError::VideoInitError(ref e) => {
write!(f, "failed to initialize video system: {}", e)
}
Sdl2SurfaceError::GraphicsStateError(ref e) => {
write!(f, "failed to get graphics state: {}", e)
}
}
}
}
pub struct GL33Surface {
sdl: sdl2::Sdl,
window: sdl2::video::Window,
gl: GL33,
_gl_context: sdl2::video::GLContext,
}
impl GL33Surface {
pub fn build_with<WB>(window_builder: WB) -> Result<Self, Sdl2SurfaceError>
where
WB: FnOnce(&sdl2::VideoSubsystem) -> sdl2::video::WindowBuilder,
{
let sdl = sdl2::init().map_err(Sdl2SurfaceError::InitError)?;
let video_system = sdl.video().map_err(Sdl2SurfaceError::VideoInitError)?;
let gl_attr = video_system.gl_attr();
gl_attr.set_context_profile(sdl2::video::GLProfile::Core);
gl_attr.set_context_flags().forward_compatible().set();
gl_attr.set_context_major_version(3);
gl_attr.set_context_minor_version(3);
let window = window_builder(&video_system)
.opengl()
.build()
.map_err(Sdl2SurfaceError::WindowCreationFailed)?;
let _gl_context = window
.gl_create_context()
.map_err(Sdl2SurfaceError::GlContextInitFailed)?;
gl::load_with(|s| video_system.gl_get_proc_address(s) as *const c_void);
let gl = GL33::new().map_err(Sdl2SurfaceError::GraphicsStateError)?;
let surface = GL33Surface {
sdl,
window,
gl,
_gl_context,
};
Ok(surface)
}
pub fn sdl(&self) -> &sdl2::Sdl {
&self.sdl
}
pub fn window(&self) -> &sdl2::video::Window {
&self.window
}
pub fn window_mut(&mut self) -> &mut sdl2::video::Window {
&mut self.window
}
pub fn back_buffer(&mut self) -> Result<Framebuffer<GL33, Dim2, (), ()>, FramebufferError> {
let (w, h) = self.window.drawable_size();
Framebuffer::back_buffer(self, [w, h])
}
}
unsafe impl GraphicsContext for GL33Surface {
type Backend = GL33;
fn backend(&mut self) -> &mut Self::Backend {
&mut self.gl
}
}