[Bf-blender-cvs] [55b4652] gooseberry: BKE functions for managing cache content based on a group.

Lukas Tönne noreply at git.blender.org
Mon Mar 23 13:00:43 CET 2015


Commit: 55b4652885f0b94e1e1f9f2d4f800baef78be154
Author: Lukas Tönne
Date:   Sat Feb 21 12:28:51 2015 +0100
Branches: gooseberry
https://developer.blender.org/rB55b4652885f0b94e1e1f9f2d4f800baef78be154

BKE functions for managing cache content based on a group.

This uses a complete hierarchy of group instances, based on a path
hierarchy (object names).

Putting

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

M	source/blender/blenkernel/BKE_cache_library.h
M	source/blender/blenkernel/intern/cache_library.c
M	source/blender/makesdna/DNA_cache_library_types.h

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

diff --git a/source/blender/blenkernel/BKE_cache_library.h b/source/blender/blenkernel/BKE_cache_library.h
index 92a1f9d..53dd131 100644
--- a/source/blender/blenkernel/BKE_cache_library.h
+++ b/source/blender/blenkernel/BKE_cache_library.h
@@ -32,11 +32,28 @@
  *  \ingroup bke
  */
 
-struct CacheLibrary;
 struct Main;
+struct CacheLibrary;
+struct CacheItem;
+struct CacheItemPath;
 
 struct CacheLibrary *BKE_cache_library_add(struct Main *bmain, const char *name);
 struct CacheLibrary *BKE_cache_library_copy(struct CacheLibrary *cachelib);
-void BKE_cache_library_free(struct CacheLibrary *cache);
+void BKE_cache_library_free(struct CacheLibrary *cachelib);
+
+bool BKE_cache_item_path_cmp(const struct CacheItemPath *a, const struct CacheItemPath *b);
+int BKE_cache_item_path_len(const struct CacheItemPath *path);
+bool BKE_cache_item_path_append(struct CacheItemPath *path, const char *name);
+void BKE_cache_item_path_replace(struct CacheItemPath *path, const char *name, int index);
+void BKE_cache_item_path_clear(struct CacheItemPath *path);
+void BKE_cache_item_path_truncate(struct CacheItemPath *path, int len);
+void BKE_cache_item_path_copy(struct CacheItemPath *dst, const struct CacheItemPath *src);
+
+typedef void (*CacheGroupWalkFunc)(void *userdata, struct CacheLibrary *cachelib, const struct CacheItemPath *path);
+void BKE_cache_library_walk(struct CacheLibrary *cachelib, CacheGroupWalkFunc walk, void *userdata);
+
+struct CacheItem *BKE_cache_library_find_item(struct CacheLibrary *cachelib, const struct CacheItemPath *path);
+struct CacheItem *BKE_cache_library_add_item(struct CacheLibrary *cachelib, const struct CacheItemPath *path);
+bool BKE_cache_library_remove_item(struct CacheLibrary *cachelib, const struct CacheItemPath *path);
 
 #endif
diff --git a/source/blender/blenkernel/intern/cache_library.c b/source/blender/blenkernel/intern/cache_library.c
index cbfed7c..0ab19ba 100644
--- a/source/blender/blenkernel/intern/cache_library.c
+++ b/source/blender/blenkernel/intern/cache_library.c
@@ -27,18 +27,83 @@
  *  \ingroup bke
  */
 
+#include <string.h>
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_string.h"
 #include "BLI_utildefines.h"
 
 #include "DNA_cache_library_types.h"
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
 
 #include "BKE_cache_library.h"
 #include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
 
