[Bf-blender-cvs] [01291783764] master: UI: Use a map for block name lookups

Erik noreply at git.blender.org
Mon Nov 22 18:29:24 CET 2021


Commit: 012917837649676e9ec4b9c2d7d4f7bdfd408739
Author: Erik
Date:   Mon Nov 15 17:10:53 2021 +0100
Branches: master
https://developer.blender.org/rB012917837649676e9ec4b9c2d7d4f7bdfd408739

UI: Use a map for block name lookups

Use a map to speed up search for UI block names.
Time to redraw the node editor was decreased from
around 75-120ms to 40-70ms in a tree with many
Geometry Nodes.

Differential Revision: https://developer.blender.org/D13225

===================================================================

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_region_popup.c
M	source/blender/editors/interface/interface_template_search_menu.cc
M	source/blender/editors/screen/area.c
M	source/blender/editors/screen/screen_edit.c
M	source/blender/editors/space_buttons/space_buttons.c
M	source/blender/makesdna/DNA_screen_types.h

===================================================================

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index f0f267a3cb4..c587425c47f 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -731,8 +731,8 @@ bool UI_block_is_search_only(const uiBlock *block);
 void UI_block_set_search_only(uiBlock *block, bool search_only);
 
 void UI_block_free(const struct bContext *C, uiBlock *block);
-void UI_blocklist_free(const struct bContext *C, struct ListBase *lb);
-void UI_blocklist_free_inactive(const struct bContext *C, struct ListBase *lb);
+void UI_blocklist_free(const struct bContext *C, struct ARegion *region);
+void UI_blocklist_free_inactive(const struct bContext *C, struct ARegion *region);
 void UI_screen_free_active_but(const struct bContext *C, struct bScreen *screen);
 
 void UI_block_region_set(uiBlock *block, struct ARegion *region);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index c753c06b791..55fab04e9a4 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -37,6 +37,7 @@
 #include "DNA_workspace_types.h"
 
 #include "BLI_alloca.h"
+#include "BLI_ghash.h"
 #include "BLI_listbase.h"
 #include "BLI_math.h"
 #include "BLI_rect.h"
@@ -3521,22 +3522,35 @@ void UI_blocklist_draw(const bContext *C, const ListBase *lb)
 }
 
 /* can be called with C==NULL */
-void UI_blocklist_free(const bContext *C, ListBase *lb)
+void UI_blocklist_free(const bContext *C, ARegion *region)
 {
+  ListBase *lb = &region->uiblocks;
   uiBlock *block;
   while ((block = BLI_pophead(lb))) {
     UI_block_free(C, block);
   }
+  if (region->runtime.block_name_map != NULL) {
+    BLI_ghash_free(region->runtime.block_name_map, NULL, NULL);
+    region->runtime.block_name_map = NULL;
+  }
 }
 
