diff --git a/glutin/src/api/egl/config.rs b/glutin/src/api/egl/config.rs index 0c9c2da5e0..d136d93547 100644 --- a/glutin/src/api/egl/config.rs +++ b/glutin/src/api/egl/config.rs @@ -5,9 +5,7 @@ use std::ops::Deref; use std::sync::Arc; use std::{fmt, mem}; -use raw_window_handle::{ - HasDisplayHandle, HasRawDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawWindowHandle, -}; +use raw_window_handle::{HasDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawWindowHandle}; use glutin_egl_sys::egl; use glutin_egl_sys::egl::types::{EGLConfig, EGLint}; @@ -186,7 +184,7 @@ impl Display { } let raw_handle = - template.native_window.map(|w| w.window_handle()?.raw_window_handle()).transpose()?; + template._native_window.map(|w| w.window_handle()?.raw_window_handle()).transpose()?; let configs = found_configs .into_iter() .map(move |raw| { @@ -352,7 +350,7 @@ impl GlConfig for Config { #[cfg(any(wayland_platform, x11_platform))] fn supports_transparency(&self) -> Option { - use raw_window_handle::RawDisplayHandle; + use raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle}; match self .inner .display @@ -411,6 +409,7 @@ impl AsRawConfig for Config { #[cfg(x11_platform)] impl X11GlConfigExt for Config { fn x11_visual(&self) -> Option { + use raw_window_handle::HasRawDisplayHandle; match self .inner .display diff --git a/glutin/src/api/egl/display.rs b/glutin/src/api/egl/display.rs index b044fc5a60..69835561ee 100644 --- a/glutin/src/api/egl/display.rs +++ b/glutin/src/api/egl/display.rs @@ -16,7 +16,9 @@ use raw_window_handle::{HasDisplayHandle, HasRawDisplayHandle, HasWindowHandle, use crate::config::ConfigTemplate; use crate::context::Version; -use crate::display::{AsRawDisplay, DisplayFeatures, GetDisplayExtensions, RawDisplay}; +use crate::display::{ + AsRawDisplay, DisplayFeatures, DisplayResult, GetDisplayExtensions, RawDisplay, +}; use crate::error::{ErrorKind, Result}; use crate::prelude::*; use crate::private::Sealed; @@ -55,32 +57,39 @@ impl Display { /// `EGL_DEFAULT_DISPLAY`, which is not recommended or will /// work on a platform with a concept of native display, like Wayland. pub fn new(raw_display: D) -> Result { + Self::new_with_display(raw_display).map_err(Into::into) + } + + pub(crate) fn new_with_display(raw_display: D) -> DisplayResult { let egl = match EGL.as_ref() { Some(egl) => egl, - None => return Err(ErrorKind::NotFound.into()), + None => return Err((ErrorKind::NotFound, raw_display).into()), }; NO_DISPLAY_EXTENSIONS.get_or_init(|| get_extensions(egl, egl::NO_DISPLAY)); // Create a EGL display by chaining all display creation functions aborting on // `EGL_BAD_ATTRIBUTE`. - let display = Self::get_platform_display(egl, raw_display) + let display = match Self::get_platform_display(egl, &raw_display) .or_else(|err| { if err.error_kind() == ErrorKind::BadAttribute { Err(err) } else { - Self::get_platform_display_ext(egl, raw_display) + Self::get_platform_display_ext(egl, &raw_display) } }) .or_else(|err| { if err.error_kind() == ErrorKind::BadAttribute { Err(err) } else { - Self::get_display(egl, raw_display) + Self::get_display(egl, &raw_display) } - })?; + }) { + Ok(display) => display, + Err(err) => return Err((err, raw_display).into()), + }; - Self::initialize_display(egl, display, Some(raw_display)) + Self::initialize_display(egl, display, Some(raw_display)).map_err(|e| e.unwrap()) } /// Create an EGL display using the specified device. @@ -145,7 +154,7 @@ impl Display { }) .map(EglDisplay::Ext)?; - Self::initialize_display(egl, display, None) + Self::initialize_display(egl, display, None).map_err(Into::into) } /// Get the [`Device`] the display is using. @@ -188,7 +197,7 @@ impl Display { Device::from_ptr(self.inner.egl, device) } - fn get_platform_display(egl: &Egl, display: D) -> Result { + fn get_platform_display(egl: &Egl, display: &D) -> Result { if !egl.GetPlatformDisplay.is_loaded() { return Err(ErrorKind::NotSupported("eglGetPlatformDisplay is not supported").into()); } @@ -236,7 +245,7 @@ impl Display { Self::check_display_error(display).map(EglDisplay::Khr) } - fn get_platform_display_ext(egl: &Egl, display: D) -> Result { + fn get_platform_display_ext(egl: &Egl, display: &D) -> Result { if !egl.GetPlatformDisplayEXT.is_loaded() { return Err(ErrorKind::NotSupported("eglGetPlatformDisplayEXT is not supported").into()); } @@ -306,7 +315,7 @@ impl Display { }) } - fn get_display(egl: &Egl, display: D) -> Result { + fn get_display(egl: &Egl, display: &D) -> Result { let mut display = match display.display_handle()?.raw_display_handle()? { RawDisplayHandle::Gbm(handle) => handle.gbm_device, #[cfg(x11_platform)] @@ -374,11 +383,15 @@ impl Display { egl: &'static Egl, display: EglDisplay, handle: Option, - ) -> Result { + ) -> DisplayResult> { let version = unsafe { let (mut major, mut minor) = (0, 0); if egl.Initialize(*display, &mut major, &mut minor) == egl::FALSE { - return Err(super::check_error().expect_err("eglInit failed without a reason")); + return Err(( + super::check_error().expect_err("eglInit failed without a reason"), + handle, + ) + .into()); } Version::new(major as u8, minor as u8) diff --git a/glutin/src/api/glx/config.rs b/glutin/src/api/glx/config.rs index f682ce47d7..091ff7edfc 100644 --- a/glutin/src/api/glx/config.rs +++ b/glutin/src/api/glx/config.rs @@ -97,7 +97,7 @@ impl Display { // Add visual if was provided. if let Some(RawWindowHandle::Xlib(window)) = - template.native_window.map(|w| w.window_handle()?.raw_window_handle()).transpose()? + template._native_window.map(|w| w.window_handle()?.raw_window_handle()).transpose()? { if window.visual_id > 0 { config_attributes.push(glx::VISUAL_ID as c_int); diff --git a/glutin/src/api/glx/display.rs b/glutin/src/api/glx/display.rs index 543716335d..6afb1a6900 100644 --- a/glutin/src/api/glx/display.rs +++ b/glutin/src/api/glx/display.rs @@ -13,7 +13,9 @@ use raw_window_handle::{HasDisplayHandle, HasRawDisplayHandle, HasWindowHandle, use crate::config::ConfigTemplate; use crate::context::Version; -use crate::display::{AsRawDisplay, DisplayFeatures, GetDisplayExtensions, RawDisplay}; +use crate::display::{ + AsRawDisplay, DisplayFeatures, DisplayResult, GetDisplayExtensions, RawDisplay, +}; use crate::error::{ErrorKind, Result}; use crate::prelude::*; use crate::private::Sealed; @@ -39,25 +41,36 @@ impl Clone for Display { impl Display { /// Create GLX display. pub fn new(display_handle: D, error_hook_registrar: XlibErrorHookRegistrar) -> Result { + Self::new_with_display(display_handle, error_hook_registrar).map_err(Into::into) + } + + pub(crate) fn new_with_display( + display_handle: D, + error_hook_registrar: XlibErrorHookRegistrar, + ) -> DisplayResult { // Don't load GLX when unsupported platform was requested. - let (display, screen) = match display_handle.display_handle()?.raw_display_handle()? { - RawDisplayHandle::Xlib(handle) => { - if handle.display.is_null() { - return Err(ErrorKind::BadDisplay.into()); - } - - (GlxDisplay(handle.display as *mut _), handle.screen as i32) - }, - _ => { - return Err( - ErrorKind::NotSupported("provided native display isn't supported").into() - ) - }, - }; + let (display, screen) = + match display_handle.display_handle().and_then(|w| w.raw_display_handle()) { + Ok(RawDisplayHandle::Xlib(handle)) => { + if handle.display.is_null() { + return Err((ErrorKind::BadDisplay, display_handle).into()); + } + + (GlxDisplay(handle.display as *mut _), handle.screen as i32) + }, + Ok(_) => { + return Err(( + ErrorKind::NotSupported("provided native display isn't supported"), + display_handle, + ) + .into()) + }, + Err(e) => return Err((crate::error::Error::from(e), display_handle).into()), + }; let glx = match GLX.as_ref() { Some(glx) => glx, - None => return Err(ErrorKind::NotFound.into()), + None => return Err((ErrorKind::NotFound, display_handle).into()), }; // Set the base for errors coming from GLX. @@ -66,7 +79,7 @@ impl Display { let mut event_base = 0; if glx.QueryExtension(display.0, &mut error_base, &mut event_base) == 0 { // The glx extension isn't present. - return Err(ErrorKind::InitializationFailed.into()); + return Err((ErrorKind::InitializationFailed, display_handle).into()); } GLX_BASE_ERROR.store(error_base, Ordering::Relaxed); } @@ -82,13 +95,17 @@ impl Display { let version = unsafe { let (mut major, mut minor) = (0, 0); if glx.QueryVersion(display.0, &mut major, &mut minor) == 0 { - return Err(ErrorKind::InitializationFailed.into()); + return Err((ErrorKind::InitializationFailed, display_handle).into()); } Version::new(major as u8, minor as u8) }; if version < Version::new(1, 3) { - return Err(ErrorKind::NotSupported("the glx below 1.3 isn't supported").into()); + return Err(( + ErrorKind::NotSupported("the glx below 1.3 isn't supported"), + display_handle, + ) + .into()); } // Register the error handling hook. diff --git a/glutin/src/api/wgl/config.rs b/glutin/src/api/wgl/config.rs index ad5fabbe8d..e65e187a2d 100644 --- a/glutin/src/api/wgl/config.rs +++ b/glutin/src/api/wgl/config.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use std::{fmt, iter}; use glutin_wgl_sys::wgl_extra; -use raw_window_handle::RawWindowHandle; +use raw_window_handle::{HasDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawWindowHandle}; use windows_sys::Win32::Graphics::Gdi::{self as gdi, HDC}; use windows_sys::Win32::Graphics::OpenGL::{self as gl, PIXELFORMATDESCRIPTOR}; @@ -27,12 +27,17 @@ const MAX_QUERY_CONFIGS: usize = 256; const SRGB_ARB: &str = "WGL_ARB_framebuffer_sRGB"; const SRGB_EXT: &str = "WGL_EXT_framebuffer_sRGB"; -impl Display { - pub(crate) unsafe fn find_configs( +impl Display { + pub(crate) fn find_configs( &self, - template: ConfigTemplate, - ) -> Result + '_>> { - let hwnd = match template.native_window { + template: ConfigTemplate, + ) -> Result> + '_>> { + let hwnd = match template + ._native_window + .as_ref() + .map(|w| w.window_handle()?.raw_window_handle()) + .transpose()? + { Some(RawWindowHandle::Win32(window_handle)) => window_handle.hwnd as _, _ => 0, }; @@ -47,11 +52,11 @@ impl Display { } } - fn find_normal_configs( + fn find_normal_configs( &self, - template: ConfigTemplate, + template: ConfigTemplate, hdc: HDC, - ) -> Result + '_>> { + ) -> Result> + '_>> { let (r_size, g_size, b_size) = match template.color_buffer_type { ColorBufferType::Rgb { r_size, g_size, b_size } => (r_size, g_size, b_size), _ => { @@ -152,11 +157,11 @@ impl Display { } } - fn find_configs_arb( + fn find_configs_arb( &self, - template: ConfigTemplate, + template: ConfigTemplate, hdc: HDC, - ) -> Result + '_>> { + ) -> Result> + '_>> { let wgl_extra = self.inner.wgl_extra.unwrap(); let mut attrs = Vec::::with_capacity(32); @@ -276,19 +281,33 @@ impl Display { } /// A wrapper around `PIXELFORMAT`. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Config { - pub(crate) inner: Arc, +#[derive(Debug)] +pub struct Config { + pub(crate) inner: Arc>, } -impl Config { +impl Clone for Config { + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } +} + +impl PartialEq for Config { + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner + } +} + +impl Eq for Config {} + +impl Config { /// Set the pixel format on the native window. /// /// # Safety /// /// The `raw_window_handle` should point to a valid value. - pub unsafe fn apply_on_native_window(&self, raw_window_handle: &RawWindowHandle) -> Result<()> { - let hdc = match raw_window_handle { + pub fn apply_on_native_window(&self, raw_window_handle: impl HasWindowHandle) -> Result<()> { + let hdc = match raw_window_handle.window_handle()?.raw_window_handle()? { RawWindowHandle::Win32(window) => unsafe { gdi::GetDC(window.hwnd as _) }, _ => return Err(ErrorKind::BadNativeWindow.into()), }; @@ -332,7 +351,7 @@ impl Config { } } -impl GlConfig for Config { +impl GlConfig for Config { fn color_buffer_type(&self) -> Option { let (r_size, g_size, b_size) = match self.inner.descriptor.as_ref() { Some(descriptor) => (descriptor.cRedBits, descriptor.cGreenBits, descriptor.cBlueBits), @@ -452,38 +471,38 @@ impl GlConfig for Config { } } -impl GetGlDisplay for Config { - type Target = Display; +impl GetGlDisplay for Config { + type Target = Display; fn display(&self) -> Self::Target { self.inner.display.clone() } } -impl AsRawConfig for Config { +impl AsRawConfig for Config { fn raw_config(&self) -> RawConfig { RawConfig::Wgl(self.inner.pixel_format_index) } } -impl Sealed for Config {} +impl Sealed for Config {} -pub(crate) struct ConfigInner { - pub(crate) display: Display, +pub(crate) struct ConfigInner { + pub(crate) display: Display, pub(crate) hdc: HDC, pub(crate) pixel_format_index: i32, pub(crate) descriptor: Option, } -impl PartialEq for ConfigInner { +impl PartialEq for ConfigInner { fn eq(&self, other: &Self) -> bool { self.pixel_format_index == other.pixel_format_index } } -impl Eq for ConfigInner {} +impl Eq for ConfigInner {} -impl fmt::Debug for ConfigInner { +impl fmt::Debug for ConfigInner { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Config") .field("hdc", &self.hdc) diff --git a/glutin/src/api/wgl/context.rs b/glutin/src/api/wgl/context.rs index dca9294a0b..8e218e1960 100644 --- a/glutin/src/api/wgl/context.rs +++ b/glutin/src/api/wgl/context.rs @@ -8,7 +8,7 @@ use std::os::raw::c_int; use glutin_wgl_sys::wgl::types::HGLRC; use glutin_wgl_sys::{wgl, wgl_extra}; -use raw_window_handle::RawWindowHandle; +use raw_window_handle::{HasDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawWindowHandle}; use windows_sys::Win32::Graphics::Gdi::{self as gdi, HDC}; use crate::config::GetGlConfig; @@ -26,21 +26,26 @@ use super::config::Config; use super::display::Display; use super::surface::Surface; -impl Display { - pub(crate) unsafe fn create_context( +impl Display { + pub(crate) fn create_context( &self, - config: &Config, - context_attributes: &ContextAttributes, - ) -> Result { - let hdc = match context_attributes.raw_window_handle.as_ref() { - handle @ Some(RawWindowHandle::Win32(window)) => unsafe { - let _ = config.apply_on_native_window(handle.unwrap()); + config: &Config, + context_attributes: &ContextAttributes, + ) -> Result> { + let hdc = match context_attributes + ._window + .as_ref() + .map(|w| w.window_handle()?.raw_window_handle()) + .transpose()? + { + Some(RawWindowHandle::Win32(window)) => unsafe { + let _ = config.apply_on_native_window(context_attributes._window.as_ref().unwrap()); gdi::GetDC(window.hwnd as _) }, _ => config.inner.hdc, }; - let share_ctx = match context_attributes.shared_context { + let share_ctx = match context_attributes.inner.shared_context { Some(RawContext::Wgl(share)) => share, _ => std::ptr::null(), }; @@ -64,16 +69,16 @@ impl Display { }; let config = config.clone(); - let is_gles = matches!(context_attributes.api, Some(ContextApi::Gles(_))); + let is_gles = matches!(context_attributes.inner.api, Some(ContextApi::Gles(_))); let inner = ContextInner { display: self.clone(), config, raw: context, is_gles }; Ok(NotCurrentContext { inner }) } - fn create_context_arb( + fn create_context_arb( &self, hdc: HDC, share_context: HGLRC, - context_attributes: &ContextAttributes, + context_attributes: &ContextAttributes, ) -> Result { let extra = self.inner.wgl_extra.as_ref().unwrap(); let mut attrs = Vec::::with_capacity(16); @@ -81,10 +86,11 @@ impl Display { // 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) = match context_attributes.inner.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); + let (profile, version) = + context::pick_profile(context_attributes.inner.profile, version); let profile = match profile { GlProfile::Core => wgl_extra::CONTEXT_CORE_PROFILE_BIT_ARB, GlProfile::Compatibility => wgl_extra::CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, @@ -118,7 +124,7 @@ impl Display { attrs.push(version.minor as c_int); } - if let Some(profile) = context_attributes.profile { + if let Some(profile) = context_attributes.inner.profile { let profile = match profile { GlProfile::Core => wgl_extra::CONTEXT_CORE_PROFILE_BIT_ARB, GlProfile::Compatibility => wgl_extra::CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, @@ -130,7 +136,7 @@ impl Display { let mut flags: c_int = 0; if self.inner.features.contains(DisplayFeatures::CONTEXT_ROBUSTNESS) { - match context_attributes.robustness { + match context_attributes.inner.robustness { Robustness::NotRobust => (), Robustness::RobustNoResetNotification => { attrs.push(wgl_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as c_int); @@ -153,7 +159,7 @@ impl Display { attrs.push(wgl_extra::CONTEXT_OPENGL_NO_ERROR_ARB as c_int); }, } - } else if context_attributes.robustness != Robustness::NotRobust { + } else if context_attributes.inner.robustness != Robustness::NotRobust { return Err(ErrorKind::NotSupported( "WGL_ARB_create_context_robustness is not supported", ) @@ -161,7 +167,7 @@ impl Display { } // Debug flag. - if context_attributes.debug { + if context_attributes.inner.debug { flags |= wgl_extra::CONTEXT_DEBUG_BIT_ARB as c_int; } @@ -172,7 +178,7 @@ impl Display { // Flush control. if self.inner.features.contains(DisplayFeatures::CONTEXT_RELEASE_BEHAVIOR) { - match context_attributes.release_behavior { + match context_attributes.inner.release_behavior { // This is the default behavior in specification. // // XXX even though we check for extensions don't pass it because it could cause @@ -183,7 +189,7 @@ impl Display { attrs.push(wgl_extra::CONTEXT_RELEASE_BEHAVIOR_NONE_ARB as c_int); }, } - } else if context_attributes.release_behavior != ReleaseBehavior::Flush { + } else if context_attributes.inner.release_behavior != ReleaseBehavior::Flush { return Err(ErrorKind::NotSupported( "flush control behavior WGL_ARB_context_flush_control", ) @@ -207,23 +213,23 @@ impl Display { /// A wrapper around the WGL context that is known to be not current to the /// calling thread. #[derive(Debug)] -pub struct NotCurrentContext { - inner: ContextInner, +pub struct NotCurrentContext { + inner: ContextInner, } -impl Sealed for NotCurrentContext {} +impl Sealed for NotCurrentContext {} -impl NotCurrentContext { - fn new(inner: ContextInner) -> Self { +impl NotCurrentContext { + fn new(inner: ContextInner) -> Self { Self { inner } } } -impl NotCurrentGlContext for NotCurrentContext { - type PossiblyCurrentContext = PossiblyCurrentContext; - type Surface = Surface; +impl NotCurrentGlContext for NotCurrentContext { + type PossiblyCurrentContext = PossiblyCurrentContext; + type Surface = Surface; - fn treat_as_possibly_current(self) -> PossiblyCurrentContext { + fn treat_as_possibly_current(self) -> PossiblyCurrentContext { PossiblyCurrentContext { inner: self.inner, _nosendsync: PhantomData } } @@ -244,29 +250,29 @@ impl NotCurrentGlContext for NotCurrentContext { } } -impl GlContext for NotCurrentContext { +impl GlContext for NotCurrentContext { fn context_api(&self) -> ContextApi { self.inner.context_api() } } -impl GetGlDisplay for NotCurrentContext { - type Target = Display; +impl GetGlDisplay for NotCurrentContext { + type Target = Display; fn display(&self) -> Self::Target { self.inner.display.clone() } } -impl GetGlConfig for NotCurrentContext { - type Target = Config; +impl GetGlConfig for NotCurrentContext { + type Target = Config; fn config(&self) -> Self::Target { self.inner.config.clone() } } -impl AsRawContext for NotCurrentContext { +impl AsRawContext for NotCurrentContext { fn raw_context(&self) -> RawContext { RawContext::Wgl(*self.inner.raw) } @@ -274,15 +280,15 @@ impl AsRawContext for NotCurrentContext { /// A wrapper around WGL context that could be current to the calling thread. #[derive(Debug)] -pub struct PossiblyCurrentContext { - inner: ContextInner, +pub struct PossiblyCurrentContext { + inner: ContextInner, // The context could be current only on the one thread. _nosendsync: PhantomData, } -impl PossiblyCurrentGlContext for PossiblyCurrentContext { - type NotCurrentContext = NotCurrentContext; - type Surface = Surface; +impl PossiblyCurrentGlContext for PossiblyCurrentContext { + type NotCurrentContext = NotCurrentContext; + type Surface = Surface; fn make_not_current(self) -> Result { unsafe { @@ -314,44 +320,44 @@ impl PossiblyCurrentGlContext for PossiblyCurrentContext { } } -impl Sealed for PossiblyCurrentContext {} +impl Sealed for PossiblyCurrentContext {} -impl GetGlDisplay for PossiblyCurrentContext { - type Target = Display; +impl GetGlDisplay for PossiblyCurrentContext { + type Target = Display; fn display(&self) -> Self::Target { self.inner.display.clone() } } -impl GetGlConfig for PossiblyCurrentContext { - type Target = Config; +impl GetGlConfig for PossiblyCurrentContext { + type Target = Config; fn config(&self) -> Self::Target { self.inner.config.clone() } } -impl GlContext for PossiblyCurrentContext { +impl GlContext for PossiblyCurrentContext { fn context_api(&self) -> ContextApi { self.inner.context_api() } } -impl AsRawContext for PossiblyCurrentContext { +impl AsRawContext for PossiblyCurrentContext { fn raw_context(&self) -> RawContext { RawContext::Wgl(*self.inner.raw) } } -struct ContextInner { - display: Display, - config: Config, +struct ContextInner { + display: Display, + config: Config, raw: WglContext, is_gles: bool, } -impl fmt::Debug for ContextInner { +impl fmt::Debug for ContextInner { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Context") .field("config", &self.config.inner.pixel_format_index) @@ -373,16 +379,16 @@ impl Deref for WglContext { unsafe impl Send for WglContext {} -impl ContextInner { +impl ContextInner { fn make_current_draw_read( &self, - _surface_draw: &Surface, - _surface_read: &Surface, + _surface_draw: &Surface, + _surface_read: &Surface, ) -> ErrorKind { ErrorKind::NotSupported("make_current_draw_read is not supported by WGL") } - fn make_current(&self, surface: &Surface) -> Result<()> { + fn make_current(&self, surface: &Surface) -> Result<()> { unsafe { if wgl::MakeCurrent(surface.hdc as _, self.raw.cast()) == 0 { Err(IoError::last_os_error().into()) @@ -401,7 +407,7 @@ impl ContextInner { } } -impl Drop for ContextInner { +impl Drop for ContextInner { fn drop(&mut self) { unsafe { wgl::DeleteContext(*self.raw); diff --git a/glutin/src/api/wgl/display.rs b/glutin/src/api/wgl/display.rs index fb19098bb9..e392ccbb53 100644 --- a/glutin/src/api/wgl/display.rs +++ b/glutin/src/api/wgl/display.rs @@ -7,13 +7,18 @@ use std::os::windows::ffi::OsStrExt; use std::sync::Arc; use glutin_wgl_sys::wgl; -use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; +use raw_window_handle::{ + HasDisplayHandle, HasRawDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawDisplayHandle, + RawWindowHandle, +}; use windows_sys::Win32::Foundation::HINSTANCE; use windows_sys::Win32::Graphics::Gdi::HDC; use windows_sys::Win32::System::LibraryLoader as dll_loader; use crate::config::ConfigTemplate; -use crate::display::{AsRawDisplay, DisplayFeatures, GetDisplayExtensions, RawDisplay}; +use crate::display::{ + AsRawDisplay, DisplayFeatures, DisplayResult, GetDisplayExtensions, RawDisplay, +}; use crate::error::{ErrorKind, Result}; use crate::prelude::*; use crate::private::Sealed; @@ -25,52 +30,86 @@ use super::surface::Surface; use super::WglExtra; /// A WGL display. -#[derive(Debug, Clone)] -pub struct Display { - pub(crate) inner: Arc, +#[derive(Debug)] +pub struct Display { + pub(crate) inner: Arc>, } -impl Display { +impl Clone for Display { + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } +} + +impl Display { /// Create WGL display. /// /// The `native_window` is used to perform extension loading. If it's not /// passed the OpenGL will be limited to what it can do, though, basic /// operations could still be performed. - /// - /// # Safety - /// - /// The `native_window` must point to the valid platform window and have - /// valid `hinstance`. - pub unsafe fn new( - display: RawDisplayHandle, - native_window: Option, - ) -> Result { - if !matches!(display, RawDisplayHandle::Windows(..)) { - return Err(ErrorKind::NotSupported("provided native display is not supported").into()); + pub fn new(display: D, native_window: Option) -> Result { + Self::new_with_display(display, native_window).map_err(Into::into) + } + + pub(crate) fn new_with_display( + display: D, + native_window: Option, + ) -> DisplayResult { + macro_rules! leap { + ($res:expr) => {{ + match ($res) { + Ok(x) => x, + Err(e) => { + let error = crate::error::Error::from(e); + return Err((error, display).into()); + }, + } + }}; } + match leap!(display.display_handle().and_then(|r| r.raw_display_handle())) { + RawDisplayHandle::Windows(..) => {}, + _ => { + return Err(( + ErrorKind::NotSupported("provided native display is not supported"), + display, + ) + .into()) + }, + }; + let name = OsStr::new("opengl32.dll").encode_wide().chain(Some(0).into_iter()).collect::>(); let lib_opengl32 = unsafe { dll_loader::LoadLibraryW(name.as_ptr()) }; if lib_opengl32 == 0 { - return Err(ErrorKind::NotFound.into()); + return Err((ErrorKind::NotFound, display).into()); } // In case native window was provided init extra functions. - let (wgl_extra, client_extensions) = - if let Some(RawWindowHandle::Win32(window)) = native_window { - unsafe { - let (wgl_extra, client_extensions) = - super::load_extra_functions(window.hinstance as _, window.hwnd as _)?; - (Some(wgl_extra), client_extensions) - } - } else { - (None, HashSet::new()) - }; + let (wgl_extra, client_extensions) = match leap!(native_window + .map(|w| w.window_handle()?.raw_window_handle()) + .transpose()) + { + Some(RawWindowHandle::Win32(window)) => unsafe { + let (wgl_extra, client_extensions) = + match super::load_extra_functions(window.hinstance as _, window.hwnd as _) { + Ok(x) => x, + Err(e) => return Err((e, display).into()), + }; + (Some(wgl_extra), client_extensions) + }, + _ => (None, HashSet::new()), + }; let features = Self::extract_display_features(&client_extensions); - let inner = Arc::new(DisplayInner { lib_opengl32, wgl_extra, features, client_extensions }); + let inner = Arc::new(DisplayInner { + lib_opengl32, + wgl_extra, + features, + client_extensions, + _display: display, + }); Ok(Display { inner }) } @@ -122,48 +161,48 @@ impl Display { } } -impl GlDisplay for Display { - type Config = Config; - type NotCurrentContext = NotCurrentContext; - type PbufferSurface = Surface; - type PixmapSurface = Surface; - type WindowSurface = Surface; +impl GlDisplay for Display { + type Config = Config; + type NotCurrentContext = NotCurrentContext; + type PbufferSurface = Surface; + type PixmapSurface = Surface; + type WindowSurface = Surface>; - unsafe fn find_configs( + fn find_configs( &self, - template: ConfigTemplate, + template: ConfigTemplate, ) -> Result + '_>> { - unsafe { Self::find_configs(self, template) } + Self::find_configs(self, template) } - unsafe fn create_window_surface( + fn create_window_surface( &self, config: &Self::Config, - surface_attributes: &SurfaceAttributes, - ) -> Result { - unsafe { Self::create_window_surface(self, config, surface_attributes) } + surface_attributes: SurfaceAttributes>, + ) -> Result> { + Self::create_window_surface(self, config, surface_attributes) } unsafe fn create_pbuffer_surface( &self, config: &Self::Config, - surface_attributes: &SurfaceAttributes, + surface_attributes: SurfaceAttributes, ) -> Result { unsafe { Self::create_pbuffer_surface(self, config, surface_attributes) } } - unsafe fn create_context( + fn create_context( &self, config: &Self::Config, - context_attributes: &crate::context::ContextAttributes, + context_attributes: &crate::context::ContextAttributes, ) -> Result { - unsafe { Self::create_context(self, config, context_attributes) } + Self::create_context(self, config, context_attributes) } unsafe fn create_pixmap_surface( &self, config: &Self::Config, - surface_attributes: &SurfaceAttributes, + surface_attributes: SurfaceAttributes, ) -> Result { unsafe { Self::create_pixmap_surface(self, config, surface_attributes) } } @@ -190,21 +229,21 @@ impl GlDisplay for Display { } } -impl GetDisplayExtensions for Display { +impl GetDisplayExtensions for Display { fn extensions(&self) -> &HashSet<&'static str> { &self.inner.client_extensions } } -impl AsRawDisplay for Display { +impl AsRawDisplay for Display { fn raw_display(&self) -> RawDisplay { RawDisplay::Wgl } } -impl Sealed for Display {} +impl Sealed for Display {} -pub(crate) struct DisplayInner { +pub(crate) struct DisplayInner { /// Client WGL extensions. pub(crate) lib_opengl32: HINSTANCE, @@ -214,9 +253,12 @@ pub(crate) struct DisplayInner { pub(crate) features: DisplayFeatures, pub(crate) client_extensions: HashSet<&'static str>, + + /// Hold onto the display reference to keep it valid. + pub(crate) _display: D, } -impl fmt::Debug for DisplayInner { +impl fmt::Debug for DisplayInner { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Display") .field("features", &self.features) diff --git a/glutin/src/api/wgl/surface.rs b/glutin/src/api/wgl/surface.rs index fb3c204666..776d0c3536 100644 --- a/glutin/src/api/wgl/surface.rs +++ b/glutin/src/api/wgl/surface.rs @@ -1,11 +1,10 @@ //! A wrapper around `HWND` used for GL operations. use std::io::Error as IoError; -use std::marker::PhantomData; use std::num::NonZeroU32; use std::{fmt, mem}; -use raw_window_handle::RawWindowHandle; +use raw_window_handle::{HasDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawWindowHandle}; use windows_sys::Win32::Foundation::{HWND, RECT}; use windows_sys::Win32::Graphics::Gdi::HDC; use windows_sys::Win32::Graphics::{Gdi as gdi, OpenGL as gl}; @@ -25,35 +24,35 @@ use super::config::Config; use super::context::PossiblyCurrentContext; use super::display::Display; -impl Display { +impl Display { pub(crate) unsafe fn create_pixmap_surface( &self, - _config: &Config, - _surface_attributes: &SurfaceAttributes, - ) -> Result> { + _config: &Config, + _surface_attributes: SurfaceAttributes, + ) -> Result> { Err(ErrorKind::NotSupported("pixmaps are not implemented with WGL").into()) } pub(crate) unsafe fn create_pbuffer_surface( &self, - _config: &Config, - _surface_attributes: &SurfaceAttributes, - ) -> Result> { + _config: &Config, + _surface_attributes: SurfaceAttributes, + ) -> Result> { Err(ErrorKind::NotSupported("pbuffers are not implemented with WGL").into()) } - pub(crate) unsafe fn create_window_surface( + pub(crate) fn create_window_surface( &self, - config: &Config, - surface_attributes: &SurfaceAttributes, - ) -> Result> { - let hwnd = match surface_attributes.raw_window_handle.as_ref().unwrap() { - handle @ RawWindowHandle::Win32(window_handle) => { + config: &Config, + surface_attributes: SurfaceAttributes>, + ) -> Result>> { + let hwnd = match surface_attributes.ty.0.window_handle()?.raw_window_handle()? { + RawWindowHandle::Win32(window_handle) => { if window_handle.hwnd.is_null() { return Err(ErrorKind::BadNativeWindow.into()); } - let _ = unsafe { config.apply_on_native_window(handle) }; + let _ = config.apply_on_native_window(&surface_attributes.ty.0); window_handle.hwnd as HWND }, _ => { @@ -65,23 +64,28 @@ impl Display { let hdc = unsafe { gdi::GetDC(hwnd) }; - let surface = - Surface { display: self.clone(), config: config.clone(), hwnd, hdc, _ty: PhantomData }; + let surface = Surface { + display: self.clone(), + config: config.clone(), + hwnd, + hdc, + _ty: surface_attributes.ty, + }; Ok(surface) } } /// A Wrapper around `HWND`. -pub struct Surface { - display: Display, - config: Config, +pub struct Surface { + display: Display, + config: Config, pub(crate) hwnd: HWND, pub(crate) hdc: HDC, - _ty: PhantomData, + _ty: T, } -impl Drop for Surface { +impl Drop for Surface { fn drop(&mut self) { unsafe { gdi::ReleaseDC(self.hwnd, self.hdc); @@ -89,8 +93,8 @@ impl Drop for Surface { } } -impl GlSurface for Surface { - type Context = PossiblyCurrentContext; +impl GlSurface for Surface { + type Context = PossiblyCurrentContext; type SurfaceType = T; fn buffer_age(&self) -> u32 { @@ -170,7 +174,7 @@ impl GlSurface for Surface { } } -impl fmt::Debug for Surface { +impl fmt::Debug for Surface { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Surface") .field("config", &self.config.inner.pixel_format_index) @@ -180,26 +184,26 @@ impl fmt::Debug for Surface { } } -impl AsRawSurface for Surface { +impl AsRawSurface for Surface { fn raw_surface(&self) -> RawSurface { RawSurface::Wgl(self.hwnd as _) } } -impl GetGlConfig for Surface { - type Target = Config; +impl GetGlConfig for Surface { + type Target = Config; fn config(&self) -> Self::Target { self.config.clone() } } -impl GetGlDisplay for Surface { - type Target = Display; +impl GetGlDisplay for Surface { + type Target = Display; fn display(&self) -> Self::Target { self.display.clone() } } -impl Sealed for Surface {} +impl Sealed for Surface {} diff --git a/glutin/src/display.rs b/glutin/src/display.rs index a4a2aefdd7..efc41d1974 100644 --- a/glutin/src/display.rs +++ b/glutin/src/display.rs @@ -203,39 +203,39 @@ impl Display { Ok(Self::Glx(GlxDisplay::new(display, registrar)?)) }, #[cfg(all(egl_backend, glx_backend))] - DisplayApiPreference::GlxThenEgl(registrar) => unsafe { - if let Ok(display) = GlxDisplay::new(display, registrar) { - Ok(Self::Glx(display)) - } else { - Ok(Self::Egl(EglDisplay::new(display)?)) + DisplayApiPreference::GlxThenEgl(registrar) => { + match GlxDisplay::new_with_display(display, registrar) { + Ok(display) => Ok(Self::Glx(display)), + Err(err) => Ok(Self::Egl(EglDisplay::new_with_display(err.display)?)), } }, #[cfg(all(egl_backend, glx_backend))] - DisplayApiPreference::EglThenGlx(registrar) => unsafe { - if let Ok(display) = EglDisplay::new(display) { - Ok(Self::Egl(display)) - } else { - Ok(Self::Glx(GlxDisplay::new(display, registrar)?)) + DisplayApiPreference::EglThenGlx(registrar) => { + match EglDisplay::new_with_display(display) { + Ok(display) => Ok(Self::Egl(display)), + Err(err) => { + Ok(Self::Glx(GlxDisplay::new_with_display(err.display, registrar)?)) + }, } }, #[cfg(wgl_backend)] - DisplayApiPreference::Wgl(window_handle) => unsafe { + DisplayApiPreference::Wgl(window_handle) => { Ok(Self::Wgl(WglDisplay::new(display, window_handle)?)) }, #[cfg(all(egl_backend, wgl_backend))] - DisplayApiPreference::EglThenWgl(window_handle) => unsafe { - if let Ok(display) = EglDisplay::new(display) { - Ok(Self::Egl(display)) - } else { - Ok(Self::Wgl(WglDisplay::new(display, window_handle)?)) + DisplayApiPreference::EglThenWgl(window_handle) => { + match EglDisplay::new_with_display(display) { + Ok(display) => Ok(Self::Egl(display)), + Err(err) => { + Ok(Self::Wgl(WglDisplay::new_with_display(err.display, window_handle)?)) + }, } }, #[cfg(all(egl_backend, wgl_backend))] - DisplayApiPreference::WglThenEgl(window_handle) => unsafe { - if let Ok(display) = WglDisplay::new(display, window_handle) { - Ok(Self::Wgl(display)) - } else { - Ok(Self::Egl(EglDisplay::new(display)?)) + DisplayApiPreference::WglThenEgl(window_handle) => { + match WglDisplay::new_with_display(display, window_handle) { + Ok(display) => Ok(Self::Wgl(display)), + Err(err) => Ok(Self::Egl(EglDisplay::new_with_display(err.display)?)), } }, #[cfg(cgl_backend)] @@ -262,9 +262,7 @@ impl GlDisplay for Display { #[cfg(glx_backend)] Self::Glx(display) => Ok(Box::new(display.find_configs(template)?.map(Config::Glx))), #[cfg(wgl_backend)] - Self::Wgl(display) => unsafe { - Ok(Box::new(display.find_configs(template)?.map(Config::Wgl))) - }, + Self::Wgl(display) => Ok(Box::new(display.find_configs(template)?.map(Config::Wgl))), #[cfg(cgl_backend)] Self::Cgl(display) => Ok(Box::new(display.find_configs(template)?.map(Config::Cgl))), } @@ -285,7 +283,7 @@ impl GlDisplay for Display { Ok(NotCurrentContext::Glx(display.create_context(config, context_attributes)?)) }, #[cfg(wgl_backend)] - (Self::Wgl(display), Config::Wgl(config)) => unsafe { + (Self::Wgl(display), Config::Wgl(config)) => { Ok(NotCurrentContext::Wgl(display.create_context(config, context_attributes)?)) }, #[cfg(cgl_backend)] @@ -311,7 +309,7 @@ impl GlDisplay for Display { Ok(Surface::Glx(display.create_window_surface(config, surface_attributes)?)) }, #[cfg(wgl_backend)] - (Self::Wgl(display), Config::Wgl(config)) => unsafe { + (Self::Wgl(display), Config::Wgl(config)) => { Ok(Surface::Wgl(display.create_window_surface(config, surface_attributes)?)) }, #[cfg(cgl_backend)] @@ -577,3 +575,40 @@ pub enum RawDisplay { #[cfg(cgl_backend)] Cgl, } + +#[cfg_attr(cgl_backend, allow(dead_code))] +pub(crate) struct DisplayError { + /// The error that occurred. + pub(crate) error: crate::error::Error, + + /// The display that caused the error. + pub(crate) display: D, +} + +impl DisplayError> { + #[allow(unused)] + pub(crate) fn unwrap(self) -> DisplayError { + DisplayError { error: self.error, display: self.display.unwrap() } + } +} + +impl From> for crate::error::Error { + fn from(value: DisplayError) -> Self { + value.error + } +} + +impl From<(crate::error::Error, D)> for DisplayError { + fn from(value: (crate::error::Error, D)) -> Self { + Self { error: value.0, display: value.1 } + } +} + +impl From<(crate::error::ErrorKind, D)> for DisplayError { + fn from(value: (crate::error::ErrorKind, D)) -> Self { + Self { error: value.0.into(), display: value.1 } + } +} + +#[cfg_attr(cgl_backend, allow(dead_code))] +pub(crate) type DisplayResult = std::result::Result>; diff --git a/glutin/src/surface.rs b/glutin/src/surface.rs index df7ee1bc04..80630a0c5d 100644 --- a/glutin/src/surface.rs +++ b/glutin/src/surface.rs @@ -215,7 +215,7 @@ impl SurfaceAttributesBuilder { /// Attributes which are used for creating a particular surface. #[derive(Default, Debug, Clone)] pub struct SurfaceAttributes { - #[cfg_attr(cgl_backend, allow(dead_code))] + #[cfg_attr(any(cgl_backend, all(wgl_backend, not(egl_backend))), allow(dead_code))] pub(crate) inner: AttributesInner, pub(crate) ty: T, }