Merge pull request #8 from MirkoCovizzi/master
Add OpenGL context on Windows
This commit is contained in:
commit
472c7a00cb
|
@ -15,7 +15,8 @@ edition = "2018"
|
||||||
xcb = { version = "0.9", features = ["thread", "xlib_xcb", "dri2"] }
|
xcb = { version = "0.9", features = ["thread", "xlib_xcb", "dri2"] }
|
||||||
|
|
||||||
[target.'cfg(target_os="windows")'.dependencies]
|
[target.'cfg(target_os="windows")'.dependencies]
|
||||||
winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi"] }
|
winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi", "wingdi"] }
|
||||||
|
gl = "0.14.0"
|
||||||
|
|
||||||
[target.'cfg(target_os="macos")'.dependencies]
|
[target.'cfg(target_os="macos")'.dependencies]
|
||||||
cocoa = "0.20.1"
|
cocoa = "0.20.1"
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
extern crate winapi;
|
extern crate winapi;
|
||||||
|
|
||||||
|
use std::ffi::CString;
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
use self::winapi::_core::mem::MaybeUninit;
|
|
||||||
use self::winapi::shared::guiddef::GUID;
|
use self::winapi::shared::guiddef::GUID;
|
||||||
use self::winapi::shared::minwindef::{LPARAM, LPVOID, LRESULT, UINT, WPARAM};
|
use self::winapi::shared::minwindef::{LPARAM, LRESULT, UINT, WPARAM};
|
||||||
use self::winapi::shared::windef::{HBRUSH, HICON, HMENU, HWND};
|
use self::winapi::shared::windef::{HGLRC, HWND};
|
||||||
use self::winapi::um::combaseapi::CoCreateGuid;
|
use self::winapi::um::combaseapi::CoCreateGuid;
|
||||||
use self::winapi::um::libloaderapi::GetModuleHandleA;
|
use self::winapi::um::libloaderapi::{GetProcAddress, LoadLibraryA};
|
||||||
|
use self::winapi::um::wingdi::{
|
||||||
|
wglCreateContext, wglMakeCurrent, ChoosePixelFormat, SetPixelFormat, SwapBuffers,
|
||||||
|
PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_MAIN_PLANE, PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA,
|
||||||
|
PIXELFORMATDESCRIPTOR,
|
||||||
|
};
|
||||||
use self::winapi::um::winuser::{
|
use self::winapi::um::winuser::{
|
||||||
CreateWindowExA, DefWindowProcA, DispatchMessageA, PeekMessageA, PostQuitMessage,
|
CreateWindowExA, DefWindowProcA, DispatchMessageA, GetDC, PeekMessageA, PostQuitMessage,
|
||||||
RegisterClassA, TranslateMessage, CS_HREDRAW, CS_OWNDC, CS_VREDRAW, CW_USEDEFAULT, MSG,
|
RegisterClassA, TranslateMessage, CS_HREDRAW, CS_OWNDC, CS_VREDRAW, CW_USEDEFAULT, MSG,
|
||||||
PM_REMOVE, WM_DESTROY, WM_QUIT, WNDCLASSA, WS_OVERLAPPEDWINDOW, WS_VISIBLE,
|
PM_REMOVE, WM_DESTROY, WM_QUIT, WNDCLASSA, WS_OVERLAPPEDWINDOW, WS_VISIBLE,
|
||||||
};
|
};
|
||||||
|
@ -19,10 +24,11 @@ use crate::WindowOpenOptions;
|
||||||
pub struct Window;
|
pub struct Window;
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
// todo: we should decide this interface
|
||||||
pub fn open(options: WindowOpenOptions) -> Self {
|
pub fn open(options: WindowOpenOptions) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
// We generate a unique name for the new window class to prevent name collisions
|
// We generate a unique name for the new window class to prevent name collisions
|
||||||
let mut guid: GUID = MaybeUninit::uninit().assume_init();
|
let mut guid: GUID = std::mem::zeroed();
|
||||||
CoCreateGuid(&mut guid);
|
CoCreateGuid(&mut guid);
|
||||||
let class_name = format!(
|
let class_name = format!(
|
||||||
"Baseview-{:0X}-{:0X}-{:0X}-{:0X}{:0X}-{:0X}{:0X}{:0X}{:0X}{:0X}{:0X}\0",
|
"Baseview-{:0X}-{:0X}-{:0X}-{:0X}{:0X}-{:0X}{:0X}{:0X}{:0X}{:0X}{:0X}\0",
|
||||||
|
@ -39,23 +45,22 @@ impl Window {
|
||||||
guid.Data4[7]
|
guid.Data4[7]
|
||||||
);
|
);
|
||||||
|
|
||||||
let hinstance = GetModuleHandleA(0 as *const i8);
|
|
||||||
let wnd_class = WNDCLASSA {
|
let wnd_class = WNDCLASSA {
|
||||||
// todo: for OpenGL, will use it later
|
// todo: for OpenGL, will use it later
|
||||||
style: CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
|
style: CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
|
||||||
lpfnWndProc: Some(wnd_proc),
|
lpfnWndProc: Some(wnd_proc),
|
||||||
hInstance: hinstance,
|
hInstance: null_mut(),
|
||||||
lpszClassName: class_name.as_ptr() as *const i8,
|
lpszClassName: class_name.as_ptr() as *const i8,
|
||||||
cbClsExtra: 0,
|
cbClsExtra: 0,
|
||||||
cbWndExtra: 0,
|
cbWndExtra: 0,
|
||||||
hIcon: 0 as HICON,
|
hIcon: null_mut(),
|
||||||
hCursor: 0 as HICON,
|
hCursor: null_mut(),
|
||||||
hbrBackground: 0 as HBRUSH,
|
hbrBackground: null_mut(),
|
||||||
lpszMenuName: 0 as *const i8,
|
lpszMenuName: std::ptr::null::<i8>(),
|
||||||
};
|
};
|
||||||
RegisterClassA(&wnd_class);
|
RegisterClassA(&wnd_class);
|
||||||
|
|
||||||
let _hwnd = CreateWindowExA(
|
let hwnd = CreateWindowExA(
|
||||||
0,
|
0,
|
||||||
class_name.as_ptr() as *const i8,
|
class_name.as_ptr() as *const i8,
|
||||||
(options.title.to_owned() + "\0").as_ptr() as *const i8,
|
(options.title.to_owned() + "\0").as_ptr() as *const i8,
|
||||||
|
@ -66,16 +71,60 @@ impl Window {
|
||||||
// todo: check if usize fits into i32
|
// todo: check if usize fits into i32
|
||||||
options.width as i32,
|
options.width as i32,
|
||||||
options.height as i32,
|
options.height as i32,
|
||||||
0 as HWND,
|
null_mut(),
|
||||||
0 as HMENU,
|
null_mut(),
|
||||||
hinstance,
|
null_mut(),
|
||||||
0 as LPVOID,
|
null_mut(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let hdc = GetDC(hwnd);
|
||||||
|
|
||||||
|
let mut pfd: PIXELFORMATDESCRIPTOR = std::mem::zeroed();
|
||||||
|
pfd.nSize = std::mem::size_of::<PIXELFORMATDESCRIPTOR>() as u16;
|
||||||
|
pfd.nVersion = 1;
|
||||||
|
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||||
|
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||||
|
pfd.cColorBits = 32;
|
||||||
|
// todo: ask wrl why 24 instead of 32?
|
||||||
|
pfd.cDepthBits = 24;
|
||||||
|
pfd.cStencilBits = 8;
|
||||||
|
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||||
|
|
||||||
|
let pf_id: i32 = ChoosePixelFormat(hdc, &pfd);
|
||||||
|
if pf_id == 0 {
|
||||||
|
return Window;
|
||||||
|
}
|
||||||
|
|
||||||
|
if SetPixelFormat(hdc, pf_id, &pfd) == 0 {
|
||||||
|
return Window;
|
||||||
|
}
|
||||||
|
|
||||||
|
let gl_context: HGLRC = wglCreateContext(hdc);
|
||||||
|
if gl_context == 0 as HGLRC {
|
||||||
|
return Window;
|
||||||
|
}
|
||||||
|
|
||||||
|
if wglMakeCurrent(hdc, gl_context) == 0 {
|
||||||
|
return Window;
|
||||||
|
}
|
||||||
|
|
||||||
|
let h = LoadLibraryA("opengl32.dll\0".as_ptr() as *const i8);
|
||||||
|
gl::load_with(|symbol| {
|
||||||
|
let symbol = CString::new(symbol.as_bytes()).unwrap();
|
||||||
|
let symbol = symbol.as_ptr();
|
||||||
|
GetProcAddress(h, symbol) as *const _
|
||||||
|
});
|
||||||
|
|
||||||
|
// todo: decide what to do with the message pump
|
||||||
loop {
|
loop {
|
||||||
if !handle_msg(null_mut()) {
|
if !handle_msg(null_mut()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: pass callback rendering function instead
|
||||||
|
gl::ClearColor(0.3, 0.8, 0.3, 1.0);
|
||||||
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
|
SwapBuffers(hdc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +134,7 @@ impl Window {
|
||||||
|
|
||||||
fn handle_msg(_window: HWND) -> bool {
|
fn handle_msg(_window: HWND) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut msg: MSG = MaybeUninit::uninit().assume_init();
|
let mut msg: MSG = std::mem::zeroed();
|
||||||
loop {
|
loop {
|
||||||
if PeekMessageA(&mut msg, 0 as HWND, 0, 0, PM_REMOVE) == 0 {
|
if PeekMessageA(&mut msg, 0 as HWND, 0, 0, PM_REMOVE) == 0 {
|
||||||
return true;
|
return true;
|
||||||
|
@ -113,5 +162,5 @@ unsafe extern "system" fn wnd_proc(
|
||||||
return DefWindowProcA(hwnd, msg, w_param, l_param);
|
return DefWindowProcA(hwnd, msg, w_param, l_param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
0
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue