Use the gl_generator macro to generate the bindings for WGL

This commit is contained in:
Tomaka17 2014-09-12 15:51:43 +02:00
parent 3043cb2848
commit 2af367b55c
5 changed files with 52 additions and 67 deletions

View file

@ -10,5 +10,5 @@ git = "https://github.com/huonw/compile_msg"
[dependencies.android_glue] [dependencies.android_glue]
git = "https://github.com/tomaka/android-rs-glue" git = "https://github.com/tomaka/android-rs-glue"
[dev-dependencies.gl_generator] [dependencies.gl_generator]
git = "https://github.com/bjz/gl-rs" git = "https://github.com/bjz/gl-rs"

View file

@ -19,6 +19,7 @@
//! will look and behave. //! will look and behave.
#[phase(plugin)] extern crate compile_msg; #[phase(plugin)] extern crate compile_msg;
#[phase(plugin)] extern crate gl_generator;
extern crate libc; extern crate libc;
pub use events::*; pub use events::*;

View file

@ -5,6 +5,16 @@
use libc; use libc;
/// WGL bindings
pub mod wgl {
generate_gl_bindings!("wgl", "core", "1.0", "static")
}
/// Functions that are not necessarly always available
pub mod wgl_extra {
generate_gl_bindings!("wgl", "core", "1.0", "struct", [ "WGL_ARB_create_context" ])
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
// we don't define the T types to ensure that A/W functions are used // we don't define the T types to ensure that A/W functions are used
pub type ATOM = WORD; pub type ATOM = WORD;
@ -32,7 +42,7 @@ pub type LPSTR = *mut libc::c_char;
pub type LPVOID = *mut libc::c_void; pub type LPVOID = *mut libc::c_void;
pub type LPWSTR = *mut WCHAR; pub type LPWSTR = *mut WCHAR;
pub type LRESULT = LONG_PTR; pub type LRESULT = LONG_PTR;
pub type PVOID = *mut libc::c_void; pub type PVOID = *const libc::c_void;
pub type UINT = libc::c_uint; pub type UINT = libc::c_uint;
pub type UINT_PTR = int; pub type UINT_PTR = int;
pub type WCHAR = libc::wchar_t; pub type WCHAR = libc::wchar_t;
@ -385,17 +395,6 @@ pub static VK_NONAME: WPARAM = 0xFC;
pub static VK_PA1: WPARAM = 0xFD; pub static VK_PA1: WPARAM = 0xFD;
pub static VK_OEM_CLEAR: WPARAM = 0xFE; pub static VK_OEM_CLEAR: WPARAM = 0xFE;
// ?
pub static WGL_CONTEXT_DEBUG_BIT_ARB: libc::c_int = 0x00000001;
pub static WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB: libc::c_int = 0x00000002;
pub static WGL_CONTEXT_MAJOR_VERSION_ARB: libc::c_int = 0x2091;
pub static WGL_CONTEXT_MINOR_VERSION_ARB: libc::c_int = 0x2092;
pub static WGL_CONTEXT_LAYER_PLANE_ARB: libc::c_int = 0x2093;
pub static WGL_CONTEXT_FLAGS_ARB: libc::c_int = 0x2094;
pub static WGL_CONTEXT_PROFILE_MASK_ARB: libc::c_int = 0x9126;
pub static WGL_CONTEXT_CORE_PROFILE_BIT_ARB: libc::c_int = 0x00000001;
pub static WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: libc::c_int = 0x00000002;
// messages // messages
pub static WM_LBUTTONDOWN: UINT = 0x0201; pub static WM_LBUTTONDOWN: UINT = 0x0201;
pub static WM_LBUTTONUP: UINT = 0x0202; pub static WM_LBUTTONUP: UINT = 0x0202;
@ -766,16 +765,4 @@ extern "system" {
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644956(v=vs.85).aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/ms644956(v=vs.85).aspx
pub fn WaitMessage() -> BOOL; pub fn WaitMessage() -> BOOL;
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd374379(v=vs.85).aspx
pub fn wglCreateContext(hdc: HDC) -> HGLRC;
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd374381(v=vs.85).aspx
pub fn wglDeleteContext(hglrc: HGLRC);
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd374386(v=vs.85).aspx
pub fn wglGetProcAddress(lpszProc: LPCSTR) -> *const libc::c_void;
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd374387(v=vs.85).aspx
pub fn wglMakeCurrent(hdc: HDC, hglrc: HGLRC);
} }

