1
0
Fork 0

Merge pull request #8 from MirkoCovizzi/master

Add OpenGL context on Windows
This commit is contained in:
Mirko Covizzi 2020-05-30 16:49:47 +02:00 committed by GitHub
commit 472c7a00cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 20 deletions

View file

@ -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"

View file

@ -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
} }