doxygen: add newline after \file
[blender.git] / source / blender / draw / engines / gpencil / gpencil_cache_utils.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2017, Blender Foundation.
17  */
18
19 /** \file
20  * \ingroup draw
21  */
22
23 #include "DRW_engine.h"
24 #include "DRW_render.h"
25
26 #include "ED_gpencil.h"
27 #include "ED_view3d.h"
28
29 #include "DNA_gpencil_types.h"
30 #include "DNA_view3d_types.h"
31
32 #include "BKE_gpencil.h"
33
34 #include "gpencil_engine.h"
35
36 #include "draw_cache_impl.h"
37
38 #include "DEG_depsgraph.h"
39
40  /* add a gpencil object to cache to defer drawing */
41 tGPencilObjectCache *gpencil_object_cache_add(
42         tGPencilObjectCache *cache_array, Object *ob,
43         int *gp_cache_size, int *gp_cache_used)
44 {
45         const DRWContextState *draw_ctx = DRW_context_state_get();
46         tGPencilObjectCache *cache_elem = NULL;
47         RegionView3D *rv3d = draw_ctx->rv3d;
48         tGPencilObjectCache *p = NULL;
49
50         /* By default a cache is created with one block with a predefined number of free slots,
51         if the size is not enough, the cache is reallocated adding a new block of free slots.
52         This is done in order to keep cache small */
53         if (*gp_cache_used + 1 > *gp_cache_size) {
54                 if ((*gp_cache_size == 0) || (cache_array == NULL)) {
55                         p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE, "tGPencilObjectCache");
56                         *gp_cache_size = GP_CACHE_BLOCK_SIZE;
57                 }
58                 else {
59                         *gp_cache_size += GP_CACHE_BLOCK_SIZE;
60                         p = MEM_recallocN(cache_array, sizeof(struct tGPencilObjectCache) * *gp_cache_size);
61                 }
62                 cache_array = p;
63         }
64         /* zero out all pointers */
65         cache_elem = &cache_array[*gp_cache_used];
66         memset(cache_elem, 0, sizeof(*cache_elem));
67
68         cache_elem->ob = ob;
69         cache_elem->gpd = (bGPdata *)ob->data;
70         copy_v3_v3(cache_elem->loc, ob->obmat[3]);
71         copy_m4_m4(cache_elem->obmat, ob->obmat);
72         cache_elem->idx = *gp_cache_used;
73
74         /* object is duplicated (particle) */
75         cache_elem->is_dup_ob = ob->base_flag & BASE_FROM_DUPLI;
76         cache_elem->scale = mat4_to_scale(ob->obmat);
77
78         /* save FXs */
79         cache_elem->pixfactor = cache_elem->gpd->pixfactor;
80         cache_elem->shader_fx = ob->shader_fx;
81
82         /* shgrp array */
83         cache_elem->tot_layers = 0;
84         int totgpl = BLI_listbase_count(&cache_elem->gpd->layers);
85         if (totgpl > 0) {
86                 cache_elem->shgrp_array = MEM_callocN(sizeof(tGPencilObjectCache_shgrp) * totgpl, __func__);
87         }
88
89         /* calculate zdepth from point of view */
90         float zdepth = 0.0;
91         if (rv3d) {
92                 if (rv3d->is_persp) {
93                         zdepth = ED_view3d_calc_zfac(rv3d, ob->obmat[3], NULL);
94                 }
95                 else {
96                         zdepth = -dot_v3v3(rv3d->viewinv[2], ob->obmat[3]);
97                 }
98         }
99         else {
100                 /* In render mode, rv3d is not available, so use the distance to camera.
101                  * The real distance is not important, but the relative distance to the camera plane
102                  * in order to sort by z_depth of the objects
103                  */
104                 float vn[3] = { 0.0f, 0.0f, -1.0f }; /* always face down */
105                 float plane_cam[4];
106                 struct Object *camera = draw_ctx->scene->camera;
107                 if (camera) {
108                         mul_m4_v3(camera->obmat, vn);
109                         normalize_v3(vn);
110                         plane_from_point_normal_v3(plane_cam, camera->loc, vn);
111                         zdepth = dist_squared_to_plane_v3(ob->obmat[3], plane_cam);
112                 }
113         }
114         cache_elem->zdepth = zdepth;
115         /* increase slots used in cache */
116         (*gp_cache_used)++;
117
118         return cache_array;
119 }
120
121 /* add a shading group to the cache to create later */
122 GpencilBatchGroup *gpencil_group_cache_add(
123         GpencilBatchGroup *cache_array,
124         bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
125         const short type, const bool onion,
126         const int vertex_idx,
127         int *grp_size, int *grp_used)
128 {
129         GpencilBatchGroup *cache_elem = NULL;
130         GpencilBatchGroup *p = NULL;
131
132         /* By default a cache is created with one block with a predefined number of free slots,
133         if the size is not enough, the cache is reallocated adding a new block of free slots.
134         This is done in order to keep cache small */
135         if (*grp_used + 1 > *grp_size) {
136                 if ((*grp_size == 0) || (cache_array == NULL)) {
137                         p = MEM_callocN(sizeof(struct GpencilBatchGroup) * GPENCIL_GROUPS_BLOCK_SIZE, "GpencilBatchGroup");
138                         *grp_size = GPENCIL_GROUPS_BLOCK_SIZE;
139                 }
140                 else {
141                         *grp_size += GPENCIL_GROUPS_BLOCK_SIZE;
142                         p = MEM_recallocN(cache_array, sizeof(struct GpencilBatchGroup) * *grp_size);
143                 }
144                 cache_array = p;
145         }
146         /* zero out all data */
147         cache_elem = &cache_array[*grp_used];
148         memset(cache_elem, 0, sizeof(*cache_elem));
149
150         cache_elem->gpl = gpl;
151         cache_elem->gpf = gpf;
152         cache_elem->gps = gps;
153         cache_elem->type = type;
154         cache_elem->onion = onion;
155         cache_elem->vertex_idx = vertex_idx;
156
157         /* increase slots used in cache */
158         (*grp_used)++;
159
160         return cache_array;
161 }
162
163 /* get current cache data */
164 static GpencilBatchCache *gpencil_batch_get_element(Object *ob)
165 {
166         return ob->runtime.gpencil_cache;
167 }
168
169 /* verify if cache is valid */
170 static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra)
171 {
172         bool valid = true;
173         if (cache == NULL) {
174                 return false;
175         }
176
177         cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
178         if (cfra != cache->cache_frame) {
179                 valid = false;
180         }
181         else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) {
182                 valid = false;
183         }
184         else if (gpd->flag & GP_DATA_PYTHON_UPDATED) {
185                 gpd->flag &= ~GP_DATA_PYTHON_UPDATED;
186                 valid = false;
187         }
188         else if (DRW_gpencil_onion_active(gpd)) {
189                 /* if onion, set as dirty always
190                  * This reduces performance, but avoid any crash in the multiple
191                  * overlay and multiwindow options and keep all windows working
192                  */
193                 valid = false;
194         }
195         else if (cache->is_editmode) {
196                 valid = false;
197         }
198         else if (cache->is_dirty) {
199                 valid = false;
200         }
201
202         return valid;
203 }
204
205 /* cache init */
206 static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
207 {
208         bGPdata *gpd = (bGPdata *)ob->data;
209
210         GpencilBatchCache *cache = gpencil_batch_get_element(ob);
211
212         if (!cache) {
213                 cache = MEM_callocN(sizeof(*cache), __func__);
214                 ob->runtime.gpencil_cache = cache;
215         }
216         else {
217                 memset(cache, 0, sizeof(*cache));
218         }
219
220         cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
221
222         cache->is_dirty = true;
223
224         cache->cache_frame = cfra;
225
226         /* create array of derived frames equal to number of layers */
227         cache->tot_layers = BLI_listbase_count(&gpd->layers);
228         CLAMP_MIN(cache->tot_layers, 1);
229         cache->derived_array = MEM_callocN(sizeof(struct bGPDframe) * cache->tot_layers, "Derived GPF");
230
231         return cache;
232 }
233
234 /* clear cache */
235 static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
236 {
237         if (!cache) {
238                 return;
239         }
240
241         GPU_BATCH_DISCARD_SAFE(cache->b_stroke.batch);
242         GPU_BATCH_DISCARD_SAFE(cache->b_point.batch);
243         GPU_BATCH_DISCARD_SAFE(cache->b_fill.batch);
244         GPU_BATCH_DISCARD_SAFE(cache->b_edit.batch);
245         GPU_BATCH_DISCARD_SAFE(cache->b_edlin.batch);
246
247         MEM_SAFE_FREE(cache->b_stroke.batch);
248         MEM_SAFE_FREE(cache->b_point.batch);
249         MEM_SAFE_FREE(cache->b_fill.batch);
250         MEM_SAFE_FREE(cache->b_edit.batch);
251         MEM_SAFE_FREE(cache->b_edlin.batch);
252
253         MEM_SAFE_FREE(cache->grp_cache);
254         cache->grp_size = 0;
255         cache->grp_used = 0;
256
257         /* clear all frames derived data */
258         for (int i = 0; i < cache->tot_layers; i++) {
259                 bGPDframe *derived_gpf = &cache->derived_array[i];
260                 BKE_gpencil_free_frame_runtime_data(derived_gpf);
261                 derived_gpf = NULL;
262         }
263         cache->tot_layers = 0;
264         MEM_SAFE_FREE(cache->derived_array);
265 }
266
267 /* get cache */
268 GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra)
269 {
270         bGPdata *gpd = (bGPdata *)ob->data;
271
272         GpencilBatchCache *cache = gpencil_batch_get_element(ob);
273         if (!gpencil_batch_cache_valid(cache, gpd, cfra)) {
274                 if (cache) {
275                         gpencil_batch_cache_clear(cache);
276                 }
277                 return gpencil_batch_cache_init(ob, cfra);
278         }
279         else {
280                 return cache;
281         }
282 }
283
284 /* set cache as dirty */
285 void DRW_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
286 {
287         gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
288 }
289
290 /* free batch cache */
291 void DRW_gpencil_batch_cache_free(bGPdata *UNUSED(gpd))
292 {
293         return;
294 }
295
296 /* wrapper to clear cache */
297 void DRW_gpencil_freecache(struct Object *ob)
298 {
299         if ((ob) && (ob->type == OB_GPENCIL)) {
300                 gpencil_batch_cache_clear(ob->runtime.gpencil_cache);
301                 MEM_SAFE_FREE(ob->runtime.gpencil_cache);
302                 bGPdata *gpd = (bGPdata *)ob->data;
303                 if (gpd) {
304                         gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
305                 }
306         }
307 }