From f85bf48a4b2748709af0d1474c5cd5a32610eef3 Mon Sep 17 00:00:00 2001 From: "tomasz.wlostowski@cern.ch" Date: Thu, 12 Sep 2013 11:40:16 +0200 Subject: [PATCH] EDA_DRAW_PANEL_GAL: redraw stuff in a single place, with "coalescing" Redraws can be requested way too often than it is required. This commit adds redraw timeout: - if the view became dirty and there has been no redraw for longer than certain time, it is redrawed immediately - otherwise, we wait for the next frame This in general improves smoothness of rendering. --- common/drawpanel_gal.cpp | 33 ++++++++++++++++++++++++++++++-- common/view/wx_view_controls.cpp | 3 +-- include/class_drawpanel_gal.h | 7 +++++++ include/view/view.h | 5 +++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/common/drawpanel_gal.cpp b/common/drawpanel_gal.cpp index cb259aba39..9363e099f6 100644 --- a/common/drawpanel_gal.cpp +++ b/common/drawpanel_gal.cpp @@ -91,6 +91,11 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin Connect( wxEVT_KEY_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); Connect( wxEVT_KEY_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); Connect( wxEVT_ENTER_WINDOW, wxEventHandler (EDA_DRAW_PANEL_GAL::onEnter ), NULL, this ); + + + m_refreshTimer.SetOwner( this ); + Connect( wxEVT_TIMER, wxTimerEventHandler( EDA_DRAW_PANEL_GAL::onRefreshTimer ), NULL, this ); + this->SetFocus(); } @@ -113,6 +118,9 @@ EDA_DRAW_PANEL_GAL::~EDA_DRAW_PANEL_GAL() void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) ) { + m_pendingRefresh = false; + m_lastRefresh = wxGetLocalTimeMillis(); + #ifdef __WXDEBUG__ prof_counter time; prof_start( &time, false ); @@ -147,13 +155,33 @@ void EDA_DRAW_PANEL_GAL::onSize( wxSizeEvent& aEvent ) } -void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect ) +void EDA_DRAW_PANEL_GAL::onRefreshTimer( wxTimerEvent& aEvent ) { wxPaintEvent redrawEvent; wxPostEvent( this, redrawEvent ); } +void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect ) +{ + if(m_pendingRefresh) + return; + + wxLongLong t = wxGetLocalTimeMillis(); + wxLongLong delta = t - m_lastRefresh; + + if(t >= MinRefreshPeriod) + { + wxPaintEvent redrawEvent; + wxPostEvent( this, redrawEvent ); + m_pendingRefresh = true; + } else { + m_refreshTimer.Start ( (MinRefreshPeriod - t).ToLong(), true ); + m_pendingRefresh = true; + } +} + + void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) { // Do not do anything if the currently used GAL is correct @@ -208,7 +236,8 @@ void EDA_DRAW_PANEL_GAL::onEvent( wxEvent& aEvent ) m_eventDispatcher->DispatchWxEvent( aEvent ); } - Refresh(); + if(m_view->IsDirty()) + Refresh(); } diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index 838f5b82a0..5cbc97f9cf 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -196,8 +196,7 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent ) dir = m_view->ToWorld( dir, false ); m_view->SetCenter( m_view->GetCenter() + dir * m_autoPanSpeed ); - - m_parentPanel->Refresh(); + m_view->MakeDirty(); } break; diff --git a/include/class_drawpanel_gal.h b/include/class_drawpanel_gal.h index 7daee84a6b..8d6a789db2 100644 --- a/include/class_drawpanel_gal.h +++ b/include/class_drawpanel_gal.h @@ -116,8 +116,15 @@ protected: void onSize( wxSizeEvent& aEvent ); void onEvent( wxEvent& aEvent ); void onEnter( wxEvent& aEvent ); + void onRefreshTimer ( wxTimerEvent& aEvent ); void skipEvent( wxEvent& aEvent ); + static const int MinRefreshPeriod = 17; ///< 60 FPS. + + wxLongLong m_lastRefresh; ///< Last time the panel was refreshed + bool m_pendingRefresh; + wxTimer m_refreshTimer; + KiGfx::GAL* m_gal; ///< Interface for drawing objects on a 2D-surface KiGfx::VIEW* m_view; ///< Stores view settings (scale, center, etc.) ///< and items to be drawn diff --git a/include/view/view.h b/include/view/view.h index 29cb5ecb0e..dbbdd60744 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -443,6 +443,11 @@ public: return ( m_layers.at( aLayer ).target == TARGET_CACHED ); } + void MakeDirty() + { + for(int i = 0; i < TARGETS_NUMBER; i++) + m_dirtyTargets[i] = true; + } static const int VIEW_MAX_LAYERS = 128; ///* maximum number of layers that may be shown