Convert GLX to the new design

This commit is contained in:
Pierre Krieger 2015-09-21 11:39:34 +02:00
parent 8f3ec7998d
commit b5d0a3eb67
2 changed files with 34 additions and 37 deletions

View file

@ -1,13 +1,14 @@
#![cfg(all(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"), feature = "window"))] #![cfg(all(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"), feature = "window"))]
use BuilderAttribs;
use ContextError; use ContextError;
use CreationError; use CreationError;
use GlAttributes;
use GlContext; use GlContext;
use GlProfile; use GlProfile;
use GlRequest; use GlRequest;
use Api; use Api;
use PixelFormat; use PixelFormat;
use PixelFormatRequirements;
use Robustness; use Robustness;
use libc; use libc;
@ -34,14 +35,14 @@ fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const libc::c_char) ->
} }
impl Context { impl Context {
pub fn new<'a>(glx: ffi::glx::Glx, xlib: &ffi::Xlib, builder: &'a BuilderAttribs<'a>, pub fn new<'a>(glx: ffi::glx::Glx, xlib: &ffi::Xlib, pf_reqs: &PixelFormatRequirements,
display: *mut ffi::Display) opengl: &'a GlAttributes<&'a Context>, display: *mut ffi::Display)
-> Result<ContextPrototype<'a>, CreationError> -> Result<ContextPrototype<'a>, CreationError>
{ {
// finding the pixel format we want // finding the pixel format we want
let (fb_config, pixel_format) = { let (fb_config, pixel_format) = {
let configs = unsafe { try!(enumerate_configs(&glx, xlib, display)) }; let configs = unsafe { try!(enumerate_configs(&glx, xlib, display)) };
try!(builder.choose_pixel_format(configs.into_iter())) try!(pf_reqs.choose_pixel_format(configs.into_iter()))
}; };
// getting the visual infos // getting the visual infos
@ -57,7 +58,7 @@ impl Context {
Ok(ContextPrototype { Ok(ContextPrototype {
glx: glx, glx: glx,
builder: builder, opengl: opengl,
display: display, display: display,
fb_config: fb_config, fb_config: fb_config,
visual_infos: unsafe { mem::transmute(visual_infos) }, visual_infos: unsafe { mem::transmute(visual_infos) },
@ -120,7 +121,7 @@ impl Drop for Context {
pub struct ContextPrototype<'a> { pub struct ContextPrototype<'a> {
glx: ffi::glx::Glx, glx: ffi::glx::Glx,
builder: &'a BuilderAttribs<'a>, opengl: &'a GlAttributes<&'a Context>,
display: *mut ffi::Display, display: *mut ffi::Display,
fb_config: ffi::glx::types::GLXFBConfig, fb_config: ffi::glx::types::GLXFBConfig,
visual_infos: ffi::XVisualInfo, visual_infos: ffi::XVisualInfo,
@ -133,16 +134,9 @@ impl<'a> ContextPrototype<'a> {
} }
pub fn finish(self, window: ffi::Window) -> Result<Context, CreationError> { pub fn finish(self, window: ffi::Window) -> Result<Context, CreationError> {
let share = if let Some(win) = self.builder.opengl.sharing { let share = match self.opengl.sharing {
match win { Some(ctxt) => ctxt.context,
&PlatformWindow::X(ref win) => match win.x.context { None => ptr::null()
::api::x11::Context::Glx(ref c) => c.context,
_ => panic!("Cannot share contexts between different APIs")
},
_ => panic!("Cannot use glx on a non-X11 window.")
}
} else {
ptr::null()
}; };
// loading the list of extensions // loading the list of extensions
@ -160,46 +154,46 @@ impl<'a> ContextPrototype<'a> {
}); });
// creating GL context // creating GL context
let context = match self.builder.opengl.version { let context = match self.opengl.version {
GlRequest::Latest => { GlRequest::Latest => {
if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &extensions, (3, 2), if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &extensions, (3, 2),
self.builder.opengl.profile, self.builder.opengl.debug, self.opengl.profile, self.opengl.debug,
self.builder.opengl.robustness, share, self.opengl.robustness, share,
self.display, self.fb_config, &self.visual_infos) self.display, self.fb_config, &self.visual_infos)
{ {
ctxt ctxt
} else if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &extensions, } else if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &extensions,
(3, 1), self.builder.opengl.profile, (3, 1), self.opengl.profile,
self.builder.opengl.debug, self.opengl.debug,
self.builder.opengl.robustness, share, self.display, self.opengl.robustness, share, self.display,
self.fb_config, &self.visual_infos) self.fb_config, &self.visual_infos)
{ {
ctxt ctxt
} else { } else {
try!(create_context(&self.glx, &extra_functions, &extensions, (1, 0), try!(create_context(&self.glx, &extra_functions, &extensions, (1, 0),
self.builder.opengl.profile, self.builder.opengl.debug, self.opengl.profile, self.opengl.debug,
self.builder.opengl.robustness, self.opengl.robustness,
share, self.display, self.fb_config, &self.visual_infos)) share, self.display, self.fb_config, &self.visual_infos))
} }
}, },
GlRequest::Specific(Api::OpenGl, (major, minor)) => { GlRequest::Specific(Api::OpenGl, (major, minor)) => {
try!(create_context(&self.glx, &extra_functions, &extensions, (major, minor), try!(create_context(&self.glx, &extra_functions, &extensions, (major, minor),
self.builder.opengl.profile, self.builder.opengl.debug, self.opengl.profile, self.opengl.debug,
self.builder.opengl.robustness, share, self.display, self.fb_config, self.opengl.robustness, share, self.display, self.fb_config,
&self.visual_infos)) &self.visual_infos))
}, },
GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"), GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"),
GlRequest::GlThenGles { opengl_version: (major, minor), .. } => { GlRequest::GlThenGles { opengl_version: (major, minor), .. } => {
try!(create_context(&self.glx, &extra_functions, &extensions, (major, minor), try!(create_context(&self.glx, &extra_functions, &extensions, (major, minor),
self.builder.opengl.profile, self.builder.opengl.debug, self.opengl.profile, self.opengl.debug,
self.builder.opengl.robustness, share, self.display, self.fb_config, self.opengl.robustness, share, self.display, self.fb_config,
&self.visual_infos)) &self.visual_infos))
}, },
}; };
// vsync // vsync
if self.builder.opengl.vsync { if self.opengl.vsync {
unsafe { self.glx.MakeCurrent(self.display as *mut _, window, context) }; unsafe { self.glx.MakeCurrent(self.display as *mut _, window, context) };
if extra_functions.SwapIntervalEXT.is_loaded() { if extra_functions.SwapIntervalEXT.is_loaded() {
@ -209,7 +203,8 @@ impl<'a> ContextPrototype<'a> {
} }
// checking that it worked // checking that it worked
if self.builder.strict { // TODO: handle this
/*if self.builder.strict {
let mut swap = unsafe { mem::uninitialized() }; let mut swap = unsafe { mem::uninitialized() };
unsafe { unsafe {
self.glx.QueryDrawable(self.display as *mut _, window, self.glx.QueryDrawable(self.display as *mut _, window,
@ -221,7 +216,7 @@ impl<'a> ContextPrototype<'a> {
return Err(CreationError::OsError(format!("Couldn't setup vsync: expected \ return Err(CreationError::OsError(format!("Couldn't setup vsync: expected \
interval `1` but got `{}`", swap))); interval `1` but got `{}`", swap)));
} }
} }*/
// GLX_MESA_swap_control is not official // GLX_MESA_swap_control is not official
/*} else if extra_functions.SwapIntervalMESA.is_loaded() { /*} else if extra_functions.SwapIntervalMESA.is_loaded() {
@ -234,9 +229,10 @@ impl<'a> ContextPrototype<'a> {
extra_functions.SwapIntervalSGI(1); extra_functions.SwapIntervalSGI(1);
} }
} else if self.builder.strict { }/* else if self.builder.strict {
// TODO: handle this
return Err(CreationError::OsError(format!("Couldn't find any available vsync extension"))); return Err(CreationError::OsError(format!("Couldn't find any available vsync extension")));
} }*/
unsafe { self.glx.MakeCurrent(self.display as *mut _, 0, ptr::null()) }; unsafe { self.glx.MakeCurrent(self.display as *mut _, 0, ptr::null()) };
} }

View file

@ -349,22 +349,23 @@ impl Window {
Egl(::api::egl::ContextPrototype<'a>), Egl(::api::egl::ContextPrototype<'a>),
} }
let builder_clone = builder.clone(); let builder_clone = builder.clone();
let builder_clone_opengl = builder_clone.opengl.clone().map_sharing(|_| unimplemented!()); let builder_clone_opengl_glx = builder_clone.opengl.clone().map_sharing(|_| unimplemented!()); // FIXME:
let builder_clone_opengl_egl = builder_clone.opengl.clone().map_sharing(|_| unimplemented!()); // FIXME:
let context = match builder.opengl.version { let context = match builder.opengl.version {
GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => { GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => {
// GLX should be preferred over EGL, otherwise crashes may occur // GLX should be preferred over EGL, otherwise crashes may occur
// on X11 issue #314 // on X11 issue #314
if let Some(ref glx) = display.glx { if let Some(ref glx) = display.glx {
Prototype::Glx(try!(GlxContext::new(glx.clone(), &display.xlib, &builder_clone, display.display))) Prototype::Glx(try!(GlxContext::new(glx.clone(), &display.xlib, &builder_clone.pf_reqs, &builder_clone_opengl_glx, display.display)))
} else if let Some(ref egl) = display.egl { } else if let Some(ref egl) = display.egl {
Prototype::Egl(try!(EglContext::new(egl.clone(), &builder_clone.pf_reqs, &builder_clone_opengl, egl::NativeDisplay::X11(Some(display.display as *const _))))) Prototype::Egl(try!(EglContext::new(egl.clone(), &builder_clone.pf_reqs, &builder_clone_opengl_egl, egl::NativeDisplay::X11(Some(display.display 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 {
Prototype::Egl(try!(EglContext::new(egl.clone(), &builder_clone.pf_reqs, &builder_clone_opengl, egl::NativeDisplay::X11(Some(display.display as *const _))))) Prototype::Egl(try!(EglContext::new(egl.clone(), &builder_clone.pf_reqs, &builder_clone_opengl_egl, egl::NativeDisplay::X11(Some(display.display as *const _)))))
} else { } else {
return Err(CreationError::NotSupported); return Err(CreationError::NotSupported);
} }