1+ #![ allow( non_snake_case) ]
2+
13use crate :: gl:: { GlConfig , Profile } ;
4+ use crate :: tracing:: warn;
25use crate :: wrappers:: win32:: window:: OwnDeviceContext ;
36use std:: ffi:: { c_void, CStr } ;
47use std:: fmt:: { Display , Formatter } ;
58use std:: mem:: transmute;
69use std:: num:: NonZeroI32 ;
710use std:: ptr:: { null_mut, NonNull } ;
811use windows_core:: Error ;
12+ use windows_sys:: s;
13+ use windows_sys:: Win32 :: Foundation :: PROC ;
914use windows_sys:: Win32 :: Graphics :: Gdi :: HDC ;
1015use windows_sys:: Win32 :: Graphics :: OpenGL :: {
1116 wglDeleteContext, wglGetCurrentContext, wglGetProcAddress, wglMakeCurrent, HGLRC ,
@@ -74,8 +79,14 @@ impl WglContext {
7479
7580impl Drop for WglContext {
7681 fn drop ( & mut self ) {
77- let _ = unsafe { self . make_not_current ( ) } ;
78- unsafe { wglDeleteContext ( self . inner . as_ptr ( ) ) } ; // TODO: warn on error
82+ if let Err ( e) = unsafe { self . make_not_current ( ) } {
83+ warn ! ( "Could not unset current GL context {}" , e) ;
84+ }
85+
86+ let result = unsafe { wglDeleteContext ( self . inner . as_ptr ( ) ) } ;
87+ if result == 0 {
88+ warn ! ( "Could not delete GL context: {}" , Error :: from_thread( ) ) ;
89+ }
7990 }
8091}
8192
@@ -89,42 +100,35 @@ type WglChoosePixelFormatARB =
89100// See https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_create_context.txt
90101type WglCreateContextAttribsARB = unsafe extern "system" fn ( HDC , HGLRC , * const i32 ) -> HGLRC ;
91102
92- #[ allow( non_snake_case) ]
93103pub struct WglExtra {
94- wglCreateContextAttribsARB : WglCreateContextAttribsARB ,
95- wglChoosePixelFormatARB : WglChoosePixelFormatARB ,
96- wglSwapIntervalEXT : WglSwapIntervalEXT ,
104+ wglCreateContextAttribsARB : Option < WglCreateContextAttribsARB > ,
105+ wglChoosePixelFormatARB : Option < WglChoosePixelFormatARB > ,
106+ wglSwapIntervalEXT : Option < WglSwapIntervalEXT > ,
97107}
98108
99109impl WglExtra {
100- pub fn load ( ) -> Result < Self , MissingExtensionFunctionError > {
110+ pub fn load ( ) -> Self {
101111 unsafe {
102- Ok ( Self {
103- wglCreateContextAttribsARB : transmute :: < * const c_void , WglCreateContextAttribsARB > (
104- Self :: load_fn ( c "wglCreateContextAttribsARB") ? ,
112+ Self {
113+ wglCreateContextAttribsARB : transmute :: < PROC , Option < WglCreateContextAttribsARB > > (
114+ wglGetProcAddress ( s ! ( "wglCreateContextAttribsARB" ) ) ,
105115 ) ,
106- wglChoosePixelFormatARB : transmute :: < * const c_void , WglChoosePixelFormatARB > (
107- Self :: load_fn ( c "wglChoosePixelFormatARB") ? ,
116+ wglChoosePixelFormatARB : transmute :: < PROC , Option < WglChoosePixelFormatARB > > (
117+ wglGetProcAddress ( s ! ( "wglChoosePixelFormatARB" ) ) ,
108118 ) ,
109- wglSwapIntervalEXT : transmute :: < * const c_void , WglSwapIntervalEXT > ( Self :: load_fn (
110- c"wglSwapIntervalEXT" ,
111- ) ?) ,
112- } )
113- }
114- }
115-
116- fn load_fn ( name : & ' static CStr ) -> Result < * const c_void , MissingExtensionFunctionError > {
117- let ptr = unsafe { wglGetProcAddress ( name. as_ptr ( ) as * const u8 ) } ;
118-
119- match ptr {
120- Some ( ptr) => Ok ( ptr as * const c_void ) ,
121- None => Err ( MissingExtensionFunctionError { name } ) ,
119+ wglSwapIntervalEXT : transmute :: < PROC , Option < WglSwapIntervalEXT > > (
120+ wglGetProcAddress ( s ! ( "wglSwapIntervalEXT" ) ) ,
121+ ) ,
122+ }
122123 }
123124 }
124125
125126 pub fn create_context_for_config (
126127 & self , dc : & OwnDeviceContext , config : & GlConfig ,
127- ) -> windows_core:: Result < WglContext > {
128+ ) -> Result < WglContext , CreateContextError > {
129+ let Some ( wglCreateContextAttribsARB) = self . wglCreateContextAttribsARB else {
130+ return Err ( CreateContextError :: Unavailable ) ;
131+ } ;
128132 let profile_mask = match config. profile {
129133 Profile :: Core => WGL_CONTEXT_CORE_PROFILE_BIT_ARB ,
130134 Profile :: Compatibility => WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ,
@@ -138,17 +142,22 @@ impl WglExtra {
138142 0
139143 ] ;
140144
141- let ctx = unsafe {
142- ( self . wglCreateContextAttribsARB ) ( dc. as_raw ( ) , null_mut ( ) , ctx_attribs. as_ptr ( ) )
143- } ;
145+ let ctx =
146+ unsafe { wglCreateContextAttribsARB ( dc. as_raw ( ) , null_mut ( ) , ctx_attribs. as_ptr ( ) ) } ;
144147
145- let ctx = NonNull :: new ( ctx) . ok_or_else ( Error :: from_thread) ?;
148+ let ctx =
149+ NonNull :: new ( ctx) . ok_or_else ( || CreateContextError :: Win32 ( Error :: from_thread ( ) ) ) ?;
146150
147151 Ok ( WglContext { inner : ctx } )
148152 }
149153
150154 pub fn set_vsync ( & self , vsync : bool ) -> windows_core:: Result < ( ) > {
151- let result = unsafe { ( self . wglSwapIntervalEXT ) ( vsync. into ( ) ) } ;
155+ let Some ( wglSwapIntervalEXT) = self . wglSwapIntervalEXT else {
156+ warn ! ( "Could not set vsync: wglSwapIntervalEXT is not available" ) ;
157+ return Ok ( ( ) ) ;
158+ } ;
159+
160+ let result = unsafe { wglSwapIntervalEXT ( vsync. into ( ) ) } ;
152161 if result == 0 {
153162 return Err ( Error :: from_thread ( ) ) ;
154163 }
@@ -158,11 +167,15 @@ impl WglExtra {
158167
159168 pub fn choose_pixel_format_from_attribs (
160169 & self , attribs : & PixelFormatAttribs , dc : & OwnDeviceContext ,
161- ) -> windows_core:: Result < Option < NonZeroI32 > > {
170+ ) -> Result < Option < NonZeroI32 > , ChoosePixelFormatFromAttribsError > {
171+ let Some ( wglChoosePixelFormatARB) = self . wglChoosePixelFormatARB else {
172+ return Err ( ChoosePixelFormatFromAttribsError :: Unavailable ) ;
173+ } ;
174+
162175 let mut pixel_formats = [ 0 ] ;
163176 let mut num_formats = 0 ;
164177 let result = unsafe {
165- ( self . wglChoosePixelFormatARB ) (
178+ wglChoosePixelFormatARB (
166179 dc. as_raw ( ) ,
167180 attribs. inner . as_ptr ( ) ,
168181 std:: ptr:: null ( ) ,
@@ -173,7 +186,7 @@ impl WglExtra {
173186 } ;
174187
175188 if result == 0 {
176- return Err ( Error :: from_thread ( ) ) ;
189+ return Err ( ChoosePixelFormatFromAttribsError :: Win32 ( Error :: from_thread ( ) ) ) ;
177190 }
178191
179192 if num_formats == 0 {
@@ -184,6 +197,38 @@ impl WglExtra {
184197 }
185198}
186199
200+ pub enum CreateContextError {
201+ Win32 ( Error ) ,
202+ Unavailable ,
203+ }
204+
205+ impl Display for CreateContextError {
206+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
207+ match self {
208+ CreateContextError :: Win32 ( err) => Display :: fmt ( err, f) ,
209+ CreateContextError :: Unavailable => {
210+ f. write_str ( "wglCreateContextAttribsARB is not available" )
211+ }
212+ }
213+ }
214+ }
215+
216+ pub enum ChoosePixelFormatFromAttribsError {
217+ Win32 ( Error ) ,
218+ Unavailable ,
219+ }
220+
221+ impl Display for ChoosePixelFormatFromAttribsError {
222+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
223+ match self {
224+ ChoosePixelFormatFromAttribsError :: Win32 ( e) => Display :: fmt ( e, f) ,
225+ ChoosePixelFormatFromAttribsError :: Unavailable => {
226+ f. write_str ( "wglChoosePixelFormatARB is not available" )
227+ }
228+ }
229+ }
230+ }
231+
187232const WGL_DRAW_TO_WINDOW_ARB : i32 = 0x2001 ;
188233const WGL_ACCELERATION_ARB : i32 = 0x2003 ;
189234const WGL_SUPPORT_OPENGL_ARB : i32 = 0x2010 ;
0 commit comments