aboutsummaryrefslogtreecommitdiff
path: root/src/renderer/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/mod.rs')
-rw-r--r--src/renderer/mod.rs318
1 files changed, 182 insertions, 136 deletions
diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs
index bcc896ef..28b44633 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -16,22 +16,22 @@ use std::fs::File;
use std::hash::BuildHasherDefault;
use std::io::{self, Read};
use std::mem::size_of;
-use std::path::{PathBuf};
+use std::path::PathBuf;
use std::ptr;
use std::sync::mpsc;
use std::time::Duration;
use cgmath;
use fnv::FnvHasher;
-use font::{self, Rasterizer, Rasterize, RasterizedGlyph, FontDesc, GlyphKey, FontKey};
+use font::{self, FontDesc, FontKey, GlyphKey, Rasterize, RasterizedGlyph, Rasterizer};
use gl::types::*;
use gl;
-use index::{Line, Column, RangeInclusive};
-use notify::{Watcher, watcher, RecursiveMode, DebouncedEvent};
+use index::{Column, Line, RangeInclusive};
+use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
use config::{self, Config, Delta};
use term::{self, cell, RenderableCell};
-use window::{Size, Pixels};
+use window::{Pixels, Size};
use Rgb;
@@ -40,12 +40,10 @@ static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/
static TEXT_SHADER_V_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl");
// Shader source which is used when live-shader-reload feature is disable
-static TEXT_SHADER_F: &'static str = include_str!(
- concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl")
-);
-static TEXT_SHADER_V: &'static str = include_str!(
- concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl")
-);
+static TEXT_SHADER_F: &'static str =
+ include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl"));
+static TEXT_SHADER_V: &'static str =
+ include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl"));
/// `LoadGlyph` allows for copying a rasterized glyph into graphics memory
pub trait LoadGlyph {
@@ -97,7 +95,6 @@ impl From<ShaderCreationError> for Error {
}
}
-
/// Text drawing program
///
/// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a".
@@ -127,7 +124,6 @@ pub struct ShaderProgram {
padding_y: u8,
}
-
#[derive(Debug, Clone)]
pub struct Glyph {
tex_id: GLuint,
@@ -174,9 +170,10 @@ impl GlyphCache {
pub fn new<L>(
mut rasterizer: Rasterizer,
font: &config::Font,
- loader: &mut L
+ loader: &mut L,
) -> Result<GlyphCache, font::Error>
- where L: LoadGlyph
+ where
+ L: LoadGlyph,
{
let (regular, bold, italic) = Self::compute_font_keys(font, &mut rasterizer)?;
@@ -184,7 +181,8 @@ impl GlyphCache {
// The glyph requested here ('m' at the time of writing) has no special
// meaning.
rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size() })?;
- let metrics = rasterizer.metrics(regular)?;
+
+ let metrics = rasterizer.metrics(regular, font.size())?;
let mut cache = GlyphCache {
cache: HashMap::default(),
@@ -204,11 +202,7 @@ impl GlyphCache {
Ok(cache)
}
- fn load_glyphs_for_font<L: LoadGlyph>(
- &mut self,
- font: FontKey,
- loader: &mut L,
- ) {
+ fn load_glyphs_for_font<L: LoadGlyph>(&mut self, font: FontKey, loader: &mut L) {
let size = self.font_size;
for i in RangeInclusive::new(32u8, 128u8) {
self.get(GlyphKey {
@@ -222,22 +216,23 @@ impl GlyphCache {
/// Computes font keys for (Regular, Bold, Italic)
fn compute_font_keys(
font: &config::Font,
- rasterizer: &mut Rasterizer
+ rasterizer: &mut Rasterizer,
) -> Result<(FontKey, FontKey, FontKey), font::Error> {
let size = font.size();
// Load regular font
let regular_desc = Self::make_desc(&font.normal, font::Slant::Normal, font::Weight::Normal);
- let regular = rasterizer
- .load_font(&regular_desc, size)?;
+ let regular = rasterizer.load_font(&regular_desc, size)?;
// helper to load a description if it is not the regular_desc
- let mut load_or_regular = |desc:FontDesc| {
+ let mut load_or_regular = |desc: FontDesc| {
if desc == regular_desc {
regular
} else {
- rasterizer.load_font(&desc, size).unwrap_or_else(|_| regular)
+ rasterizer
+ .load_font(&desc, size)
+ .unwrap_or_else(|_| regular)
}
};
@@ -269,7 +264,7 @@ impl GlyphCache {
pub fn font_metrics(&self) -> font::Metrics {
self.rasterizer
- .metrics(self.font_key)
+ .metrics(self.font_key, self.font_size)
.expect("metrics load since font is loaded at glyph cache creation")
}
@@ -290,7 +285,7 @@ impl GlyphCache {
rasterized.top -= metrics.descent as i32;
loader.load_glyph(&rasterized)
- })
+ })
}
pub fn update_font_size<L: LoadGlyph>(
&mut self,
@@ -306,8 +301,9 @@ impl GlyphCache {
let font = font.to_owned().with_size(size);
info!("Font size changed: {:?}", font.size);
let (regular, bold, italic) = Self::compute_font_keys(&font, &mut self.rasterizer)?;
+
self.rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size() })?;
- let metrics = self.rasterizer.metrics(regular)?;
+ let metrics = self.rasterizer.metrics(regular, size)?;
self.font_size = font.size;
self.font_key = regular;
@@ -405,11 +401,7 @@ impl Batch {
}
}
- pub fn add_item(
- &mut self,
- cell: &RenderableCell,
- glyph: &Glyph,
- ) {
+ pub fn add_item(&mut self, cell: &RenderableCell, glyph: &Glyph) {
if self.is_empty() {
self.tex = glyph.tex_id;
}
@@ -509,69 +501,99 @@ impl QuadRenderer {
gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
- gl::VertexAttribPointer(0, 2,
- gl::FLOAT, gl::FALSE,
- size_of::<PackedVertex>() as i32,
- ptr::null());
+ gl::VertexAttribPointer(
+ 0,
+ 2,
+ gl::FLOAT,
+ gl::FALSE,
+ size_of::<PackedVertex>() as i32,
+ ptr::null(),
+ );
gl::EnableVertexAttribArray(0);
- gl::BufferData(gl::ARRAY_BUFFER,
- (size_of::<PackedVertex>() * vertices.len()) as GLsizeiptr,
- vertices.as_ptr() as *const _,
- gl::STATIC_DRAW);
+ gl::BufferData(
+ gl::ARRAY_BUFFER,
+ (size_of::<PackedVertex>() * vertices.len()) as GLsizeiptr,
+ vertices.as_ptr() as *const _,
+ gl::STATIC_DRAW,
+ );
// ---------------------
// Set up element buffer
// ---------------------
- let indices: [u32; 6] = [0, 1, 3,
- 1, 2, 3];
+ let indices: [u32; 6] = [0, 1, 3, 1, 2, 3];
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
- gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
- (6 * size_of::<u32>()) as isize,
- indices.as_ptr() as *const _,
- gl::STATIC_DRAW);
+ gl::BufferData(
+ gl::ELEMENT_ARRAY_BUFFER,
+ (6 * size_of::<u32>()) as isize,
+ indices.as_ptr() as *const _,
+ gl::STATIC_DRAW,
+ );
// ----------------------------
// Setup vertex instance buffer
// ----------------------------
gl::BindBuffer(gl::ARRAY_BUFFER, vbo_instance);
- gl::BufferData(gl::ARRAY_BUFFER,
- (BATCH_MAX * size_of::<InstanceData>()) as isize,
- ptr::null(), gl::STREAM_DRAW);
+ gl::BufferData(
+ gl::ARRAY_BUFFER,
+ (BATCH_MAX * size_of::<InstanceData>()) as isize,
+ ptr::null(),
+ gl::STREAM_DRAW,
+ );
// coords
- gl::VertexAttribPointer(1, 2,
- gl::FLOAT, gl::FALSE,
- size_of::<InstanceData>() as i32,
- ptr::null());
+ gl::VertexAttribPointer(
+ 1,
+ 2,
+ gl::FLOAT,
+ gl::FALSE,
+ size_of::<InstanceData>() as i32,
+ ptr::null(),
+ );
gl::EnableVertexAttribArray(1);
gl::VertexAttribDivisor(1, 1);
// glyphoffset
- gl::VertexAttribPointer(2, 4,
- gl::FLOAT, gl::FALSE,
- size_of::<InstanceData>() as i32,
- (2 * size_of::<f32>()) as *const _);
+ gl::VertexAttribPointer(
+ 2,
+ 4,
+ gl::FLOAT,
+ gl::FALSE,
+ size_of::<InstanceData>() as i32,
+ (2 * size_of::<f32>()) as *const _,
+ );
gl::EnableVertexAttribArray(2);
gl::VertexAttribDivisor(2, 1);
// uv
- gl::VertexAttribPointer(3, 4,
- gl::FLOAT, gl::FALSE,
- size_of::<InstanceData>() as i32,
- (6 * size_of::<f32>()) as *const _);
+ gl::VertexAttribPointer(
+ 3,
+ 4,
+ gl::FLOAT,
+ gl::FALSE,
+ size_of::<InstanceData>() as i32,
+ (6 * size_of::<f32>()) as *const _,
+ );
gl::EnableVertexAttribArray(3);
gl::VertexAttribDivisor(3, 1);
// color
- gl::VertexAttribPointer(4, 3,
- gl::FLOAT, gl::FALSE,
- size_of::<InstanceData>() as i32,
- (10 * size_of::<f32>()) as *const _);
+ gl::VertexAttribPointer(
+ 4,
+ 3,
+ gl::FLOAT,
+ gl::FALSE,
+ size_of::<InstanceData>() as i32,
+ (10 * size_of::<f32>()) as *const _,
+ );
gl::EnableVertexAttribArray(4);
gl::VertexAttribDivisor(4, 1);
// color
- gl::VertexAttribPointer(5, 4,
- gl::FLOAT, gl::FALSE,
- size_of::<InstanceData>() as i32,
- (13 * size_of::<f32>()) as *const _);
+ gl::VertexAttribPointer(
+ 5,
+ 4,
+ gl::FLOAT,
+ gl::FALSE,
+ size_of::<InstanceData>() as i32,
+ (13 * size_of::<f32>()) as *const _,
+ );
gl::EnableVertexAttribArray(5);
gl::VertexAttribDivisor(5, 1);
@@ -585,18 +607,23 @@ impl QuadRenderer {
::std::thread::spawn(move || {
let (tx, rx) = ::std::sync::mpsc::channel();
// The Duration argument is a debouncing period.
- let mut watcher = watcher(tx, Duration::from_millis(10)).expect("create file watcher");
- watcher.watch(TEXT_SHADER_F_PATH, RecursiveMode::NonRecursive)
- .expect("watch fragment shader");
- watcher.watch(TEXT_SHADER_V_PATH, RecursiveMode::NonRecursive)
- .expect("watch vertex shader");
+ let mut watcher =
+ watcher(tx, Duration::from_millis(10)).expect("create file watcher");
+ watcher
+ .watch(TEXT_SHADER_F_PATH, RecursiveMode::NonRecursive)
+ .expect("watch fragment shader");
+ watcher
+ .watch(TEXT_SHADER_V_PATH, RecursiveMode::NonRecursive)
+ .expect("watch vertex shader");
loop {
let event = rx.recv().expect("watcher event");
match event {
DebouncedEvent::Rename(_, _) => continue,
- DebouncedEvent::Create(_) | DebouncedEvent::Write(_) | DebouncedEvent::Chmod(_) => {
+ DebouncedEvent::Create(_)
+ | DebouncedEvent::Write(_)
+ | DebouncedEvent::Chmod(_) => {
msg_tx.send(Msg::ShaderReload).expect("msg send ok");
}
_ => {}
@@ -629,17 +656,21 @@ impl QuadRenderer {
config: &Config,
props: &term::SizeInfo,
visual_bell_intensity: f64,
- func: F
+ func: F,
) -> T
- where F: FnOnce(RenderApi) -> T
+ where
+ F: FnOnce(RenderApi) -> T,
{
while let Ok(msg) = self.rx.try_recv() {
match msg {
Msg::ShaderReload => {
- self.reload_shaders(config, Size {
- width: Pixels(props.width as u32),
- height: Pixels(props.height as u32)
- });
+ self.reload_shaders(
+ config,
+ Size {
+ width: Pixels(props.width as u32),
+ height: Pixels(props.height as u32),
+ },
+ );
}
}
}
@@ -677,7 +708,8 @@ impl QuadRenderer {
}
pub fn with_loader<F, T>(&mut self, func: F) -> T
- where F: FnOnce(LoaderApi) -> T
+ where
+ F: FnOnce(LoaderApi) -> T,
{
unsafe {
gl::ActiveTexture(gl::TEXTURE0);
@@ -696,12 +728,12 @@ impl QuadRenderer {
Ok(program) => {
warn!(" ... OK");
program
- },
+ }
Err(err) => {
match err {
ShaderCreationError::Io(err) => {
error!("Error reading shader file: {}", err);
- },
+ }
ShaderCreationError::Compile(path, log) => {
error!("Error compiling shader at {:?}\n{}", path, log);
}
@@ -724,7 +756,12 @@ impl QuadRenderer {
// viewport
unsafe {
- gl::Viewport(padding_x, padding_y, width - 2 * padding_x, height - 2 * padding_y);
+ gl::Viewport(
+ padding_x,
+ padding_y,
+ width - 2 * padding_x,
+ height - 2 * padding_y,
+ );
}
// update projection
@@ -750,8 +787,12 @@ impl<'a> RenderApi<'a> {
fn render_batch(&mut self) {
unsafe {
- gl::BufferSubData(gl::ARRAY_BUFFER, 0, self.batch.size() as isize,
- self.batch.instances.as_ptr() as *const _);
+ gl::BufferSubData(
+ gl::ARRAY_BUFFER,
+ 0,
+ self.batch.size() as isize,
+ self.batch.instances.as_ptr() as *const _,
+ );
}
// Bind texture if necessary
@@ -764,29 +805,33 @@ impl<'a> RenderApi<'a> {
unsafe {
self.program.set_background_pass(true);
- gl::DrawElementsInstanced(gl::TRIANGLES,
- 6, gl::UNSIGNED_INT, ptr::null(),
- self.batch.len() as GLsizei);
+ gl::DrawElementsInstanced(
+ gl::TRIANGLES,
+ 6,
+ gl::UNSIGNED_INT,
+ ptr::null(),
+ self.batch.len() as GLsizei,
+ );
self.program.set_background_pass(false);
- gl::DrawElementsInstanced(gl::TRIANGLES,
- 6, gl::UNSIGNED_INT, ptr::null(),
- self.batch.len() as GLsizei);
+ gl::DrawElementsInstanced(
+ gl::TRIANGLES,
+ 6,
+ gl::UNSIGNED_INT,
+ ptr::null(),
+ self.batch.len() as GLsizei,
+ );
}
self.batch.clear();
}
/// Render a string in a predefined location. Used for printing render time for profiling and
/// optimization.
- pub fn render_string(
- &mut self,
- string: &str,
- glyph_cache: &mut GlyphCache,
- color: Rgb,
- ) {
+ pub fn render_string(&mut self, string: &str, glyph_cache: &mut GlyphCache, color: Rgb) {
let line = Line(23);
let col = Column(0);
- let cells = string.chars()
+ let cells = string
+ .chars()
.enumerate()
.map(|(i, c)| RenderableCell {
line,
@@ -795,7 +840,7 @@ impl<'a> RenderApi<'a> {
bg: color,
fg: Rgb { r: 0, g: 0, b: 0 },
flags: cell::Flags::empty(),
- bg_alpha: 1.0
+ bg_alpha: 1.0,
})
.collect::<Vec<_>>();
@@ -838,7 +883,7 @@ impl<'a> RenderApi<'a> {
let mut glyph_key = GlyphKey {
font_key,
size: glyph_cache.font_size,
- c: cell.c
+ c: cell.c,
};
// Don't render text of HIDDEN cells
@@ -859,7 +904,7 @@ impl<'a> RenderApi<'a> {
let glyph_key = GlyphKey {
font_key,
size: glyph_cache.font_size,
- c: '_'
+ c: '_',
};
let underscore = glyph_cache.get(glyph_key, self);
@@ -959,28 +1004,22 @@ impl ShaderProgram {
pub fn new(
config: &Config,
- size: Size<Pixels<u32>>
+ size: Size<Pixels<u32>>,
) -> Result<ShaderProgram, ShaderCreationError> {
let vertex_source = if cfg!(feature = "live-shader-reload") {
None
} else {
Some(TEXT_SHADER_V)
};
- let vertex_shader = ShaderProgram::create_shader(
- TEXT_SHADER_V_PATH,
- gl::VERTEX_SHADER,
- vertex_source
- )?;
+ let vertex_shader =
+ ShaderProgram::create_shader(TEXT_SHADER_V_PATH, gl::VERTEX_SHADER, vertex_source)?;
let frag_source = if cfg!(feature = "live-shader-reload") {
None
} else {
Some(TEXT_SHADER_F)
};
- let fragment_shader = ShaderProgram::create_shader(
- TEXT_SHADER_F_PATH,
- gl::FRAGMENT_SHADER,
- frag_source
- )?;
+ let fragment_shader =
+ ShaderProgram::create_shader(TEXT_SHADER_F_PATH, gl::FRAGMENT_SHADER, frag_source)?;
let program = ShaderProgram::create_program(vertex_shader, fragment_shader)?;
unsafe {
@@ -1060,10 +1099,13 @@ impl ShaderProgram {
info!("width: {}, height: {}", width, height);
unsafe {
- gl::UniformMatrix4fv(self.u_projection,
- 1, gl::FALSE, projection.as_ptr() as *const _);
+ gl::UniformMatrix4fv(
+ self.u_projection,
+ 1,
+ gl::FALSE,
+ projection.as_ptr() as *const _,
+ );
}
-
}
fn set_term_uniforms(&self, props: &term::SizeInfo) {
@@ -1080,11 +1122,7 @@ impl ShaderProgram {
}
fn set_background_pass(&self, background_pass: bool) {
- let value = if background_pass {
- 1
- } else {
- 0
- };
+ let value = if background_pass { 1 } else { 0 };
unsafe {
gl::Uniform1i(self.u_background, value);
@@ -1109,11 +1147,10 @@ impl ShaderProgram {
}
}
-
fn create_shader(
path: &str,
kind: GLenum,
- source: Option<&'static str>
+ source: Option<&'static str>,
) -> Result<GLuint, ShaderCreationError> {
let from_disk;
let source = if let Some(src) = source {
@@ -1144,7 +1181,9 @@ impl ShaderProgram {
let log = get_shader_info_log(shader);
// Cleanup
- unsafe { gl::DeleteShader(shader); }
+ unsafe {
+ gl::DeleteShader(shader);
+ }
Err(ShaderCreationError::Compile(PathBuf::from(path), log))
}
@@ -1170,7 +1209,12 @@ fn get_program_info_log(program: GLuint) -> String {
let mut actual_length: GLint = 0;
let mut buf: Vec<u8> = Vec::with_capacity(max_length as usize);
unsafe {
- gl::GetProgramInfoLog(program, max_length, &mut actual_length, buf.as_mut_ptr() as *mut _);
+ gl::GetProgramInfoLog(
+ program,
+ max_length,
+ &mut actual_length,
+ buf.as_mut_ptr() as *mut _,
+ );
}
// Build a string
@@ -1193,7 +1237,12 @@ fn get_shader_info_log(shader: GLuint) -> String {
let mut actual_length: GLint = 0;
let mut buf: Vec<u8> = Vec::with_capacity(max_length as usize);
unsafe {
- gl::GetShaderInfoLog(shader, max_length, &mut actual_length, buf.as_mut_ptr() as *mut _);
+ gl::GetShaderInfoLog(
+ shader,
+ max_length,
+ &mut actual_length,
+ buf.as_mut_ptr() as *mut _,
+ );
}
// Build a string
@@ -1248,10 +1297,8 @@ impl ::std::fmt::Display for ShaderCreationError {
ShaderCreationError::Io(ref err) => write!(f, "couldn't read shader: {}", err),
ShaderCreationError::Compile(ref _path, ref s) => {
write!(f, "failed compiling shader: {}", s)
- },
- ShaderCreationError::Link(ref s) => {
- write!(f, "failed linking shader: {}", s)
- },
+ }
+ ShaderCreationError::Link(ref s) => write!(f, "failed linking shader: {}", s),
}
}
}
@@ -1262,7 +1309,6 @@ impl From<io::Error> for ShaderCreationError {
}
}
-
/// Manages a single texture atlas
///
/// The strategy for filling an atlas looks roughly like this:
@@ -1332,7 +1378,7 @@ impl Atlas {
0,
gl::RGB,
gl::UNSIGNED_BYTE,
- ptr::null()
+ ptr::null(),
);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
@@ -1407,7 +1453,7 @@ impl Atlas {
height,
gl::RGB,
gl::UNSIGNED_BYTE,
- glyph.buf.as_ptr() as *const _
+ glyph.buf.as_ptr() as *const _,
);
gl::BindTexture(gl::TEXTURE_2D, 0);