diff options
author | Christian Duerr <contact@christianduerr.com> | 2018-01-24 00:07:15 +0100 |
---|---|---|
committer | Christian Duerr <contact@christianduerr.com> | 2018-02-16 22:41:56 +0100 |
commit | c14128e9dcaf74ec5286edcfd31fdf1f8a9738cf (patch) | |
tree | 967b3d8d19a02e94095abcf8428677ed1c819a69 | |
parent | cbbfa4448659e258971e1c401bf5c4733a2d9209 (diff) | |
download | alacritty-c14128e9dcaf74ec5286edcfd31fdf1f8a9738cf.tar.gz alacritty-c14128e9dcaf74ec5286edcfd31fdf1f8a9738cf.zip |
Add separate rectangle drawing method
In preparation for potential other users of the rectangle drawing, a new
method has been added which moves all the setup and teardown outside of
the render_rect method.
This change will hopefully make it more efficient to draw loads of
rectangles in one frame and prevent excessive program swaps.
-rw-r--r-- | src/display.rs | 13 | ||||
-rw-r--r-- | src/renderer/mod.rs | 88 |
2 files changed, 61 insertions, 40 deletions
diff --git a/src/display.rs b/src/display.rs index 9227037e..826916ce 100644 --- a/src/display.rs +++ b/src/display.rs @@ -193,7 +193,7 @@ impl Display { // Clear screen let background_color = config.colors().primary.background; - renderer.with_api(config, &size_info, 0. /* visual bell intensity */, |api| { + renderer.with_api(config, &size_info, |api| { api.clear(background_color); }); @@ -339,7 +339,6 @@ impl Display { } let size_info = *terminal.size_info(); - let visual_bell_intensity = terminal.visual_bell.intensity(); let background_color = terminal.background_color(); let background_color_changed = background_color != self.last_background_color; @@ -358,7 +357,7 @@ impl Display { // TODO I wonder if the renderable cells iter could avoid the // mutable borrow let window_focused = self.window.is_focused; - self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| { + self.renderer.with_api(config, &size_info, |mut api| { // Clear screen to update whole background with new color if background_color_changed { api.clear(background_color); @@ -372,11 +371,15 @@ impl Display { }); } + // Draw rectangles + let visual_bell_intensity = terminal.visual_bell.intensity(); + self.renderer.draw_rects(config, &size_info, visual_bell_intensity); + // Draw render timer if self.render_timer { let timing = format!("{:.3} usec", self.meter.average()); let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 }; - self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| { + self.renderer.with_api(config, &size_info, |mut api| { api.render_string(&timing[..], glyph_cache, color); }); } @@ -397,7 +400,7 @@ impl Display { // worked around to some extent. Since this doesn't actually address the // issue of glClear being slow, less time is available for input // handling and rendering. - self.renderer.with_api(config, &size_info, visual_bell_intensity, |api| { + self.renderer.with_api(config, &size_info, |api| { api.clear(background_color); }); } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 96ef78c1..d08095f7 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -663,23 +663,69 @@ impl QuadRenderer { Ok(renderer) } - pub fn with_api<F, T>( + // Draw all rectangles, this prevents excessive program swaps + pub fn draw_rects( &mut self, config: &Config, props: &term::SizeInfo, - visual_bell_intensity: f64, - func: F - ) -> T - where F: FnOnce(RenderApi) -> T + visual_bell_intensity: f64) { + // Swap to rectangle rendering program + unsafe { + // Swap program + gl::UseProgram(self.rect_program.id); + + // Change blending strategy + gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); + + // Setup data and buffers + gl::BindVertexArray(self.rect_vao); + gl::BindBuffer(gl::ARRAY_BUFFER, self.rect_vbo); + + // Position + gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, (size_of::<f32>() * 3) as _, ptr::null()); + gl::EnableVertexAttribArray(0); + } + + // Get window size let size = Size { width: Pixels(props.width as u32), height: Pixels(props.height as u32), }; + // Draw visual bell + let color = config.visual_bell().color(); + let rect = Rect::new(0, 0, *size.width, *size.height); + self.render_rect(&rect, color, visual_bell_intensity as f32, size); + + // Deactivate rectangle program 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); + + // Disable program + gl::UseProgram(0); + } + } + + pub fn with_api<F, T>( + &mut self, + config: &Config, + props: &term::SizeInfo, + func: F + ) -> T + where F: FnOnce(RenderApi) -> T + { // Flush message queue if let Ok(Msg::ShaderReload) = self.rx.try_recv() { - self.reload_shaders(config, size); + self.reload_shaders(config, Size { + width: Pixels(props.width as u32), + height: Pixels(props.height as u32), + }); } while let Ok(_) = self.rx.try_recv() {} @@ -702,11 +748,6 @@ impl QuadRenderer { config: config, }); - // Draw visual bell - let color = config.visual_bell().color(); - let rect = Rect::new(0, 0, *size.width, *size.height); - self.render_rect(&rect, color, visual_bell_intensity as f32, size); - unsafe { gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0); gl::BindBuffer(gl::ARRAY_BUFFER, 0); @@ -778,8 +819,7 @@ impl QuadRenderer { } // Render a rectangle - // TODO: When stuff other than visual bell uses render_rect, - // draw calls should be collected to reduce number of program swaps + // This requires the rectangle program to be activated fn render_rect(&mut self, rect: &Rect<u32>, color: Rgb, alpha: f32, size: Size<Pixels<u32>>) { // Do nothing when alpha is fully transparent if alpha == 0. { @@ -795,12 +835,6 @@ impl QuadRenderer { let height = rect.height as f32 / center_y; unsafe { - // Activate rectangle program - gl::UseProgram(self.rect_program.id); - - // Change blending strategy - gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); - // Setup vertices let vertices: [f32; 12] = [ x + width, y , 0.0, @@ -810,29 +844,13 @@ impl QuadRenderer { ]; // Load vertex data into array buffer - gl::BindVertexArray(self.rect_vao); - - gl::BindBuffer(gl::ARRAY_BUFFER, self.rect_vbo); gl::BufferData(gl::ARRAY_BUFFER, (size_of::<f32>() * vertices.len()) as _, vertices.as_ptr() as *const _, gl::STATIC_DRAW); - // Position - gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, (size_of::<f32>() * 3) as _, ptr::null()); - gl::EnableVertexAttribArray(0); - - gl::BindBuffer(gl::ARRAY_BUFFER, 0); - // Color self.rect_program.set_color(color, alpha); // Draw the rectangle gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null()); - - // Reset state - gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR); - gl::BindVertexArray(0); - - // Deactivate program - gl::UseProgram(0); } } } |