[Bf-blender-cvs] [bbfd0b9] wiggly-widgets: Use GHash for widget update-draw routine

Julian Eisel noreply at git.blender.org
Wed Nov 25 13:01:43 CET 2015


Commit: bbfd0b9c179ea04cd73f56c82fa63f1d9e019886
Author: Julian Eisel
Date:   Wed Nov 25 12:33:41 2015 +0100
Branches: wiggly-widgets
https://developer.blender.org/rBbbfd0b9c179ea04cd73f56c82fa63f1d9e019886

Use GHash for widget update-draw routine

Helps to avoid some unnecessary loop-in-loops and calling wmWidgetGroupType->poll multiple times without changed context. Did some benchmarks but didn't measure a reliable difference in a scene with Franck rig, subsurf level 2 and 6 face-maps. It should help with some really big scenes though (we have to expect rigs with hundreds of face maps).

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

M	source/blender/editors/space_graph/space_graph.c
M	source/blender/editors/space_node/node_draw.c
M	source/blender/editors/space_sequencer/sequencer_draw.c
M	source/blender/editors/space_sequencer/space_sequencer.c
M	source/blender/editors/space_view3d/view3d_draw.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_widgets.c

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

diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 5c83dbc..0340935 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -361,7 +361,7 @@ static void graph_main_area_draw(const bContext *C, ARegion *ar)
 	
 	/* finally draw any widgets here */
 	WM_widgets_update(C, ar->widgetmaps.first);
-	WM_widgets_draw(C, ar->widgetmaps.first, false);
+	WM_widgets_draw(C, ar->widgetmaps.first, false, true);
 	
 	/* scrollers */
 	// FIXME: args for scrollers depend on the type of data being shown...
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index deb2803..e6e545f 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -1367,7 +1367,7 @@ void drawnodespace(const bContext *C, ARegion *ar)
 			wmOrtho2_pixelspace(ar->winx, ar->winy);
 
 			WM_widgets_update(C, ar->widgetmaps.first);
-			WM_widgets_draw(C, ar->widgetmaps.first, false);
+			WM_widgets_draw(C, ar->widgetmaps.first, false, true);
 
 			glMatrixMode(GL_PROJECTION);
 			glPopMatrix();
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 17d2208..6378f9d 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -1651,7 +1651,7 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
 	
 	/* finally draw any widgets here */
 	WM_widgets_update(C, ar->widgetmaps.first);
-	WM_widgets_draw(C, ar->widgetmaps.first, false);
+	WM_widgets_draw(C, ar->widgetmaps.first, false, true);
 
 	/* scrollers */
 	unit = (sseq->flag & SEQ_DRAWFRAMES) ? V2D_UNIT_FRAMES : V2D_UNIT_SECONDS;
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 05078e3..7af6f77 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -606,7 +606,7 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
 	}
 
 	WM_widgets_update(C, ar->widgetmaps.first);
-	WM_widgets_draw(C, ar->widgetmaps.first, false);
+	WM_widgets_draw(C, ar->widgetmaps.first, false, true);
 }
 
 static void sequencer_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index ee3bdec..6554022 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -3893,7 +3893,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
 	 * it might be better to have 2 update calls, too */
 	WM_widgets_update(C, ar->widgetmaps.first);
 	/* draw depth culled widgets */
