Merge remote-tracking branch 'origin/master' into blender2.8
[blender.git] / source / blender / draw / intern / draw_cache_impl_metaball.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
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  * The Original Code is Copyright (C) 2017 by Blender Foundation.
19  * All rights reserved.
20  *
21  * ***** END GPL LICENSE BLOCK *****
22  */
23
24 /** \file draw_cache_impl_metaball.c
25  *  \ingroup draw
26  *
27  * \brief MetaBall API for render engines
28  */
29
30 #include "MEM_guardedalloc.h"
31
32 #include "BLI_utildefines.h"
33
34 #include "DNA_meta_types.h"
35 #include "DNA_object_types.h"
36
37 #include "BKE_curve.h"
38 #include "BKE_mball.h"
39
40 #include "GPU_batch.h"
41
42 #include "draw_cache_impl.h"  /* own include */
43
44
45 static void metaball_batch_cache_clear(MetaBall *mb);
46
47 /* ---------------------------------------------------------------------- */
48 /* MetaBall GPUBatch Cache */
49
50 typedef struct MetaBallBatchCache {
51         GPUBatch *batch;
52         GPUBatch **shaded_triangles;
53
54         int mat_len;
55         /* settings to determine if cache is invalid */
56         bool is_dirty;
57 } MetaBallBatchCache;
58
59 /* GPUBatch cache management. */
60
61 static bool metaball_batch_cache_valid(MetaBall *mb)
62 {
63         MetaBallBatchCache *cache = mb->batch_cache;
64
65         if (cache == NULL) {
66                 return false;
67         }
68
69         return cache->is_dirty == false;
70 }
71
72 static void metaball_batch_cache_init(MetaBall *mb)
73 {
74         MetaBallBatchCache *cache = mb->batch_cache;
75
76         if (!cache) {
77                 cache = mb->batch_cache = MEM_mallocN(sizeof(*cache), __func__);
78         }
79         cache->batch = NULL;
80         cache->mat_len = 0;
81         cache->shaded_triangles = NULL;
82         cache->is_dirty = false;
83 }
84
85 static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb)
86 {
87         if (!metaball_batch_cache_valid(mb)) {
88                 metaball_batch_cache_clear(mb);
89                 metaball_batch_cache_init(mb);
90         }
91         return mb->batch_cache;
92 }
93
94 void DRW_mball_batch_cache_dirty_tag(MetaBall *mb, int mode)
95 {
96         MetaBallBatchCache *cache = mb->batch_cache;
97         if (cache == NULL) {
98                 return;
99         }
100         switch (mode) {
101                 case BKE_MBALL_BATCH_DIRTY_ALL:
102                         cache->is_dirty = true;
103                         break;
104                 default:
105                         BLI_assert(0);
106         }
107 }
108
109 static void metaball_batch_cache_clear(MetaBall *mb)
110 {
111         MetaBallBatchCache *cache = mb->batch_cache;
112         if (!cache) {
113                 return;
114         }
115
116         GPU_BATCH_DISCARD_SAFE(cache->batch);
117         /* Note: shaded_triangles[0] is already freed by cache->batch */
118         MEM_SAFE_FREE(cache->shaded_triangles);
119         cache->mat_len = 0;
120 }
121
122 void DRW_mball_batch_cache_free(MetaBall *mb)
123 {
124         metaball_batch_cache_clear(mb);
125         MEM_SAFE_FREE(mb->batch_cache);
126 }
127
128 /* -------------------------------------------------------------------- */
129
130 /** \name Public Object/MetaBall API
131  * \{ */
132
133 GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
134 {
135         if (!BKE_mball_is_basis(ob)) {
136                 return NULL;
137         }
138
139         MetaBall *mb = ob->data;
140         MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
141
142         if (cache->batch == NULL) {
143                 ListBase *lb = &ob->runtime.curve_cache->disp;
144                 cache->batch = GPU_batch_create_ex(
145                         GPU_PRIM_TRIS,
146                         DRW_displist_vertbuf_calc_pos_with_normals(lb),
147                         DRW_displist_indexbuf_calc_triangles_in_order(lb),
148                         GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
149         }
150
151         return cache->batch;
152 }
153
154 GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb, struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len)
155 {
156         if (!BKE_mball_is_basis(ob)) {
157                 return NULL;
158         }
159
160         MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
161         if (cache->shaded_triangles == NULL) {
162                 cache->mat_len = gpumat_array_len;
163                 cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * cache->mat_len, __func__);
164                 cache->shaded_triangles[0] = DRW_metaball_batch_cache_get_triangles_with_normals(ob);
165                 for (int i = 1; i < cache->mat_len; ++i) {
166                         cache->shaded_triangles[i] = NULL;
167                 }
168         }
169         return cache->shaded_triangles;
170
171 }