diff --git a/.travis.yml b/.travis.yml index 22761ba7..eab930b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1 +1,5 @@ language: rust + +os: + - linux + - osx diff --git a/README.md b/README.md index 9ea0ec04..5972f998 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,6 @@ extern crate libc; extern crate gl; fn main() { - use std::default::Default; - let window = init::Window::new().unwrap(); unsafe { window.make_current() }; @@ -29,7 +27,7 @@ fn main() { gl::ClearColor(0.0, 1.0, 0.0, 1.0); - while !window.should_close() { + while !window.is_closed() { window.wait_events(); gl::Clear(gl::COLOR_BUFFER_BIT); diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index e5f8fd4f..5cb71f74 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -37,14 +37,18 @@ fn main() { }; println!("OpenGL version {}", version.as_str().unwrap()); + + { + let win_size = window.get_inner_size().unwrap(); + gl::Viewport(0, 0, win_size.val0() as libc::c_int, win_size.val1() as libc::c_int); + } gl::ClearColor(0.0, 1.0, 0.0, 1.0); while !window.is_closed() { - println!("{}", window.wait_events().collect::>()); - gl::Clear(gl::COLOR_BUFFER_BIT); - window.swap_buffers(); + + println!("{}", window.wait_events().collect::>()); } } diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs new file mode 100644 index 00000000..5bc1b075 --- /dev/null +++ b/examples/multiwindow.rs @@ -0,0 +1,36 @@ +extern crate init = "gl-init-rs"; +extern crate libc; +extern crate gl; + +fn main() { + let window1 = init::Window::new().unwrap(); + let window2 = init::Window::new().unwrap(); + + spawn(proc() { + run(window1, (0.0, 1.0, 0.0, 1.0)); + }); + + spawn(proc() { + run(window2, (0.0, 0.0, 1.0, 1.0)); + }); +} + +fn run(window: init::Window, color: (f32, f32, f32, f32)) { + unsafe { window.make_current() }; + + gl::load_with(|symbol| window.get_proc_address(symbol) as *const libc::c_void); + + { + let win_size = window.get_inner_size().unwrap(); + gl::Viewport(0, 0, win_size.val0() as libc::c_int, win_size.val1() as libc::c_int); + } + + gl::ClearColor(color.val0(), color.val1(), color.val2(), color.val3()); + + while !window.is_closed() { + gl::Clear(gl::COLOR_BUFFER_BIT); + window.swap_buffers(); + + window.wait_events().collect::>(); + } +} diff --git a/examples/window.rs b/examples/window.rs index c366ee0a..db80e393 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -16,13 +16,17 @@ fn main() { println!("OpenGL version {}", version.as_str().unwrap()); + { + let win_size = window.get_inner_size().unwrap(); + gl::Viewport(0, 0, win_size.val0() as libc::c_int, win_size.val1() as libc::c_int); + } + gl::ClearColor(0.0, 1.0, 0.0, 1.0); while !window.is_closed() { - println!("{}", window.wait_events().collect::>()); - gl::Clear(gl::COLOR_BUFFER_BIT); - window.swap_buffers(); + + println!("{}", window.wait_events().collect::>()); } } diff --git a/src/lib.rs b/src/lib.rs index e238b15e..3333ebc8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,25 +2,48 @@ #![feature(globs)] #![unstable] +//! The purpose of this library is to provide an OpenGL context on as many +//! platforms as possible. +//! +//! # Building a window +//! +//! There are two ways to create a window: +//! +//! - Calling `Window::new()`. +//! - Calling `let builder = WindowBuilder::new()` then `builder.build()`. +//! +//! The first way is the simpliest way and will give you default values. +//! +//! The second way allows you to customize the way your window and GL context +//! will look and behave. + extern crate libc; pub use events::*; #[cfg(windows)] use winimpl = win32; -#[cfg(unix)] +#[cfg(target_os = "linux")] use winimpl = x11; +#[cfg(target_os = "macos")] +use winimpl = osx; -#[cfg(windows)] +#[cfg(target_os = "win32")] mod win32; -#[cfg(unix)] +#[cfg(target_os = "linux")] mod x11; +#[cfg(target_os = "macos")] +mod osx; #[allow(dead_code)] //mod egl; mod events; +#[cfg(not(target_os = "win32"), not(target_os = "linux"), not(target_os = "macos"))] +#[static_assert] +static this_platform_is_not_supposed: bool = false; + /// Identifier for a monitor. pub struct MonitorID(winimpl::MonitorID); @@ -99,7 +122,7 @@ impl WindowBuilder { /// /// # Example /// -/// ``` +/// ```ignore /// let window = Window::new().unwrap(); /// /// unsafe { window.make_current() }; diff --git a/src/osx/mod.rs b/src/osx/mod.rs new file mode 100644 index 00000000..f846cf4b --- /dev/null +++ b/src/osx/mod.rs @@ -0,0 +1,79 @@ +//! Dummy implementation for OS/X to make gl-init-rs compile on this platform + +use {Event, WindowBuilder}; + +pub struct Window; + +pub struct MonitorID; + +pub fn get_available_monitors() -> Vec { + unimplemented!() +} + +pub fn get_primary_monitor() -> MonitorID { + unimplemented!() +} + +impl MonitorID { + pub fn get_name(&self) -> Option { + unimplemented!() + } + + pub fn get_dimensions(&self) -> (uint, uint) { + unimplemented!() + } +} + +impl Window { + pub fn new(_builder: WindowBuilder) -> Result { + unimplemented!() + } + + pub fn is_closed(&self) -> bool { + unimplemented!() + } + + pub fn set_title(&self, _title: &str) { + unimplemented!() + } + + pub fn get_position(&self) -> Option<(int, int)> { + unimplemented!() + } + + pub fn set_position(&self, _x: uint, _y: uint) { + unimplemented!() + } + + pub fn get_inner_size(&self) -> Option<(uint, uint)> { + unimplemented!() + } + + pub fn get_outer_size(&self) -> Option<(uint, uint)> { + unimplemented!() + } + + pub fn set_inner_size(&self, _x: uint, _y: uint) { + unimplemented!() + } + + pub fn poll_events(&self) -> Vec { + unimplemented!() + } + + pub fn wait_events(&self) -> Vec { + unimplemented!() + } + + pub unsafe fn make_current(&self) { + unimplemented!() + } + + pub fn get_proc_address(&self, _addr: &str) -> *const () { + unimplemented!() + } + + pub fn swap_buffers(&self) { + unimplemented!() + } +} diff --git a/src/win32/mod.rs b/src/win32/mod.rs index 891c7835..f29bf89b 100644 --- a/src/win32/mod.rs +++ b/src/win32/mod.rs @@ -133,6 +133,7 @@ impl Window { } } + // if one of the received events is `Closed`, setting `is_closed` to true if events.iter().find(|e| match e { &&::Closed => true, _ => false }).is_some() { use std::sync::atomics::Relaxed; self.is_closed.store(true, Relaxed); @@ -146,10 +147,21 @@ impl Window { pub fn wait_events(&self) -> Vec { match self.events_receiver.recv_opt() { Ok(ev) => { + // if the received event is `Closed`, setting `is_closed` to true + match ev { + ::Closed => { + use std::sync::atomics::Relaxed; + self.is_closed.store(true, Relaxed); + }, + _ => () + }; + + // looing for other possible events in the queue let mut result = self.poll_events(); result.insert(0, ev); result }, + Err(_) => { use std::sync::atomics::Relaxed; self.is_closed.store(true, Relaxed); @@ -187,6 +199,9 @@ impl Window { #[unsafe_destructor] impl Drop for Window { fn drop(&mut self) { + use std::ptr; + unsafe { ffi::wglMakeCurrent(ptr::mut_null(), ptr::mut_null()); } + unsafe { ffi::wglDeleteContext(self.context); } unsafe { ffi::DestroyWindow(self.window); } } }