aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2018-01-14 10:17:08 -0800
committerJoe Wilm <joe@jwilm.com>2018-03-07 09:46:18 -0800
commitc954b6cb92672970293424d60e2a829b626a41d3 (patch)
tree8a878627694bd78eb7cef25a65f099174c355944
parent2612c9b6944491fc37be8427493ad80b914698ae (diff)
downloadalacritty-c954b6cb92672970293424d60e2a829b626a41d3.tar.gz
alacritty-c954b6cb92672970293424d60e2a829b626a41d3.zip
Use memcpy for resetting row contents
In addition to a marginal performance improvement, this simplifies some logic in the Term implementation since now the Grid fully handles row recycling.
-rw-r--r--src/grid/mod.rs81
-rw-r--r--src/grid/row.rs12
-rw-r--r--src/term/mod.rs27
3 files changed, 69 insertions, 51 deletions
diff --git a/src/grid/mod.rs b/src/grid/mod.rs
index 9ca0011a..e790dd41 100644
--- a/src/grid/mod.rs
+++ b/src/grid/mod.rs
@@ -73,6 +73,15 @@ pub struct Grid<T> {
///
/// Invariant: lines is equivalent to raw.len()
lines: index::Line,
+
+ /// Template row.
+ ///
+ /// This is used to quickly populate new lines and clear recycled lines
+ /// during scroll wrapping.
+ template_row: Row<T>,
+
+ /// Template cell for populating template_row
+ template: T,
}
pub struct GridIterator<'a, T: 'a> {
@@ -80,66 +89,60 @@ pub struct GridIterator<'a, T: 'a> {
pub cur: Point,
}
-impl<T: Clone> Grid<T> {
- pub fn new(lines: index::Line, cols: index::Column, template: &T) -> Grid<T> {
+impl<T: Copy + Clone> Grid<T> {
+ pub fn new(lines: index::Line, cols: index::Column, template: T) -> Grid<T> {
let mut raw = VecDeque::with_capacity(*lines);
+ let template_row = Row::new(cols, &template);
for _ in IndexRange(index::Line(0)..lines) {
- raw.push_back(Row::new(cols, template));
+ raw.push_back(template_row.clone());
}
Grid {
raw,
cols,
lines,
+ template_row,
+ template,
}
}
- pub fn resize(&mut self, lines: index::Line, cols: index::Column, template: &T) {
+ pub fn resize(&mut self, lines: index::Line, cols: index::Column) {
// Check that there's actually work to do and return early if not
if lines == self.lines && cols == self.cols {
return;
}
match self.lines.cmp(&lines) {
- Ordering::Less => self.grow_lines(lines, template),
+ Ordering::Less => self.grow_lines(lines),
Ordering::Greater => self.shrink_lines(lines),
Ordering::Equal => (),
}
match self.cols.cmp(&cols) {
- Ordering::Less => self.grow_cols(cols, template),
+ Ordering::Less => self.grow_cols(cols),
Ordering::Greater => self.shrink_cols(cols),
Ordering::Equal => (),
}
}
- fn grow_lines(&mut self, lines: index::Line, template: &T) {
+ fn grow_lines(&mut self, lines: index::Line) {
for _ in IndexRange(self.num_lines()..lines) {
- self.raw.push_back(Row::new(self.cols, template));
+ self.raw.push_back(self.template_row.clone());
}
self.lines = lines;
}
- fn grow_cols(&mut self, cols: index::Column, template: &T) {
+ fn grow_cols(&mut self, cols: index::Column) {
for row in self.raw.iter_mut() {
- row.grow(cols, template);
+ row.grow(cols, &self.template);
}
+ // Update self cols
self.cols = cols;
- }
-
-}
-
-impl<T> Grid<T> {
- #[inline]
- pub fn num_lines(&self) -> index::Line {
- self.lines
- }
- #[inline]
- pub fn num_cols(&self) -> index::Column {
- self.cols
+ // Also update template_row to be the correct length
+ self.template_row.grow(cols, &self.template);
}
#[inline]
@@ -147,7 +150,8 @@ impl<T> Grid<T> {
if region.start == Line(0) && region.end == self.num_lines() {
// Full rotation
for _ in 0..positions.0 {
- let item = self.raw.pop_back().unwrap();
+ let mut item = self.raw.pop_back().unwrap();
+ item.reset(&self.template_row);
self.raw.push_front(item);
}
} else {
@@ -155,6 +159,13 @@ impl<T> Grid<T> {
for line in IndexRange((region.start + positions)..region.end).rev() {
self.swap_lines(line, line - positions);
}
+
+ let template = &self.template_row;
+ for i in IndexRange(Line(0)..positions) {
+ self.raw
+ .get_mut(*(region.start + i))
+ .map(|row| row.reset(template));
+ }
}
}
@@ -163,7 +174,8 @@ impl<T> Grid<T> {
if region.start == Line(0) && region.end == self.num_lines() {
// Full rotation
for _ in 0..positions.0 {
- let item = self.raw.pop_front().unwrap();
+ let mut item = self.raw.pop_front().unwrap();
+ item.reset(&self.template_row);
self.raw.push_back(item);
}
} else {
@@ -171,8 +183,28 @@ impl<T> Grid<T> {
for line in IndexRange(region.start..(region.end - positions)) {
self.swap_lines(line, line + positions);
}
+
+ // Clear reused lines
+ let template = &self.template_row;
+ for i in IndexRange(Line(0)..positions) {
+ self.raw
+ .get_mut(*(region.end - i - 1))
+ .map(|row| row.reset(template));
+ }
}
}
+}
+
+impl<T> Grid<T> {
+ #[inline]
+ pub fn num_lines(&self) -> index::Line {
+ self.lines
+ }
+
+ #[inline]
+ pub fn num_cols(&self) -> index::Column {
+ self.cols
+ }
pub fn iter_from(&self, point: Point) -> GridIterator<T> {
GridIterator {
@@ -209,6 +241,7 @@ impl<T> Grid<T> {
}
self.cols = cols;
+ self.template_row.shrink(cols);
}
}
diff --git a/src/grid/row.rs b/src/grid/row.rs
index 4b355a56..e9cf8dc9 100644
--- a/src/grid/row.rs
+++ b/src/grid/row.rs
@@ -24,16 +24,22 @@ use index::Column;
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct Row<T>(Vec<T>);
-impl<T: Clone> Row<T> {
+impl<T: Copy + Clone> Row<T> {
pub fn new(columns: Column, template: &T) -> Row<T> {
- Row(vec![template.to_owned(); *columns])
+ Row(vec![*template; *columns])
}
pub fn grow(&mut self, cols: Column, template: &T) {
while self.len() != *cols {
- self.push(template.to_owned());
+ self.push(*template);
}
}
+
+ /// Resets contents to the contents of `other`
+ #[inline]
+ pub fn reset(&mut self, other: &Row<T>) {
+ self.copy_from_slice(&**other);
+ }
}
impl<T> Row<T> {
diff --git a/src/term/mod.rs b/src/term/mod.rs
index 1cb37816..d501d1c1 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -799,7 +799,7 @@ impl Term {
let num_cols = size.cols();
let num_lines = size.lines();
- let grid = Grid::new(num_lines, num_cols, &template);
+ let grid = Grid::new(num_lines, num_cols, template);
let tabspaces = config.tabspaces();
let tabs = IndexRange::from(Column(0)..grid.num_cols())
@@ -1064,9 +1064,8 @@ impl Term {
debug!("num_cols, num_lines = {}, {}", num_cols, num_lines);
// Resize grids to new size
- let template = Cell::default();
- self.grid.resize(num_lines, num_cols, &template);
- self.alt_grid.resize(num_lines, num_cols, &template);
+ self.grid.resize(num_lines, num_cols);
+ self.alt_grid.resize(num_lines, num_cols);
// Reset scrolling region to new size
self.scroll_region = Line(0)..self.grid.num_lines();
@@ -1131,17 +1130,6 @@ impl Term {
trace!("scroll_down_relative: origin={}, lines={}", origin, lines);
let lines = min(lines, self.scroll_region.end - self.scroll_region.start);
- // Copy of cell template; can't have it borrowed when calling clear/scroll
- let template = self.cursor.template;
-
- // Clear `lines` lines at bottom of area
- {
- let start = max(origin, Line(self.scroll_region.end.0.saturating_sub(lines.0)));
- self.grid
- .region_mut(start..self.scroll_region.end)
- .each(|c| c.reset(&template));
- }
-
// Scroll between origin and bottom
self.grid.scroll_down(&(origin..self.scroll_region.end), lines);
}
@@ -1155,15 +1143,6 @@ impl Term {
trace!("scroll_up_relative: origin={}, lines={}", origin, lines);
let lines = min(lines, self.scroll_region.end - self.scroll_region.start);
- // Copy of cell template; can't have it borrowed when calling clear/scroll
- let template = self.cursor.template;
-
- // Clear `lines` lines starting from origin to origin + lines
- {
- let end = min(origin + lines, self.scroll_region.end);
- self.grid.region_mut(origin..end).each(|c| c.reset(&template));
- }
-
// Scroll from origin to bottom less number of lines
self.grid.scroll_up(&(origin..self.scroll_region.end), lines);
}