mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-12 21:51:32 +11:00
Now using wglCreateContextAttribs when available
This commit is contained in:
parent
21c8ffab80
commit
959613870c
|
@ -107,8 +107,108 @@ pub fn new_window(dimensions: Option<(uint, uint)>, title: &str,
|
||||||
// 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) };
|
||||||
|
|
||||||
// creating the window
|
// getting the address of wglCreateContextAttribs and the pixel format
|
||||||
let handle = unsafe {
|
// that we will use
|
||||||
|
let (create_context_attribs, pixel_format) = {
|
||||||
|
// creating a dummy invisible window for GL initialization
|
||||||
|
let dummy_window = unsafe {
|
||||||
|
let handle = ffi::CreateWindowExW(ex_style, class_name.as_ptr(),
|
||||||
|
title.as_ptr() as ffi::LPCWSTR,
|
||||||
|
style | ffi::WS_CLIPSIBLINGS | ffi::WS_CLIPCHILDREN,
|
||||||
|
ffi::CW_USEDEFAULT, ffi::CW_USEDEFAULT,
|
||||||
|
rect.right - rect.left, rect.bottom - rect.top,
|
||||||
|
ptr::mut_null(), ptr::mut_null(), ffi::GetModuleHandleW(ptr::null()),
|
||||||
|
ptr::mut_null());
|
||||||
|
|
||||||
|
if handle.is_null() {
|
||||||
|
use std::os;
|
||||||
|
tx.send(Err(format!("CreateWindowEx function failed: {}",
|
||||||
|
os::error_string(os::errno() as uint))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle
|
||||||
|
};
|
||||||
|
|
||||||
|
// getting the HDC of the dummy window
|
||||||
|
let dummy_hdc = {
|
||||||
|
let hdc = unsafe { ffi::GetDC(dummy_window) };
|
||||||
|
if hdc.is_null() {
|
||||||
|
tx.send(Err(format!("GetDC function failed: {}",
|
||||||
|
os::error_string(os::errno() as uint))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hdc
|
||||||
|
};
|
||||||
|
|
||||||
|
// getting the pixel format that we will use
|
||||||
|
// TODO: use something cleaner which uses hints
|
||||||
|
let pixel_format = {
|
||||||
|
let mut output: ffi::PIXELFORMATDESCRIPTOR = unsafe { mem::uninitialized() };
|
||||||
|
|
||||||
|
if unsafe { ffi::DescribePixelFormat(dummy_hdc, 1,
|
||||||
|
mem::size_of::<ffi::PIXELFORMATDESCRIPTOR>() as ffi::UINT, &mut output) } == 0
|
||||||
|
{
|
||||||
|
tx.send(Err(format!("DescribePixelFormat function failed: {}",
|
||||||
|
os::error_string(os::errno() as uint))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
};
|
||||||
|
|
||||||
|
// calling SetPixelFormat
|
||||||
|
unsafe {
|
||||||
|
if ffi::SetPixelFormat(dummy_hdc, 1, &pixel_format) == 0 {
|
||||||
|
tx.send(Err(format!("SetPixelFormat function failed: {}",
|
||||||
|
os::error_string(os::errno() as uint))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// creating the dummy OpenGL context
|
||||||
|
let dummy_context = {
|
||||||
|
let ctxt = unsafe { ffi::wglCreateContext(dummy_hdc) };
|
||||||
|
if ctxt.is_null() {
|
||||||
|
tx.send(Err(format!("wglCreateContext function failed: {}",
|
||||||
|
os::error_string(os::errno() as uint))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctxt
|
||||||
|
};
|
||||||
|
|
||||||
|
// making context current
|
||||||
|
unsafe { ffi::wglMakeCurrent(dummy_hdc, dummy_context); }
|
||||||
|
|
||||||
|
// getting the pointer to wglCreateContextAttribs
|
||||||
|
let mut addr = unsafe { ffi::wglGetProcAddress(b"wglCreateContextAttribs".as_ptr()
|
||||||
|
as *const i8) } as *const ();
|
||||||
|
|
||||||
|
if addr.is_null() {
|
||||||
|
addr = unsafe { ffi::wglGetProcAddress(b"wglCreateContextAttribsARB".as_ptr()
|
||||||
|
as *const i8) } as *const ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// removing current context
|
||||||
|
unsafe { ffi::wglMakeCurrent(ptr::mut_null(), ptr::mut_null()); }
|
||||||
|
|
||||||
|
// destroying the context and the window
|
||||||
|
unsafe { ffi::wglDeleteContext(dummy_context); }
|
||||||
|
unsafe { ffi::DestroyWindow(dummy_window); }
|
||||||
|
|
||||||
|
// returning the address
|
||||||
|
if addr.is_null() {
|
||||||
|
(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
|
||||||
|
let real_window = unsafe {
|
||||||
let handle = ffi::CreateWindowExW(ex_style, class_name.as_ptr(),
|
let handle = ffi::CreateWindowExW(ex_style, class_name.as_ptr(),
|
||||||
title.as_ptr() as ffi::LPCWSTR,
|
title.as_ptr() as ffi::LPCWSTR,
|
||||||
style | ffi::WS_VISIBLE | ffi::WS_CLIPSIBLINGS | ffi::WS_CLIPCHILDREN,
|
style | ffi::WS_VISIBLE | ffi::WS_CLIPSIBLINGS | ffi::WS_CLIPCHILDREN,
|
||||||
|
@ -128,21 +228,9 @@ pub fn new_window(dimensions: Option<(uint, uint)>, title: &str,
|
||||||
handle
|
handle
|
||||||
};
|
};
|
||||||
|
|
||||||
// calling SetForegroundWindow if fullscreen
|
// getting the HDC of the window
|
||||||
if monitor.is_some() {
|
|
||||||
unsafe { ffi::SetForegroundWindow(handle) };
|
|
||||||
}
|
|
||||||
|
|
||||||
// filling the WINDOW task-local storage
|
|
||||||
let events_receiver = {
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
WINDOW.replace(Some((handle, tx)));
|
|
||||||
rx
|
|
||||||
};
|
|
||||||
|
|
||||||
// Getting the HDC of the window
|
|
||||||
let hdc = {
|
let hdc = {
|
||||||
let hdc = unsafe { ffi::GetDC(handle) };
|
let hdc = unsafe { ffi::GetDC(real_window) };
|
||||||
if hdc.is_null() {
|
if hdc.is_null() {
|
||||||
tx.send(Err(format!("GetDC function failed: {}",
|
tx.send(Err(format!("GetDC function failed: {}",
|
||||||
os::error_string(os::errno() as uint))));
|
os::error_string(os::errno() as uint))));
|
||||||
|
@ -151,22 +239,6 @@ pub fn new_window(dimensions: Option<(uint, uint)>, title: &str,
|
||||||
hdc
|
hdc
|
||||||
};
|
};
|
||||||
|
|
||||||
// getting the pixel format that we will use
|
|
||||||
// TODO: use something cleaner which uses hints
|
|
||||||
let pixel_format = {
|
|
||||||
let mut output: ffi::PIXELFORMATDESCRIPTOR = unsafe { mem::uninitialized() };
|
|
||||||
|
|
||||||
if unsafe { ffi::DescribePixelFormat(hdc, 1,
|
|
||||||
mem::size_of::<ffi::PIXELFORMATDESCRIPTOR>() as ffi::UINT, &mut output) } == 0
|
|
||||||
{
|
|
||||||
tx.send(Err(format!("DescribePixelFormat function failed: {}",
|
|
||||||
os::error_string(os::errno() as uint))));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
output
|
|
||||||
};
|
|
||||||
|
|
||||||
// calling SetPixelFormat
|
// calling SetPixelFormat
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::SetPixelFormat(hdc, 1, &pixel_format) == 0 {
|
if ffi::SetPixelFormat(hdc, 1, &pixel_format) == 0 {
|
||||||
|
@ -178,15 +250,40 @@ pub fn new_window(dimensions: Option<(uint, uint)>, title: &str,
|
||||||
|
|
||||||
// creating the OpenGL context
|
// creating the OpenGL context
|
||||||
let context = {
|
let context = {
|
||||||
let ctxt = unsafe { ffi::wglCreateContext(hdc) };
|
use libc;
|
||||||
|
|
||||||
|
let attributes: [libc::c_int, ..1] = [
|
||||||
|
0
|
||||||
|
];
|
||||||
|
|
||||||
|
let ctxt = unsafe {
|
||||||
|
match create_context_attribs {
|
||||||
|
None => ffi::wglCreateContext(hdc),
|
||||||
|
Some(ptr) => ptr(hdc, ptr::mut_null(), attributes.as_ptr())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if ctxt.is_null() {
|
if ctxt.is_null() {
|
||||||
tx.send(Err(format!("wglCreateContext function failed: {}",
|
tx.send(Err(format!("OpenGL context creation failed: {}",
|
||||||
os::error_string(os::errno() as uint))));
|
os::error_string(os::errno() as uint))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt
|
ctxt
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// calling SetForegroundWindow if fullscreen
|
||||||
|
if monitor.is_some() {
|
||||||
|
unsafe { ffi::SetForegroundWindow(real_window) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// filling the WINDOW task-local storage
|
||||||
|
let events_receiver = {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
WINDOW.replace(Some((real_window, tx)));
|
||||||
|
rx
|
||||||
|
};
|
||||||
|
|
||||||
// loading the opengl32 module
|
// loading the opengl32 module
|
||||||
let gl_library = {
|
let gl_library = {
|
||||||
let name = "opengl32.dll".utf16_units().collect::<Vec<u16>>().append_one(0).as_ptr();
|
let name = "opengl32.dll".utf16_units().collect::<Vec<u16>>().append_one(0).as_ptr();
|
||||||
|
@ -201,7 +298,7 @@ pub fn new_window(dimensions: Option<(uint, uint)>, title: &str,
|
||||||
|
|
||||||
// building the struct
|
// building the struct
|
||||||
tx.send(Ok(Window{
|
tx.send(Ok(Window{
|
||||||
window: handle,
|
window: real_window,
|
||||||
hdc: hdc,
|
hdc: hdc,
|
||||||
context: context,
|
context: context,
|
||||||
gl_library: gl_library,
|
gl_library: gl_library,
|
||||||
|
@ -251,7 +348,18 @@ extern "stdcall" fn callback(window: ffi::HWND, msg: ffi::UINT,
|
||||||
match msg {
|
match msg {
|
||||||
ffi::WM_DESTROY => {
|
ffi::WM_DESTROY => {
|
||||||
use Closed;
|
use Closed;
|
||||||
|
|
||||||
|
match WINDOW.get() {
|
||||||
|
None => (),
|
||||||
|
Some(v) => {
|
||||||
|
let &(ref win, _) = v.deref();
|
||||||
|
|
||||||
|
if win == &window {
|
||||||
unsafe { ffi::PostQuitMessage(0); }
|
unsafe { ffi::PostQuitMessage(0); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
send_event(window, Closed);
|
send_event(window, Closed);
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue