diff --git a/CHANGELOG.md b/CHANGELOG.md index b64ceee90a..bed8265ab8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,16 @@ # Unreleased -- Add `PossiblyCurrentContext::make_not_current_in_place(&self)` for when `Send` capability of `NotCurrentContext` is not required. -- Add `NotCurrentContext::make_current_surfaceless(self)` and `PossiblyCurrentContext::make_current_surfaceless(&self)` in the `Cgl` implementation to allow the use of surfaceless contexts on MacOS. -- Add `NotCurrentContext::make_current_surfaceless(self)` and `PossiblyCurrentContext::make_current_surfaceless(&self)` in the `Glx` implementation to allow the use of surfaceless contexts with GLX. +- Added `PossiblyCurrentContext::make_not_current_in_place(&self)` for when `Send` capability of `NotCurrentContext` is not required. +- Added `NotCurrentContext::make_current_surfaceless(self)` and + `PossiblyCurrentContext::make_current_surfaceless(&self)` in the `Cgl` + implementation to allow the use of surfaceless contexts on MacOS. +- Added `NotCurrentContext::make_current_surfaceless(self)` and + `PossiblyCurrentContext::make_current_surfaceless(&self)` in the `Glx` + implementation to allow the use of surfaceless contexts with GLX. +- Added `NotCurrentContext::make_current_surfaceless(self)` and + `PossiblyCurrentContext::make_current_surfaceless(&self)` in the `Wgl` + implementation to allow the use of surfaceless contexts with WGL. + # Version 0.32.1 diff --git a/glutin/src/api/wgl/context.rs b/glutin/src/api/wgl/context.rs index b443cab6da..e676ba7914 100644 --- a/glutin/src/api/wgl/context.rs +++ b/glutin/src/api/wgl/context.rs @@ -45,27 +45,34 @@ impl Display { _ => std::ptr::null(), }; - let context = if self.inner.client_extensions.contains("WGL_ARB_create_context") { - self.create_context_arb(hdc, share_ctx, context_attributes)? - } else { - unsafe { - let raw = wgl::CreateContext(hdc as *const _); - if raw.is_null() { - return Err(IoError::last_os_error().into()); - } + let (context, supports_surfaceless) = + if self.inner.client_extensions.contains("WGL_ARB_create_context") { + self.create_context_arb(hdc, share_ctx, context_attributes)? + } else { + unsafe { + let raw = wgl::CreateContext(hdc as *const _); + if raw.is_null() { + return Err(IoError::last_os_error().into()); + } - // Context sharing. - if !share_ctx.is_null() && wgl::ShareLists(share_ctx, raw) == 0 { - return Err(IoError::last_os_error().into()); - } + // Context sharing. + if !share_ctx.is_null() && wgl::ShareLists(share_ctx, raw) == 0 { + return Err(IoError::last_os_error().into()); + } - WglContext(raw) - } - }; + (WglContext(raw), false) + } + }; let config = config.clone(); let is_gles = matches!(context_attributes.api, Some(ContextApi::Gles(_))); - let inner = ContextInner { display: self.clone(), config, raw: context, is_gles }; + let inner = ContextInner { + display: self.clone(), + config, + raw: context, + is_gles, + supports_surfaceless, + }; Ok(NotCurrentContext { inner }) } @@ -74,14 +81,14 @@ impl Display { hdc: HDC, share_context: HGLRC, context_attributes: &ContextAttributes, - ) -> Result { + ) -> Result<(WglContext, bool)> { let extra = self.inner.wgl_extra.as_ref().unwrap(); let mut attrs = Vec::::with_capacity(16); // Check whether the ES context creation is supported. let supports_es = self.inner.features.contains(DisplayFeatures::CREATE_ES_CONTEXT); - let (profile, version) = match context_attributes.api { + let (profile, version, supports_surfaceless) = match context_attributes.api { api @ Some(ContextApi::OpenGl(_)) | api @ None => { let version = api.and_then(|api| api.version()); let (profile, version) = context::pick_profile(context_attributes.profile, version); @@ -90,11 +97,16 @@ impl Display { GlProfile::Compatibility => wgl_extra::CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, }; - (Some(profile), Some(version)) + // Surfaceless contexts are supported with the WGL_ARB_create_context extension + // when using OpenGL 3.0 or greater. + let supports_surfaceless = version >= Version::new(3, 0); + + (Some(profile), Some(version), supports_surfaceless) }, Some(ContextApi::Gles(version)) if supports_es => ( Some(wgl_extra::CONTEXT_ES2_PROFILE_BIT_EXT), Some(version.unwrap_or(Version::new(2, 0))), + false, ), _ => { return Err(ErrorKind::NotSupported( @@ -201,7 +213,7 @@ impl Display { if raw.is_null() { Err(IoError::last_os_error().into()) } else { - Ok(WglContext(raw)) + Ok((WglContext(raw), supports_surfaceless)) } } } @@ -220,6 +232,15 @@ impl NotCurrentContext { fn new(inner: ContextInner) -> Self { Self { inner } } + + /// Make a [`Self::PossiblyCurrentContext`] indicating that the context + /// could be current on the thread. + /// + /// Requires the WGL_ARB_create_context extension and OpenGL 3.0 or greater. + pub fn make_current_surfaceless(self) -> Result { + self.inner.make_current_surfaceless()?; + Ok(PossiblyCurrentContext { inner: self.inner, _nosendsync: PhantomData }) + } } impl NotCurrentGlContext for NotCurrentContext { @@ -283,6 +304,15 @@ pub struct PossiblyCurrentContext { _nosendsync: PhantomData, } +impl PossiblyCurrentContext { + /// Make this context current on the calling thread. + /// + /// Requires the WGL_ARB_create_context extension and OpenGL 3.0 or greater. + pub fn make_current_surfaceless(&self) -> Result<()> { + self.inner.make_current_surfaceless() + } +} + impl PossiblyCurrentGlContext for PossiblyCurrentContext { type NotCurrentContext = NotCurrentContext; type Surface = Surface; @@ -356,6 +386,7 @@ struct ContextInner { config: Config, raw: WglContext, is_gles: bool, + supports_surfaceless: bool, } impl fmt::Debug for ContextInner { @@ -381,6 +412,22 @@ impl Deref for WglContext { unsafe impl Send for WglContext {} impl ContextInner { + fn make_current_surfaceless(&self) -> Result<()> { + if !self.supports_surfaceless { + return Err( + ErrorKind::NotSupported("the surfaceless context Api isn't supported").into() + ); + } + + unsafe { + if wgl::MakeCurrent(std::ptr::null(), self.raw.cast()) == 0 { + Err(IoError::last_os_error().into()) + } else { + Ok(()) + } + } + } + fn make_current_draw_read( &self, _surface_draw: &Surface,