1- use std:: ffi:: { c_void, CString , OsStr } ;
2- use std:: os:: windows:: ffi:: OsStrExt ;
1+ use std:: ffi:: { c_void, CString } ;
32use std:: rc:: Rc ;
43use 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
2521use 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
3125type WglCreateContextAttribsARB = extern "system" fn ( HDC , HGLRC , * const i32 ) -> HGLRC ;
@@ -70,9 +64,37 @@ const WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: i32 = 0x20A9;
7064
7165type WglSwapIntervalEXT = extern "system" fn ( i32 ) -> i32 ;
7266
73- pub type CreationFailedError = ( ) ;
67+ pub type CreationFailedError = windows_core :: Error ;
7468pub 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+
7698pub 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 } )
0 commit comments