Add a renderer escape hatch (wgpu default, glow fallback)

The desktop forces the wgpu/Vulkan renderer because glow/OpenGL crashes
on NVIDIA + Wayland maximize. But on some systems wgpu creates the window
and never presents a frame, so nothing appears. Keep wgpu the default but
compile glow back in and let it be selected via `--renderer glow` or
`YT_OFFLINE_RENDERER=glow` for those machines.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-06-08 00:04:24 -07:00
parent 2692fa2c9e
commit 9ba375f7b1
4 changed files with 166 additions and 8 deletions

View file

@ -36,6 +36,33 @@ mod vtt;
mod web;
mod ytdlp_bin;
fn renderer_from_name(requested: Option<&str>) -> eframe::Renderer {
match requested.map(|s| s.trim().to_ascii_lowercase()).as_deref() {
Some("glow" | "opengl" | "gl") => eframe::Renderer::Glow,
Some("wgpu" | "vulkan" | "vk") | None => eframe::Renderer::Wgpu,
Some(name) => {
eprintln!(
"Warning: unknown renderer '{name}' (expected 'wgpu' or 'glow'); using wgpu."
);
eframe::Renderer::Wgpu
}
}
}
fn renderer_from_args(args: &[String]) -> eframe::Renderer {
let requested = args
.iter()
.position(|a| a == "--renderer")
.and_then(|pos| args.get(pos + 1).map(String::as_str));
if requested.is_some() {
renderer_from_name(requested)
} else {
let env_renderer = std::env::var("YT_OFFLINE_RENDERER").ok();
renderer_from_name(env_renderer.as_deref())
}
}
fn main() -> eframe::Result<()> {
let args: Vec<String> = std::env::args().collect();
@ -82,10 +109,11 @@ fn main() -> eframe::Result<()> {
.with_inner_size([1280.0, 820.0])
.with_min_inner_size([800.0, 500.0])
.with_title("yt-offline"),
// Force the wgpu (Vulkan) renderer. The default glow/OpenGL path
// crashes on NVIDIA + Wayland when the window is maximized
// (Glutin EGL_BAD_ALLOC). wgpu reconfigures the swapchain cleanly.
renderer: eframe::Renderer::Wgpu,
// Default to wgpu (Vulkan): the glow/OpenGL path crashes on some
// NVIDIA + Wayland maximizes (Glutin EGL_BAD_ALLOC). Keep a launch
// escape hatch for systems where Vulkan/wgpu opens a blank window:
// `YT_OFFLINE_RENDERER=glow yt-offline` or `yt-offline --renderer glow`.
renderer: renderer_from_args(&args),
..Default::default()
};
eframe::run_native(
@ -94,3 +122,41 @@ fn main() -> eframe::Result<()> {
Box::new(|cc| Ok(Box::new(app::App::new(cc, tray)))),
)
}
#[cfg(test)]
mod tests {
#[test]
fn renderer_name_accepts_default_and_aliases() {
assert_eq!(super::renderer_from_name(None), eframe::Renderer::Wgpu);
assert_eq!(
super::renderer_from_name(Some("wgpu")),
eframe::Renderer::Wgpu
);
assert_eq!(
super::renderer_from_name(Some("vulkan")),
eframe::Renderer::Wgpu
);
assert_eq!(
super::renderer_from_name(Some("glow")),
eframe::Renderer::Glow
);
assert_eq!(
super::renderer_from_name(Some("opengl")),
eframe::Renderer::Glow
);
assert_eq!(
super::renderer_from_name(Some("unknown")),
eframe::Renderer::Wgpu
);
}
#[test]
fn renderer_arg_overrides_env_parser_path() {
let args = vec![
"yt-offline".to_string(),
"--renderer".to_string(),
"gl".to_string(),
];
assert_eq!(super::renderer_from_args(&args), eframe::Renderer::Glow);
}
}