-	WM_widgets_draw(C, ar->widgetmaps.first, true);
+	WM_widgets_draw(C, ar->widgetmaps.first, true, false);
 
 	/* post process */
 	if (do_compositing) {
@@ -4068,7 +4068,7 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
 	if (update_widgets) {
 		WM_widgets_update(C, ar->widgetmaps.first);
 	}
-	WM_widgets_draw(C, ar->widgetmaps.first, false);
+	WM_widgets_draw(C, ar->widgetmaps.first, false, true);
 
 	ED_region_pixelspace(ar);
 	
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 969bd6d..e893673 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -511,7 +511,8 @@ struct wmWidget *WM_widget_new(void (*draw)(const struct bContext *, struct wmWi
                                int  (*handler)(struct bContext *, const struct wmEvent *, struct wmWidget *));
 
 void  WM_widgets_update(const struct bContext *C, struct wmWidgetMap *wmap);
-void  WM_widgets_draw(const struct bContext *C, const struct wmWidgetMap *wmap, const bool in_scene);
+void  WM_widgets_draw(const struct bContext *C, const struct wmWidgetMap *wmap,
+                      const bool in_scene, const bool free_drawwidgets);
 void  WM_event_add_area_widgetmap_handlers(struct ARegion *ar);
 void  WM_modal_handler_attach_widgetgroup(struct bContext *C, struct wmEventHandler *handler,
                                           struct wmWidgetGroupType *wgrouptype, struct wmOperator *op);
diff --git a/source/blender/windowmanager/intern/wm_widgets.c b/source/blender/windowmanager/intern/wm_widgets.c
index 0ffd4f1..4cf0dd6 100644
--- a/source/blender/windowmanager/intern/wm_widgets.c
+++ b/source/blender/windowmanager/intern/wm_widgets.c
@@ -98,6 +98,12 @@ typedef struct wmWidgetMapType {
  * area type can query the widgetbox to do so */
 static ListBase widgetmaptypes = {NULL, NULL};
 
+/**
+ * Hash table of all visible widgets to avoid unnecessary loops and wmWidgetGroupType->poll checks.
+ * Collected in WM_widgets_update, freed in WM_widgets_draw.
+ */
+static GHash *draw_widgets = NULL;
+
 
 wmWidgetGroupType *WM_widgetgrouptype_new(
         int (*poll)(const bContext *C, wmWidgetGroupType *),
@@ -215,10 +221,16 @@ static void wm_widget_data_free(wmWidget *widget)
 	MEM_freeN(widget->ptr);
 }
 
+/**
+ * Free and NULL \a widget.
+ * \a widgetlist is allowed to be NULL.
+ */
 static void wm_widget_delete(ListBase *widgetlist, wmWidget *widget)
 {
 	wm_widget_data_free(widget);
-	BLI_freelinkN(widgetlist, widget);
+	if (widgetlist)
+		BLI_remlink(widgetlist, widget);
+	MEM_SAFE_FREE(widget);
 }
 
 
@@ -276,18 +288,21 @@ void WM_widgets_update(const bContext *C, wmWidgetMap *wmap)
 	if (!wmap)
 		return;
 
+	if (!draw_widgets) {
+		draw_widgets = BLI_ghash_str_new(__func__);
+	}
+
 	if (widget) {
 		if ((widget->flag & WM_WIDGET_HIDDEN) == 0) {
 			widget_calculate_scale(widget, C);
+			BLI_ghash_reinsert(draw_widgets, widget->idname, widget, NULL, NULL);
 		}
 	}
 	else if (wmap->widgetgroups.first) {
-		GHash *hash = BLI_ghash_str_new(__func__);
+		wmWidget *highlighted = NULL;
 
 		for (wmWidgetGroup *wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) {
 			if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) {
-				wmWidget *highlighted = NULL;
-
 				/* first delete and recreate the widgets */
 				for (widget = wgroup->widgets.first; widget;) {
 					wmWidget *widget_next = widget->next;
@@ -313,38 +328,38 @@ void WM_widgets_update(const bContext *C, wmWidgetMap *wmap)
 					wgroup->type->create(C, wgroup);
 				}
 
-				if (highlighted) {
-					for (widget = wgroup->widgets.first; widget; widget = widget->next) {
-						if (widgets_compare(widget, highlighted)) {
-							widget_highlight_update(wmap, highlighted, widget);
-							wm_widget_delete(&wgroup->widgets, highlighted);
-							highlighted = NULL;
-							break;
-						}
-					}
-				}
-
-				/* if we don't find a highlighted widget, delete the old one here */
-				if (highlighted) {
-					MEM_freeN(highlighted);
-					highlighted = NULL;
-					wmap->wmap_context.highlighted_widget = NULL;
-				}
-
 				for (widget = wgroup->widgets.first; widget; widget = widget->next) {
 					if (widget->flag & WM_WIDGET_HIDDEN)
 						continue;
+
 					widget_calculate_scale(widget, C);
 					/* insert newly created widget into hash table */
-					BLI_ghash_insert(hash, widget->idname, widget);
+					BLI_ghash_reinsert(draw_widgets, widget->idname, widget, NULL, NULL);
 				}
+
+				/* *** From now on, draw_widgets hash table can be used! *** */
+
+			}
+		}
+
+		if (highlighted) {
+			wmWidget *highlighted_new = BLI_ghash_lookup(draw_widgets, highlighted->idname);
+			if (highlighted_new) {
+				BLI_assert(widgets_compare(highlighted, highlighted_new));
+				widget_highlight_update(wmap, highlighted, highlighted_new);
+				wm_widget_delete(NULL, highlighted);
+			}
+			/* if we didn't find a highlighted widget, delete the old one here */
+			else {
+				MEM_SAFE_FREE(highlighted);
+				wmap->wmap_context.highlighted_widget = NULL;
 			}
 		}
 
 		if (wmap->wmap_context.selected_widgets) {
 			for (int i = 0; i < wmap->wmap_context.tot_selected; i++) {
 				wmWidget *sel_old = wmap->wmap_context.selected_widgets[i];
-				wmWidget *sel_new = BLI_ghash_lookup(hash, sel_old->idname);
+				wmWidget *sel_new = BLI_ghash_lookup(draw_widgets, sel_old->idname);
 
 				/* fails if wgtype->poll state changed */
 				if (!sel_new)
@@ -363,8 +378,6 @@ void WM_widgets_update(const bContext *C, wmWidgetMap *wmap)
 				wmap->wmap_context.selected_widgets[i] = sel_new;
 			}
 		}
-
-		BLI_ghash_free(hash, NULL, NULL);
 	}
 }
 
@@ -373,7 +386,16 @@ BLI_INLINE bool widgetgroup_poll_check(const bContext *C, const wmWidgetGroup *w
 	return (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type));
 }
 
