@@ -2,22 +2,21 @@ use platform::NativeGLContextMethods;
2
2
use std:: ffi:: CString ;
3
3
use std:: os:: raw:: c_void;
4
4
use std:: ptr;
5
- use std:: sync:: { Once , ONCE_INIT } ;
6
5
7
6
use winapi;
8
7
use user32;
9
8
use kernel32;
10
9
use super :: wgl;
11
10
use super :: wgl_attributes:: * ;
12
- use gleam :: gl ;
11
+ use super :: utils ;
13
12
14
- /// Wrapper to satisfy `Sync`.
13
+ // Wrappers to satisfy `Sync`.
15
14
struct HMODULEWrapper ( winapi:: HMODULE ) ;
16
15
unsafe impl Sync for HMODULEWrapper { }
17
16
18
17
lazy_static ! {
19
18
static ref GL_LIB : Option <HMODULEWrapper > = {
20
- let p = unsafe { kernel32:: LoadLibraryA ( b"opengl32.dll\0 " . as_ptr( ) as * const _) } ;
19
+ let p = unsafe { kernel32:: LoadLibraryA ( b"opengl32.dll\0 " . as_ptr( ) as * const _) } ;
21
20
if p. is_null( ) {
22
21
error!( "WGL: opengl32.dll not found!" ) ;
23
22
None
@@ -26,13 +25,23 @@ lazy_static! {
26
25
Some ( HMODULEWrapper ( p) )
27
26
}
28
27
} ;
29
- }
30
28
31
- static LOAD_GL : Once = ONCE_INIT ;
32
- pub fn load_gl ( ) {
33
- LOAD_GL . call_once ( || {
34
- gl:: load_with ( |s| NativeGLContext :: get_proc_address ( s) as * const _ ) ;
35
- } ) ;
29
+ static ref PROC_ADDR_CTX : Option <NativeGLContext > = {
30
+ match unsafe { utils:: create_offscreen( ptr:: null_mut( ) , & WGLAttributes :: default ( ) ) } {
31
+ Ok ( ref res) => {
32
+ let ctx = NativeGLContext {
33
+ render_ctx: res. 0 ,
34
+ device_ctx: res. 1 ,
35
+ weak: false ,
36
+ } ;
37
+ Some ( ctx)
38
+ }
39
+ Err ( s) => {
40
+ error!( "Error creating GetProcAddress helper context: {}" , s) ;
41
+ None
42
+ }
43
+ }
44
+ } ;
36
45
}
37
46
38
47
pub struct NativeGLContext {
@@ -54,8 +63,12 @@ impl Drop for NativeGLContext {
54
63
}
55
64
}
56
65
66
+ unsafe impl Send for NativeGLContext { }
67
+ unsafe impl Sync for NativeGLContext { }
68
+
57
69
pub struct NativeGLContextHandle ( winapi:: HGLRC , winapi:: HDC ) ;
58
70
unsafe impl Send for NativeGLContextHandle { }
71
+ unsafe impl Sync for NativeGLContextHandle { }
59
72
60
73
impl NativeGLContextMethods for NativeGLContext {
61
74
type Handle = NativeGLContextHandle ;
@@ -64,10 +77,27 @@ impl NativeGLContextMethods for NativeGLContext {
64
77
let addr = CString :: new ( addr. as_bytes ( ) ) . unwrap ( ) ;
65
78
let addr = addr. as_ptr ( ) ;
66
79
unsafe {
80
+
81
+ if wgl:: GetCurrentContext ( ) . is_null ( ) {
82
+ // wglGetProcAddress only works in the presence of a valid GL context
83
+ // We use a dummy ctx when the caller calls this function without a valid GL context
84
+ if let Some ( ref ctx) = * PROC_ADDR_CTX {
85
+ if ctx. make_current ( ) . is_err ( ) {
86
+ return ptr:: null_mut ( ) ;
87
+ }
88
+ } else {
89
+ return ptr:: null_mut ( ) ;
90
+ }
91
+ }
92
+
67
93
let p = wgl:: GetProcAddress ( addr) as * const _ ;
68
94
if !p. is_null ( ) {
69
95
return p;
70
96
}
97
+ // wglGetProcAddress doesn't return function pointers for some legacy functions,
98
+ // (the ones coming from OpenGL 1.1)
99
+ // These functions are exported by the opengl32.dll itself,
100
+ // so we have to fallback to kernel32 getProcAddress if wglGetProcAddress return null
71
101
match * GL_LIB {
72
102
Some ( ref lib) => kernel32:: GetProcAddress ( lib. 0 , addr) as * const _ ,
73
103
None => ptr:: null_mut ( ) ,
@@ -81,17 +111,15 @@ impl NativeGLContextMethods for NativeGLContext {
81
111
Some ( ref handle) => handle. 0 ,
82
112
None => ptr:: null_mut ( ) ,
83
113
} ;
84
- match unsafe { super :: utils:: create_offscreen ( render_ctx, & WGLAttributes :: default ( ) ) } {
114
+ match unsafe { utils:: create_offscreen ( render_ctx, & WGLAttributes :: default ( ) ) } {
85
115
Ok ( ref res) => {
86
- // wglGetProcAddress only works in the presence of a valid GL context
87
- // OpenGL functions must be loaded after the first context is created
116
+
88
117
let ctx = NativeGLContext {
89
118
render_ctx : res. 0 ,
90
119
device_ctx : res. 1 ,
91
120
weak : false ,
92
121
} ;
93
122
ctx. make_current ( ) . unwrap ( ) ;
94
- load_gl ( ) ;
95
123
Ok ( ctx)
96
124
}
97
125
Err ( s) => {
0 commit comments