1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 13:21:38 +03:00

windows: Software frontend is now mesa llvmpipe

This is a bit of a switch-up, see this comment for more background:
refs: https://github.com/wez/wezterm/issues/265#issuecomment-701882933

This commit:

* Adds a pre-compiled mesa3d opengl32.dll replacement
* The mesa dll is deployed to `<appdir>/mesa/opengl32.dll` which by
  default is ignored.
* When the frontend is set to `Software` then the `mesa` directory
  is added to the dll search path, causing the llvmpipe renderer
  to be enabled.
* The old software renderer implementation is available using the
  `OldSoftware` frontend name

I'm not a huge fan of the subdirectory for the opengl32.dll, but
I couldn't get it to work under a different dll name; the code
thought that everything was initialized, but the window just rendered
a white rectangle.
This commit is contained in:
Wez Furlong 2020-10-01 18:31:57 -07:00
parent 6069eabc9b
commit e6a858664f
10 changed files with 78 additions and 5 deletions

View File

@ -8,6 +8,7 @@ default-run = "wezterm"
[build-dependencies]
vergen = "3"
anyhow = "1.0"
[target.'cfg(windows)'.build-dependencies]
embed-resource = "1.3"

View File

@ -0,0 +1,6 @@
This is a pre-built opendl32.dll for 64-bit Windows systems.
It was obtained from <http://mesa.fdossena.com/>
Mesa's License text can be found here:
https://docs.mesa3d.org/license.html
(a mixture of largely MITish licenses)

Binary file not shown.

View File

@ -1,3 +1,4 @@
use anyhow::Context as _;
use std::path::Path;
use vergen::{generate_cargo_keys, ConstantsFlags};
@ -81,7 +82,29 @@ fn main() {
let src_name = conhost_dir.join(name);
if !dest_name.exists() {
std::fs::copy(src_name, dest_name).unwrap();
std::fs::copy(&src_name, &dest_name)
.context(format!(
"copy {} -> {}",
src_name.display(),
dest_name.display()
))
.unwrap();
}
}
{
let dest_mesa = exe_output_dir.join("mesa");
let _ = std::fs::create_dir(&dest_mesa);
let dest_name = dest_mesa.join("opengl32.dll");
let src_name = windows_dir.join("mesa").join("opengl32.dll");
if !dest_name.exists() {
std::fs::copy(&src_name, &dest_name)
.context(format!(
"copy {} -> {}",
src_name.display(),
dest_name.display()
))
.unwrap();
}
}

View File