+bool BKE_cache_item_path_cmp(const CacheItemPath *a, const CacheItemPath *b)
+{
+	int i, cmp;
+	for (i = 0; i < MAX_CACHE_GROUP_LEVEL; ++i) {
+		if (a->value[i][0] == '\0' && b->value[i][0] == '\0')
+			break;
+		cmp = strcmp(a->value[i], b->value[i]);
+		if (cmp != 0)
+			return cmp;
+	}
+	return 0;
+}
+
+int BKE_cache_item_path_len(const CacheItemPath *path)
+{
+	int i;
+	for (i = 0; i < MAX_CACHE_GROUP_LEVEL; ++i) {
+		if (path->value[i][0] == '\0')
+			break;
+	}
+	return i;
+}
+
+bool BKE_cache_item_path_append(CacheItemPath *path, const char *name)
+{
+	int i;
+	for (i = 0; i < MAX_CACHE_GROUP_LEVEL; ++i) {
+		if (path->value[i][0] == '\0') {
+			BLI_strncpy(path->value[i], name, sizeof(path->value[i]));
+			return true;
+		}
+	}
+	return false;
+}
+
+void BKE_cache_item_path_replace(CacheItemPath *path, const char *name, int index)
+{
+	BLI_assert(index < MAX_CACHE_GROUP_LEVEL);
+	BLI_strncpy(path->value[index], name, sizeof(path->value[index]));
+}
+
+void BKE_cache_item_path_clear(CacheItemPath *path)
+{
+	path->value[0][0] = '\0';
+}
+
+void BKE_cache_item_path_truncate(CacheItemPath *path, int len)
+{
+	BLI_assert(len < MAX_CACHE_GROUP_LEVEL);
+	path->value[len][0] = '\0';
+}
+
+void BKE_cache_item_path_copy(CacheItemPath *dst, const CacheItemPath *src)
+{
+	memcpy(dst->value, src->value, sizeof(CacheItemPath));
+}
+
+/* ========================================================================= */
+
 CacheLibrary *BKE_cache_library_add(Main *bmain, const char *name)
 {
 	CacheLibrary *cachelib;
@@ -56,6 +121,8 @@ CacheLibrary *BKE_cache_library_copy(CacheLibrary *cachelib)
 	
 	cachelibn = BKE_libblock_copy(&cachelib->id);
 	
+	BLI_duplicatelist(&cachelibn->items, &cachelib->items);
+	
 	if (cachelib->id.lib) {
 		BKE_id_lib_local_paths(G.main, cachelib->id.lib, &cachelibn->id);
 	}
@@ -63,6 +130,188 @@ CacheLibrary *BKE_cache_library_copy(CacheLibrary *cachelib)
 	return cachelibn;
 }
 
