aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2018-01-24 00:07:15 +0100
committerChristian Duerr <contact@christianduerr.com>2018-02-16 22:41:56 +0100
commitc14128e9dcaf74ec5286edcfd31fdf1f8a9738cf (patch)
tree967b3d8d19a02e94095abcf8428677ed1c819a69
parentcbbfa4448659e258971e1c401bf5c4733a2d9209 (diff)
downloadalacritty-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.rs13
-rw-r--r--src/renderer/mod.rs88
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);
}
}
}