Skip to content

Commit 4dade24

Browse files
committed
wip
1 parent db0b8ed commit 4dade24

4 files changed

Lines changed: 107 additions & 95 deletions

File tree

src/platform/win/gl.rs

Lines changed: 27 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,17 @@ use std::rc::Rc;
33
use windows_sys::{
44
core::s,
55
Win32::{
6-
Foundation::{FreeLibrary, HMODULE, HWND},
7-
Graphics::{
8-
Gdi::{GetDC, ReleaseDC, HDC},
9-
OpenGL::{
10-
wglCreateContext, wglDeleteContext, wglGetProcAddress, wglMakeCurrent,
11-
ChoosePixelFormat, DescribePixelFormat, SetPixelFormat, SwapBuffers, HGLRC,
12-
PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_MAIN_PLANE, PFD_SUPPORT_OPENGL,
13-
PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR,
14-
},
15-
},
6+
Foundation::{FreeLibrary, HMODULE},
7+
Graphics::OpenGL::{wglGetProcAddress, wglMakeCurrent},
168
System::LibraryLoader::{GetProcAddress, LoadLibraryA},
17-
UI::WindowsAndMessaging::{DestroyWindow, UnregisterClassW},
189
},
1910
};
2011

2112
use crate::gl::*;
22-
use crate::wrappers::win32::window::{with_dummy_window, HWnd, PixelFormat};
23-
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_create_context.txt
24-
25-
type WglCreateContextAttribsARB = extern "system" fn(HDC, HGLRC, *const i32) -> HGLRC;
13+
use crate::wrappers::win32::window::{
14+
with_dummy_window, HWnd, MissingExtensionFunctionError, OwnDeviceContext, PixelFormat,
15+
WglContext, WglExtra,
16+
};
2617

2718
const WGL_CONTEXT_MAJOR_VERSION_ARB: i32 = 0x2091;
2819
const WGL_CONTEXT_MINOR_VERSION_ARB: i32 = 0x2092;
@@ -31,11 +22,6 @@ const WGL_CONTEXT_PROFILE_MASK_ARB: i32 = 0x9126;
3122
const WGL_CONTEXT_CORE_PROFILE_BIT_ARB: i32 = 0x00000001;
3223
const WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: i32 = 0x00000002;
3324

34-
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt
35-
36-
type WglChoosePixelFormatARB =
37-
extern "system" fn(HDC, *const i32, *const f32, u32, *mut i32, *mut u32) -> i32;
38-
3925
const WGL_DRAW_TO_WINDOW_ARB: i32 = 0x2001;
4026
const WGL_ACCELERATION_ARB: i32 = 0x2003;
4127
const WGL_SUPPORT_OPENGL_ARB: i32 = 0x2010;
@@ -60,11 +46,18 @@ const WGL_SAMPLES_ARB: i32 = 0x2042;
6046

6147
const WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: i32 = 0x20A9;
6248

63-
// See https://www.khronos.org/registry/OpenGL/extensions/EXT/WGL_EXT_swap_control.txt
49+
#[derive(Debug)]
50+
pub enum CreationFailedError {
51+
Win32(windows_core::Error),
52+
MissingWglExtension(MissingExtensionFunctionError),
53+
}
6454

65-
type WglSwapIntervalEXT = extern "system" fn(i32) -> i32;
55+
impl From<windows_core::Error> for CreationFailedError {
56+
fn from(err: windows_core::Error) -> Self {
57+
CreationFailedError::Win32(err)
58+
}
59+
}
6660

67-
pub type CreationFailedError = windows_core::Error;
6861
pub type GlContext = Rc<GlContextInner>;
6962

7063
impl From<CreationFailedError> for GlError {
@@ -73,48 +66,23 @@ impl From<CreationFailedError> for GlError {
7366
}
7467
}
7568

76-
#[allow(non_snake_case)]
77-
struct WglExtra {
78-
wglCreateContextAttribsARB: Option<WglCreateContextAttribsARB>,
79-
wglChoosePixelFormatARB: Option<WglChoosePixelFormatARB>,
80-
wglSwapIntervalEXT: Option<WglSwapIntervalEXT>,
81-
}
82-
83-
impl WglExtra {
84-
pub fn load() -> Self {
85-
unsafe {
86-
Self {
87-
wglCreateContextAttribsARB: wglGetProcAddress(s!("wglCreateContextAttribsARB"))
88-
.map(|addr| std::mem::transmute(addr)),
89-
wglChoosePixelFormatARB: wglGetProcAddress(s!("wglChoosePixelFormatARB"))
90-
.map(|addr| std::mem::transmute(addr)),
91-
wglSwapIntervalEXT: wglGetProcAddress(s!("wglSwapIntervalEXT"))
92-
.map(|addr| std::mem::transmute(addr)),
93-
}
94-
}
95-
}
96-
}
97-
9869
pub struct GlContextInner {
99-
hwnd: HWND,
100-
hdc: HDC,
101-
hglrc: HGLRC,
70+
hwnd: HWnd,
71+
hdc: OwnDeviceContext,
72+
hglrc: WglContext,
10273
gl_library: HMODULE,
10374
}
10475

