Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save goddessfreya/20398fb571ca5f73e08c00338ffb669a to your computer and use it in GitHub Desktop.
Save goddessfreya/20398fb571ca5f73e08c00338ffb669a to your computer and use it in GitHub Desktop.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0b4978b..3f0243c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,10 +5,10 @@
- Added headless example.
- Removed internal code relating to libcaca.
- Implemented `Debug` on all public facing types.
- - Dropping contexts on platforms using egl and/or glx no longer resets the
+ - Dropping contexts on platforms using egl and/or glx no longer resets the
current context, if the context dropped wasn't the current context.
- Added context sharing support to MacOS.
- - **Breaking**: Split `ContextTrait` into `ContextTrait` and `PossiblyCurrentContextTrait`.
+ - **Breaking**: Removed `ContextTrait`.
- **Breaking**: Renamed `OsMesaContextExt` to `HeadlessContextExt`. Added functions
for using egl-surfaceless.
- **Breaking**: Changed `WindowedContext` and `RawContext` into typedefs of
@@ -16,10 +16,9 @@
- **Breaking**: Removed `new_windowed` and `new_headless` from `WindowedContext`
and `Context`, respectively.
- **Breaking**: Added two new types, `NotCurrentContext` and `PossiblyCurrentContext`,
- which `RawContext`, `WindowedContext`, `ContextBuilder` and `Context` are now
+ which `RawContext`, `WindowedContext`, `ContextBuilder` and `Context` are now
generic over.
- - Added `make_not_current` function into `ContextTrait`.
- - Added `treat_as_not_current` function into `ContextTrait`.
+ - Added `{make,treat_as}_not_current` function to `{Raw,Windowed,}Context`.
- We now load `libGL.so` instead of `libGLX.so`.
- **Breaking**: Added `DisplayLost` variant to `ContextError`.
- Fixed bug where we drop the hidden window belonging to a headless context on
diff --git a/README.md b/README.md
index bf1380e..a1c1338 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,6 @@ gl = "*"
```rust
use glutin::dpi::*;
-use glutin::ContextTrait;
fn main() {
let mut el = glutin::EventsLoop::new();
diff --git a/glutin/src/api/android/mod.rs b/glutin/src/api/android/mod.rs
index bf825f3..a8a9f43 100644
--- a/glutin/src/api/android/mod.rs
+++ b/glutin/src/api/android/mod.rs
@@ -59,7 +59,7 @@ impl Context {
let gl_attr = gl_attr.clone().map_sharing(|c| &c.0.egl_context);
let nwin = unsafe { android_glue::get_native_window() };
if nwin.is_null() {
- return Err(OsError(format!("Android's native window is null")));
+ return Err(OsError("Android's native window is null".to_string()));
}
let native_display = NativeDisplay::Android;
let egl_context =
diff --git a/glutin/src/api/egl/mod.rs b/glutin/src/api/egl/mod.rs
index bc21383..8c4374a 100644
--- a/glutin/src/api/egl/mod.rs
+++ b/glutin/src/api/egl/mod.rs
@@ -330,9 +330,9 @@ impl Context {
let mut minor: ffi::egl::types::EGLint = std::mem::uninitialized();
if egl.Initialize(display, &mut major, &mut minor) == 0 {
- return Err(CreationError::OsError(format!(
- "eglInitialize failed"
- )));
+ return Err(CreationError::OsError(
+ "eglInitialize failed".to_string(),
+ ));
}
(major, minor)
@@ -768,9 +768,9 @@ impl<'a> ContextPrototype<'a> {
std::ptr::null(),
);
if surface.is_null() {
- return Err(CreationError::OsError(format!(
- "eglCreateWindowSurface failed"
- )));
+ return Err(CreationError::OsError(
+ "eglCreateWindowSurface failed".to_string(),
+ ));
}
surface
};
@@ -794,9 +794,9 @@ impl<'a> ContextPrototype<'a> {
.find(|s| s == &"EGL_KHR_surfaceless_context")
.is_none()
{
- Err(CreationError::OsError(format!(
- "EGL surfaceless not supported."
- )))
+ Err(CreationError::NotSupported(
+ "EGL surfaceless not supported".to_string(),
+ ))
} else {
self.finish_impl(None)
}
@@ -838,9 +838,9 @@ impl<'a> ContextPrototype<'a> {
attrs.as_ptr(),
);
if surface.is_null() || surface == ffi::egl::NO_SURFACE {
- return Err(CreationError::OsError(format!(
- "eglCreatePbufferSurface failed"
- )));
+ return Err(CreationError::OsError(
+ "eglCreatePbufferSurface failed".to_string(),
+ ));
}
surface
};
@@ -1100,7 +1100,9 @@ unsafe fn choose_fbconfig(
&mut num_configs,
) == 0
{
- return Err(CreationError::OsError(format!("eglChooseConfig failed")));
+ return Err(CreationError::OsError(
+ "eglChooseConfig failed".to_string(),
+ ));
}
if num_configs == 0 {
return Err(CreationError::NoAvailablePixelFormat);
@@ -1117,9 +1119,9 @@ unsafe fn choose_fbconfig(
&mut value,
);
if res == 0 {
- return Err(CreationError::OsError(format!(
- "eglGetConfigAttrib failed"
- )));
+ return Err(CreationError::OsError(
+ "eglGetConfigAttrib failed".to_string(),
+ ));
}
value
}};
diff --git a/glutin/src/api/glx/mod.rs b/glutin/src/api/glx/mod.rs
index e71abd5..6d586b8 100644
--- a/glutin/src/api/glx/mod.rs
+++ b/glutin/src/api/glx/mod.rs
@@ -103,9 +103,10 @@ impl Context {
let extensions =
glx.QueryExtensionsString(xconn.display as *mut _, screen_id);
if extensions.is_null() {
- return Err(CreationError::OsError(format!(
+ return Err(CreationError::OsError(
"`glXQueryExtensionsString` found no glX extensions"
- )));
+ .to_string(),
+ ));
}
let extensions = CStr::from_ptr(extensions).to_bytes().to_vec();
String::from_utf8(extensions).unwrap()
@@ -129,9 +130,10 @@ impl Context {
let vi =
glx.GetVisualFromFBConfig(xconn.display as *mut _, fb_config);
if vi.is_null() {
- return Err(CreationError::OsError(format!(
+ return Err(CreationError::OsError(
"`glXGetVisualFromFBConfig` failed: invalid `GLXFBConfig`"
- )));
+ .to_string(),
+ ));
}
let vi_copy = std::ptr::read(vi as *const _);
(xconn.xlib.XFree)(vi as *mut _);
@@ -471,9 +473,9 @@ impl<'a> ContextPrototype<'a> {
extra_functions.SwapIntervalSGI(1);
}
} else {
- return Err(CreationError::OsError(format!(
- "Couldn't find any available vsync extension"
- )));
+ return Err(CreationError::OsError(
+ "Couldn't find any available vsync extension".to_string(),
+ ));
}
}
@@ -614,9 +616,9 @@ fn create_context(
if context.is_null() {
// TODO: check for errors and return `OpenGlVersionNotSupported`
- return Err(CreationError::OsError(format!(
- "GL context creation failed"
- )));
+ return Err(CreationError::OsError(
+ "GL context creation failed".to_string(),
+ ));
}
Ok(context)
diff --git a/glutin/src/api/ios/mod.rs b/glutin/src/api/ios/mod.rs
index 9ba831f..88581a3 100644
--- a/glutin/src/api/ios/mod.rs
+++ b/glutin/src/api/ios/mod.rs
@@ -239,9 +239,10 @@ impl Context {
version -= 1;
}
if valid_context == ffi::nil {
- Err(CreationError::OsError(format!(
+ Err(CreationError::OsError(
"Failed to create an OpenGL ES context with any version"
- )))
+ .to_string(),
+ ))
} else {
Ok(eagl_context)
}
diff --git a/glutin/src/api/wgl/make_current_guard.rs b/glutin/src/api/wgl/make_current_guard.rs
index d355d89..2a05561 100644
--- a/glutin/src/api/wgl/make_current_guard.rs
+++ b/glutin/src/api/wgl/make_current_guard.rs
@@ -29,7 +29,7 @@ impl<'a, 'b> CurrentContextGuard<'a, 'b> {
if result == 0 {
return Err(CreationError::OsError(format!(
"wglMakeCurrent function failed: {}",
- format!("{}", io::Error::last_os_error())
+ io::Error::last_os_error()
)));
}
diff --git a/glutin/src/api/wgl/mod.rs b/glutin/src/api/wgl/mod.rs
index 91b33ee..93d22eb 100644
--- a/glutin/src/api/wgl/mod.rs
+++ b/glutin/src/api/wgl/mod.rs
@@ -84,7 +84,7 @@ impl Context {
if hdc.is_null() {
let err = Err(CreationError::OsError(format!(
"GetDC function failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
return err;
}
@@ -164,9 +164,9 @@ impl Context {
if extra_functions.SwapIntervalEXT(if opengl.vsync { 1 } else { 0 })
== 0
{
- return Err(CreationError::OsError(format!(
- "wglSwapIntervalEXT failed"
- )));
+ return Err(CreationError::OsError(
+ "wglSwapIntervalEXT failed".to_string(),
+ ));
}
}
@@ -361,7 +361,7 @@ unsafe fn create_context(
attributes.push(flag as raw::c_int);
} else {
return Err(CreationError::NotSupported(
- "required extension \"WGL_ARB_create_context_profile\" not found",
+ "required extension \"WGL_ARB_create_context_profile\" not found".to_string(),
));
}
}
@@ -437,7 +437,7 @@ unsafe fn create_context(
if ctx.is_null() {
return Err(CreationError::OsError(format!(
"wglCreateContextAttribsARB failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
} else {
return Ok(ContextWrapper(ctx as HGLRC));
@@ -451,7 +451,7 @@ unsafe fn create_context(
if ctx.is_null() {
return Err(CreationError::OsError(format!(
"wglCreateContext failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
}
@@ -459,7 +459,7 @@ unsafe fn create_context(
if gl::wgl::ShareLists(share as *const raw::c_void, ctx) == 0 {
return Err(CreationError::OsError(format!(
"wglShareLists failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
}
};
@@ -850,14 +850,14 @@ unsafe fn set_pixel_format(
{
return Err(CreationError::OsError(format!(
"DescribePixelFormat function failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
}
if SetPixelFormat(hdc, id, &output) == 0 {
return Err(CreationError::OsError(format!(
"SetPixelFormat function failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
}
@@ -876,7 +876,7 @@ unsafe fn load_opengl32_dll() -> Result<HMODULE, CreationError> {
if lib.is_null() {
return Err(CreationError::OsError(format!(
"LoadLibrary function failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
}
@@ -912,7 +912,7 @@ unsafe fn load_extra_functions(
if GetClassNameW(win, class_name.as_mut_ptr(), 128) == 0 {
return Err(CreationError::OsError(format!(
"GetClassNameW function failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
}
@@ -923,7 +923,7 @@ unsafe fn load_extra_functions(
if GetClassInfoExW(instance, class_name.as_ptr(), &mut class) == 0 {
return Err(CreationError::OsError(format!(
"GetClassInfoExW function failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
}
@@ -968,7 +968,7 @@ unsafe fn load_extra_functions(
if win.is_null() {
return Err(CreationError::OsError(format!(
"CreateWindowEx function failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
}
@@ -976,7 +976,7 @@ unsafe fn load_extra_functions(
if hdc.is_null() {
let err = Err(CreationError::OsError(format!(
"GetDC function failed: {}",
- format!("{}", std::io::Error::last_os_error())
+ std::io::Error::last_os_error()
)));
return err;
}
diff --git a/glutin/src/context.rs b/glutin/src/context.rs
index 8fa6a69..680cbb1 100644
--- a/glutin/src/context.rs
+++ b/glutin/src/context.rs
@@ -10,7 +10,6 @@ use std::marker::PhantomData;
/// # Example
///
/// ```no_run
-/// # use glutin::ContextTrait;
/// # fn main() {
/// # let el = glutin::EventsLoop::new();
/// # let wb = glutin::WindowBuilder::new();
@@ -29,56 +28,14 @@ pub struct Context<T: ContextCurrentState> {
pub(crate) phantom: PhantomData<T>,
}
-/// A trait for types associated with a GL context.
-pub trait ContextTrait
-where
- Self: Sized,
-{
- type PossiblyCurrentContext: PossiblyCurrentContextTrait
- + ContextTrait<
- PossiblyCurrentContext = Self::PossiblyCurrentContext,
- NotCurrentContext = Self::NotCurrentContext,
- >;
- type NotCurrentContext: ContextTrait<
- PossiblyCurrentContext = Self::PossiblyCurrentContext,
- NotCurrentContext = Self::NotCurrentContext,
- >;
-
- /// Sets the context as the current context. The previously current context
- /// (if any) is no longer current.
- unsafe fn make_current(
- self,
- ) -> Result<Self::PossiblyCurrentContext, (Self, ContextError)>;
-
- /// If this context is current, makes the context not current.
- unsafe fn make_not_current(
- self,
- ) -> Result<Self::NotCurrentContext, (Self, ContextError)>;
-
- /// Treats the context as not current, even if it is current. We do no
- /// checks to confirm that this is the case. Prefer to use
- /// `make_not_current` which will do nothing if this context is not current.
- unsafe fn treat_as_not_current(self) -> Self::NotCurrentContext;
-
- /// Returns true if this context is the current one in this thread.
- fn is_current(&self) -> bool;
-
- /// Returns the OpenGL API being used.
- fn get_api(&self) -> Api;
-}
-
-pub trait PossiblyCurrentContextTrait {
- /// Returns the address of an OpenGL function.
- fn get_proc_address(&self, addr: &str) -> *const ();
-}
-
-impl<T: ContextCurrentState> ContextTrait for Context<T> {
- type PossiblyCurrentContext = Context<PossiblyCurrentContext>;
- type NotCurrentContext = Context<NotCurrentContext>;
-
- unsafe fn make_current(
+impl<T: ContextCurrentState> Context<T> {
+ /// See [`ContextWrapper::make_current`].
+ ///
+ /// [`ContextWrapper::make_current`]:
+ /// struct.ContextWrapper.html#method.make_current
+ pub unsafe fn make_current(
self,
- ) -> Result<Self::PossiblyCurrentContext, (Self, ContextError)> {
+ ) -> Result<Context<PossiblyCurrentContext>, (Self, ContextError)> {
match self.context.make_current() {
Ok(()) => Ok(Context {
context: self.context,
@@ -94,9 +51,13 @@ impl<T: ContextCurrentState> ContextTrait for Context<T> {
}
}
- unsafe fn make_not_current(
+ /// See [`ContextWrapper::make_not_current`].
+ ///
+ /// [`ContextWrapper::make_not_current`]:
+ /// struct.ContextWrapper.html#method.make_not_current
+ pub unsafe fn make_not_current(
self,
- ) -> Result<Self::NotCurrentContext, (Self, ContextError)> {
+ ) -> Result<Context<NotCurrentContext>, (Self, ContextError)> {
match self.context.make_not_current() {
Ok(()) => Ok(Context {
context: self.context,
@@ -112,24 +73,39 @@ impl<T: ContextCurrentState> ContextTrait for Context<T> {
}
}
- unsafe fn treat_as_not_current(self) -> Self::NotCurrentContext {
+ /// See [`ContextWrapper::treat_as_not_current`].
+ ///
+ /// [`ContextWrapper::treat_as_not_current`]:
+ /// struct.ContextWrapper.html#method.treat_as_not_current
+ pub unsafe fn treat_as_not_current(self) -> Context<NotCurrentContext> {
Context {
context: self.context,
phantom: PhantomData,
}
}
- fn is_current(&self) -> bool {
+ /// See [`ContextWrapper::is_current`].
+ ///
+ /// [`ContextWrapper::is_current`]:
+ /// struct.ContextWrapper.html#method.is_current
+ pub fn is_current(&self) -> bool {
self.context.is_current()
}
- fn get_api(&self) -> Api {
+ /// See [`ContextWrapper::get_api`].
+ ///
+ /// [`ContextWrapper::get_api`]: struct.ContextWrapper.html#method.get_api
+ pub fn get_api(&self) -> Api {
self.context.get_api()
}
}
-impl PossiblyCurrentContextTrait for Context<PossiblyCurrentContext> {
- fn get_proc_address(&self, addr: &str) -> *const () {
+impl Context<PossiblyCurrentContext> {
+ /// See [`ContextWrapper::get_proc_address`].
+ ///
+ /// [`ContextWrapper::get_proc_address`]:
+ /// struct.ContextWrapper.html#method.get_proc_address
+ pub fn get_proc_address(&self, addr: &str) -> *const () {
self.context.get_proc_address(addr)
}
}
@@ -140,11 +116,43 @@ impl<'a, T: ContextCurrentState> ContextBuilder<'a, T> {
/// One notable limitation of the Wayland backend when it comes to shared
/// contexts is that both contexts must use the same events loop.
///
+ /// When on linux, prefer [`build_surfaceless`]. If both
+ /// [`build_surfaceless`] and `build_headless` fail, try using a hidden
+ /// window, or [`build_osmesa`]. Please note that if you choose to use a
+ /// hidden window, you must still handle the events it generates on the
+ /// events loop.
+ ///
/// Errors can occur in two scenarios:
/// - If the window could not be created (via permission denied,
/// incompatible system, out of memory, etc.). This should be very rare.
/// - If the OpenGL context could not be created. This generally happens
/// because the underlying platform doesn't support a requested feature.
+ #[cfg_attr(
+ not(any(
+ target_os = "linux",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )),
+ doc = "\
+ [`build_surfaceless`]: os/index.html
+ [`build_osmesa`]: os/index.html
+ "
+ )]
+ #[cfg_attr(
+ any(
+ target_os = "linux",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ),
+ doc = "\
+ [`build_surfaceless`]: os/unix/trait.HeadlessContextExt.html#tymethod.build_surfaceless
+ [`build_osmesa`]: os/unix/trait.HeadlessContextExt.html#tymethod.build_osmesa
+ "
+ )]
pub fn build_headless(
self,
el: &EventsLoop,
@@ -167,14 +175,33 @@ impl<'a, T: ContextCurrentState> ContextBuilder<'a, T> {
//
// Instead we add a phantom type to PossiblyCurrentContext
-#[derive(Debug, Clone)]
+/// A type that contexts which might possibly be currently current on some
+/// thread take as a generic.
+///
+/// See [`ContextWrapper::make_current`] for more details.
+///
+/// [`ContextWrapper::make_current`]:
+/// struct.ContextWrapper.html#method.make_current
+#[derive(Debug, Clone, Copy)]
pub struct PossiblyCurrentContext {
phantom: PhantomData<*mut ()>,
}
-#[derive(Debug, Clone)]
+/// A type that contexts which are not currently current on any thread take as
+/// a generic.
+///
+/// See [`ContextWrapper::make_current`] for more details.
+///
+/// [`ContextWrapper::make_current`]:
+/// struct.ContextWrapper.html#method.make_current
+#[derive(Debug, Clone, Copy)]
pub enum NotCurrentContext {}
+/// A trait implemented on both [`NotCurrentContext`] and
+/// [`PossiblyCurrentContext`].
+///
+/// [`NotCurrentContext`]: enum.NotCurrentContext.html
+/// [`PossiblyCurrentContext`]: struct.PossiblyCurrentContext.html
pub trait ContextCurrentState: std::fmt::Debug + Clone {}
impl ContextCurrentState for PossiblyCurrentContext {}
diff --git a/glutin/src/lib.rs b/glutin/src/lib.rs
index 32f42c0..1d8625c 100644
--- a/glutin/src/lib.rs
+++ b/glutin/src/lib.rs
@@ -43,6 +43,8 @@
missing_debug_implementations,
//missing_docs,
)]
+// Docs for subcrates are borked.
+#![allow(intra_doc_link_resolution_failure)]
#[cfg(any(
target_os = "windows",
@@ -76,8 +78,7 @@ mod platform;
mod windowed;
pub use crate::context::{
- Context, ContextCurrentState, ContextTrait, NotCurrentContext,
- PossiblyCurrentContext, PossiblyCurrentContextTrait,
+ Context, ContextCurrentState, NotCurrentContext, PossiblyCurrentContext,
};
pub use crate::windowed::{ContextWrapper, RawContext, WindowedContext};
@@ -264,20 +265,19 @@ impl<'a, T: ContextCurrentState> ContextBuilder<'a, T> {
#[derive(Debug)]
pub enum CreationError {
OsError(String),
- /// TODO: remove this error
- NotSupported(&'static str),
+ NotSupported(String),
NoBackendAvailable(Box<std::error::Error + Send + Sync>),
RobustnessNotSupported,
OpenGlVersionNotSupported,
NoAvailablePixelFormat,
PlatformSpecific(String),
Window(WindowCreationError),
- /// We received two errors, instead of one.
+ /// We received multiple errors, instead of one.
CreationErrors(Vec<Box<CreationError>>),
}
impl CreationError {
- pub fn append(self, err: CreationError) -> Self {
+ pub(crate) fn append(self, err: CreationError) -> Self {
match self {
CreationError::CreationErrors(mut errs) => {
errs.push(Box::new(err));
@@ -292,8 +292,8 @@ impl CreationError {
fn to_string(&self) -> &str {
match *self {
- CreationError::OsError(ref text) => &text,
- CreationError::NotSupported(text) => &text,
+ CreationError::OsError(ref text)
+ | CreationError::NotSupported(ref text) => &text,
CreationError::NoBackendAvailable(_) => "No backend is available",
CreationError::RobustnessNotSupported => {
"You requested robustness, but it is not supported."
@@ -327,9 +327,6 @@ impl std::fmt::Display for CreationError {
write!(formatter, "`")?;
}
- if let &CreationError::NotSupported(msg) = self {
- write!(formatter, ": {}", msg)?;
- }
if let Some(err) = std::error::Error::source(self) {
write!(formatter, ": {}", err)?;
}
@@ -508,17 +505,20 @@ pub enum ReleaseBehavior {
Flush,
}
-/// Describes a possible format. Unused.
+/// Describes a possible format.
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub struct PixelFormat {
pub hardware_accelerated: bool,
+ /// The number of color bits. Does not include alpha bits.
pub color_bits: u8,
pub alpha_bits: u8,
pub depth_bits: u8,
pub stencil_bits: u8,
pub stereoscopy: bool,
pub double_buffer: bool,
+ /// `None` if multisampling is disabled, otherwise `Some(N)` where `N` is
+ /// the multisampling level.
pub multisampling: Option<u16>,
pub srgb: bool,
}
@@ -551,7 +551,7 @@ pub struct PixelFormatRequirements {
/// The default value is `Some(24)`.
pub depth_bits: Option<u8>,
- /// Minimum number of bits for the depth buffer. `None` means "don't care".
+ /// Minimum number of stencil bits. `None` means "don't care".
/// The default value is `Some(8)`.
pub stencil_bits: Option<u8>,
diff --git a/glutin/src/os/mod.rs b/glutin/src/os/mod.rs
index 4ef0c07..b73a465 100644
--- a/glutin/src/os/mod.rs
+++ b/glutin/src/os/mod.rs
@@ -9,11 +9,17 @@
//! - `windows`
//!
+/// Platform specific methods for android.
pub mod android;
+/// Platform specific methods for blank backend.
pub mod blank;
+/// Platform specific methods for iOS.
pub mod ios;
+/// Platform specific methods for macOS.
pub mod macos;
+/// Platform specific methods for unix.
pub mod unix;
+/// Platform specific methods for Windows.
pub mod windows;
use std::os::raw;
diff --git a/glutin/src/platform/linux/mod.rs b/glutin/src/platform/linux/mod.rs
index 2e16790..1f99f8e 100644
--- a/glutin/src/platform/linux/mod.rs
+++ b/glutin/src/platform/linux/mod.rs
@@ -26,7 +26,9 @@ use std::sync::Arc;
/// Context handles available on Unix-like platforms.
#[derive(Clone, Debug)]
pub enum RawHandle {
+ /// Context handles for glx contexts.
Glx(glutin_glx_sys::GLXContext),
+ /// Context handles for egl contexts.
Egl(glutin_egl_sys::EGLContext),
}
@@ -240,7 +242,16 @@ impl Context {
}
}
+/// A linux-specific extension to the [`ContextBuilder`] which allows building
+/// linux specific headless contexts.
+///
+/// [`ContextBuilder`]: struct.ContextBuilder.html
pub trait HeadlessContextExt {
+ /// Builds the given OsMesa context.
+ ///
+ /// Errors can occur if the OpenGL context could not be created. This
+ /// generally happens because the underlying platform doesn't support a
+ /// requested feature.
fn build_osmesa(
self,
size: dpi::PhysicalSize,
@@ -248,6 +259,11 @@ pub trait HeadlessContextExt {
where
Self: Sized;
+ /// Builds an EGL-surfaceless context.
+ ///
+ /// Errors can occur if the OpenGL context could not be created. This
+ /// generally happens because the underlying platform doesn't support a
+ /// requested feature.
fn build_surfaceless(
self,
el: &winit::EventsLoop,
@@ -259,11 +275,6 @@ pub trait HeadlessContextExt {
impl<'a, T: ContextCurrentState> HeadlessContextExt
for crate::ContextBuilder<'a, T>
{
- /// Builds the given OsMesa context.
- ///
- /// Errors can occur if the OpenGL context could not be created. This
- /// generally happens because the underlying platform doesn't support a
- /// requested feature.
#[inline]
fn build_osmesa(
self,
@@ -287,11 +298,6 @@ impl<'a, T: ContextCurrentState> HeadlessContextExt
})
}
- /// Builds an egl-surfaceless context.
- ///
- /// Errors can occur if the OpenGL context could not be created. This
- /// generally happens because the underlying platform doesn't support a
- /// requested feature.
#[inline]
fn build_surfaceless(
self,
@@ -311,6 +317,11 @@ impl<'a, T: ContextCurrentState> HeadlessContextExt
}
}
+/// A linux-specific for the [`ContextBuilder`] which allows assembling
+/// [`RawContext<T>`]s.
+///
+/// [`RawContext<T>`]: type.RawContext.html
+/// [`ContextBuilder`]: struct.ContextBuilder.html
pub trait RawContextExt {
/// Creates a raw context on the provided surface.
///
diff --git a/glutin/src/platform/linux/wayland.rs b/glutin/src/platform/linux/wayland.rs
index 6e8b332..8c97f90 100644
--- a/glutin/src/platform/linux/wayland.rs
+++ b/glutin/src/platform/linux/wayland.rs
@@ -95,7 +95,9 @@ impl Context {
let surface = match surface {
Some(s) => s,
None => {
- return Err(CreationError::NotSupported("Wayland not found"));
+ return Err(CreationError::NotSupported(
+ "Wayland not found".to_string(),
+ ));
}
};
diff --git a/glutin/src/platform/linux/x11.rs b/glutin/src/platform/linux/x11.rs
index f838e1a..dbda206 100644
--- a/glutin/src/platform/linux/x11.rs
+++ b/glutin/src/platform/linux/x11.rs
@@ -298,7 +298,7 @@ impl Context {
}
return Err(CreationError::NotSupported(
- "both libGL and libEGL are not present",
+ "both libGL and libEGL are not present".to_string(),
));
} else {
match (&*GLX, &*EGL, prefer_egl) {
@@ -308,7 +308,7 @@ impl Context {
}
return Err(CreationError::NotSupported(
- "lacking either libGL or libEGL so could not fallback to other",
+ "lacking either libGL or libEGL so could not fallback to other".to_string(),
));
}
}
@@ -328,13 +328,13 @@ impl Context {
)?)
} else {
return Err(CreationError::NotSupported(
- "libEGL not present",
+ "libEGL not present".to_string(),
));
}
}
GlRequest::Specific(_, _) => {
return Err(CreationError::NotSupported(
- "requested specific without gl or gles",
+ "requested specific without gl or gles".to_string(),
));
}
})
diff --git a/glutin/src/platform/macos/mod.rs b/glutin/src/platform/macos/mod.rs
index cd58f32..6aeea50 100644
--- a/glutin/src/platform/macos/mod.rs
+++ b/glutin/src/platform/macos/mod.rs
@@ -90,7 +90,7 @@ impl Context {
Some(gl_context) => gl_context,
None => {
return Err(CreationError::NotSupported(
- "could not open gl context",
+ "could not open gl context".to_string(),
));
}
};
@@ -175,16 +175,16 @@ impl Context {
let pixelformat = NSOpenGLPixelFormat::alloc(nil)
.initWithAttributes_(&attributes);
if pixelformat == nil {
- return Err(CreationError::OsError(format!(
- "Could not create the pixel format"
- )));
+ return Err(CreationError::OsError(
+ "Could not create the pixel format".to_string(),
+ ));
}
let context = NSOpenGLContext::alloc(nil)
.initWithFormat_shareContext_(pixelformat, nil);
if context == nil {
- return Err(CreationError::OsError(format!(
- "Could not create the rendering context"
- )));
+ return Err(CreationError::OsError(
+ "Could not create the rendering context".to_string(),
+ ));
}
IdRef::new(context)
diff --git a/glutin/src/windowed.rs b/glutin/src/windowed.rs
index 5c4e51e..5bb254c 100644
--- a/glutin/src/windowed.rs
+++ b/glutin/src/windowed.rs
@@ -4,10 +4,11 @@ use std::marker::PhantomData;
/// Represents an OpenGL context and the `Window` with which it is associated.
///
+/// Please see [`ContextWrapper<T, Window>`].
+///
/// # Example
///
/// ```no_run
-/// # use glutin::ContextTrait;
/// # fn main() {
/// let mut el = glutin::EventsLoop::new();
/// let wb = glutin::WindowBuilder::new();
@@ -32,11 +33,69 @@ use std::marker::PhantomData;
/// }
/// # }
/// ```
+///
+/// [`ContextWrapper<T, Window>`]: struct.ContextWrapper.html
pub type WindowedContext<T> = ContextWrapper<T, Window>;
-/// Represents a raw OpenGL context.
+/// Represents am OpenGL context which has an underlying window that is
+/// stored separately.
+///
+/// This type can only be created via one of three ways:
+///
+/// * [`os::unix::RawContextExt`]
+/// * [`os::windows::RawContextExt`]
+/// * [`WindowedContext<T>::split`]
+///
+/// Please see [`ContextWrapper<T, ()>`].
+///
+/// [`ContextWrapper<T, ()>`]: struct.ContextWrapper.html
+/// [`WindowedContext<T>::split`]: type.WindowedContext.html#method.split
+#[cfg_attr(
+ target_os = "windows",
+ doc = "\
+[`os::windows::RawContextExt`]: os/windows/enum.RawHandle.html
+"
+)]
+#[cfg_attr(
+ not(target_os = "windows",),
+ doc = "\
+[`os::windows::RawContextExt`]: os/index.html
+"
+)]
+#[cfg_attr(
+ not(any(
+ target_os = "linux",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )),
+ doc = "\
+[`os::unix::RawContextExt`]: os/index.html
+"
+)]
+#[cfg_attr(
+ any(
+ target_os = "linux",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ),
+ doc = "\
+[`os::unix::RawContextExt`]: os/unix/enum.RawHandle.html
+"
+)]
pub type RawContext<T> = ContextWrapper<T, ()>;
+/// A context which has an underlying window, which may or may not be stored
+/// separately.
+///
+/// If the window is stored separately, it is a [`RawContext<T>`]. Otherwise,
+/// it is a [`WindowedContext<T>`].
+///
+/// [`WindowedContext<T>`]: type.WindowedContext.html
+/// [`RawContext<T>`]: type.RawContext.html
#[derive(Debug)]
pub struct ContextWrapper<T: ContextCurrentState, W> {
pub(crate) context: Context<T>,
@@ -65,13 +124,6 @@ impl<T: ContextCurrentState> WindowedContext<T> {
}
}
-impl<T: ContextCurrentState, W> ContextWrapper<T, W> {
- /// Borrow the inner GL `Context`.
- pub fn context(&self) -> &Context<T> {
- &self.context
- }
-}
-
impl<W> ContextWrapper<PossiblyCurrentContext, W> {
/// Swaps the buffers in case of double or triple buffering.
///
@@ -105,13 +157,70 @@ impl<W> ContextWrapper<PossiblyCurrentContext, W> {
}
}
-impl<T: ContextCurrentState, W> ContextTrait for ContextWrapper<T, W> {
- type PossiblyCurrentContext = ContextWrapper<PossiblyCurrentContext, W>;
- type NotCurrentContext = ContextWrapper<NotCurrentContext, W>;
+impl<T: ContextCurrentState, W> ContextWrapper<T, W> {
+ /// Borrow the inner GL `Context`.
+ pub fn context(&self) -> &Context<T> {
+ &self.context
+ }
- unsafe fn make_current(
+ /// Sets this context as the current context. The previously current context
+ /// (if any) is no longer current.
+ ///
+ /// A failed call to `make_current` might make this, or no context
+ /// current. It could also keep the previous context current. What happens
+ /// varies by platform and error.
+ ///
+ /// To attempt to recover and get back into a know state, either:
+ ///
+ /// * attempt to use [`is_current`] to find the new current context; or
+ /// * call [`make_not_current`] on both the previously
+ /// current context and this context.
+ ///
+ /// # An higher level overview.
+ ///
+ /// In OpenGl, only a single context can be current in a thread at a time.
+ /// Making a new context current will make the old one not current.
+ /// Contexts can only be sent to different threads if they are not current.
+ ///
+ /// If you call `make_current` on some context, you should call
+ /// [`treat_as_not_current`] as soon as possible on the previously current
+ /// context.
+ ///
+ /// If you wish to move a currently current context to a different thread,
+ /// you should do one of two options:
+ ///
+ /// * Call `make_current` on an other context, then call
+ /// [`treat_as_not_current`] on this context.
+ /// * Call [`make_current`] on this context.
+ ///
+ /// If you are aware of what context you intend to make current next, it is
+ /// preferable for performance reasons to call `make_current` on that
+ /// context, then [`treat_as_not_current`] on this context.
+ ///
+ /// If you are not aware of what context you intend to make current next,
+ /// consider waiting until you do. If you need this context not current
+ /// immediately (e.g. to transfer it to an other thread), then call
+ /// [`make_not_current`] on this context.
+ ///
+ /// Please avoid calling [`make_not_current`] on one context only to call
+ /// [`make_current`] on an other context before and/or after. This hurts
+ /// performance by requiring glutin to:
+ ///
+ /// * Check if this context is current; then
+ /// * If it is, change the current context from this context to none; then
+ /// * Change the current context from none to the new context.
+ ///
+ /// Instead prefer the method we mentioned above with `make_current` and
+ /// [`treat_as_not_current`].
+ ///
+ /// [`make_not_current`]: struct.ContextWrapper.html#method.make_not_current
+ /// [`treat_as_not_current`]:
+ /// struct.ContextWrapper.html#method.treat_as_not_current
+ /// [`is_current`]: struct.ContextWrapper.html#method.is_current
+ pub unsafe fn make_current(
self,
- ) -> Result<Self::PossiblyCurrentContext, (Self, ContextError)> {
+ ) -> Result<ContextWrapper<PossiblyCurrentContext, W>, (Self, ContextError)>
+ {
let window = self.window;
match self.context.make_current() {
Ok(context) => Ok(ContextWrapper { window, context }),
@@ -121,9 +230,16 @@ impl<T: ContextCurrentState, W> ContextTrait for ContextWrapper<T, W> {
}
}
- unsafe fn make_not_current(
+ /// If this context is current, makes this context not current. If this
+ /// context is not current however, this function does nothing.
+ ///
+ /// Please see [`make_current`].
+ ///
+ /// [`make_current`]: struct.ContextWrapper.html#method.make_current
+ pub unsafe fn make_not_current(
self,
- ) -> Result<Self::NotCurrentContext, (Self, ContextError)> {
+ ) -> Result<ContextWrapper<NotCurrentContext, W>, (Self, ContextError)>
+ {
let window = self.window;
match self.context.make_not_current() {
Ok(context) => Ok(ContextWrapper { window, context }),
@@ -133,26 +249,40 @@ impl<T: ContextCurrentState, W> ContextTrait for ContextWrapper<T, W> {
}
}
- unsafe fn treat_as_not_current(self) -> Self::NotCurrentContext {
+ /// Treats this context as not current, even if it is current. We do no
+ /// checks to confirm that this is actually case.
+ ///
+ /// If unsure whether or not this context is current, please use
+ /// [`make_not_current`] which will do nothing if this context is not
+ /// current.
+ ///
+ /// Please see [`make_current`].
+ ///
+ /// [`make_not_current`]: struct.ContextWrapper.html#method.make_not_current
+ /// [`make_current`]: struct.ContextWrapper.html#method.make_current
+ pub unsafe fn treat_as_not_current(
+ self,
+ ) -> ContextWrapper<NotCurrentContext, W> {
ContextWrapper {
context: self.context.treat_as_not_current(),
window: self.window,
}
}
- fn is_current(&self) -> bool {
+ /// Returns true if this context is the current one in this thread.
+ pub fn is_current(&self) -> bool {
self.context.is_current()
}
- fn get_api(&self) -> Api {
+ /// Returns the OpenGL API being used.
+ pub fn get_api(&self) -> Api {
self.context.get_api()
}
}
-impl<W> PossiblyCurrentContextTrait
- for ContextWrapper<PossiblyCurrentContext, W>
-{
- fn get_proc_address(&self, addr: &str) -> *const () {
+impl<W> ContextWrapper<PossiblyCurrentContext, W> {
+ /// Returns the address of an OpenGL function.
+ pub fn get_proc_address(&self, addr: &str) -> *const () {
self.context.get_proc_address(addr)
}
}
diff --git a/glutin_examples/examples/fullscreen.rs b/glutin_examples/examples/fullscreen.rs
index 2e7baf0..628fec0 100644
--- a/glutin_examples/examples/fullscreen.rs
+++ b/glutin_examples/examples/fullscreen.rs
@@ -1,6 +1,5 @@
mod support;
-use glutin::ContextTrait;
use std::io::{self, Write};
fn main() {
diff --git a/glutin_examples/examples/headless.rs b/glutin_examples/examples/headless.rs
index beba6c5..50abf67 100644
--- a/glutin_examples/examples/headless.rs
+++ b/glutin_examples/examples/headless.rs
@@ -1,7 +1,6 @@
mod support;
use glutin::dpi::PhysicalSize;
-use glutin::ContextTrait;
use std::path::Path;
use support::gl;
diff --git a/glutin_examples/examples/multiwindow.rs b/glutin_examples/examples/multiwindow.rs
index e4ac4ec..9ce8b06 100644
--- a/glutin_examples/examples/multiwindow.rs
+++ b/glutin_examples/examples/multiwindow.rs
@@ -1,7 +1,5 @@
mod support;
-use glutin::ContextTrait;
-
use support::{ContextCurrentWrapper, ContextTracker, ContextWrapper};
fn main() {
diff --git a/glutin_examples/examples/raw_context.rs b/glutin_examples/examples/raw_context.rs
index 5fac0ce..a47c584 100644
--- a/glutin_examples/examples/raw_context.rs
+++ b/glutin_examples/examples/raw_context.rs
@@ -11,7 +11,6 @@ fn main() {
#[cfg(any(target_os = "linux", target_os = "windows"))]
mod this_example {
use super::support;
- use glutin::ContextTrait;
pub fn main() {
let (raw_context, mut el, win) = {
diff --git a/glutin_examples/examples/support/mod.rs b/glutin_examples/examples/support/mod.rs
index d7a31c4..008cfb4 100644
--- a/glutin_examples/examples/support/mod.rs
+++ b/glutin_examples/examples/support/mod.rs
@@ -1,4 +1,4 @@
-use glutin::{self, PossiblyCurrentContext, PossiblyCurrentContextTrait};
+use glutin::{self, PossiblyCurrentContext};
use std::ffi::CStr;
@@ -168,8 +168,8 @@ pub use self::context_tracker::{
#[allow(dead_code)] // Not used by all examples
mod context_tracker {
use glutin::{
- self, Context, ContextCurrentState, ContextError, ContextTrait,
- NotCurrentContext, PossiblyCurrentContext, WindowedContext,
+ self, Context, ContextCurrentState, ContextError, NotCurrentContext,
+ PossiblyCurrentContext, WindowedContext,
};
use takeable_option::Takeable;
@@ -370,6 +370,17 @@ mod context_tracker {
}
}
+ if let Err(err2) = self.modify(id, |ctx| {
+ ctx.map_possibly(|ctx| {
+ ctx.map(
+ |ctx| ctx.make_not_current(),
+ |ctx| ctx.make_not_current(),
+ )
+ })
+ }) {
+ panic!("Could not `make_current` nor `make_not_current`, {:?}, {:?}", err, err2);
+ }
+
return Err(err);
}
diff --git a/glutin_examples/examples/transparent.rs b/glutin_examples/examples/transparent.rs
index 6480472..3ff7429 100644
--- a/glutin_examples/examples/transparent.rs
+++ b/glutin_examples/examples/transparent.rs
@@ -1,7 +1,5 @@
mod support;
-use glutin::ContextTrait;
-
fn main() {
let mut el = glutin::EventsLoop::new();
let wb = glutin::WindowBuilder::new()
diff --git a/glutin_examples/examples/window.rs b/glutin_examples/examples/window.rs
index 92cedb7..6e23485 100644
--- a/glutin_examples/examples/window.rs
+++ b/glutin_examples/examples/window.rs
@@ -1,7 +1,5 @@
mod support;
-use glutin::ContextTrait;
-
fn main() {
let mut el = glutin::EventsLoop::new();
let wb = glutin::WindowBuilder::new().with_title("A fantastic window!");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment