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-08-15 17:07:16 +0300
committerAntonioya <blendergit@gmail.com>2018-08-15 21:27:59 +0300
commit8e8d93eb86109988db44730a0107e9da9e870328 (patch)
tree7a4e317f52de4e07d3261817e55a5444be1379f2 /source/blender/draw/engines/gpencil/gpencil_engine.c
parentbb84f7ff5f5268226b4d14e0f1e44a2579354b37 (diff)
GP: Redesign logic of drawing engine for object instance support
The initial design assumed that there was only one object for each unique name, but that was not the case when instances were created. Now, instances are supported and speed has been greatly improved when repetitions are used. As a result of this change, the option to create objects has been removed in the Instances modifier. This option was strange and was also against Blender's design rules, since a modifier should never create objects. The old functionality of the modifier can be achieved with instances. Also, several memory leakage problems that were not previously detected have been eliminated, and especially in the grid and in the drawing process Onion Skin is not supported in multi-user datablocks. Support this, makes incompatible with instances. We need find a solution in the long term, but now it's better keep disabled and make instances work. Anyway, the new instances makes unnecessary to use muli-user datablocks.
Diffstat (limited to 'source/blender/draw/engines/gpencil/gpencil_engine.c')
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c200
1 files changed, 112 insertions, 88 deletions
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 2a4f2f999bc..90ef6fedd58 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -273,6 +273,9 @@ static void GPENCIL_engine_free(void)
GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_fill);
MEM_SAFE_FREE(e_data.batch_buffer_fill);
+ GPU_BATCH_DISCARD_SAFE(e_data.batch_grid);
+ MEM_SAFE_FREE(e_data.batch_grid);
+
/* effects */
GPENCIL_delete_fx_shaders(&e_data);
}
@@ -333,9 +336,16 @@ void GPENCIL_cache_init(void *vedata)
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
/* detect if playing animation */
- stl->storage->is_playing = false;
if (draw_ctx->evil_C) {
- stl->storage->is_playing = ED_screen_animation_playing(CTX_wm_manager(draw_ctx->evil_C)) != NULL;
+ bool playing = ED_screen_animation_playing(CTX_wm_manager(draw_ctx->evil_C)) != NULL;
+ if (playing != stl->storage->is_playing) {
+ stl->storage->reset_cache = true;
+ }
+ stl->storage->is_playing = playing;
+ }
+ else {
+ stl->storage->is_playing = false;
+ stl->storage->reset_cache = false;
}
/* save render state */
stl->storage->is_render = DRW_state_is_image_render();
@@ -477,6 +487,56 @@ void GPENCIL_cache_init(void *vedata)
}
}
+static void gpencil_add_draw_data(void *vedata, Object *ob)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+
+ int i = stl->g_data->gp_cache_used - 1;
+ tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
+
+ if (cache_ob->is_dup_ob == false) {
+ /* save init shading group */
+ cache_ob->init_grp = stl->storage->shgroup_id;
+
+ /* fill shading groups */
+ if (!is_multiedit) {
+ DRW_gpencil_populate_datablock(&e_data, vedata, scene, ob, cache_ob);
+ }
+ else {
+ DRW_gpencil_populate_multiedit(&e_data, vedata, scene, ob, cache_ob);
+ }
+
+ /* save end shading group */
+ cache_ob->end_grp = stl->storage->shgroup_id - 1;
+ }
+ else {
+ /* save init shading group */
+ cache_ob->init_grp = stl->storage->shgroup_id;
+
+ DRW_gpencil_populate_datablock(&e_data, vedata, scene, ob,
+ cache_ob);
+
+ /* save end shading group */
+ cache_ob->end_grp = stl->storage->shgroup_id - 1;
+ }
+
+ /* FX passses */
+ cache_ob->has_fx = false;
+ if ((!stl->storage->simplify_fx) &&
+ (BKE_shaderfx_has_gpencil(ob)))
+ {
+ cache_ob->has_fx = true;
+ if ((!stl->storage->simplify_fx) && (!is_multiedit)) {
+ DRW_gpencil_fx_prepare(&e_data, vedata, cache_ob);
+ }
+ }
+
+}
+
void GPENCIL_cache_populate(void *vedata, Object *ob)
{
/* object must be visible */
@@ -489,31 +549,40 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
Scene *scene = draw_ctx->scene;
ToolSettings *ts = scene->toolsettings;
View3D *v3d = draw_ctx->v3d;
+ tGPencilObjectCache *cache_ob = NULL;
/* object datablock (this is not draw now) */
if (ob->type == OB_GPENCIL && ob->data) {
bGPdata *gpd = (bGPdata *)ob->data;
- if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) {
- /* if render set as dirty */
- if (stl->storage->is_render == true) {
- gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
+ /* when start/stop animation the cache must be set as dirty to reset all data */
+ if (stl->storage->reset_cache) {
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ stl->storage->reset_cache = false;
+ }
- /* allocate memory for saving gp objects for drawing later */
+ /* is edit mode only current object, not instances */
+ if ((draw_ctx->obact != ob) && GPENCIL_ANY_EDIT_MODE(gpd)) {
+ return;
+ }
+
+ if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) {
+
+ /* save gp objects for drawing later */
stl->g_data->gp_object_cache = gpencil_object_cache_add(
- stl->g_data->gp_object_cache, ob, false,
- &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used);
-
- /* generate instances as separate cache objects for instance modifiers
- * with the "Make as Objects" option enabled
- */
- if (!stl->storage->simplify_modif) {
- gpencil_instance_modifiers(stl, ob);
- }
+ stl->g_data->gp_object_cache, ob,
+ &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used);
+
+ cache_ob = &stl->g_data->gp_object_cache[stl->g_data->gp_cache_used - 1];
+
+ /* load drawing data */
+ gpencil_add_draw_data(vedata, ob);
}
+
/* draw current painting strokes */
- DRW_gpencil_populate_buffer_strokes(&e_data, vedata, ts, ob);
+ if (draw_ctx->obact == ob) {
+ DRW_gpencil_populate_buffer_strokes(&e_data, vedata, ts, ob);
+ }
/* grid */
if ((v3d) &&
@@ -521,57 +590,21 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
(v3d->gp_flag & V3D_GP_SHOW_GRID) &&
(ob->type == OB_GPENCIL) && (ob == draw_ctx->obact))
{
- stl->g_data->batch_grid = DRW_gpencil_get_grid();
+ GPU_BATCH_DISCARD_SAFE(e_data.batch_grid);
+ MEM_SAFE_FREE(e_data.batch_grid);
+
+ e_data.batch_grid = DRW_gpencil_get_grid();
DRW_shgroup_call_add(stl->g_data->shgrps_grid,
- stl->g_data->batch_grid,
- ob->obmat);
+ e_data.batch_grid,
+ ob->obmat);
}
}
}
-void GPENCIL_cache_finish(void *vedata)
+void GPENCIL_cache_finish(void *UNUSED(vedata))
{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- bool is_multiedit = false;
-
- /* if painting session, don't need to do more */
- if (stl->g_data->session_flag & GP_DRW_PAINT_PAINTING) {
- return;
- }
-
- /* Draw all pending objects */
- if (stl->g_data->gp_cache_used > 0) {
- for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
- Object *ob = stl->g_data->gp_object_cache[i].ob;
- bGPdata *gpd = ob->data;
-
- /* save init shading group */
- stl->g_data->gp_object_cache[i].init_grp = stl->storage->shgroup_id;
+ return;
- /* fill shading groups */
- is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- if (!is_multiedit) {
- DRW_gpencil_populate_datablock(&e_data, vedata, scene, ob, gpd);
- }
- else {
- DRW_gpencil_populate_multiedit(&e_data, vedata, scene, ob, gpd);
- }
-
- /* save end shading group */
- stl->g_data->gp_object_cache[i].end_grp = stl->storage->shgroup_id - 1;
- /* if render set to dirty to refresh viewport */
- if (stl->storage->is_render == true) {
- gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
- /* FX passses */
- tGPencilObjectCache *cache = &stl->g_data->gp_object_cache[i];
- if ((!stl->storage->simplify_fx) && (!is_multiedit)) {
- DRW_gpencil_fx_prepare(&e_data, vedata, cache);
- }
- }
- }
}
/* helper function to sort inverse gpencil objects using qsort */
@@ -605,21 +638,8 @@ static void gpencil_prepare_fast_drawing(
}
}
-static void gpencil_free_obj_list(GPENCIL_StorageList *stl)
+static void gpencil_free_obj_runtime(GPENCIL_StorageList *stl)
{
- /* Clear temp objects created for display instances only. These objects are created
- * while the draw manager draw the scene, but only to hold the strokes data.
- * see: gp_instance_modifier_make_instances()
- *
- * the normal objects are not freed because they are not tagged as temp objects
- */
- for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
- Object *ob = stl->g_data->gp_object_cache[i].ob;
- if (stl->g_data->gp_object_cache[i].temp_ob) {
- MEM_SAFE_FREE(ob);
- }
- }
-
/* free the cache itself */
MEM_SAFE_FREE(stl->g_data->gp_object_cache);
}
@@ -636,7 +656,7 @@ void GPENCIL_draw_scene(void *ved)
GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
int init_grp, end_grp;
- tGPencilObjectCache *cache;
+ tGPencilObjectCache *cache_ob;
const float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -667,7 +687,7 @@ void GPENCIL_draw_scene(void *ved)
MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, dfbl->default_fb, txl);
/* free memory */
- gpencil_free_obj_list(stl);
+ gpencil_free_obj_runtime(stl);
/* grid pass */
if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) {
@@ -699,11 +719,11 @@ void GPENCIL_draw_scene(void *ved)
sizeof(tGPencilObjectCache), gpencil_object_cache_compare_zdepth);
for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
- cache = &stl->g_data->gp_object_cache[i];
- Object *ob = cache->ob;
- bGPdata *gpd = ob->data;
- init_grp = cache->init_grp;
- end_grp = cache->end_grp;
+ cache_ob = &stl->g_data->gp_object_cache[i];
+ bGPdata *gpd = cache_ob->gpd;
+ init_grp = cache_ob->init_grp;
+ end_grp = cache_ob->end_grp;
+
/* Render stroke in separated framebuffer */
GPU_framebuffer_bind(fbl->temp_fb_a);
GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
@@ -724,15 +744,15 @@ void GPENCIL_draw_scene(void *ved)
}
/* Current buffer drawing */
- if ((!is_render) && (gpd->runtime.sbuffer_size > 0)) {
+ if ((!is_render) && (cache_ob->is_dup_ob == false))
+ {
DRW_draw_pass(psl->drawing_pass);
}
/* fx passes */
- if ((!stl->storage->simplify_fx) &&
- (BKE_shaderfx_has_gpencil(ob)))
+ if (cache_ob->has_fx == true)
{
stl->storage->tonemapping = 0;
- DRW_gpencil_fx_draw(&e_data, vedata, cache);
+ DRW_gpencil_fx_draw(&e_data, vedata, cache_ob);
}
e_data.input_depth_tx = e_data.temp_depth_tx_a;
@@ -754,6 +774,10 @@ void GPENCIL_draw_scene(void *ved)
if (!is_render) {
gpencil_prepare_fast_drawing(stl, dfbl, fbl, psl->mix_pass_noblend, clearcol);
}
+ else {
+ /* if render, the cache must be dirty for next loop */
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
}
/* edit points */
if ((!is_render) && (!playing)) {
@@ -770,7 +794,7 @@ void GPENCIL_draw_scene(void *ved)
}
}
/* free memory */
- gpencil_free_obj_list(stl);
+ gpencil_free_obj_runtime(stl);
/* detach temp textures */
if (DRW_state_is_fbo()) {