Skip to content

Commit db0b8ed

Browse files
committed
wip
1 parent 962c20e commit db0b8ed

5 files changed

Lines changed: 215 additions & 112 deletions

File tree

src/platform/win/gl.rs

Lines changed: 50 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use std::ffi::{c_void, CString, OsStr};
2-
use std::os::windows::ffi::OsStrExt;
1+
use std::ffi::{c_void, CString};
32
use std::rc::Rc;
43
use windows_sys::{
54
core::s,
@@ -15,17 +14,12 @@ use windows_sys::{
1514
},
1615
},
1716
System::LibraryLoader::{GetProcAddress, LoadLibraryA},
18-
UI::WindowsAndMessaging::{
19-
CreateWindowExW, DefWindowProcW, DestroyWindow, RegisterClassW, UnregisterClassW,
20-
CS_OWNDC, CW_USEDEFAULT, WNDCLASSW,
21-
},
17+
UI::WindowsAndMessaging::{DestroyWindow, UnregisterClassW},
2218
},
2319
};
2420

2521
use crate::gl::*;
26-
use crate::wrappers::win32::h_instance::HInstance;
27-
use crate::wrappers::win32::uuid::Uuid;
28-
use crate::wrappers::win32::window::HWnd;
22+
use crate::wrappers::win32::window::{with_dummy_window, HWnd, PixelFormat};
2923
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_create_context.txt
3024

3125
type WglCreateContextAttribsARB = extern "system" fn(HDC, HGLRC, *const i32) -> HGLRC;
@@ -70,9 +64,37 @@ const WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: i32 = 0x20A9;
7064

7165
type WglSwapIntervalEXT = extern "system" fn(i32) -> i32;
7266

73-
pub type CreationFailedError = ();
67+
pub type CreationFailedError = windows_core::Error;
7468
pub type GlContext = Rc<GlContextInner>;
7569

