diff --git a/Cargo.toml b/Cargo.toml index 02ca731..6450c5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,8 @@ edition = "2018" xcb = { version = "0.9", features = ["thread", "xlib_xcb", "dri2"] } [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] cocoa = "0.20.1" diff --git a/src/win/window.rs b/src/win/window.rs index 3aa9371..f13322a 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -1,15 +1,20 @@ extern crate winapi; +use std::ffi::CString; use std::ptr::null_mut; -use self::winapi::_core::mem::MaybeUninit; use self::winapi::shared::guiddef::GUID; -use self::winapi::shared::minwindef::{LPARAM, LPVOID, LRESULT, UINT, WPARAM}; -use self::winapi::shared::windef::{HBRUSH, HICON, HMENU, HWND}; +use self::winapi::shared::minwindef::{LPARAM, LRESULT, UINT, WPARAM}; +use self::winapi::shared::windef::{HGLRC, HWND}; 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::{ - CreateWindowExA, DefWindowProcA, DispatchMessageA, PeekMessageA, PostQuitMessage, + CreateWindowExA, DefWindowProcA, DispatchMessageA, GetDC, PeekMessageA, PostQuitMessage, RegisterClassA, TranslateMessage, CS_HREDRAW, CS_OWNDC, CS_VREDRAW, CW_USEDEFAULT, MSG, PM_REMOVE, WM_DESTROY, WM_QUIT, WNDCLASSA, WS_OVERLAPPEDWINDOW, WS_VISIBLE, }; @@ -19,10 +24,11 @@ use crate::WindowOpenOptions; pub struct Window; impl Window { + // todo: we should decide this interface pub fn open(options: WindowOpenOptions) -> Self { unsafe { // 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); let class_name = format!( "Baseview-{:0X}-{:0X}-{:0X}-{:0X}{:0X}-{:0X}{:0X}{:0X}{:0X}{:0X}{:0X}\0", @@ -39,23 +45,22 @@ impl Window { guid.Data4[7] ); - let hinstance = GetModuleHandleA(0 as *const i8); let wnd_class = WNDCLASSA { // todo: for OpenGL, will use it later style: CS_OWNDC | CS_HREDRAW | CS_VREDRAW, lpfnWndProc: Some(wnd_proc), - hInstance: hinstance, + hInstance: null_mut(), lpszClassName: class_name.as_ptr() as *const i8, cbClsExtra: 0, cbWndExtra: 0, - hIcon: 0 as HICON, - hCursor: 0 as HICON, - hbrBackground: 0 as HBRUSH, - lpszMenuName: 0 as *const i8, + hIcon: null_mut(), + hCursor: null_mut(), + hbrBackground: null_mut(), + lpszMenuName: std::ptr::null::(), }; RegisterClassA(&wnd_class); - let _hwnd = CreateWindowExA( + let hwnd = CreateWindowExA( 0, class_name.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 options.width as i32, options.height as i32, - 0 as HWND, - 0 as HMENU, - hinstance, - 0 as LPVOID, + null_mut(), + null_mut(), + null_mut(), + null_mut(), ); + let hdc = GetDC(hwnd); + + let mut pfd: PIXELFORMATDESCRIPTOR = std::mem::zeroed(); + pfd.nSize = std::mem::size_of::() 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 { if !handle_msg(null_mut()) { 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 { unsafe { - let mut msg: MSG = MaybeUninit::uninit().assume_init(); + let mut msg: MSG = std::mem::zeroed(); loop { if PeekMessageA(&mut msg, 0 as HWND, 0, 0, PM_REMOVE) == 0 { return true; @@ -113,5 +162,5 @@ unsafe extern "system" fn wnd_proc( return DefWindowProcA(hwnd, msg, w_param, l_param); } } - return 0; + 0 }