Speed up back color erase -- no more loop over all cells

This commit is contained in:
Keith Winstein
2011-02-10 20:32:39 -05:00
parent 0fb343292a
commit 7d1013681f
5 changed files with 47 additions and 74 deletions
+3 -3
View File
@@ -49,7 +49,7 @@ void Emulator::print( Parser::Print *act )
if ( fb.ds.auto_wrap_mode if ( fb.ds.auto_wrap_mode
&& (chwidth == 2) && (chwidth == 2)
&& (fb.ds.get_cursor_col() == fb.ds.get_width() - 1) ) { && (fb.ds.get_cursor_col() == fb.ds.get_width() - 1) ) {
this_cell->reset(); fb.reset_cell( this_cell );
fb.get_row( -1 )->wrap = false; fb.get_row( -1 )->wrap = false;
/* There doesn't seem to be a consistent way to get the /* There doesn't seem to be a consistent way to get the
downstream terminal emulator to set the wrap-around downstream terminal emulator to set the wrap-around
@@ -67,14 +67,14 @@ void Emulator::print( Parser::Print *act )
this_cell = fb.get_cell(); this_cell = fb.get_cell();
this_cell->reset(); fb.reset_cell( this_cell );
this_cell->contents.push_back( act->ch ); this_cell->contents.push_back( act->ch );
this_cell->width = chwidth; this_cell->width = chwidth;
fb.apply_renditions_to_current_cell(); fb.apply_renditions_to_current_cell();
if ( chwidth == 2 ) { /* erase overlapped cell */ if ( chwidth == 2 ) { /* erase overlapped cell */
if ( fb.ds.get_cursor_col() + 1 < fb.ds.get_width() ) { if ( fb.ds.get_cursor_col() + 1 < fb.ds.get_width() ) {
fb.get_cell( fb.ds.get_cursor_row(), fb.ds.get_cursor_col() + 1 )->reset(); fb.reset_cell( fb.get_cell( fb.ds.get_cursor_row(), fb.ds.get_cursor_col() + 1 ) );
} }
} }
+1 -5
View File
@@ -10,10 +10,6 @@ std::string Display::new_frame( Framebuffer &f )
{ {
FrameState frame; FrameState frame;
/* fill in background color on any cells that have been reset
or created since last time */
f.back_color_erase();
char tmp[ 64 ]; char tmp[ 64 ];
/* has window title changed? */ /* has window title changed? */
@@ -77,7 +73,7 @@ std::string Display::new_frame( Framebuffer &f )
&& (!f.get_row( frame.y )->wrap) && (!f.get_row( frame.y )->wrap)
&& (!initialized || last_frame.get_row( frame.y )->wrap) ) { && (!initialized || last_frame.get_row( frame.y )->wrap) ) {
frame.x = last_x; frame.x = last_x;
last_frame.get_cell( frame.y, frame.x )->reset(); last_frame.reset_cell( last_frame.get_cell( frame.y, frame.x ) );
snprintf( tmp, 64, "\033[%d;%dH\033[K", frame.y + 1, frame.x + 1 ); snprintf( tmp, 64, "\033[%d;%dH\033[K", frame.y + 1, frame.x + 1 );
frame.append( tmp ); frame.append( tmp );
+23 -37
View File
@@ -4,12 +4,12 @@
using namespace Terminal; using namespace Terminal;
void Cell::reset( void ) void Cell::reset( int background_color )
{ {
contents.clear(); contents.clear();
fallback = false; fallback = false;
width = 1; width = 1;
renditions = Renditions(); renditions = Renditions( background_color );
} }
DrawState::DrawState( int s_width, int s_height ) DrawState::DrawState( int s_width, int s_height )
@@ -17,7 +17,7 @@ DrawState::DrawState( int s_width, int s_height )
cursor_col( 0 ), cursor_row( 0 ), cursor_col( 0 ), cursor_row( 0 ),
combining_char_col( 0 ), combining_char_row( 0 ), tabs( s_width ), combining_char_col( 0 ), combining_char_row( 0 ), tabs( s_width ),
scrolling_region_top_row( 0 ), scrolling_region_bottom_row( height - 1 ), scrolling_region_top_row( 0 ), scrolling_region_bottom_row( height - 1 ),
renditions(), save(), renditions( 0 ), save(),
next_print_will_wrap( false ), origin_mode( false ), auto_wrap_mode( true ), next_print_will_wrap( false ), origin_mode( false ), auto_wrap_mode( true ),
insert_mode( false ), cursor_visible( true ), reverse_video( false ), insert_mode( false ), cursor_visible( true ), reverse_video( false ),
application_mode_cursor_keys( false ) application_mode_cursor_keys( false )
@@ -28,7 +28,7 @@ DrawState::DrawState( int s_width, int s_height )
} }
Framebuffer::Framebuffer( int s_width, int s_height ) Framebuffer::Framebuffer( int s_width, int s_height )
: rows( s_height, Row( s_width ) ), window_title(), ds( s_width, s_height ) : rows( s_height, Row( s_width, 0 ) ), window_title(), ds( s_width, s_height )
{ {
assert( s_height > 0 ); assert( s_height > 0 );
assert( s_width > 0 ); assert( s_width > 0 );
@@ -45,7 +45,7 @@ void Framebuffer::scroll( int N )
N = -N; N = -N;
for ( int i = 0; i < N; i++ ) { for ( int i = 0; i < N; i++ ) {
rows.insert( rows.begin() + ds.get_scrolling_region_top_row(), Row( ds.get_width() ) ); rows.insert( rows.begin() + ds.get_scrolling_region_top_row(), newrow() );
rows.erase( rows.begin() + ds.get_scrolling_region_bottom_row() + 1 ); rows.erase( rows.begin() + ds.get_scrolling_region_bottom_row() + 1 );
ds.move_row( 1, true ); ds.move_row( 1, true );
} }
@@ -204,7 +204,7 @@ void Framebuffer::apply_renditions_to_current_cell( void )
SavedCursor::SavedCursor() SavedCursor::SavedCursor()
: cursor_col( 0 ), cursor_row( 0 ), : cursor_col( 0 ), cursor_row( 0 ),
renditions(), renditions( 0 ),
auto_wrap_mode( true ), auto_wrap_mode( true ),
origin_mode( false ) origin_mode( false )
{} {}
@@ -237,7 +237,7 @@ void Framebuffer::insert_line( int before_row )
return; return;
} }
rows.insert( rows.begin() + before_row, Row( ds.get_width() ) ); rows.insert( rows.begin() + before_row, newrow() );
rows.erase( rows.begin() + ds.get_scrolling_region_bottom_row() + 1 ); rows.erase( rows.begin() + ds.get_scrolling_region_bottom_row() + 1 );
} }
@@ -250,42 +250,42 @@ void Framebuffer::delete_line( int row )
int insertbefore = ds.get_scrolling_region_bottom_row() + 1; int insertbefore = ds.get_scrolling_region_bottom_row() + 1;
if ( insertbefore == ds.get_height() ) { if ( insertbefore == ds.get_height() ) {
rows.push_back( Row( ds.get_width() ) ); rows.push_back( newrow() );
} else { } else {
rows.insert( rows.begin() + insertbefore, Row( ds.get_width() ) ); rows.insert( rows.begin() + insertbefore, newrow() );
} }
rows.erase( rows.begin() + row ); rows.erase( rows.begin() + row );
} }
void Row::insert_cell( int col ) void Row::insert_cell( int col, int background_color )
{ {
cells.insert( cells.begin() + col, Cell() ); cells.insert( cells.begin() + col, Cell( background_color ) );
cells.pop_back(); cells.pop_back();
} }
void Row::delete_cell( int col ) void Row::delete_cell( int col, int background_color )
{ {
cells.push_back( Cell() ); cells.push_back( Cell( background_color ) );
cells.erase( cells.begin() + col ); cells.erase( cells.begin() + col );
} }
void Framebuffer::insert_cell( int row, int col ) void Framebuffer::insert_cell( int row, int col )
{ {
rows[ row ].insert_cell( col ); rows[ row ].insert_cell( col, ds.get_background_rendition() );
} }
void Framebuffer::delete_cell( int row, int col ) void Framebuffer::delete_cell( int row, int col )
{ {
rows[ row ].delete_cell( col ); rows[ row ].delete_cell( col, ds.get_background_rendition() );
} }
void Framebuffer::reset( void ) void Framebuffer::reset( void )
{ {
int width = ds.get_width(), height = ds.get_height(); int width = ds.get_width(), height = ds.get_height();
rows = std::deque<Row>( height, Row( width ) );
window_title.clear();
ds = DrawState( width, height ); ds = DrawState( width, height );
rows = std::deque<Row>( height, newrow() );
window_title.clear();
} }
void Framebuffer::soft_reset( void ) void Framebuffer::soft_reset( void )
@@ -304,12 +304,12 @@ void Framebuffer::resize( int s_width, int s_height )
assert( s_width > 0 ); assert( s_width > 0 );
assert( s_height > 0 ); assert( s_height > 0 );
rows.resize( s_height, Row( ds.get_width() ) ); rows.resize( s_height, newrow() );
for ( std::deque<Row>::iterator i = rows.begin(); for ( std::deque<Row>::iterator i = rows.begin();
i != rows.end(); i != rows.end();
i++ ) { i++ ) {
(*i).cells.resize( s_width, Cell() ); (*i).cells.resize( s_width, Cell( ds.get_background_rendition() ) );
} }
ds.resize( s_width, s_height ); ds.resize( s_width, s_height );
@@ -342,24 +342,10 @@ void DrawState::resize( int s_width, int s_height )
} }
} }
void Framebuffer::back_color_erase( void ) Renditions::Renditions( int s_background )
{
int bg_color = ds.get_background_rendition();
for ( int row = 0; row < ds.get_height(); row++ ) {
for ( int col = 0; col < ds.get_width(); col++ ) {
Cell *cell = get_cell( row, col );
if ( cell->renditions.background_color == -1 ) {
cell->renditions.background_color = bg_color == -1 ? 0 : bg_color;
}
}
}
}
Renditions::Renditions()
: bold( false ), underlined( false ), blink( false ), : bold( false ), underlined( false ), blink( false ),
inverse( false ), invisible( false ), foreground_color( 0 ), inverse( false ), invisible( false ), foreground_color( 0 ),
background_color( -1 ) background_color( s_background )
{} {}
void Renditions::set_rendition( int num ) void Renditions::set_rendition( int num )
@@ -412,11 +398,11 @@ std::string Renditions::sgr( void )
return ret; return ret;
} }
void Row::reset( void ) void Row::reset( int background_color )
{ {
for ( std::vector<Cell>::iterator i = cells.begin(); for ( std::vector<Cell>::iterator i = cells.begin();
i != cells.end(); i != cells.end();
i++ ) { i++ ) {
i->reset(); i->reset( background_color );
} }
} }
+13 -14
View File
@@ -15,13 +15,9 @@ namespace Terminal {
int foreground_color; int foreground_color;
int background_color; int background_color;
Renditions(); Renditions( int s_background );
void set_rendition( int num ); void set_rendition( int num );
std::string sgr( void ); std::string sgr( void );
void back_color_erase( int num )
{
if ( background_color == -1 ) background_color = num;
}
bool operator==( const Renditions &x ) bool operator==( const Renditions &x )
{ {
@@ -39,14 +35,14 @@ namespace Terminal {
int width; int width;
Renditions renditions; Renditions renditions;
Cell() Cell( int background_color )
: contents(), : contents(),
fallback( false ), fallback( false ),
width( 1 ), width( 1 ),
renditions() renditions( background_color )
{} {}
void reset( void ); void reset( int background_color );
inline bool operator==( const Cell &x ) inline bool operator==( const Cell &x )
{ {
@@ -62,14 +58,14 @@ namespace Terminal {
std::vector<Cell> cells; std::vector<Cell> cells;
bool wrap; bool wrap;
Row( size_t s_width ) Row( size_t s_width, int background_color )
: cells( s_width ), wrap( false ) : cells( s_width, Cell( background_color ) ), wrap( false )
{} {}
void insert_cell( int col ); void insert_cell( int col, int background_color );
void delete_cell( int col ); void delete_cell( int col, int background_color );
void reset( void ); void reset( int background_color );
}; };
class SavedCursor { class SavedCursor {
@@ -158,6 +154,8 @@ namespace Terminal {
void scroll( int N ); void scroll( int N );
Row newrow( void ) { return Row( ds.get_width(), ds.get_background_rendition() ); }
public: public:
Framebuffer( int s_width, int s_height ); Framebuffer( int s_width, int s_height );
DrawState ds; DrawState ds;
@@ -202,7 +200,8 @@ namespace Terminal {
void resize( int s_width, int s_height ); void resize( int s_width, int s_height );
void back_color_erase( void ); void reset_cell( Cell *c ) { c->reset( ds.get_background_rendition() ); }
void reset_row( Row *r ) { r->reset( ds.get_background_rendition() ); }
}; };
} }
+7 -15
View File
@@ -12,7 +12,7 @@ using namespace Terminal;
static void clearline( Framebuffer *fb, int row, int start, int end ) static void clearline( Framebuffer *fb, int row, int start, int end )
{ {
for ( int col = start; col <= end; col++ ) { for ( int col = start; col <= end; col++ ) {
fb->get_cell( row, col )->reset(); fb->reset_cell( fb->get_cell( row, col ) );
} }
} }
@@ -27,7 +27,7 @@ void CSI_EL( Framebuffer *fb, Dispatcher *dispatch )
clearline( fb, -1, 0, fb->ds.get_cursor_col() ); clearline( fb, -1, 0, fb->ds.get_cursor_col() );
break; break;
case 2: /* all of line */ case 2: /* all of line */
fb->get_row( -1 )->reset(); fb->reset_row( fb->get_row( -1 ) );
break; break;
} }
} }
@@ -40,18 +40,18 @@ void CSI_ED( Framebuffer *fb, Dispatcher *dispatch ) {
case 0: /* active position to end of screen, inclusive */ case 0: /* active position to end of screen, inclusive */
clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 ); clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 );
for ( int y = fb->ds.get_cursor_row() + 1; y < fb->ds.get_height(); y++ ) { for ( int y = fb->ds.get_cursor_row() + 1; y < fb->ds.get_height(); y++ ) {
fb->get_row( y )->reset(); fb->reset_row( fb->get_row( y ) );
} }
break; break;
case 1: /* start of screen to active position, inclusive */ case 1: /* start of screen to active position, inclusive */
for ( int y = 0; y < fb->ds.get_cursor_row(); y++ ) { for ( int y = 0; y < fb->ds.get_cursor_row(); y++ ) {
fb->get_row( y )->reset(); fb->reset_row( fb->get_row( y ) );
} }
clearline( fb, -1, 0, fb->ds.get_cursor_col() ); clearline( fb, -1, 0, fb->ds.get_cursor_col() );
break; break;
case 2: /* entire screen */ case 2: /* entire screen */
for ( int y = 0; y < fb->ds.get_height(); y++ ) { for ( int y = 0; y < fb->ds.get_height(); y++ ) {
fb->get_row( y )->reset(); fb->reset_row( fb->get_row( y ) );
} }
break; break;
} }
@@ -114,7 +114,7 @@ void Esc_DECALN( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
{ {
for ( int y = 0; y < fb->ds.get_height(); y++ ) { for ( int y = 0; y < fb->ds.get_height(); y++ ) {
for ( int x = 0; x < fb->ds.get_width(); x++ ) { for ( int x = 0; x < fb->ds.get_width(); x++ ) {
fb->get_cell( y, x )->reset(); fb->reset_cell( fb->get_cell( y, x ) );
fb->get_cell( y, x )->contents.push_back( L'E' ); fb->get_cell( y, x )->contents.push_back( L'E' );
} }
} }
@@ -215,7 +215,7 @@ static bool *get_DEC_mode( int param, Framebuffer *fb ) {
fb->ds.move_row( 0 ); fb->ds.move_row( 0 );
fb->ds.move_col( 0 ); fb->ds.move_col( 0 );
for ( int y = 0; y < fb->ds.get_height(); y++ ) { for ( int y = 0; y < fb->ds.get_height(); y++ ) {
fb->get_row( y )->reset(); fb->reset_row( fb->get_row( y ) );
} }
return NULL; return NULL;
case 5: /* reverse video */ case 5: /* reverse video */
@@ -312,16 +312,8 @@ static Function func_Ctrl_BEL( CONTROL, "\x07", Ctrl_BEL );
/* select graphics rendition -- e.g., bold, blinking, etc. */ /* select graphics rendition -- e.g., bold, blinking, etc. */
void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch )
{ {
bool bce = false;
for ( int i = 0; i < dispatch->param_count(); i++ ) { for ( int i = 0; i < dispatch->param_count(); i++ ) {
int rendition = dispatch->getparam( i, 0 ); int rendition = dispatch->getparam( i, 0 );
if ( (40 <= rendition) && (rendition <= 49) && (!bce) ) {
/* we're changing the background color */
fb->back_color_erase();
bce = true;
}
fb->ds.add_rendition( rendition ); fb->ds.add_rendition( rendition );
} }
} }