diff options
Diffstat (limited to 'alacritty/src/renderer/mod.rs')
-rw-r--r-- | alacritty/src/renderer/mod.rs | 195 |
1 files changed, 27 insertions, 168 deletions
diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index af1f3c3e..ccdd2812 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -30,21 +30,17 @@ use crate::config::ui_config::{Delta, UIConfig}; use crate::cursor; use crate::gl; use crate::gl::types::*; -use crate::renderer::rects::RenderRect; +use crate::renderer::rects::{RectRenderer, RectShaderProgram, RenderRect}; pub mod rects; // Shader paths for live reload. static TEXT_SHADER_F_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl"); static TEXT_SHADER_V_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl"); -static RECT_SHADER_F_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/rect.f.glsl"); -static RECT_SHADER_V_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/rect.v.glsl"); // Shader source which is used when live-shader-reload feature is disable. static TEXT_SHADER_F: &str = include_str!("../../res/text.f.glsl"); static TEXT_SHADER_V: &str = include_str!("../../res/text.v.glsl"); -static RECT_SHADER_F: &str = include_str!("../../res/rect.f.glsl"); -static RECT_SHADER_V: &str = include_str!("../../res/rect.v.glsl"); /// `LoadGlyph` allows for copying a rasterized glyph into graphics memory. pub trait LoadGlyph { @@ -110,17 +106,6 @@ pub struct TextShaderProgram { u_background: GLint, } -/// Rectangle drawing program. -/// -/// Uniforms are prefixed with "u". -#[derive(Debug)] -pub struct RectShaderProgram { - /// Program id. - id: GLuint, - /// Rectangle color. - u_color: GLint, -} - #[derive(Copy, Debug, Clone)] pub struct Glyph { tex_id: GLuint, @@ -410,17 +395,16 @@ struct InstanceData { #[derive(Debug)] pub struct QuadRenderer { program: TextShaderProgram, - rect_program: RectShaderProgram, vao: GLuint, ebo: GLuint, vbo_instance: GLuint, - rect_vao: GLuint, - rect_vbo: GLuint, atlas: Vec<Atlas>, current_atlas: usize, active_tex: GLuint, batch: Batch, rx: mpsc::Receiver<Msg>, + + rect_renderer: RectRenderer, } #[derive(Debug)] @@ -526,17 +510,12 @@ const ATLAS_SIZE: i32 = 1024; impl QuadRenderer { pub fn new() -> Result<QuadRenderer, Error> { let program = TextShaderProgram::new()?; - let rect_program = RectShaderProgram::new()?; let mut vao: GLuint = 0; let mut ebo: GLuint = 0; let mut vbo_instance: GLuint = 0; - let mut rect_vao: GLuint = 0; - let mut rect_vbo: GLuint = 0; - let mut rect_ebo: GLuint = 0; - unsafe { gl::Enable(gl::BLEND); gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR); @@ -617,20 +596,6 @@ impl QuadRenderer { // Background color. add_attr!(4, gl::UNSIGNED_BYTE, u8); - // Rectangle setup. - gl::GenVertexArrays(1, &mut rect_vao); - gl::GenBuffers(1, &mut rect_vbo); - gl::GenBuffers(1, &mut rect_ebo); - gl::BindVertexArray(rect_vao); - let indices: [i32; 6] = [0, 1, 3, 1, 2, 3]; - gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, rect_ebo); - gl::BufferData( - gl::ELEMENT_ARRAY_BUFFER, - (size_of::<i32>() * indices.len()) as _, - indices.as_ptr() as *const _, - gl::STATIC_DRAW, - ); - // Cleanup. gl::BindVertexArray(0); gl::BindBuffer(gl::ARRAY_BUFFER, 0); @@ -651,6 +616,12 @@ impl QuadRenderer { watcher .watch(TEXT_SHADER_V_PATH, RecursiveMode::NonRecursive) .expect("watch vertex shader"); + watcher + .watch(rects::RECT_SHADER_V_PATH, RecursiveMode::NonRecursive) + .expect("watch rect vertex shader"); + watcher + .watch(rects::RECT_SHADER_F_PATH, RecursiveMode::NonRecursive) + .expect("watch rect fragment shader"); loop { let event = rx.recv().expect("watcher event"); @@ -670,12 +641,10 @@ impl QuadRenderer { let mut renderer = Self { program, - rect_program, + rect_renderer: RectRenderer::new()?, vao, ebo, vbo_instance, - rect_vao, - rect_vbo, atlas: Vec::new(), current_atlas: 0, active_tex: 0, @@ -690,56 +659,31 @@ impl QuadRenderer { } /// Draw all rectangles simultaneously to prevent excessive program swaps. - pub fn draw_rects(&mut self, props: &SizeInfo, rects: Vec<RenderRect>) { - // Swap to rectangle rendering program. - unsafe { - // Swap program. - gl::UseProgram(self.rect_program.id); + pub fn draw_rects(&mut self, size_info: &SizeInfo, rects: Vec<RenderRect>) { + if rects.is_empty() { + return; + } + // Prepare rect rendering state. + unsafe { // Remove padding from viewport. - gl::Viewport(0, 0, props.width() as i32, props.height() as i32); - - // Change blending strategy. + gl::Viewport(0, 0, size_info.width() as i32, size_info.height() as i32); gl::BlendFuncSeparate(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA, gl::SRC_ALPHA, gl::ONE); - - // Setup data and buffers. - gl::BindVertexArray(self.rect_vao); - gl::BindBuffer(gl::ARRAY_BUFFER, self.rect_vbo); - - // Position. - gl::VertexAttribPointer( - 0, - 2, - gl::FLOAT, - gl::FALSE, - (size_of::<f32>() * 2) as _, - ptr::null(), - ); - gl::EnableVertexAttribArray(0); } - // Draw all the rects. - for rect in rects { - self.render_rect(&rect, props); - } + self.rect_renderer.draw(size_info, rects); - // Deactivate rectangle program again. + // Activate regular state again. unsafe { // Reset blending strategy. gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR); - // Reset data and buffers. - gl::BindBuffer(gl::ARRAY_BUFFER, 0); - gl::BindVertexArray(0); - - let padding_x = props.padding_x() as i32; - let padding_y = props.padding_y() as i32; - let width = props.width() as i32; - let height = props.height() as i32; + // Restore viewport with padding. + let padding_x = size_info.padding_x() as i32; + let padding_y = size_info.padding_y() as i32; + let width = size_info.width() as i32; + let height = size_info.height() as i32; gl::Viewport(padding_x, padding_y, width - 2 * padding_x, height - 2 * padding_y); - - // Disable program. - gl::UseProgram(0); } } @@ -832,7 +776,7 @@ impl QuadRenderer { self.active_tex = 0; self.program = program; - self.rect_program = rect_program; + self.rect_renderer.set_program(rect_program); } pub fn resize(&mut self, size: &SizeInfo) { @@ -856,43 +800,6 @@ impl QuadRenderer { gl::UseProgram(0); } } - - /// Render a rectangle. - /// - /// This requires the rectangle program to be activated. - fn render_rect(&mut self, rect: &RenderRect, size: &SizeInfo) { - // Do nothing when alpha is fully transparent. - if rect.alpha == 0. { - return; - } - - // Calculate rectangle position. - let center_x = size.width() / 2.; - let center_y = size.height() / 2.; - let x = (rect.x - center_x) / center_x; - let y = -(rect.y - center_y) / center_y; - let width = rect.width / center_x; - let height = rect.height / center_y; - - unsafe { - // Setup vertices. - let vertices: [f32; 8] = [x + width, y, x + width, y - height, x, y - height, x, y]; - - // Load vertex data into array buffer. - gl::BufferData( - gl::ARRAY_BUFFER, - (size_of::<f32>() * vertices.len()) as _, - vertices.as_ptr() as *const _, - gl::STATIC_DRAW, - ); - - // Color. - self.rect_program.set_color(rect.color, rect.alpha); - - // Draw the rectangle. - gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null()); - } - } } impl<'a> RenderApi<'a> { @@ -1237,55 +1144,7 @@ impl Drop for TextShaderProgram { } } -impl RectShaderProgram { - pub fn new() -> Result<Self, ShaderCreationError> { - let (vertex_src, fragment_src) = if cfg!(feature = "live-shader-reload") { - (None, None) - } else { - (Some(RECT_SHADER_V), Some(RECT_SHADER_F)) - }; - let vertex_shader = create_shader(RECT_SHADER_V_PATH, gl::VERTEX_SHADER, vertex_src)?; - let fragment_shader = create_shader(RECT_SHADER_F_PATH, gl::FRAGMENT_SHADER, fragment_src)?; - let program = create_program(vertex_shader, fragment_shader)?; - - unsafe { - gl::DeleteShader(fragment_shader); - gl::DeleteShader(vertex_shader); - gl::UseProgram(program); - } - - // Get uniform locations. - let u_color = unsafe { gl::GetUniformLocation(program, b"color\0".as_ptr() as *const _) }; - - let shader = Self { id: program, u_color }; - - unsafe { gl::UseProgram(0) } - - Ok(shader) - } - - fn set_color(&self, color: Rgb, alpha: f32) { - unsafe { - gl::Uniform4f( - self.u_color, - f32::from(color.r) / 255., - f32::from(color.g) / 255., - f32::from(color.b) / 255., - alpha, - ); - } - } -} - -impl Drop for RectShaderProgram { - fn drop(&mut self) { - unsafe { - gl::DeleteProgram(self.id); - } - } -} - -fn create_program(vertex: GLuint, fragment: GLuint) -> Result<GLuint, ShaderCreationError> { +pub fn create_program(vertex: GLuint, fragment: GLuint) -> Result<GLuint, ShaderCreationError> { unsafe { let program = gl::CreateProgram(); gl::AttachShader(program, vertex); @@ -1303,7 +1162,7 @@ fn create_program(vertex: GLuint, fragment: GLuint) -> Result<GLuint, ShaderCrea } } -fn create_shader( +pub fn create_shader( path: &str, kind: GLenum, source: Option<&'static str>, |