Rework Terminal::Display to improve performance and treat passed Framebuffers as const.

* Refactor put_cell() and parts of new_frame(), and associated state, into put_row().
* Optimize display and line wrap handling code/output.
* Make last_frame a const ref, to eliminate a costly copy of the framebuffer on every screen refresh.
* In new_frame()'s scroll optimization, don't copy rows, use pointers instead.
* Don't check entire frame buffer for scrolling if first line hasn't scrolled.
* Add a generation counter on Row objects to allow quicker/better identification of scroll regions
* Use at() for bounds-checking on framebuffers, because they can be resized.
* Copy and resize scroll buffer on window resize.
This commit is contained in:
John Hood
2013-12-15 18:39:23 -05:00
parent 32afa96111
commit c090d257f2
4 changed files with 285 additions and 200 deletions
+23 -8
View File
@@ -89,7 +89,6 @@ namespace Terminal {
Renditions renditions;
uint8_t width;
bool fallback; /* first character is combining character */
bool wrap; /* if last cell, wrap to next line */
Cell( color_type background_color );
Cell(); /* default constructor required by C++11 STL */
@@ -101,8 +100,7 @@ namespace Terminal {
return ( (contents == x.contents)
&& (fallback == x.fallback)
&& (width == x.width)
&& (renditions == x.renditions)
&& (wrap == x.wrap) );
&& (renditions == x.renditions) );
}
bool operator!=( const Cell &x ) const { return !operator==( x ); }
@@ -149,6 +147,11 @@ namespace Terminal {
public:
typedef std::vector<Cell> cells_type;
cells_type cells;
bool wrap; /* if last cell, wrap to next line */
// gen is a generation counter. It can be used to quickly rule
// out the possibility of two rows being identical; this is useful
// in scrolling.
uint64_t gen;
Row( size_t s_width, color_type background_color );
Row(); /* default constructor required by C++11 STL */
@@ -160,11 +163,13 @@ namespace Terminal {
bool operator==( const Row &x ) const
{
return ( cells == x.cells );
return ( gen == x.gen && cells == x.cells && wrap == x.wrap );
}
bool get_wrap( void ) const { return cells.back().wrap; }
void set_wrap( bool w ) { cells.back().wrap = w; }
bool get_wrap( void ) const { return wrap; }
void set_wrap( bool w ) { wrap = w; }
uint64_t get_gen() const;
};
class SavedCursor {
@@ -285,6 +290,7 @@ namespace Terminal {
class Framebuffer {
public:
typedef std::vector<wchar_t> title_type;
typedef std::vector<const Row *> rows_p_type;
private:
typedef std::vector<Row> rows_type;
@@ -303,11 +309,20 @@ namespace Terminal {
void scroll( int N );
void move_rows_autoscroll( int rows );
rows_p_type get_p_rows() const
{
rows_p_type retval;
for ( size_t i = 0; i < rows.size(); i++ ) {
retval.push_back( &rows.at(i) );
}
return retval;
}
const Row *get_row( int row ) const
{
if ( row == -1 ) row = ds.get_cursor_row();
return &rows[ row ];
return &rows.at( row );
}
inline const Cell *get_cell( int row = -1, int col = -1 ) const
@@ -315,7 +330,7 @@ namespace Terminal {
if ( row == -1 ) row = ds.get_cursor_row();
if ( col == -1 ) col = ds.get_cursor_col();
return &rows[ row ].cells[ col ];
return &rows.at( row ).cells.at( col );
}
Row *get_mutable_row( int row )