← Back to team overview

kicad-developers team mailing list archive

[PATCH] GerbView performance optimizations

 

These patches improves redraw performance when toggling sketch/filled draw
modes.

On Linux at least, the difference is quite noticeable on complicated Gerber
files.

-Jon
From 04cb51708ff6f46773b3f1acad2b8b8e9adf2db6 Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@xxxxxxxxxxxxx>
Date: Sun, 25 Feb 2018 15:14:28 -0500
Subject: [PATCH 2/2] Add a method to conditionally update VIEW_ITEMs (GerbView
 performance)

---
 common/view/view.cpp                 | 18 +++++++++++
 gerbview/events_called_functions.cpp | 62 ++++++++++++++++++++++++++++++++----
 include/view/view.h                  |  8 +++++
 3 files changed, 81 insertions(+), 7 deletions(-)

diff --git a/common/view/view.cpp b/common/view/view.cpp
index b3c37afdd..9b7a48cfc 100644
--- a/common/view/view.cpp
+++ b/common/view/view.cpp
@@ -1302,6 +1302,24 @@ void VIEW::UpdateAllItems( int aUpdateFlags )
 }
 
 
+void VIEW::UpdateAllItemsConditionally( int aUpdateFlags,
+                                        std::function<bool( VIEW_ITEM* )> aCondition )
+{
+    for( VIEW_ITEM* item : m_allItems )
+    {
+        if( aCondition( item ) )
+        {
+            auto viewData = item->viewPrivData();
+
+            if( !viewData )
+                continue;
+
+            viewData->m_requiredUpdate |= aUpdateFlags;
+        }
+    }
+}
+
+
 struct VIEW::extentsVisitor
 {
     BOX2I extents;
diff --git a/gerbview/events_called_functions.cpp b/gerbview/events_called_functions.cpp
index 8d5043e97..1cfb59463 100644
--- a/gerbview/events_called_functions.cpp
+++ b/gerbview/events_called_functions.cpp
@@ -451,7 +451,6 @@ void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event )
     int     id = event.GetId();
     bool    state;
     bool    needs_refresh = false;
-    bool    needs_repaint = false;
 
     switch( id )
     {
@@ -473,17 +472,17 @@ void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event )
 
     case ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH:
         m_DisplayOptions.m_DisplayFlashedItemsFill = not state;
-        needs_refresh = needs_repaint = true;
+        needs_refresh = true;
         break;
 
     case ID_TB_OPTIONS_SHOW_LINES_SKETCH:
         m_DisplayOptions.m_DisplayLinesFill = not state;
-        needs_refresh = needs_repaint = true;
+        needs_refresh = true;
         break;
 
     case ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH:
         m_DisplayOptions.m_DisplayPolygonsFill = not state;
-        needs_refresh = needs_repaint = true;
+        needs_refresh = true;
         break;
 
     case ID_TB_OPTIONS_SHOW_DCODES:
@@ -532,10 +531,59 @@ void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event )
         applyDisplaySettingsToGAL();
         auto view = GetGalCanvas()->GetView();
 
-        if( needs_repaint )
-            view->UpdateAllItems( KIGFX::REPAINT );
-        else
+        switch( id )
+        {
+        case ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH:
+            view->UpdateAllItemsConditionally( KIGFX::REPAINT,
+                                               []( KIGFX::VIEW_ITEM* aItem ) {
+                auto item = static_cast<GERBER_DRAW_ITEM*>( aItem );
+
+                switch( item->m_Shape )
+                {
+                case GBR_SPOT_CIRCLE:
+                case GBR_SPOT_RECT:
+                case GBR_SPOT_OVAL:
+                case GBR_SPOT_POLY:
+                case GBR_SPOT_MACRO:
+                    return true;
+
+                default:
+                    return false;
+                }
+            } );
+            break;
+
+        case ID_TB_OPTIONS_SHOW_LINES_SKETCH:
+            view->UpdateAllItemsConditionally( KIGFX::REPAINT,
+                                               []( KIGFX::VIEW_ITEM* aItem ) {
+                auto item = static_cast<GERBER_DRAW_ITEM*>( aItem );
+
+                switch( item->m_Shape )
+                {
+                case GBR_CIRCLE:
+                case GBR_ARC:
+                case GBR_SEGMENT:
+                    return true;
+
+                default:
+                    return false;
+                }
+            } );
+            break;
+
+        case ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH:
+            view->UpdateAllItemsConditionally( KIGFX::REPAINT,
+                                               []( KIGFX::VIEW_ITEM* aItem ) {
+                auto item = static_cast<GERBER_DRAW_ITEM*>( aItem );
+
+                return ( item->m_Shape == GBR_POLYGON );
+            } );
+            break;
+
+        default:
             view->UpdateAllItems( KIGFX::COLOR );
+            break;
+        }
 
         m_canvas->Refresh( true );
     }
