Split creating an EGL context in two parts

This commit is contained in:
Pierre Krieger 2015-07-18 18:32:02 +02:00
parent c1ebb8cf31
commit 4eacfce59e
5 changed files with 112 additions and 63 deletions

View file

@ -111,8 +111,8 @@ impl Window {
return Err(OsError(format!("Android's native window is null"))); return Err(OsError(format!("Android's native window is null")));
} }
let context = try!(EglContext::new(egl::ffi::egl::Egl, &builder, None, let context = try!(EglContext::new(egl::ffi::egl::Egl, &builder, None)
native_window as *const _)); .and_then(|p| p.finish(native_window as *const _)));
let (tx, rx) = channel(); let (tx, rx) = channel();
android_glue::add_sender(tx); android_glue::add_sender(tx);

View file

@ -26,9 +26,14 @@ pub struct Context {
} }
impl Context { impl Context {
pub fn new(egl: ffi::egl::Egl, builder: &BuilderAttribs, /// Start building an EGL context.
native_display: Option<ffi::EGLNativeDisplayType>, ///
native_window: ffi::EGLNativeWindowType) -> Result<Context, CreationError> /// This function initializes some things and chooses the pixel format.
///
/// To finish the process, you must call `.finish(window)` on the `ContextPrototype`.
pub fn new<'a>(egl: ffi::egl::Egl, builder: &'a BuilderAttribs<'a>,
native_display: Option<ffi::EGLNativeDisplayType>)
-> Result<ContextPrototype<'a>, CreationError>
{ {
if builder.sharing.is_some() { if builder.sharing.is_some() {
unimplemented!() unimplemented!()
@ -106,60 +111,14 @@ impl Context {
let configs = unsafe { try!(enumerate_configs(&egl, display, &egl_version, api, version)) }; let configs = unsafe { try!(enumerate_configs(&egl, display, &egl_version, api, version)) };
let (config_id, pixel_format) = try!(builder.choose_pixel_format(configs.into_iter())); let (config_id, pixel_format) = try!(builder.choose_pixel_format(configs.into_iter()));
let surface = unsafe { Ok(ContextPrototype {
let surface = egl.CreateWindowSurface(display, config_id, native_window, ptr::null()); builder: builder,
if surface.is_null() {
return Err(CreationError::OsError(format!("eglCreateWindowSurface failed")))
}
surface
};
let context = unsafe {
if let Some(version) = version {
try!(create_context(&egl, display, &egl_version, api, version, config_id,
builder.gl_debug, builder.gl_robustness))
} else if api == Api::OpenGlEs {
if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (2, 0),
config_id, builder.gl_debug, builder.gl_robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (1, 0),
config_id, builder.gl_debug,
builder.gl_robustness)
{
ctxt
} else {
return Err(CreationError::NotSupported);
}
} else {
if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (3, 2),
config_id, builder.gl_debug, builder.gl_robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (3, 1),
config_id, builder.gl_debug,
builder.gl_robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (1, 0),
config_id, builder.gl_debug,
builder.gl_robustness)
{
ctxt
} else {
return Err(CreationError::NotSupported);
}
}
};
Ok(Context {
egl: egl, egl: egl,
display: display, display: display,
context: context, egl_version: egl_version,
surface: surface,
api: api, api: api,
version: version,
config_id: config_id,
pixel_format: pixel_format, pixel_format: pixel_format,
}) })
} }
@ -234,6 +193,96 @@ impl Drop for Context {
} }
} }
pub struct ContextPrototype<'a> {
builder: &'a BuilderAttribs<'a>,
egl: ffi::egl::Egl,
display: ffi::egl::types::EGLDisplay,
egl_version: (ffi::egl::types::EGLint, ffi::egl::types::EGLint),
api: Api,
version: Option<(u8, u8)>,
config_id: ffi::egl::types::EGLConfig,
pixel_format: PixelFormat,
}
impl<'a> ContextPrototype<'a> {
pub fn get_native_visual_id(&self) -> ffi::egl::types::EGLint {
let mut value = unsafe { mem::uninitialized() };
let ret = unsafe { self.egl.GetConfigAttrib(self.display, self.config_id,
ffi::egl::NATIVE_VISUAL_ID
as ffi::egl::types::EGLint, &mut value) };
if ret == 0 { panic!("eglGetConfigAttrib failed") };
value
}
pub fn finish(self, native_window: ffi::EGLNativeWindowType)
-> Result<Context, CreationError>
{
let surface = unsafe {
let surface = self.egl.CreateWindowSurface(self.display, self.config_id, native_window,
ptr::null());
if surface.is_null() {
return Err(CreationError::OsError(format!("eglCreateWindowSurface failed")))
}
surface
};
let context = unsafe {
if let Some(version) = self.version {
try!(create_context(&self.egl, self.display, &self.egl_version, self.api,
version, self.config_id, self.builder.gl_debug,
self.builder.gl_robustness))
} else if self.api == Api::OpenGlEs {
if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
self.api, (2, 0), self.config_id,
self.builder.gl_debug, self.builder.gl_robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
self.api, (1, 0), self.config_id,
self.builder.gl_debug,
self.builder.gl_robustness)
{
ctxt
} else {
return Err(CreationError::NotSupported);
}
} else {
if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
self.api, (3, 2), self.config_id,
self.builder.gl_debug, self.builder.gl_robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
self.api, (3, 1), self.config_id,
self.builder.gl_debug,
self.builder.gl_robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
self.api, (1, 0), self.config_id,
self.builder.gl_debug,
self.builder.gl_robustness)
{
ctxt
} else {
return Err(CreationError::NotSupported);
}
}
};
Ok(Context {
egl: self.egl,
display: self.display,
context: context,
surface: surface,
api: self.api,
pixel_format: self.pixel_format,
})
}
}
unsafe fn enumerate_configs(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDisplay, unsafe fn enumerate_configs(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDisplay,
egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint), egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint),
api: Api, version: Option<(u8, u8)>) api: Api, version: Option<(u8, u8)>)

