From 4eacfce59e99e4d841255a053ce6acdc77b0c91c Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 18 Jul 2015 18:32:02 +0200 Subject: Split creating an EGL context in two parts --- src/api/android/mod.rs | 4 +- src/api/egl/mod.rs | 157 ++++++++++++++++++++++++++++++++----------------- src/api/wayland/mod.rs | 6 +- src/api/win32/init.rs | 4 +- src/api/x11/window.rs | 4 +- 5 files changed, 112 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/api/android/mod.rs b/src/api/android/mod.rs index 1649772..b5fac08 100644 --- a/src/api/android/mod.rs +++ b/src/api/android/mod.rs @@ -111,8 +111,8 @@ impl Window { return Err(OsError(format!("Android's native window is null"))); } - let context = try!(EglContext::new(egl::ffi::egl::Egl, &builder, None, - native_window as *const _)); + let context = try!(EglContext::new(egl::ffi::egl::Egl, &builder, None) + .and_then(|p| p.finish(native_window as *const _))); let (tx, rx) = channel(); android_glue::add_sender(tx); diff --git a/src/api/egl/mod.rs b/src/api/egl/mod.rs index 1a6cc06..0cb6dbd 100644 --- a/src/api/egl/mod.rs +++ b/src/api/egl/mod.rs @@ -26,9 +26,14 @@ pub struct Context { } impl Context { - pub fn new(egl: ffi::egl::Egl, builder: &BuilderAttribs, - native_display: Option, - native_window: ffi::EGLNativeWindowType) -> Result + /// Start building an EGL context. + /// + /// 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) + -> Result, CreationError> { if builder.sharing.is_some() { unimplemented!() @@ -106,60 +111,14 @@ impl Context { 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 surface = unsafe { - let surface = egl.CreateWindowSurface(display, 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) = 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 { + Ok(ContextPrototype { + builder: builder, egl: egl, display: display, - context: context, - surface: surface, + egl_version: egl_version, api: api, + version: version, + config_id: config_id, 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 + { + 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, egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint), api: Api, version: Option<(u8, u8)>) diff --git a/src/api/wayland/mod.rs b/src/api/wayland/mod.rs index 0af5496..826826e 100644 --- a/src/api/wayland/mod.rs +++ b/src/api/wayland/mod.rs @@ -169,9 +169,9 @@ impl Window { try!(EglContext::new( egl, &builder, - Some(wayland_context.display.ptr() as *const _), - (*shell_surface).ptr() as *const _ - )) + Some(wayland_context.display.ptr() as *const _)) + .and_then(|p| p.finish((*shell_surface).ptr() as *const _)) + ) }; let events = Arc::new(Mutex::new(VecDeque::new())); diff --git a/src/api/win32/init.rs b/src/api/win32/init.rs index cc6d2d2..fdb88c9 100644 --- a/src/api/win32/init.rs +++ b/src/api/win32/init.rs @@ -177,8 +177,8 @@ unsafe fn init(title: Vec, builder: BuilderAttribs<'static>, unsafe { kernel32::GetProcAddress(dll, name.as_ptr()) as *const libc::c_void } }); - if let Ok(c) = EglContext::new(egl, &builder, Some(ptr::null()), - real_window.0) + if let Ok(c) = EglContext::new(egl, &builder, Some(ptr::null())) + .and_then(|p| p.finish(real_window.0)) { Context::Egl(c) diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs index 15e27ce..04ad2ab 100644 --- a/src/api/x11/window.rs +++ b/src/api/x11/window.rs @@ -572,14 +572,14 @@ impl Window { Context::Glx(try!(GlxContext::new(glx.clone(), builder, display.display, window, fb_config, visual_infos))) } 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 { return Err(CreationError::NotSupported); } }, GlRequest::Specific(Api::OpenGlEs, _) => { 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 { return Err(CreationError::NotSupported); } -- cgit v1.2.3