From 264f81cd1bf11cde98679f3b168e2f9d5c25ac8e Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Sun, 21 Jul 2024 21:35:50 +0200 Subject: [PATCH] gles/wgl: Migrate from ancient/unmaintained `winapi` to `windows-rs` --- CHANGELOG.md | 10 +- Cargo.lock | 131 +++++++++++---- Cargo.toml | 3 + wgpu-hal/Cargo.toml | 7 +- wgpu-hal/src/gles/wgl.rs | 354 ++++++++++++++++++--------------------- 5 files changed, 282 insertions(+), 223 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c781d3f6047..3ad8d9e937a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Please add your PR to the changelog! Choose from a top level and bottom level category, then write your changes like follows: -- Describe your change in a user friendly format by @yourslug in [#99999](https://github.com/gfx-rs/wgpu/pull/99999) +- Describe your change in a user friendly format. By @yourslug in [#99999](https://github.com/gfx-rs/wgpu/pull/99999) You can add additional user facing information if it's a major breaking change. You can use the following to help: @@ -48,6 +48,12 @@ Bottom level categories: - Bump MSRV for `d3d12`/`naga`/`wgpu-core`/`wgpu-hal`/`wgpu-types`' to 1.76. By @wumpf in [#6003](https://github.com/gfx-rs/wgpu/pull/6003) - Print requested and supported usages on `UnsupportedUsage` error. By @VladasZ in [#6007](https://github.com/gfx-rs/wgpu/pull/6007) +### Dependency Updates + +#### GLES + +- Replace `winapi` code in WGL wrapper to use the `windows` crate. By @MarijnS95 in [#6006](https://github.com/gfx-rs/wgpu/pull/6006) + ## 22.0.0 (2024-07-17) ### Overview @@ -57,7 +63,7 @@ Bottom level categories: For the first time ever, WGPU is being released with a major version (i.e., 22.* instead of 0.22.*)! Maintainership has decided to fully adhere to [Semantic Versioning](https://semver.org/)'s recommendations for versioning production software. According to [SemVer 2.0.0's Q&A about when to use 1.0.0 versions (and beyond)](https://semver.org/spec/v2.0.0.html#how-do-i-know-when-to-release-100): > ### How do I know when to release 1.0.0? -> +> > If your software is being used in production, it should probably already be 1.0.0. If you have a stable API on which users have come to depend, you should be 1.0.0. If you’re worrying a lot about backward compatibility, you should probably already be 1.0.0. It is a well-known fact that WGPU has been used for applications and platforms already in production for years, at this point. We are often concerned with tracking breaking changes, and affecting these consumers' ability to ship. By releasing our first major version, we publicly acknowledge that this is the case. We encourage other projects in the Rust ecosystem to follow suit. diff --git a/Cargo.lock b/Cargo.lock index 8b4e604f4ee..7747deeb4ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1522,7 +1522,7 @@ dependencies = [ "libc", "log", "rustversion", - "windows", + "windows 0.54.0", ] [[package]] @@ -1686,7 +1686,7 @@ dependencies = [ "presser", "thiserror", "winapi", - "windows", + "windows 0.58.0", ] [[package]] @@ -2608,7 +2608,7 @@ dependencies = [ "redox_syscall 0.5.1", "smallvec", "thread-id", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -4327,7 +4327,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading 0.7.4", + "libloading 0.8.4", "log", "metal", "naga", @@ -4346,6 +4346,7 @@ dependencies = [ "web-sys", "wgpu-types", "winapi", + "windows 0.58.0", "winit 0.29.15", ] @@ -4473,8 +4474,18 @@ version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ - "windows-core", - "windows-targets 0.52.5", + "windows-core 0.54.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", ] [[package]] @@ -4483,8 +4494,43 @@ version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ - "windows-result", - "windows-targets 0.52.5", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.71", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.71", ] [[package]] @@ -4493,7 +4539,26 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", ] [[package]] @@ -4533,7 +4598,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -4568,18 +4633,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -4596,9 +4661,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -4620,9 +4685,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -4644,9 +4709,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" @@ -4674,9 +4739,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -4698,9 +4763,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -4716,9 +4781,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -4740,9 +4805,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" diff --git a/Cargo.toml b/Cargo.toml index 51fe42197e1..76b3de9dc23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -160,6 +160,9 @@ khronos-egl = "6" glow = "0.14.0" glutin = "0.29.1" +# DX and GLES dependencies +windows = { version = "0.58", default-features = false } + # wasm32 dependencies console_error_panic_hook = "0.1.7" console_log = "1" diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index a54332fef63..19effa88376 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -61,7 +61,10 @@ gles = [ "dep:khronos-egl", "dep:libloading", "dep:ndk-sys", - "winapi/libloaderapi", + "windows/Win32_Graphics_OpenGL", + "windows/Win32_Graphics_Gdi", + "windows/Win32_System_LibraryLoader", + "windows/Win32_UI_WindowsAndMessaging", ] ## Enables the DX12 backend when targeting Windows. ## @@ -144,6 +147,8 @@ khronos-egl = { version = "6", features = ["static", "no-pkg-config"] } libloading = { version = ">=0.7, <0.9", optional = true } [target.'cfg(windows)'.dependencies] +# backend: Dx12 and Gles +windows = { workspace = true, optional = true } # backend: Dx12 bit-set = { version = "0.8", optional = true } range-alloc = { version = "0.1", optional = true } diff --git a/wgpu-hal/src/gles/wgl.rs b/wgpu-hal/src/gles/wgl.rs index c221b3e59d2..0614e9557a0 100644 --- a/wgpu-hal/src/gles/wgl.rs +++ b/wgpu-hal/src/gles/wgl.rs @@ -9,7 +9,6 @@ use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use std::{ collections::HashSet, ffi::{c_void, CStr, CString}, - io::Error, mem, os::raw::c_int, ptr, @@ -21,23 +20,13 @@ use std::{ time::Duration, }; use wgt::InstanceFlags; -use winapi::{ - shared::{ - minwindef::{FALSE, HMODULE, LPARAM, LRESULT, UINT, WPARAM}, - windef::{HDC, HGLRC, HWND}, - }, - um::{ - libloaderapi::{GetModuleHandleA, GetProcAddress, LoadLibraryA}, - wingdi::{ - wglCreateContext, wglDeleteContext, wglGetCurrentContext, wglGetProcAddress, - wglMakeCurrent, ChoosePixelFormat, DescribePixelFormat, GetPixelFormat, SetPixelFormat, - SwapBuffers, PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, - PIXELFORMATDESCRIPTOR, - }, - winuser::{ - CreateWindowExA, DefWindowProcA, DestroyWindow, GetDC, RegisterClassExA, ReleaseDC, - CS_OWNDC, WNDCLASSEXA, - }, +use windows::{ + core::{Error, PCSTR}, + Win32::{ + Foundation, + Graphics::{Gdi, OpenGL}, + System::LibraryLoader, + UI::WindowsAndMessaging, }, }; @@ -59,7 +48,7 @@ impl AdapterContext { } pub fn raw_context(&self) -> *mut c_void { - self.inner.lock().context.context as *mut _ + self.inner.lock().context.context.0 } /// Obtain a lock to the WGL context and get handle to the [`glow::Context`] that can be used to @@ -84,7 +73,7 @@ impl AdapterContext { /// Unlike [`lock`](Self::lock), this accepts a device to pass to `make_current` and exposes the error /// when `make_current` fails. #[track_caller] - fn lock_with_dc(&self, device: HDC) -> Result, Error> { + fn lock_with_dc(&self, device: Gdi::HDC) -> windows::core::Result> { let inner = self .inner .try_lock_for(Duration::from_secs(CONTEXT_LOCK_TIMEOUT_SECS)) @@ -117,37 +106,27 @@ impl<'a> Drop for AdapterContextLock<'a> { } struct WglContext { - context: HGLRC, + context: OpenGL::HGLRC, } impl WglContext { - fn make_current(&self, device: HDC) -> Result<(), Error> { - if unsafe { wglMakeCurrent(device, self.context) } == FALSE { - Err(Error::last_os_error()) - } else { - Ok(()) - } + fn make_current(&self, device: Gdi::HDC) -> windows::core::Result<()> { + unsafe { OpenGL::wglMakeCurrent(device, self.context) } } - fn unmake_current(&self) -> Result<(), Error> { - if unsafe { wglGetCurrentContext().is_null() } { + fn unmake_current(&self) -> windows::core::Result<()> { + if unsafe { OpenGL::wglGetCurrentContext() }.is_invalid() { return Ok(()); } - if unsafe { wglMakeCurrent(ptr::null_mut(), ptr::null_mut()) } == FALSE { - Err(Error::last_os_error()) - } else { - Ok(()) - } + unsafe { OpenGL::wglMakeCurrent(None, None) } } } impl Drop for WglContext { fn drop(&mut self) { - unsafe { - if wglDeleteContext(self.context) == FALSE { - log::error!("failed to delete WGL context {}", Error::last_os_error()); - } - }; + if let Err(e) = unsafe { OpenGL::wglDeleteContext(self.context) } { + log::error!("failed to delete WGL context: {e}"); + } } } @@ -171,20 +150,21 @@ pub struct Instance { unsafe impl Send for Instance {} unsafe impl Sync for Instance {} -fn load_gl_func(name: &str, module: Option) -> *const c_void { +fn load_gl_func(name: &str, module: Option) -> *const c_void { let addr = CString::new(name.as_bytes()).unwrap(); - let mut ptr = unsafe { wglGetProcAddress(addr.as_ptr()) }; - if ptr.is_null() { + let mut ptr = unsafe { OpenGL::wglGetProcAddress(PCSTR(addr.as_ptr() as *const u8)) }; + if ptr.is_none() { if let Some(module) = module { - ptr = unsafe { GetProcAddress(module, addr.as_ptr()) }; + ptr = + unsafe { LibraryLoader::GetProcAddress(module, PCSTR(addr.as_ptr() as *const u8)) }; } } - ptr.cast() + ptr.map_or_else(ptr::null_mut, |p| p as *mut c_void) } -fn get_extensions(extra: &Wgl, dc: HDC) -> HashSet { +fn get_extensions(extra: &Wgl, dc: Gdi::HDC) -> HashSet { if extra.GetExtensionsStringARB.is_loaded() { - unsafe { CStr::from_ptr(extra.GetExtensionsStringARB(dc as *const _)) } + unsafe { CStr::from_ptr(extra.GetExtensionsStringARB(dc.0)) } .to_str() .unwrap_or("") } else { @@ -195,63 +175,75 @@ fn get_extensions(extra: &Wgl, dc: HDC) -> HashSet { .collect() } -unsafe fn setup_pixel_format(dc: HDC) -> Result<(), crate::InstanceError> { - let mut format: PIXELFORMATDESCRIPTOR = unsafe { mem::zeroed() }; - format.nVersion = 1; - format.nSize = mem::size_of_val(&format) as u16; - format.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - format.iPixelType = PFD_TYPE_RGBA; - format.cColorBits = 8; +unsafe fn setup_pixel_format(dc: Gdi::HDC) -> Result<(), crate::InstanceError> { + { + let format = OpenGL::PIXELFORMATDESCRIPTOR { + nVersion: 1, + nSize: mem::size_of::() as u16, + dwFlags: OpenGL::PFD_DRAW_TO_WINDOW + | OpenGL::PFD_SUPPORT_OPENGL + | OpenGL::PFD_DOUBLEBUFFER, + iPixelType: OpenGL::PFD_TYPE_RGBA, + cColorBits: 8, + ..unsafe { mem::zeroed() } + }; - let index = unsafe { ChoosePixelFormat(dc, &format) }; - if index == 0 { - return Err(crate::InstanceError::with_source( - String::from("unable to choose pixel format"), - Error::last_os_error(), - )); - } + let index = unsafe { OpenGL::ChoosePixelFormat(dc, &format) }; + if index == 0 { + return Err(crate::InstanceError::with_source( + String::from("unable to choose pixel format"), + Error::from_win32(), + )); + } - let current = unsafe { GetPixelFormat(dc) }; + let current = unsafe { OpenGL::GetPixelFormat(dc) }; - if index != current && unsafe { SetPixelFormat(dc, index, &format) } == FALSE { - return Err(crate::InstanceError::with_source( - String::from("unable to set pixel format"), - Error::last_os_error(), - )); + if index != current { + unsafe { OpenGL::SetPixelFormat(dc, index, &format) }.map_err(|e| { + crate::InstanceError::with_source(String::from("unable to set pixel format"), e) + })?; + } } - let index = unsafe { GetPixelFormat(dc) }; - if index == 0 { - return Err(crate::InstanceError::with_source( - String::from("unable to get pixel format index"), - Error::last_os_error(), - )); - } - if unsafe { DescribePixelFormat(dc, index, mem::size_of_val(&format) as UINT, &mut format) } - == 0 { - return Err(crate::InstanceError::with_source( - String::from("unable to read pixel format"), - Error::last_os_error(), - )); - } + let index = unsafe { OpenGL::GetPixelFormat(dc) }; + if index == 0 { + return Err(crate::InstanceError::with_source( + String::from("unable to get pixel format index"), + Error::from_win32(), + )); + } + let mut format = Default::default(); + if unsafe { + OpenGL::DescribePixelFormat( + dc, + index, + mem::size_of_val(&format) as u32, + Some(&mut format), + ) + } == 0 + { + return Err(crate::InstanceError::with_source( + String::from("unable to read pixel format"), + Error::from_win32(), + )); + } - if format.dwFlags & PFD_SUPPORT_OPENGL == 0 || format.iPixelType != PFD_TYPE_RGBA { - return Err(crate::InstanceError::new(String::from( - "unsuitable pixel format", - ))); + if !format.dwFlags.contains(OpenGL::PFD_SUPPORT_OPENGL) + || format.iPixelType != OpenGL::PFD_TYPE_RGBA + { + return Err(crate::InstanceError::new(String::from( + "unsuitable pixel format", + ))); + } } Ok(()) } fn create_global_window_class() -> Result { - let instance = unsafe { GetModuleHandleA(ptr::null()) }; - if instance.is_null() { - return Err(crate::InstanceError::with_source( - String::from("unable to get executable instance"), - Error::last_os_error(), - )); - } + let instance = unsafe { LibraryLoader::GetModuleHandleA(None) }.map_err(|e| { + crate::InstanceError::with_source(String::from("unable to get executable instance"), e) + })?; // Use the address of `UNIQUE` as part of the window class name to ensure different // `wgpu` versions use different names. @@ -262,35 +254,35 @@ fn create_global_window_class() -> Result { // Use a wrapper function for compatibility with `windows-rs`. unsafe extern "system" fn wnd_proc( - window: HWND, - msg: UINT, - wparam: WPARAM, - lparam: LPARAM, - ) -> LRESULT { - unsafe { DefWindowProcA(window, msg, wparam, lparam) } + window: Foundation::HWND, + msg: u32, + wparam: Foundation::WPARAM, + lparam: Foundation::LPARAM, + ) -> Foundation::LRESULT { + unsafe { WindowsAndMessaging::DefWindowProcA(window, msg, wparam, lparam) } } - let window_class = WNDCLASSEXA { - cbSize: mem::size_of::() as u32, - style: CS_OWNDC, + let window_class = WindowsAndMessaging::WNDCLASSEXA { + cbSize: mem::size_of::() as u32, + style: WindowsAndMessaging::CS_OWNDC, lpfnWndProc: Some(wnd_proc), cbClsExtra: 0, cbWndExtra: 0, - hInstance: instance, - hIcon: ptr::null_mut(), - hCursor: ptr::null_mut(), - hbrBackground: ptr::null_mut(), - lpszMenuName: ptr::null_mut(), - lpszClassName: name.as_ptr(), - hIconSm: ptr::null_mut(), + hInstance: instance.into(), + hIcon: WindowsAndMessaging::HICON::default(), + hCursor: WindowsAndMessaging::HCURSOR::default(), + hbrBackground: Gdi::HBRUSH::default(), + lpszMenuName: PCSTR::null(), + lpszClassName: PCSTR(name.as_ptr() as *const u8), + hIconSm: WindowsAndMessaging::HICON::default(), }; - let atom = unsafe { RegisterClassExA(&window_class) }; + let atom = unsafe { WindowsAndMessaging::RegisterClassExA(&window_class) }; if atom == 0 { return Err(crate::InstanceError::with_source( String::from("unable to register window class"), - Error::last_os_error(), + Error::from_win32(), )); } @@ -306,7 +298,7 @@ fn get_global_window_class() -> Result { } struct InstanceDevice { - dc: HDC, + dc: Gdi::HDC, /// This is used to keep the thread owning `dc` alive until this struct is dropped. _tx: SyncSender<()>, @@ -314,31 +306,19 @@ struct InstanceDevice { fn create_instance_device() -> Result { #[derive(Clone, Copy)] - struct SendDc(HDC); + // TODO: We can get these SendSync definitions in the upstream metadata if this is the case + struct SendDc(Gdi::HDC); unsafe impl Sync for SendDc {} unsafe impl Send for SendDc {} struct Window { - window: HWND, + window: Foundation::HWND, } impl Drop for Window { fn drop(&mut self) { - unsafe { - if DestroyWindow(self.window) == FALSE { - log::error!("failed to destroy window {}", Error::last_os_error()); - } - }; - } - } - struct DeviceContextHandle { - dc: HDC, - window: HWND, - } - impl Drop for DeviceContextHandle { - fn drop(&mut self) { - unsafe { - ReleaseDC(self.window, self.dc); - }; + if let Err(e) = unsafe { WindowsAndMessaging::DestroyWindow(self.window) } { + log::error!("failed to destroy window: {e}"); + } } } @@ -353,58 +333,57 @@ fn create_instance_device() -> Result { .name("wgpu-hal WGL Instance Thread".to_owned()) .spawn(move || { let setup = (|| { - let instance = unsafe { GetModuleHandleA(ptr::null()) }; - if instance.is_null() { - return Err(crate::InstanceError::with_source( + let instance = unsafe { LibraryLoader::GetModuleHandleA(None) }.map_err(|e| { + crate::InstanceError::with_source( String::from("unable to get executable instance"), - Error::last_os_error(), - )); - } + e, + ) + })?; // Create a hidden window since we don't pass `WS_VISIBLE`. let window = unsafe { - CreateWindowExA( - 0, - window_class.as_ptr(), - window_class.as_ptr(), - 0, + WindowsAndMessaging::CreateWindowExA( + WindowsAndMessaging::WINDOW_EX_STYLE::default(), + PCSTR(window_class.as_ptr() as *const u8), + PCSTR(window_class.as_ptr() as *const u8), + WindowsAndMessaging::WINDOW_STYLE::default(), 0, 0, 1, 1, - ptr::null_mut(), - ptr::null_mut(), + None, + None, instance, - ptr::null_mut(), + None, ) - }; - if window.is_null() { - return Err(crate::InstanceError::with_source( - String::from("unable to create hidden instance window"), - Error::last_os_error(), - )); } + .map_err(|e| { + crate::InstanceError::with_source( + String::from("unable to create hidden instance window"), + e, + ) + })?; let window = Window { window }; - let dc = unsafe { GetDC(window.window) }; - if dc.is_null() { + let dc = unsafe { Gdi::GetDC(window.window) }; + if dc.is_invalid() { return Err(crate::InstanceError::with_source( String::from("unable to create memory device"), - Error::last_os_error(), + Error::from_win32(), )); } let dc = DeviceContextHandle { - dc, + device: dc, window: window.window, }; - unsafe { setup_pixel_format(dc.dc)? }; + unsafe { setup_pixel_format(dc.device)? }; Ok((window, dc)) })(); match setup { Ok((_window, dc)) => { - setup_tx.send(Ok(SendDc(dc.dc))).unwrap(); + setup_tx.send(Ok(SendDc(dc.device))).unwrap(); // Wait for the shutdown event to free the window and device context handle. drop_rx.recv().ok(); } @@ -427,24 +406,25 @@ impl crate::Instance for Instance { unsafe fn init(desc: &crate::InstanceDescriptor) -> Result { profiling::scope!("Init OpenGL (WGL) Backend"); - let opengl_module = unsafe { LoadLibraryA("opengl32.dll\0".as_ptr() as *const _) }; - if opengl_module.is_null() { - return Err(crate::InstanceError::with_source( - String::from("unable to load the OpenGL library"), - Error::last_os_error(), - )); - } + let opengl_module = + unsafe { LibraryLoader::LoadLibraryA(PCSTR("opengl32.dll\0".as_ptr())) }.map_err( + |e| { + crate::InstanceError::with_source( + String::from("unable to load the OpenGL library"), + e, + ) + }, + )?; let device = create_instance_device()?; let dc = device.dc; - let context = unsafe { wglCreateContext(dc) }; - if context.is_null() { - return Err(crate::InstanceError::with_source( + let context = unsafe { OpenGL::wglCreateContext(dc) }.map_err(|e| { + crate::InstanceError::with_source( String::from("unable to create initial OpenGL context"), - Error::last_os_error(), - )); - } + e, + ) + })?; let context = WglContext { context }; context.make_current(dc).map_err(|e| { crate::InstanceError::with_source( @@ -471,17 +451,16 @@ impl crate::Instance for Instance { }, 0, // End of list ]; - let context = unsafe { - extra.CreateContextAttribsARB(dc as *const _, ptr::null(), attributes.as_ptr()) - }; + let context = + unsafe { extra.CreateContextAttribsARB(dc.0, ptr::null(), attributes.as_ptr()) }; if context.is_null() { return Err(crate::InstanceError::with_source( String::from("unable to create OpenGL context"), - Error::last_os_error(), + Error::from_win32(), )); } WglContext { - context: context as *mut _, + context: OpenGL::HGLRC(context as *mut c_void), } } else { context @@ -550,7 +529,8 @@ impl crate::Instance for Instance { ))); }; Ok(Surface { - window: window.hwnd.get() as *mut _, + // This cast exists because of https://github.com/rust-windowing/raw-window-handle/issues/171 + window: Foundation::HWND(window.hwnd.get() as *mut _), presentable: true, swapchain: RwLock::new(None), srgb_capable: self.srgb_capable, @@ -573,14 +553,14 @@ impl crate::Instance for Instance { } struct DeviceContextHandle { - device: HDC, - window: HWND, + device: Gdi::HDC, + window: Foundation::HWND, } impl Drop for DeviceContextHandle { fn drop(&mut self) { unsafe { - ReleaseDC(self.window, self.device); + Gdi::ReleaseDC(self.window, self.device); }; } } @@ -599,7 +579,7 @@ pub struct Swapchain { } pub struct Surface { - window: HWND, + window: Foundation::HWND, pub(super) presentable: bool, swapchain: RwLock>, srgb_capable: bool, @@ -616,11 +596,11 @@ impl Surface { ) -> Result<(), crate::SurfaceError> { let swapchain = self.swapchain.read(); let sc = swapchain.as_ref().unwrap(); - let dc = unsafe { GetDC(self.window) }; - if dc.is_null() { + let dc = unsafe { Gdi::GetDC(self.window) }; + if dc.is_invalid() { log::error!( "unable to get the device context from window: {}", - Error::last_os_error() + Error::from_win32() ); return Err(crate::SurfaceError::Other( "unable to get the device context from window", @@ -670,8 +650,8 @@ impl Surface { unsafe { gl.bind_renderbuffer(glow::RENDERBUFFER, None) }; unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None) }; - if unsafe { SwapBuffers(dc.device) } == FALSE { - log::error!("unable to swap buffers: {}", Error::last_os_error()); + if let Err(e) = unsafe { OpenGL::SwapBuffers(dc.device) } { + log::error!("unable to swap buffers: {e}"); return Err(crate::SurfaceError::Other("unable to swap buffers")); } @@ -694,11 +674,11 @@ impl crate::Surface for Surface { // Remove the old configuration. unsafe { self.unconfigure(device) }; - let dc = unsafe { GetDC(self.window) }; - if dc.is_null() { + let dc = unsafe { Gdi::GetDC(self.window) }; + if dc.is_invalid() { log::error!( "unable to get the device context from window: {}", - Error::last_os_error() + Error::from_win32() ); return Err(crate::SurfaceError::Other( "unable to get the device context from window", @@ -771,8 +751,8 @@ impl crate::Surface for Surface { } }; - if unsafe { extra.SwapIntervalEXT(if vsync { 1 } else { 0 }) } == FALSE { - log::error!("unable to set swap interval: {}", Error::last_os_error()); + if unsafe { extra.SwapIntervalEXT(if vsync { 1 } else { 0 }) } == Foundation::FALSE.0 { + log::error!("unable to set swap interval: {}", Error::from_win32()); return Err(crate::SurfaceError::Other("unable to set swap interval")); }