Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate the builder attributes into multiple substates #603

Merged
merged 12 commits into from
Sep 21, 2015
23 changes: 17 additions & 6 deletions src/api/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ use events::MouseButton;
use std::collections::VecDeque;

use Api;
use BuilderAttribs;
use ContextError;
use CursorState;
use GlAttributes;
use GlContext;
use GlRequest;
use PixelFormat;
use PixelFormatRequirements;
use WindowAttributes;
use native_monitor::NativeMonitorId;

use api::egl;
Expand Down Expand Up @@ -104,15 +106,20 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
}

impl Window {
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
pub fn new(win_attribs: &WindowAttributes, pf_reqs: &PixelFormatRequirements,
opengl: &GlAttributes<&Window>) -> Result<Window, CreationError>
{
use std::{mem, ptr};

let opengl = opengl.clone().map_sharing(|w| &w.context);

let native_window = unsafe { android_glue::get_native_window() };
if native_window.is_null() {
return Err(OsError(format!("Android's native window is null")));
}

let context = try!(EglContext::new(egl::ffi::egl::Egl, &builder, egl::NativeDisplay::Android)
let context = try!(EglContext::new(egl::ffi::egl::Egl, pf_reqs, &opengl,
egl::NativeDisplay::Android)
.and_then(|p| p.finish(native_window as *const _)));

let (tx, rx) = channel();
Expand Down Expand Up @@ -254,9 +261,13 @@ pub struct HeadlessContext(EglContext);

impl HeadlessContext {
/// See the docs in the crate root file.
pub fn new(builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> {
let context = try!(EglContext::new(egl::ffi::egl::Egl, &builder, egl::NativeDisplay::Android));
let context = try!(context.finish_pbuffer());
pub fn new(dimensions: (u32, u32), pf_reqs: &PixelFormatRequirements,
opengl: &GlAttributes<&HeadlessContext>) -> Result<HeadlessContext, CreationError>
{
let opengl = opengl.clone().map_sharing(|c| &c.0);
let context = try!(EglContext::new(egl::ffi::egl::Egl, pf_reqs, &opengl,
egl::NativeDisplay::Android));
let context = try!(context.finish_pbuffer(dimensions)); // TODO:
Ok(HeadlessContext(context))
}
}
Expand Down
14 changes: 11 additions & 3 deletions src/api/caca/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ use libc;
use api::osmesa::{OsMesaContext, OsMesaCreationError};

use Api;
use BuilderAttribs;
use ContextError;
use CreationError;
use Event;
use GlAttributes;
use GlContext;
use PixelFormat;
use PixelFormatRequirements;
use CursorState;
use MouseCursor;
use WindowAttributes;

use std::collections::VecDeque;
use std::path::Path;
Expand Down Expand Up @@ -84,8 +86,14 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
}

impl Window {
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
let opengl = match OsMesaContext::new(builder) {
pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements,
opengl: &GlAttributes<&Window>) -> Result<Window, CreationError>
{
let opengl = opengl.clone().map_sharing(|w| &w.opengl);

let opengl = match OsMesaContext::new(window.dimensions.unwrap_or((800, 600)), pf_reqs,
&opengl)
{
Err(OsMesaCreationError::NotSupported) => return Err(CreationError::NotSupported),
Err(OsMesaCreationError::CreationError(e)) => return Err(e),
Ok(c) => c
Expand Down
8 changes: 5 additions & 3 deletions src/api/cocoa/headless.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use ContextError;
use CreationError;
use CreationError::OsError;
use BuilderAttribs;
use GlAttributes;
use GlContext;
use PixelFormatRequirements;
use libc;
use std::ptr;

Expand All @@ -27,8 +28,9 @@ pub struct HeadlessContext {
}

impl HeadlessContext {
pub fn new(builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> {
let (width, height) = builder.dimensions.unwrap_or((1024, 768));
pub fn new((width, height): (u32, u32), pf_reqs: &PixelFormatRequirements,
opengl: &GlAttributes<&HeadlessContext>) -> Result<HeadlessContext, CreationError>
{
let context = unsafe {
let attributes = [
NSOpenGLPFAAccelerated as u32,
Expand Down
48 changes: 27 additions & 21 deletions src/api/cocoa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ use CreationError::OsError;
use libc;

use Api;
use BuilderAttribs;
use ContextError;
use GlAttributes;
use GlContext;
use GlProfile;
use GlRequest;
use PixelFormat;
use PixelFormatRequirements;
use Robustness;
use WindowAttributes;
use native_monitor::NativeMonitorId;

use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
Expand Down Expand Up @@ -266,12 +268,14 @@ impl<'a> Iterator for WaitEventsIterator<'a> {

impl Window {
#[cfg(feature = "window")]
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
if builder.sharing.is_some() {
pub fn new(win_attribs: &WindowAttributes, pf_reqs: &PixelFormatRequirements,
opengl: &GlAttributes<&Window>) -> Result<Window, CreationError>
{
if opengl.sharing.is_some() {
unimplemented!()
}

match builder.gl_robustness {
match opengl.robustness {
Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => {
return Err(CreationError::RobustnessNotSupported);
},
Expand All @@ -283,7 +287,7 @@ impl Window {
None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
};

let window = match Window::create_window(&builder)
let window = match Window::create_window(win_attribs)
{
Some(window) => window,
None => { return Err(OsError(format!("Couldn't create NSWindow"))); },
Expand All @@ -295,13 +299,13 @@ impl Window {

// TODO: perhaps we should return error from create_context so we can
// determine the cause of failure and possibly recover?
let (context, pf) = match Window::create_context(*view, &builder) {
let (context, pf) = match Window::create_context(*view, pf_reqs, opengl) {
Ok((context, pf)) => (context, pf),
Err(e) => { return Err(OsError(format!("Couldn't create OpenGL context: {}", e))); },
};

unsafe {
if builder.transparent {
if win_attribs.transparent {
let clear_col = {
let cls = Class::get("NSColor").unwrap();

Expand All @@ -317,7 +321,7 @@ impl Window {
}

app.activateIgnoringOtherApps_(YES);
if builder.visible {
if win_attribs.visible {
window.makeKeyAndOrderFront_(nil);
} else {
window.makeKeyWindow();
Expand Down Expand Up @@ -356,9 +360,9 @@ impl Window {
}
}

fn create_window(builder: &BuilderAttribs) -> Option<IdRef> {
fn create_window(attrs: &WindowAttributes) -> Option<IdRef> {
unsafe {
let screen = match builder.monitor {
let screen = match attrs.monitor {
Some(ref monitor_id) => {
let native_id = match monitor_id.get_native_identifier() {
NativeMonitorId::Numeric(num) => num,
Expand Down Expand Up @@ -390,12 +394,12 @@ impl Window {
let frame = match screen {
Some(screen) => NSScreen::frame(screen),
None => {
let (width, height) = builder.dimensions.unwrap_or((800, 600));
let (width, height) = attrs.dimensions.unwrap_or((800, 600));
NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
}
};

let masks = if screen.is_some() || !builder.decorations {
let masks = if screen.is_some() || !attrs.decorations {
NSBorderlessWindowMask as NSUInteger |
NSResizableWindowMask as NSUInteger
} else {
Expand All @@ -412,7 +416,7 @@ impl Window {
NO,
));
window.non_nil().map(|window| {
let title = IdRef::new(NSString::alloc(nil).init_str(&builder.title));
let title = IdRef::new(NSString::alloc(nil).init_str(&attrs.title));
window.setTitle_(*title);
window.setAcceptsMouseMovedEvents_(YES);
if screen.is_some() {
Expand All @@ -437,8 +441,10 @@ impl Window {
}
}

fn create_context(view: id, builder: &BuilderAttribs) -> Result<(IdRef, PixelFormat), CreationError> {
let profile = match (builder.gl_version, builder.gl_version.to_gl_version(), builder.gl_profile) {
fn create_context(view: id, pf_reqs: &PixelFormatRequirements, opengl: &GlAttributes<&Window>)
-> Result<(IdRef, PixelFormat), CreationError>
{
let profile = match (opengl.version, opengl.version.to_gl_version(), opengl.profile) {

// Note: we are not using ranges because of a rust bug that should be fixed here:
// https://github.com/rust-lang/rust/pull/27050
Expand Down Expand Up @@ -471,16 +477,16 @@ impl Window {
// full color size and hope for the best. Another hiccup is that
// `NSOpenGLPFAColorSize` also includes `NSOpenGLPFAAlphaSize`,
// so we have to account for that as well.
let alpha_depth = builder.alpha_bits.unwrap_or(8);
let color_depth = builder.color_bits.unwrap_or(24) + alpha_depth;
let alpha_depth = pf_reqs.alpha_bits.unwrap_or(8);
let color_depth = pf_reqs.color_bits.unwrap_or(24) + alpha_depth;

let mut attributes = vec![
NSOpenGLPFADoubleBuffer as u32,
NSOpenGLPFAClosestPolicy as u32,
NSOpenGLPFAColorSize as u32, color_depth as u32,
NSOpenGLPFAAlphaSize as u32, alpha_depth as u32,
NSOpenGLPFADepthSize as u32, builder.depth_bits.unwrap_or(24) as u32,
NSOpenGLPFAStencilSize as u32, builder.stencil_bits.unwrap_or(8) 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,
NSOpenGLPFAOpenGLProfile as u32, profile,
];

Expand All @@ -491,7 +497,7 @@ impl Window {
attributes.push(NSOpenGLPFAColorFloat as u32);
}

builder.multisampling.map(|samples| {
pf_reqs.multisampling.map(|samples| {
attributes.push(NSOpenGLPFAMultisample as u32);
attributes.push(NSOpenGLPFASampleBuffers as u32); attributes.push(1);
attributes.push(NSOpenGLPFASamples as u32); attributes.push(samples as u32);
Expand Down Expand Up @@ -540,7 +546,7 @@ impl Window {
};

cxt.setView_(view);
let value = if builder.vsync { 1 } else { 0 };
let value = if opengl.vsync { 1 } else { 0 };
cxt.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval);

CGLEnable(cxt.CGLContextObj(), kCGLCECrashOnRemovedFunctions);
Expand Down
39 changes: 19 additions & 20 deletions src/api/egl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
target_os = "dragonfly", target_os = "freebsd"))]
#![allow(unused_variables)]

use BuilderAttribs;
use ContextError;
use CreationError;
use GlAttributes;
use GlContext;
use GlRequest;
use PixelFormat;
use PixelFormatRequirements;
use Robustness;
use Api;

Expand Down Expand Up @@ -158,11 +159,11 @@ impl 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: NativeDisplay)
pub fn new<'a>(egl: ffi::egl::Egl, pf_reqs: &PixelFormatRequirements,
opengl: &'a GlAttributes<&'a Context>, native_display: NativeDisplay)
-> Result<ContextPrototype<'a>, CreationError>
{
if builder.sharing.is_some() {
if opengl.sharing.is_some() {
unimplemented!()
}

Expand Down Expand Up @@ -197,7 +198,7 @@ impl Context {

// binding the right API and choosing the version
let (version, api) = unsafe {
match builder.gl_version {
match opengl.version {
GlRequest::Latest => {
if egl_version >= (1, 4) {
if egl.BindAPI(ffi::egl::OPENGL_API) != 0 {
Expand Down Expand Up @@ -246,10 +247,10 @@ 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 (config_id, pixel_format) = try!(pf_reqs.choose_pixel_format(configs.into_iter()));

Ok(ContextPrototype {
builder: builder,
opengl: opengl,
egl: egl,
display: display,
egl_version: egl_version,
Expand Down Expand Up @@ -330,7 +331,7 @@ impl Drop for Context {
}

pub struct ContextPrototype<'a> {
builder: &'a BuilderAttribs<'a>,
opengl: &'a GlAttributes<&'a Context>,
egl: ffi::egl::Egl,
display: ffi::egl::types::EGLDisplay,
egl_version: (ffi::egl::types::EGLint, ffi::egl::types::EGLint),
Expand Down Expand Up @@ -366,9 +367,7 @@ impl<'a> ContextPrototype<'a> {
self.finish_impl(surface)
}

pub fn finish_pbuffer(self) -> Result<Context, CreationError> {
let dimensions = self.builder.dimensions.unwrap_or((800, 600));

pub fn finish_pbuffer(self, dimensions: (u32, u32)) -> Result<Context, CreationError> {
let attrs = &[
ffi::egl::WIDTH as libc::c_int, dimensions.0 as libc::c_int,
ffi::egl::HEIGHT as libc::c_int, dimensions.1 as libc::c_int,
Expand All @@ -394,18 +393,18 @@ impl<'a> ContextPrototype<'a> {
if let Some(version) = self.version {
try!(create_context(&self.egl, self.display, &self.egl_version,
&self.extensions, self.api, version, self.config_id,
self.builder.gl_debug, self.builder.gl_robustness))
self.opengl.debug, self.opengl.robustness))

} else if self.api == Api::OpenGlEs {
if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
&self.extensions, self.api, (2, 0), self.config_id,
self.builder.gl_debug, self.builder.gl_robustness)
self.opengl.debug, self.opengl.robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
&self.extensions, self.api, (1, 0),
self.config_id, self.builder.gl_debug,
self.builder.gl_robustness)
self.config_id, self.opengl.debug,
self.opengl.robustness)
{
ctxt
} else {
Expand All @@ -415,19 +414,19 @@ impl<'a> ContextPrototype<'a> {
} else {
if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
&self.extensions, self.api, (3, 2), self.config_id,
self.builder.gl_debug, self.builder.gl_robustness)
self.opengl.debug, self.opengl.robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
&self.extensions, self.api, (3, 1),
self.config_id, self.builder.gl_debug,
self.builder.gl_robustness)
self.config_id, self.opengl.debug,
self.opengl.robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version,
&self.extensions, self.api, (1, 0),
self.config_id, self.builder.gl_debug,
self.builder.gl_robustness)
self.config_id, self.opengl.debug,
self.opengl.robustness)
{
ctxt
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/api/emscripten/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl Window {

// setting the attributes
// FIXME:
/*match builder.gl_version {
/*match builder.opengl.version {
Some((major, minor)) => {
attributes.majorVersion = major as libc::c_int;
attributes.minorVersion = minor as libc::c_int;
Expand Down
Loading