diff options
-rw-r--r-- | src/api/android/mod.rs | 5 | ||||
-rw-r--r-- | src/api/caca/mod.rs | 7 | ||||
-rw-r--r-- | src/api/cocoa/headless.rs | 8 | ||||
-rw-r--r-- | src/api/cocoa/mod.rs | 24 | ||||
-rw-r--r-- | src/api/egl/mod.rs | 23 | ||||
-rw-r--r-- | src/api/emscripten/mod.rs | 11 | ||||
-rw-r--r-- | src/api/glx/mod.rs | 19 | ||||
-rw-r--r-- | src/api/osmesa/mod.rs | 18 | ||||
-rw-r--r-- | src/api/wayland/mod.rs | 6 | ||||
-rw-r--r-- | src/api/wgl/mod.rs | 18 | ||||
-rw-r--r-- | src/api/win32/mod.rs | 5 | ||||
-rw-r--r-- | src/api/x11/window.rs | 9 | ||||
-rw-r--r-- | src/headless.rs | 7 | ||||
-rw-r--r-- | src/lib.rs | 15 | ||||
-rw-r--r-- | src/platform/android/mod.rs | 4 | ||||
-rw-r--r-- | src/platform/emscripten/mod.rs | 5 | ||||
-rw-r--r-- | src/platform/linux/api_dispatch.rs | 5 | ||||
-rw-r--r-- | src/platform/linux/mod.rs | 5 | ||||
-rw-r--r-- | src/platform/windows/mod.rs | 5 | ||||
-rw-r--r-- | src/window.rs | 9 |
20 files changed, 143 insertions, 65 deletions
diff --git a/src/api/android/mod.rs b/src/api/android/mod.rs index d1281e3..1649772 100644 --- a/src/api/android/mod.rs +++ b/src/api/android/mod.rs @@ -15,6 +15,7 @@ use std::collections::VecDeque; use Api; use BuilderAttribs; +use ContextError; use CursorState; use GlContext; use GlRequest; @@ -213,7 +214,7 @@ unsafe impl Send for Window {} unsafe impl Sync for Window {} impl GlContext for Window { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { self.context.make_current() } @@ -225,7 +226,7 @@ impl GlContext for Window { self.context.get_proc_address(addr) } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { self.context.swap_buffers() } diff --git a/src/api/caca/mod.rs b/src/api/caca/mod.rs index 953ce7d..3b4018e 100644 --- a/src/api/caca/mod.rs +++ b/src/api/caca/mod.rs @@ -6,6 +6,7 @@ use api::osmesa::{OsMesaContext, OsMesaCreationError}; use Api; use BuilderAttribs; +use ContextError; use CreationError; use Event; use GlContext; @@ -205,7 +206,7 @@ impl Window { } impl GlContext for Window { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { self.opengl.make_current() } @@ -217,7 +218,7 @@ impl GlContext for Window { self.opengl.get_proc_address(addr) } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { unsafe { let canvas = (self.libcaca.caca_get_canvas)(self.display); let width = (self.libcaca.caca_get_canvas_width)(canvas); @@ -231,6 +232,8 @@ impl GlContext for Window { buffer.as_ptr() as *const _); (self.libcaca.caca_refresh_display)(self.display); }; + + Ok(()) } fn get_api(&self) -> Api { diff --git a/src/api/cocoa/headless.rs b/src/api/cocoa/headless.rs index 75cca8d..7cd0f88 100644 --- a/src/api/cocoa/headless.rs +++ b/src/api/cocoa/headless.rs @@ -1,3 +1,4 @@ +use ContextError; use CreationError; use CreationError::OsError; use BuilderAttribs; @@ -61,7 +62,7 @@ impl HeadlessContext { } impl GlContext for HeadlessContext { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { self.context.makeCurrentContext(); gl::GenFramebuffersEXT(1, &mut framebuffer); @@ -78,6 +79,8 @@ impl GlContext for HeadlessContext { if status != gl::FRAMEBUFFER_COMPLETE_EXT { panic!("Error while creating the framebuffer"); } + + Ok(()) } fn is_current(&self) -> bool { @@ -96,7 +99,8 @@ impl GlContext for HeadlessContext { symbol as *const libc::c_void } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { + Ok(()) } fn get_api(&self) -> ::Api { diff --git a/src/api/cocoa/mod.rs b/src/api/cocoa/mod.rs index de24c2b..772b906 100644 --- a/src/api/cocoa/mod.rs +++ b/src/api/cocoa/mod.rs @@ -8,6 +8,7 @@ use libc; use Api; use BuilderAttribs; +use ContextError; use GlContext; use GlProfile; use GlRequest; @@ -354,6 +355,21 @@ impl Window { }; unsafe { + if builder.transparent { + let clear_col = { + let cls = Class::get("NSColor").unwrap(); + + msg_send![cls, clearColor] + }; + window.setOpaque_(NO); + window.setBackgroundColor_(clear_col); + + let obj = context.CGLContextObj(); + + let mut opacity = 0; + CGLSetParameter(obj, kCGLCPSurfaceOpacity, &mut opacity); + } + app.activateIgnoringOtherApps_(YES); if builder.visible { window.makeKeyAndOrderFront_(nil); @@ -433,7 +449,7 @@ impl Window { } }; - let masks = if screen.is_some() { + let masks = if screen.is_some() || !builder.decorations { NSBorderlessWindowMask as NSUInteger } else { NSTitledWindowMask as NSUInteger | @@ -758,9 +774,10 @@ impl Window { } impl GlContext for Window { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { let _: () = msg_send![*self.context, update]; self.context.makeCurrentContext(); + Ok(()) } fn is_current(&self) -> bool { @@ -787,8 +804,9 @@ impl GlContext for Window { symbol as *const _ } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { unsafe { self.context.flushBuffer(); } + Ok(()) } fn get_api(&self) -> ::Api { diff --git a/src/api/egl/mod.rs b/src/api/egl/mod.rs index 3335de0..7b31017 100644 --- a/src/api/egl/mod.rs +++ b/src/api/egl/mod.rs @@ -2,6 +2,7 @@ #![allow(unused_variables)] use BuilderAttribs; +use ContextError; use CreationError; use GlContext; use GlRequest; @@ -161,11 +162,18 @@ impl Context { } impl GlContext for Context { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { let ret = self.egl.MakeCurrent(self.display, self.surface, self.surface, self.context); if ret == 0 { - panic!("eglMakeCurrent failed"); + if self.egl.GetError() as u32 == ffi::egl::CONTEXT_LOST { + return Err(ContextError::ContextLost); + } else { + panic!("eglMakeCurrent failed"); + } + + } else { + Ok(()) } } @@ -181,13 +189,20 @@ impl GlContext for Context { } } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { let ret = unsafe { self.egl.SwapBuffers(self.display, self.surface) }; if ret == 0 { - panic!("eglSwapBuffers failed"); + if unsafe { self.egl.GetError() } as u32 == ffi::egl::CONTEXT_LOST { + return Err(ContextError::ContextLost); + } else { + panic!("eglSwapBuffers failed"); + } + + } else { + Ok(()) } } diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 9d4bb56..79dda6b 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -5,6 +5,7 @@ use libc; use {Event, BuilderAttribs, CreationError, MouseCursor}; use Api; use PixelFormat; +use ContextError; use GlContext; use std::collections::VecDeque; @@ -186,9 +187,10 @@ impl Window { } impl GlContext for Window { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { // TOOD: check if == EMSCRIPTEN_RESULT ffi::emscripten_webgl_make_context_current(self.context); + Ok(()) } fn is_current(&self) -> bool { @@ -204,10 +206,9 @@ impl GlContext for Window { } } - fn swap_buffers(&self) { - unsafe { - ffi::emscripten_sleep(1); // FIXME: - } + fn swap_buffers(&self) -> Result<(), ContextError> { + unsafe { ffi::emscripten_sleep(1); } // FIXME: + Ok(()) } fn get_api(&self) -> Api { diff --git a/src/api/glx/mod.rs b/src/api/glx/mod.rs index f1eb436..455f6a5 100644 --- a/src/api/glx/mod.rs +++ b/src/api/glx/mod.rs @@ -1,6 +1,7 @@ #![cfg(all(target_os = "linux", feature = "window"))] use BuilderAttribs; +use ContextError; use CreationError; use GlContext; use GlProfile; @@ -139,11 +140,13 @@ impl Context { } impl GlContext for Context { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { + // TODO: glutin needs some internal changes for proper error recovery let res = self.glx.MakeCurrent(self.display as *mut _, self.window, self.context); if res == 0 { panic!("glx::MakeCurrent failed"); } + Ok(()) } fn is_current(&self) -> bool { @@ -158,10 +161,10 @@ impl GlContext for Context { } } - fn swap_buffers(&self) { - unsafe { - self.glx.SwapBuffers(self.display as *mut _, self.window) - } + fn swap_buffers(&self) -> Result<(), ContextError> { + // TODO: glutin needs some internal changes for proper error recovery + unsafe { self.glx.SwapBuffers(self.display as *mut _, self.window); } + Ok(()) } fn get_api(&self) -> ::Api { @@ -179,8 +182,10 @@ unsafe impl Sync for Context {} impl Drop for Context { fn drop(&mut self) { unsafe { - // we don't call MakeCurrent(0, 0) because we are not sure that the context - // is still the current one + if self.is_current() { + self.glx.MakeCurrent(self.display as *mut _, 0, ptr::null_mut()); + } + self.glx.DestroyContext(self.display as *mut _, self.context); } } diff --git a/src/api/osmesa/mod.rs b/src/api/osmesa/mod.rs index 26808f7..daaba52 100644 --- a/src/api/osmesa/mod.rs +++ b/src/api/osmesa/mod.rs @@ -4,6 +4,7 @@ extern crate osmesa_sys; use Api; use BuilderAttribs; +use ContextError; use CreationError; use GlContext; use PixelFormat; @@ -67,14 +68,18 @@ impl OsMesaContext { } impl GlContext for OsMesaContext { - unsafe fn make_current(&self) { - let ret = osmesa_sys::OSMesaMakeCurrent(self.context, - self.buffer.as_ptr() as *mut libc::c_void, - 0x1401, self.width as libc::c_int, self.height as libc::c_int); + unsafe fn make_current(&self) -> Result<(), ContextError> { + let ret = osmesa_sys::OSMesaMakeCurrent(self.context, self.buffer.as_ptr() + as *mut libc::c_void, 0x1401, self.width + as libc::c_int, self.height as libc::c_int); + // an error can only happen in case of invalid parameter, which would indicate a bug + // in glutin if ret == 0 { - panic!("OSMesaMakeCurrent failed") + panic!("OSMesaMakeCurrent failed"); } + + Ok(()) } fn is_current(&self) -> bool { @@ -88,7 +93,8 @@ impl GlContext for OsMesaContext { } } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { + Ok(()) } fn get_api(&self) -> Api { diff --git a/src/api/wayland/mod.rs b/src/api/wayland/mod.rs index 95996ca..852172b 100644 --- a/src/api/wayland/mod.rs +++ b/src/api/wayland/mod.rs @@ -9,6 +9,7 @@ use api::dlopen; use api::egl::Context as EglContext; use BuilderAttribs; +use ContextError; use CreationError; use Event; use PixelFormat; @@ -277,8 +278,7 @@ impl Window { } impl GlContext for Window { - - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { self.context.make_current() } @@ -290,7 +290,7 @@ impl GlContext for Window { self.context.get_proc_address(addr) } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { self.context.swap_buffers() } diff --git a/src/api/wgl/mod.rs b/src/api/wgl/mod.rs index d1f42d2..c33054e 100644 --- a/src/api/wgl/mod.rs +++ b/src/api/wgl/mod.rs @@ -1,6 +1,7 @@ #![cfg(any(target_os = "windows"))] use BuilderAttribs; +use ContextError; use CreationError; use GlContext; use GlRequest; @@ -156,9 +157,12 @@ impl Context { } impl GlContext for Context { - unsafe fn make_current(&self) { - // TODO: check return value - gl::wgl::MakeCurrent(self.hdc as *const _, self.context.0 as *const _); + unsafe fn make_current(&self) -> Result<(), ContextError> { + if gl::wgl::MakeCurrent(self.hdc as *const _, self.context.0 as *const _) != 0 { + Ok(()) + } else { + Err(ContextError::IoError(io::Error::last_os_error())) + } } fn is_current(&self) -> bool { @@ -176,9 +180,11 @@ impl GlContext for Context { } } - fn swap_buffers(&self) { - unsafe { - gdi32::SwapBuffers(self.hdc); + fn swap_buffers(&self) -> Result<(), ContextError> { + if unsafe { gdi32::SwapBuffers(self.hdc) } != 0 { + Ok(()) + } else { + Err(ContextError::IoError(io::Error::last_os_error())) } } diff --git a/src/api/win32/mod.rs b/src/api/win32/mod.rs index 5b0339a..d21f16d 100644 --- a/src/api/win32/mod.rs +++ b/src/api/win32/mod.rs @@ -11,6 +11,7 @@ use std::sync::{ }; use std::sync::mpsc::Receiver; use libc; +use ContextError; use {CreationError, Event, MouseCursor}; use CursorState; use GlContext; @@ -306,7 +307,7 @@ impl Window { } impl GlContext for Window { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { match self.context { Context::Wgl(ref c) => c.make_current(), Context::Egl(ref c) => c.make_current(), @@ -327,7 +328,7 @@ impl GlContext for Window { } } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { match self.context { Context::Wgl(ref c) => c.swap_buffers(), Context::Egl(ref c) => c.swap_buffers(), diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs index 41b74f5..dc24e38 100644 --- a/src/api/x11/window.rs +++ b/src/api/x11/window.rs @@ -9,6 +9,7 @@ use std::collections::VecDeque; use std::sync::{Arc, Mutex}; use Api; +use ContextError; use CursorState; use GlContext; use GlRequest; @@ -796,11 +797,11 @@ impl Window { } impl GlContext for Window { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { match self.x.context { Context::Glx(ref ctxt) => ctxt.make_current(), Context::Egl(ref ctxt) => ctxt.make_current(), - Context::None => {} + Context::None => Ok(()) } } @@ -820,11 +821,11 @@ impl GlContext for Window { } } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { match self.x.context { Context::Glx(ref ctxt) => ctxt.swap_buffers(), Context::Egl(ref ctxt) => ctxt.swap_buffers(), - Context::None => {} + Context::None => Ok(()) } } diff --git a/src/headless.rs b/src/headless.rs index 997d87a..8ee81d8 100644 --- a/src/headless.rs +++ b/src/headless.rs @@ -1,5 +1,6 @@ use Api; use BuilderAttribs; +use ContextError; use CreationError; use GlRequest; use GlContext; @@ -69,7 +70,7 @@ impl HeadlessContext { /// Creates a new OpenGL context /// Sets the context as the current context. #[inline] - pub unsafe fn make_current(&self) { + pub unsafe fn make_current(&self) -> Result<(), ContextError> { self.context.make_current() } @@ -105,7 +106,7 @@ impl gl_common::GlFunctionsSource for HeadlessContext { } impl GlContext for HeadlessContext { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { self.context.make_current() } @@ -117,7 +118,7 @@ impl GlContext for HeadlessContext { self.context.get_proc_address(addr) } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { self.context.swap_buffers() } @@ -65,6 +65,8 @@ pub use window::{AvailableMonitorsIter, MonitorID, get_available_monitors, get_p #[cfg(feature = "window")] pub use native_monitor::NativeMonitorId; +use std::io; + mod api; mod platform; mod events; @@ -75,7 +77,7 @@ mod window; /// Trait that describes objects that have access to an OpenGL context. pub trait GlContext { /// Sets the context as the current context. - unsafe fn make_current(&self); + unsafe fn make_current(&self) -> Result<(), ContextError>; /// Returns true if this context is the current one in this thread. fn is_current(&self) -> bool; @@ -86,12 +88,12 @@ pub trait GlContext { /// Swaps the buffers in case of double or triple buffering. /// /// You should call this function every time you have finished rendering, or the image - /// may not be displayed on the screen. + /// may not be displayed on the screen. /// /// **Warning**: if you enabled vsync, this function will block until the next time the screen /// is refreshed. However drivers can choose to override your vsync settings, which means that /// you can't know in advance whether `swap_buffers` will block or not. - fn swap_buffers(&self); + fn swap_buffers(&self) -> Result<(), ContextError>; /// Returns the OpenGL API being used. fn get_api(&self) -> Api; @@ -128,6 +130,13 @@ impl std::error::Error for CreationError { } } +/// Error that can happen when manipulating an OpenGL context. +#[derive(Debug)] +pub enum ContextError { + IoError(io::Error), + ContextLost, +} + /// All APIs related to OpenGL that you can possibly get while using glutin. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Api { diff --git a/src/platform/android/mod.rs b/src/platform/android/mod.rs index a1b9416..50f554b 100644 --- a/src/platform/android/mod.rs +++ b/src/platform/android/mod.rs @@ -2,6 +2,8 @@ pub use api::android::*; +use ContextError; + pub struct HeadlessContext(i32); impl HeadlessContext { @@ -11,7 +13,7 @@ impl HeadlessContext { } /// See the docs in the crate root file. - pub unsafe fn make_current(&self) { + pub unsafe fn make_current(&self) -> Result<(), ContextError> { unimplemented!() } diff --git a/src/platform/emscripten/mod.rs b/src/platform/emscripten/mod.rs index 56a7e9f..d3aa6d6 100644 --- a/src/platform/emscripten/mod.rs +++ b/src/platform/emscripten/mod.rs @@ -1,5 +1,6 @@ #![cfg(target_os = "emscripten")] +use ContextError; use GlContext; pub use api::emscripten::{Window, WindowProxy, MonitorID, get_available_monitors}; @@ -15,7 +16,7 @@ impl HeadlessContext { } impl GlContext for HeadlessContext { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { self.0.make_current() } @@ -27,7 +28,7 @@ impl GlContext for HeadlessContext { self.0.get_proc_address(addr) } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { self.0.swap_buffers() } diff --git a/src/platform/linux/api_dispatch.rs b/src/platform/linux/api_dispatch.rs index 795b89f..b2cd741 100644 --- a/src/platform/linux/api_dispatch.rs +++ b/src/platform/linux/api_dispatch.rs @@ -7,6 +7,7 @@ use std::collections::VecDeque; use std::sync::Arc; use BuilderAttribs; +use ContextError; use CreationError; use CursorState; use Event; @@ -282,7 +283,7 @@ impl Window { } impl GlContext for Window { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { match self { &Window::X(ref w) => w.make_current(), &Window::Wayland(ref w) => w.make_current() @@ -303,7 +304,7 @@ impl GlContext for Window { } } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { match self { &Window::X(ref w) => w.swap_buffers(), &Window::Wayland(ref w) => w.swap_buffers() diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 323a21a..fc42f18 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -2,6 +2,7 @@ use Api; use BuilderAttribs; +use ContextError; use CreationError; use GlContext; use PixelFormat; @@ -37,7 +38,7 @@ impl HeadlessContext { impl GlContext for HeadlessContext { #[inline] - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { self.0.make_current() } @@ -52,7 +53,7 @@ impl GlContext for HeadlessContext { } #[inline] - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { self.0.swap_buffers() } diff --git a/src/platform/windows/mod.rs b/src/platform/windows/mod.rs index 260ab94..b33b8ee 100644 --- a/src/platform/windows/mod.rs +++ b/src/platform/windows/mod.rs @@ -6,6 +6,7 @@ use libc; use Api; use BuilderAttribs; +use ContextError; use CreationError; use PixelFormat; use GlContext; @@ -21,7 +22,7 @@ impl HeadlessContext { } impl GlContext for HeadlessContext { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { self.0.make_current() } @@ -33,7 +34,7 @@ impl GlContext for HeadlessContext { self.0.get_proc_address(addr) } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { self.0.swap_buffers() } diff --git a/src/window.rs b/src/window.rs index b42a16f..485ba58 100644 --- a/src/window.rs +++ b/src/window.rs @@ -3,6 +3,7 @@ use std::default::Default; use Api; use BuilderAttribs; +use ContextError; use CreationError; use CursorState; use Event; @@ -333,7 +334,7 @@ impl Window { /// Sets the context as the current context. #[inline] - pub unsafe fn make_current(&self) { + pub unsafe fn make_current(&self) -> Result<(), ContextError> { self.window.make_current() } @@ -360,7 +361,7 @@ impl Window { /// is refreshed. However drivers can choose to override your vsync settings, which means that /// you can't know in advance whether `swap_buffers` will block or not. #[inline] - pub fn swap_buffers(&self) { + pub fn swap_buffers(&self) -> Result<(), ContextError> { self.window.swap_buffers() } @@ -443,7 +444,7 @@ impl gl_common::GlFunctionsSource for Window { } impl GlContext for Window { - unsafe fn make_current(&self) { + unsafe fn make_current(&self) -> Result<(), ContextError> { self.make_current() } @@ -455,7 +456,7 @@ impl GlContext for Window { self.get_proc_address(addr) } - fn swap_buffers(&self) { + fn swap_buffers(&self) -> Result<(), ContextError> { self.swap_buffers() } |