View file

@ -169,9 +169,9 @@ impl Window {
try!(EglContext::new( try!(EglContext::new(
egl, egl,
&builder, &builder,
Some(wayland_context.display.ptr() as *const _), Some(wayland_context.display.ptr() as *const _))
(*shell_surface).ptr() as *const _ .and_then(|p| p.finish((*shell_surface).ptr() as *const _))
)) )
}; };
let events = Arc::new(Mutex::new(VecDeque::new())); let events = Arc::new(Mutex::new(VecDeque::new()));

View file

@ -177,8 +177,8 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
unsafe { kernel32::GetProcAddress(dll, name.as_ptr()) as *const libc::c_void } unsafe { kernel32::GetProcAddress(dll, name.as_ptr()) as *const libc::c_void }
}); });
if let Ok(c) = EglContext::new(egl, &builder, Some(ptr::null()), if let Ok(c) = EglContext::new(egl, &builder, Some(ptr::null()))
real_window.0) .and_then(|p| p.finish(real_window.0))
{ {
Context::Egl(c) Context::Egl(c)

View file

@ -572,14 +572,14 @@ impl Window {
Context::Glx(try!(GlxContext::new(glx.clone(), builder, display.display, window, Context::Glx(try!(GlxContext::new(glx.clone(), builder, display.display, window,
fb_config, visual_infos))) fb_config, visual_infos)))
} else if let Some(ref egl) = display.egl { } else if let Some(ref egl) = display.egl {
Context::Egl(try!(EglContext::new(egl.clone(), &builder, Some(display.display as *const _), window as *const _))) Context::Egl(try!(EglContext::new(egl.clone(), &builder, Some(display.display as *const _)).and_then(|p| p.finish(window as *const _))))
} else { } else {
return Err(CreationError::NotSupported); return Err(CreationError::NotSupported);
} }
}, },
GlRequest::Specific(Api::OpenGlEs, _) => { GlRequest::Specific(Api::OpenGlEs, _) => {
if let Some(ref egl) = display.egl { if let Some(ref egl) = display.egl {
Context::Egl(try!(EglContext::new(egl.clone(), &builder, Some(display.display as *const _), window as *const _))) Context::Egl(try!(EglContext::new(egl.clone(), &builder, Some(display.display as *const _)).and_then(|p| p.finish(window as *const _))))
} else { } else {
return Err(CreationError::NotSupported); return Err(CreationError::NotSupported);
} }