diff --git a/.gitignore b/.gitignore index a36df82ca5..4461cbc942 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ Cargo.lock target/ +.DS_Store *~ #*# diff --git a/src/headless.rs b/src/headless.rs index a1e24a10a4..91125182f8 100644 --- a/src/headless.rs +++ b/src/headless.rs @@ -33,7 +33,10 @@ impl<'a> HeadlessRendererBuilder<'a> { pub fn new(width: u32, height: u32) -> HeadlessRendererBuilder<'a> { HeadlessRendererBuilder { dimensions: (width, height), - pf_reqs: Default::default(), + pf_reqs: PixelFormatRequirements { + hardware_accelerated: None, + .. Default::default() + }, opengl: Default::default(), platform_specific: Default::default(), } diff --git a/src/lib.rs b/src/lib.rs index 21b41e1537..ad36ebd0b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ #[macro_use] extern crate lazy_static; +#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] #[macro_use] extern crate shared_library; diff --git a/src/platform/macos/headless.rs b/src/platform/macos/headless.rs index 31030e71da..8ab9245a47 100644 --- a/src/platform/macos/headless.rs +++ b/src/platform/macos/headless.rs @@ -26,10 +26,9 @@ impl HeadlessContext { _: &PlatformSpecificHeadlessBuilderAttributes) -> Result { + let gl_profile = helpers::get_gl_profile(opengl)?; + let attributes = helpers::build_nsattributes(pf_reqs, gl_profile)?; let context = unsafe { - - let attributes = try!(helpers::build_nsattributes(pf_reqs, opengl)); - let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes); if pixelformat == nil { return Err(OsError(format!("Could not create the pixel format"))); @@ -42,7 +41,7 @@ impl HeadlessContext { }; let headless = HeadlessContext { - context: context, + context, }; Ok(headless) diff --git a/src/platform/macos/helpers.rs b/src/platform/macos/helpers.rs index daa3044d52..8ac965a9f9 100644 --- a/src/platform/macos/helpers.rs +++ b/src/platform/macos/helpers.rs @@ -6,38 +6,59 @@ use GlRequest; use PixelFormatRequirements; use ReleaseBehavior; use cocoa::appkit::*; - -pub fn build_nsattributes(pf_reqs: &PixelFormatRequirements, opengl: &GlAttributes<&T>) - -> Result, CreationError> { - - let profile = match (opengl.version, opengl.version.to_gl_version(), opengl.profile) { - +use cocoa::base::nil; + +pub fn get_gl_profile( + opengl: &GlAttributes<&T> +) -> Result { + let version = opengl.version.to_gl_version(); + // first, compatibility profile support is strict + if opengl.profile == Some(GlProfile::Compatibility) { // Note: we are not using ranges because of a rust bug that should be fixed here: // https://github.com/rust-lang/rust/pull/27050 - - (GlRequest::Latest, _, Some(GlProfile::Compatibility)) => NSOpenGLProfileVersionLegacy as u32, - (GlRequest::Latest, _, _) => unsafe { - if NSAppKitVersionNumber.floor() >= NSAppKitVersionNumber10_9 { - NSOpenGLProfileVersion4_1Core as u32 - } else if NSAppKitVersionNumber.floor() >= NSAppKitVersionNumber10_7 { - NSOpenGLProfileVersion3_2Core as u32 - } else { - NSOpenGLProfileVersionLegacy as u32 + if version.unwrap_or((2, 1)) < (3, 2) { + Ok(NSOpenGLProfileVersionLegacy) + } else { + Err(CreationError::OpenGlVersionNotSupported) + } + } else if let Some(v) = version { + // second, process exact requested version, if any + if v < (3, 2) { + Err(CreationError::OpenGlVersionNotSupported) + } else if v == (3, 2) { + Ok(NSOpenGLProfileVersion3_2Core) + } else { + Ok(NSOpenGLProfileVersion4_1Core) + } + } else if let GlRequest::Latest = opengl.version { + // now, find the latest supported version automatically + let mut attributes = vec![ + // Note: we assume here that non-accelerated contexts don't care + NSOpenGLPFAAccelerated as u32, + NSOpenGLPFAOpenGLProfile as u32, + 0, // this is where we put the test profile + 0, + ]; + for &profile in &[NSOpenGLProfileVersion4_1Core, NSOpenGLProfileVersion3_2Core] { + attributes[2] = profile as u32; + let id = unsafe { + NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes) + }; + if id != nil { + unsafe { msg_send![id, release] } + return Ok(profile); } - }, - - (_, Some((1, _)), _) => NSOpenGLProfileVersionLegacy as u32, - (_, Some((2, _)), _) => NSOpenGLProfileVersionLegacy as u32, - (_, Some((3, 0)), _) => NSOpenGLProfileVersionLegacy as u32, - (_, Some((3, 1)), _) => NSOpenGLProfileVersionLegacy as u32, - (_, Some((3, 2)), _) => NSOpenGLProfileVersion3_2Core as u32, - (_, Some((3, _)), Some(GlProfile::Compatibility)) => return Err(CreationError::OpenGlVersionNotSupported), - (_, Some((3, _)), _) => NSOpenGLProfileVersion4_1Core as u32, - (_, Some((4, _)), Some(GlProfile::Compatibility)) => return Err(CreationError::OpenGlVersionNotSupported), - (_, Some((4, _)), _) => NSOpenGLProfileVersion4_1Core as u32, - _ => return Err(CreationError::OpenGlVersionNotSupported), - }; + } + // nothing else to do + Ok(NSOpenGLProfileVersionLegacy) + } else { + Err(CreationError::OpenGlVersionNotSupported) + } +} +pub fn build_nsattributes( + pf_reqs: &PixelFormatRequirements, profile: NSOpenGLPFAOpenGLProfiles +) -> Result, CreationError> { // NOTE: OS X no longer has the concept of setting individual // color component's bit size. Instead we can only specify the // full color size and hope for the best. Another hiccup is that @@ -46,19 +67,24 @@ pub fn build_nsattributes(pf_reqs: &PixelFormatRequirements, opengl: &GlAttri let alpha_depth = pf_reqs.alpha_bits.unwrap_or(8); let color_depth = pf_reqs.color_bits.unwrap_or(24) + alpha_depth; - // TODO: handle hardware_accelerated parameter of pf_reqs - let mut attributes = vec![ - NSOpenGLPFADoubleBuffer as u32, + NSOpenGLPFAOpenGLProfile as u32, profile as u32, NSOpenGLPFAClosestPolicy as u32, NSOpenGLPFAColorSize as u32, color_depth as u32, NSOpenGLPFAAlphaSize as u32, alpha_depth as u32, NSOpenGLPFADepthSize as u32, pf_reqs.depth_bits.unwrap_or(24) as u32, NSOpenGLPFAStencilSize as u32, pf_reqs.stencil_bits.unwrap_or(8) as u32, NSOpenGLPFAAllowOfflineRenderers as u32, - NSOpenGLPFAOpenGLProfile as u32, profile, ]; + if let Some(true) = pf_reqs.hardware_accelerated { + attributes.push(NSOpenGLPFAAccelerated as u32); + } + + if let Some(true) = pf_reqs.double_buffer { + attributes.push(NSOpenGLPFADoubleBuffer as u32); + } + if pf_reqs.release_behavior != ReleaseBehavior::Flush { return Err(CreationError::NoAvailablePixelFormat); } @@ -67,19 +93,15 @@ pub fn build_nsattributes(pf_reqs: &PixelFormatRequirements, opengl: &GlAttri unimplemented!(); // TODO: } - if pf_reqs.double_buffer == Some(false) { - unimplemented!(); // TODO: - } - if pf_reqs.float_color_buffer { attributes.push(NSOpenGLPFAColorFloat as u32); } - pf_reqs.multisampling.map(|samples| { + if let Some(samples) = pf_reqs.multisampling { attributes.push(NSOpenGLPFAMultisample as u32); attributes.push(NSOpenGLPFASampleBuffers as u32); attributes.push(1); attributes.push(NSOpenGLPFASamples as u32); attributes.push(samples as u32); - }); + } // attribute list must be null terminated. attributes.push(0); diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index eb2f8df8a9..6b8b05b125 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -61,7 +61,8 @@ impl Context { let view = window.get_nsview() as id; - let attributes = try!(helpers::build_nsattributes(pf_reqs, gl_attr)); + let gl_profile = helpers::get_gl_profile(gl_attr)?; + let attributes = helpers::build_nsattributes(pf_reqs, gl_profile)?; unsafe { let pixel_format = IdRef::new(NSOpenGLPixelFormat::alloc(nil) .initWithAttributes_(&attributes)); @@ -138,13 +139,12 @@ impl Context { unsafe { let pool = NSAutoreleasePool::new(nil); let current = NSOpenGLContext::currentContext(nil); - let mut res = false; - if current != nil { + let res = if current != nil { let is_equal: BOOL = msg_send![current, isEqual:*self.gl]; - res = is_equal != NO + is_equal != NO } else { - res = false - } + false + }; let _: () = msg_send![pool, release]; res }