use egl;
use std::ptr;
use error::Result;
use {Surface, Context, Version, FrameBufferConfigRef, ConfigFilterRef};
pub enum ContextClientVersion {
OpenGlEs1,
OpenGlEs2,
}
pub struct Display {
terminated: bool,
handle: egl::EGLDisplay,
}
impl Drop for Display {
fn drop(&mut self) {
if !self.terminated {
let _ = self.make_not_current();
let _ = egl::terminate(self.handle);
}
}
}
impl Into<egl::EGLDisplay> for Display {
fn into(self) -> egl::EGLDisplay {
self.forget()
}
}
impl Display {
pub fn from_display_id(display_id: egl::EGLNativeDisplayType) -> Result<Display> {
match egl::get_display(display_id) {
Ok(handle) => {
Ok(Display {
terminated: false,
handle: handle,
})
}
Err(e) => Err(e.into()),
}
}
pub fn from_default_display() -> Result<Display> {
Display::from_display_id(egl::EGL_DEFAULT_DISPLAY)
}
pub fn initialize_and_get_version(&self) -> Result<Version> {
let (mut major, mut minor) = (0, 0);
egl::initialize_and_get_version(self.handle, &mut major, &mut minor)?;
Ok(Version {
major: major as i32,
minor: minor as i32,
})
}
pub fn initialize(&self) -> Result<()> {
egl::initialize(self.handle)?;
Ok(())
}
pub fn query_client_apis(&self) -> Result<&'static str> {
let cstr = egl::query_string(self.handle, egl::EGL_CLIENT_APIS)?;
Ok(cstr.to_str()?)
}
pub fn query_vendor(&self) -> Result<&'static str> {
let cstr = egl::query_string(self.handle, egl::EGL_VENDOR)?;
Ok(cstr.to_str()?)
}
pub fn query_version(&self) -> Result<&'static str> {
let cstr = egl::query_string(self.handle, egl::EGL_VERSION)?;
Ok(cstr.to_str()?)
}
pub fn query_extensions(&self) -> Result<&'static str> {
let cstr = egl::query_string(self.handle, egl::EGL_EXTENSIONS)?;
Ok(cstr.to_str()?)
}
pub fn get_configs(&self) -> Result<Vec<FrameBufferConfigRef>> {
let count = egl::num_configs(self.handle)? as usize;
let mut configs: Vec<egl::EGLConfig> = vec![ptr::null_mut(); count];
let returned_count = egl::get_configs(self.handle, &mut configs)? as usize;
Ok(configs[..returned_count]
.iter()
.map(|c| FrameBufferConfigRef::from_native(self.handle, *c))
.collect())
}
pub fn config_filter(&self) -> ConfigFilterRef {
ConfigFilterRef::from_native(self.handle)
}
pub fn create_window_surface(&self,
config: FrameBufferConfigRef,
window: egl::EGLNativeWindowType)
-> Result<Surface> {
let maybe_handle = egl::create_window_surface(self.handle, config.handle(), window);
Ok(Surface::from_handle(self.handle, maybe_handle?))
}
pub fn create_context(&self, config: FrameBufferConfigRef) -> Result<Context> {
let maybe_handle = egl::create_context(self.handle, config.handle());
Ok(Context::from_handle(self.handle, maybe_handle?))
}
pub fn create_context_with_client_version(&self,
config: FrameBufferConfigRef,
client_version: ContextClientVersion)
-> Result<Context> {
let attribs = [egl::EGL_CONTEXT_CLIENT_VERSION,
match client_version {
ContextClientVersion::OpenGlEs1 => 1,
ContextClientVersion::OpenGlEs2 => 2,
},
egl::EGL_NONE];
let maybe_handle = egl::create_context_with_attribs(self.handle,
config.handle(),
ptr::null_mut(),
&attribs);
Ok(Context::from_handle(self.handle, maybe_handle?))
}
pub fn make_current(&self, draw: &Surface, read: &Surface, context: &Context) -> Result<()> {
egl::make_current(self.handle, draw.handle(), read.handle(), context.handle())?;
Ok(())
}
pub fn make_not_current(&self) -> Result<()> {
egl::make_current(self.handle,
egl::EGL_NO_SURFACE,
egl::EGL_NO_SURFACE,
egl::EGL_NO_CONTEXT)?;
Ok(())
}
pub fn swap_buffers(&self, surface: &Surface) -> Result<()> {
egl::swap_buffers(self.handle, surface.handle())?;
Ok(())
}
pub fn with_handle<F, R>(&self, action: F) -> R
where F: FnOnce(egl::EGLDisplay) -> R
{
action(self.handle)
}
pub fn forget(mut self) -> egl::EGLDisplay {
self.terminated = true;
self.handle
}
}