70+
impl From<CreationFailedError> for GlError {
71+
fn from(e: CreationFailedError) -> Self {
72+
GlError::CreationFailed(e)
73+
}
74+
}
75+
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+
7698
pub struct GlContextInner {
7799
hwnd: HWND,
78100
hdc: HDC,
@@ -84,97 +106,21 @@ impl GlContextInner {
84106
pub unsafe fn create(window: HWnd, config: GlConfig) -> Result<Self, GlError> {
85107
// Create temporary window and context to load function pointers
86108

87-
let class_name_str = format!("raw-gl-context-window-{}", Uuid::new());
88-
let mut class_name: Vec<u16> = OsStr::new(&class_name_str).encode_wide().collect();
89-
class_name.push(0);
90-
91-
let hinstance = HInstance::get_from_dll();
92-
93-
let wnd_class = WNDCLASSW {
94-
style: CS_OWNDC,
95-
lpfnWndProc: Some(DefWindowProcW),
96-
hInstance: hinstance.as_raw(),
97-
lpszClassName: class_name.as_ptr(),
98-
..std::mem::zeroed()
99-
};
100-
101-
let class = RegisterClassW(&wnd_class);
102-
if class == 0 {
103-
return Err(GlError::CreationFailed(()));
104-
}
105-
106-
let hwnd_tmp = CreateWindowExW(
107-
0,
108-
class as *const _,
109-
[0].as_ptr(),
110-
0,
111-
CW_USEDEFAULT,
112-
CW_USEDEFAULT,
113-
CW_USEDEFAULT,
114-
CW_USEDEFAULT,
115-
std::ptr::null_mut(),
116-
std::ptr::null_mut(),
117-
hinstance.as_raw(),
118-
std::ptr::null_mut(),
119-
);
120-
121-
if hwnd_tmp.is_null() {
122-
return Err(GlError::CreationFailed(()));
123-
}
109+
let extra = with_dummy_window(|hwnd_tmp| {
110+
let hdc = hwnd_tmp.get_own_dc()?;
111+
hdc.set_pixel_format(&PixelFormat::default())?;
124112

125-
let hdc_tmp = GetDC(hwnd_tmp);
126-
127-
let pfd_tmp = PIXELFORMATDESCRIPTOR {
128-
nSize: std::mem::size_of::<PIXELFORMATDESCRIPTOR>() as u16,
129-
nVersion: 1,
130-
dwFlags: PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
131-
iPixelType: PFD_TYPE_RGBA,
132-
cColorBits: 32,
133-
cAlphaBits: 8,
134-
cDepthBits: 24,
135-
cStencilBits: 8,
136-
iLayerType: PFD_MAIN_PLANE as u8,
137-
..std::mem::zeroed()
138-
};
139-
140-
SetPixelFormat(hdc_tmp, ChoosePixelFormat(hdc_tmp, &pfd_tmp), &pfd_tmp);
141-
142-
let hglrc_tmp = wglCreateContext(hdc_tmp);
143-
if hglrc_tmp.is_null() {
144-
ReleaseDC(hwnd_tmp, hdc_tmp);
145-
UnregisterClassW(class as *const _, hinstance.as_raw());
146-
DestroyWindow(hwnd_tmp);
147-
return Err(GlError::CreationFailed(()));
148-
}
113+
let wgl_ctx = hdc.create_wgl_context()?;
114+
wgl_ctx.make_current(&hdc)?;
149115

150-
wglMakeCurrent(hdc_tmp, hglrc_tmp);
151-
152-
#[allow(non_snake_case)]
153-
let wglCreateContextAttribsARB: Option<WglCreateContextAttribsARB> = {
154-
wglGetProcAddress(s!("wglCreateContextAttribsARB"))
155-
.map(|addr| std::mem::transmute(addr))
156-
};
157-
158-
#[allow(non_snake_case)]
159-
let wglChoosePixelFormatARB: Option<WglChoosePixelFormatARB> = {
160-
wglGetProcAddress(s!("wglChoosePixelFormatARB")).map(|addr| std::mem::transmute(addr))
161-
};
162-
163-
#[allow(non_snake_case)]
164-
let wglSwapIntervalEXT: Option<WglSwapIntervalEXT> =
165-
{ wglGetProcAddress(s!("wglSwapIntervalEXT")).map(|addr| std::mem::transmute(addr)) };
166-
167-
wglMakeCurrent(hdc_tmp, std::ptr::null_mut());
168-
wglDeleteContext(hglrc_tmp);
169-
ReleaseDC(hwnd_tmp, hdc_tmp);
170-
UnregisterClassW(class as *const _, hinstance.as_raw());
171-
DestroyWindow(hwnd_tmp);
116+
Ok(WglExtra::load())
117+
})?;
172118

173119
// Create actual context
174120

175121
let hwnd = window.as_raw();
176122

177-
let hdc = GetDC(hwnd);
123+
let hdc = window.get_own_dc()?;
178124

179125
// Try to choose pixel format with requested config
180126
#[rustfmt::skip]
@@ -198,7 +144,7 @@ impl GlContextInner {
198144

199145
let mut pixel_format = 0;
200146
let mut num_formats = 0;
201-
wglChoosePixelFormatARB.unwrap()(
147+
extra.wglChoosePixelFormatARB.unwrap()(
202148
hdc,
203149
pixel_format_attribs.as_ptr(),
204150
std::ptr::null(),
@@ -230,7 +176,7 @@ impl GlContextInner {
230176
0,
231177
];
232178

233-
wglChoosePixelFormatARB.unwrap()(
179+
extra.wglChoosePixelFormatARB.unwrap()(
234180
hdc,
235181
pixel_format_attribs_fallback.as_ptr(),
236182
std::ptr::null(),
@@ -262,6 +208,8 @@ impl GlContextInner {
262208
return Err(GlError::CreationFailed(()));
263209
}
264210

211+
hdc.set_pixel_format_from_index(pixel_format)?;
212+
265213
let mut pfd: PIXELFORMATDESCRIPTOR = std::mem::zeroed();
266214
DescribePixelFormat(
267215
hdc,
@@ -284,16 +232,19 @@ impl GlContextInner {
284232
0
285233
];
286234

287-
let hglrc =
288-
wglCreateContextAttribsARB.unwrap()(hdc, std::ptr::null_mut(), ctx_attribs.as_ptr());
235+
let hglrc = extra.wglCreateContextAttribsARB.unwrap()(
236+
hdc,
237+
std::ptr::null_mut(),
238+
ctx_attribs.as_ptr(),
239+
);
289240
if hglrc.is_null() {
290241
return Err(GlError::CreationFailed(()));
291242
}
292243

293244
let gl_library = LoadLibraryA(s!("opengl32.dll"));
294245

295246
wglMakeCurrent(hdc, hglrc);
296-
wglSwapIntervalEXT.unwrap()(config.vsync as i32);
247+
extra.wglSwapIntervalEXT.unwrap()(config.vsync as i32);
297248
wglMakeCurrent(hdc, std::ptr::null_mut());
298249

299250
Ok(Self { hwnd, hdc, hglrc, gl_library })

src/wrappers/win32/window.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ pub fn with_dummy_window<T>(handler: impl FnOnce(HWnd) -> Result<T>) -> Result<T
109109
)
110110
};
111111

112-
if hwnd.is_null() {
113-
return Err(Error::from_thread());
114-
}
112+
let Some(hwnd) = NonNull::new(hwnd) else { return Err(Error::from_thread()) };
113+
// SAFETY: This Hwnd is valid since it came from CreateWindowExW
114+
let hwnd = unsafe { HWnd::from_raw(hwnd) };
115115

116116
handler(hwnd)
117117
}

0 commit comments

Comments
 (0)