Skip to content

Commit

Permalink
Add Sixel support
Browse files Browse the repository at this point in the history
Fixes #910
  • Loading branch information
ayosec committed Mar 11, 2021
1 parent d5dd009 commit 18fd66e
Show file tree
Hide file tree
Showing 27 changed files with 1,981 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- IME composition preview not appearing on Windows
- Synchronized terminal updates using `DCS = 1 s ST`/`DCS = 2 s ST`
- Regex terminal hints ([see features.md](./docs/features.md#hints))
- Support for Sixel protocol

### Fixed

Expand Down
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions alacritty/Cargo.toml
Expand Up @@ -35,6 +35,7 @@ libc = "0.2"
unicode-width = "0.1"
bitflags = "1"
dirs = "3.0.1"
memoffset = "0.6.1"

[build-dependencies]
gl_generator = "0.14.0"
Expand Down
40 changes: 40 additions & 0 deletions alacritty/res/graphics.f.glsl
@@ -0,0 +1,40 @@
#version 330 core

// Index in the textures[] uniform.
flat in int texId;

// Texture coordinates.
in vec2 texCoords;

// Array with graphics data.
uniform sampler2D textures[16];

// Computed color.
out vec4 color;

void main() {
// The expression `textures[texId]` can't be used in OpenGL 3.3.
// If we try to use it, the compiler throws this error:
//
// sampler arrays indexed with non-constant expressions
// are forbidden in GLSL 1.30 and later
//
// To overcome this limitation we use a switch for every valid
// value of `texId`.
//
// The first expression (`textures[texId]`) works with OpenGL 4.0
// or later (using `#version 400 core`). If Alacritty drops support
// for OpenGL 3.3, this switch block can be replaced with it.


#define TEX(N) case N: color = texture(textures[N], texCoords); break;

switch(texId) {
TEX( 0) TEX( 1) TEX( 2) TEX( 3)
TEX( 4) TEX( 5) TEX( 6) TEX( 7)
TEX( 8) TEX( 9) TEX(10) TEX(11)
TEX(12) TEX(13) TEX(14) TEX(15)
default:
discard;
}
}
79 changes: 79 additions & 0 deletions alacritty/res/graphics.v.glsl
@@ -0,0 +1,79 @@
#version 330 core

// ------
// INPUTS

// Texture associated to the graphic.
layout(location = 0) in int textureId;

// Sides where the vertex is located.
//
// Bit 0 (LSB) is 0 for top and 1 for bottom.
// Bit 1 is 0 for left and 1 for right.
layout(location = 1) in int sides;

// Column number in the grid where the left vertex is set.
layout(location = 2) in float column;

// Line number in the grid where the left vertex is set.
layout(location = 3) in float line;

// Height in pixels of the texture.
layout(location = 4) in float height;

// Width in pixels of the texture.
layout(location = 5) in float width;

// Offset in the X direction.
layout(location = 6) in float offsetX;

// Offset in the Y direction.
layout(location = 7) in float offsetY;

// Height in pixels of a single cell when the graphic was added.
layout(location = 8) in float baseCellHeight;

// -------
// OUTPUTS

// Texture sent to the fragment shader.
flat out int texId;

// Coordinates sent to the fragment shader.
out vec2 texCoords;

// --------
// UNIFORMS

// Width and height of a single cell.
uniform vec2 cellDimensions;

// Width and height of the view.
uniform vec2 viewDimensions;


#define IS_RIGHT_SIDE ((sides & 1) == 1)
#define IS_BOTTOM_SIDE ((sides & 2) == 2)

void main() {
float scale = cellDimensions.y / baseCellHeight;
float x = (column * cellDimensions.x - offsetX * scale) / (viewDimensions.x / 2) - 1;
float y = -(line * cellDimensions.y - offsetY * scale) / (viewDimensions.y / 2) + 1;

vec4 position = vec4(x, y, 0, 1);
vec2 coords = vec2(0, 0);

if(IS_RIGHT_SIDE) {
position.x += scale * width / (viewDimensions.x / 2);
coords.x = 1;
}

if(IS_BOTTOM_SIDE) {
position.y += -scale * height / (viewDimensions.y / 2);
coords.y = 1;
}

gl_Position = position;
texCoords = coords;
texId = textureId;
}
3 changes: 3 additions & 0 deletions alacritty/src/display/content.rs
Expand Up @@ -6,6 +6,7 @@ use std::ops::{Deref, DerefMut, RangeInclusive};
use alacritty_terminal::ansi::{Color, CursorShape, NamedColor};
use alacritty_terminal::config::Config;
use alacritty_terminal::event::EventListener;
use alacritty_terminal::graphics::GraphicCell;
use alacritty_terminal::grid::{Dimensions, Indexed};
use alacritty_terminal::index::{Column, Direction, Line, Point};
use alacritty_terminal::term::cell::{Cell, Flags};
Expand Down Expand Up @@ -178,6 +179,7 @@ impl<'a> Iterator for RenderableContent<'a> {
pub struct RenderableCell {
pub character: char,
pub zerowidth: Option<Vec<char>>,
pub graphic: Option<GraphicCell>,
pub point: Point,
pub fg: Rgb,
pub bg: Rgb,
Expand Down Expand Up @@ -240,6 +242,7 @@ impl RenderableCell {
RenderableCell {
character,
zerowidth: cell.zerowidth().map(|zerowidth| zerowidth.to_vec()),
graphic: cell.graphic().cloned(),
point: cell.point,
fg: fg_rgb,
bg: bg_rgb,
Expand Down
14 changes: 13 additions & 1 deletion alacritty/src/display/mod.rs
Expand Up @@ -470,7 +470,7 @@ impl Display {
/// This call may block if vsync is enabled.
pub fn draw<T: EventListener>(
&mut self,
terminal: MutexGuard<'_, Term<T>>,
mut terminal: MutexGuard<'_, Term<T>>,
message_buffer: &MessageBuffer,
config: &Config,
mouse: &Mouse,
Expand Down Expand Up @@ -505,15 +505,22 @@ impl Display {
let vi_mode = terminal.mode().contains(TermMode::VI);
let vi_mode_cursor = if vi_mode { Some(terminal.vi_mode_cursor) } else { None };

let graphics_queues = terminal.graphics_take_queues();

// Drop terminal as early as possible to free lock.
drop(terminal);

self.renderer.with_api(&config.ui_config, &size_info, |api| {
api.clear(background_color);
});

if let Some(graphics_queues) = graphics_queues {
self.renderer.graphics_run_updates(graphics_queues, &size_info);
}

let mut lines = RenderLines::new();
let mut urls = Urls::new();
let mut graphics_list = renderer::graphics::RenderList::default();

// Draw grid.
{
Expand Down Expand Up @@ -542,12 +549,17 @@ impl Display {
// Update underline/strikeout.
lines.update(&cell);

// Track any graphic present in the cell.
graphics_list.update(&cell);

// Draw the cell.
api.render_cell(cell, glyph_cache);
}
});
}

self.renderer.graphics_draw(graphics_list, &size_info);

let mut rects = lines.rects(&metrics, &size_info);

// Update visible URLs.
Expand Down

0 comments on commit 18fd66e

Please sign in to comment.