aboutsummaryrefslogtreecommitdiff
path: root/src/renderer/mod.rs
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-10-23 15:37:06 -0700
committerJoe Wilm <joe@jwilm.com>2016-10-23 15:37:06 -0700
commit5876b4bf7a88a59482aefcc85e04a9ef6ecfed74 (patch)
tree8e55fbf061383569fca610418e02368b05a29fc2 /src/renderer/mod.rs
parentea07f03ac901c366ed31da540711b84ca9e75602 (diff)
downloadalacritty-5876b4bf7a88a59482aefcc85e04a9ef6ecfed74.tar.gz
alacritty-5876b4bf7a88a59482aefcc85e04a9ef6ecfed74.zip
Proof of concept live reloading for colors
The architecture here is really poor. Need to move file watching into a dedicated location and probably have an spmc broadcast queue. other modules besides rendering will care about config reloading in the future.
Diffstat (limited to 'src/renderer/mod.rs')
-rw-r--r--src/renderer/mod.rs139
1 files changed, 110 insertions, 29 deletions
diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs
index 7ddf1d01..959b3d4f 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -20,6 +20,7 @@ use std::path::{PathBuf};
use std::ptr;
use std::sync::Arc;
use std::sync::atomic::{Ordering, AtomicBool};
+use std::sync::mpsc;
use cgmath;
use font::{self, Rasterizer, RasterizedGlyph, FontDesc, GlyphKey, FontKey};
@@ -42,6 +43,38 @@ pub trait LoadGlyph {
fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph;
}
+enum Msg {
+ ConfigReload(Config),
+ ShaderReload,
+}
+
+/// Colors!
+///
+/// FIXME this is obviously bad; need static for reload logic for now. Hacking something in with
+/// minimal effort and will improve later.
+///
+/// Only renderer is allowed to access this to prevent race conditions
+static mut COLORS: [Rgb; 18] = [
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+ Rgb { r: 0, g: 0, b: 0 },
+];
+
/// Text drawing program
///
/// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a".
@@ -222,7 +255,6 @@ struct InstanceData {
#[derive(Debug)]
pub struct QuadRenderer {
program: ShaderProgram,
- should_reload: Arc<AtomicBool>,
vao: GLuint,
vbo: GLuint,
ebo: GLuint,
@@ -230,6 +262,7 @@ pub struct QuadRenderer {
atlas: Vec<Atlas>,
active_tex: GLuint,
batch: Batch,
+ rx: mpsc::Receiver<Msg>,
}
#[derive(Debug)]
@@ -272,6 +305,18 @@ impl Batch {
self.tex = glyph.tex_id;
}
+ // TODO move colors list to uniform buffer and do this indexing in vertex shader
+ let fg = match cell.fg {
+ ::term::cell::Color::Rgb(rgb) => rgb,
+ ::term::cell::Color::Ansi(ansi) => unsafe { COLORS[ansi as usize] },
+ };
+
+ // TODO move colors list to uniform buffer and do this indexing in vertex shader
+ let bg = match cell.bg {
+ ::term::cell::Color::Rgb(rgb) => rgb,
+ ::term::cell::Color::Ansi(ansi) => unsafe { COLORS[ansi as usize] },
+ };
+
let mut instance = InstanceData {
col: col,
row: row,
@@ -286,23 +331,23 @@ impl Batch {
uv_width: glyph.uv_width,
uv_height: glyph.uv_height,
- r: cell.fg.r as f32,
- g: cell.fg.g as f32,
- b: cell.fg.b as f32,
+ r: fg.r as f32,
+ g: fg.g as f32,
+ b: fg.b as f32,
- bg_r: cell.bg.r as f32,
- bg_g: cell.bg.g as f32,
- bg_b: cell.bg.b as f32,
+ bg_r: bg.r as f32,
+ bg_g: bg.g as f32,
+ bg_b: bg.b as f32,
};
if cell.flags.contains(cell::INVERSE) {
- instance.r = cell.bg.r as f32;
- instance.g = cell.bg.g as f32;
- instance.b = cell.bg.b as f32;
+ instance.r = bg.r as f32;
+ instance.g = bg.g as f32;
+ instance.b = bg.b as f32;
- instance.bg_r = cell.fg.r as f32;
- instance.bg_g = cell.fg.g as f32;
- instance.bg_b = cell.fg.b as f32;
+ instance.bg_r = fg.r as f32;
+ instance.bg_g = fg.g as f32;
+ instance.bg_b = fg.b as f32;
}
self.instances.push(instance);
@@ -345,7 +390,7 @@ const ATLAS_SIZE: i32 = 1024;
impl QuadRenderer {
// TODO should probably hand this a transform instead of width/height
- pub fn new(width: u32, height: u32) -> QuadRenderer {
+ pub fn new(config: &Config, width: u32, height: u32) -> QuadRenderer {
let program = ShaderProgram::new(width, height).unwrap();
let mut vao: GLuint = 0;
@@ -448,11 +493,14 @@ impl QuadRenderer {
let should_reload = Arc::new(AtomicBool::new(false));
let should_reload2 = should_reload.clone();
+ let (msg_tx, msg_rx) = mpsc::channel();
+
::std::thread::spawn(move || {
- let (tx, rx) = ::std::sync::mpsc::channel();
+ let (tx, rx) = mpsc::channel();
let mut watcher = Watcher::new(tx).unwrap();
watcher.watch(TEXT_SHADER_F_PATH).expect("watch fragment shader");
watcher.watch(TEXT_SHADER_V_PATH).expect("watch vertex shader");
+ watcher.watch("/home/jwilm/.alacritty.yml").expect("watch alacritty yml");
loop {
let event = rx.recv().expect("watcher event");
@@ -468,10 +516,17 @@ impl QuadRenderer {
if let Err(err) = watcher.watch(path) {
println!("failed to establish watch on {:?}: {:?}", path, err);
}
- }
- // This is last event we see after saving in vim
- should_reload2.store(true, Ordering::Relaxed);
+ if path == ::std::path::Path::new("/home/jwilm/.alacritty.yml") {
+ if let Ok(config) = Config::load() {
+ msg_tx.send(Msg::ConfigReload(config))
+ .expect("msg send ok");
+ };
+ } else {
+ msg_tx.send(Msg::ShaderReload)
+ .expect("msg send ok");
+ }
+ }
}
}
}
@@ -479,7 +534,6 @@ impl QuadRenderer {
let mut renderer = QuadRenderer {
program: program,
- should_reload: should_reload,
vao: vao,
vbo: vbo,
ebo: ebo,
@@ -487,8 +541,13 @@ impl QuadRenderer {
atlas: Vec::new(),
active_tex: 0,
batch: Batch::new(),
+ rx: msg_rx,
};
+ unsafe {
+ COLORS = config.color_list();
+ }
+
let atlas = Atlas::new(ATLAS_SIZE);
renderer.atlas.push(atlas);
@@ -498,8 +557,17 @@ impl QuadRenderer {
pub fn with_api<F, T>(&mut self, props: &term::SizeInfo, func: F) -> T
where F: FnOnce(RenderApi) -> T
{
- if self.should_reload.load(Ordering::Relaxed) {
- self.reload_shaders(props.width as u32, props.height as u32);
+ while let Ok(msg) = self.rx.try_recv() {
+ match msg {
+ Msg::ConfigReload(config) => {
+ unsafe {
+ COLORS = config.color_list();
+ }
+ },
+ Msg::ShaderReload => {
+ self.reload_shaders(props.width as u32, props.height as u32);
+ }
+ }
}
unsafe {
@@ -544,7 +612,6 @@ impl QuadRenderer {
}
pub fn reload_shaders(&mut self, width: u32, height: u32) {
- self.should_reload.store(false, Ordering::Relaxed);
let program = match ShaderProgram::new(width, height) {
Ok(program) => program,
Err(err) => {
@@ -612,10 +679,9 @@ impl<'a> RenderApi<'a> {
/// optimization.
pub fn render_string(
&mut self,
- bg: &Rgb,
s: &str,
glyph_cache: &mut GlyphCache,
- color: &Rgb,
+ color: &::term::cell::Color,
) {
let row = 40.0;
let mut col = 100.0;
@@ -630,8 +696,8 @@ impl<'a> RenderApi<'a> {
if let Some(glyph) = glyph_cache.get(&glyph_key, self) {
let cell = Cell {
c: c,
- fg: *color,
- bg: *bg,
+ fg: color.clone(),
+ bg: cell::Color::Rgb(Rgb { r: 0, g: 0, b: 0}),
flags: cell::INVERSE,
};
self.add_render_item(row, col, &cell, glyph);
@@ -658,12 +724,27 @@ impl<'a> RenderApi<'a> {
}
}
- pub fn render_grid(&mut self, bg: &Rgb, grid: &Grid<Cell>, glyph_cache: &mut GlyphCache) {
+ pub fn render_grid(
+ &mut self,
+ grid: &Grid<Cell>,
+ glyph_cache: &mut GlyphCache
+ ) {
+ // TODO should be built into renderer
+ let color = unsafe { COLORS[::ansi::Color::Background as usize] };
+ unsafe {
+ gl::ClearColor(
+ color.r as f32 / 255.0,
+ color.g as f32 / 255.0,
+ color.b as f32 / 255.0,
+ 1.0
+ );
+ gl::Clear(gl::COLOR_BUFFER_BIT);
+ }
+
for (i, line) in grid.lines().enumerate() {
for (j, cell) in line.cells().enumerate() {
// Skip empty cells
- if cell.c == ' ' &&
- cell.bg == *bg &&
+ if cell.c == ' ' && cell.bg == cell::Color::Ansi(::ansi::Color::Background) &&
!cell.flags.contains(cell::INVERSE)
{
continue;