From baf9b92d3f8a62c6a10d2ea1506e262597e70ac9 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sun, 19 Jul 2015 13:53:40 +0200 Subject: Correct window creation on X11 --- src/api/x11/window.rs | 173 +++++++++++++++++--------------------------------- 1 file changed, 59 insertions(+), 114 deletions(-) (limited to 'src/api/x11/window.rs') diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs index 79118ff..6a4f39a 100644 --- a/src/api/x11/window.rs +++ b/src/api/x11/window.rs @@ -271,7 +271,6 @@ pub struct Window { is_closed: AtomicBool, wm_delete_window: ffi::Atom, current_size: Cell<(libc::c_int, libc::c_int)>, - pixel_format: PixelFormat, /// Events that have been retreived with XLib but not dispatched with iterators yet pending_events: Mutex>, cursor_state: Mutex, @@ -287,64 +286,6 @@ impl Window { _ => unsafe { (display.xlib.XDefaultScreen)(display.display) }, }; - // getting the FBConfig - let fb_config = unsafe { - let mut visual_attributes = vec![ - ffi::glx::X_RENDERABLE as libc::c_int, 1, - ffi::glx::DRAWABLE_TYPE as libc::c_int, ffi::glx::WINDOW_BIT as libc::c_int, - ffi::glx::RENDER_TYPE as libc::c_int, ffi::glx::RGBA_BIT as libc::c_int, - ffi::glx::X_VISUAL_TYPE as libc::c_int, ffi::glx::TRUE_COLOR as libc::c_int, - ffi::glx::RED_SIZE as libc::c_int, 8, - ffi::glx::GREEN_SIZE as libc::c_int, 8, - ffi::glx::BLUE_SIZE as libc::c_int, 8, - ffi::glx::ALPHA_SIZE as libc::c_int, 8, - ffi::glx::DEPTH_SIZE as libc::c_int, 24, - ffi::glx::STENCIL_SIZE as libc::c_int, 8, - ffi::glx::DOUBLEBUFFER as libc::c_int, 1, - ]; - - if let Some(val) = builder.multisampling { - visual_attributes.push(ffi::glx::SAMPLE_BUFFERS as libc::c_int); - visual_attributes.push(1); - visual_attributes.push(ffi::glx::SAMPLES as libc::c_int); - visual_attributes.push(val as libc::c_int); - } - - if let Some(val) = builder.srgb { - visual_attributes.push(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int); - visual_attributes.push(if val {1} else {0}); - } - - visual_attributes.push(0); - - let mut num_fb: libc::c_int = mem::uninitialized(); - - let fb = display.glx.as_ref().unwrap().ChooseFBConfig(display.display as *mut _, (display.xlib.XDefaultScreen)(display.display), - visual_attributes.as_ptr(), &mut num_fb); - if fb.is_null() { - return Err(OsError(format!("glx::ChooseFBConfig failed"))); - } - - let preferred_fb = if builder.transparent { - let mut best_fbi_for_transparent = 0isize; - - for i in 0isize..num_fb as isize { - let vi = display.glx.as_ref().unwrap().GetVisualFromFBConfig(display.display as *mut _, *fb.offset(i)); - if (*vi).depth == 32 { - best_fbi_for_transparent = i; - break; - } - } - - *fb.offset(best_fbi_for_transparent) - } else { - *fb // TODO: choose more wisely - }; - - (display.xlib.XFree)(fb as *mut _); - preferred_fb - }; - // finding the mode to switch to if necessary let (mode_to_switch_to, xf86_desk_mode) = unsafe { let mut mode_num: libc::c_int = mem::uninitialized(); @@ -385,40 +326,53 @@ impl Window { (mode_to_switch_to, xf86_desk_mode) }; - // getting the visual infos - let visual_infos: ffi::glx::types::XVisualInfo = unsafe { - let vi = display.glx.as_ref().unwrap().GetVisualFromFBConfig(display.display as *mut _, fb_config); - if vi.is_null() { - return Err(OsError(format!("glx::ChooseVisual failed"))); - } - let vi_copy = ptr::read(vi as *const _); - (display.xlib.XFree)(vi as *mut _); - vi_copy + // start the context building process + enum Prototype<'a> { + Glx(::api::glx::ContextPrototype<'a>), + Egl(::api::egl::ContextPrototype<'a>), + } + let builder_clone = builder.clone(); + let context = match builder.gl_version { + GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => { + if let Some(ref glx) = display.glx { + Prototype::Glx(try!(GlxContext::new(glx.clone(), &display.xlib, &builder_clone, display.display))) + } else if let Some(ref egl) = display.egl { + Prototype::Egl(try!(EglContext::new(egl.clone(), &builder_clone, Some(display.display as *const _)))) + } else { + return Err(CreationError::NotSupported); + } + }, + GlRequest::Specific(Api::OpenGlEs, _) => { + if let Some(ref egl) = display.egl { + Prototype::Egl(try!(EglContext::new(egl.clone(), &builder_clone, Some(display.display as *const _)))) + } else { + return Err(CreationError::NotSupported); + } + }, + GlRequest::Specific(_, _) => { + return Err(CreationError::NotSupported); + }, }; - // querying the chosen pixel format - let pixel_format = { - let get_attrib = |attrib: libc::c_int| -> i32 { - let mut value = 0; - unsafe { display.glx.as_ref().unwrap().GetFBConfigAttrib(display.display as *mut _, fb_config, attrib, &mut value); } - value - }; - - PixelFormat { - hardware_accelerated: true, - color_bits: get_attrib(ffi::glx::RED_SIZE as libc::c_int) as u8 + - get_attrib(ffi::glx::GREEN_SIZE as libc::c_int) as u8 + - get_attrib(ffi::glx::BLUE_SIZE as libc::c_int) as u8, - alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as libc::c_int) as u8, - depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as libc::c_int) as u8, - stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as libc::c_int) as u8, - stereoscopy: get_attrib(ffi::glx::STEREO as libc::c_int) != 0, - double_buffer: get_attrib(ffi::glx::DOUBLEBUFFER as libc::c_int) != 0, - multisampling: if get_attrib(ffi::glx::SAMPLE_BUFFERS as libc::c_int) != 0 { - Some(get_attrib(ffi::glx::SAMPLES as libc::c_int) as u16) - }else { None }, - srgb: get_attrib(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int) != 0, - } + // getting the `visual_infos` (a struct that contains information about the visual to use) + let visual_infos = match context { + Prototype::Glx(ref p) => p.get_visual_infos().clone(), + Prototype::Egl(ref p) => { + unsafe { + let mut template: ffi::XVisualInfo = mem::zeroed(); + template.visualid = p.get_native_visual_id() as ffi::VisualID; + + let mut num_visuals = 0; + let vi = (display.xlib.XGetVisualInfo)(display.display, ffi::VisualIDMask, + &mut template, &mut num_visuals); + assert!(!vi.is_null()); + assert!(num_visuals == 1); + + let vi_copy = ptr::read(vi as *const _); + (display.xlib.XFree)(vi as *mut _); + vi_copy + } + }, }; // getting the root window @@ -427,7 +381,8 @@ impl Window { // creating the color map let cmap = unsafe { let cmap = (display.xlib.XCreateColormap)(display.display, root, - visual_infos.visual as *mut _, ffi::AllocNone); + visual_infos.visual as *mut _, + ffi::AllocNone); // TODO: error checking? cmap }; @@ -545,27 +500,14 @@ impl Window { } let is_fullscreen = builder.monitor.is_some(); - // creating the context - let context = match builder.gl_version { - GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => { - if let Some(ref glx) = display.glx { - 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 _)).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 _)).and_then(|p| p.finish(window as *const _)))) - } else { - return Err(CreationError::NotSupported); - } + + // finish creating the OpenGL context + let context = match context { + Prototype::Glx(ctxt) => { + Context::Glx(try!(ctxt.finish(window))) }, - GlRequest::Specific(_, _) => { - return Err(CreationError::NotSupported); + Prototype::Egl(ctxt) => { + Context::Egl(try!(ctxt.finish(window as *const libc::c_void))) }, }; @@ -585,7 +527,6 @@ impl Window { is_closed: AtomicBool::new(false), wm_delete_window: wm_delete_window, current_size: Cell::new((0, 0)), - pixel_format: pixel_format, pending_events: Mutex::new(VecDeque::new()), cursor_state: Mutex::new(CursorState::Normal), input_handler: Mutex::new(XInputEventHandler::new(display, window, ic)) @@ -835,6 +776,10 @@ impl GlContext for Window { } fn get_pixel_format(&self) -> PixelFormat { - self.pixel_format.clone() + match self.x.context { + Context::Glx(ref ctxt) => ctxt.get_pixel_format(), + Context::Egl(ref ctxt) => ctxt.get_pixel_format(), + Context::None => panic!() + } } } -- cgit v1.2.3