mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
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.
This commit is contained in:
parent
44f58b81f2
commit
d0a1ff4736
3 changed files with 90 additions and 72 deletions
123
src/grid/mod.rs
123
src/grid/mod.rs
|
@ -73,6 +73,15 @@ pub struct Grid<T> {
|
||||||
///
|
///
|
||||||
/// Invariant: lines is equivalent to raw.len()
|
/// Invariant: lines is equivalent to raw.len()
|
||||||
lines: index::Line,
|
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> {
|
pub struct GridIterator<'a, T: 'a> {
|
||||||
|
@ -80,55 +89,110 @@ pub struct GridIterator<'a, T: 'a> {
|
||||||
pub cur: Point,
|
pub cur: Point,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone> Grid<T> {
|
impl<T: Copy + Clone> Grid<T> {
|
||||||
pub fn new(lines: index::Line, cols: index::Column, template: &T) -> Grid<T> {
|
pub fn new(lines: index::Line, cols: index::Column, template: T) -> Grid<T> {
|
||||||
let mut raw = VecDeque::with_capacity(*lines);
|
let mut raw = VecDeque::with_capacity(*lines);
|
||||||
|
let template_row = Row::new(cols, &template);
|
||||||
for _ in IndexRange(index::Line(0)..lines) {
|
for _ in IndexRange(index::Line(0)..lines) {
|
||||||
raw.push_back(Row::new(cols, template));
|
raw.push_back(template_row.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
Grid {
|
Grid {
|
||||||
raw: raw,
|
raw,
|
||||||
cols: cols,
|
cols,
|
||||||
lines: lines,
|
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
|
// Check that there's actually work to do and return early if not
|
||||||
if lines == self.lines && cols == self.cols {
|
if lines == self.lines && cols == self.cols {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.lines.cmp(&lines) {
|
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::Greater => self.shrink_lines(lines),
|
||||||
Ordering::Equal => (),
|
Ordering::Equal => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.cols.cmp(&cols) {
|
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::Greater => self.shrink_cols(cols),
|
||||||
Ordering::Equal => (),
|
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) {
|
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;
|
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() {
|
for row in self.raw.iter_mut() {
|
||||||
row.grow(cols, template);
|
row.grow(cols, &self.template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update self cols
|
||||||
self.cols = cols;
|
self.cols = cols;
|
||||||
|
|
||||||
|
// Also update template_row to be the correct length
|
||||||
|
self.template_row.grow(cols, &self.template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn scroll_down(&mut self, region: &Range<index::Line>, positions: index::Line) {
|
||||||
|
if region.start == Line(0) && region.end == self.num_lines() {
|
||||||
|
// Full rotation
|
||||||
|
for _ in 0..positions.0 {
|
||||||
|
let mut item = self.raw.pop_back().unwrap();
|
||||||
|
item.reset(&self.template_row);
|
||||||
|
self.raw.push_front(item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Subregion rotation
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn scroll_up(&mut self, region: &Range<index::Line>, positions: index::Line) {
|
||||||
|
if region.start == Line(0) && region.end == self.num_lines() {
|
||||||
|
// Full rotation
|
||||||
|
for _ in 0..positions.0 {
|
||||||
|
let mut item = self.raw.pop_front().unwrap();
|
||||||
|
item.reset(&self.template_row);
|
||||||
|
self.raw.push_back(item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Subregion rotation
|
||||||
|
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> {
|
impl<T> Grid<T> {
|
||||||
|
@ -142,38 +206,6 @@ impl<T> Grid<T> {
|
||||||
self.cols
|
self.cols
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn scroll_down(&mut self, region: &Range<index::Line>, positions: index::Line) {
|
|
||||||
if region.start == Line(0) && region.end == self.num_lines() {
|
|
||||||
// Full rotation
|
|
||||||
for _ in 0..positions.0 {
|
|
||||||
let item = self.raw.pop_back().unwrap();
|
|
||||||
self.raw.push_front(item);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Subregion rotation
|
|
||||||
for line in IndexRange((region.start + positions)..region.end).rev() {
|
|
||||||
self.swap_lines(line, line - positions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn scroll_up(&mut self, region: &Range<index::Line>, positions: index::Line) {
|
|
||||||
if region.start == Line(0) && region.end == self.num_lines() {
|
|
||||||
// Full rotation
|
|
||||||
for _ in 0..positions.0 {
|
|
||||||
let item = self.raw.pop_front().unwrap();
|
|
||||||
self.raw.push_back(item);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Subregion rotation
|
|
||||||
for line in IndexRange(region.start..(region.end - positions)) {
|
|
||||||
self.swap_lines(line, line + positions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_from(&self, point: Point) -> GridIterator<T> {
|
pub fn iter_from(&self, point: Point) -> GridIterator<T> {
|
||||||
GridIterator {
|
GridIterator {
|
||||||
grid: self,
|
grid: self,
|
||||||
|
@ -209,6 +241,7 @@ impl<T> Grid<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cols = cols;
|
self.cols = cols;
|
||||||
|
self.template_row.shrink(cols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,16 +24,22 @@ use index::Column;
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
pub struct Row<T>(Vec<T>);
|
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> {
|
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) {
|
pub fn grow(&mut self, cols: Column, template: &T) {
|
||||||
while self.len() != *cols {
|
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> {
|
impl<T> Row<T> {
|
||||||
|
|
|
@ -799,7 +799,7 @@ impl Term {
|
||||||
let num_cols = size.cols();
|
let num_cols = size.cols();
|
||||||
let num_lines = size.lines();
|
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 tabspaces = config.tabspaces();
|
||||||
let tabs = IndexRange::from(Column(0)..grid.num_cols())
|
let tabs = IndexRange::from(Column(0)..grid.num_cols())
|
||||||
|
@ -1064,9 +1064,8 @@ impl Term {
|
||||||
debug!("num_cols, num_lines = {}, {}", num_cols, num_lines);
|
debug!("num_cols, num_lines = {}, {}", num_cols, num_lines);
|
||||||
|
|
||||||
// Resize grids to new size
|
// Resize grids to new size
|
||||||
let template = Cell::default();
|
self.grid.resize(num_lines, num_cols);
|
||||||
self.grid.resize(num_lines, num_cols, &template);
|
self.alt_grid.resize(num_lines, num_cols);
|
||||||
self.alt_grid.resize(num_lines, num_cols, &template);
|
|
||||||
|
|
||||||
// Reset scrolling region to new size
|
// Reset scrolling region to new size
|
||||||
self.scroll_region = Line(0)..self.grid.num_lines();
|
self.scroll_region = Line(0)..self.grid.num_lines();
|
||||||
|
@ -1131,17 +1130,6 @@ impl Term {
|
||||||
trace!("scroll_down_relative: origin={}, lines={}", origin, lines);
|
trace!("scroll_down_relative: origin={}, lines={}", origin, lines);
|
||||||
let lines = min(lines, self.scroll_region.end - self.scroll_region.start);
|
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
|
// Scroll between origin and bottom
|
||||||
self.grid.scroll_down(&(origin..self.scroll_region.end), lines);
|
self.grid.scroll_down(&(origin..self.scroll_region.end), lines);
|
||||||
}
|
}
|
||||||
|
@ -1155,15 +1143,6 @@ impl Term {
|
||||||
trace!("scroll_up_relative: origin={}, lines={}", origin, lines);
|
trace!("scroll_up_relative: origin={}, lines={}", origin, lines);
|
||||||
let lines = min(lines, self.scroll_region.end - self.scroll_region.start);
|
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
|
// Scroll from origin to bottom less number of lines
|
||||||
self.grid.scroll_up(&(origin..self.scroll_region.end), lines);
|
self.grid.scroll_up(&(origin..self.scroll_region.end), lines);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue