Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/intern/draw_manager.c64
-rw-r--r--source/blender/draw/intern/draw_manager.h15
2 files changed, 63 insertions, 16 deletions
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 7f850435a64..9590a4aa7ee 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -632,14 +632,29 @@ void DRW_viewport_request_redraw(void)
/** \name Duplis
* \{ */
-static void drw_duplidata_load(DupliObject *dupli)
+static uint dupli_key_hash(const void *key)
{
+ const DupliKey *dupli_key = (const DupliKey *)key;
+ return BLI_ghashutil_ptrhash(dupli_key->ob) ^ BLI_ghashutil_ptrhash(dupli_key->ob_data);
+}
+
+static bool dupli_key_cmp(const void *key1, const void *key2)
+{
+ const DupliKey *dupli_key1 = (const DupliKey *)key1;
+ const DupliKey *dupli_key2 = (const DupliKey *)key2;
+ return dupli_key1->ob != dupli_key2->ob || dupli_key1->ob_data != dupli_key2->ob_data;
+}
+
+static void drw_duplidata_load(Object *ob)
+{
+ DupliObject *dupli = DST.dupli_source;
if (dupli == NULL) {
return;
}
- if (DST.dupli_origin != dupli->ob) {
+ if (DST.dupli_origin != dupli->ob || (DST.dupli_origin_data != dupli->ob_data)) {
DST.dupli_origin = dupli->ob;
+ DST.dupli_origin_data = dupli->ob_data;
}
else {
/* Same data as previous iter. No need to poll ghash for this. */
@@ -647,16 +662,23 @@ static void drw_duplidata_load(DupliObject *dupli)
}
if (DST.dupli_ghash == NULL) {
- DST.dupli_ghash = BLI_ghash_ptr_new(__func__);
+ DST.dupli_ghash = BLI_ghash_new(dupli_key_hash, dupli_key_cmp, __func__);
}
+ DupliKey *key = MEM_callocN(sizeof(DupliKey), __func__);
+ key->ob = dupli->ob;
+ key->ob_data = dupli->ob_data;
+
void **value;
- if (!BLI_ghash_ensure_p(DST.dupli_ghash, DST.dupli_origin, &value)) {
+ if (!BLI_ghash_ensure_p(DST.dupli_ghash, key, &value)) {
*value = MEM_callocN(sizeof(void *) * DST.enabled_engine_count, __func__);
/* TODO: Meh a bit out of place but this is nice as it is
- * only done once per "original" object. */
- drw_batch_cache_validate(DST.dupli_origin);
+ * only done once per instance type. */
+ drw_batch_cache_validate(ob);
+ }
+ else {
+ MEM_freeN(key);
}
DST.dupli_datas = *(void ***)value;
}
@@ -670,12 +692,24 @@ static void duplidata_value_free(void *val)
MEM_freeN(val);
}
+static void duplidata_key_free(void *key)
+{
+ DupliKey *dupli_key = (DupliKey *)key;
+ if (dupli_key->ob_data == NULL) {
+ drw_batch_cache_generate_requested(dupli_key->ob);
+ }
+ else {
+ Object temp_object = *dupli_key->ob;
+ BKE_object_replace_data_on_shallow_copy(&temp_object, dupli_key->ob_data);
+ drw_batch_cache_generate_requested(&temp_object);
+ }
+ MEM_freeN(key);
+}
+
static void drw_duplidata_free(void)
{
if (DST.dupli_ghash != NULL) {
- BLI_ghash_free(DST.dupli_ghash,
- (void (*)(void *key))drw_batch_cache_generate_requested,
- duplidata_value_free);
+ BLI_ghash_free(DST.dupli_ghash, duplidata_key_free, duplidata_value_free);
DST.dupli_ghash = NULL;
}
}
@@ -1523,6 +1557,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
/* Only iterate over objects for internal engines or when overlays are enabled */
if (do_populate_loop) {
DST.dupli_origin = NULL;
+ DST.dupli_origin_data = NULL;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
continue;
@@ -1532,7 +1567,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
}
DST.dupli_parent = data_.dupli_parent;
DST.dupli_source = data_.dupli_object_current;
- drw_duplidata_load(DST.dupli_source);
+ drw_duplidata_load(ob);
drw_engines_cache_populate(ob);
}
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
@@ -1881,12 +1916,13 @@ void DRW_render_object_iter(
draw_ctx->v3d->object_type_exclude_viewport :
0;
DST.dupli_origin = NULL;
+ DST.dupli_origin_data = NULL;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
if ((object_type_exclude_viewport & (1 << ob->type)) == 0) {
DST.dupli_parent = data_.dupli_parent;
DST.dupli_source = data_.dupli_object_current;
DST.ob_handle = 0;
- drw_duplidata_load(DST.dupli_source);
+ drw_duplidata_load(ob);
if (!DST.dupli_source) {
drw_batch_cache_validate(ob);
@@ -2330,6 +2366,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
v3d->object_type_exclude_select);
bool filter_exclude = false;
DST.dupli_origin = NULL;
+ DST.dupli_origin_data = NULL;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
if (!BKE_object_is_visible_in_viewport(v3d, ob)) {
continue;
@@ -2362,7 +2399,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
DRW_select_load_id(ob->runtime.select_id);
DST.dupli_parent = data_.dupli_parent;
DST.dupli_source = data_.dupli_object_current;
- drw_duplidata_load(DST.dupli_source);
+ drw_duplidata_load(ob);
drw_engines_cache_populate(ob);
}
}
@@ -2475,6 +2512,7 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph,
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
DST.dupli_origin = NULL;
+ DST.dupli_origin_data = NULL;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (DST.draw_ctx.depsgraph, ob) {
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
continue;
@@ -2484,7 +2522,7 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph,
}
DST.dupli_parent = data_.dupli_parent;
DST.dupli_source = data_.dupli_object_current;
- drw_duplidata_load(DST.dupli_source);
+ drw_duplidata_load(ob);
drw_engines_cache_populate(ob);
}
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index 33e1a57198c..1747ca752c7 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -497,6 +497,11 @@ typedef struct DRWDebugSphere {
/* ------------- DRAW MANAGER ------------ */
+typedef struct DupliKey {
+ struct Object *ob;
+ struct ID *ob_data;
+} DupliKey;
+
#define DST_MAX_SLOTS 64 /* Cannot be changed without modifying RST.bound_tex_slots */
#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
#define STENCIL_UNDEFINED 256
@@ -515,15 +520,19 @@ typedef struct DRWManager {
/** Handle of next DRWPass to be allocated. */
DRWResourceHandle pass_handle;
- /** Dupli state. NULL if not dupli. */
+ /** Dupli object that corresponds to the current object. */
struct DupliObject *dupli_source;
+ /** Object that created the dupli-list the current object is part of. */
struct Object *dupli_parent;
+ /** Object referenced by the current dupli object. */
struct Object *dupli_origin;
- /** Ghash containing original objects. */
+ /** Object-data referenced by the current dupli object. */
+ struct ID *dupli_origin_data;
+ /** Ghash: #DupliKey -> void pointer for each enabled engine. */
struct GHash *dupli_ghash;
/** TODO(fclem): try to remove usage of this. */
DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE];
- /* Array of dupli_data (one for each enabled engine) to handle duplis. */
+ /* Dupli data for the current dupli for each enabled engine. */
void **dupli_datas;
/* Rendering state */