mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
window: use wgl for opengl on windows
This commit is contained in:
parent
5135c724e6
commit
f2fce18586
@ -41,5 +41,13 @@ fn main() {
|
||||
}
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
if target.contains("windows") {
|
||||
let mut file = File::create(&dest.join("wgl_bindings.rs")).unwrap();
|
||||
let reg = Registry::new(Api::Wgl, (1, 0), Profile::Core, Fallbacks::All, []);
|
||||
|
||||
reg.write_bindings(gl_generator::StructGenerator, &mut file)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,11 @@ pub mod os;
|
||||
mod spawn;
|
||||
mod tasks;
|
||||
|
||||
#[cfg(all(not(target_os = "macos"), feature = "opengl"))]
|
||||
#[cfg(all(
|
||||
not(target_os = "macos"),
|
||||
not(target_os = "windows"),
|
||||
feature = "opengl"
|
||||
))]
|
||||
mod egl;
|
||||
|
||||
#[cfg(feature = "opengl")]
|
||||
|
@ -1,6 +1,7 @@
|
||||
pub mod connection;
|
||||
pub mod event;
|
||||
pub mod gdi;
|
||||
mod wgl;
|
||||
pub mod window;
|
||||
|
||||
pub use connection::*;
|
||||
|
122
window/src/os/windows/wgl.rs
Normal file
122
window/src/os/windows/wgl.rs
Normal file
@ -0,0 +1,122 @@
|
||||
#![cfg(feature = "opengl")]
|
||||
|
||||
use failure::Fallible;
|
||||
use std::os::raw::c_void;
|
||||
use winapi::shared::windef::*;
|
||||
use winapi::um::wingdi::*;
|
||||
use winapi::um::winuser::*;
|
||||
|
||||
pub mod ffi {
|
||||
include!(concat!(env!("OUT_DIR"), "/wgl_bindings.rs"));
|
||||
}
|
||||
|
||||
pub struct WglWrapper {
|
||||
lib: libloading::Library,
|
||||
wgl: ffi::Wgl,
|
||||
}
|
||||
|
||||
type GetProcAddressFunc =
|
||||
unsafe extern "system" fn(*const std::os::raw::c_char) -> *const std::os::raw::c_void;
|
||||
|
||||
impl WglWrapper {
|
||||
pub fn create() -> Fallible<Self> {
|
||||
let lib = libloading::Library::new("opengl32.dll")?;
|
||||
|
||||
let get_proc_address: libloading::Symbol<GetProcAddressFunc> =
|
||||
unsafe { lib.get(b"wglGetProcAddress\0")? };
|
||||
let wgl = ffi::Wgl::load_with(|s: &'static str| {
|
||||
let sym_name = std::ffi::CString::new(s).expect("symbol to be cstring compatible");
|
||||
if let Ok(sym) = unsafe { lib.get(sym_name.as_bytes_with_nul()) } {
|
||||
return *sym;
|
||||
}
|
||||
unsafe { get_proc_address(sym_name.as_ptr()) }
|
||||
});
|
||||
Ok(Self { lib, wgl })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GlState {
|
||||
wgl: WglWrapper,
|
||||
hdc: HDC,
|
||||
rc: ffi::types::HGLRC,
|
||||
}
|
||||
|
||||
impl GlState {
|
||||
pub fn create(window: HWND) -> Fallible<Self> {
|
||||
let wgl = WglWrapper::create()?;
|
||||
|
||||
let hdc = unsafe { GetDC(window) };
|
||||
|
||||
let pfd = PIXELFORMATDESCRIPTOR {
|
||||
nSize: std::mem::size_of::<PIXELFORMATDESCRIPTOR>() as u16,
|
||||
nVersion: 1,
|
||||
dwFlags: PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
||||
iPixelType: PFD_TYPE_RGBA,
|
||||
cColorBits: 24,
|
||||
cRedBits: 0,
|
||||
cRedShift: 0,
|
||||
cGreenBits: 0,
|
||||
cGreenShift: 0,
|
||||
cBlueBits: 0,
|
||||
cBlueShift: 0,
|
||||
cAlphaBits: 8,
|
||||
cAlphaShift: 0,
|
||||
cAccumBits: 0,
|
||||
cAccumRedBits: 0,
|
||||
cAccumGreenBits: 0,
|
||||
cAccumBlueBits: 0,
|
||||
cAccumAlphaBits: 0,
|
||||
cDepthBits: 24,
|
||||
cStencilBits: 8,
|
||||
cAuxBuffers: 0,
|
||||
iLayerType: PFD_MAIN_PLANE,
|
||||
bReserved: 0,
|
||||
dwLayerMask: 0,
|
||||
dwVisibleMask: 0,
|
||||
dwDamageMask: 0,
|
||||
};
|
||||
let format = unsafe { ChoosePixelFormat(hdc, &pfd) };
|
||||
unsafe {
|
||||
SetPixelFormat(hdc, format, &pfd);
|
||||
}
|
||||
|
||||
let rc = unsafe { wgl.wgl.CreateContext(hdc as *mut _) };
|
||||
unsafe {
|
||||
wgl.wgl.MakeCurrent(hdc as *mut _, rc);
|
||||
}
|
||||
|
||||
Ok(Self { wgl, rc, hdc })
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl glium::backend::Backend for GlState {
|
||||
fn swap_buffers(&self) -> Result<(), glium::SwapBuffersError> {
|
||||
unsafe {
|
||||
SwapBuffers(self.hdc);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
|
||||
let sym_name = std::ffi::CString::new(symbol).expect("symbol to be cstring compatible");
|
||||
if let Ok(sym) = self.wgl.lib.get(sym_name.as_bytes_with_nul()) {
|
||||
//eprintln!("{} -> {:?}", symbol, sym);
|
||||
return *sym;
|
||||
}
|
||||
let res = self.wgl.wgl.GetProcAddress(sym_name.as_ptr()) as *const c_void;
|
||||
// eprintln!("{} -> {:?}", symbol, res);
|
||||
res
|
||||
}
|
||||
|
||||
fn get_framebuffer_dimensions(&self) -> (u32, u32) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn is_current(&self) -> bool {
|
||||
unsafe { self.wgl.wgl.GetCurrentContext() == self.rc }
|
||||
}
|
||||
|
||||
unsafe fn make_current(&self) {
|
||||
self.wgl.wgl.MakeCurrent(self.hdc as *mut _, self.rc);
|
||||
}
|
||||
}
|
@ -31,6 +31,8 @@ pub(crate) struct WindowInner {
|
||||
hwnd: HWindow,
|
||||
callbacks: RefCell<Box<dyn WindowCallbacks>>,
|
||||
bitmap: RefCell<GdiBitmap>,
|
||||
#[cfg(feature = "opengl")]
|
||||
gl_state: Option<Rc<glium::backend::Context>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -166,6 +168,8 @@ impl Window {
|
||||
hwnd: HWindow(null_mut()),
|
||||
callbacks: RefCell::new(callbacks),
|
||||
bitmap: RefCell::new(GdiBitmap::new_empty()),
|
||||
#[cfg(feature = "opengl")]
|
||||
gl_state: None,
|
||||
}));
|
||||
|
||||
// Careful: `raw` owns a ref to inner, but there is no Drop impl
|
||||
@ -291,17 +295,23 @@ impl WindowOps for Window {
|
||||
Connection::with_window_inner(self.0, move |inner| {
|
||||
let window = Window(inner.hwnd);
|
||||
|
||||
let dc = unsafe { GetDC(inner.hwnd.0) };
|
||||
match crate::egl::GlState::create(Some(dc as *const _), inner.hwnd.0) {
|
||||
Ok(_) => eprintln!("EGL initialized!?"),
|
||||
Err(err) => eprintln!("EGL: {}", err),
|
||||
};
|
||||
let gl_state = super::wgl::GlState::create(inner.hwnd.0)
|
||||
.map(Rc::new)
|
||||
.and_then(|state| unsafe {
|
||||
Ok(glium::backend::Context::new(
|
||||
Rc::clone(&state),
|
||||
true,
|
||||
if cfg!(debug_assertions) {
|
||||
glium::debug::DebugCallbackBehavior::DebugMessageOnError
|
||||
} else {
|
||||
glium::debug::DebugCallbackBehavior::Ignore
|
||||
},
|
||||
)?)
|
||||
});
|
||||
|
||||
func(
|
||||
inner.callbacks.borrow_mut().as_any(),
|
||||
&window,
|
||||
Err(failure::err_msg("opengl not supported in this build")),
|
||||
);
|
||||
inner.gl_state = gl_state.as_ref().map(Rc::clone).ok();
|
||||
|
||||
func(inner.callbacks.borrow_mut().as_any(), &window, gl_state);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -449,6 +459,19 @@ unsafe fn wm_paint(hwnd: HWND, _msg: UINT, _wparam: WPARAM, _lparam: LPARAM) ->
|
||||
let width = rect_width(&rect) as usize;
|
||||
let height = rect_height(&rect) as usize;
|
||||
|
||||
#[cfg(feature = "opengl")]
|
||||
{
|
||||
if let Some(gl_context) = inner.gl_state.as_ref() {
|
||||
let mut frame =
|
||||
glium::Frame::new(Rc::clone(&gl_context), (width as u32, height as u32));
|
||||
|
||||
inner.callbacks.borrow_mut().paint_opengl(&mut frame);
|
||||
frame.finish().expect("frame.finish failed");
|
||||
EndPaint(hwnd, &mut ps);
|
||||
return Some(0);
|
||||
}
|
||||
}
|
||||
|
||||
if width > 0 && height > 0 {
|
||||
let mut bitmap = inner.bitmap.borrow_mut();
|
||||
let (bm_width, bm_height) = bitmap.image_dimensions();
|
||||
|
Loading…
Reference in New Issue
Block a user