Skip to content

Commit ca5fce1

Browse files
committed
Use a dummy context for wglGetProcAddress when needed instead of loading gl symbols after a context creation: wglGetProcAddress only works in the presence of a valid GL context, so we use a dummy ctx when the caller calls wglGetProcAddress without a valid GL context bound
1 parent a949520 commit ca5fce1

File tree

1 file changed

+42
-14
lines changed

1 file changed

+42
-14
lines changed

src/platform/with_wgl/native_gl_context.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,21 @@ use platform::NativeGLContextMethods;
22
use std::ffi::CString;
33
use std::os::raw::c_void;
44
use std::ptr;
5-
use std::sync::{Once, ONCE_INIT};
65

76
use winapi;
87
use user32;
98
use kernel32;
109
use super::wgl;
1110
use super::wgl_attributes::*;
12-
use gleam::gl;
11+
use super::utils;
1312

14-
/// Wrapper to satisfy `Sync`.
13+
// Wrappers to satisfy `Sync`.
1514
struct HMODULEWrapper(winapi::HMODULE);
1615
unsafe impl Sync for HMODULEWrapper {}
1716

1817
lazy_static! {
1918
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 _) };
2120
if p.is_null() {
2221
error!("WGL: opengl32.dll not found!");
2322
None
@@ -26,13 +25,23 @@ lazy_static! {
2625
Some(HMODULEWrapper(p))
2726
}
2827
};
29-
}
3028

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+
};
3645
}
3746

3847
pub struct NativeGLContext {
@@ -54,8 +63,12 @@ impl Drop for NativeGLContext {
5463
}
5564
}
5665

66+
unsafe impl Send for NativeGLContext {}
67+
unsafe impl Sync for NativeGLContext {}
68+
5769
pub struct NativeGLContextHandle(winapi::HGLRC, winapi::HDC);
5870
unsafe impl Send for NativeGLContextHandle {}
71+
unsafe impl Sync for NativeGLContextHandle {}
5972

6073
impl NativeGLContextMethods for NativeGLContext {
6174
type Handle = NativeGLContextHandle;
@@ -64,10 +77,27 @@ impl NativeGLContextMethods for NativeGLContext {
6477
let addr = CString::new(addr.as_bytes()).unwrap();
6578
let addr = addr.as_ptr();
6679
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+
6793
let p = wgl::GetProcAddress(addr) as *const _;
6894
if !p.is_null() {
6995
return p;
7096
}
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
71101
match *GL_LIB {
72102
Some(ref lib) => kernel32::GetProcAddress(lib.0, addr) as *const _,
73103
None => ptr::null_mut(),
@@ -81,17 +111,15 @@ impl NativeGLContextMethods for NativeGLContext {
81111
Some(ref handle) => handle.0,
82112
None => ptr::null_mut(),
83113
};
84-
match unsafe { super::utils::create_offscreen(render_ctx, &WGLAttributes::default()) } {
114+
match unsafe { utils::create_offscreen(render_ctx, &WGLAttributes::default()) } {
85115
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+
88117
let ctx = NativeGLContext {
89118
render_ctx: res.0,
90119
device_ctx: res.1,
91120
weak: false,
92121
};
93122
ctx.make_current().unwrap();
94-
load_gl();
95123
Ok(ctx)
96124
}
97125
Err(s) => {

0 commit comments

Comments
 (0)