-void BKE_cache_library_free(CacheLibrary *UNUSED(cache))
+void BKE_cache_library_free(CacheLibrary *cachelib)
+{
+	BLI_freelistN(&cachelib->items);
+}
+
+/* ========================================================================= */
+
+static void cache_library_walk_recursive(CacheLibrary *cachelib, CacheGroupWalkFunc walk, void *userdata, const CacheItemPath *path, int level, Object *ob)
+{
+	/* object dm */
+	walk(userdata, cachelib, path);
+	
+	/* dupli group recursion */
+	if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
+		GroupObject *gob;
+		
+		for (gob = ob->dup_group->gobject.first; gob; gob = gob->next) {
+			CacheItemPath gpath;
+			BKE_cache_item_path_copy(&gpath, path);
+			BKE_cache_item_path_append(&gpath, ob->id.name+2);
+			cache_library_walk_recursive(cachelib, walk, userdata, &gpath, level + 1, gob->ob);
+		}
+	}
+}
+
+void BKE_cache_library_walk(CacheLibrary *cachelib, CacheGroupWalkFunc walk, void *userdata)
+{
+	CacheItemPath path;
+	BKE_cache_item_path_clear(&path);
+	
+	if (cachelib && cachelib->group) {
+		GroupObject *gob;
+		
+		for (gob = cachelib->group->gobject.first; gob; gob = gob->next) {
+			cache_library_walk_recursive(cachelib, walk, userdata, &path, 0, gob->ob);
+		}
+	}
+}
+
+/* ========================================================================= */
+
+BLI_INLINE unsigned int hash_int_2d(unsigned int kx, unsigned int ky)
+{
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+	uint a, b, c;
+
+	a = b = c = 0xdeadbeef + (2 << 2) + 13;
+	a += kx;
+	b += ky;
+
+	c ^= b; c -= rot(b,14);
+	a ^= c; a -= rot(c,11);
+	b ^= a; b -= rot(a,25);
+	c ^= b; c -= rot(b,16);
+	a ^= c; a -= rot(c,4);
+	b ^= a; b -= rot(a,14);
+	c ^= b; c -= rot(b,24);
+
+	return c;
+
+#undef rot
+}
+
+static unsigned int cache_item_hash(const void *key)
+{
+	const CacheItemPath *path = key;
+	int i;
+	unsigned int hash = 0;
+	
+	for (i = 0; i < MAX_CACHE_GROUP_LEVEL; ++i) {
+		hash = hash_int_2d(hash, BLI_ghashutil_strhash(path->value[i]));
+	}
+	return hash;
+}
+
+static bool cache_item_cmp(const void *key_a, const void *key_b)
+{
+	return BKE_cache_item_path_cmp(key_a, key_b) != 0;
+}
+
+static void cache_library_insert_item_hash(CacheLibrary *cachelib, CacheItem *item, bool replace)
+{
+	CacheItemPath *path = &item->path;
+	CacheItem *exist = BLI_ghash_lookup(cachelib->items_hash, path);
+	if (exist && replace) {
+		BLI_remlink(&cachelib->items, exist);
+		BLI_ghash_remove(cachelib->items_hash, path, NULL, NULL);
+		MEM_freeN(exist);
+	}
+	if (!exist || replace)
+		BLI_ghash_insert(cachelib->items_hash, path, item);
+}
+
+static void cache_library_ensure_items_hash(CacheLibrary *cachelib)
+{
+	CacheItem *item;
+	
+	if (cachelib->items_hash) {
+		BLI_ghash_clear(cachelib->items_hash, NULL, NULL);
+	}
+	else {
+		cachelib->items_hash = BLI_ghash_new(cache_item_hash, cache_item_cmp, "cache item hash");
+	}
+	
+	for (item = cachelib->items.first; item; item = item->next) {
+		cache_library_insert_item_hash(cachelib, item, true);
+	}
+}
+
+CacheItem *BKE_cache_library_find_item(CacheLibrary *cachelib, const CacheItemPath *path)
 {
+	return BLI_ghash_lookup(cachelib->items_hash, path);
+}
+
+CacheItem *BKE_cache_library_add_item(CacheLibrary *cachelib, const CacheItemPath *path)
+{
+	CacheItem *item = BLI_ghash_lookup(cachelib->items_hash, path);
+	
+	if (!item) {
+		item = MEM_callocN(sizeof(CacheItem), "cache library item");
+		BKE_cache_item_path_copy(&item->path, path);
+		
+		BLI_addtail(&cachelib->items, item);
+		cache_library_insert_item_hash(cachelib, item, false);
+	}
+	
+	return item;
+}
+
+bool BKE_cache_library_remove_item(CacheLibrary *cachelib, const CacheItemPath *path)
+{
+	CacheItem *item = BLI_ghash_lookup(cachelib->items_hash, path);
+	if (item) {
+		BLI_ghash_remove(cachelib->items_hash, (CacheItemPath *)path, NULL, NULL);
+		BLI_remlink(&cachelib->items, item);
+		MEM_freeN(item);
+		return true;
+	}
+	else
+		return false;
+}
+
+/* ========================================================================= */
+
+#if 0
+typedef struct UpdateItemsData {
+	CacheItem *cur;
+} UpdateItemsData;
+
+static void cache_library_update_items_walk(void *userdata, CacheLibrary *cachelib)
+{
+	UpdateItemsData *data = userdata;
+	CacheItem *item;
+	
+	if (data->cur) {
+		item = data->cur;
+		data->cur = data->cur->next;
+	}
+	else {
+		item = MEM_callocN(sizeof(CacheItem), "cache library item");
+		BLI_addtail(&cachelib->items, item);
+	}
+}
+
+void BKE_cache_library_update_items(CacheLibrary *cachelib)
+{
+	UpdateItemsData data;
+	
+	data.cur = cachelib->items.first;
+	BKE_cache_library_walk(cachelib, cache_library_update_items_walk, &data);
+	
+	/* truncate items list */
+	if (data.cur) {
+		cachelib->items.last = data.cur->prev;
+		while (data.cur) {
+			CacheItem *item = data.cur;
+			data.cur = data.cur->next;
+			
+			BLI_remlink(&cachelib->items, item);
+			MEM_freeN(item);
+		}
+	}
 }
+#endif
diff --git a/source/blender/makesdna/DNA_cache_library_types.h b/source/blender/makesdna/DNA_cache_library_types.h
index 223cde1..36b60d7 100644
--- a/source/blender/makesdna/DNA_cache_library_types.h
+++ b/source/blender/makesdna/DNA_cache_library_types.h
@@ -34,12 +34,28 @@
 
 #include "DNA_defs.h"
 #include "DNA_ID.h"
+#include "DNA_listBase.h"
+
+#define MAX_CACHE_GROUP_LEVEL 8
+
+typedef struct CacheItemPath {
+	char value[8][64]; /* MAX_CACHE_GROUP_LEVEL, MAX_NAME */
+} CacheItemPath;
+
+typedef struct CacheItem {
+	struct CacheItem *next, *prev;
+	
+	CacheItemPath path;
+} CacheItem;
 
 typedef struct CacheLibrary {
 	ID id;
 	
 	char filepath[1024]; /* 1024 = FILE_MAX */
 	struct Group *group;
+	
+	ListBase items;				/* cached items */
+	struct GHash *items_hash;	/* runtime: cached items hash for fast lookup */
 } CacheLibrary;
 
 #endif




More information about the Bf-blender-cvs mailing list