-void WM_widgets_draw(const bContext *C, const wmWidgetMap *wmap, const bool in_scene)
+/**
+ * Draw all visible widgets in \a wmap.
+ * Uses global draw_widgets hash table.
+ *
+ * \param in_scene  draw depth-culled widgets (wmWidget->flag WM_WIDGET_SCENE_DEPTH) - TODO
+ * \param free_drawwidgets  free global draw_widgets hash table (always enable for last draw call in region!).
+ */
+void WM_widgets_draw(
+        const bContext *C, const wmWidgetMap *wmap,
+        const bool in_scene, const bool free_drawwidgets)
 {
 	const bool draw_multisample = (U.ogl_multisamples != USER_MULTISAMPLE_NONE);
 	const bool use_lighting = (U.tw_flag & V3D_SHADED_WIDGETS) != 0;
@@ -406,11 +428,7 @@ void WM_widgets_draw(const bContext *C, const wmWidgetMap *wmap, const bool in_s
 
 	wmWidget *widget = wmap->wmap_context.active_widget;
 
-#define WIDGET_DRAW_POLL(widget_) \
-	(in_scene == ((widget_->flag & WM_WIDGET_SCENE_DEPTH) != 0)) && \
-	((widget_->flag & WM_WIDGET_HIDDEN) == 0)
-
-	if (widget && WIDGET_DRAW_POLL(widget)) {
+	if (widget && in_scene == (widget->flag & WM_WIDGET_SCENE_DEPTH)) {
 		if (widget->flag & WM_WIDGET_DRAW_ACTIVE) {
 			/* notice that we don't update the widgetgroup, widget is now on
 			 * its own, it should have all relevant data to update itself */
@@ -418,16 +436,15 @@ void WM_widgets_draw(const bContext *C, const wmWidgetMap *wmap, const bool in_s
 		}
 	}
 	e

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list