-void UI_blocklist_free_inactive(const bContext *C, ListBase *lb)
+void UI_blocklist_free_inactive(const bContext *C, ARegion *region)
 {
+  ListBase *lb = &region->uiblocks;
+
   LISTBASE_FOREACH_MUTABLE (uiBlock *, block, lb) {
     if (!block->handle) {
       if (block->active) {
         block->active = false;
       }
       else {
+        if (region->runtime.block_name_map != NULL) {
+          uiBlock *b = BLI_ghash_lookup(region->runtime.block_name_map, block->name);
+          if (b == block) {
+            BLI_ghash_remove(region->runtime.block_name_map, b->name, NULL, NULL);
+          }
+        }
         BLI_remlink(lb, block);
         UI_block_free(C, block);
       }
@@ -3552,7 +3566,10 @@ void UI_block_region_set(uiBlock *block, ARegion *region)
   /* each listbase only has one block with this name, free block
    * if is already there so it can be rebuilt from scratch */
   if (lb) {
-    oldblock = BLI_findstring(lb, block->name, offsetof(uiBlock, name));
+    if (region->runtime.block_name_map == NULL) {
+      region->runtime.block_name_map = BLI_ghash_str_new(__func__);
+    }
+    oldblock = (uiBlock *)BLI_ghash_lookup(region->runtime.block_name_map, block->name);
 
     if (oldblock) {
       oldblock->active = false;
@@ -3562,6 +3579,7 @@ void UI_block_region_set(uiBlock *block, ARegion *region)
 
     /* at the beginning of the list! for dynamical menus/blocks */
     BLI_addhead(lb, block);
+    BLI_ghash_reinsert(region->runtime.block_name_map, block->name, block, NULL, NULL);
   }
 
   block->oldblock = oldblock;
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 555b699872b..d18b3fdf505 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -11340,8 +11340,7 @@ static void ui_region_handler_remove(bContext *C, void *UNUSED(userdata))
     return;
   }
 
-  UI_blocklist_free(C, &region->uiblocks);
-
+  UI_blocklist_free(C, region);
   bScreen *screen = CTX_wm_screen(C);
   if (screen == NULL) {
     return;
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index 0e53100f91b..0f903bd4af9 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -743,7 +743,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
   if (block_old) {
     block->oldblock = block_old;
     UI_block_update_from_old(C, block);
-    UI_blocklist_free_inactive(C, &region->uiblocks);
+    UI_blocklist_free_inactive(C, region);
   }
 
   /* checks which buttons are visible, sets flags to prevent draw (do after region init) */
diff --git a/source/blender/editors/interface/interface_template_search_menu.cc b/source/blender/editors/interface/interface_template_search_menu.cc
index 64468f4a812..f846eebb457 100644
--- a/source/blender/editors/interface/interface_template_search_menu.cc
+++ b/source/blender/editors/interface/interface_template_search_menu.cc
@@ -787,12 +787,14 @@ static MenuSearch_Data *menu_items_from_ui_create(
           }
 
           if (region) {
+            BLI_ghash_remove(region->runtime.block_name_map, sub_block->name, NULL, NULL);
             BLI_remlink(&region->uiblocks, sub_block);
           }
           UI_block_free(nullptr, sub_block);
         }
       }
       if (region) {
+        BLI_ghash_remove(region->runtime.block_name_map, block->name, NULL, NULL);
         BLI_remlink(&region->uiblocks, block);
       }
       UI_block_free(nullptr, block);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 8523496bdbd..38eadf95bde 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -594,7 +594,7 @@ void ED_region_do_draw(bContext *C, ARegion *region)
 
   memset(&region->drawrct, 0, sizeof(region->drawrct));
 
-  UI_blocklist_free_inactive(C, &region->uiblocks);
+  UI_blocklist_free_inactive(C, region);
 
   if (area) {
     const bScreen *screen = WM_window_get_active_screen(win);
@@ -1985,7 +1985,7 @@ void ED_area_init(wmWindowManager *wm, wmWindow *win, ScrArea *area)
     }
     else {
       /* prevent uiblocks to run */
-      UI_blocklist_free(NULL, &region->uiblocks);
+      UI_blocklist_free(NULL, region);
     }
 
     /* Some AZones use View2D data which is only updated in region init, so call that first! */
@@ -3323,7 +3323,7 @@ bool ED_region_property_search(const bContext *C,
   }
 
   /* Free the panels and blocks, as they are only used for search. */
-  UI_blocklist_free(C, &region->uiblocks);
+  UI_blocklist_free(C, region);
   UI_panels_free_instanced(C, region);
   BKE_area_region_panels_free(&region->panels);
 
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index fa0cfd16817..3c8fb2e7446 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1495,8 +1495,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const
      * switching screens with tooltip open because region and tooltip
      * are no longer in the same screen */
     LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
-      UI_blocklist_free(C, &region->uiblocks);
-
+      UI_blocklist_free(C, region);
       if (region->regiontimer) {
         WM_event_remove_timer(wm, NULL, region->regiontimer);
         region->regiontimer = NULL;
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index b04291b7ab4..bc701bd7aa5 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -445,7 +445,7 @@ static void property_search_all_tabs(const bContext *C,
                    i,
                    property_search_for_context(C, region_copy, &sbuts_copy));
 
-    UI_blocklist_free(C, &region_copy->uiblocks);
+    UI_blocklist_free(C, region_copy);
   }
 
   BKE_area_region_free(area_copy.type, region_copy);
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 03110f6e1be..f15767ff692 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -458,6 +458,9 @@ typedef struct ARegion_Runtime {
 
   /* The offset needed to not overlap with window scrollbars. Only used by HUD regions for now. */
   int offset_x, offset_y;
+
+  /* Maps uiBlock->name to uiBlock for faster lookups. */
+  struct GHash *block_name_map;
 } ARegion_Runtime;
 
 typedef struct ARegion {



More information about the Bf-blender-cvs mailing list