* ./hurricane/src/hviewer :

- Optimization: rework the display speed and display policies. Now redraw
        requests no longer interrupt themselves, provoking a lagging effect but
        a more fluid display (Events interruption is working nonetheless).
          Small rework on RedrawManger: more meaningful attributes names and
        code simplification.
          The previous behavior can be re-enabled with the ALLOW_REQUEST_INTERRUPT
        define.
          Try to reduce to the min the number of pixmap copy, less calls to
        DrawingPlanes & repaint.
          The hurricaneAMS transview so regain it's previous fluidity when
        parameters are changed.
    - Change: the _stripWidth can now be adjusted.
    - Note on profiling: sysprof, or rusage do not take account for operations
        outside the processus, so for example, when a pixmap copy is done, it
        doesn't show any cost in the processus but it's paid in Xorg.
          The operation seems to be fast while it's slower instead.
This commit is contained in:
Jean-Paul Chaput 2009-01-24 11:14:38 +00:00
parent 996c1d1c93
commit e58c397360
3 changed files with 139 additions and 112 deletions

View File

@ -196,10 +196,10 @@ namespace Hurricane {
CellWidget::RedrawManager::RedrawManager ( CellWidget* widget ) CellWidget::RedrawManager::RedrawManager ( CellWidget* widget )
: _widget (widget) : _widget (widget)
, _events () , _events ()
, _overrun(false) , _processing (false)
, _refreshInterrupt(false) , _interrupted(false)
{ } { }
@ -214,77 +214,86 @@ namespace Hurricane {
void CellWidget::RedrawManager::goLeft ( int shift ) void CellWidget::RedrawManager::goLeft ( int shift )
{ {
#ifdef ALLOW_REQUEST_INTERRUPT
list<RedrawEvent*>::iterator ievent = _events.end(); list<RedrawEvent*>::iterator ievent = _events.end();
if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) )
--ievent; --ievent;
_events.insert ( ievent, new RedrawEvent(RedrawEvent::GoLeft,shift,_widget) ); _events.insert ( ievent, new RedrawEvent(RedrawEvent::GoLeft,shift,_widget) );
#else
_events.push_back ( new RedrawEvent(RedrawEvent::GoLeft,shift,_widget) );
#endif
if ( !_overrun ) { if ( !_processing ) process ();
if ( _events.size() == 1 ) process ();
else _overrun = true;
}
} }
void CellWidget::RedrawManager::goRight ( int shift ) void CellWidget::RedrawManager::goRight ( int shift )
{ {
#ifdef ALLOW_REQUEST_INTERRUPT
list<RedrawEvent*>::iterator ievent = _events.end(); list<RedrawEvent*>::iterator ievent = _events.end();
if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) )
--ievent; --ievent;
_events.insert ( ievent, new RedrawEvent(RedrawEvent::GoRight,shift,_widget) ); _events.insert ( ievent, new RedrawEvent(RedrawEvent::GoRight,shift,_widget) );
#else
_events.push_back ( new RedrawEvent(RedrawEvent::GoRight,shift,_widget) );
#endif
if ( !_overrun ) { if ( !_processing ) process ();
if ( _events.size() == 1 ) process ();
else _overrun = true;
}
} }
void CellWidget::RedrawManager::goUp ( int shift ) void CellWidget::RedrawManager::goUp ( int shift )
{ {
#ifdef ALLOW_REQUEST_INTERRUPT
list<RedrawEvent*>::iterator ievent = _events.end(); list<RedrawEvent*>::iterator ievent = _events.end();
if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) )
--ievent; --ievent;
_events.insert ( ievent, new RedrawEvent(RedrawEvent::GoUp,shift,_widget) ); _events.insert ( ievent, new RedrawEvent(RedrawEvent::GoUp,shift,_widget) );
#else
_events.push_back ( new RedrawEvent(RedrawEvent::GoUp,shift,_widget) );
#endif
if ( !_overrun ) { if ( !_processing ) process ();
if ( _events.size() == 1 ) process ();
else _overrun = true;
}
} }
void CellWidget::RedrawManager::goDown ( int shift ) void CellWidget::RedrawManager::goDown ( int shift )
{ {
#ifdef ALLOW_REQUEST_INTERRUPT
list<RedrawEvent*>::iterator ievent = _events.end(); list<RedrawEvent*>::iterator ievent = _events.end();
if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) )
--ievent; --ievent;
_events.insert ( ievent, new RedrawEvent(RedrawEvent::GoDown,shift,_widget) ); _events.insert ( ievent, new RedrawEvent(RedrawEvent::GoDown,shift,_widget) );
#else
_events.push_back ( new RedrawEvent(RedrawEvent::GoDown,shift,_widget) );
#endif
if ( !_overrun ) { if ( !_processing ) process ();
if ( _events.size() == 1 ) process ();
else _overrun = true;
}
} }
void CellWidget::RedrawManager::refresh () void CellWidget::RedrawManager::refresh ()
{ {
#ifdef ALLOW_REQUEST_INTERRUPT
if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) { if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) {
_refreshInterrupt = true; _interrupted = true;
} else if ( _events.empty() ) { } else if ( _events.empty() ) {
_events.push_back ( new RedrawEvent(RedrawEvent::Refresh,0,_widget) ); _events.push_back ( new RedrawEvent(RedrawEvent::Refresh,0,_widget) );
if ( !_overrun ) { if ( !_processing ) process ();
if ( _events.size() == 1 ) process ();
else _overrun = true;
}
} }
#else
_events.push_back ( new RedrawEvent(RedrawEvent::Refresh,0,_widget) );
if ( !_processing ) process ();
#endif
} }
inline void CellWidget::RedrawManager::process () inline void CellWidget::RedrawManager::process ()
{ {
_processing = true;
while ( !_events.empty() ) { while ( !_events.empty() ) {
RedrawEvent* event = _events.front (); RedrawEvent* event = _events.front ();
@ -296,19 +305,24 @@ namespace Hurricane {
case RedrawEvent::Refresh: _widget->_refresh (); break; case RedrawEvent::Refresh: _widget->_refresh (); break;
} }
if ( event->getType() == RedrawEvent::Refresh ) #ifdef ALLOW_REQUEST_INTERRUPT
if ( event->getType() == RedrawEvent::Refresh ) {
_events.pop_back (); _events.pop_back ();
else } else
_events.pop_front (); _events.pop_front ();
delete event; delete event;
if ( _events.empty() && (_overrun || _refreshInterrupt) ) { if ( _events.empty() && _interrupted ) {
_events.push_back ( new RedrawEvent(RedrawEvent::Refresh,0,_widget) ); _events.push_back ( new RedrawEvent(RedrawEvent::Refresh,0,_widget) );
_overrun = false; _interrupted = false;
_refreshInterrupt = false;
} }
#else
_events.pop_front ();
#endif
} }
_processing = false;
} }
@ -831,38 +845,40 @@ namespace Hurricane {
// Class : "Hurricane::CellWidget". // Class : "Hurricane::CellWidget".
const int CellWidget::_stripWidth = 100; const int CellWidget::_stripWidth = 10;
const int CellWidget::_initialSide = (400/_stripWidth)*_stripWidth;
CellWidget::CellWidget ( QWidget* parent ) : QWidget(parent) CellWidget::CellWidget ( QWidget* parent )
, _technology(NULL) : QWidget (parent)
, _palette(NULL) , _technology (NULL)
, _displayArea(0,0,6*_stripWidth,6*_stripWidth) , _palette (NULL)
, _visibleArea(_stripWidth,_stripWidth,4*_stripWidth,4*_stripWidth) , _displayArea (0,0,_initialSide+2*_stripWidth,_initialSide+2*_stripWidth)
, _scale(1.0) , _visibleArea (_stripWidth,_stripWidth,_initialSide,_initialSide)
, _offsetVA(_stripWidth,_stripWidth) , _scale (1.0)
, _redrawManager(this) , _offsetVA (_stripWidth,_stripWidth)
, _drawingPlanes(QSize(6*_stripWidth,6*_stripWidth),this) , _redrawManager (this)
, _drawingQuery(this) , _drawingPlanes (QSize(_initialSide+2*_stripWidth,_initialSide+2*_stripWidth),this)
, _textDrawingQuery(this) , _drawingQuery (this)
, _queryFilter(~Query::DoTerminalCells) , _textDrawingQuery (this)
, _darkening(100) , _queryFilter (~Query::DoTerminalCells)
, _mousePosition(0,0) , _darkening (100)
, _spot(this) , _mousePosition (0,0)
, _cell(NULL) , _spot (this)
, _cellChanged(true) , _cell (NULL)
, _showBoundaries(true) , _cellChanged (true)
, _showSelection(false) , _showBoundaries (true)
, _cumulativeSelection(false) , _showSelection (false)
, _selectionHasChanged(false) , _cumulativeSelection (false)
, _delaySelectionChanged(0) , _selectionHasChanged (false)
, _cellModificated(true) , _delaySelectionChanged(0)
, _selectors() , _cellModificated (true)
, _selection(this) , _selectors ()
, _commands() , _selection (this)
, _redrawRectCount(0) , _commands ()
, _textFontHeight(20) , _redrawRectCount (0)
, _rubberShape(Steiner) , _textFontHeight (20)
, _rubberShape (Steiner)
{ {
//setBackgroundRole ( QPalette::Dark ); //setBackgroundRole ( QPalette::Dark );
//setAutoFillBackground ( false ); //setAutoFillBackground ( false );
@ -971,7 +987,7 @@ namespace Hurricane {
QSize CellWidget::minimumSizeHint () const QSize CellWidget::minimumSizeHint () const
{ {
return QSize(_stripWidth*4,_stripWidth*4); return QSize(_initialSide,_initialSide);
} }
@ -1010,13 +1026,13 @@ namespace Hurricane {
// << _selectionHasChanged << " filter:" // << _selectionHasChanged << " filter:"
// << _queryFilter << endl; // << _queryFilter << endl;
static bool timedout; // static bool timedout;
static Timer timer; // static Timer timer;
if ( !isVisible() ) return; if ( !isVisible() ) return;
timer.start (); // timer.start ();
timedout = false; // timedout = false;
_cellChanged = false; _cellChanged = false;
_redrawRectCount = 0; _redrawRectCount = 0;
@ -1024,7 +1040,7 @@ namespace Hurricane {
if ( ! ( _selectionHasChanged && _showSelection ) || _cellModificated ) { if ( ! ( _selectionHasChanged && _showSelection ) || _cellModificated ) {
_spot.setRestore ( false ); _spot.setRestore ( false );
_drawingPlanes.copyToSelect ( redrawArea ); //_drawingPlanes.copyToSelect ( redrawArea );
_drawingPlanes.select ( PlaneId::Normal ); _drawingPlanes.select ( PlaneId::Normal );
_drawingPlanes.painterBegin (); _drawingPlanes.painterBegin ();
@ -1032,7 +1048,7 @@ namespace Hurricane {
_drawingPlanes.painter().setBackground ( Graphics::getBrush("background") ); _drawingPlanes.painter().setBackground ( Graphics::getBrush("background") );
_drawingPlanes.painter().setClipRect ( redrawArea ); _drawingPlanes.painter().setClipRect ( redrawArea );
_drawingPlanes.painter().eraseRect ( redrawArea ); _drawingPlanes.painter().eraseRect ( redrawArea );
repaint (); //repaint ();
setDarkening ( (_showSelection) ? Graphics::getDarkening() : 100 ); setDarkening ( (_showSelection) ? Graphics::getDarkening() : 100 );
@ -1055,8 +1071,8 @@ namespace Hurricane {
_drawingQuery.setBasicLayer ( *iLayer ); _drawingQuery.setBasicLayer ( *iLayer );
_drawingQuery.setFilter ( _queryFilter & ~(Query::DoMasterCells|Query::DoRubbers) ); _drawingQuery.setFilter ( _queryFilter & ~(Query::DoMasterCells|Query::DoRubbers) );
_drawingQuery.doQuery (); _drawingQuery.doQuery ();
_drawingPlanes.copyToSelect ( redrawArea ); //_drawingPlanes.copyToSelect ( redrawArea );
repaint (); //repaint ();
} }
QApplication::processEvents(); QApplication::processEvents();
if ( _redrawManager.interrupted() ) { if ( _redrawManager.interrupted() ) {
@ -1074,8 +1090,8 @@ namespace Hurricane {
_drawingQuery.setBasicLayer ( NULL ); _drawingQuery.setBasicLayer ( NULL );
_drawingQuery.setFilter ( _queryFilter & ~(Query::DoComponents|Query::DoRubbers) ); _drawingQuery.setFilter ( _queryFilter & ~(Query::DoComponents|Query::DoRubbers) );
_drawingQuery.doQuery (); _drawingQuery.doQuery ();
_drawingPlanes.copyToSelect ( redrawArea ); //_drawingPlanes.copyToSelect ( redrawArea );
repaint (); //repaint ();
} }
} }
@ -1087,8 +1103,8 @@ namespace Hurricane {
_drawingQuery.setBasicLayer ( NULL ); _drawingQuery.setBasicLayer ( NULL );
_drawingQuery.setFilter ( _queryFilter & ~(Query::DoComponents|Query::DoMasterCells) ); _drawingQuery.setFilter ( _queryFilter & ~(Query::DoComponents|Query::DoMasterCells) );
_drawingQuery.doQuery (); _drawingQuery.doQuery ();
_drawingPlanes.copyToSelect ( redrawArea ); //_drawingPlanes.copyToSelect ( redrawArea );
repaint (); //repaint ();
} }
} }
@ -1101,8 +1117,8 @@ namespace Hurricane {
_textDrawingQuery.setArea ( redrawBox ); _textDrawingQuery.setArea ( redrawBox );
_textDrawingQuery.setTransformation ( Transformation() ); _textDrawingQuery.setTransformation ( Transformation() );
_textDrawingQuery.doQuery (); _textDrawingQuery.doQuery ();
_drawingPlanes.copyToSelect ( redrawArea ); //_drawingPlanes.copyToSelect ( redrawArea );
repaint (); //repaint ();
} }
} }
@ -1116,10 +1132,11 @@ namespace Hurricane {
_drawingQuery.setDrawExtensionGo ( (*islice)->getName() ); _drawingQuery.setDrawExtensionGo ( (*islice)->getName() );
_drawingQuery.setFilter ( Query::DoExtensionGos ); _drawingQuery.setFilter ( Query::DoExtensionGos );
_drawingQuery.doQuery (); _drawingQuery.doQuery ();
_drawingPlanes.copyToSelect ( redrawArea ); //_drawingPlanes.copyToSelect ( redrawArea );
repaint (); //repaint ();
} }
} }
repaint ();
} }
_drawingPlanes.painterEnd (); _drawingPlanes.painterEnd ();
@ -1134,7 +1151,7 @@ namespace Hurricane {
popCursor (); popCursor ();
timer.stop (); // timer.stop ();
// cerr << "CellWidget::redraw() - " << _redrawRectCount // cerr << "CellWidget::redraw() - " << _redrawRectCount
// << " in " << timer.getCombTime() << "s (" // << " in " << timer.getCombTime() << "s ("
// << setprecision(3) << (timer.getCombTime()/_redrawRectCount) << " s/r)"; // << setprecision(3) << (timer.getCombTime()/_redrawRectCount) << " s/r)";
@ -1654,34 +1671,33 @@ namespace Hurricane {
void CellWidget::paintEvent ( QPaintEvent* event ) void CellWidget::paintEvent ( QPaintEvent* event )
{ {
static Timer timer; // static Timer timer;
static time_t prevTime = 0; // static time_t prevTime = 0;
static time_t currTime = 0; // static time_t currTime = 0;
timer.start (); // timer.start ();
_drawingPlanes.painterBegin ( PlaneId::Widget ); _drawingPlanes.painterBegin ( PlaneId::Widget );
_drawingPlanes.copyToScreen (); _drawingPlanes.copyToScreen ();
for ( size_t i=0 ; i<_commands.size() ; i++ ) for ( size_t i=0 ; i<_commands.size() ; i++ )
_commands[i]->draw ( this ); _commands[i]->draw ( this );
// if ( isDrawable("grid") ) drawGrid ();
if ( isDrawable("spot") ) _spot.moveTo ( _mousePosition ); if ( isDrawable("spot") ) _spot.moveTo ( _mousePosition );
_drawingPlanes.painterEnd ( PlaneId::Widget ); _drawingPlanes.painterEnd ( PlaneId::Widget );
timer.stop (); // timer.stop ();
time ( &currTime ); // time ( &currTime );
double delta = difftime ( currTime, prevTime ); // double delta = difftime ( currTime, prevTime );
// if ( delta ) // if ( delta )
// cerr << "CellWidget::paintEvent() - lagging: " << delta << endl; // cerr << "CellWidget::paintEvent() - lagging: " << delta << endl;
prevTime = currTime; // prevTime = currTime;
} }
void CellWidget::resizeEvent ( QResizeEvent* ) void CellWidget::resizeEvent ( QResizeEvent* )
{ {
//cerr << "CellWidget::resizeEvent() - size: " << geometry().width() << "x" << geometry().height() << endl; // cerr << "CellWidget::resizeEvent() - size: " << geometry().width() << "x" << geometry().height() << endl;
QSize uaDelta ( 0, 0 ); QSize uaDelta ( 0, 0 );
QSize uaSize = geometry().size(); QSize uaSize = geometry().size();

View File

@ -91,9 +91,13 @@ namespace Hurricane {
QPoint eventPosition = event->pos(); QPoint eventPosition = event->pos();
if ( _firstEvent ) { _firstEvent = false; _lastPosition = eventPosition; } if ( _firstEvent ) { _firstEvent = false; _lastPosition = eventPosition; }
int dx = ( eventPosition.x() - _lastPosition.x() ) << 1; int dx = eventPosition.x() - _lastPosition.x();
int dy = ( eventPosition.y() - _lastPosition.y() ) << 1; int dy = eventPosition.y() - _lastPosition.y();
_lastPosition = eventPosition; int rx = dx%2;
int ry = dy%2;
_lastPosition = QPoint ( eventPosition.x() - rx, eventPosition.y() - ry );
dx -= rx;
dy -= ry;
if ( dx > 0 ) widget->goLeft ( dx ); if ( dx > 0 ) widget->goLeft ( dx );
if ( dx < 0 ) widget->goRight ( -dx ); if ( dx < 0 ) widget->goRight ( -dx );

View File

@ -273,23 +273,23 @@ namespace Hurricane {
private: private:
class RedrawManager { class RedrawManager {
public: public:
inline RedrawManager ( CellWidget* ); inline RedrawManager ( CellWidget* );
~RedrawManager (); ~RedrawManager ();
void goLeft ( int ); void goLeft ( int );
void goRight ( int ); void goRight ( int );
void goUp ( int ); void goUp ( int );
void goDown ( int ); void goDown ( int );
void refresh (); void refresh ();
void process (); void process ();
inline void clearOverrun (); inline void stopProcessing ();
inline bool isOverrun () const; inline bool isProcessing () const;
inline bool interrupted () const; inline bool interrupted () const;
inline size_t getPendings () const; inline size_t getPendings () const;
private: private:
CellWidget* _widget; CellWidget* _widget;
list<RedrawEvent*> _events; list<RedrawEvent*> _events;
bool _overrun; bool _processing;
bool _refreshInterrupt; bool _interrupted;
}; };
public: public:
@ -442,6 +442,7 @@ namespace Hurricane {
protected: protected:
// Internal: Attributes. // Internal: Attributes.
static const int _stripWidth; static const int _stripWidth;
static const int _initialSide;
vector<Qt::CursorShape> _cursors; vector<Qt::CursorShape> _cursors;
// MapView* _mapView; // MapView* _mapView;
Technology* _technology; Technology* _technology;
@ -541,12 +542,12 @@ namespace Hurricane {
{ return _shift; } { return _shift; }
inline bool CellWidget::RedrawManager::isOverrun () const inline bool CellWidget::RedrawManager::isProcessing () const
{ return _overrun; } { return _processing; }
inline void CellWidget::RedrawManager::clearOverrun () inline void CellWidget::RedrawManager::stopProcessing ()
{ _overrun = false; } { _processing = false; }
inline size_t CellWidget::RedrawManager::getPendings () const inline size_t CellWidget::RedrawManager::getPendings () const
@ -554,7 +555,13 @@ namespace Hurricane {
inline bool CellWidget::RedrawManager::interrupted () const inline bool CellWidget::RedrawManager::interrupted () const
{ return ( _events.size() > 5 ) || _refreshInterrupt; } {
#ifdef ALLOW_REQUEST_INTERRUPT
return ( _events.size() > 5 ) || _interrupted;
#else
return _interrupted;
#endif
}
inline bool CellWidget::DrawingPlanes::getLineMode () const inline bool CellWidget::DrawingPlanes::getLineMode () const