GP: Refactor drawing engine to single VBO
[blender.git] / source / blender / draw / engines / gpencil / gpencil_cache_utils.c
1 /*
2  * Copyright 2017, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Antonio Vazquez
19  *
20  */
21
22 /** \file blender/draw/engines/gpencil/gpencil_cache_utils.c
23  *  \ingroup draw
24  */
25
26 #include "DRW_engine.h"
27 #include "DRW_render.h"
28
29 #include "ED_gpencil.h"
30 #include "ED_view3d.h"
31
32 #include "DNA_gpencil_types.h"
33 #include "DNA_view3d_types.h"
34
35 #include "BKE_gpencil.h"
36
37 #include "gpencil_engine.h"
38
39 #include "draw_cache_impl.h"
40
41 #include "DEG_depsgraph.h"
42 #include "DEG_depsgraph_query.h"
43
44  /* add a gpencil object to cache to defer drawing */
45 tGPencilObjectCache *gpencil_object_cache_add(
46         tGPencilObjectCache *cache_array, Object *ob,
47         int *gp_cache_size, int *gp_cache_used)
48 {
49         const DRWContextState *draw_ctx = DRW_context_state_get();
50         tGPencilObjectCache *cache_elem = NULL;
51         RegionView3D *rv3d = draw_ctx->rv3d;
52         tGPencilObjectCache *p = NULL;
53
54         /* By default a cache is created with one block with a predefined number of free slots,
55         if the size is not enough, the cache is reallocated adding a new block of free slots.
56         This is done in order to keep cache small */
57         if (*gp_cache_used + 1 > *gp_cache_size) {
58                 if ((*gp_cache_size == 0) || (cache_array == NULL)) {
59                         p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE, "tGPencilObjectCache");
60                         *gp_cache_size = GP_CACHE_BLOCK_SIZE;
61                 }
62                 else {
63                         *gp_cache_size += GP_CACHE_BLOCK_SIZE;
64                         p = MEM_recallocN(cache_array, sizeof(struct tGPencilObjectCache) * *gp_cache_size);
65                 }
66                 cache_array = p;
67         }
68         /* zero out all pointers */
69         cache_elem = &cache_array[*gp_cache_used];
70         memset(cache_elem, 0, sizeof(*cache_elem));
71
72         Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
73         cache_elem->ob = ob_orig;
74         cache_elem->gpd = (bGPdata *)ob_orig->data;
75         copy_v3_v3(cache_elem->loc, ob->loc);
76         copy_m4_m4(cache_elem->obmat, ob->obmat);
77         cache_elem->idx = *gp_cache_used;
78
79         /* object is duplicated (particle) */
80         cache_elem->is_dup_ob = ob->base_flag & BASE_FROMDUPLI;
81
82         /* save FXs */
83         cache_elem->pixfactor = cache_elem->gpd->pixfactor;
84         cache_elem->shader_fx = ob_orig->shader_fx;
85
86         cache_elem->init_grp = NULL;
87         cache_elem->end_grp = NULL;
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->loc, NULL);
94                 }
95                 else {
96                         zdepth = -dot_v3v3(rv3d->viewinv[2], ob->loc);
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->loc, 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         Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
167         return ob_orig->runtime.gpencil_cache;
168 }
169
170 /* verify if cache is valid */
171 static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra)
172 {
173         bool valid = true;
174         if (cache == NULL) {
175                 return false;
176         }
177
178         cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
179         if (cfra != cache->cache_frame) {
180                 valid = false;
181         }
182         else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) {
183                 valid = false;
184         }
185         else if (gpd->flag & GP_DATA_SHOW_ONIONSKINS) {
186                 /* if onion, set as dirty always
187                  * This reduces performance, but avoid any crash in the multiple
188                  * overlay and multiwindow options and keep all windows working
189                  */
190                 valid = false;
191         }
192         else if (cache->is_editmode) {
193                 valid = false;
194         }
195         else if (cache->is_dirty) {
196                 valid = false;
197         }
198
199         return valid;
200 }
201
202 /* cache init */
203 static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
204 {
205         Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
206         bGPdata *gpd = (bGPdata *)ob_orig->data;
207
208         GpencilBatchCache *cache = gpencil_batch_get_element(ob);
209
210         if (!cache) {
211                 cache = MEM_callocN(sizeof(*cache), __func__);
212                 ob_orig->runtime.gpencil_cache = cache;
213         }
214         else {
215                 memset(cache, 0, sizeof(*cache));
216         }
217
218         cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
219
220         cache->is_dirty = true;
221
222         cache->cache_frame = cfra;
223
224         /* create array of derived frames equal to number of layers */
225         cache->tot_layers = BLI_listbase_count(&gpd->layers);
226         CLAMP_MIN(cache->tot_layers, 1);
227         cache->derived_array = MEM_callocN(sizeof(struct bGPDframe) * cache->tot_layers, "Derived GPF");
228
229         return cache;
230 }
231
232 /* clear cache */
233 static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
234 {
235         if (!cache) {
236                 return;
237         }
238
239         GPU_BATCH_DISCARD_SAFE(cache->b_stroke.batch);
240         GPU_BATCH_DISCARD_SAFE(cache->b_point.batch);
241         GPU_BATCH_DISCARD_SAFE(cache->b_fill.batch);
242         GPU_BATCH_DISCARD_SAFE(cache->b_edit.batch);
243         GPU_BATCH_DISCARD_SAFE(cache->b_edlin.batch);
244
245         MEM_SAFE_FREE(cache->b_stroke.batch);
246         MEM_SAFE_FREE(cache->b_point.batch);
247         MEM_SAFE_FREE(cache->b_fill.batch);
248         MEM_SAFE_FREE(cache->b_edit.batch);
249         MEM_SAFE_FREE(cache->b_edlin.batch);
250
251         MEM_SAFE_FREE(cache->grp_cache);
252         cache->grp_size = 0;
253         cache->grp_used = 0;
254
255         /* clear all frames derived data */
256         for (int i = 0; i < cache->tot_layers; i++) {
257                 bGPDframe *derived_gpf = &cache->derived_array[i];
258                 BKE_gpencil_free_frame_runtime_data(derived_gpf);
259                 derived_gpf = NULL;
260         }
261         cache->tot_layers = 0;
262         MEM_SAFE_FREE(cache->derived_array);
263 }
264
265 /* get cache */
266 GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra)
267 {
268         Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
269         bGPdata *gpd = (bGPdata *)ob_orig->data;
270
271         GpencilBatchCache *cache = gpencil_batch_get_element(ob);
272         if (!gpencil_batch_cache_valid(cache, gpd, cfra)) {
273                 if (cache) {
274                         gpencil_batch_cache_clear(cache);
275                 }
276                 return gpencil_batch_cache_init(ob, cfra);
277         }
278         else {
279                 return cache;
280         }
281 }
282
283 /* set cache as dirty */
284 void DRW_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
285 {
286         bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id);
287         gpd_orig->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 }