From b9710f05a9d1e7fd10536b604074baf748fb5bd7 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sun, 28 Dec 2014 15:08:41 +0100 Subject: [PATCH] Unify WindowBuilder and HeadlessRendererBuilder for easier implementations --- src/android/mod.rs | 7 ++-- src/lib.rs | 75 ++++++++++++++++++++++++++----------------- src/osx/headless.rs | 4 +-- src/osx/mod.rs | 5 ++- src/win32/mod.rs | 23 +++++-------- src/x11/headless.rs | 12 ++++--- src/x11/mod.rs | 5 +++ src/x11/window/mod.rs | 6 ++-- 8 files changed, 76 insertions(+), 61 deletions(-) diff --git a/src/android/mod.rs b/src/android/mod.rs index 111d4b42..b8514f1e 100644 --- a/src/android/mod.rs +++ b/src/android/mod.rs @@ -7,8 +7,7 @@ use events::ElementState::{Pressed, Released}; use events::Event::{MouseInput, MouseMoved}; use events::MouseButton::LeftMouseButton; -#[cfg(feature = "headless")] -use HeadlessRendererBuilder; +use BuilderAttribs; pub struct Window { display: ffi::egl::types::EGLDisplay, @@ -45,7 +44,7 @@ pub struct HeadlessContext(int); #[cfg(feature = "headless")] impl HeadlessContext { /// See the docs in the crate root file. - pub fn new(_builder: HeadlessRendererBuilder) -> Result { + pub fn new(_builder: BuilderAttribs) -> Result { unimplemented!() } @@ -66,7 +65,7 @@ unsafe impl Send for HeadlessContext {} unsafe impl Sync for HeadlessContext {} impl Window { - pub fn new(builder: WindowBuilder) -> Result { + pub fn new(builder: BuilderAttribs) -> Result { use std::{mem, ptr}; if builder.sharing.is_some() { diff --git a/src/lib.rs b/src/lib.rs index 6a736cdd..29dcdb49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,14 @@ pub enum Api { /// Object that allows you to build windows. #[cfg(feature = "window")] pub struct WindowBuilder<'a> { - sharing: Option<&'a Window>, + attribs: BuilderAttribs<'a> +} + +/// Attributes +struct BuilderAttribs<'a> { + headless: bool, + strict: bool, + sharing: Option<&'a winimpl::Window>, dimensions: Option<(uint, uint)>, title: String, monitor: Option, @@ -103,11 +110,11 @@ pub struct WindowBuilder<'a> { multisampling: Option, } -#[cfg(feature = "window")] -impl<'a> WindowBuilder<'a> { - /// Initializes a new `WindowBuilder` with default values. - pub fn new() -> WindowBuilder<'a> { - WindowBuilder { +impl BuilderAttribs<'static> { + fn new() -> BuilderAttribs<'static> { + BuilderAttribs { + headless: false, + strict: false, sharing: None, dimensions: None, title: "glutin window".to_string(), @@ -119,18 +126,28 @@ impl<'a> WindowBuilder<'a> { multisampling: None, } } +} + +#[cfg(feature = "window")] +impl<'a> WindowBuilder<'a> { + /// Initializes a new `WindowBuilder` with default values. + pub fn new() -> WindowBuilder<'a> { + WindowBuilder { + attribs: BuilderAttribs::new(), + } + } /// Requests the window to be of specific dimensions. /// /// Width and height are in pixels. pub fn with_dimensions(mut self, width: uint, height: uint) -> WindowBuilder<'a> { - self.dimensions = Some((width, height)); + self.attribs.dimensions = Some((width, height)); self } /// Requests a specific title for the window. pub fn with_title(mut self, title: String) -> WindowBuilder<'a> { - self.title = title; + self.attribs.title = title; self } @@ -139,7 +156,7 @@ impl<'a> WindowBuilder<'a> { /// If you don't specify dimensions for the window, it will match the monitor's. pub fn with_fullscreen(mut self, monitor: MonitorID) -> WindowBuilder<'a> { let MonitorID(monitor) = monitor; - self.monitor = Some(monitor); + self.attribs.monitor = Some(monitor); self } @@ -147,7 +164,7 @@ impl<'a> WindowBuilder<'a> { /// /// There are some exceptions, like FBOs or VAOs. See the OpenGL documentation. pub fn with_shared_lists(mut self, other: &'a Window) -> WindowBuilder<'a> { - self.sharing = Some(other); + self.attribs.sharing = Some(&other.window); self } @@ -156,7 +173,7 @@ impl<'a> WindowBuilder<'a> { /// Version is a (major, minor) pair. For example to request OpenGL 3.3 /// you would pass `(3, 3)`. pub fn with_gl_version(mut self, version: (uint, uint)) -> WindowBuilder<'a> { - self.gl_version = Some(version); + self.attribs.gl_version = Some(version); self } @@ -165,19 +182,19 @@ impl<'a> WindowBuilder<'a> { /// The default value for this flag is `cfg!(ndebug)`, which means that it's enabled /// when you run `cargo build` and disabled when you run `cargo build --release`. pub fn with_gl_debug_flag(mut self, flag: bool) -> WindowBuilder<'a> { - self.gl_debug = flag; + self.attribs.gl_debug = flag; self } /// Requests that the window has vsync enabled. pub fn with_vsync(mut self) -> WindowBuilder<'a> { - self.vsync = true; + self.attribs.vsync = true; self } /// Sets whether the window will be initially hidden or visible. pub fn with_visibility(mut self, visible: bool) -> WindowBuilder<'a> { - self.visible = visible; + self.attribs.visible = visible; self } @@ -189,7 +206,7 @@ impl<'a> WindowBuilder<'a> { pub fn with_multisampling(mut self, samples: u16) -> WindowBuilder<'a> { use std::num::UnsignedInt; assert!(samples.is_power_of_two()); - self.multisampling = Some(samples); + self.attribs.multisampling = Some(samples); self } @@ -199,26 +216,24 @@ impl<'a> WindowBuilder<'a> { /// out of memory, etc. pub fn build(mut self) -> Result { // resizing the window to the dimensions of the monitor when fullscreen - if self.dimensions.is_none() && self.monitor.is_some() { - self.dimensions = Some(self.monitor.as_ref().unwrap().get_dimensions()) + if self.attribs.dimensions.is_none() && self.attribs.monitor.is_some() { + self.attribs.dimensions = Some(self.attribs.monitor.as_ref().unwrap().get_dimensions()) } // default dimensions - if self.dimensions.is_none() { - self.dimensions = Some((1024, 768)); + if self.attribs.dimensions.is_none() { + self.attribs.dimensions = Some((1024, 768)); } // building - winimpl::Window::new(self).map(|w| Window { window: w }) + winimpl::Window::new(self.attribs).map(|w| Window { window: w }) } } /// Object that allows you to build headless contexts. #[cfg(feature = "headless")] pub struct HeadlessRendererBuilder { - dimensions: (uint, uint), - gl_version: Option<(uint, uint)>, - gl_debug: bool, + attribs: BuilderAttribs<'static>, } #[cfg(feature = "headless")] @@ -226,9 +241,11 @@ impl HeadlessRendererBuilder { /// Initializes a new `HeadlessRendererBuilder` with default values. pub fn new(width: uint, height: uint) -> HeadlessRendererBuilder { HeadlessRendererBuilder { - dimensions: (width, height), - gl_version: None, - gl_debug: cfg!(ndebug), + attribs: BuilderAttribs { + headless: true, + dimensions: Some((width, height)), + .. BuilderAttribs::new() + }, } } @@ -237,7 +254,7 @@ impl HeadlessRendererBuilder { /// Version is a (major, minor) pair. For example to request OpenGL 3.3 /// you would pass `(3, 3)`. pub fn with_gl_version(mut self, version: (uint, uint)) -> HeadlessRendererBuilder { - self.gl_version = Some(version); + self.attribs.gl_version = Some(version); self } @@ -246,7 +263,7 @@ impl HeadlessRendererBuilder { /// The default value for this flag is `cfg!(ndebug)`, which means that it's enabled /// when you run `cargo build` and disabled when you run `cargo build --release`. pub fn with_gl_debug_flag(mut self, flag: bool) -> HeadlessRendererBuilder { - self.gl_debug = flag; + self.attribs.gl_debug = flag; self } @@ -255,7 +272,7 @@ impl HeadlessRendererBuilder { /// Error should be very rare and only occur in case of permission denied, incompatible system, /// out of memory, etc. pub fn build(self) -> Result { - winimpl::HeadlessContext::new(self).map(|w| HeadlessContext { context: w }) + winimpl::HeadlessContext::new(self.attribs).map(|w| HeadlessContext { context: w }) } } diff --git a/src/osx/headless.rs b/src/osx/headless.rs index 1332cf31..39c8f50d 100644 --- a/src/osx/headless.rs +++ b/src/osx/headless.rs @@ -1,6 +1,6 @@ use CreationError; use CreationError::OsError; -use HeadlessRendererBuilder; +use BuilderAttribs; use libc; use std::ptr; @@ -30,7 +30,7 @@ pub struct HeadlessContext { } impl HeadlessContext { - pub fn new(builder: HeadlessRendererBuilder) -> Result { + pub fn new(builder: BuilderAttribs) -> Result { let (width, height) = builder.dimensions; let context = unsafe { let attributes = [ diff --git a/src/osx/mod.rs b/src/osx/mod.rs index 92ef641d..b65f67a6 100644 --- a/src/osx/mod.rs +++ b/src/osx/mod.rs @@ -5,8 +5,7 @@ use {CreationError, Event}; use CreationError::OsError; use libc; -#[cfg(feature = "window")] -use WindowBuilder; +use BuilderAttribs; use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair}; use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar}; @@ -63,7 +62,7 @@ pub struct Window { #[cfg(feature = "window")] impl Window { - pub fn new(builder: WindowBuilder) -> Result { + pub fn new(builder: BuilderAttribs) -> Result { if builder.sharing.is_some() { unimplemented!() } diff --git a/src/win32/mod.rs b/src/win32/mod.rs index a5f05476..e90f93fc 100644 --- a/src/win32/mod.rs +++ b/src/win32/mod.rs @@ -3,11 +3,7 @@ use std::ptr; use libc; use {CreationError, Event}; -#[cfg(feature = "window")] -use WindowBuilder; - -#[cfg(feature = "headless")] -use HeadlessRendererBuilder; +use BuilderAttribs; pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; @@ -19,15 +15,13 @@ mod init; mod monitor; /// -#[cfg(feature = "headless")] pub struct HeadlessContext(Window); -#[cfg(feature = "headless")] impl HeadlessContext { /// See the docs in the crate root file. - pub fn new(builder: HeadlessRendererBuilder) -> Result { - let HeadlessRendererBuilder { dimensions, gl_version, gl_debug } = builder; - init::new_window(Some(dimensions), "".to_string(), None, gl_version, gl_debug, false, true, + pub fn new(builder: BuilderAttribs) -> Result { + let BuilderAttribs { dimensions, gl_version, gl_debug, .. } = builder; + init::new_window(dimensions, "".to_string(), None, gl_version, gl_debug, false, true, None, None) .map(|w| HeadlessContext(w)) } @@ -83,14 +77,13 @@ pub struct Window { unsafe impl Send for Window {} unsafe impl Sync for Window {} -#[cfg(feature = "window")] impl Window { /// See the docs in the crate root file. - pub fn new(builder: WindowBuilder) -> Result { - let WindowBuilder { dimensions, title, monitor, gl_version, - gl_debug, vsync, visible, sharing, multisampling } = builder; + pub fn new(builder: BuilderAttribs) -> Result { + let BuilderAttribs { dimensions, title, monitor, gl_version, + gl_debug, vsync, visible, sharing, multisampling, .. } = builder; init::new_window(dimensions, title, monitor, gl_version, gl_debug, vsync, - !visible, sharing.map(|w| init::ContextHack(w.window.context)), + !visible, sharing.map(|w| init::ContextHack(w.context)), multisampling) } } diff --git a/src/x11/headless.rs b/src/x11/headless.rs index d6f1023c..22d0654a 100644 --- a/src/x11/headless.rs +++ b/src/x11/headless.rs @@ -1,4 +1,4 @@ -use HeadlessRendererBuilder; +use BuilderAttribs; use CreationError; use CreationError::OsError; use libc; @@ -13,11 +13,13 @@ pub struct HeadlessContext { } impl HeadlessContext { - pub fn new(builder: HeadlessRendererBuilder) -> Result { + pub fn new(builder: BuilderAttribs) -> Result { + let dimensions = builder.dimensions.unwrap(); + Ok(HeadlessContext { - width: builder.dimensions.0, - height: builder.dimensions.1, - buffer: Vec::from_elem(builder.dimensions.0 * builder.dimensions.1, unsafe { mem::uninitialized() }), + width: dimensions.0, + height: dimensions.1, + buffer: Vec::from_elem(dimensions.0 * dimensions.1, unsafe { mem::uninitialized() }), context: unsafe { let ctxt = ffi::OSMesaCreateContext(0x1908, ptr::null()); if ctxt.is_null() { diff --git a/src/x11/mod.rs b/src/x11/mod.rs index 9ce789f7..22184a9f 100644 --- a/src/x11/mod.rs +++ b/src/x11/mod.rs @@ -11,3 +11,8 @@ mod headless; #[cfg(feature = "window")] mod window; + +#[cfg(not(feature = "window"))] +pub type Window = (); // TODO: hack to make things work +#[cfg(not(feature = "window"))] +pub type MonitorID = (); // TODO: hack to make things work diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs index 0a8c3d58..fc622ea5 100644 --- a/src/x11/window/mod.rs +++ b/src/x11/window/mod.rs @@ -1,4 +1,4 @@ -use {Event, WindowBuilder}; +use {Event, BuilderAttribs}; use CreationError; use CreationError::OsError; use libc; @@ -89,7 +89,7 @@ pub struct Window { } impl Window { - pub fn new(builder: WindowBuilder) -> Result { + pub fn new(builder: BuilderAttribs) -> Result { ensure_thread_init(); let dimensions = builder.dimensions.unwrap_or((800, 600)); @@ -308,7 +308,7 @@ impl Window { }); let share = if let Some(win) = builder.sharing { - win.window.x.context + win.x.context } else { ptr::null() };