mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
Fix solid background color opacity (#847)
Since landing the patch adding transparency support to Alacritty, there's been an issue where othewise solid background cells were also being rendered partially transparent. Now, all filled background cells are rendered fully opaque. Some logic was added to support discarding filled backgrounds which had the same color as the default background. This means that, if the default background is #000 and a cell has that background, it will never be rendered opaque. This may not be correct. Note that many truecolor vim color schemes print spaces for default colored background cells. Performance can be dramatically improved by using ctermbg=NONE guibg=NONE to skip rendering those cells.
This commit is contained in:
parent
7a5eebd094
commit
b79574ee82
6 changed files with 83 additions and 36 deletions
|
@ -14,7 +14,7 @@
|
||||||
#version 330 core
|
#version 330 core
|
||||||
in vec2 TexCoords;
|
in vec2 TexCoords;
|
||||||
in vec3 fg;
|
in vec3 fg;
|
||||||
in vec3 bg;
|
in vec4 bg;
|
||||||
flat in float vb;
|
flat in float vb;
|
||||||
flat in int background;
|
flat in int background;
|
||||||
|
|
||||||
|
@ -27,8 +27,11 @@ uniform sampler2D mask;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
if (background != 0) {
|
if (background != 0) {
|
||||||
|
if (bg.a == 0.0)
|
||||||
|
discard;
|
||||||
|
|
||||||
alphaMask = vec4(1.0);
|
alphaMask = vec4(1.0);
|
||||||
color = vec4(bg + vb, 1.0) * bgOpacity;
|
color = vec4(bg.rgb + vb, 1.0);
|
||||||
} else {
|
} else {
|
||||||
vec3 textColor = texture(mask, TexCoords).rgb;
|
vec3 textColor = texture(mask, TexCoords).rgb;
|
||||||
alphaMask = vec4(textColor, textColor.r);
|
alphaMask = vec4(textColor, textColor.r);
|
||||||
|
|
|
@ -26,11 +26,11 @@ layout (location = 3) in vec4 uv;
|
||||||
// text fg color
|
// text fg color
|
||||||
layout (location = 4) in vec3 textColor;
|
layout (location = 4) in vec3 textColor;
|
||||||
// Background color
|
// Background color
|
||||||
layout (location = 5) in vec3 backgroundColor;
|
layout (location = 5) in vec4 backgroundColor;
|
||||||
|
|
||||||
out vec2 TexCoords;
|
out vec2 TexCoords;
|
||||||
out vec3 fg;
|
out vec3 fg;
|
||||||
out vec3 bg;
|
out vec4 bg;
|
||||||
|
|
||||||
// Terminal properties
|
// Terminal properties
|
||||||
uniform vec2 termDim;
|
uniform vec2 termDim;
|
||||||
|
@ -63,7 +63,6 @@ void main()
|
||||||
gl_Position = projection * vec4(finalPosition.xy, 0.0, 1.0);
|
gl_Position = projection * vec4(finalPosition.xy, 0.0, 1.0);
|
||||||
TexCoords = vec2(0, 0);
|
TexCoords = vec2(0, 0);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Glyphs are offset within their cell; account for y-flip
|
// Glyphs are offset within their cell; account for y-flip
|
||||||
vec2 cellOffset = vec2(glyphOffset.x, glyphOffset.y - glyphSize.y);
|
vec2 cellOffset = vec2(glyphOffset.x, glyphOffset.y - glyphSize.y);
|
||||||
|
|
||||||
|
@ -76,6 +75,6 @@ void main()
|
||||||
|
|
||||||
vb = visualBell;
|
vb = visualBell;
|
||||||
background = backgroundPass;
|
background = backgroundPass;
|
||||||
bg = backgroundColor / vec3(255.0, 255.0, 255.0);
|
bg = vec4(backgroundColor.rgb / 255.0, backgroundColor.a);
|
||||||
fg = textColor / vec3(255.0, 255.0, 255.0);
|
fg = textColor / vec3(255.0, 255.0, 255.0);
|
||||||
}
|
}
|
||||||
|
|
14
scripts/fg-bg.sh
Executable file
14
scripts/fg-bg.sh
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
printf "Fg=Black, Bg=Background \e[30;49mTEST\e[m\n"
|
||||||
|
printf "Fg=Black, Bg=Black \e[30;40mTEST\e[m\n"
|
||||||
|
printf "Fg=Foreground,Bg=Background \e[39;49mTEST\e[m\n"
|
||||||
|
printf "Fg=Foreground,Bg=Black \e[39;40mTEST\e[m\n"
|
||||||
|
printf "Fg=Foreground,Bg=White \e[39;47mTEST\e[m\n"
|
||||||
|
printf "Fg=White, Bg=Foreground \e[37;39mTEST\e[m\n"
|
||||||
|
printf "Fg=Black, Bg=Background, Inverse \e[7;30;49mTEST\e[m\n"
|
||||||
|
printf "Fg=Black, Bg=Black, Inverse \e[7;30;40mTEST\e[m\n"
|
||||||
|
printf "Fg=Foreground,Bg=Background, Inverse \e[7;39;49mTEST\e[m\n"
|
||||||
|
printf "Fg=Foreground,Bg=Black, Inverse \e[7;39;40mTEST\e[m\n"
|
||||||
|
printf "Fg=Foreground,Bg=White, Inverse \e[7;39;47mTEST\e[m\n"
|
||||||
|
printf "Fg=White, Bg=Foreground, Inverse \e[7;37;39mTEST\e[m\n"
|
|
@ -186,6 +186,7 @@ impl Alpha {
|
||||||
self.0 = Self::clamp_to_valid_range(value);
|
self.0 = Self::clamp_to_valid_range(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub fn get(&self) -> f32 {
|
pub fn get(&self) -> f32 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
@ -1093,6 +1094,7 @@ impl Config {
|
||||||
&self.colors
|
&self.colors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn background_opacity(&self) -> Alpha {
|
pub fn background_opacity(&self) -> Alpha {
|
||||||
self.background_opacity
|
self.background_opacity
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,8 +125,6 @@ pub struct ShaderProgram {
|
||||||
|
|
||||||
padding_x: f32,
|
padding_x: f32,
|
||||||
padding_y: f32,
|
padding_y: f32,
|
||||||
|
|
||||||
u_bg_opacity: GLint,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -351,6 +349,7 @@ struct InstanceData {
|
||||||
bg_r: f32,
|
bg_r: f32,
|
||||||
bg_g: f32,
|
bg_g: f32,
|
||||||
bg_b: f32,
|
bg_b: f32,
|
||||||
|
bg_a: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -436,6 +435,7 @@ impl Batch {
|
||||||
bg_r: cell.bg.r as f32,
|
bg_r: cell.bg.r as f32,
|
||||||
bg_g: cell.bg.g as f32,
|
bg_g: cell.bg.g as f32,
|
||||||
bg_b: cell.bg.b as f32,
|
bg_b: cell.bg.b as f32,
|
||||||
|
bg_a: cell.bg_alpha,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,7 +568,7 @@ impl QuadRenderer {
|
||||||
gl::EnableVertexAttribArray(4);
|
gl::EnableVertexAttribArray(4);
|
||||||
gl::VertexAttribDivisor(4, 1);
|
gl::VertexAttribDivisor(4, 1);
|
||||||
// color
|
// color
|
||||||
gl::VertexAttribPointer(5, 3,
|
gl::VertexAttribPointer(5, 4,
|
||||||
gl::FLOAT, gl::FALSE,
|
gl::FLOAT, gl::FALSE,
|
||||||
size_of::<InstanceData>() as i32,
|
size_of::<InstanceData>() as i32,
|
||||||
(13 * size_of::<f32>()) as *const _);
|
(13 * size_of::<f32>()) as *const _);
|
||||||
|
@ -648,7 +648,6 @@ impl QuadRenderer {
|
||||||
self.program.activate();
|
self.program.activate();
|
||||||
self.program.set_term_uniforms(props);
|
self.program.set_term_uniforms(props);
|
||||||
self.program.set_visual_bell(visual_bell_intensity as _);
|
self.program.set_visual_bell(visual_bell_intensity as _);
|
||||||
self.program.set_bg_opacity(config.background_opacity().get());
|
|
||||||
|
|
||||||
gl::BindVertexArray(self.vao);
|
gl::BindVertexArray(self.vao);
|
||||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo);
|
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo);
|
||||||
|
@ -692,17 +691,22 @@ impl QuadRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reload_shaders(&mut self, config: &Config, size: Size<Pixels<u32>>) {
|
pub fn reload_shaders(&mut self, config: &Config, size: Size<Pixels<u32>>) {
|
||||||
info!("Reloading shaders");
|
warn!("Reloading shaders ...");
|
||||||
let program = match ShaderProgram::new(config, size) {
|
let program = match ShaderProgram::new(config, size) {
|
||||||
Ok(program) => program,
|
Ok(program) => {
|
||||||
|
warn!(" ... OK");
|
||||||
|
program
|
||||||
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
match err {
|
match err {
|
||||||
ShaderCreationError::Io(err) => {
|
ShaderCreationError::Io(err) => {
|
||||||
error!("Error reading shader file: {}", err);
|
error!("Error reading shader file: {}", err);
|
||||||
},
|
},
|
||||||
ShaderCreationError::Compile(path, log) => {
|
ShaderCreationError::Compile(path, log) => {
|
||||||
error!("Error compiling shader at {:?}", path);
|
error!("Error compiling shader at {:?}\n{}", path, log);
|
||||||
let _ = io::copy(&mut log.as_bytes(), &mut io::stdout());
|
}
|
||||||
|
ShaderCreationError::Link(log) => {
|
||||||
|
error!("Error reloading shaders: {}", log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,6 +795,7 @@ impl<'a> RenderApi<'a> {
|
||||||
bg: color,
|
bg: color,
|
||||||
fg: Rgb { r: 0, g: 0, b: 0 },
|
fg: Rgb { r: 0, g: 0, b: 0 },
|
||||||
flags: cell::Flags::empty(),
|
flags: cell::Flags::empty(),
|
||||||
|
bg_alpha: 1.0
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -957,7 +962,7 @@ impl ShaderProgram {
|
||||||
gl::FRAGMENT_SHADER,
|
gl::FRAGMENT_SHADER,
|
||||||
frag_source
|
frag_source
|
||||||
)?;
|
)?;
|
||||||
let program = ShaderProgram::create_program(vertex_shader, fragment_shader);
|
let program = ShaderProgram::create_program(vertex_shader, fragment_shader)?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::DeleteShader(vertex_shader);
|
gl::DeleteShader(vertex_shader);
|
||||||
|
@ -980,14 +985,13 @@ impl ShaderProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get uniform locations
|
// get uniform locations
|
||||||
let (projection, term_dim, cell_dim, visual_bell, background, bg_opacity) = unsafe {
|
let (projection, term_dim, cell_dim, visual_bell, background) = unsafe {
|
||||||
(
|
(
|
||||||
gl::GetUniformLocation(program, cptr!(b"projection\0")),
|
gl::GetUniformLocation(program, cptr!(b"projection\0")),
|
||||||
gl::GetUniformLocation(program, cptr!(b"termDim\0")),
|
gl::GetUniformLocation(program, cptr!(b"termDim\0")),
|
||||||
gl::GetUniformLocation(program, cptr!(b"cellDim\0")),
|
gl::GetUniformLocation(program, cptr!(b"cellDim\0")),
|
||||||
gl::GetUniformLocation(program, cptr!(b"visualBell\0")),
|
gl::GetUniformLocation(program, cptr!(b"visualBell\0")),
|
||||||
gl::GetUniformLocation(program, cptr!(b"backgroundPass\0")),
|
gl::GetUniformLocation(program, cptr!(b"backgroundPass\0")),
|
||||||
gl::GetUniformLocation(program, cptr!(b"bgOpacity\0")),
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1002,7 +1006,6 @@ impl ShaderProgram {
|
||||||
u_background: background,
|
u_background: background,
|
||||||
padding_x: config.padding().x.floor(),
|
padding_x: config.padding().x.floor(),
|
||||||
padding_y: config.padding().y.floor(),
|
padding_y: config.padding().y.floor(),
|
||||||
u_bg_opacity: bg_opacity,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
shader.update_projection(*size.width as f32, *size.height as f32);
|
shader.update_projection(*size.width as f32, *size.height as f32);
|
||||||
|
@ -1063,13 +1066,7 @@ impl ShaderProgram {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_bg_opacity(&self, bg_opacity: f32) {
|
fn create_program(vertex: GLuint, fragment: GLuint) -> Result<GLuint, ShaderCreationError> {
|
||||||
unsafe {
|
|
||||||
gl::Uniform1f(self.u_bg_opacity, bg_opacity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_program(vertex: GLuint, fragment: GLuint) -> GLuint {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let program = gl::CreateProgram();
|
let program = gl::CreateProgram();
|
||||||
gl::AttachShader(program, vertex);
|
gl::AttachShader(program, vertex);
|
||||||
|
@ -1080,10 +1077,10 @@ impl ShaderProgram {
|
||||||
gl::GetProgramiv(program, gl::LINK_STATUS, &mut success);
|
gl::GetProgramiv(program, gl::LINK_STATUS, &mut success);
|
||||||
|
|
||||||
if success != (gl::TRUE as GLint) {
|
if success != (gl::TRUE as GLint) {
|
||||||
error!("{}", get_program_info_log(program));
|
Err(ShaderCreationError::Link(get_program_info_log(program)))
|
||||||
panic!("failed to link shader program");
|
} else {
|
||||||
|
Ok(program)
|
||||||
}
|
}
|
||||||
program
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,13 +1195,16 @@ pub enum ShaderCreationError {
|
||||||
|
|
||||||
/// Error compiling shader
|
/// Error compiling shader
|
||||||
Compile(PathBuf, String),
|
Compile(PathBuf, String),
|
||||||
|
|
||||||
|
/// Problem linking
|
||||||
|
Link(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::error::Error for ShaderCreationError {
|
impl ::std::error::Error for ShaderCreationError {
|
||||||
fn cause(&self) -> Option<&::std::error::Error> {
|
fn cause(&self) -> Option<&::std::error::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
ShaderCreationError::Io(ref err) => Some(err),
|
ShaderCreationError::Io(ref err) => Some(err),
|
||||||
ShaderCreationError::Compile(_, _) => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1212,6 +1212,7 @@ impl ::std::error::Error for ShaderCreationError {
|
||||||
match *self {
|
match *self {
|
||||||
ShaderCreationError::Io(ref err) => err.description(),
|
ShaderCreationError::Io(ref err) => err.description(),
|
||||||
ShaderCreationError::Compile(ref _path, ref s) => s.as_str(),
|
ShaderCreationError::Compile(ref _path, ref s) => s.as_str(),
|
||||||
|
ShaderCreationError::Link(ref s) => s.as_str(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1223,6 +1224,9 @@ impl ::std::fmt::Display for ShaderCreationError {
|
||||||
ShaderCreationError::Compile(ref _path, ref s) => {
|
ShaderCreationError::Compile(ref _path, ref s) => {
|
||||||
write!(f, "failed compiling shader: {}", s)
|
write!(f, "failed compiling shader: {}", s)
|
||||||
},
|
},
|
||||||
|
ShaderCreationError::Link(ref s) => {
|
||||||
|
write!(f, "failed linking shader: {}", s)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,6 +299,14 @@ impl<'a> RenderableCellsIter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn compute_bg_alpha(&self, bg: &Color) -> f32 {
|
||||||
|
match *bg {
|
||||||
|
Color::Named(NamedColor::Background) => 0.0,
|
||||||
|
_ => 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn compute_bg_rgb(&self, bg: &Color) -> Rgb {
|
fn compute_bg_rgb(&self, bg: &Color) -> Rgb {
|
||||||
match *bg {
|
match *bg {
|
||||||
Color::Spec(rgb) => rgb,
|
Color::Spec(rgb) => rgb,
|
||||||
|
@ -314,6 +322,7 @@ pub struct RenderableCell {
|
||||||
pub c: char,
|
pub c: char,
|
||||||
pub fg: Rgb,
|
pub fg: Rgb,
|
||||||
pub bg: Rgb,
|
pub bg: Rgb,
|
||||||
|
pub bg_alpha: f32,
|
||||||
pub flags: cell::Flags,
|
pub flags: cell::Flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,19 +372,35 @@ impl<'a> Iterator for RenderableCellsIter<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Apply inversion and lookup RGB values
|
// Apply inversion and lookup RGB values
|
||||||
let (fg, bg) = if selected || cell.inverse() {
|
let mut bg_alpha = 1.0;
|
||||||
(self.compute_bg_rgb(&cell.bg), self.compute_fg_rgb(&cell.fg, &cell))
|
let fg_rgb;
|
||||||
|
let bg_rgb;
|
||||||
|
|
||||||
|
let invert = selected ^ cell.inverse();
|
||||||
|
|
||||||
|
if invert {
|
||||||
|
if cell.fg == cell.bg {
|
||||||
|
bg_rgb = self.colors[NamedColor::Foreground];
|
||||||
|
fg_rgb = self.colors[NamedColor::Background];
|
||||||
|
bg_alpha = 1.0
|
||||||
} else {
|
} else {
|
||||||
(self.compute_fg_rgb(&cell.fg, &cell), self.compute_bg_rgb(&cell.bg))
|
bg_rgb = self.compute_fg_rgb(&cell.fg, &cell);
|
||||||
};
|
fg_rgb = self.compute_bg_rgb(&cell.bg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fg_rgb = self.compute_fg_rgb(&cell.fg, &cell);
|
||||||
|
bg_rgb = self.compute_bg_rgb(&cell.bg);
|
||||||
|
bg_alpha = self.compute_bg_alpha(&cell.bg);
|
||||||
|
}
|
||||||
|
|
||||||
return Some(RenderableCell {
|
return Some(RenderableCell {
|
||||||
line: line,
|
line: line,
|
||||||
column: column,
|
column: column,
|
||||||
flags: cell.flags,
|
flags: cell.flags,
|
||||||
c: cell.c,
|
c: cell.c,
|
||||||
fg: fg,
|
fg: fg_rgb,
|
||||||
bg: bg,
|
bg: bg_rgb,
|
||||||
|
bg_alpha: bg_alpha,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,7 +1001,7 @@ impl Term {
|
||||||
self.mode,
|
self.mode,
|
||||||
config,
|
config,
|
||||||
selection,
|
selection,
|
||||||
self.cursor_style
|
self.cursor_style,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue