From 7d1013681febc7cace06e8aa4493856e4b70e07d Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Thu, 10 Feb 2011 20:32:39 -0500 Subject: [PATCH] Speed up back color erase -- no more loop over all cells --- terminal.cpp | 6 ++--- terminaldisplay.cpp | 6 +---- terminalframebuffer.cpp | 60 ++++++++++++++++------------------------- terminalframebuffer.hpp | 27 +++++++++---------- terminalfunctions.cpp | 22 +++++---------- 5 files changed, 47 insertions(+), 74 deletions(-) diff --git a/terminal.cpp b/terminal.cpp index 6d21a1f..fbba772 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -49,7 +49,7 @@ void Emulator::print( Parser::Print *act ) if ( fb.ds.auto_wrap_mode && (chwidth == 2) && (fb.ds.get_cursor_col() == fb.ds.get_width() - 1) ) { - this_cell->reset(); + fb.reset_cell( this_cell ); fb.get_row( -1 )->wrap = false; /* There doesn't seem to be a consistent way to get the 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->reset(); + fb.reset_cell( this_cell ); this_cell->contents.push_back( act->ch ); this_cell->width = chwidth; fb.apply_renditions_to_current_cell(); if ( chwidth == 2 ) { /* erase overlapped cell */ 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 ) ); } } diff --git a/terminaldisplay.cpp b/terminaldisplay.cpp index 08b93e4..f51bc19 100644 --- a/terminaldisplay.cpp +++ b/terminaldisplay.cpp @@ -10,10 +10,6 @@ std::string Display::new_frame( Framebuffer &f ) { 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 ]; /* has window title changed? */ @@ -77,7 +73,7 @@ std::string Display::new_frame( Framebuffer &f ) && (!f.get_row( frame.y )->wrap) && (!initialized || last_frame.get_row( frame.y )->wrap) ) { 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 ); frame.append( tmp ); diff --git a/terminalframebuffer.cpp b/terminalframebuffer.cpp index d786aa4..2e6335e 100644 --- a/terminalframebuffer.cpp +++ b/terminalframebuffer.cpp @@ -4,12 +4,12 @@ using namespace Terminal; -void Cell::reset( void ) +void Cell::reset( int background_color ) { contents.clear(); fallback = false; width = 1; - renditions = Renditions(); + renditions = Renditions( background_color ); } 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 ), combining_char_col( 0 ), combining_char_row( 0 ), tabs( s_width ), 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 ), insert_mode( false ), cursor_visible( true ), reverse_video( 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 ) - : 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_width > 0 ); @@ -45,7 +45,7 @@ void Framebuffer::scroll( int N ) N = -N; 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 ); ds.move_row( 1, true ); } @@ -204,7 +204,7 @@ void Framebuffer::apply_renditions_to_current_cell( void ) SavedCursor::SavedCursor() : cursor_col( 0 ), cursor_row( 0 ), - renditions(), + renditions( 0 ), auto_wrap_mode( true ), origin_mode( false ) {} @@ -237,7 +237,7 @@ void Framebuffer::insert_line( int before_row ) 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 ); } @@ -250,42 +250,42 @@ void Framebuffer::delete_line( int row ) int insertbefore = ds.get_scrolling_region_bottom_row() + 1; if ( insertbefore == ds.get_height() ) { - rows.push_back( Row( ds.get_width() ) ); + rows.push_back( newrow() ); } else { - rows.insert( rows.begin() + insertbefore, Row( ds.get_width() ) ); + rows.insert( rows.begin() + insertbefore, newrow() ); } 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(); } -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 ); } 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 ) { - rows[ row ].delete_cell( col ); + rows[ row ].delete_cell( col, ds.get_background_rendition() ); } void Framebuffer::reset( void ) { int width = ds.get_width(), height = ds.get_height(); - rows = std::deque( height, Row( width ) ); - window_title.clear(); ds = DrawState( width, height ); + rows = std::deque( height, newrow() ); + window_title.clear(); } void Framebuffer::soft_reset( void ) @@ -304,12 +304,12 @@ void Framebuffer::resize( int s_width, int s_height ) assert( s_width > 0 ); assert( s_height > 0 ); - rows.resize( s_height, Row( ds.get_width() ) ); + rows.resize( s_height, newrow() ); for ( std::deque::iterator i = rows.begin(); i != rows.end(); i++ ) { - (*i).cells.resize( s_width, Cell() ); + (*i).cells.resize( s_width, Cell( ds.get_background_rendition() ) ); } 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 ) -{ - 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() +Renditions::Renditions( int s_background ) : bold( false ), underlined( false ), blink( false ), inverse( false ), invisible( false ), foreground_color( 0 ), - background_color( -1 ) + background_color( s_background ) {} void Renditions::set_rendition( int num ) @@ -412,11 +398,11 @@ std::string Renditions::sgr( void ) return ret; } -void Row::reset( void ) +void Row::reset( int background_color ) { for ( std::vector::iterator i = cells.begin(); i != cells.end(); i++ ) { - i->reset(); + i->reset( background_color ); } } diff --git a/terminalframebuffer.hpp b/terminalframebuffer.hpp index b7928ab..b94c322 100644 --- a/terminalframebuffer.hpp +++ b/terminalframebuffer.hpp @@ -15,13 +15,9 @@ namespace Terminal { int foreground_color; int background_color; - Renditions(); + Renditions( int s_background ); void set_rendition( int num ); std::string sgr( void ); - void back_color_erase( int num ) - { - if ( background_color == -1 ) background_color = num; - } bool operator==( const Renditions &x ) { @@ -39,14 +35,14 @@ namespace Terminal { int width; Renditions renditions; - Cell() + Cell( int background_color ) : contents(), fallback( false ), width( 1 ), - renditions() + renditions( background_color ) {} - void reset( void ); + void reset( int background_color ); inline bool operator==( const Cell &x ) { @@ -62,14 +58,14 @@ namespace Terminal { std::vector cells; bool wrap; - Row( size_t s_width ) - : cells( s_width ), wrap( false ) + Row( size_t s_width, int background_color ) + : cells( s_width, Cell( background_color ) ), wrap( false ) {} - void insert_cell( int col ); - void delete_cell( int col ); + void insert_cell( int col, int background_color ); + void delete_cell( int col, int background_color ); - void reset( void ); + void reset( int background_color ); }; class SavedCursor { @@ -158,6 +154,8 @@ namespace Terminal { void scroll( int N ); + Row newrow( void ) { return Row( ds.get_width(), ds.get_background_rendition() ); } + public: Framebuffer( int s_width, int s_height ); DrawState ds; @@ -202,7 +200,8 @@ namespace Terminal { 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() ); } }; } diff --git a/terminalfunctions.cpp b/terminalfunctions.cpp index 21e5303..332d2bc 100644 --- a/terminalfunctions.cpp +++ b/terminalfunctions.cpp @@ -12,7 +12,7 @@ using namespace Terminal; static void clearline( Framebuffer *fb, int row, int start, int end ) { 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() ); break; case 2: /* all of line */ - fb->get_row( -1 )->reset(); + fb->reset_row( fb->get_row( -1 ) ); break; } } @@ -40,18 +40,18 @@ void CSI_ED( Framebuffer *fb, Dispatcher *dispatch ) { case 0: /* active position to end of screen, inclusive */ 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++ ) { - fb->get_row( y )->reset(); + fb->reset_row( fb->get_row( y ) ); } break; case 1: /* start of screen to active position, inclusive */ 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() ); break; case 2: /* entire screen */ for ( int y = 0; y < fb->ds.get_height(); y++ ) { - fb->get_row( y )->reset(); + fb->reset_row( fb->get_row( y ) ); } 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 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' ); } } @@ -215,7 +215,7 @@ static bool *get_DEC_mode( int param, Framebuffer *fb ) { fb->ds.move_row( 0 ); fb->ds.move_col( 0 ); for ( int y = 0; y < fb->ds.get_height(); y++ ) { - fb->get_row( y )->reset(); + fb->reset_row( fb->get_row( y ) ); } return NULL; 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. */ void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) { - bool bce = false; - for ( int i = 0; i < dispatch->param_count(); i++ ) { 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 ); } }