View file

@ -40,12 +40,12 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
cbClsExtra: 0, cbClsExtra: 0,
cbWndExtra: 0, cbWndExtra: 0,
hInstance: unsafe { ffi::GetModuleHandleW(ptr::null()) }, hInstance: unsafe { ffi::GetModuleHandleW(ptr::null()) },
hIcon: ptr::mut_null(), hIcon: ptr::null(),
hCursor: ptr::mut_null(), hCursor: ptr::null(),
hbrBackground: ptr::mut_null(), hbrBackground: ptr::null(),
lpszMenuName: ptr::null(), lpszMenuName: ptr::null(),
lpszClassName: class_name.as_ptr(), lpszClassName: class_name.as_ptr(),
hIconSm: ptr::mut_null(), hIconSm: ptr::null(),
}; };
// We ignore errors because registering the same window class twice would trigger // We ignore errors because registering the same window class twice would trigger
@ -87,7 +87,7 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
screen_settings.dmFields = ffi::DM_BITSPERPEL | ffi::DM_PELSWIDTH | ffi::DM_PELSHEIGHT; screen_settings.dmFields = ffi::DM_BITSPERPEL | ffi::DM_PELSWIDTH | ffi::DM_PELSHEIGHT;
let result = unsafe { ffi::ChangeDisplaySettingsExW(monitor.get_system_name().as_ptr(), let result = unsafe { ffi::ChangeDisplaySettingsExW(monitor.get_system_name().as_ptr(),
&mut screen_settings, ptr::mut_null(), ffi::CDS_FULLSCREEN, ptr::mut_null()) }; &mut screen_settings, ptr::null(), ffi::CDS_FULLSCREEN, ptr::mut_null()) };
if result != ffi::DISP_CHANGE_SUCCESSFUL { if result != ffi::DISP_CHANGE_SUCCESSFUL {
tx.send(Err(format!("ChangeDisplaySettings failed: {}", result))); tx.send(Err(format!("ChangeDisplaySettings failed: {}", result)));
@ -106,9 +106,9 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
// adjusting the window coordinates using the style // adjusting the window coordinates using the style
unsafe { ffi::AdjustWindowRectEx(&mut rect, style, 0, ex_style) }; unsafe { ffi::AdjustWindowRectEx(&mut rect, style, 0, ex_style) };
// getting the address of wglCreateContextAttribs and the pixel format // getting the address of wglCreateContextAttribsARB and the pixel format
// that we will use // that we will use
let (create_context_attribs, pixel_format) = { let (extra_functions, pixel_format) = {
// creating a dummy invisible window for GL initialization // creating a dummy invisible window for GL initialization
let dummy_window = unsafe { let dummy_window = unsafe {
let handle = ffi::CreateWindowExW(ex_style, class_name.as_ptr(), let handle = ffi::CreateWindowExW(ex_style, class_name.as_ptr(),
@ -116,7 +116,7 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
style | ffi::WS_CLIPSIBLINGS | ffi::WS_CLIPCHILDREN, style | ffi::WS_CLIPSIBLINGS | ffi::WS_CLIPCHILDREN,
ffi::CW_USEDEFAULT, ffi::CW_USEDEFAULT, ffi::CW_USEDEFAULT, ffi::CW_USEDEFAULT,
rect.right - rect.left, rect.bottom - rect.top, rect.right - rect.left, rect.bottom - rect.top,
ptr::mut_null(), ptr::mut_null(), ffi::GetModuleHandleW(ptr::null()), ptr::null(), ptr::null(), ffi::GetModuleHandleW(ptr::null()),
ptr::mut_null()); ptr::mut_null());
if handle.is_null() { if handle.is_null() {
@ -191,7 +191,7 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
// creating the dummy OpenGL context // creating the dummy OpenGL context
let dummy_context = { let dummy_context = {
let ctxt = unsafe { ffi::wglCreateContext(dummy_hdc) }; let ctxt = unsafe { ffi::wgl::CreateContext(dummy_hdc) };
if ctxt.is_null() { if ctxt.is_null() {
tx.send(Err(format!("wglCreateContext function failed: {}", tx.send(Err(format!("wglCreateContext function failed: {}",
os::error_string(os::errno() as uint)))); os::error_string(os::errno() as uint))));
@ -202,33 +202,27 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
}; };
// making context current // making context current
unsafe { ffi::wglMakeCurrent(dummy_hdc, dummy_context); } unsafe { ffi::wgl::MakeCurrent(dummy_hdc, dummy_context); }
// getting the pointer to wglCreateContextAttribs // loading the extra WGL functions
let mut addr = unsafe { ffi::wglGetProcAddress(b"wglCreateContextAttribs".as_ptr() let extra_functions = ffi::wgl_extra::Wgl::load_with(|addr| {
as *const i8) } as *const (); unsafe {
addr.with_c_str(|s| {
if addr.is_null() { use libc;
addr = unsafe { ffi::wglGetProcAddress(b"wglCreateContextAttribsARB".as_ptr() ffi::wgl::GetProcAddress(s) as *const libc::c_void
as *const i8) } as *const (); })
} }
});
// removing current context // removing current context
unsafe { ffi::wglMakeCurrent(ptr::mut_null(), ptr::mut_null()); } unsafe { ffi::wgl::MakeCurrent(ptr::null(), ptr::null()); }
// destroying the context and the window // destroying the context and the window
unsafe { ffi::wglDeleteContext(dummy_context); } unsafe { ffi::wgl::DeleteContext(dummy_context); }
unsafe { ffi::DestroyWindow(dummy_window); } unsafe { ffi::DestroyWindow(dummy_window); }
// returning the address // returning the address
if addr.is_null() { (extra_functions, pixel_format)
(None, pixel_format)
} else {
use libc;
let addr: extern "system" fn(ffi::HDC, ffi::HGLRC, *const libc::c_int) -> ffi::HGLRC
= unsafe { mem::transmute(addr) };
(Some(addr), pixel_format)
}
}; };
// creating the real window this time // creating the real window this time
@ -245,7 +239,7 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
if builder.monitor.is_some() { 0 } else { ffi::CW_USEDEFAULT }, if builder.monitor.is_some() { 0 } else { ffi::CW_USEDEFAULT },
if builder.monitor.is_some() { 0 } else { ffi::CW_USEDEFAULT }, if builder.monitor.is_some() { 0 } else { ffi::CW_USEDEFAULT },
width.unwrap_or(ffi::CW_USEDEFAULT), height.unwrap_or(ffi::CW_USEDEFAULT), width.unwrap_or(ffi::CW_USEDEFAULT), height.unwrap_or(ffi::CW_USEDEFAULT),
ptr::mut_null(), ptr::mut_null(), ffi::GetModuleHandleW(ptr::null()), ptr::null(), ptr::null(), ffi::GetModuleHandleW(ptr::null()),
ptr::mut_null()); ptr::mut_null());
if handle.is_null() { if handle.is_null() {
@ -288,18 +282,20 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
if builder.gl_version.is_some() { if builder.gl_version.is_some() {
let version = builder.gl_version.as_ref().unwrap(); let version = builder.gl_version.as_ref().unwrap();
attributes.push(ffi::WGL_CONTEXT_MAJOR_VERSION_ARB); attributes.push(ffi::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int);
attributes.push(version.val0() as libc::c_int); attributes.push(version.val0() as libc::c_int);
attributes.push(ffi::WGL_CONTEXT_MINOR_VERSION_ARB); attributes.push(ffi::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int);
attributes.push(version.val1() as libc::c_int); attributes.push(version.val1() as libc::c_int);
} }
attributes.push(0); attributes.push(0);
let ctxt = unsafe { let ctxt = unsafe {
match create_context_attribs { if extra_functions.CreateContextAttribsARB.is_loaded() {
None => ffi::wglCreateContext(hdc), extra_functions.CreateContextAttribsARB(hdc, ptr::null(),
Some(ptr) => ptr(hdc, ptr::mut_null(), attributes.as_slice().as_ptr()) attributes.as_slice().as_ptr())
} else {
ffi::wgl::CreateContext(hdc)
} }
}; };
@ -332,7 +328,7 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
if lib.is_null() { if lib.is_null() {
tx.send(Err(format!("LoadLibrary function failed: {}", tx.send(Err(format!("LoadLibrary function failed: {}",
os::error_string(os::errno() as uint)))); os::error_string(os::errno() as uint))));
unsafe { ffi::wglDeleteContext(context); } unsafe { ffi::wgl::DeleteContext(context); }
unsafe { ffi::DestroyWindow(real_window); } unsafe { ffi::DestroyWindow(real_window); }
return; return;
} }
@ -357,7 +353,7 @@ pub fn new_window(builder: WindowBuilder) -> Result<Window, String> {
loop { loop {
let mut msg = unsafe { mem::uninitialized() }; let mut msg = unsafe { mem::uninitialized() };
if unsafe { ffi::GetMessageW(&mut msg, ptr::mut_null(), 0, 0) } == 0 { if unsafe { ffi::GetMessageW(&mut msg, ptr::null(), 0, 0) } == 0 {
break; break;
} }

View file

@ -75,7 +75,7 @@ impl Window {
use libc; use libc;
unsafe { unsafe {
ffi::SetWindowPos(self.window, ptr::mut_null(), x as libc::c_int, y as libc::c_int, ffi::SetWindowPos(self.window, ptr::null(), x as libc::c_int, y as libc::c_int,
0, 0, ffi::SWP_NOZORDER | ffi::SWP_NOSIZE); 0, 0, ffi::SWP_NOZORDER | ffi::SWP_NOSIZE);
ffi::UpdateWindow(self.window); ffi::UpdateWindow(self.window);
} }
@ -116,7 +116,7 @@ impl Window {
use libc; use libc;
unsafe { unsafe {
ffi::SetWindowPos(self.window, ptr::mut_null(), 0, 0, x as libc::c_int, ffi::SetWindowPos(self.window, ptr::null(), 0, 0, x as libc::c_int,
y as libc::c_int, ffi::SWP_NOZORDER | ffi::SWP_NOREPOSITION); y as libc::c_int, ffi::SWP_NOZORDER | ffi::SWP_NOREPOSITION);
ffi::UpdateWindow(self.window); ffi::UpdateWindow(self.window);
} }
@ -172,7 +172,8 @@ impl Window {
/// See the docs in the crate root file. /// See the docs in the crate root file.
pub unsafe fn make_current(&self) { pub unsafe fn make_current(&self) {
ffi::wglMakeCurrent(self.hdc, self.context) // TODO: check return value
ffi::wgl::MakeCurrent(self.hdc, self.context);
} }
/// See the docs in the crate root file. /// See the docs in the crate root file.
@ -181,7 +182,7 @@ impl Window {
unsafe { unsafe {
addr.with_c_str(|s| { addr.with_c_str(|s| {
let p = ffi::wglGetProcAddress(s) as *const (); let p = ffi::wgl::GetProcAddress(s) as *const ();
if !p.is_null() { return p; } if !p.is_null() { return p; }
ffi::GetProcAddress(self.gl_library, s) as *const () ffi::GetProcAddress(self.gl_library, s) as *const ()
}) })
@ -203,8 +204,8 @@ impl Window {
impl Drop for Window { impl Drop for Window {
fn drop(&mut self) { fn drop(&mut self) {
use std::ptr; use std::ptr;
unsafe { ffi::wglMakeCurrent(ptr::mut_null(), ptr::mut_null()); } unsafe { ffi::wgl::MakeCurrent(ptr::null(), ptr::null()); }
unsafe { ffi::wglDeleteContext(self.context); } unsafe { ffi::wgl::DeleteContext(self.context); }
unsafe { ffi::DestroyWindow(self.window); } unsafe { ffi::DestroyWindow(self.window); }
} }
} }