diff --git a/include/view/view.h b/include/view/view.h
index 15f851e13..9029b7be2 100644
--- a/include/view/view.h
+++ b/include/view/view.h
@@ -616,6 +616,14 @@ public:
      */
     void UpdateAllItems( int aUpdateFlags );
 
+    /**
+     * Updates items in the view according to the given flags and condition
+     * @param aUpdateFlags is is according to KIGFX::VIEW_UPDATE_FLAGS
+     * @param aCondition is a function returning true if the item should be updated
+     */
+    void UpdateAllItemsConditionally( int aUpdateFlags,
+                                      std::function<bool( VIEW_ITEM* )> aCondition );
+
     const BOX2I CalculateExtents() ;
 
     /**
-- 
2.14.1

From 03ed9575d9134058ea860fc1317ab362431bbd3d Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@xxxxxxxxxxxxx>
Date: Sun, 25 Feb 2018 15:01:17 -0500
Subject: [PATCH 1/2] Add a REPAINT flag for faster redraw when bounding box
 hasn't changed

---
 common/view/view.cpp                 | 2 +-
 gerbview/events_called_functions.cpp | 2 +-
 include/view/view_item.h             | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/common/view/view.cpp b/common/view/view.cpp
index b2d5a87e1..b3c37afdd 100644
--- a/common/view/view.cpp
+++ b/common/view/view.cpp
@@ -1092,7 +1092,7 @@ void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags )
 
         if( IsCached( layerId ) )
         {
-            if( aUpdateFlags & ( GEOMETRY | LAYERS ) )
+            if( aUpdateFlags & ( GEOMETRY | LAYERS | REPAINT ) )
                 updateItemGeometry( aItem, layerId );
             else if( aUpdateFlags & COLOR )
                 updateItemColor( aItem, layerId );
diff --git a/gerbview/events_called_functions.cpp b/gerbview/events_called_functions.cpp
index bca5f36c6..8d5043e97 100644
--- a/gerbview/events_called_functions.cpp
+++ b/gerbview/events_called_functions.cpp
@@ -533,7 +533,7 @@ void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event )
         auto view = GetGalCanvas()->GetView();
 
         if( needs_repaint )
-            view->UpdateAllItems( KIGFX::GEOMETRY );
+            view->UpdateAllItems( KIGFX::REPAINT );
         else
             view->UpdateAllItems( KIGFX::COLOR );
 
diff --git a/include/view/view_item.h b/include/view/view_item.h
index 8c1825caa..67d6dad74 100644
--- a/include/view/view_item.h
+++ b/include/view/view_item.h
@@ -57,6 +57,7 @@ enum VIEW_UPDATE_FLAGS {
     GEOMETRY    = 0x04,     /// Position or shape has changed
     LAYERS      = 0x08,     /// Layers have changed
     INITIAL_ADD = 0x10,     /// Item is being added to the view
+    REPAINT     = 0x20,     /// Item needs to be redrawn
     ALL         = 0xef      /// All except INITIAL_ADD
 };
 
-- 
2.14.1


Follow ups