From 6f987ddf9a23862b05a7517e88500127636fff48 Mon Sep 17 00:00:00 2001 From: Josh Wood Date: Thu, 19 Sep 2024 00:34:00 +0200 Subject: [PATCH 1/9] wip(wgl): add support for pixel buffer surfaces --- CHANGELOG.md | 1 + glutin/src/api/wgl/config.rs | 5 ++ glutin/src/api/wgl/context.rs | 9 ++- glutin/src/api/wgl/surface.rs | 139 ++++++++++++++++++++++++++++------ glutin_wgl_sys/build.rs | 3 +- 5 files changed, 130 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f5b5a45e6..4ace3a0c1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Added `Device::drm_device_node_path()` and `Device::drm_render_device_node_path()` getters to EGL via `EGL_EXT_device_drm`. - Added support for `DrmDisplayHandle` in EGL's `Display::with_device()` using `EGL_DRM_MASTER_FD_EXT` from `EGL_EXT_device_drm`. - Properly set up OpenGL-specific stuff on the `NSView`, instead of relying on Winit to do it. +- Added support for `Display::create_pbuffer_surface()` in WGL via `WGL_ARB_pbuffer`. # Version 0.32.0 diff --git a/glutin/src/api/wgl/config.rs b/glutin/src/api/wgl/config.rs index 9c8448c89c..2be7a7773f 100644 --- a/glutin/src/api/wgl/config.rs +++ b/glutin/src/api/wgl/config.rs @@ -237,6 +237,11 @@ impl Display { attrs.push(1); } + if template.config_surface_types.contains(ConfigSurfaceTypes::PBUFFER) { + attrs.push(wgl_extra::DRAW_TO_PBUFFER_ARB as c_int); + attrs.push(1); + } + if template.transparency { attrs.push(wgl_extra::TRANSPARENT_ARB as c_int); attrs.push(1); diff --git a/glutin/src/api/wgl/context.rs b/glutin/src/api/wgl/context.rs index fe5278456e..22458bc5ce 100644 --- a/glutin/src/api/wgl/context.rs +++ b/glutin/src/api/wgl/context.rs @@ -22,7 +22,7 @@ use crate::prelude::*; use crate::private::Sealed; use crate::surface::SurfaceTypeTrait; -use super::config::Config; +use super::{config::Config, surface::WGLSurface}; use super::display::Display; use super::surface::Surface; @@ -387,7 +387,12 @@ impl ContextInner { fn make_current(&self, surface: &Surface) -> Result<()> { unsafe { - if wgl::MakeCurrent(surface.hdc as _, self.raw.cast()) == 0 { + let hdc = match surface.raw { + WGLSurface::Window(_, hdc) => hdc as _, + WGLSurface::PBuffer(_, hdc) => hdc as _, + }; + + if wgl::MakeCurrent(hdc, self.raw.cast()) == 0 { Err(IoError::last_os_error().into()) } else { Ok(()) diff --git a/glutin/src/api/wgl/surface.rs b/glutin/src/api/wgl/surface.rs index 15f45089e4..4770f507a2 100644 --- a/glutin/src/api/wgl/surface.rs +++ b/glutin/src/api/wgl/surface.rs @@ -1,13 +1,14 @@ //! A wrapper around `HWND` used for GL operations. +use std::{fmt, mem}; use std::io::Error as IoError; use std::marker::PhantomData; use std::num::NonZeroU32; -use std::{fmt, mem}; +use std::os::raw::c_int; +use glutin_wgl_sys::{wgl::types::GLenum, wgl_extra::{self, types::HPBUFFEREXT}}; use raw_window_handle::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}; use windows_sys::Win32::UI::WindowsAndMessaging::GetClientRect; @@ -36,10 +37,37 @@ impl Display { pub(crate) unsafe fn create_pbuffer_surface( &self, - _config: &Config, - _surface_attributes: &SurfaceAttributes, + config: &Config, + surface_attributes: &SurfaceAttributes, ) -> Result> { - Err(ErrorKind::NotSupported("pbuffers are not implemented with WGL").into()) + let hdc = config.inner.hdc; + let width = surface_attributes.width.unwrap().get() as c_int; + let height = surface_attributes.height.unwrap().get() as c_int; + + let mut attrs = Vec::::with_capacity(2); + if surface_attributes.largest_pbuffer { + attrs.push(wgl_extra::PBUFFER_LARGEST_ARB as c_int); + attrs.push(1 as c_int); + } + attrs.push(0); + + let (hbuf, hdc) = match self.inner.wgl_extra { + Some(extra) if extra.CreatePbufferARB.is_loaded() => unsafe { + let hbuf = extra.CreatePbufferARB(hdc as _, config.inner.pixel_format_index, width, height, attrs.as_ptr()); + let hdc = extra.GetPbufferDCARB(hbuf); + (hbuf, hdc) + }, + _ => { + return Err( + ErrorKind::NotSupported("pbuffer extensions are not supported").into() + ) + }, + }; + + let surface = + Surface { display: self.clone(), config: config.clone(), raw: WGLSurface::PBuffer(hbuf, hdc), _ty: PhantomData }; + + Ok(surface) } pub(crate) unsafe fn create_window_surface( @@ -62,28 +90,66 @@ impl Display { let hdc = unsafe { gdi::GetDC(hwnd) }; let surface = - Surface { display: self.clone(), config: config.clone(), hwnd, hdc, _ty: PhantomData }; + Surface { display: self.clone(), config: config.clone(), raw: WGLSurface::Window(hwnd, hdc), _ty: PhantomData }; Ok(surface) } } -/// A Wrapper around `HWND`. +/// A wrapper around WGL surfaces. +#[derive(Debug)] +pub enum WGLSurface { + /// Surface backed by a window surface. + Window(HWND, gdi::HDC), + /// Surface backed by a pixel buffer. + PBuffer(HPBUFFEREXT, wgl_extra::types::HDC), +} + +/// A Wrapper around `WGLSurface`. pub struct Surface { display: Display, config: Config, - pub(crate) hwnd: HWND, - pub(crate) hdc: HDC, + pub(crate) raw: WGLSurface, _ty: PhantomData, } // Impl only `Send` for Surface. unsafe impl Send for Surface {} +impl Surface { + /// # Safety + /// + /// The caller must ensure that the attribute could be present. + unsafe fn raw_attribute(&self, attr: GLenum) -> c_int { + let mut value = 0; + unsafe { + match self.raw { + WGLSurface::Window(_, _) => unreachable!(), + WGLSurface::PBuffer(hbuf, _) => { + if let Some(extra) = self.display.inner.wgl_extra { + extra.QueryPbufferARB(hbuf, attr as _, &mut value); + } + }, + } + } + value + } +} + impl Drop for Surface { fn drop(&mut self) { unsafe { - gdi::ReleaseDC(self.hwnd, self.hdc); + match self.raw { + WGLSurface::Window(hwnd, hdc) => { + gdi::ReleaseDC(hwnd, hdc); + } + WGLSurface::PBuffer(hbuf, hdc) => { + if let Some(extra) = self.display.inner.wgl_extra { + extra.ReleasePbufferDCARB(hbuf, hdc); + extra.DestroyPbufferARB(hbuf); + } + }, + } } } } @@ -97,20 +163,34 @@ impl GlSurface for Surface { } fn width(&self) -> Option { - let mut rect: RECT = unsafe { mem::zeroed() }; - if unsafe { GetClientRect(self.hwnd, &mut rect) } == false.into() { - None - } else { - Some((rect.right - rect.left) as u32) + match self.raw { + WGLSurface::Window(hwnd, _) => { + let mut rect: RECT = unsafe { mem::zeroed() }; + if unsafe { GetClientRect(hwnd, &mut rect) } == false.into() { + None + } else { + Some((rect.right - rect.left) as u32) + } + }, + WGLSurface::PBuffer(_, _) => { + unsafe { Some(self.raw_attribute(wgl_extra::PBUFFER_WIDTH_ARB) as _) } + }, } } fn height(&self) -> Option { - let mut rect: RECT = unsafe { mem::zeroed() }; - if unsafe { GetClientRect(self.hwnd, &mut rect) } == false.into() { - None - } else { - Some((rect.bottom - rect.top) as u32) + match self.raw { + WGLSurface::Window(hwnd, _) => { + let mut rect: RECT = unsafe { mem::zeroed() }; + if unsafe { GetClientRect(hwnd, &mut rect) } == false.into() { + None + } else { + Some((rect.bottom - rect.top) as u32) + } + }, + WGLSurface::PBuffer(_, _) => { + unsafe { Some(self.raw_attribute(wgl_extra::PBUFFER_HEIGHT_ARB) as _) } + }, } } @@ -120,7 +200,12 @@ impl GlSurface for Surface { fn swap_buffers(&self, _context: &Self::Context) -> Result<()> { unsafe { - if gl::SwapBuffers(self.hdc) == 0 { + let hdc = match self.raw { + WGLSurface::Window(_, hdc) => hdc as _, + WGLSurface::PBuffer(_, hdc) => hdc as _ + }; + + if gl::SwapBuffers(hdc) == 0 { Err(IoError::last_os_error().into()) } else { Ok(()) @@ -129,6 +214,10 @@ impl GlSurface for Surface { } fn set_swap_interval(&self, _context: &Self::Context, interval: SwapInterval) -> Result<()> { + let WGLSurface::Window(_, _) = self.raw else { + return Ok(()); + }; + let interval = match interval { SwapInterval::DontWait => 0, SwapInterval::Wait(n) => n.get(), @@ -173,15 +262,17 @@ 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) - .field("hwnd", &self.hwnd) - .field("hdc", &self.hdc) + .field("raw", &self.raw) .finish() } } impl AsRawSurface for Surface { fn raw_surface(&self) -> RawSurface { - RawSurface::Wgl(self.hwnd as _) + match self.raw { + WGLSurface::Window(hwnd, _) => RawSurface::Wgl(hwnd as _), + WGLSurface::PBuffer(_, _) => RawSurface::Wgl(0 as _), + } } } diff --git a/glutin_wgl_sys/build.rs b/glutin_wgl_sys/build.rs index ab15682fd0..78846fa959 100644 --- a/glutin_wgl_sys/build.rs +++ b/glutin_wgl_sys/build.rs @@ -18,12 +18,13 @@ fn main() { let mut file = File::create(dest.join("wgl_extra_bindings.rs")).unwrap(); Registry::new(Api::Wgl, (1, 0), Profile::Core, Fallbacks::All, [ "WGL_ARB_context_flush_control", - "WGL_ARB_create_context", "WGL_ARB_create_context_no_error", "WGL_ARB_create_context_profile", "WGL_ARB_create_context_robustness", + "WGL_ARB_create_context", "WGL_ARB_extensions_string", "WGL_ARB_framebuffer_sRGB", + "WGL_ARB_pbuffer", "WGL_ARB_multisample", "WGL_ARB_pixel_format", "WGL_ARB_pixel_format_float", From 09a7611aef1adeb6230cdb1f64da081f8e94ae01 Mon Sep 17 00:00:00 2001 From: Josh Wood Date: Thu, 19 Sep 2024 20:31:01 +0200 Subject: [PATCH 2/9] chore: cargo fmt --- glutin/src/api/wgl/context.rs | 6 ++-- glutin/src/api/wgl/surface.rs | 54 +++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/glutin/src/api/wgl/context.rs b/glutin/src/api/wgl/context.rs index 22458bc5ce..1dc492ac47 100644 --- a/glutin/src/api/wgl/context.rs +++ b/glutin/src/api/wgl/context.rs @@ -22,9 +22,9 @@ use crate::prelude::*; use crate::private::Sealed; use crate::surface::SurfaceTypeTrait; -use super::{config::Config, surface::WGLSurface}; +use super::config::Config; use super::display::Display; -use super::surface::Surface; +use super::surface::{Surface, WGLSurface}; impl Display { pub(crate) unsafe fn create_context( @@ -388,7 +388,7 @@ impl ContextInner { fn make_current(&self, surface: &Surface) -> Result<()> { unsafe { let hdc = match surface.raw { - WGLSurface::Window(_, hdc) => hdc as _, + WGLSurface::Window(_, hdc) => hdc as _, WGLSurface::PBuffer(_, hdc) => hdc as _, }; diff --git a/glutin/src/api/wgl/surface.rs b/glutin/src/api/wgl/surface.rs index 4770f507a2..fe0c161958 100644 --- a/glutin/src/api/wgl/surface.rs +++ b/glutin/src/api/wgl/surface.rs @@ -1,12 +1,14 @@ //! A wrapper around `HWND` used for GL operations. -use std::{fmt, mem}; use std::io::Error as IoError; use std::marker::PhantomData; use std::num::NonZeroU32; use std::os::raw::c_int; +use std::{fmt, mem}; -use glutin_wgl_sys::{wgl::types::GLenum, wgl_extra::{self, types::HPBUFFEREXT}}; +use glutin_wgl_sys::wgl::types::GLenum; +use glutin_wgl_sys::wgl_extra::types::HPBUFFEREXT; +use glutin_wgl_sys::wgl_extra::{self}; use raw_window_handle::RawWindowHandle; use windows_sys::Win32::Foundation::{HWND, RECT}; use windows_sys::Win32::Graphics::{Gdi as gdi, OpenGL as gl}; @@ -53,19 +55,25 @@ impl Display { let (hbuf, hdc) = match self.inner.wgl_extra { Some(extra) if extra.CreatePbufferARB.is_loaded() => unsafe { - let hbuf = extra.CreatePbufferARB(hdc as _, config.inner.pixel_format_index, width, height, attrs.as_ptr()); + let hbuf = extra.CreatePbufferARB( + hdc as _, + config.inner.pixel_format_index, + width, + height, + attrs.as_ptr(), + ); let hdc = extra.GetPbufferDCARB(hbuf); (hbuf, hdc) }, - _ => { - return Err( - ErrorKind::NotSupported("pbuffer extensions are not supported").into() - ) - }, + _ => return Err(ErrorKind::NotSupported("pbuffer extensions are not supported").into()), }; - let surface = - Surface { display: self.clone(), config: config.clone(), raw: WGLSurface::PBuffer(hbuf, hdc), _ty: PhantomData }; + let surface = Surface { + display: self.clone(), + config: config.clone(), + raw: WGLSurface::PBuffer(hbuf, hdc), + _ty: PhantomData, + }; Ok(surface) } @@ -89,8 +97,12 @@ impl Display { let hdc = unsafe { gdi::GetDC(hwnd) }; - let surface = - Surface { display: self.clone(), config: config.clone(), raw: WGLSurface::Window(hwnd, hdc), _ty: PhantomData }; + let surface = Surface { + display: self.clone(), + config: config.clone(), + raw: WGLSurface::Window(hwnd, hdc), + _ty: PhantomData, + }; Ok(surface) } @@ -124,7 +136,7 @@ impl Surface { let mut value = 0; unsafe { match self.raw { - WGLSurface::Window(_, _) => unreachable!(), + WGLSurface::Window(..) => unreachable!(), WGLSurface::PBuffer(hbuf, _) => { if let Some(extra) = self.display.inner.wgl_extra { extra.QueryPbufferARB(hbuf, attr as _, &mut value); @@ -142,7 +154,7 @@ impl Drop for Surface { match self.raw { WGLSurface::Window(hwnd, hdc) => { gdi::ReleaseDC(hwnd, hdc); - } + }, WGLSurface::PBuffer(hbuf, hdc) => { if let Some(extra) = self.display.inner.wgl_extra { extra.ReleasePbufferDCARB(hbuf, hdc); @@ -172,8 +184,8 @@ impl GlSurface for Surface { Some((rect.right - rect.left) as u32) } }, - WGLSurface::PBuffer(_, _) => { - unsafe { Some(self.raw_attribute(wgl_extra::PBUFFER_WIDTH_ARB) as _) } + WGLSurface::PBuffer(..) => unsafe { + Some(self.raw_attribute(wgl_extra::PBUFFER_WIDTH_ARB) as _) }, } } @@ -188,8 +200,8 @@ impl GlSurface for Surface { Some((rect.bottom - rect.top) as u32) } }, - WGLSurface::PBuffer(_, _) => { - unsafe { Some(self.raw_attribute(wgl_extra::PBUFFER_HEIGHT_ARB) as _) } + WGLSurface::PBuffer(..) => unsafe { + Some(self.raw_attribute(wgl_extra::PBUFFER_HEIGHT_ARB) as _) }, } } @@ -202,7 +214,7 @@ impl GlSurface for Surface { unsafe { let hdc = match self.raw { WGLSurface::Window(_, hdc) => hdc as _, - WGLSurface::PBuffer(_, hdc) => hdc as _ + WGLSurface::PBuffer(_, hdc) => hdc as _, }; if gl::SwapBuffers(hdc) == 0 { @@ -214,7 +226,7 @@ impl GlSurface for Surface { } fn set_swap_interval(&self, _context: &Self::Context, interval: SwapInterval) -> Result<()> { - let WGLSurface::Window(_, _) = self.raw else { + let WGLSurface::Window(..) = self.raw else { return Ok(()); }; @@ -271,7 +283,7 @@ impl AsRawSurface for Surface { fn raw_surface(&self) -> RawSurface { match self.raw { WGLSurface::Window(hwnd, _) => RawSurface::Wgl(hwnd as _), - WGLSurface::PBuffer(_, _) => RawSurface::Wgl(0 as _), + WGLSurface::PBuffer(..) => RawSurface::Wgl(0 as _), } } } From 44f2ec1f08ce9c1432969a0fbeb9aba4c818a564 Mon Sep 17 00:00:00 2001 From: Josh Wood Date: Sun, 22 Sep 2024 06:25:45 +0200 Subject: [PATCH 3/9] chore(wgl): address review feedback --- glutin/src/api/wgl/context.rs | 6 +- glutin/src/api/wgl/surface.rs | 188 ++++++++++++++++++---------------- 2 files changed, 101 insertions(+), 93 deletions(-) diff --git a/glutin/src/api/wgl/context.rs b/glutin/src/api/wgl/context.rs index 1dc492ac47..6369415a0a 100644 --- a/glutin/src/api/wgl/context.rs +++ b/glutin/src/api/wgl/context.rs @@ -24,7 +24,7 @@ use crate::surface::SurfaceTypeTrait; use super::config::Config; use super::display::Display; -use super::surface::{Surface, WGLSurface}; +use super::surface::{Surface, WglSurface}; impl Display { pub(crate) unsafe fn create_context( @@ -388,8 +388,8 @@ impl ContextInner { fn make_current(&self, surface: &Surface) -> Result<()> { unsafe { let hdc = match surface.raw { - WGLSurface::Window(_, hdc) => hdc as _, - WGLSurface::PBuffer(_, hdc) => hdc as _, + WglSurface::Window(_, hdc) => hdc as _, + WglSurface::PBuffer(_, hdc) => hdc as _, }; if wgl::MakeCurrent(hdc, self.raw.cast()) == 0 { diff --git a/glutin/src/api/wgl/surface.rs b/glutin/src/api/wgl/surface.rs index fe0c161958..a8cb0508c2 100644 --- a/glutin/src/api/wgl/surface.rs +++ b/glutin/src/api/wgl/surface.rs @@ -11,6 +11,7 @@ use glutin_wgl_sys::wgl_extra::types::HPBUFFEREXT; use glutin_wgl_sys::wgl_extra::{self}; use raw_window_handle::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}; use windows_sys::Win32::UI::WindowsAndMessaging::GetClientRect; @@ -42,36 +43,45 @@ impl Display { config: &Config, surface_attributes: &SurfaceAttributes, ) -> Result> { + let extra = self + .inner + .wgl_extra + .filter(|_| self.inner.client_extensions.contains("WGL_ARB_pbuffer")) + .ok_or(ErrorKind::NotSupported("pbuffer extensions are not supported"))?; + let hdc = config.inner.hdc; let width = surface_attributes.width.unwrap().get() as c_int; let height = surface_attributes.height.unwrap().get() as c_int; + let attrs: [c_int; 3] = { + if surface_attributes.largest_pbuffer { + [wgl_extra::PBUFFER_LARGEST_ARB as _, 1, 0] + } else { + [0; 3] + } + }; - let mut attrs = Vec::::with_capacity(2); - if surface_attributes.largest_pbuffer { - attrs.push(wgl_extra::PBUFFER_LARGEST_ARB as c_int); - attrs.push(1 as c_int); - } - attrs.push(0); - - let (hbuf, hdc) = match self.inner.wgl_extra { - Some(extra) if extra.CreatePbufferARB.is_loaded() => unsafe { - let hbuf = extra.CreatePbufferARB( - hdc as _, - config.inner.pixel_format_index, - width, - height, - attrs.as_ptr(), - ); - let hdc = extra.GetPbufferDCARB(hbuf); - (hbuf, hdc) - }, - _ => return Err(ErrorKind::NotSupported("pbuffer extensions are not supported").into()), + let hbuf = unsafe { + extra.CreatePbufferARB( + hdc as _, + config.inner.pixel_format_index, + width, + height, + attrs.as_ptr(), + ) }; + if hbuf == std::ptr::null() { + return Err(IoError::last_os_error().into()); + } + + let hdc = unsafe { extra.GetPbufferDCARB(hbuf) }; + if hdc == std::ptr::null() { + return Err(IoError::last_os_error().into()); + } let surface = Surface { display: self.clone(), config: config.clone(), - raw: WGLSurface::PBuffer(hbuf, hdc), + raw: WglSurface::PBuffer(hbuf, hdc as _), _ty: PhantomData, }; @@ -100,7 +110,7 @@ impl Display { let surface = Surface { display: self.clone(), config: config.clone(), - raw: WGLSurface::Window(hwnd, hdc), + raw: WglSurface::Window(hwnd, hdc), _ty: PhantomData, }; @@ -108,20 +118,11 @@ impl Display { } } -/// A wrapper around WGL surfaces. -#[derive(Debug)] -pub enum WGLSurface { - /// Surface backed by a window surface. - Window(HWND, gdi::HDC), - /// Surface backed by a pixel buffer. - PBuffer(HPBUFFEREXT, wgl_extra::types::HDC), -} - /// A Wrapper around `WGLSurface`. pub struct Surface { display: Display, config: Config, - pub(crate) raw: WGLSurface, + pub(crate) raw: WglSurface, _ty: PhantomData, } @@ -129,22 +130,20 @@ pub struct Surface { unsafe impl Send for Surface {} impl Surface { - /// # Safety - /// - /// The caller must ensure that the attribute could be present. - unsafe fn raw_attribute(&self, attr: GLenum) -> c_int { - let mut value = 0; - unsafe { - match self.raw { - WGLSurface::Window(..) => unreachable!(), - WGLSurface::PBuffer(hbuf, _) => { - if let Some(extra) = self.display.inner.wgl_extra { - extra.QueryPbufferARB(hbuf, attr as _, &mut value); - } - }, - } + fn raw_attribute(&self, attr: GLenum) -> Option { + match self.raw { + WglSurface::Window(..) => None, + WglSurface::PBuffer(hbuf, _) => { + let extra = self.display.inner.wgl_extra.unwrap(); + + let mut value = 0; + if unsafe { extra.QueryPbufferARB(hbuf, attr as _, &mut value) } != 0 { + Some(value) + } else { + None + } + }, } - value } } @@ -152,14 +151,13 @@ impl Drop for Surface { fn drop(&mut self) { unsafe { match self.raw { - WGLSurface::Window(hwnd, hdc) => { + WglSurface::Window(hwnd, hdc) => { gdi::ReleaseDC(hwnd, hdc); }, - WGLSurface::PBuffer(hbuf, hdc) => { - if let Some(extra) = self.display.inner.wgl_extra { - extra.ReleasePbufferDCARB(hbuf, hdc); - extra.DestroyPbufferARB(hbuf); - } + WglSurface::PBuffer(hbuf, hdc) => { + let extra = self.display.inner.wgl_extra.unwrap(); + extra.ReleasePbufferDCARB(hbuf, hdc as _); + extra.DestroyPbufferARB(hbuf); }, } } @@ -176,7 +174,7 @@ impl GlSurface for Surface { fn width(&self) -> Option { match self.raw { - WGLSurface::Window(hwnd, _) => { + WglSurface::Window(hwnd, _) => { let mut rect: RECT = unsafe { mem::zeroed() }; if unsafe { GetClientRect(hwnd, &mut rect) } == false.into() { None @@ -184,15 +182,15 @@ impl GlSurface for Surface { Some((rect.right - rect.left) as u32) } }, - WGLSurface::PBuffer(..) => unsafe { - Some(self.raw_attribute(wgl_extra::PBUFFER_WIDTH_ARB) as _) + WglSurface::PBuffer(..) => { + self.raw_attribute(wgl_extra::PBUFFER_WIDTH_ARB).map(|x| x as _) }, } } fn height(&self) -> Option { match self.raw { - WGLSurface::Window(hwnd, _) => { + WglSurface::Window(hwnd, _) => { let mut rect: RECT = unsafe { mem::zeroed() }; if unsafe { GetClientRect(hwnd, &mut rect) } == false.into() { None @@ -200,8 +198,8 @@ impl GlSurface for Surface { Some((rect.bottom - rect.top) as u32) } }, - WGLSurface::PBuffer(..) => unsafe { - Some(self.raw_attribute(wgl_extra::PBUFFER_HEIGHT_ARB) as _) + WglSurface::PBuffer(..) => { + self.raw_attribute(wgl_extra::PBUFFER_HEIGHT_ARB).map(|x| x as _) }, } } @@ -212,12 +210,7 @@ impl GlSurface for Surface { fn swap_buffers(&self, _context: &Self::Context) -> Result<()> { unsafe { - let hdc = match self.raw { - WGLSurface::Window(_, hdc) => hdc as _, - WGLSurface::PBuffer(_, hdc) => hdc as _, - }; - - if gl::SwapBuffers(hdc) == 0 { + if gl::SwapBuffers(self.raw.hdc()) == 0 { Err(IoError::last_os_error().into()) } else { Ok(()) @@ -226,30 +219,27 @@ impl GlSurface for Surface { } fn set_swap_interval(&self, _context: &Self::Context, interval: SwapInterval) -> Result<()> { - let WGLSurface::Window(..) = self.raw else { - return Ok(()); - }; - - let interval = match interval { - SwapInterval::DontWait => 0, - SwapInterval::Wait(n) => n.get(), - }; - - let res = match self.display.inner.wgl_extra { - Some(extra) if self.display.inner.features.contains(DisplayFeatures::SWAP_CONTROL) => unsafe { - extra.SwapIntervalEXT(interval as _) - }, - _ => { - return Err( - ErrorKind::NotSupported("swap control extensions are not supported").into() - ) + match self.raw { + WglSurface::Window(..) => { + let extra = self + .display + .inner + .wgl_extra + .filter(|_| self.display.inner.features.contains(DisplayFeatures::SWAP_CONTROL)) + .ok_or(ErrorKind::NotSupported("pbuffer extensions are not supported"))?; + + let interval = match interval { + SwapInterval::DontWait => 0, + SwapInterval::Wait(n) => n.get(), + }; + + if unsafe { extra.SwapIntervalEXT(interval as _) } == 0 { + Err(IoError::last_os_error().into()) + } else { + Ok(()) + } }, - }; - - if res == 0 { - Err(IoError::last_os_error().into()) - } else { - Ok(()) + _ => Err(ErrorKind::NotSupported("swap control not support for surface").into()), } } @@ -282,8 +272,8 @@ impl fmt::Debug for Surface { impl AsRawSurface for Surface { fn raw_surface(&self) -> RawSurface { match self.raw { - WGLSurface::Window(hwnd, _) => RawSurface::Wgl(hwnd as _), - WGLSurface::PBuffer(..) => RawSurface::Wgl(0 as _), + WglSurface::Window(hwnd, _) => RawSurface::Wgl(hwnd as _), + WglSurface::PBuffer(..) => RawSurface::Wgl(0 as _), } } } @@ -305,3 +295,21 @@ impl GetGlDisplay for Surface { } impl Sealed for Surface {} + +/// A wrapper around WGL surfaces. +#[derive(Debug)] +pub enum WglSurface { + /// Surface backed by a window surface. + Window(HWND, HDC), + /// Surface backed by a pixel buffer. + PBuffer(HPBUFFEREXT, HDC), +} + +impl WglSurface { + fn hdc(&self) -> HDC { + *match self { + WglSurface::Window(_, hdc) => hdc, + WglSurface::PBuffer(_, hdc) => hdc, + } + } +} From 16362ec538a51853ba6e54461268e154ae45f302 Mon Sep 17 00:00:00 2001 From: Josh Wood Date: Sun, 22 Sep 2024 06:28:00 +0200 Subject: [PATCH 4/9] fix(wgl): use `.is_null()` instead of `== std::ptr::null()` --- glutin/src/api/wgl/surface.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glutin/src/api/wgl/surface.rs b/glutin/src/api/wgl/surface.rs index a8cb0508c2..4caf399b6a 100644 --- a/glutin/src/api/wgl/surface.rs +++ b/glutin/src/api/wgl/surface.rs @@ -69,12 +69,12 @@ impl Display { attrs.as_ptr(), ) }; - if hbuf == std::ptr::null() { + if hbuf.is_null() { return Err(IoError::last_os_error().into()); } let hdc = unsafe { extra.GetPbufferDCARB(hbuf) }; - if hdc == std::ptr::null() { + if hdc.is_null() { return Err(IoError::last_os_error().into()); } From 81758df63244321689c4b641e9cab0b52bf8b5b9 Mon Sep 17 00:00:00 2001 From: Josh Wood Date: Sun, 22 Sep 2024 06:33:58 +0200 Subject: [PATCH 5/9] chore(wgl): use `== false.into()` instead of `!= 0` to match rest of file --- glutin/src/api/wgl/surface.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/glutin/src/api/wgl/surface.rs b/glutin/src/api/wgl/surface.rs index 4caf399b6a..34c62acd24 100644 --- a/glutin/src/api/wgl/surface.rs +++ b/glutin/src/api/wgl/surface.rs @@ -135,12 +135,11 @@ impl Surface { WglSurface::Window(..) => None, WglSurface::PBuffer(hbuf, _) => { let extra = self.display.inner.wgl_extra.unwrap(); - let mut value = 0; - if unsafe { extra.QueryPbufferARB(hbuf, attr as _, &mut value) } != 0 { - Some(value) - } else { + if unsafe { extra.QueryPbufferARB(hbuf, attr as _, &mut value) } == false.into() { None + } else { + Some(value) } }, } From faf6293f199d43f45b0f6a87901bb535ac3ca812 Mon Sep 17 00:00:00 2001 From: Josh Wood Date: Sun, 22 Sep 2024 06:39:52 +0200 Subject: [PATCH 6/9] fix(wgl): error message typos --- glutin/src/api/wgl/surface.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glutin/src/api/wgl/surface.rs b/glutin/src/api/wgl/surface.rs index 34c62acd24..980f3251ec 100644 --- a/glutin/src/api/wgl/surface.rs +++ b/glutin/src/api/wgl/surface.rs @@ -225,7 +225,7 @@ impl GlSurface for Surface { .inner .wgl_extra .filter(|_| self.display.inner.features.contains(DisplayFeatures::SWAP_CONTROL)) - .ok_or(ErrorKind::NotSupported("pbuffer extensions are not supported"))?; + .ok_or(ErrorKind::NotSupported("swap control extensions are not supported"))?; let interval = match interval { SwapInterval::DontWait => 0, @@ -238,7 +238,7 @@ impl GlSurface for Surface { Ok(()) } }, - _ => Err(ErrorKind::NotSupported("swap control not support for surface").into()), + _ => Err(ErrorKind::NotSupported("swap control not supported for surface").into()), } } From 7f5d22520e810e6fdf1949231439b9e2a8119672 Mon Sep 17 00:00:00 2001 From: Josh Wood Date: Sun, 22 Sep 2024 13:59:35 +0200 Subject: [PATCH 7/9] chore(wgl): address review feedback --- glutin/src/api/wgl/context.rs | 9 ++------- glutin/src/api/wgl/surface.rs | 16 +++++++--------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/glutin/src/api/wgl/context.rs b/glutin/src/api/wgl/context.rs index 6369415a0a..25e5de00ba 100644 --- a/glutin/src/api/wgl/context.rs +++ b/glutin/src/api/wgl/context.rs @@ -24,7 +24,7 @@ use crate::surface::SurfaceTypeTrait; use super::config::Config; use super::display::Display; -use super::surface::{Surface, WglSurface}; +use super::surface::Surface; impl Display { pub(crate) unsafe fn create_context( @@ -387,12 +387,7 @@ impl ContextInner { fn make_current(&self, surface: &Surface) -> Result<()> { unsafe { - let hdc = match surface.raw { - WglSurface::Window(_, hdc) => hdc as _, - WglSurface::PBuffer(_, hdc) => hdc as _, - }; - - if wgl::MakeCurrent(hdc, self.raw.cast()) == 0 { + if wgl::MakeCurrent(surface.raw.hdc() as _, self.raw.cast()) == 0 { Err(IoError::last_os_error().into()) } else { Ok(()) diff --git a/glutin/src/api/wgl/surface.rs b/glutin/src/api/wgl/surface.rs index 980f3251ec..62a1c51fad 100644 --- a/glutin/src/api/wgl/surface.rs +++ b/glutin/src/api/wgl/surface.rs @@ -52,13 +52,11 @@ impl Display { let hdc = config.inner.hdc; let width = surface_attributes.width.unwrap().get() as c_int; let height = surface_attributes.height.unwrap().get() as c_int; - let attrs: [c_int; 3] = { - if surface_attributes.largest_pbuffer { - [wgl_extra::PBUFFER_LARGEST_ARB as _, 1, 0] - } else { - [0; 3] - } - }; + let mut attrs = [0; 3]; + if surface_attributes.largest_pbuffer { + attrs[0] = wgl_extra::PBUFFER_LARGEST_ARB as c_int; + attrs[1] = 1; + } let hbuf = unsafe { extra.CreatePbufferARB( @@ -272,7 +270,7 @@ impl AsRawSurface for Surface { fn raw_surface(&self) -> RawSurface { match self.raw { WglSurface::Window(hwnd, _) => RawSurface::Wgl(hwnd as _), - WglSurface::PBuffer(..) => RawSurface::Wgl(0 as _), + WglSurface::PBuffer(hbuf, _) => RawSurface::Wgl(hbuf as _), } } } @@ -305,7 +303,7 @@ pub enum WglSurface { } impl WglSurface { - fn hdc(&self) -> HDC { + pub(crate) fn hdc(&self) -> HDC { *match self { WglSurface::Window(_, hdc) => hdc, WglSurface::PBuffer(_, hdc) => hdc, From c561464395c29e53199e434f7d472d664575d196 Mon Sep 17 00:00:00 2001 From: Josh Wood Date: Sun, 22 Sep 2024 14:03:03 +0200 Subject: [PATCH 8/9] chore(wgl): fix documentation typo --- glutin/src/api/wgl/surface.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glutin/src/api/wgl/surface.rs b/glutin/src/api/wgl/surface.rs index 62a1c51fad..7034bbf851 100644 --- a/glutin/src/api/wgl/surface.rs +++ b/glutin/src/api/wgl/surface.rs @@ -116,7 +116,7 @@ impl Display { } } -/// A Wrapper around `WGLSurface`. +/// A Wrapper around `WglSurface`. pub struct Surface { display: Display, config: Config, From 89254823bd4a36f30af1353b3bfb9befdf5bbe51 Mon Sep 17 00:00:00 2001 From: Josh Wood Date: Sun, 22 Sep 2024 15:41:53 +0200 Subject: [PATCH 9/9] chore(docs): `RawSurface::Wgl` inner value depends on `SurfaceType` --- glutin/src/surface.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glutin/src/surface.rs b/glutin/src/surface.rs index e7f6aa2b93..9c8e65ea6c 100644 --- a/glutin/src/surface.rs +++ b/glutin/src/surface.rs @@ -519,7 +519,7 @@ pub enum RawSurface { #[cfg(glx_backend)] Glx(u64), - /// HWND + /// Either a `HWND` or `HPBUFFEREXT` depending on [`SurfaceType`]. #[cfg(wgl_backend)] Wgl(*const std::ffi::c_void),