10576
impl GlContextInner {
10677
pub unsafe fn create(window: HWnd, config: GlConfig) -> Result<Self, GlError> {
10778
// Create temporary window and context to load function pointers
108-
10979
let extra = with_dummy_window(|hwnd_tmp| {
11080
let hdc = hwnd_tmp.get_own_dc()?;
11181
hdc.set_pixel_format(&PixelFormat::default())?;
11282

11383
let wgl_ctx = hdc.create_wgl_context()?;
114-
wgl_ctx.make_current(&hdc)?;
115-
116-
Ok(WglExtra::load())
117-
})?;
84+
wgl_ctx.with_current(&hdc, || WglExtra::load())
85+
})??;
11886

11987
// Create actual context
12088

@@ -145,7 +113,7 @@ impl GlContextInner {
145113
let mut pixel_format = 0;
146114
let mut num_formats = 0;
147115
extra.wglChoosePixelFormatARB.unwrap()(
148-
hdc,
116+
hdc.as_raw(),
149117
pixel_format_attribs.as_ptr(),
150118
std::ptr::null(),
151119
1,
@@ -177,7 +145,7 @@ impl GlContextInner {
177145
];
178146

179147
extra.wglChoosePixelFormatARB.unwrap()(
180-
hdc,
148+
hdc.as_raw(),
181149
pixel_format_attribs_fallback.as_ptr(),
182150
std::ptr::null(),
183151
1,
@@ -188,37 +156,11 @@ impl GlContextInner {
188156

189157
// if no num_formats are found which happens in Wine for child windows, use fallback
190158
if num_formats == 0 {
191-
let fallback_pfd = PIXELFORMATDESCRIPTOR {
192-
nSize: std::mem::size_of::<PIXELFORMATDESCRIPTOR>() as u16,
193-
nVersion: 1,
194-
dwFlags: PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
195-
iPixelType: PFD_TYPE_RGBA,
196-
cColorBits: 32,
197-
cAlphaBits: config.alpha_bits,
198-
cDepthBits: config.depth_bits,
199-
cStencilBits: config.stencil_bits,
200-
iLayerType: PFD_MAIN_PLANE as u8,
201-
..std::mem::zeroed()
202-
};
203-
pixel_format = ChoosePixelFormat(hdc, &fallback_pfd);
204-
}
205-
206-
if pixel_format == 0 {
207-
ReleaseDC(hwnd, hdc);
208-
return Err(GlError::CreationFailed(()));
159+
hdc.set_pixel_format(&PixelFormat::from_config(&config))?;
209160
}
210161

211162
hdc.set_pixel_format_from_index(pixel_format)?;
212163

213-
let mut pfd: PIXELFORMATDESCRIPTOR = std::mem::zeroed();
214-
DescribePixelFormat(
215-
hdc,
216-
pixel_format,
217-
std::mem::size_of::<PIXELFORMATDESCRIPTOR>() as u32,
218-
&mut pfd,
219-
);
220-
SetPixelFormat(hdc, pixel_format, &pfd);
221-
222164
let profile_mask = match config.profile {
223165
Profile::Core => WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
224166
Profile::Compatibility => WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
@@ -251,11 +193,11 @@ impl GlContextInner {
251193
}
252194

253195
pub unsafe fn make_current(&self) {
254-
wglMakeCurrent(self.hdc, self.hglrc);
196+
let _ = self.hglrc.make_current(&self.hdc);
255197
}
256198

257199
pub unsafe fn make_not_current(&self) {
258-
wglMakeCurrent(self.hdc, std::ptr::null_mut());
200+
let _ = self.hglrc.make_not_current();
259201
}
260202

261203
pub fn get_proc_address(&self, symbol: &str) -> *const c_void {
@@ -273,18 +215,13 @@ impl GlContextInner {
273215
}
274216

275217
pub fn swap_buffers(&self) {
276-
unsafe {
277-
SwapBuffers(self.hdc);
278-
}
218+
let _ = self.hdc.swap_buffers();
279219
}
280220
}
281221

282222
impl Drop for GlContextInner {
283223
fn drop(&mut self) {
284224
unsafe {
285-
wglMakeCurrent(std::ptr::null_mut(), std::ptr::null_mut());
286-
wglDeleteContext(self.hglrc);
287-
ReleaseDC(self.hwnd, self.hdc);
288225
FreeLibrary(self.gl_library);
289226
}
290227
}

src/wrappers/win32/window.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ mod window_class;
55

66
#[cfg(feature = "opengl")]
77
mod dc;
8-
98
#[cfg(feature = "opengl")]
109
pub use dc::*;
10+
#[cfg(feature = "opengl")]
11+
mod wgl;
12+
#[cfg(feature = "opengl")]
13+
pub use wgl::*;
1114

1215
use data::WindowData;
1316
use dpi::PhysicalSize;

src/wrappers/win32/window/dc.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1+
use crate::gl::GlConfig;
12
use crate::wrappers::win32::window::HWnd;
23
use std::ffi::c_void;
34
use std::num::{NonZero, NonZeroI32};
45
use std::ptr::{null_mut, NonNull};
56
use windows_core::{Error, Result};
67
use windows_sys::Win32::Graphics::Gdi::{GetDC, HDC};
78
use windows_sys::Win32::Graphics::OpenGL::{
8-
wglCreateContext, wglDeleteContext, wglGetCurrentContext, wglMakeCurrent, ChoosePixelFormat,
9-
DescribePixelFormat, SetPixelFormat, PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_MAIN_PLANE,
10-
PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR,
9+
wglCreateContext, wglDeleteContext, wglGetCurrentContext, wglGetProcAddress, wglMakeCurrent,
10+
ChoosePixelFormat, DescribePixelFormat, SetPixelFormat, SwapBuffers, PFD_DOUBLEBUFFER,
11+
PFD_DRAW_TO_WINDOW, PFD_MAIN_PLANE, PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR,
1112
};
1213

1314
pub struct OwnDeviceContext {
@@ -23,7 +24,7 @@ impl OwnDeviceContext {
2324
Ok(Self { inner: dc })
2425
}
2526

26-
fn as_raw(&self) -> HDC {
27+
pub fn as_raw(&self) -> HDC {
2728
self.inner.as_ptr()
2829
}
2930

@@ -80,6 +81,15 @@ impl OwnDeviceContext {
8081

8182
Ok(WglContext { inner: ctx })
8283
}
84+
85+
pub fn swap_buffers(&self) -> Result<()> {
86+
let result = unsafe { SwapBuffers(self.as_raw()) };
87+
if result == 0 {
88+
return Err(Error::from_thread());
89+
}
90+
91+
Ok(())
92+
}
8393
}
8494

8595
pub struct WglContext {
@@ -156,6 +166,14 @@ impl Default for PixelFormat {
156166
}
157167

158168
impl PixelFormat {
169+
pub fn from_config(config: &GlConfig) -> Self {
170+
Self {
171+
alpha_bits: config.alpha_bits,
172+
depth_bits: config.depth_bits,
173+
stencil_bits: config.stencil_bits,
174+
}
175+
}
176+
159177
pub fn to_raw_descriptor(&self) -> PIXELFORMATDESCRIPTOR {
160178
PIXELFORMATDESCRIPTOR {
161179
nSize: size_of::<PIXELFORMATDESCRIPTOR>() as u16,

src/wrappers/win32/window/wgl.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use std::ffi::CStr;
2+
use std::fmt::{Display, Formatter};
3+
use std::mem::transmute;
4+
use windows_sys::Win32::Graphics::Gdi::HDC;
5+
use windows_sys::Win32::Graphics::OpenGL::{wglGetProcAddress, HGLRC};
6+
7+
// See https://www.khronos.org/registry/OpenGL/extensions/EXT/WGL_EXT_swap_control.txt
8+
type WglSwapIntervalEXT = extern "system" fn(i32) -> i32;
9+
10+
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt
11+
type WglChoosePixelFormatARB =
12+
extern "system" fn(HDC, *const i32, *const f32, u32, *mut i32, *mut u32) -> i32;
13+
14+
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_create_context.txt
15+
type WglCreateContextAttribsARB = extern "system" fn(HDC, HGLRC, *const i32) -> HGLRC;
16+
17+
#[allow(non_snake_case)]
18+
pub struct WglExtra {
19+
wglCreateContextAttribsARB: WglCreateContextAttribsARB,
20+
wglChoosePixelFormatARB: WglChoosePixelFormatARB,
21+
wglSwapIntervalEXT: WglSwapIntervalEXT,
22+
}
23+
24+
impl WglExtra {
25+
pub fn load() -> Result<Self, MissingExtensionFunctionError> {
26+
unsafe {
27+
Ok(Self {
28+
wglCreateContextAttribsARB: transmute(Self::load_fn(
29+
c"wglCreateContextAttribsARB",
30+
)?),
31+
wglChoosePixelFormatARB: transmute(Self::load_fn(c"wglChoosePixelFormatARB")?),
32+
wglSwapIntervalEXT: transmute(Self::load_fn(c"wglSwapIntervalEXT")?),
33+
})
34+
}
35+
}
36+
37+
fn load_fn(
38+
name: &'static CStr,
39+
) -> Result<unsafe extern "system" fn() -> isize, MissingExtensionFunctionError> {
40+
unsafe { wglGetProcAddress(name.as_ptr() as *const u8) }
41+
.ok_or_else(|| MissingExtensionFunctionError { name })
42+
}
43+
}
44+
45+
#[derive(Debug)]
46+
pub struct MissingExtensionFunctionError {
47+
name: &'static CStr,
48+
}
49+
50+
impl Display for MissingExtensionFunctionError {
51+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
52+
write!(f, "Missing WGL function extension: {}", self.name.to_string_lossy())
53+
}
54+
}

0 commit comments

Comments
 (0)