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:
authorAntonioya <blendergit@gmail.com>2018-10-19 21:39:21 +0300
committerAntonioya <blendergit@gmail.com>2018-10-20 10:08:34 +0300
commit541d07045b79cef52bdcf8bd1d90fc60793c9872 (patch)
treec8fcaaf79ce0d3a0cea526338e65d63a6de6048f /source/blender/draw/engines/gpencil/gpencil_cache_utils.c
parentb634bf9fb64930e0073c17bc115b6c3436b9a8e2 (diff)
GP: Redesign drawing cache to support particles
Full redesign of the cache system used for drawing strokes and handle derived frame data. Before, the cache was saved in bGPdata and a hash was used to manage several objects with the same datablock. Old design made the use of particles very inefficient and prone to bugs and segment faults, and especially when this was mixed with onion skinning and multiple objects using same datablock. Also, there were some conflicts with the depsgrah logic (the old design was done before despgraph was in place) that made the use of hash not working. The new design saves the data in the object runtime struct and avoid the use of any hash to find the right data. This improves the speed and reduce a lot the complexity of the code, memory allocation, hash overload and adds full support for particles and reused datablocks. The particles can reuse the modifiers and shader effects of the original grease pencil object.
Diffstat (limited to 'source/blender/draw/engines/gpencil/gpencil_cache_utils.c')
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c158
1 files changed, 92 insertions, 66 deletions
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index e8f8254bb5b..9d8c4b6d0f8 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -37,17 +37,20 @@
#include "draw_cache_impl.h"
-static bool gpencil_check_ob_duplicated(tGPencilObjectCache *cache_array, int gp_cache_used, Object *ob)
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+static bool gpencil_check_ob_duplicated(tGPencilObjectCache *cache_array,
+ int gp_cache_used, Object *ob, int *r_index)
{
if (gp_cache_used == 0) {
return false;
}
- for (int i = 0; i < gp_cache_used + 1; i++) {
+ for (int i = 0; i < gp_cache_used; i++) {
tGPencilObjectCache *cache_elem = &cache_array[i];
- if (STREQ(cache_elem->ob_name, ob->id.name) &&
- (cache_elem->is_dup_ob == false))
- {
+ if (cache_elem->ob == ob) {
+ *r_index = cache_elem->data_idx;
return true;
}
}
@@ -62,9 +65,9 @@ static bool gpencil_check_datablock_duplicated(
return false;
}
- for (int i = 0; i < gp_cache_used + 1; i++) {
+ for (int i = 0; i < gp_cache_used; i++) {
tGPencilObjectCache *cache_elem = &cache_array[i];
- if (!STREQ(cache_elem->ob_name, ob->id.name) &&
+ if ((cache_elem->ob != ob) &&
(cache_elem->gpd == gpd))
{
return true;
@@ -73,6 +76,27 @@ static bool gpencil_check_datablock_duplicated(
return false;
}
+static int gpencil_len_datablock_duplicated(
+ tGPencilObjectCache *cache_array, int gp_cache_used,
+ Object *ob, bGPdata *gpd)
+{
+ int tot = 0;
+ if (gp_cache_used == 0) {
+ return 0;
+ }
+
+ for (int i = 0; i < gp_cache_used; i++) {
+ tGPencilObjectCache *cache_elem = &cache_array[i];
+ if ((cache_elem->ob != ob) &&
+ (cache_elem->gpd == gpd) &&
+ (!cache_elem->is_dup_ob))
+ {
+ tot++;
+ }
+ }
+ return tot;
+}
+
/* add a gpencil object to cache to defer drawing */
tGPencilObjectCache *gpencil_object_cache_add(
tGPencilObjectCache *cache_array, Object *ob,
@@ -101,22 +125,41 @@ tGPencilObjectCache *gpencil_object_cache_add(
cache_elem = &cache_array[*gp_cache_used];
memset(cache_elem, 0, sizeof(*cache_elem));
- cache_elem->is_dup_ob = gpencil_check_ob_duplicated(cache_array, *gp_cache_used, ob);
-
- STRNCPY(cache_elem->ob_name, ob->id.name);
- cache_elem->gpd = (bGPdata *)ob->data;
-
+ Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
+ cache_elem->ob = ob_orig;
+ cache_elem->gpd = (bGPdata *)ob_orig->data;
copy_v3_v3(cache_elem->loc, ob->loc);
copy_m4_m4(cache_elem->obmat, ob->obmat);
cache_elem->idx = *gp_cache_used;
- cache_elem->is_dup_onion = gpencil_check_datablock_duplicated(
- cache_array, *gp_cache_used,
- ob, cache_elem->gpd);
+ /* check if object is duplicated */
+ cache_elem->is_dup_ob = gpencil_check_ob_duplicated(cache_array,
+ *gp_cache_used, ob_orig,
+ &cache_elem->data_idx);
+
+ if (!cache_elem->is_dup_ob) {
+ /* check if object reuse datablock */
+ cache_elem->is_dup_data = gpencil_check_datablock_duplicated(
+ cache_array, *gp_cache_used,
+ ob_orig, cache_elem->gpd);
+ if (cache_elem->is_dup_data) {
+ cache_elem->data_idx = gpencil_len_datablock_duplicated(
+ cache_array, *gp_cache_used,
+ ob_orig, cache_elem->gpd);
+
+ cache_elem->gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
+ else {
+ cache_elem->data_idx = 0;
+ }
+ }
+ else {
+ cache_elem->is_dup_data = false;
+ }
/* save FXs */
cache_elem->pixfactor = cache_elem->gpd->pixfactor;
- cache_elem->shader_fx = ob->shader_fx;
+ cache_elem->shader_fx = ob_orig->shader_fx;
cache_elem->init_grp = 0;
cache_elem->end_grp = -1;
@@ -156,20 +199,13 @@ tGPencilObjectCache *gpencil_object_cache_add(
/* get current cache data */
static GpencilBatchCache *gpencil_batch_get_element(Object *ob)
{
- bGPdata *gpd = (bGPdata *)ob->data;
- if (gpd->runtime.batch_cache_data == NULL) {
- gpd->runtime.batch_cache_data = BLI_ghash_str_new("GP batch cache data");
- return NULL;
- }
-
- return (GpencilBatchCache *) BLI_ghash_lookup(gpd->runtime.batch_cache_data, ob->id.name);
+ Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
+ return ob_orig->runtime.gpencil_cache;
}
/* verify if cache is valid */
-static bool gpencil_batch_cache_valid(Object *ob, bGPdata *gpd, int cfra)
+static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra)
{
- GpencilBatchCache *cache = gpencil_batch_get_element(ob);
-
if (cache == NULL) {
return false;
}
@@ -218,10 +254,12 @@ void gpencil_batch_cache_check_free_slots(Object *ob)
}
/* cache init */
-static void gpencil_batch_cache_init(Object *ob, int cfra)
+static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
{
+ Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
+ bGPdata *gpd = (bGPdata *)ob_orig->data;
+
GpencilBatchCache *cache = gpencil_batch_get_element(ob);
- bGPdata *gpd = ob->data;
if (G.debug_value >= 664) {
printf("gpencil_batch_cache_init: %s\n", ob->id.name);
@@ -229,7 +267,7 @@ static void gpencil_batch_cache_init(Object *ob, int cfra)
if (!cache) {
cache = MEM_callocN(sizeof(*cache), __func__);
- BLI_ghash_insert(gpd->runtime.batch_cache_data, ob->id.name, cache);
+ ob_orig->runtime.gpencil_cache = cache;
}
else {
memset(cache, 0, sizeof(*cache));
@@ -247,6 +285,8 @@ static void gpencil_batch_cache_init(Object *ob, int cfra)
cache->cache_idx = 0;
cache->is_dirty = true;
cache->cache_frame = cfra;
+
+ return cache;
}
/* clear cache */
@@ -273,68 +313,54 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
MEM_SAFE_FREE(cache->batch_edlin);
}
- MEM_SAFE_FREE(cache);
+ cache->cache_size = 0;
}
/* get cache */
GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra)
{
- bGPdata *gpd = ob->data;
+ Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
+ bGPdata *gpd = (bGPdata *)ob_orig->data;
- if (!gpencil_batch_cache_valid(ob, gpd, cfra)) {
+ GpencilBatchCache *cache = gpencil_batch_get_element(ob);
+ if (!gpencil_batch_cache_valid(cache, gpd, cfra)) {
if (G.debug_value >= 664) {
printf("gpencil_batch_cache: %s\n", gpd->id.name);
}
- GpencilBatchCache *cache = gpencil_batch_get_element(ob);
if (cache) {
gpencil_batch_cache_clear(cache);
- BLI_ghash_remove(gpd->runtime.batch_cache_data, ob->id.name, NULL, NULL);
}
- gpencil_batch_cache_init(ob, cfra);
+ return gpencil_batch_cache_init(ob, cfra);
+ }
+ else {
+ return cache;
}
-
- return gpencil_batch_get_element(ob);
}
/* set cache as dirty */
void DRW_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
{
- if (gpd->runtime.batch_cache_data == NULL) {
- return;
- }
-
- GHashIterator *ihash = BLI_ghashIterator_new(gpd->runtime.batch_cache_data);
- while (!BLI_ghashIterator_done(ihash)) {
- GpencilBatchCache *cache = (GpencilBatchCache *)BLI_ghashIterator_getValue(ihash);
- if (cache) {
- cache->is_dirty = true;
- }
- BLI_ghashIterator_step(ihash);
- }
- BLI_ghashIterator_free(ihash);
+ bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id);
+ gpd_orig->flag |= GP_DATA_CACHE_IS_DIRTY;
}
/* free batch cache */
void DRW_gpencil_batch_cache_free(bGPdata *gpd)
{
- if (gpd->runtime.batch_cache_data == NULL) {
- return;
- }
+ return;
+}
- GHashIterator *ihash = BLI_ghashIterator_new(gpd->runtime.batch_cache_data);
- while (!BLI_ghashIterator_done(ihash)) {
- GpencilBatchCache *cache = (GpencilBatchCache *)BLI_ghashIterator_getValue(ihash);
- if (cache) {
- gpencil_batch_cache_clear(cache);
+/* wrapper to clear cache */
+void DRW_gpencil_freecache(struct Object *ob)
+{
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ gpencil_batch_cache_clear(ob->runtime.gpencil_cache);
+ MEM_SAFE_FREE(ob->runtime.gpencil_cache);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (gpd) {
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
}
- BLI_ghashIterator_step(ihash);
- }
- BLI_ghashIterator_free(ihash);
-
- /* free hash */
- if (gpd->runtime.batch_cache_data) {
- BLI_ghash_free(gpd->runtime.batch_cache_data, NULL, NULL);
- gpd->runtime.batch_cache_data = NULL;
}
}
+