@ -52,6 +52,9 @@ case $OSTYPE in
assets/windows/conhost/conpty.dll \
assets/windows/conhost/OpenConsole.exe \
$zipdir
mkdir $zipdir/mesa
cp $TARGET_DIR/release/mesa/opengl32.dll \
$zipdir/mesa
7z a -tzip $zipname $zipdir
iscc.exe -DMyAppVersion=${TAG_NAME#nightly} -F${instname} ci/windows-installer.iss
;;

View File

@ -43,6 +43,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
[Files]
Source: "..\target\release\wezterm.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\target\release\mesa\opengl32.dll"; DestDir: "{app}\mesa"; Flags: ignoreversion
Source: "..\target\release\conpty.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\target\release\OpenConsole.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\target\release\strip-ansi-escapes.exe"; DestDir: "{app}"; Flags: ignoreversion

View File

@ -42,6 +42,11 @@ impl GuiFrontEnd {
Self::try_new()
}
pub fn try_new_swrast() -> anyhow::Result<Rc<dyn FrontEnd>> {
::window::prefer_swrast();
Self::try_new()
}
pub fn try_new() -> anyhow::Result<Rc<dyn FrontEnd>> {
#[cfg(all(unix, not(target_os = "macos")))]
{
@ -49,6 +54,7 @@ impl GuiFrontEnd {
Connection::disable_wayland();
}
}
let connection = Connection::init()?;
let front_end = Rc::new(GuiFrontEnd { connection });
Ok(front_end)

View File

@ -16,6 +16,7 @@ pub mod muxserver;
pub enum FrontEndSelection {
OpenGL,
Software,
OldSoftware,
MuxServer,
Null,
}
@ -59,7 +60,8 @@ impl FrontEndSelection {
let (front_end, is_gui) = match self {
FrontEndSelection::MuxServer => (muxserver::MuxServerFrontEnd::try_new(), false),
FrontEndSelection::Null => (muxserver::MuxServerFrontEnd::new_null(), false),
FrontEndSelection::Software => (gui::GuiFrontEnd::try_new_no_opengl(), true),
FrontEndSelection::Software => (gui::GuiFrontEnd::try_new_swrast(), true),
FrontEndSelection::OldSoftware => (gui::GuiFrontEnd::try_new_no_opengl(), true),
FrontEndSelection::OpenGL => (gui::GuiFrontEnd::try_new(), true),
};
@ -73,7 +75,7 @@ impl FrontEndSelection {
// TODO: find or build a proc macro for this
pub fn variants() -> Vec<&'static str> {
vec!["OpenGL", "Software", "MuxServer", "Null"]
vec!["OpenGL", "Software", "OldSoftware", "MuxServer", "Null"]
}
}
@ -84,6 +86,7 @@ impl std::str::FromStr for FrontEndSelection {
"muxserver" => Ok(FrontEndSelection::MuxServer),
"null" => Ok(FrontEndSelection::Null),
"software" => Ok(FrontEndSelection::Software),
"oldsoftware" => Ok(FrontEndSelection::OldSoftware),
"opengl" => Ok(FrontEndSelection::OpenGL),
_ => Err(anyhow!(
"{} is not a valid FrontEndSelection variant, possible values are {:?}",

View File

@ -1,5 +1,6 @@
use promise::Future;
use std::any::Any;
use std::sync::atomic::{AtomicBool, Ordering};
pub mod bitmaps;
pub mod color;
pub mod connection;
@ -292,3 +293,13 @@ pub trait WindowOpsMut {
/// and/or in the task manager/task switcher
fn set_icon(&mut self, _image: &dyn BitmapImage) {}
}
static PREFER_SWRAST: AtomicBool = AtomicBool::new(false);
pub fn prefer_swrast() {
PREFER_SWRAST.store(true, Ordering::Release);
}
pub fn is_swrast_preferred() -> bool {
PREFER_SWRAST.load(Ordering::Acquire)
}

View File

@ -1,6 +1,7 @@
#![cfg(feature = "opengl")]
use super::*;
use crate::is_swrast_preferred;
use glium::backend::Backend;
use std::ffi::CStr;
use std::io::Error as IoError;
@ -8,6 +9,7 @@ use std::os::raw::c_void;
use std::ptr::{null, null_mut};
use winapi::shared::windef::*;
use winapi::um::libloaderapi::GetModuleHandleW;
use winapi::um::libloaderapi::*;
use winapi::um::wingdi::*;
use winapi::um::winuser::*;
@ -94,8 +96,25 @@ impl WglWrapper {
}
fn create() -> anyhow::Result<Self> {
let lib = libloading::Library::new("opengl32.dll")?;
log::trace!("loading opengl32.dll as {:?}", lib);
if is_swrast_preferred() {
let mesa_dir = std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.join("mesa");
let mesa_dir = wide_string(mesa_dir.to_str().unwrap());
unsafe {
AddDllDirectory(mesa_dir.as_ptr());
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
}
}
let lib = libloading::Library::new("opengl32.dll").map_err(|e| {
log::error!("{:?}", e);
e
})?;
log::trace!("loaded {:?}", lib);
let get_proc_address: libloading::Symbol<GetProcAddressFunc> =
unsafe { lib.get(b"wglGetProcAddress\0")? };