Merge branch 'master' into blender2.8
[blender.git] / source / blender / gpu / intern / gpu_buffers.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) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_buffers.c
29  *  \ingroup gpu
30  *
31  * Mesh drawing using OpenGL VBO (Vertex Buffer Objects)
32  */
33
34 #include <limits.h>
35 #include <stddef.h>
36 #include <string.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_bitmap.h"
41 #include "BLI_math.h"
42 #include "BLI_utildefines.h"
43 #include "BLI_ghash.h"
44 #include "BLI_threads.h"
45
46 #include "DNA_meshdata_types.h"
47
48 #include "BKE_ccg.h"
49 #include "BKE_DerivedMesh.h"
50 #include "BKE_paint.h"
51 #include "BKE_mesh.h"
52 #include "BKE_pbvh.h"
53
54 #include "GPU_buffers.h"
55 #include "GPU_draw.h"
56 #include "GPU_immediate.h"
57 #include "GPU_batch.h"
58
59 #include "bmesh.h"
60
61 static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
62
63 /* multires global buffer, can be used for many grids having the same grid size */
64 typedef struct GridCommonGPUBuffer {
65         Gwn_IndexBuf *mres_buffer;
66         int mres_prev_gridsize;
67         unsigned mres_prev_totquad;
68 } GridCommonGPUBuffer;
69
70 /* XXX: the rest of the code in this file is used for optimized PBVH
71  * drawing and doesn't interact at all with the buffer code above */
72
73 struct GPU_PBVH_Buffers {
74         Gwn_IndexBuf *index_buf, *index_buf_fast;
75         Gwn_VertBuf *vert_buf;
76
77         Gwn_Batch *triangles;
78         Gwn_Batch *triangles_fast;
79
80         /* mesh pointers in case buffer allocation fails */
81         const MPoly *mpoly;
82         const MLoop *mloop;
83         const MLoopTri *looptri;
84         const MVert *mvert;
85
86         const int *face_indices;
87         int        face_indices_len;
88         const float *vmask;
89
90         /* grid pointers */
91         CCGKey gridkey;
92         CCGElem **grids;
93         const DMFlagMat *grid_flag_mats;
94         BLI_bitmap * const *grid_hidden;
95         const int *grid_indices;
96         int totgrid;
97         bool has_hidden;
98         bool is_index_buf_global;  /* Means index_buf uses global bvh's grid_common_gpu_buffer, **DO NOT** free it! */
99
100         bool use_bmesh;
101
102         unsigned int tot_tri, tot_quad;
103
104         /* The PBVH ensures that either all faces in the node are
105          * smooth-shaded or all faces are flat-shaded */
106         bool smooth;
107
108         bool show_diffuse_color;
109         bool show_mask;
110
111         float diffuse_color[4];
112 };
113
114 static struct {
115         uint pos, nor, col;
116 } g_vbo_id = {0};
117
118 static void gpu_material_diffuse_get(int UNUSED(nr), float diff[4])
119 {
120         /* TODO: sculpt diffuse color option not supported in 2.8 yet. */
121         diff[0] = 0.8f;
122         diff[1] = 0.8f;
123         diff[2] = 0.8f;
124         diff[3] = 1.0f;
125 }
126
127 /* Allocates a non-initialized buffer to be sent to GPU.
128  * Return is false it indicates that the memory map failed. */
129 static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, unsigned int vert_ct)
130 {
131         if (buffers->vert_buf == NULL) {
132                 /* Initialize vertex buffer */
133                 /* match 'VertexBufferFormat' */
134
135                 static Gwn_VertFormat format = {0};
136                 if (format.attrib_ct == 0) {
137                         g_vbo_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
138                         g_vbo_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
139                         g_vbo_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
140                 }
141 #if 0
142                 buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_DYNAMIC);
143                 GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct);
144         }
145         else if (vert_ct != buffers->vert_buf->vertex_ct) {
146                 GWN_vertbuf_data_resize(buffers->vert_buf, vert_ct);
147         }
148 #else
149                 buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC);
150         }
151         GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct);
152 #endif
153         return buffers->vert_buf->data != NULL;
154 }
155
156 static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers)
157 {
158         /* force flushing to the GPU */
159         if (buffers->vert_buf->data) {
160                 GWN_vertbuf_use(buffers->vert_buf);
161         }
162
163         if (buffers->triangles == NULL) {
164                 buffers->triangles = GWN_batch_create(
165                         GWN_PRIM_TRIS, buffers->vert_buf,
166                         /* can be NULL */
167                         buffers->index_buf);
168         }
169
170         if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) {
171                 buffers->triangles_fast = GWN_batch_create(
172                         GWN_PRIM_TRIS, buffers->vert_buf,
173                         /* can be NULL */
174                         buffers->index_buf_fast);
175         }
176 }
177
178 static float gpu_color_from_mask(float mask)
179 {
180         return 1.0f - mask * 0.75f;
181 }
182
183 static void gpu_color_from_mask_copy(float mask, const float diffuse_color[4], unsigned char out[3])
184 {
185         float mask_color;
186
187         mask_color = gpu_color_from_mask(mask) * 255.0f;
188
189         out[0] = diffuse_color[0] * mask_color;
190         out[1] = diffuse_color[1] * mask_color;
191         out[2] = diffuse_color[2] * mask_color;
192 }
193
194 static void gpu_color_from_mask_quad_copy(const CCGKey *key,
195                                           CCGElem *a, CCGElem *b,
196                                           CCGElem *c, CCGElem *d,
197                                           const float *diffuse_color,
198                                           unsigned char out[3])
199 {
200         float mask_color =
201             gpu_color_from_mask((*CCG_elem_mask(key, a) +
202                                  *CCG_elem_mask(key, b) +
203                                  *CCG_elem_mask(key, c) +
204                                  *CCG_elem_mask(key, d)) * 0.25f) * 255.0f;
205
206         out[0] = diffuse_color[0] * mask_color;
207         out[1] = diffuse_color[1] * mask_color;
208         out[2] = diffuse_color[2] * mask_color;
209 }
210
211 void GPU_pbvh_mesh_buffers_update(
212         GPU_PBVH_Buffers *buffers, const MVert *mvert,
213         const int *vert_indices, int totvert, const float *vmask,
214         const int (*face_vert_indices)[3],
215         const int update_flags)
216 {
217         const bool show_diffuse_color = (update_flags & GPU_PBVH_BUFFERS_SHOW_DIFFUSE_COLOR) != 0;
218         const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
219
220         buffers->vmask = vmask;
221         buffers->show_diffuse_color = show_diffuse_color;
222         buffers->show_mask = show_mask;
223
224         {
225                 int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3));
226                 float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 0.8f};
227
228                 if (show_diffuse_color) {
229                         const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
230                         const MPoly *mp = &buffers->mpoly[lt->poly];
231
232                         gpu_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
233                 }
234
235                 copy_v4_v4(buffers->diffuse_color, diffuse_color);
236
237                 uchar diffuse_color_ub[4];
238                 rgba_float_to_uchar(diffuse_color_ub, diffuse_color);
239
240                 /* Build VBO */
241                 if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) {
242                         /* Vertex data is shared if smooth-shaded, but separate
243                          * copies are made for flat shading because normals
244                          * shouldn't be shared. */
245                         if (buffers->smooth) {
246                                 for (uint i = 0; i < totvert; ++i) {
247                                         const MVert *v = &mvert[vert_indices[i]];
248                                         GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, i, v->co);
249                                         GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, i, v->no);
250                                 }
251
252                                 for (uint i = 0; i < buffers->face_indices_len; i++) {
253                                         const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
254                                         for (uint j = 0; j < 3; j++) {
255                                                 int vidx = face_vert_indices[i][j];
256                                                 if (vmask && show_mask) {
257                                                         int v_index = buffers->mloop[lt->tri[j]].v;
258                                                         uchar color_ub[3];
259                                                         gpu_color_from_mask_copy(vmask[v_index], diffuse_color, color_ub);
260                                                         GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, color_ub);
261                                                 }
262                                                 else {
263                                                         GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, diffuse_color_ub);
264                                                 }
265                                         }
266                                 }
267                         }
268                         else {
269                                 /* calculate normal for each polygon only once */
270                                 unsigned int mpoly_prev = UINT_MAX;
271                                 short no[3];
272                                 int vbo_index = 0;
273
274                                 for (uint i = 0; i < buffers->face_indices_len; i++) {
275                                         const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
276                                         const unsigned int vtri[3] = {
277                                             buffers->mloop[lt->tri[0]].v,
278                                             buffers->mloop[lt->tri[1]].v,
279                                             buffers->mloop[lt->tri[2]].v,
280                                         };
281
282                                         if (paint_is_face_hidden(lt, mvert, buffers->mloop))
283                                                 continue;
284
285                                         /* Face normal and mask */
286                                         if (lt->poly != mpoly_prev) {
287                                                 const MPoly *mp = &buffers->mpoly[lt->poly];
288                                                 float fno[3];
289                                                 BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno);
290                                                 normal_float_to_short_v3(no, fno);
291                                                 mpoly_prev = lt->poly;
292                                         }
293
294                                         uchar color_ub[3];
295                                         if (vmask && show_mask) {
296                                                 float fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f;
297                                                 gpu_color_from_mask_copy(fmask, diffuse_color, color_ub);
298                                         }
299                                         else {
300                                                 copy_v3_v3_uchar(color_ub, diffuse_color_ub);
301                                         }
302
303                                         for (uint j = 0; j < 3; j++) {
304                                                 const MVert *v = &mvert[vtri[j]];
305
306                                                 GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, v->co);
307                                                 GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no);
308                                                 GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
309
310                                                 vbo_index++;
311                                         }
312                                 }
313                         }
314
315                         gpu_pbvh_batch_init(buffers);
316                 }
317         }
318
319         buffers->mvert = mvert;
320 }
321
322 GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(
323         const int (*face_vert_indices)[3],
324         const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri,
325         const MVert *mvert,
326         const int *face_indices,
327         const int  face_indices_len)
328 {
329         GPU_PBVH_Buffers *buffers;
330         int i, tottri;
331
332         buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
333
334         /* smooth or flat for all */
335 #if 0
336         buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH;
337 #else
338         /* for DrawManager we dont support mixed smooth/flat */
339         buffers->smooth = (mpoly[0].flag & ME_SMOOTH) != 0;
340 #endif
341
342         buffers->show_diffuse_color = false;
343         buffers->show_mask = true;
344
345         /* Count the number of visible triangles */
346         for (i = 0, tottri = 0; i < face_indices_len; ++i) {
347                 const MLoopTri *lt = &looptri[face_indices[i]];
348                 if (!paint_is_face_hidden(lt, mvert, mloop))
349                         tottri++;
350         }
351
352         if (tottri == 0) {
353                 buffers->tot_tri = 0;
354
355                 buffers->mpoly = mpoly;
356                 buffers->mloop = mloop;
357                 buffers->looptri = looptri;
358                 buffers->face_indices = face_indices;
359                 buffers->face_indices_len = 0;
360
361                 return buffers;
362         }
363
364         /* An element index buffer is used for smooth shading, but flat
365          * shading requires separate vertex normals so an index buffer is
366          * can't be used there. */
367         if (buffers->smooth) {
368                 /* Fill the triangle buffer */
369                 buffers->index_buf = NULL;
370                 Gwn_IndexBufBuilder elb;
371                 GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, INT_MAX);
372
373                 for (i = 0; i < face_indices_len; ++i) {
374                         const MLoopTri *lt = &looptri[face_indices[i]];
375
376                         /* Skip hidden faces */
377                         if (paint_is_face_hidden(lt, mvert, mloop))
378                                 continue;
379
380                         GWN_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i]));
381                 }
382                 buffers->index_buf = GWN_indexbuf_build(&elb);
383         }
384         else {
385                 if (!buffers->is_index_buf_global) {
386                         GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
387                 }
388                 buffers->index_buf = NULL;
389                 buffers->is_index_buf_global = false;
390         }
391
392         buffers->tot_tri = tottri;
393
394         buffers->mpoly = mpoly;
395         buffers->mloop = mloop;
396         buffers->looptri = looptri;
397
398         buffers->face_indices = face_indices;
399         buffers->face_indices_len = face_indices_len;
400
401         return buffers;
402 }
403
404 void GPU_pbvh_grid_buffers_update(
405         GPU_PBVH_Buffers *buffers, CCGElem **grids,
406         const DMFlagMat *grid_flag_mats, int *grid_indices,
407         int totgrid, const CCGKey *key,
408         const int update_flags)
409 {
410         const bool show_diffuse_color = (update_flags & GPU_PBVH_BUFFERS_SHOW_DIFFUSE_COLOR) != 0;
411         const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
412         int i, j, k, x, y;
413
414         buffers->show_diffuse_color = show_diffuse_color;
415         buffers->show_mask = show_mask;
416         buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
417
418         /* Build VBO */
419         if (buffers->index_buf) {
420                 const int has_mask = key->has_mask;
421                 float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
422
423                 if (show_diffuse_color) {
424                         const DMFlagMat *flags = &grid_flag_mats[grid_indices[0]];
425
426                         gpu_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
427                 }
428
429                 copy_v4_v4(buffers->diffuse_color, diffuse_color);
430
431                 uint vbo_index_offset = 0;
432                 /* Build VBO */
433                 if (gpu_pbvh_vert_buf_data_set(buffers, totgrid * key->grid_area)) {
434                         for (i = 0; i < totgrid; ++i) {
435                                 CCGElem *grid = grids[grid_indices[i]];
436                                 int vbo_index = vbo_index_offset;
437
438                                 for (y = 0; y < key->grid_size; y++) {
439                                         for (x = 0; x < key->grid_size; x++) {
440                                                 CCGElem *elem = CCG_grid_elem(key, grid, x, y);
441                                                 GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
442
443                                                 if (buffers->smooth) {
444                                                         short no_short[3];
445                                                         normal_float_to_short_v3(no_short, CCG_elem_no(key, elem));
446                                                         GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
447
448                                                         if (has_mask) {
449                                                                 uchar color_ub[3];
450                                                                 if (show_mask) {
451                                                                         gpu_color_from_mask_copy(*CCG_elem_mask(key, elem),
452                                                                                                  diffuse_color, color_ub);
453                                                                 }
454                                                                 else {
455                                                                         unit_float_to_uchar_clamp_v3(color_ub, diffuse_color);
456                                                                 }
457                                                                 GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
458                                                         }
459                                                 }
460                                                 vbo_index += 1;
461                                         }
462                                 }
463                                 
464                                 if (!buffers->smooth) {
465                                         for (j = 0; j < key->grid_size - 1; j++) {
466                                                 for (k = 0; k < key->grid_size - 1; k++) {
467                                                         CCGElem *elems[4] = {
468                                                                 CCG_grid_elem(key, grid, k, j + 1),
469                                                                 CCG_grid_elem(key, grid, k + 1, j + 1),
470                                                                 CCG_grid_elem(key, grid, k + 1, j),
471                                                                 CCG_grid_elem(key, grid, k, j)
472                                                         };
473                                                         float fno[3];
474
475                                                         normal_quad_v3(fno,
476                                                                        CCG_elem_co(key, elems[0]),
477                                                                        CCG_elem_co(key, elems[1]),
478                                                                        CCG_elem_co(key, elems[2]),
479                                                                        CCG_elem_co(key, elems[3]));
480
481                                                         vbo_index = vbo_index_offset + ((j + 1) * key->grid_size + k);
482                                                         short no_short[3];
483                                                         normal_float_to_short_v3(no_short, fno);
484                                                         GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
485
486                                                         if (has_mask) {
487                                                                 uchar color_ub[3];
488                                                                 if (show_mask) {
489                                                                         gpu_color_from_mask_quad_copy(key,
490                                                                                                       elems[0],
491                                                                                                       elems[1],
492                                                                                                       elems[2],
493                                                                                                       elems[3],
494                                                                                                       diffuse_color,
495                                                                                                       color_ub);
496                                                                 }
497                                                                 else {
498                                                                         unit_float_to_uchar_clamp_v3(color_ub, diffuse_color);
499                                                                 }
500                                                                 GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
501                                                         }
502                                                 }
503                                         }
504                                 }
505
506                                 vbo_index_offset += key->grid_area;
507                         }
508
509                         gpu_pbvh_batch_init(buffers);
510                 }
511         }
512
513         buffers->grids = grids;
514         buffers->grid_indices = grid_indices;
515         buffers->totgrid = totgrid;
516         buffers->grid_flag_mats = grid_flag_mats;
517         buffers->gridkey = *key;
518
519         //printf("node updated %p\n", buffers);
520 }
521
522 /* Build the element array buffer of grid indices using either
523  * unsigned shorts or unsigned ints. */
524 #define FILL_QUAD_BUFFER(max_vert_, tot_quad_, buffer_)                 \
525     {                                                                   \
526         int offset = 0;                                                 \
527         int i, j, k;                                                    \
528                                                                         \
529         Gwn_IndexBufBuilder elb;                                        \
530         GWN_indexbuf_init(                                              \
531                 &elb, GWN_PRIM_TRIS, tot_quad_ * 2, max_vert_);         \
532                                                                         \
533         /* Fill the buffer */                                           \
534         for (i = 0; i < totgrid; ++i) {                                 \
535             BLI_bitmap *gh = NULL;                                      \
536             if (grid_hidden)                                            \
537                 gh = grid_hidden[(grid_indices)[i]];                    \
538                                                                         \
539             for (j = 0; j < gridsize - 1; ++j) {                        \
540                 for (k = 0; k < gridsize - 1; ++k) {                    \
541                     /* Skip hidden grid face */                         \
542                     if (gh && paint_is_grid_face_hidden(                \
543                             gh, gridsize, k, j))                        \
544                     {                                                   \
545                         continue;                                       \
546                     }                                                   \
547                     GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
548                     GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k);    \
549                     GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
550                                                                             \
551                     GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k + 1); \
552                     GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
553                     GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
554                 }                                                       \
555             }                                                           \
556                                                                         \
557             offset += gridsize * gridsize;                              \
558         }                                                               \
559         buffer_ = GWN_indexbuf_build(&elb);                             \
560     } (void)0
561 /* end FILL_QUAD_BUFFER */
562
563 static Gwn_IndexBuf *gpu_get_grid_buffer(
564         int gridsize, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer,
565         /* remove this arg  when gawain gets base-vertex support! */
566         int totgrid)
567 {
568         /* used in the FILL_QUAD_BUFFER macro */
569         BLI_bitmap * const *grid_hidden = NULL;
570         const int *grid_indices = NULL;
571         // int totgrid = 1;
572
573         GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer;
574
575         if (gridbuff == NULL) {
576                 *grid_common_gpu_buffer = gridbuff = MEM_mallocN(sizeof(GridCommonGPUBuffer), __func__);
577                 gridbuff->mres_buffer = NULL;
578                 gridbuff->mres_prev_gridsize = -1;
579                 gridbuff->mres_prev_totquad = 0;
580         }
581
582         /* VBO is already built */
583         if (gridbuff->mres_buffer && gridbuff->mres_prev_gridsize == gridsize) {
584                 *totquad = gridbuff->mres_prev_totquad;
585                 return gridbuff->mres_buffer;
586         }
587         /* we can't reuse old, delete the existing buffer */
588         else if (gridbuff->mres_buffer) {
589                 GWN_indexbuf_discard(gridbuff->mres_buffer);
590                 gridbuff->mres_buffer = NULL;
591         }
592
593         /* Build new VBO */
594         *totquad = (gridsize - 1) * (gridsize - 1) * totgrid;
595         int max_vert = gridsize * gridsize * totgrid;
596
597         FILL_QUAD_BUFFER(max_vert, *totquad, gridbuff->mres_buffer);
598
599         gridbuff->mres_prev_gridsize = gridsize;
600         gridbuff->mres_prev_totquad = *totquad;
601         return gridbuff->mres_buffer;
602 }
603
604 #define FILL_FAST_BUFFER() \
605 { \
606         Gwn_IndexBufBuilder elb; \
607         GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, 6 * totgrid, INT_MAX); \
608         for (int i = 0; i < totgrid; i++) { \
609                 GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
610                 GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize); \
611                 GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
612                 GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - 1); \
613                 GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
614                 GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
615         } \
616         buffers->index_buf_fast = GWN_indexbuf_build(&elb); \
617 } (void)0
618
619 GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
620         int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *UNUSED(key),
621         GridCommonGPUBuffer **grid_common_gpu_buffer)
622 {
623         GPU_PBVH_Buffers *buffers;
624         int totquad;
625         int fully_visible_totquad = (gridsize - 1) * (gridsize - 1) * totgrid;
626
627         buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
628         buffers->grid_hidden = grid_hidden;
629         buffers->totgrid = totgrid;
630
631         buffers->show_diffuse_color = false;
632         buffers->show_mask = true;
633
634         /* Count the number of quads */
635         totquad = BKE_pbvh_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize);
636
637         /* totally hidden node, return here to avoid BufferData with zero below. */
638         if (totquad == 0)
639                 return buffers;
640
641         /* create and fill indices of the fast buffer too */
642         FILL_FAST_BUFFER();
643
644         if (totquad == fully_visible_totquad) {
645                 buffers->index_buf = gpu_get_grid_buffer(
646                         gridsize, &buffers->tot_quad, grid_common_gpu_buffer, totgrid);
647                 buffers->has_hidden = false;
648                 buffers->is_index_buf_global = true;
649         }
650         else {
651                 uint max_vert = totgrid * gridsize * gridsize;
652                 buffers->tot_quad = totquad;
653
654                 FILL_QUAD_BUFFER(max_vert, totquad, buffers->index_buf);
655
656                 buffers->has_hidden = false;
657                 buffers->is_index_buf_global = false;
658         }
659
660 #ifdef USE_BASE_ELEM
661         /* Build coord/normal VBO */
662         if (GLEW_ARB_draw_elements_base_vertex /* 3.2 */) {
663                 int i;
664                 buffers->baseelemarray = MEM_mallocN(sizeof(int) * totgrid * 2, "GPU_PBVH_Buffers.baseelemarray");
665                 buffers->baseindex = MEM_mallocN(sizeof(void *) * totgrid, "GPU_PBVH_Buffers.baseindex");
666                 for (i = 0; i < totgrid; i++) {
667                         buffers->baseelemarray[i] = buffers->tot_quad * 6;
668                         buffers->baseelemarray[i + totgrid] = i * key->grid_area;
669                         buffers->baseindex[i] = NULL;
670                 }
671         }
672 #endif
673
674         return buffers;
675 }
676
677 #undef FILL_QUAD_BUFFER
678
679 /* Output a BMVert into a VertexBufferFormat array
680  *
681  * The vertex is skipped if hidden, otherwise the output goes into
682  * index '*v_index' in the 'vert_data' array and '*v_index' is
683  * incremented.
684  */
685 static void gpu_bmesh_vert_to_buffer_copy__gwn(
686         BMVert *v,
687         Gwn_VertBuf *vert_buf,
688         int *v_index,
689         const float fno[3],
690         const float *fmask,
691         const int cd_vert_mask_offset,
692         const float diffuse_color[4],
693         const bool show_mask)
694 {
695         if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
696
697                 /* Set coord, normal, and mask */
698                 GWN_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co);
699
700                 {
701                         short no_short[3];
702                         normal_float_to_short_v3(no_short, fno ? fno : v->no);
703                         GWN_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short);
704                 }
705
706                 {
707                         uchar color_ub[3];
708                         float effective_mask;
709                         if (show_mask) {
710                                 effective_mask = fmask ? *fmask
711                                                        : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
712                         }
713                         else {
714                                 effective_mask = 0.0f;
715                         }
716
717                         gpu_color_from_mask_copy(
718                                 effective_mask,
719                                 diffuse_color,
720                                 color_ub);
721                         GWN_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, color_ub);
722                 }
723
724                 /* Assign index for use in the triangle index buffer */
725                 /* note: caller must set:  bm->elem_index_dirty |= BM_VERT; */
726                 BM_elem_index_set(v, (*v_index)); /* set_dirty! */
727
728                 (*v_index)++;
729         }
730 }
731
732 /* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */
733 static int gpu_bmesh_vert_visible_count(GSet *bm_unique_verts,
734                                         GSet *bm_other_verts)
735 {
736         GSetIterator gs_iter;
737         int totvert = 0;
738
739         GSET_ITER (gs_iter, bm_unique_verts) {
740                 BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
741                 if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
742                         totvert++;
743         }
744         GSET_ITER (gs_iter, bm_other_verts) {
745                 BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
746                 if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
747                         totvert++;
748         }
749
750         return totvert;
751 }
752
753 /* Return the total number of visible faces */
754 static int gpu_bmesh_face_visible_count(GSet *bm_faces)
755 {
756         GSetIterator gh_iter;
757         int totface = 0;
758
759         GSET_ITER (gh_iter, bm_faces) {
760                 BMFace *f = BLI_gsetIterator_getKey(&gh_iter);
761
762                 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN))
763                         totface++;
764         }
765
766         return totface;
767 }
768
769 /* Creates a vertex buffer (coordinate, normal, color) and, if smooth
770  * shading, an element index buffer. */
771 void GPU_pbvh_bmesh_buffers_update(
772         GPU_PBVH_Buffers *buffers,
773         BMesh *bm,
774         GSet *bm_faces,
775         GSet *bm_unique_verts,
776         GSet *bm_other_verts,
777         const int update_flags)
778 {
779         const bool show_diffuse_color = (update_flags & GPU_PBVH_BUFFERS_SHOW_DIFFUSE_COLOR) != 0;
780         const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
781         int tottri, totvert, maxvert = 0;
782         float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
783
784         /* TODO, make mask layer optional for bmesh buffer */
785         const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
786
787         buffers->show_diffuse_color = show_diffuse_color;
788         buffers->show_mask = show_mask;
789
790         /* Count visible triangles */
791         tottri = gpu_bmesh_face_visible_count(bm_faces);
792
793         if (buffers->smooth) {
794                 /* Count visible vertices */
795                 totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts);
796         }
797         else
798                 totvert = tottri * 3;
799
800         if (!tottri) {
801                 buffers->tot_tri = 0;
802                 return;
803         }
804
805         if (show_diffuse_color) {
806                 /* due to dynamic nature of dyntopo, only get first material */
807                 GSetIterator gs_iter;
808                 BMFace *f;
809                 BLI_gsetIterator_init(&gs_iter, bm_faces);
810                 f = BLI_gsetIterator_getKey(&gs_iter);
811                 gpu_material_diffuse_get(f->mat_nr + 1, diffuse_color);
812         }
813
814         copy_v4_v4(buffers->diffuse_color, diffuse_color);
815
816         /* Fill vertex buffer */
817         if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) {
818                 int v_index = 0;
819
820                 if (buffers->smooth) {
821                         GSetIterator gs_iter;
822
823                         /* Vertices get an index assigned for use in the triangle
824                          * index buffer */
825                         bm->elem_index_dirty |= BM_VERT;
826
827                         GSET_ITER (gs_iter, bm_unique_verts) {
828                                 gpu_bmesh_vert_to_buffer_copy__gwn(
829                                         BLI_gsetIterator_getKey(&gs_iter),
830                                         buffers->vert_buf, &v_index, NULL, NULL,
831                                         cd_vert_mask_offset, diffuse_color,
832                                         show_mask);
833                         }
834
835                         GSET_ITER (gs_iter, bm_other_verts) {
836                                 gpu_bmesh_vert_to_buffer_copy__gwn(
837                                         BLI_gsetIterator_getKey(&gs_iter),
838                                         buffers->vert_buf, &v_index, NULL, NULL,
839                                         cd_vert_mask_offset, diffuse_color,
840                                         show_mask);
841                         }
842
843                         maxvert = v_index;
844                 }
845                 else {
846                         GSetIterator gs_iter;
847
848                         GSET_ITER (gs_iter, bm_faces) {
849                                 BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
850
851                                 BLI_assert(f->len == 3);
852
853                                 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
854                                         BMVert *v[3];
855                                         float fmask = 0;
856                                         int i;
857
858 #if 0
859                                         BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void **)v, 3);
860 #endif
861                                         BM_face_as_array_vert_tri(f, v);
862
863                                         /* Average mask value */
864                                         for (i = 0; i < 3; i++) {
865                                                 fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset);
866                                         }
867                                         fmask /= 3.0f;
868                                         
869                                         for (i = 0; i < 3; i++) {
870                                                 gpu_bmesh_vert_to_buffer_copy__gwn(
871                                                         v[i], buffers->vert_buf,
872                                                         &v_index, f->no, &fmask,
873                                                         cd_vert_mask_offset, diffuse_color,
874                                                         show_mask);
875                                         }
876                                 }
877                         }
878
879                         buffers->tot_tri = tottri;
880                 }
881
882                 /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */
883                 bm->elem_index_dirty |= BM_VERT;
884         }
885         else {
886                 /* Memory map failed */
887                 return;
888         }
889
890         if (buffers->smooth) {
891                 /* Fill the triangle buffer */
892                 buffers->index_buf = NULL;
893                 Gwn_IndexBufBuilder elb;
894                 GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, maxvert);
895
896                 /* Initialize triangle index buffer */
897                 buffers->is_index_buf_global = false;
898
899                 /* Fill triangle index buffer */
900
901                 {
902                         GSetIterator gs_iter;
903
904                         GSET_ITER (gs_iter, bm_faces) {
905                                 BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
906
907                                 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
908                                         BMLoop *l_iter;
909                                         BMLoop *l_first;
910
911                                         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
912                                         do {
913                                                 GWN_indexbuf_add_generic_vert(&elb, BM_elem_index_get(l_iter->v));
914                                         } while ((l_iter = l_iter->next) != l_first);
915                                 }
916                         }
917
918                         buffers->tot_tri = tottri;
919
920                         if (buffers->index_buf == NULL) {
921                                 buffers->index_buf = GWN_indexbuf_build(&elb);
922                         }
923                         else {
924                                 GWN_indexbuf_build_in_place(&elb, buffers->index_buf);
925                         }
926                 }
927         }
928         else if (buffers->index_buf) {
929                 if (!buffers->is_index_buf_global) {
930                         GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
931                 }
932                 buffers->index_buf = NULL;
933                 buffers->is_index_buf_global = false;
934         }
935
936         gpu_pbvh_batch_init(buffers);
937 }
938
939 GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
940 {
941         GPU_PBVH_Buffers *buffers;
942
943         buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
944         buffers->use_bmesh = true;
945         buffers->smooth = smooth_shading;
946         buffers->show_diffuse_color = false;
947         buffers->show_mask = true;
948
949         return buffers;
950 }
951
952 Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast)
953 {
954         return (fast && buffers->triangles_fast) ?
955                 buffers->triangles_fast : buffers->triangles;
956 }
957
958 bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
959 {
960         float diffuse_color[4];
961
962         if (buffers->show_diffuse_color != show_diffuse_color)
963                 return true;
964
965         if (buffers->show_diffuse_color == false)
966                 return false;
967
968         if (buffers->looptri) {
969                 const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
970                 const MPoly *mp = &buffers->mpoly[lt->poly];
971
972                 gpu_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
973         }
974         else if (buffers->use_bmesh) {
975                 /* due to dynamic nature of dyntopo, only get first material */
976                 if (BLI_gset_len(bm_faces) > 0) {
977                         GSetIterator gs_iter;
978                         BMFace *f;
979
980                         BLI_gsetIterator_init(&gs_iter, bm_faces);
981                         f = BLI_gsetIterator_getKey(&gs_iter);
982                         gpu_material_diffuse_get(f->mat_nr + 1, diffuse_color);
983                 }
984                 else {
985                         return false;
986                 }
987         }
988         else {
989                 const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]];
990
991                 gpu_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
992         }
993
994         return !equals_v3v3(diffuse_color, buffers->diffuse_color);
995 }
996
997 bool GPU_pbvh_buffers_mask_changed(GPU_PBVH_Buffers *buffers, bool show_mask)
998 {
999         return (buffers->show_mask != show_mask);
1000 }
1001
1002 void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
1003 {
1004         if (buffers) {
1005                 GWN_BATCH_DISCARD_SAFE(buffers->triangles);
1006                 GWN_BATCH_DISCARD_SAFE(buffers->triangles_fast);
1007                 if (!buffers->is_index_buf_global) {
1008                         GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
1009                 }
1010                 GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast);
1011                 GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
1012
1013 #ifdef USE_BASE_ELEM
1014                 if (buffers->baseelemarray)
1015                         MEM_freeN(buffers->baseelemarray);
1016                 if (buffers->baseindex)
1017                         MEM_freeN(buffers->baseindex);
1018 #endif
1019
1020                 MEM_freeN(buffers);
1021         }
1022 }
1023
1024 void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer)
1025 {
1026         GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer;
1027
1028         if (gridbuff) {
1029                 if (gridbuff->mres_buffer) {
1030                         BLI_mutex_lock(&buffer_mutex);
1031                         GWN_INDEXBUF_DISCARD_SAFE(gridbuff->mres_buffer);
1032                         BLI_mutex_unlock(&buffer_mutex);
1033                 }
1034                 MEM_freeN(gridbuff);
1035                 *grid_common_gpu_buffer = NULL;
1036         }
1037 }
1038
1039 /* debug function, draws the pbvh BB */
1040 void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos)
1041 {
1042         if (leaf)
1043                 immUniformColor4f(0.0, 1.0, 0.0, 0.5);
1044         else
1045                 immUniformColor4f(1.0, 0.0, 0.0, 0.5);
1046
1047         /* TODO(merwin): revisit this after we have mutable VertexBuffers
1048          * could keep a static batch & index buffer, change the VBO contents per draw
1049          */
1050
1051         immBegin(GWN_PRIM_LINES, 24);
1052
1053         /* top */
1054         immVertex3f(pos, min[0], min[1], max[2]);
1055         immVertex3f(pos, min[0], max[1], max[2]);
1056
1057         immVertex3f(pos, min[0], max[1], max[2]);
1058         immVertex3f(pos, max[0], max[1], max[2]);
1059
1060         immVertex3f(pos, max[0], max[1], max[2]);
1061         immVertex3f(pos, max[0], min[1], max[2]);
1062
1063         immVertex3f(pos, max[0], min[1], max[2]);
1064         immVertex3f(pos, min[0], min[1], max[2]);
1065
1066         /* bottom */
1067         immVertex3f(pos, min[0], min[1], min[2]);
1068         immVertex3f(pos, min[0], max[1], min[2]);
1069
1070         immVertex3f(pos, min[0], max[1], min[2]);
1071         immVertex3f(pos, max[0], max[1], min[2]);
1072
1073         immVertex3f(pos, max[0], max[1], min[2]);
1074         immVertex3f(pos, max[0], min[1], min[2]);
1075
1076         immVertex3f(pos, max[0], min[1], min[2]);
1077         immVertex3f(pos, min[0], min[1], min[2]);
1078
1079         /* sides */
1080         immVertex3f(pos, min[0], min[1], min[2]);
1081         immVertex3f(pos, min[0], min[1], max[2]);
1082
1083         immVertex3f(pos, min[0], max[1], min[2]);
1084         immVertex3f(pos, min[0], max[1], max[2]);
1085
1086         immVertex3f(pos, max[0], max[1], min[2]);
1087         immVertex3f(pos, max[0], max[1], max[2]);
1088
1089         immVertex3f(pos, max[0], min[1], min[2]);
1090         immVertex3f(pos, max[0], min[1], max[2]);
1091
1092         immEnd();
1093 }
1094
1095 void GPU_pbvh_fix_linking()
1096 {
1097 }