diff --git a/Cargo.lock b/Cargo.lock index deb689fb4..9b439880a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -922,7 +922,7 @@ dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", "lazy_static", - "memoffset 0.6.4", + "memoffset", "scopeguard", ] @@ -1759,15 +1759,14 @@ dependencies = [ [[package]] name = "glium" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eeec7b733d14519e2541f4cc8a1230de9143d4ec439dd51b6c048d8ec991759" +version = "0.30.1" +source = "git+https://github.com/glium/glium.git?rev=aed95270f0714036003589d6e52de196e7ff75d1#aed95270f0714036003589d6e52de196e7ff75d1" dependencies = [ "backtrace", "fnv", "gl_generator", "lazy_static", - "memoffset 0.5.6", + "memoffset", "smallvec 1.6.1", "takeable-option", ] @@ -2371,15 +2370,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" -[[package]] -name = "memoffset" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.6.4" diff --git a/wezterm-gui/src/glyph-frag.glsl b/wezterm-gui/src/glyph-frag.glsl index 3d161bee5..1baeecf39 100644 --- a/wezterm-gui/src/glyph-frag.glsl +++ b/wezterm-gui/src/glyph-frag.glsl @@ -1,6 +1,6 @@ // This is the Glyph fragment shader. // It is responsible for laying down the glyph graphics on top of the other layers. - +#extension GL_EXT_blend_func_extended: enable precision highp float; in float o_has_color; @@ -9,29 +9,16 @@ in vec3 o_hsv; in vec4 o_fg_color; in vec4 o_bg_color; -out vec4 color; +// The color + alpha +layout(location=0, index=0) out vec4 color; +// Individual alpha channels for RGBA in color, used for subpixel +// antialiasing blending +layout(location=0, index=1) out vec4 colorMask; uniform vec3 foreground_text_hsb; uniform sampler2D atlas_nearest_sampler; uniform sampler2D atlas_linear_sampler; - -float multiply_one(float src, float dst, float inv_dst_alpha, float inv_src_alpha) { - return (src * dst) + (src * (inv_dst_alpha)) + (dst * (inv_src_alpha)); -} - -// Alpha-regulated multiply to colorize the glyph bitmap. -vec4 multiply(vec4 src, vec4 dst) { - float inv_src_alpha = 1.0 - src.a; - float inv_dst_alpha = 1.0 - dst.a; - - return vec4( - multiply_one(src.r, dst.r, inv_dst_alpha, inv_src_alpha), - multiply_one(src.g, dst.g, inv_dst_alpha, inv_src_alpha), - multiply_one(src.b, dst.b, inv_dst_alpha, inv_src_alpha), - dst.a); -} - vec3 rgb2hsv(vec3 c) { vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); @@ -61,41 +48,6 @@ vec4 apply_hsv(vec4 c, vec3 transform) return vec4(hsv2rgb(hsv).rgb, c.a); } -// Given glyph, the greyscale rgba value computed by freetype, -// and color, the desired color, compute the resultant pixel -// value for rendering over the top of the given background -// color. -// -// The freetype glyph is greyscale (R=G=B=A) when font_antialias=Greyscale, -// where each channel holds the brightness of the pixel. -// It holds separate intensity values for the R, G and B channels when -// subpixel anti-aliasing is in use, with an approximated A value -// derived from the R, G, B values. -// -// In sub-pixel mode we don't want to look at glyph.a as we effective -// have per-channel alpha. In greyscale mode, glyph.a is the same -// as the other channels, so this routine ignores glyph.a when -// computing the blend, but does include that value for the returned -// alpha value. -// -// See also: https://www.puredevsoftware.com/blog/2019/01/22/sub-pixel-gamma-correct-font-rendering/ -vec4 colorize(vec4 glyph, vec4 color, vec4 background) { - float r = glyph.r * color.r + (1.0 - glyph.r) * background.r; - float g = glyph.g * color.g + (1.0 - glyph.g) * background.g; - float b = glyph.b * color.b + (1.0 - glyph.b) * background.b; - - return vec4(r, g, b, glyph.a); -} - -// Like colorize, but for when the background color is unknown. -// This isn't "good" because it generally results in dark fringes. -// Ideally we wouldn't need to know the background and we could -// use dual source blending instead of colorize and colorize2. -// -vec4 colorize2(vec4 glyph, vec4 color) { - return vec4(glyph.rgb * color.rgb, glyph.a); -} - vec4 from_linear(vec4 v) { return pow(v, vec4(2.2)); } @@ -120,18 +72,22 @@ void main() { if (o_has_color == 3.0) { // Solid color block color = o_fg_color; + colorMask = vec4(1.0, 1.0, 1.0, 1.0); } else if (o_has_color == 2.0) { // The window background attachment color = sample_texture(atlas_linear_sampler, o_tex); // Apply window_background_image_opacity to the background image - color.a = o_fg_color.a; + colorMask = o_fg_color.aaaa; } else { color = sample_texture(atlas_nearest_sampler, o_tex); if (o_has_color == 0.0) { // if it's not a color emoji it will be grayscale // and we need to tint with the fg_color - color = colorize(color, o_fg_color, o_bg_color); + colorMask = color; + color = o_fg_color; color = apply_hsv(color, foreground_text_hsb); + } else { + colorMask = color.aaaa; } } diff --git a/wezterm-gui/src/renderstate.rs b/wezterm-gui/src/renderstate.rs index 6cda27a67..0e9a13068 100644 --- a/wezterm-gui/src/renderstate.rs +++ b/wezterm-gui/src/renderstate.rs @@ -152,7 +152,7 @@ impl RenderState { fragment_shader: fn(&str) -> (String, String), ) -> anyhow::Result { let mut errors = vec![]; - for version in &["330", "300 es"] { + for version in &["330 core", "330", "320 es", "300 es"] { let (vertex_shader, fragment_shader) = fragment_shader(version); let source = glium::program::ProgramCreationInput::SourceCode { vertex_shader: &vertex_shader, @@ -164,12 +164,11 @@ impl RenderState { uses_point_size: false, geometry_shader: None, }; - log::trace!("compiling a prog with version {}", version); match glium::Program::new(context, source) { Ok(prog) => { return Ok(prog); } - Err(err) => errors.push(err.to_string()), + Err(err) => errors.push(format!("shader version: {}: {:#}", version, err)), }; } diff --git a/wezterm-gui/src/termwindow/render.rs b/wezterm-gui/src/termwindow/render.rs index fd682fd10..ddff67075 100644 --- a/wezterm-gui/src/termwindow/render.rs +++ b/wezterm-gui/src/termwindow/render.rs @@ -467,12 +467,12 @@ impl super::TermWindow { let alpha_blending = glium::DrawParameters { blend: glium::Blend { color: BlendingFunction::Addition { - source: LinearBlendingFactor::SourceAlpha, - destination: LinearBlendingFactor::OneMinusSourceAlpha, + source: LinearBlendingFactor::SourceOneColor, + destination: LinearBlendingFactor::OneMinusSourceOneColor, }, alpha: BlendingFunction::Addition { - source: LinearBlendingFactor::One, - destination: LinearBlendingFactor::OneMinusSourceAlpha, + source: LinearBlendingFactor::SourceOneColor, + destination: LinearBlendingFactor::OneMinusSourceOneColor, }, constant_value: (0.0, 0.0, 0.0, 0.0), }, diff --git a/window/Cargo.toml b/window/Cargo.toml index cd8b2554d..ec691e3e0 100644 --- a/window/Cargo.toml +++ b/window/Cargo.toml @@ -42,7 +42,7 @@ raw-window-handle = "0.3" resize = "0.5" serde = {version="1.0", features = ["rc", "derive"]} tiny-skia = "0.5" -glium = { version = "0.28", default-features = false} +glium = { version = "0.30", default-features = false, git = "https://github.com/glium/glium.git", rev="aed95270f0714036003589d6e52de196e7ff75d1" } wezterm-font = { path = "../wezterm-font" } wezterm-input-types = { path = "../wezterm-input-types" } diff --git a/window/src/egl.rs b/window/src/egl.rs index b6f490e16..f11910271 100644 --- a/window/src/egl.rs +++ b/window/src/egl.rs @@ -54,6 +54,7 @@ impl std::fmt::Debug for EglWrapper { pub struct GlConnection { egl: EglWrapper, display: ffi::types::EGLDisplay, + is_opengl: bool, } impl std::ops::Deref for GlConnection { @@ -490,9 +491,22 @@ impl GlState { let (major, minor) = egl.initialize_and_get_version(egl_display)?; log::trace!("initialized EGL version {}.{}", major, minor); + let is_opengl = unsafe { + if egl.egl.BindAPI(ffi::OPENGL_API) != 0 { + log::trace!("using OpenGL"); + true + } else if egl.egl.BindAPI(ffi::OPENGL_ES_API) != 0 { + log::trace!("using GLES"); + false + } else { + anyhow::bail!("Unable to bind to OpenGL or GL ES!?"); + } + }; + let connection = Rc::new(GlConnection { display: egl_display, egl, + is_opengl, }); Self::create_with_existing_connection(&connection, window) @@ -539,9 +553,17 @@ impl GlState { ffi::DEPTH_SIZE, 24, ffi::CONFORMANT, - ffi::OPENGL_ES3_BIT, + if connection.is_opengl { + ffi::OPENGL_BIT + } else { + ffi::OPENGL_ES3_BIT + }, ffi::RENDERABLE_TYPE, - ffi::OPENGL_ES3_BIT, + if connection.is_opengl { + ffi::OPENGL_BIT + } else { + ffi::OPENGL_ES3_BIT + }, // Wayland EGL doesn't give us a working context if we request // PBUFFER|PIXMAP. We don't appear to require these for X11, // so we're just asking for a WINDOW capable context