d1102b03e9afcefb03831177be7f56888988e8a7
[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  * with fall-back to vertex arrays.
33  */
34
35 #include <limits.h>
36 #include <stddef.h>
37 #include <string.h>
38
39 #include "GPU_glew.h"
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_bitmap.h"
44 #include "BLI_math.h"
45 #include "BLI_utildefines.h"
46 #include "BLI_ghash.h"
47 #include "BLI_threads.h"
48
49 #include "DNA_meshdata_types.h"
50
51 #include "BKE_ccg.h"
52 #include "BKE_DerivedMesh.h"
53 #include "BKE_paint.h"
54 #include "BKE_pbvh.h"
55
56 #include "DNA_userdef_types.h"
57
58 #include "GPU_buffers.h"
59 #include "GPU_draw.h"
60
61 #include "bmesh.h"
62
63 typedef enum {
64         GPU_BUFFER_VERTEX_STATE = (1 << 0),
65         GPU_BUFFER_NORMAL_STATE = (1 << 1),
66         GPU_BUFFER_TEXCOORD_UNIT_0_STATE = (1 << 2),
67         GPU_BUFFER_TEXCOORD_UNIT_2_STATE = (1 << 3),
68         GPU_BUFFER_COLOR_STATE = (1 << 4),
69         GPU_BUFFER_ELEMENT_STATE = (1 << 5),
70 } GPUBufferState;
71
72 #define MAX_GPU_ATTRIB_DATA 32
73
74 #define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
75
76 /* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
77 static GPUBufferState GLStates = 0;
78 static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
79
80 static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
81
82 /* stores recently-deleted buffers so that new buffers won't have to
83  * be recreated as often
84  *
85  * only one instance of this pool is created, stored in
86  * gpu_buffer_pool
87  *
88  * note that the number of buffers in the pool is usually limited to
89  * MAX_FREE_GPU_BUFFERS, but this limit may be exceeded temporarily
90  * when a GPUBuffer is released outside the main thread; due to OpenGL
91  * restrictions it cannot be immediately released
92  */
93 typedef struct GPUBufferPool {
94         /* number of allocated buffers stored */
95         int totbuf;
96         int totpbvhbufids;
97         /* actual allocated length of the arrays */
98         int maxsize;
99         int maxpbvhsize;
100         GPUBuffer **buffers;
101         GLuint *pbvhbufids;
102 } GPUBufferPool;
103 #define MAX_FREE_GPU_BUFFERS 8
104 #define MAX_FREE_GPU_BUFF_IDS 100
105
106 /* create a new GPUBufferPool */
107 static GPUBufferPool *gpu_buffer_pool_new(void)
108 {
109         GPUBufferPool *pool;
110
111         pool = MEM_callocN(sizeof(GPUBufferPool), "GPUBuffer_Pool");
112
113         pool->maxsize = MAX_FREE_GPU_BUFFERS;
114         pool->maxpbvhsize = MAX_FREE_GPU_BUFF_IDS;
115         pool->buffers = MEM_mallocN(sizeof(*pool->buffers) * pool->maxsize,
116                                     "GPUBufferPool.buffers");
117         pool->pbvhbufids = MEM_mallocN(sizeof(*pool->pbvhbufids) * pool->maxpbvhsize,
118                                        "GPUBufferPool.pbvhbuffers");
119         return pool;
120 }
121
122 /* remove a GPUBuffer from the pool (does not free the GPUBuffer) */
123 static void gpu_buffer_pool_remove_index(GPUBufferPool *pool, int index)
124 {
125         int i;
126
127         if (!pool || index < 0 || index >= pool->totbuf)
128                 return;
129
130         /* shift entries down, overwriting the buffer at `index' */
131         for (i = index; i < pool->totbuf - 1; i++)
132                 pool->buffers[i] = pool->buffers[i + 1];
133
134         /* clear the last entry */
135         if (pool->totbuf > 0)
136                 pool->buffers[pool->totbuf - 1] = NULL;
137
138         pool->totbuf--;
139 }
140
141 /* delete the last entry in the pool */
142 static void gpu_buffer_pool_delete_last(GPUBufferPool *pool)
143 {
144         GPUBuffer *last;
145
146         if (pool->totbuf <= 0)
147                 return;
148
149         /* get the last entry */
150         if (!(last = pool->buffers[pool->totbuf - 1]))
151                 return;
152
153         /* delete the buffer's data */
154         if (last->use_vbo)
155                 glDeleteBuffersARB(1, &last->id);
156         else
157                 MEM_freeN(last->pointer);
158
159         /* delete the buffer and remove from pool */
160         MEM_freeN(last);
161         pool->totbuf--;
162         pool->buffers[pool->totbuf] = NULL;
163 }
164
165 /* free a GPUBufferPool; also frees the data in the pool's
166  * GPUBuffers */
167 static void gpu_buffer_pool_free(GPUBufferPool *pool)
168 {
169         if (!pool)
170                 return;
171         
172         while (pool->totbuf)
173                 gpu_buffer_pool_delete_last(pool);
174
175         MEM_freeN(pool->buffers);
176         MEM_freeN(pool->pbvhbufids);
177         MEM_freeN(pool);
178 }
179
180 static void gpu_buffer_pool_free_unused(GPUBufferPool *pool)
181 {
182         if (!pool)
183                 return;
184
185         BLI_mutex_lock(&buffer_mutex);
186         
187         while (pool->totbuf)
188                 gpu_buffer_pool_delete_last(pool);
189
190         if (pool->totpbvhbufids > 0) {
191                 glDeleteBuffersARB(pool->totpbvhbufids, pool->pbvhbufids);
192                 pool->totpbvhbufids = 0;
193         }
194
195         BLI_mutex_unlock(&buffer_mutex);
196 }
197
198 static GPUBufferPool *gpu_buffer_pool = NULL;
199 static GPUBufferPool *gpu_get_global_buffer_pool(void)
200 {
201         /* initialize the pool */
202         if (!gpu_buffer_pool)
203                 gpu_buffer_pool = gpu_buffer_pool_new();
204
205         return gpu_buffer_pool;
206 }
207
208 void GPU_global_buffer_pool_free(void)
209 {
210         gpu_buffer_pool_free(gpu_buffer_pool);
211         gpu_buffer_pool = NULL;
212 }
213
214 void GPU_global_buffer_pool_free_unused(void)
215 {
216         gpu_buffer_pool_free_unused(gpu_buffer_pool);
217 }
218
219 /* get a GPUBuffer of at least `size' bytes; uses one from the buffer
220  * pool if possible, otherwise creates a new one
221  *
222  * Thread-unsafe version for internal usage only.
223  */
224 static GPUBuffer *gpu_buffer_alloc_intern(int size, bool use_VBO)
225 {
226         GPUBufferPool *pool;
227         GPUBuffer *buf;
228         int i, bufsize, bestfit = -1;
229
230         /* bad case, leads to leak of buf since buf->pointer will allocate
231          * NULL, leading to return without cleanup. In any case better detect early
232          * psy-fi */
233         if (size == 0)
234                 return NULL;
235
236         pool = gpu_get_global_buffer_pool();
237
238         /* not sure if this buffer pool code has been profiled much,
239          * seems to me that the graphics driver and system memory
240          * management might do this stuff anyway. --nicholas
241          */
242
243         /* check the global buffer pool for a recently-deleted buffer
244          * that is at least as big as the request, but not more than
245          * twice as big */
246         for (i = 0; i < pool->totbuf; i++) {
247                 bufsize = pool->buffers[i]->size;
248
249                 /* only return a buffer that matches the VBO preference */
250                  if (pool->buffers[i]->use_vbo != use_VBO)
251                          continue;
252                 
253                 /* check for an exact size match */
254                 if (bufsize == size) {
255                         bestfit = i;
256                         break;
257                 }
258                 /* smaller buffers won't fit data and buffers at least
259                  * twice as big are a waste of memory */
260                 else if (bufsize > size && size > (bufsize / 2)) {
261                         /* is it closer to the required size than the
262                          * last appropriate buffer found. try to save
263                          * memory */
264                         if (bestfit == -1 || pool->buffers[bestfit]->size > bufsize) {
265                                 bestfit = i;
266                         }
267                 }
268         }
269
270         /* if an acceptable buffer was found in the pool, remove it
271          * from the pool and return it */
272         if (bestfit != -1) {
273                 buf = pool->buffers[bestfit];
274                 gpu_buffer_pool_remove_index(pool, bestfit);
275                 return buf;
276         }
277
278         /* no acceptable buffer found in the pool, create a new one */
279         buf = MEM_callocN(sizeof(GPUBuffer), "GPUBuffer");
280         buf->size = size;
281         buf->use_vbo = use_VBO;
282
283         if (use_VBO) {
284                 /* create a new VBO and initialize it to the requested
285                  * size */
286                 glGenBuffersARB(1, &buf->id);
287                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf->id);
288                 glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB);
289                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
290         }
291         else {
292                 buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
293                 
294                 /* purpose of this seems to be dealing with
295                  * out-of-memory errors? looks a bit iffy to me
296                  * though, at least on Linux I expect malloc() would
297                  * just overcommit. --nicholas */
298                 while (!buf->pointer && pool->totbuf > 0) {
299                         gpu_buffer_pool_delete_last(pool);
300                         buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
301                 }
302                 if (!buf->pointer)
303                         return NULL;
304         }
305
306         return buf;
307 }
308
309 /* Same as above, but safe for threading. */
310 GPUBuffer *GPU_buffer_alloc(int size, bool force_vertex_arrays)
311 {
312         GPUBuffer *buffer;
313         bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO) && !force_vertex_arrays;
314
315         if (size == 0) {
316                 /* Early out, no lock needed in this case. */
317                 return NULL;
318         }
319
320         BLI_mutex_lock(&buffer_mutex);
321         buffer = gpu_buffer_alloc_intern(size, use_VBOs);
322         BLI_mutex_unlock(&buffer_mutex);
323
324         return buffer;
325 }
326
327 /* release a GPUBuffer; does not free the actual buffer or its data,
328  * but rather moves it to the pool of recently-freed buffers for
329  * possible re-use
330  *
331  * Thread-unsafe version for internal usage only.
332  */
333 static void gpu_buffer_free_intern(GPUBuffer *buffer)
334 {
335         GPUBufferPool *pool;
336         int i;
337
338         if (!buffer)
339                 return;
340
341         pool = gpu_get_global_buffer_pool();
342
343         /* free the last used buffer in the queue if no more space, but only
344          * if we are in the main thread. for e.g. rendering or baking it can
345          * happen that we are in other thread and can't call OpenGL, in that
346          * case cleanup will be done GPU_buffer_pool_free_unused */
347         if (BLI_thread_is_main()) {
348                 /* in main thread, safe to decrease size of pool back
349                  * down to MAX_FREE_GPU_BUFFERS */
350                 while (pool->totbuf >= MAX_FREE_GPU_BUFFERS)
351                         gpu_buffer_pool_delete_last(pool);
352         }
353         else {
354                 /* outside of main thread, can't safely delete the
355                  * buffer, so increase pool size */
356                 if (pool->maxsize == pool->totbuf) {
357                         pool->maxsize += MAX_FREE_GPU_BUFFERS;
358                         pool->buffers = MEM_reallocN(pool->buffers,
359                                                      sizeof(GPUBuffer *) * pool->maxsize);
360                 }
361         }
362
363         /* shift pool entries up by one */
364         for (i = pool->totbuf; i > 0; i--)
365                 pool->buffers[i] = pool->buffers[i - 1];
366
367         /* insert the buffer into the beginning of the pool */
368         pool->buffers[0] = buffer;
369         pool->totbuf++;
370 }
371
372 /* Same as above, but safe for threading. */
373 void GPU_buffer_free(GPUBuffer *buffer)
374 {
375         if (!buffer) {
376                 /* Early output, no need to lock in this case, */
377                 return;
378         }
379
380         BLI_mutex_lock(&buffer_mutex);
381         gpu_buffer_free_intern(buffer);
382         BLI_mutex_unlock(&buffer_mutex);
383 }
384
385 /* currently unused */
386 // #define USE_GPU_POINT_LINK
387
388 typedef struct GPUVertPointLink {
389 #ifdef USE_GPU_POINT_LINK
390         struct GPUVertPointLink *next;
391 #endif
392         /* -1 means uninitialized */
393         int point_index;
394 } GPUVertPointLink;
395
396
397 /* add a new point to the list of points related to a particular
398  * vertex */
399 #ifdef USE_GPU_POINT_LINK
400
401 static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
402 {
403         GPUVertPointLink *lnk;
404
405         lnk = &gdo->vert_points[vert_index];
406
407         /* if first link is in use, add a new link at the end */
408         if (lnk->point_index != -1) {
409                 /* get last link */
410                 for (; lnk->next; lnk = lnk->next) ;
411
412                 /* add a new link from the pool */
413                 lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage];
414                 gdo->vert_points_usage++;
415         }
416
417         lnk->point_index = point_index;
418 }
419
420 #else
421
422 static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
423 {
424         GPUVertPointLink *lnk;
425         lnk = &gdo->vert_points[vert_index];
426         if (lnk->point_index == -1) {
427                 lnk->point_index = point_index;
428         }
429 }
430
431 #endif  /* USE_GPU_POINT_LINK */
432
433 /* update the vert_points and triangle_to_mface fields with a new
434  * triangle */
435 static void gpu_drawobject_add_triangle(GPUDrawObject *gdo,
436                                         int base_point_index,
437                                         int face_index,
438                                         int v1, int v2, int v3)
439 {
440         int i, v[3] = {v1, v2, v3};
441         for (i = 0; i < 3; i++)
442                 gpu_drawobject_add_vert_point(gdo, v[i], base_point_index + i);
443         gdo->triangle_to_mface[base_point_index / 3] = face_index;
444 }
445
446 /* for each vertex, build a list of points related to it; these lists
447  * are stored in an array sized to the number of vertices */
448 static void gpu_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int totface, int totmat)
449 {
450         GPUBufferMaterial *mat;
451         int i, *mat_orig_to_new;
452
453         mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
454                                                      "GPUDrawObject.mat_orig_to_new");
455         /* allocate the array and space for links */
456         gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert,
457                                        "GPUDrawObject.vert_points");
458 #ifdef USE_GPU_POINT_LINK
459         gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point,
460                                            "GPUDrawObject.vert_points_mem");
461         gdo->vert_points_usage = 0;
462 #endif
463
464         /* build a map from the original material indices to the new
465          * GPUBufferMaterial indices */
466         for (i = 0; i < gdo->totmaterial; i++)
467                 mat_orig_to_new[gdo->materials[i].mat_nr] = i;
468
469         /* -1 indicates the link is not yet used */
470         for (i = 0; i < gdo->totvert; i++) {
471 #ifdef USE_GPU_POINT_LINK
472                 gdo->vert_points[i].link = NULL;
473 #endif
474                 gdo->vert_points[i].point_index = -1;
475         }
476
477         for (i = 0; i < totface; i++, f++) {
478                 mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
479
480                 /* add triangle */
481                 gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
482                                             i, f->v1, f->v2, f->v3);
483                 mat->totpoint += 3;
484
485                 /* add second triangle for quads */
486                 if (f->v4) {
487                         gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
488                                                     i, f->v3, f->v4, f->v1);
489                         mat->totpoint += 3;
490                 }
491         }
492
493         /* map any unused vertices to loose points */
494         for (i = 0; i < gdo->totvert; i++) {
495                 if (gdo->vert_points[i].point_index == -1) {
496                         gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point;
497                         gdo->tot_loose_point++;
498                 }
499         }
500
501         MEM_freeN(mat_orig_to_new);
502 }
503
504 /* see GPUDrawObject's structure definition for a description of the
505  * data being initialized here */
506 GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm)
507 {
508         GPUDrawObject *gdo;
509         MFace *mface;
510         int totmat = dm->totmat;
511         int *points_per_mat;
512         int i, curmat, curpoint, totface;
513
514         /* object contains at least one material (default included) so zero means uninitialized dm */
515         BLI_assert(totmat != 0);
516
517         mface = dm->getTessFaceArray(dm);
518         totface = dm->getNumTessFaces(dm);
519
520         /* get the number of points used by each material, treating
521          * each quad as two triangles */
522         points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new");
523         for (i = 0; i < totface; i++)
524                 points_per_mat[mface[i].mat_nr] += mface[i].v4 ? 6 : 3;
525
526         /* create the GPUDrawObject */
527         gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
528         gdo->totvert = dm->getNumVerts(dm);
529         gdo->totedge = dm->getNumEdges(dm);
530
531         /* count the number of materials used by this DerivedMesh */
532         for (i = 0; i < totmat; i++) {
533                 if (points_per_mat[i] > 0)
534                         gdo->totmaterial++;
535         }
536
537         /* allocate an array of materials used by this DerivedMesh */
538         gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
539                                      "GPUDrawObject.materials");
540
541         /* initialize the materials array */
542         for (i = 0, curmat = 0, curpoint = 0; i < totmat; i++) {
543                 if (points_per_mat[i] > 0) {
544                         gdo->materials[curmat].start = curpoint;
545                         gdo->materials[curmat].totpoint = 0;
546                         gdo->materials[curmat].mat_nr = i;
547
548                         curpoint += points_per_mat[i];
549                         curmat++;
550                 }
551         }
552
553         /* store total number of points used for triangles */
554         gdo->tot_triangle_point = curpoint;
555
556         gdo->triangle_to_mface = MEM_mallocN(sizeof(int) * (gdo->tot_triangle_point / 3),
557                                              "GPUDrawObject.triangle_to_mface");
558
559         gpu_drawobject_init_vert_points(gdo, mface, totface, totmat);
560         MEM_freeN(points_per_mat);
561
562         return gdo;
563 }
564
565 void GPU_drawobject_free(DerivedMesh *dm)
566 {
567         GPUDrawObject *gdo;
568
569         if (!dm || !(gdo = dm->drawObject))
570                 return;
571
572         MEM_freeN(gdo->materials);
573         MEM_freeN(gdo->triangle_to_mface);
574         MEM_freeN(gdo->vert_points);
575 #ifdef USE_GPU_POINT_LINK
576         MEM_freeN(gdo->vert_points_mem);
577 #endif
578         GPU_buffer_free(gdo->points);
579         GPU_buffer_free(gdo->normals);
580         GPU_buffer_free(gdo->uv);
581         GPU_buffer_free(gdo->uv_tex);
582         GPU_buffer_free(gdo->colors);
583         GPU_buffer_free(gdo->edges);
584         GPU_buffer_free(gdo->uvedges);
585
586         MEM_freeN(gdo);
587         dm->drawObject = NULL;
588 }
589
590 static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, int size, bool use_VBOs)
591 {
592         gpu_buffer_free_intern(buffer);
593         gpu_buffer_pool_delete_last(pool);
594         buffer = NULL;
595         
596         /* try freeing an entry from the pool
597          * and reallocating the buffer */
598         if (pool->totbuf > 0) {
599                 gpu_buffer_pool_delete_last(pool);
600                 buffer = gpu_buffer_alloc_intern(size, use_VBOs);
601         }
602         
603         return buffer;
604 }
605
606 typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
607                                   int *mat_orig_to_new, void *user_data);
608
609 static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
610                                    int vector_size, int size, GLenum target,
611                                    void *user, GPUBufferCopyFunc copy_f)
612 {
613         GPUBufferPool *pool;
614         GPUBuffer *buffer;
615         float *varray;
616         int *mat_orig_to_new;
617         int *cur_index_per_mat;
618         int i;
619         bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO);
620         GLboolean uploaded;
621
622         pool = gpu_get_global_buffer_pool();
623
624         BLI_mutex_lock(&buffer_mutex);
625
626         /* alloc a GPUBuffer; fall back to legacy mode on failure */
627         if (!(buffer = gpu_buffer_alloc_intern(size, use_VBOs))) {
628                 BLI_mutex_unlock(&buffer_mutex);
629                 return NULL;
630         }
631
632         mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
633                                       "GPU_buffer_setup.mat_orig_to_new");
634         cur_index_per_mat = MEM_mallocN(sizeof(int) * object->totmaterial,
635                                         "GPU_buffer_setup.cur_index_per_mat");
636         for (i = 0; i < object->totmaterial; i++) {
637                 /* for each material, the current index to copy data to */
638                 cur_index_per_mat[i] = object->materials[i].start * vector_size;
639
640                 /* map from original material index to new
641                  * GPUBufferMaterial index */
642                 mat_orig_to_new[object->materials[i].mat_nr] = i;
643         }
644
645         if (use_VBOs) {
646                 bool success = false;
647
648                 while (!success) {
649                         /* bind the buffer and discard previous data,
650                          * avoids stalling gpu */
651                         glBindBufferARB(target, buffer->id);
652                         glBufferDataARB(target, buffer->size, NULL, GL_STATIC_DRAW_ARB);
653
654                         /* attempt to map the buffer */
655                         if (!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) {
656                                  buffer = gpu_try_realloc(pool, buffer, size, true);
657                                  
658                                 /* allocation still failed; fall back
659                                  * to legacy mode */
660                                 if (!buffer) {
661                                         use_VBOs = false;
662                                         success = true;
663                                 }
664                         }
665                         else {
666                                 success = true;
667                         }
668                 }
669
670                 /* check legacy fallback didn't happen */
671                 if (use_VBOs) {
672                         uploaded = GL_FALSE;
673                         /* attempt to upload the data to the VBO */
674                         while (uploaded == GL_FALSE) {
675                                 (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
676                                 /* glUnmapBuffer returns GL_FALSE if
677                                  * the data store is corrupted; retry
678                                  * in that case */
679                                 uploaded = glUnmapBufferARB(target);
680                         }
681                 }
682                 glBindBufferARB(target, 0);
683         }
684         if (!use_VBOs) {
685                 /* VBO not supported, use vertex array fallback */
686                 if (!buffer || !buffer->pointer) {
687                         buffer = gpu_try_realloc(pool, buffer, size, false);
688                 }
689                 
690                 if (buffer) {
691                         varray = buffer->pointer;
692                         (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
693                 }
694         }
695
696         MEM_freeN(cur_index_per_mat);
697         MEM_freeN(mat_orig_to_new);
698
699         BLI_mutex_unlock(&buffer_mutex);
700
701         return buffer;
702 }
703
704 static void GPU_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
705 {
706         MVert *mvert;
707         MFace *f;
708         int i, j, start, totface;
709
710         mvert = dm->getVertArray(dm);
711         f = dm->getTessFaceArray(dm);
712
713         totface = dm->getNumTessFaces(dm);
714         for (i = 0; i < totface; i++, f++) {
715                 start = index[mat_orig_to_new[f->mat_nr]];
716
717                 /* v1 v2 v3 */
718                 copy_v3_v3(&varray[start], mvert[f->v1].co);
719                 copy_v3_v3(&varray[start + 3], mvert[f->v2].co);
720                 copy_v3_v3(&varray[start + 6], mvert[f->v3].co);
721                 index[mat_orig_to_new[f->mat_nr]] += 9;
722
723                 if (f->v4) {
724                         /* v3 v4 v1 */
725                         copy_v3_v3(&varray[start + 9], mvert[f->v3].co);
726                         copy_v3_v3(&varray[start + 12], mvert[f->v4].co);
727                         copy_v3_v3(&varray[start + 15], mvert[f->v1].co);
728                         index[mat_orig_to_new[f->mat_nr]] += 9;
729                 }
730         }
731
732         /* copy loose points */
733         j = dm->drawObject->tot_triangle_point * 3;
734         for (i = 0; i < dm->drawObject->totvert; i++) {
735                 if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) {
736                         copy_v3_v3(&varray[j], mvert[i].co);
737                         j += 3;
738                 }
739         }
740 }
741
742 static void GPU_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
743 {
744         int i, totface;
745         int start;
746         float f_no[3];
747
748         const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
749         short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
750         MVert *mvert = dm->getVertArray(dm);
751         MFace *f = dm->getTessFaceArray(dm);
752
753         totface = dm->getNumTessFaces(dm);
754         for (i = 0; i < totface; i++, f++) {
755                 const int smoothnormal = (f->flag & ME_SMOOTH);
756
757                 start = index[mat_orig_to_new[f->mat_nr]];
758                 index[mat_orig_to_new[f->mat_nr]] += f->v4 ? 18 : 9;
759
760                 if (tlnors) {
761                         short (*tlnor)[3] = tlnors[i];
762                         /* Copy loop normals */
763                         normal_short_to_float_v3(&varray[start], tlnor[0]);
764                         normal_short_to_float_v3(&varray[start + 3], tlnor[1]);
765                         normal_short_to_float_v3(&varray[start + 6], tlnor[2]);
766
767                         if (f->v4) {
768                                 normal_short_to_float_v3(&varray[start + 9], tlnor[2]);
769                                 normal_short_to_float_v3(&varray[start + 12], tlnor[3]);
770                                 normal_short_to_float_v3(&varray[start + 15], tlnor[0]);
771                         }
772                 }
773                 else if (smoothnormal) {
774                         /* copy vertex normal */
775                         normal_short_to_float_v3(&varray[start], mvert[f->v1].no);
776                         normal_short_to_float_v3(&varray[start + 3], mvert[f->v2].no);
777                         normal_short_to_float_v3(&varray[start + 6], mvert[f->v3].no);
778
779                         if (f->v4) {
780                                 normal_short_to_float_v3(&varray[start + 9], mvert[f->v3].no);
781                                 normal_short_to_float_v3(&varray[start + 12], mvert[f->v4].no);
782                                 normal_short_to_float_v3(&varray[start + 15], mvert[f->v1].no);
783                         }
784                 }
785                 else if (nors) {
786                         /* copy cached face normal */
787                         copy_v3_v3(&varray[start], &nors[i * 3]);
788                         copy_v3_v3(&varray[start + 3], &nors[i * 3]);
789                         copy_v3_v3(&varray[start + 6], &nors[i * 3]);
790
791                         if (f->v4) {
792                                 copy_v3_v3(&varray[start + 9], &nors[i * 3]);
793                                 copy_v3_v3(&varray[start + 12], &nors[i * 3]);
794                                 copy_v3_v3(&varray[start + 15], &nors[i * 3]);
795                         }
796                 }
797                 else {
798                         /* calculate face normal */
799                         if (f->v4)
800                                 normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
801                         else
802                                 normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
803
804                         copy_v3_v3(&varray[start], f_no);
805                         copy_v3_v3(&varray[start + 3], f_no);
806                         copy_v3_v3(&varray[start + 6], f_no);
807
808                         if (f->v4) {
809                                 copy_v3_v3(&varray[start + 9], f_no);
810                                 copy_v3_v3(&varray[start + 12], f_no);
811                                 copy_v3_v3(&varray[start + 15], f_no);
812                         }
813                 }
814         }
815 }
816
817 static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
818 {
819         int start;
820         int i, totface;
821
822         MTFace *mtface;
823         MFace *f;
824
825         if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
826                 return;
827         f = dm->getTessFaceArray(dm);
828                 
829         totface = dm->getNumTessFaces(dm);
830         for (i = 0; i < totface; i++, f++) {
831                 start = index[mat_orig_to_new[f->mat_nr]];
832
833                 /* v1 v2 v3 */
834                 copy_v2_v2(&varray[start], mtface[i].uv[0]);
835                 copy_v2_v2(&varray[start + 2], mtface[i].uv[1]);
836                 copy_v2_v2(&varray[start + 4], mtface[i].uv[2]);
837                 index[mat_orig_to_new[f->mat_nr]] += 6;
838
839                 if (f->v4) {
840                         /* v3 v4 v1 */
841                         copy_v2_v2(&varray[start + 6], mtface[i].uv[2]);
842                         copy_v2_v2(&varray[start + 8], mtface[i].uv[3]);
843                         copy_v2_v2(&varray[start + 10], mtface[i].uv[0]);
844                         index[mat_orig_to_new[f->mat_nr]] += 6;
845                 }
846         }
847 }
848
849
850 static void GPU_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
851 {
852         int start;
853         int i, totface;
854
855         int totmaterial = dm->totmat;
856         MTFace **mtface_base;
857         MTFace *stencil_base;
858         int stencil;
859         MFace *mf;
860
861         /* should have been checked for before, reassert */
862         BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
863         mf = dm->getTessFaceArray(dm);
864         mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
865
866         for (i = 0; i < totmaterial; i++) {
867                 mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
868         }
869
870         stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
871         stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
872
873         totface = dm->getNumTessFaces(dm);
874
875         for (i = 0; i < totface; i++, mf++) {
876                 int mat_i = mf->mat_nr;
877                 start = index[mat_orig_to_new[mat_i]];
878
879                 /* v1 v2 v3 */
880                 copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
881                 copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
882                 copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
883                 copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
884                 copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
885                 copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
886                 index[mat_orig_to_new[mat_i]] += 12;
887
888                 if (mf->v4) {
889                         /* v3 v4 v1 */
890                         copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]);
891                         copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]);
892                         copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]);
893                         copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]);
894                         copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]);
895                         copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]);
896                         index[mat_orig_to_new[mat_i]] += 12;
897                 }
898         }
899
900         MEM_freeN(mtface_base);
901 }
902
903
904 static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
905 {
906         v[0] = col[3];
907         v[1] = col[2];
908         v[2] = col[1];
909 }
910
911 /* treat varray_ as an array of MCol, four MCol's per face */
912 static void GPU_buffer_copy_mcol(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user)
913 {
914         int i, totface;
915         unsigned char *varray = (unsigned char *)varray_;
916         unsigned char *mcol = (unsigned char *)user;
917         MFace *f = dm->getTessFaceArray(dm);
918
919         totface = dm->getNumTessFaces(dm);
920         for (i = 0; i < totface; i++, f++) {
921                 int start = index[mat_orig_to_new[f->mat_nr]];
922
923                 /* v1 v2 v3 */
924                 copy_mcol_uc3(&varray[start], &mcol[i * 16]);
925                 copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]);
926                 copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]);
927                 index[mat_orig_to_new[f->mat_nr]] += 9;
928
929                 if (f->v4) {
930                         /* v3 v4 v1 */
931                         copy_mcol_uc3(&varray[start + 9], &mcol[i * 16 + 8]);
932                         copy_mcol_uc3(&varray[start + 12], &mcol[i * 16 + 12]);
933                         copy_mcol_uc3(&varray[start + 15], &mcol[i * 16]);
934                         index[mat_orig_to_new[f->mat_nr]] += 9;
935                 }
936         }
937 }
938
939 static void GPU_buffer_copy_edge(DerivedMesh *dm, float *varray_, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
940 {
941         MEdge *medge;
942         unsigned int *varray = (unsigned int *)varray_;
943         int i, totedge;
944
945         medge = dm->getEdgeArray(dm);
946         totedge = dm->getNumEdges(dm);
947
948         for (i = 0; i < totedge; i++, medge++) {
949                 varray[i * 2] = dm->drawObject->vert_points[medge->v1].point_index;
950                 varray[i * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
951         }
952 }
953
954 static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
955 {
956         MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
957         int i, j = 0;
958
959         if (!tf)
960                 return;
961
962         for (i = 0; i < dm->numTessFaceData; i++, tf++) {
963                 MFace mf;
964                 dm->getTessFace(dm, i, &mf);
965
966                 copy_v2_v2(&varray[j], tf->uv[0]);
967                 copy_v2_v2(&varray[j + 2], tf->uv[1]);
968
969                 copy_v2_v2(&varray[j + 4], tf->uv[1]);
970                 copy_v2_v2(&varray[j + 6], tf->uv[2]);
971
972                 if (!mf.v4) {
973                         copy_v2_v2(&varray[j + 8], tf->uv[2]);
974                         copy_v2_v2(&varray[j + 10], tf->uv[0]);
975                         j += 12;
976                 }
977                 else {
978                         copy_v2_v2(&varray[j + 8], tf->uv[2]);
979                         copy_v2_v2(&varray[j + 10], tf->uv[3]);
980
981                         copy_v2_v2(&varray[j + 12], tf->uv[3]);
982                         copy_v2_v2(&varray[j + 14], tf->uv[0]);
983                         j += 16;
984                 }
985         }
986 }
987
988 typedef enum {
989         GPU_BUFFER_VERTEX = 0,
990         GPU_BUFFER_NORMAL,
991         GPU_BUFFER_COLOR,
992         GPU_BUFFER_UV,
993         GPU_BUFFER_UV_TEXPAINT,
994         GPU_BUFFER_EDGE,
995         GPU_BUFFER_UVEDGE,
996 } GPUBufferType;
997
998 typedef struct {
999         GPUBufferCopyFunc copy;
1000         GLenum gl_buffer_type;
1001         int vector_size;
1002 } GPUBufferTypeSettings;
1003
1004 const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
1005         {GPU_buffer_copy_vertex, GL_ARRAY_BUFFER_ARB, 3},
1006         {GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
1007         {GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
1008         {GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
1009     {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
1010         {GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
1011         {GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
1012 };
1013
1014 /* get the GPUDrawObject buffer associated with a type */
1015 static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBufferType type)
1016 {
1017         switch (type) {
1018                 case GPU_BUFFER_VERTEX:
1019                         return &gdo->points;
1020                 case GPU_BUFFER_NORMAL:
1021                         return &gdo->normals;
1022                 case GPU_BUFFER_COLOR:
1023                         return &gdo->colors;
1024                 case GPU_BUFFER_UV:
1025                         return &gdo->uv;
1026                 case GPU_BUFFER_UV_TEXPAINT:
1027                         return &gdo->uv_tex;
1028                 case GPU_BUFFER_EDGE:
1029                         return &gdo->edges;
1030                 case GPU_BUFFER_UVEDGE:
1031                         return &gdo->uvedges;
1032                 default:
1033                         return NULL;
1034         }
1035 }
1036
1037 /* get the amount of space to allocate for a buffer of a particular type */
1038 static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
1039 {
1040         switch (type) {
1041                 case GPU_BUFFER_VERTEX:
1042                         return sizeof(float) * 3 * (dm->drawObject->tot_triangle_point + dm->drawObject->tot_loose_point);
1043                 case GPU_BUFFER_NORMAL:
1044                         return sizeof(float) * 3 * dm->drawObject->tot_triangle_point;
1045                 case GPU_BUFFER_COLOR:
1046                         return sizeof(char) * 3 * dm->drawObject->tot_triangle_point;
1047                 case GPU_BUFFER_UV:
1048                         return sizeof(float) * 2 * dm->drawObject->tot_triangle_point;
1049                 case GPU_BUFFER_UV_TEXPAINT:
1050                         return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
1051                 case GPU_BUFFER_EDGE:
1052                         return sizeof(int) * 2 * dm->drawObject->totedge;
1053                 case GPU_BUFFER_UVEDGE:
1054                         /* each face gets 3 points, 3 edges per triangle, and
1055                          * each edge has its own, non-shared coords, so each
1056                          * tri corner needs minimum of 4 floats, quads used
1057                          * less so here we can over allocate and assume all
1058                          * tris. */
1059                         return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
1060                 default:
1061                         return -1;
1062         }
1063 }
1064
1065 /* call gpu_buffer_setup with settings for a particular type of buffer */
1066 static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
1067 {
1068         const GPUBufferTypeSettings *ts;
1069         void *user_data = NULL;
1070         GPUBuffer *buf;
1071
1072         ts = &gpu_buffer_type_settings[type];
1073
1074         /* special handling for MCol and UV buffers */
1075         if (type == GPU_BUFFER_COLOR) {
1076                 if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
1077                         return NULL;
1078         }
1079         else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) {
1080                 if (!DM_get_tessface_data_layer(dm, CD_MTFACE))
1081                         return NULL;
1082         }
1083
1084         buf = gpu_buffer_setup(dm, dm->drawObject, ts->vector_size,
1085                                gpu_buffer_size_from_type(dm, type),
1086                                ts->gl_buffer_type, user_data, ts->copy);
1087
1088         return buf;
1089 }
1090
1091 /* get the buffer of `type', initializing the GPUDrawObject and
1092  * buffer if needed */
1093 static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type)
1094 {
1095         GPUBuffer **buf;
1096
1097         if (!dm->drawObject)
1098                 dm->drawObject = GPU_drawobject_new(dm);
1099
1100         buf = gpu_drawobject_buffer_from_type(dm->drawObject, type);
1101         if (!(*buf))
1102                 *buf = gpu_buffer_setup_type(dm, type);
1103
1104         return *buf;
1105 }
1106
1107 void GPU_vertex_setup(DerivedMesh *dm)
1108 {
1109         if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX))
1110                 return;
1111
1112         glEnableClientState(GL_VERTEX_ARRAY);
1113         if (dm->drawObject->points->use_vbo) {
1114                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
1115                 glVertexPointer(3, GL_FLOAT, 0, 0);
1116         }
1117         else {
1118                 glVertexPointer(3, GL_FLOAT, 0, dm->drawObject->points->pointer);
1119         }
1120         
1121         GLStates |= GPU_BUFFER_VERTEX_STATE;
1122 }
1123
1124 void GPU_normal_setup(DerivedMesh *dm)
1125 {
1126         if (!gpu_buffer_setup_common(dm, GPU_BUFFER_NORMAL))
1127                 return;
1128
1129         glEnableClientState(GL_NORMAL_ARRAY);
1130         if (dm->drawObject->normals->use_vbo) {
1131                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id);
1132                 glNormalPointer(GL_FLOAT, 0, 0);
1133         }
1134         else {
1135                 glNormalPointer(GL_FLOAT, 0, dm->drawObject->normals->pointer);
1136         }
1137
1138         GLStates |= GPU_BUFFER_NORMAL_STATE;
1139 }
1140
1141 void GPU_uv_setup(DerivedMesh *dm)
1142 {
1143         if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV))
1144                 return;
1145
1146         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1147         if (dm->drawObject->uv->use_vbo) {
1148                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
1149                 glTexCoordPointer(2, GL_FLOAT, 0, 0);
1150         }
1151         else {
1152                 glTexCoordPointer(2, GL_FLOAT, 0, dm->drawObject->uv->pointer);
1153         }
1154
1155         GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE;
1156 }
1157
1158 void GPU_texpaint_uv_setup(DerivedMesh *dm)
1159 {
1160         if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV_TEXPAINT))
1161                 return;
1162
1163         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1164         if (dm->drawObject->uv_tex->use_vbo) {
1165                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv_tex->id);
1166                 glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
1167                 glClientActiveTexture(GL_TEXTURE2);
1168                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1169                 glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), BUFFER_OFFSET(2 * sizeof(float)));
1170                 glClientActiveTexture(GL_TEXTURE0);
1171         }
1172         else {
1173                 glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv_tex->pointer);
1174                 glClientActiveTexture(GL_TEXTURE2);
1175                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1176                 glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv_tex->pointer + 2 * sizeof(float));
1177                 glClientActiveTexture(GL_TEXTURE0);
1178         }
1179
1180         GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_2_STATE;
1181 }
1182
1183
1184 void GPU_color_setup(DerivedMesh *dm, int colType)
1185 {
1186         if (!dm->drawObject) {
1187                 /* XXX Not really nice, but we need a valid gpu draw object to set the colType...
1188                  *     Else we would have to add a new param to gpu_buffer_setup_common. */
1189                 dm->drawObject = GPU_drawobject_new(dm);
1190                 dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW;
1191                 dm->drawObject->colType = colType;
1192         }
1193         /* In paint mode, dm may stay the same during stroke, however we still want to update colors!
1194          * Also check in case we changed color type (i.e. which MCol cdlayer we use). */
1195         else if ((dm->dirty & DM_DIRTY_MCOL_UPDATE_DRAW) || (colType != dm->drawObject->colType)) {
1196                 GPUBuffer **buf = gpu_drawobject_buffer_from_type(dm->drawObject, GPU_BUFFER_COLOR);
1197                 /* XXX Freeing this buffer is a bit stupid, as geometry has not changed, size should remain the same.
1198                  *     Not sure though it would be worth defining a sort of gpu_buffer_update func - nor whether
1199                  *     it is even possible ! */
1200                 GPU_buffer_free(*buf);
1201                 *buf = NULL;
1202                 dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW;
1203                 dm->drawObject->colType = colType;
1204         }
1205
1206         if (!gpu_buffer_setup_common(dm, GPU_BUFFER_COLOR))
1207                 return;
1208
1209         glEnableClientState(GL_COLOR_ARRAY);
1210         if (dm->drawObject->colors->use_vbo) {
1211                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->colors->id);
1212                 glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
1213         }
1214         else {
1215                 glColorPointer(3, GL_UNSIGNED_BYTE, 0, dm->drawObject->colors->pointer);
1216         }
1217
1218         GLStates |= GPU_BUFFER_COLOR_STATE;
1219 }
1220
1221 void GPU_edge_setup(DerivedMesh *dm)
1222 {
1223         if (!gpu_buffer_setup_common(dm, GPU_BUFFER_EDGE))
1224                 return;
1225
1226         if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX))
1227                 return;
1228
1229         glEnableClientState(GL_VERTEX_ARRAY);
1230         if (dm->drawObject->points->use_vbo) {
1231                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
1232                 glVertexPointer(3, GL_FLOAT, 0, 0);
1233         }
1234         else {
1235                 glVertexPointer(3, GL_FLOAT, 0, dm->drawObject->points->pointer);
1236         }
1237         
1238         GLStates |= GPU_BUFFER_VERTEX_STATE;
1239
1240         if (dm->drawObject->edges->use_vbo)
1241                 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->edges->id);
1242
1243         GLStates |= GPU_BUFFER_ELEMENT_STATE;
1244 }
1245
1246 void GPU_uvedge_setup(DerivedMesh *dm)
1247 {
1248         if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UVEDGE))
1249                 return;
1250
1251         glEnableClientState(GL_VERTEX_ARRAY);
1252         if (dm->drawObject->uvedges->use_vbo) {
1253                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uvedges->id);
1254                 glVertexPointer(2, GL_FLOAT, 0, 0);
1255         }
1256         else {
1257                 glVertexPointer(2, GL_FLOAT, 0, dm->drawObject->uvedges->pointer);
1258         }
1259         
1260         GLStates |= GPU_BUFFER_VERTEX_STATE;
1261 }
1262
1263 static int GPU_typesize(int type)
1264 {
1265         switch (type) {
1266                 case GL_FLOAT:
1267                         return sizeof(float);
1268                 case GL_INT:
1269                         return sizeof(int);
1270                 case GL_UNSIGNED_INT:
1271                         return sizeof(unsigned int);
1272                 case GL_BYTE:
1273                         return sizeof(char);
1274                 case GL_UNSIGNED_BYTE:
1275                         return sizeof(unsigned char);
1276                 default:
1277                         return 0;
1278         }
1279 }
1280
1281 int GPU_attrib_element_size(GPUAttrib data[], int numdata)
1282 {
1283         int i, elementsize = 0;
1284
1285         for (i = 0; i < numdata; i++) {
1286                 int typesize = GPU_typesize(data[i].type);
1287                 if (typesize != 0)
1288                         elementsize += typesize * data[i].size;
1289         }
1290         return elementsize;
1291 }
1292
1293 void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata)
1294 {
1295         int i;
1296         int elementsize;
1297         intptr_t offset = 0;
1298         char *basep;
1299
1300         for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
1301                 if (attribData[i].index != -1) {
1302                         glDisableVertexAttribArrayARB(attribData[i].index);
1303                 }
1304                 else
1305                         break;
1306         }
1307         elementsize = GPU_attrib_element_size(data, numdata);
1308
1309         if (buffer->use_vbo) {
1310                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
1311                 basep = NULL;
1312         }
1313         else {
1314                 basep = buffer->pointer;
1315         }
1316         
1317         for (i = 0; i < numdata; i++) {
1318                 glEnableVertexAttribArrayARB(data[i].index);
1319                 glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
1320                                          GL_FALSE, elementsize, (void *)(basep + offset));
1321                 offset += data[i].size * GPU_typesize(data[i].type);
1322                 
1323                 attribData[i].index = data[i].index;
1324                 attribData[i].size = data[i].size;
1325                 attribData[i].type = data[i].type;
1326         }
1327         
1328         attribData[numdata].index = -1; 
1329 }
1330
1331
1332 void GPU_buffer_unbind(void)
1333 {
1334         int i;
1335
1336         if (GLStates & GPU_BUFFER_VERTEX_STATE)
1337                 glDisableClientState(GL_VERTEX_ARRAY);
1338         if (GLStates & GPU_BUFFER_NORMAL_STATE)
1339                 glDisableClientState(GL_NORMAL_ARRAY);
1340         if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_0_STATE)
1341                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1342         if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_2_STATE) {
1343                 glClientActiveTexture(GL_TEXTURE2);
1344                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1345                 glClientActiveTexture(GL_TEXTURE0);
1346         }
1347         if (GLStates & GPU_BUFFER_COLOR_STATE)
1348                 glDisableClientState(GL_COLOR_ARRAY);
1349         if (GLStates & GPU_BUFFER_ELEMENT_STATE) {
1350                 /* not guaranteed we used VBOs but in that case it's just a no-op */
1351                 if (GLEW_ARB_vertex_buffer_object) {
1352                         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1353                 }
1354         }
1355         GLStates &= ~(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE |
1356                       GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_2_STATE |
1357                       GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE);
1358
1359         for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
1360                 if (attribData[i].index != -1) {
1361                         glDisableVertexAttribArrayARB(attribData[i].index);
1362                 }
1363                 else
1364                         break;
1365         }
1366
1367         /* not guaranteed we used VBOs but in that case it's just a no-op */
1368         if (GLEW_ARB_vertex_buffer_object)
1369                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1370 }
1371
1372 void GPU_color_switch(int mode)
1373 {
1374         if (mode) {
1375                 if (!(GLStates & GPU_BUFFER_COLOR_STATE))
1376                         glEnableClientState(GL_COLOR_ARRAY);
1377                 GLStates |= GPU_BUFFER_COLOR_STATE;
1378         }
1379         else {
1380                 if (GLStates & GPU_BUFFER_COLOR_STATE)
1381                         glDisableClientState(GL_COLOR_ARRAY);
1382                 GLStates &= ~GPU_BUFFER_COLOR_STATE;
1383         }
1384 }
1385
1386 void *GPU_buffer_lock(GPUBuffer *buffer)
1387 {
1388         float *varray;
1389
1390         if (!buffer)
1391                 return 0;
1392
1393         if (buffer->use_vbo) {
1394                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
1395                 varray = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1396                 return varray;
1397         }
1398         else {
1399                 return buffer->pointer;
1400         }
1401 }
1402
1403 void *GPU_buffer_lock_stream(GPUBuffer *buffer)
1404 {
1405         float *varray;
1406
1407         if (!buffer)
1408                 return 0;
1409
1410         if (buffer->use_vbo) {
1411                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
1412                 /* discard previous data, avoid stalling gpu */
1413                 glBufferDataARB(GL_ARRAY_BUFFER_ARB, buffer->size, 0, GL_STREAM_DRAW_ARB);
1414                 varray = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1415                 return varray;
1416         }
1417         else {
1418                 return buffer->pointer;
1419         }
1420 }
1421
1422 void GPU_buffer_unlock(GPUBuffer *buffer)
1423 {
1424         if (buffer->use_vbo) {
1425                 /* note: this operation can fail, could return
1426                  * an error code from this function? */
1427                 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
1428                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1429         }
1430 }
1431
1432 /* used for drawing edges */
1433 void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count)
1434 {
1435         glDrawElements(mode, count, GL_UNSIGNED_INT,
1436                        (elements->use_vbo ?
1437                         (void *)(start * sizeof(unsigned int)) :
1438                         ((int *)elements->pointer) + start));
1439 }
1440
1441
1442 /* XXX: the rest of the code in this file is used for optimized PBVH
1443  * drawing and doesn't interact at all with the buffer code above */
1444
1445 /* Return false if VBO is either unavailable or disabled by the user,
1446  * true otherwise */
1447 static int gpu_vbo_enabled(void)
1448 {
1449         return (GLEW_ARB_vertex_buffer_object &&
1450                 !(U.gameflags & USER_DISABLE_VBO));
1451 }
1452
1453 /* Convenience struct for building the VBO. */
1454 typedef struct {
1455         float co[3];
1456         short no[3];
1457
1458         /* inserting this to align the 'color' field to a four-byte
1459          * boundary; drastically increases viewport performance on my
1460          * drivers (Gallium/Radeon) --nicholasbishop */
1461         char pad[2];
1462         
1463         unsigned char color[3];
1464 } VertexBufferFormat;
1465
1466 struct GPU_PBVH_Buffers {
1467         /* opengl buffer handles */
1468         GLuint vert_buf, index_buf;
1469         GLenum index_type;
1470
1471         /* mesh pointers in case buffer allocation fails */
1472         MFace *mface;
1473         MVert *mvert;
1474         const int *face_indices;
1475         int totface;
1476         const float *vmask;
1477
1478         /* grid pointers */
1479         CCGKey gridkey;
1480         CCGElem **grids;
1481         const DMFlagMat *grid_flag_mats;
1482         BLI_bitmap * const *grid_hidden;
1483         const int *grid_indices;
1484         int totgrid;
1485         int has_hidden;
1486
1487         int use_bmesh;
1488
1489         unsigned int tot_tri, tot_quad;
1490
1491         /* The PBVH ensures that either all faces in the node are
1492          * smooth-shaded or all faces are flat-shaded */
1493         int smooth;
1494
1495         bool show_diffuse_color;
1496         bool use_matcaps;
1497         float diffuse_color[4];
1498 };
1499 typedef enum {
1500         VBO_ENABLED,
1501         VBO_DISABLED
1502 } VBO_State;
1503
1504 static void gpu_colors_enable(VBO_State vbo_state)
1505 {
1506         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1507         glEnable(GL_COLOR_MATERIAL);
1508         if (vbo_state == VBO_ENABLED)
1509                 glEnableClientState(GL_COLOR_ARRAY);
1510 }
1511
1512 static void gpu_colors_disable(VBO_State vbo_state)
1513 {
1514         glDisable(GL_COLOR_MATERIAL);
1515         if (vbo_state == VBO_ENABLED)
1516                 glDisableClientState(GL_COLOR_ARRAY);
1517 }
1518
1519 static float gpu_color_from_mask(float mask)
1520 {
1521         return 1.0f - mask * 0.75f;
1522 }
1523
1524 static void gpu_color_from_mask_copy(float mask, const float diffuse_color[4], unsigned char out[3])
1525 {
1526         float mask_color;
1527
1528         mask_color = gpu_color_from_mask(mask) * 255.0f;
1529
1530         out[0] = diffuse_color[0] * mask_color;
1531         out[1] = diffuse_color[1] * mask_color;
1532         out[2] = diffuse_color[2] * mask_color;
1533 }
1534
1535 static void gpu_color_from_mask_set(float mask, float diffuse_color[4])
1536 {
1537         float color = gpu_color_from_mask(mask);
1538         glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color);
1539 }
1540
1541 static float gpu_color_from_mask_quad(const CCGKey *key,
1542                                       CCGElem *a, CCGElem *b,
1543                                       CCGElem *c, CCGElem *d)
1544 {
1545         return gpu_color_from_mask((*CCG_elem_mask(key, a) +
1546                                     *CCG_elem_mask(key, b) +
1547                                     *CCG_elem_mask(key, c) +
1548                                     *CCG_elem_mask(key, d)) * 0.25f);
1549 }
1550
1551 static void gpu_color_from_mask_quad_copy(const CCGKey *key,
1552                                           CCGElem *a, CCGElem *b,
1553                                           CCGElem *c, CCGElem *d,
1554                                           const float *diffuse_color,
1555                                           unsigned char out[3])
1556 {
1557         float mask_color =
1558             gpu_color_from_mask((*CCG_elem_mask(key, a) +
1559                                  *CCG_elem_mask(key, b) +
1560                                  *CCG_elem_mask(key, c) +
1561                                  *CCG_elem_mask(key, d)) * 0.25f) * 255.0f;
1562
1563         out[0] = diffuse_color[0] * mask_color;
1564         out[1] = diffuse_color[1] * mask_color;
1565         out[2] = diffuse_color[2] * mask_color;
1566 }
1567
1568 static void gpu_color_from_mask_quad_set(const CCGKey *key,
1569                                          CCGElem *a, CCGElem *b,
1570                                          CCGElem *c, CCGElem *d,
1571                                          const float diffuse_color[4])
1572 {
1573         float color = gpu_color_from_mask_quad(key, a, b, c, d);
1574         glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color);
1575 }
1576
1577 void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
1578                              int *vert_indices, int totvert, const float *vmask,
1579                              int (*face_vert_indices)[4], bool show_diffuse_color)
1580 {
1581         VertexBufferFormat *vert_data;
1582         int i, j, k;
1583
1584         buffers->vmask = vmask;
1585         buffers->show_diffuse_color = show_diffuse_color;
1586         buffers->use_matcaps = GPU_material_use_matcaps_get();
1587
1588         if (buffers->vert_buf) {
1589                 int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3));
1590                 float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 0.8f};
1591
1592                 if (buffers->use_matcaps)
1593                         diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
1594                 else if (show_diffuse_color) {
1595                         MFace *f = buffers->mface + buffers->face_indices[0];
1596
1597                         GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
1598                 }
1599
1600                 copy_v4_v4(buffers->diffuse_color, diffuse_color);
1601
1602                 /* Build VBO */
1603                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
1604                 glBufferDataARB(GL_ARRAY_BUFFER_ARB,
1605                                                 sizeof(VertexBufferFormat) * totelem,
1606                                                 NULL, GL_STATIC_DRAW_ARB);
1607
1608                 vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1609
1610                 if (vert_data) {
1611                         /* Vertex data is shared if smooth-shaded, but separate
1612                          * copies are made for flat shading because normals
1613                          * shouldn't be shared. */
1614                         if (buffers->smooth) {
1615                                 for (i = 0; i < totvert; ++i) {
1616                                         MVert *v = mvert + vert_indices[i];
1617                                         VertexBufferFormat *out = vert_data + i;
1618
1619                                         copy_v3_v3(out->co, v->co);
1620                                         memcpy(out->no, v->no, sizeof(short) * 3);
1621                                 }
1622
1623 #define UPDATE_VERTEX(face, vertex, index, diffuse_color) \
1624                                 { \
1625                                         VertexBufferFormat *out = vert_data + face_vert_indices[face][index]; \
1626                                         if (vmask) \
1627                                                 gpu_color_from_mask_copy(vmask[vertex], diffuse_color, out->color); \
1628                                         else \
1629                                                 rgb_float_to_uchar(out->color, diffuse_color); \
1630                                 } (void)0
1631
1632                                 for (i = 0; i < buffers->totface; i++) {
1633                                         MFace *f = buffers->mface + buffers->face_indices[i];
1634
1635                                         UPDATE_VERTEX(i, f->v1, 0, diffuse_color);
1636                                         UPDATE_VERTEX(i, f->v2, 1, diffuse_color);
1637                                         UPDATE_VERTEX(i, f->v3, 2, diffuse_color);
1638                                         if (f->v4)
1639                                                 UPDATE_VERTEX(i, f->v4, 3, diffuse_color);
1640                                 }
1641 #undef UPDATE_VERTEX
1642                         }
1643                         else {
1644                                 for (i = 0; i < buffers->totface; ++i) {
1645                                         const MFace *f = &buffers->mface[buffers->face_indices[i]];
1646                                         const unsigned int *fv = &f->v1;
1647                                         const int vi[2][3] = {{0, 1, 2}, {3, 0, 2}};
1648                                         float fno[3];
1649                                         short no[3];
1650
1651                                         float fmask;
1652
1653                                         if (paint_is_face_hidden(f, mvert))
1654                                                 continue;
1655
1656                                         /* Face normal and mask */
1657                                         if (f->v4) {
1658                                                 normal_quad_v3(fno,
1659                                                                            mvert[fv[0]].co,
1660                                                                            mvert[fv[1]].co,
1661                                                                            mvert[fv[2]].co,
1662                                                                            mvert[fv[3]].co);
1663                                                 if (vmask) {
1664                                                         fmask = (vmask[fv[0]] +
1665                                                                          vmask[fv[1]] +
1666                                                                          vmask[fv[2]] +
1667                                                                          vmask[fv[3]]) * 0.25f;
1668                                                 }
1669                                         }
1670                                         else {
1671                                                 normal_tri_v3(fno,
1672                                                                           mvert[fv[0]].co,
1673                                                                           mvert[fv[1]].co,
1674                                                                           mvert[fv[2]].co);
1675                                                 if (vmask) {
1676                                                         fmask = (vmask[fv[0]] +
1677                                                                          vmask[fv[1]] +
1678                                                                          vmask[fv[2]]) / 3.0f;
1679                                                 }
1680                                         }
1681                                         normal_float_to_short_v3(no, fno);
1682
1683                                         for (j = 0; j < (f->v4 ? 2 : 1); j++) {
1684                                                 for (k = 0; k < 3; k++) {
1685                                                         const MVert *v = &mvert[fv[vi[j][k]]];
1686                                                         VertexBufferFormat *out = vert_data;
1687
1688                                                         copy_v3_v3(out->co, v->co);
1689                                                         memcpy(out->no, no, sizeof(short) * 3);
1690
1691                                                         if (vmask)
1692                                                                 gpu_color_from_mask_copy(fmask, diffuse_color, out->color);
1693                                                         else
1694                                                                 rgb_float_to_uchar(out->color, diffuse_color);
1695
1696                                                         vert_data++;
1697                                                 }
1698                                         }
1699                                 }
1700                         }
1701
1702                         glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
1703                 }
1704                 else {
1705                         glDeleteBuffersARB(1, &buffers->vert_buf);
1706                         buffers->vert_buf = 0;
1707                 }
1708
1709                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1710         }
1711
1712         buffers->mvert = mvert;
1713 }
1714
1715 GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
1716                                     MFace *mface, MVert *mvert,
1717                                     int *face_indices,
1718                                     int totface)
1719 {
1720         GPU_PBVH_Buffers *buffers;
1721         unsigned short *tri_data;
1722         int i, j, k, tottri;
1723
1724         buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
1725         buffers->index_type = GL_UNSIGNED_SHORT;
1726         buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH;
1727
1728         buffers->show_diffuse_color = false;
1729         buffers->use_matcaps = false;
1730
1731         /* Count the number of visible triangles */
1732         for (i = 0, tottri = 0; i < totface; ++i) {
1733                 const MFace *f = &mface[face_indices[i]];
1734                 if (!paint_is_face_hidden(f, mvert))
1735                         tottri += f->v4 ? 2 : 1;
1736         }
1737
1738         if (tottri == 0) {
1739                 buffers->tot_tri = 0;
1740
1741                 buffers->mface = mface;
1742                 buffers->face_indices = face_indices;
1743                 buffers->totface = 0;
1744
1745                 return buffers;
1746         }
1747
1748         /* An element index buffer is used for smooth shading, but flat
1749          * shading requires separate vertex normals so an index buffer is
1750          * can't be used there. */
1751         if (gpu_vbo_enabled() && buffers->smooth)
1752                 glGenBuffersARB(1, &buffers->index_buf);
1753
1754         if (buffers->index_buf) {
1755                 /* Generate index buffer object */
1756                 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
1757                 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
1758                                 sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB);
1759
1760                 /* Fill the triangle buffer */
1761                 tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1762                 if (tri_data) {
1763                         for (i = 0; i < totface; ++i) {
1764                                 const MFace *f = mface + face_indices[i];
1765                                 int v[3];
1766
1767                                 /* Skip hidden faces */
1768                                 if (paint_is_face_hidden(f, mvert))
1769                                         continue;
1770
1771                                 v[0] = 0;
1772                                 v[1] = 1;
1773                                 v[2] = 2;
1774
1775                                 for (j = 0; j < (f->v4 ? 2 : 1); ++j) {
1776                                         for (k = 0; k < 3; ++k) {
1777                                                 *tri_data = face_vert_indices[i][v[k]];
1778                                                 tri_data++;
1779                                         }
1780                                         v[0] = 3;
1781                                         v[1] = 0;
1782                                         v[2] = 2;
1783                                 }
1784                         }
1785                         glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
1786                 }
1787                 else {
1788                         glDeleteBuffersARB(1, &buffers->index_buf);
1789                         buffers->index_buf = 0;
1790                 }
1791
1792                 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1793         }
1794
1795         if (gpu_vbo_enabled() && (buffers->index_buf || !buffers->smooth))
1796                 glGenBuffersARB(1, &buffers->vert_buf);
1797
1798         buffers->tot_tri = tottri;
1799
1800         buffers->mface = mface;
1801         buffers->face_indices = face_indices;
1802         buffers->totface = totface;
1803
1804         return buffers;
1805 }
1806
1807 void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
1808                              const DMFlagMat *grid_flag_mats, int *grid_indices,
1809                              int totgrid, const CCGKey *key, bool show_diffuse_color)
1810 {
1811         VertexBufferFormat *vert_data;
1812         int i, j, k, x, y;
1813
1814         buffers->show_diffuse_color = show_diffuse_color;
1815         buffers->use_matcaps = GPU_material_use_matcaps_get();
1816
1817         /* Build VBO */
1818         if (buffers->vert_buf) {
1819                 int totvert = key->grid_area * totgrid;
1820                 int smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
1821                 const int has_mask = key->has_mask;
1822                 float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
1823
1824                 if (buffers->use_matcaps)
1825                         diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
1826                 else if (show_diffuse_color) {
1827                         const DMFlagMat *flags = &grid_flag_mats[grid_indices[0]];
1828
1829                         GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
1830                 }
1831
1832                 copy_v4_v4(buffers->diffuse_color, diffuse_color);
1833
1834                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
1835                 glBufferDataARB(GL_ARRAY_BUFFER_ARB,
1836                                 sizeof(VertexBufferFormat) * totvert,
1837                                 NULL, GL_STATIC_DRAW_ARB);
1838                 vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1839                 if (vert_data) {
1840                         for (i = 0; i < totgrid; ++i) {
1841                                 VertexBufferFormat *vd = vert_data;
1842                                 CCGElem *grid = grids[grid_indices[i]];
1843
1844                                 for (y = 0; y < key->grid_size; y++) {
1845                                         for (x = 0; x < key->grid_size; x++) {
1846                                                 CCGElem *elem = CCG_grid_elem(key, grid, x, y);
1847                                                 
1848                                                 copy_v3_v3(vd->co, CCG_elem_co(key, elem));
1849                                                 if (smooth) {
1850                                                         normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem));
1851
1852                                                         if (has_mask) {
1853                                                                 gpu_color_from_mask_copy(*CCG_elem_mask(key, elem),
1854                                                                                          diffuse_color, vd->color);
1855                                                         }
1856                                                 }
1857                                                 vd++;
1858                                         }
1859                                 }
1860                                 
1861                                 if (!smooth) {
1862                                         /* for flat shading, recalc normals and set the last vertex of
1863                                          * each triangle in the index buffer to have the flat normal as
1864                                          * that is what opengl will use */
1865                                         for (j = 0; j < key->grid_size - 1; j++) {
1866                                                 for (k = 0; k < key->grid_size - 1; k++) {
1867                                                         CCGElem *elems[4] = {
1868                                                                 CCG_grid_elem(key, grid, k, j + 1),
1869                                                                 CCG_grid_elem(key, grid, k + 1, j + 1),
1870                                                                 CCG_grid_elem(key, grid, k + 1, j),
1871                                                                 CCG_grid_elem(key, grid, k, j)
1872                                                         };
1873                                                         float fno[3];
1874
1875                                                         normal_quad_v3(fno,
1876                                                                        CCG_elem_co(key, elems[0]),
1877                                                                        CCG_elem_co(key, elems[1]),
1878                                                                        CCG_elem_co(key, elems[2]),
1879                                                                        CCG_elem_co(key, elems[3]));
1880
1881                                                         vd = vert_data + (j + 1) * key->grid_size + k;
1882                                                         normal_float_to_short_v3(vd->no, fno);
1883
1884                                                         if (has_mask) {
1885                                                                 gpu_color_from_mask_quad_copy(key,
1886                                                                                               elems[0],
1887                                                                                               elems[1],
1888                                                                                               elems[2],
1889                                                                                               elems[3],
1890                                                                                               diffuse_color,
1891                                                                                               vd->color);
1892                                                         }
1893                                                 }
1894                                         }
1895                                 }
1896
1897                                 vert_data += key->grid_area;
1898                         }
1899                         glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
1900                 }
1901                 else {
1902                         glDeleteBuffersARB(1, &buffers->vert_buf);
1903                         buffers->vert_buf = 0;
1904                 }
1905                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1906         }
1907
1908         buffers->grids = grids;
1909         buffers->grid_indices = grid_indices;
1910         buffers->totgrid = totgrid;
1911         buffers->grid_flag_mats = grid_flag_mats;
1912         buffers->gridkey = *key;
1913
1914         buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
1915
1916         //printf("node updated %p\n", buffers);
1917 }
1918
1919 /* Build the element array buffer of grid indices using either
1920  * unsigned shorts or unsigned ints. */
1921 #define FILL_QUAD_BUFFER(type_, tot_quad_, buffer_)                     \
1922         {                                                                   \
1923                 type_ *tri_data;                                               \
1924                 int offset = 0;                                                 \
1925                 int i, j, k;                                                    \
1926                                                                                 \
1927                 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,                    \
1928                                                 sizeof(type_) * (tot_quad_) * 6, NULL,          \
1929                                 GL_STATIC_DRAW_ARB);                            \
1930                                                                                 \
1931                 /* Fill the buffer */                                      \
1932                 tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,         \
1933                                            GL_WRITE_ONLY_ARB);                  \
1934                 if (tri_data) {                                                \
1935                         for (i = 0; i < totgrid; ++i) {                             \
1936                                 BLI_bitmap *gh = NULL;                                  \
1937                                 if (grid_hidden)                                        \
1938                                         gh = grid_hidden[(grid_indices)[i]];                \
1939                                                                                                                                                 \
1940                                 for (j = 0; j < gridsize - 1; ++j) {                    \
1941                                         for (k = 0; k < gridsize - 1; ++k) {                \
1942                                                 /* Skip hidden grid face */                     \
1943                                                 if (gh &&                                       \
1944                                                     paint_is_grid_face_hidden(gh,               \
1945                                                                               gridsize, k, j))  \
1946                                                         continue;                                   \
1947                                                                                                                                                 \
1948                                                 *(tri_data++) = offset + j * gridsize + k + 1; \
1949                                                 *(tri_data++) = offset + j * gridsize + k;     \
1950                                                 *(tri_data++) = offset + (j + 1) * gridsize + k; \
1951                                                                                                                                                 \
1952                                                 *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \
1953                                                 *(tri_data++) = offset + j * gridsize + k + 1; \
1954                                                 *(tri_data++) = offset + (j + 1) * gridsize + k; \
1955                                         }                                                   \
1956                                 }                                                       \
1957                                                                                                                                                 \
1958                                 offset += gridsize * gridsize;                          \
1959                         }                                                           \
1960                         glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);              \
1961                 }                                                               \
1962                 else {                                                          \
1963                         glDeleteBuffersARB(1, &(buffer_));                          \
1964                         (buffer_) = 0;                                              \
1965                 }                                                               \
1966         } (void)0
1967 /* end FILL_QUAD_BUFFER */
1968
1969 static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad)
1970 {
1971         static int prev_gridsize = -1;
1972         static GLenum prev_index_type = 0;
1973         static GLuint buffer = 0;
1974         static unsigned prev_totquad;
1975
1976         /* used in the FILL_QUAD_BUFFER macro */
1977         BLI_bitmap * const *grid_hidden = NULL;
1978         const int *grid_indices = NULL;
1979         int totgrid = 1;
1980
1981         /* VBO is disabled; delete the previous buffer (if it exists) and
1982          * return an invalid handle */
1983         if (!gpu_vbo_enabled()) {
1984                 if (buffer)
1985                         glDeleteBuffersARB(1, &buffer);
1986                 return 0;
1987         }
1988
1989         /* VBO is already built */
1990         if (buffer && prev_gridsize == gridsize) {
1991                 *index_type = prev_index_type;
1992                 *totquad = prev_totquad;
1993                 return buffer;
1994         }
1995
1996         /* Build new VBO */
1997         glGenBuffersARB(1, &buffer);
1998         if (buffer) {
1999                 *totquad = (gridsize - 1) * (gridsize - 1);
2000
2001                 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer);
2002
2003                 if (gridsize * gridsize < USHRT_MAX) {
2004                         *index_type = GL_UNSIGNED_SHORT;
2005                         FILL_QUAD_BUFFER(unsigned short, *totquad, buffer);
2006                 }
2007                 else {
2008                         *index_type = GL_UNSIGNED_INT;
2009                         FILL_QUAD_BUFFER(unsigned int, *totquad, buffer);
2010                 }
2011
2012                 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
2013         }
2014
2015         prev_gridsize = gridsize;
2016         prev_index_type = *index_type;
2017         prev_totquad = *totquad;
2018         return buffer;
2019 }
2020
2021 GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
2022                                                                                           BLI_bitmap **grid_hidden, int gridsize)
2023 {
2024         GPU_PBVH_Buffers *buffers;
2025         int totquad;
2026         int fully_visible_totquad = (gridsize - 1) * (gridsize - 1) * totgrid;
2027
2028         buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
2029         buffers->grid_hidden = grid_hidden;
2030         buffers->totgrid = totgrid;
2031
2032         buffers->show_diffuse_color = false;
2033         buffers->use_matcaps = false;
2034
2035         /* Count the number of quads */
2036         totquad = BKE_pbvh_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize);
2037
2038         /* totally hidden node, return here to avoid BufferData with zero below. */
2039         if (totquad == 0)
2040                 return buffers;
2041
2042         if (totquad == fully_visible_totquad) {
2043                 buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad);
2044                 buffers->has_hidden = 0;
2045         }
2046         else if (GLEW_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO)) {
2047                 /* Build new VBO */
2048                 glGenBuffersARB(1, &buffers->index_buf);
2049                 if (buffers->index_buf) {
2050                         buffers->tot_quad = totquad;
2051
2052                         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
2053
2054                         if (totgrid * gridsize * gridsize < USHRT_MAX) {
2055                                 buffers->index_type = GL_UNSIGNED_SHORT;
2056                                 FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf);
2057                         }
2058                         else {
2059                                 buffers->index_type = GL_UNSIGNED_INT;
2060                                 FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf);
2061                         }
2062
2063                         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
2064                 }
2065
2066                 buffers->has_hidden = 1;
2067         }
2068
2069         /* Build coord/normal VBO */
2070         if (buffers->index_buf)
2071                 glGenBuffersARB(1, &buffers->vert_buf);
2072
2073         return buffers;
2074 }
2075
2076 #undef FILL_QUAD_BUFFER
2077
2078 /* Output a BMVert into a VertexBufferFormat array
2079  *
2080  * The vertex is skipped if hidden, otherwise the output goes into
2081  * index '*v_index' in the 'vert_data' array and '*v_index' is
2082  * incremented.
2083  */
2084 static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
2085                                           VertexBufferFormat *vert_data,
2086                                           int *v_index,
2087                                           const float fno[3],
2088                                           const float *fmask,
2089                                           const int cd_vert_mask_offset,
2090                                           const float diffuse_color[4])
2091 {
2092         if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
2093                 VertexBufferFormat *vd = &vert_data[*v_index];
2094
2095                 /* Set coord, normal, and mask */
2096                 copy_v3_v3(vd->co, v->co);
2097                 normal_float_to_short_v3(vd->no, fno ? fno : v->no);
2098
2099                 gpu_color_from_mask_copy(
2100                         fmask ? *fmask :
2101                                 BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset),
2102                         diffuse_color,
2103                         vd->color);
2104                 
2105
2106                 /* Assign index for use in the triangle index buffer */
2107                 /* note: caller must set:  bm->elem_index_dirty |= BM_VERT; */
2108                 BM_elem_index_set(v, (*v_index)); /* set_dirty! */
2109
2110                 (*v_index)++;
2111         }
2112 }
2113
2114 /* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */
2115 static int gpu_bmesh_vert_visible_count(GSet *bm_unique_verts,
2116                                         GSet *bm_other_verts)
2117 {
2118         GSetIterator gs_iter;
2119         int totvert = 0;
2120
2121         GSET_ITER (gs_iter, bm_unique_verts) {
2122                 BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
2123                 if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
2124                         totvert++;
2125         }
2126         GSET_ITER (gs_iter, bm_other_verts) {
2127                 BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
2128                 if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
2129                         totvert++;
2130         }
2131
2132         return totvert;
2133 }
2134
2135 /* Return the total number of visible faces */
2136 static int gpu_bmesh_face_visible_count(GSet *bm_faces)
2137 {
2138         GSetIterator gh_iter;
2139         int totface = 0;
2140
2141         GSET_ITER (gh_iter, bm_faces) {
2142                 BMFace *f = BLI_gsetIterator_getKey(&gh_iter);
2143
2144                 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN))
2145                         totface++;
2146         }
2147
2148         return totface;
2149 }
2150
2151 /* Creates a vertex buffer (coordinate, normal, color) and, if smooth
2152  * shading, an element index buffer. */
2153 void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
2154                               BMesh *bm,
2155                               GSet *bm_faces,
2156                               GSet *bm_unique_verts,
2157                               GSet *bm_other_verts,
2158                               bool show_diffuse_color)
2159 {
2160         VertexBufferFormat *vert_data;
2161         void *tri_data;
2162         int tottri, totvert, maxvert = 0;
2163         float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
2164
2165         /* TODO, make mask layer optional for bmesh buffer */
2166         const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
2167
2168         buffers->show_diffuse_color = show_diffuse_color;
2169         buffers->use_matcaps = GPU_material_use_matcaps_get();
2170
2171         if (!buffers->vert_buf || (buffers->smooth && !buffers->index_buf))
2172                 return;
2173
2174         /* Count visible triangles */
2175         tottri = gpu_bmesh_face_visible_count(bm_faces);
2176
2177         if (buffers->smooth) {
2178                 /* Count visible vertices */
2179                 totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts);
2180         }
2181         else
2182                 totvert = tottri * 3;
2183
2184         if (!tottri) {
2185                 buffers->tot_tri = 0;
2186                 return;
2187         }
2188
2189         if (buffers->use_matcaps)
2190                 diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
2191         else if (show_diffuse_color) {
2192                 /* due to dynamic nature of dyntopo, only get first material */
2193                 GSetIterator gs_iter;
2194                 BMFace *f;
2195                 BLI_gsetIterator_init(&gs_iter, bm_faces);
2196                 f = BLI_gsetIterator_getKey(&gs_iter);
2197                 GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
2198         }
2199
2200         copy_v4_v4(buffers->diffuse_color, diffuse_color);
2201
2202         /* Initialize vertex buffer */
2203         glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
2204         glBufferDataARB(GL_ARRAY_BUFFER_ARB,
2205                                         sizeof(VertexBufferFormat) * totvert,
2206                                         NULL, GL_STATIC_DRAW_ARB);
2207
2208         /* Fill vertex buffer */
2209         vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
2210         if (vert_data) {
2211                 int v_index = 0;
2212
2213                 if (buffers->smooth) {
2214                         GSetIterator gs_iter;
2215
2216                         /* Vertices get an index assigned for use in the triangle
2217                          * index buffer */
2218                         bm->elem_index_dirty |= BM_VERT;
2219
2220                         GSET_ITER (gs_iter, bm_unique_verts) {
2221                                 gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter),
2222                                                               vert_data, &v_index, NULL, NULL,
2223                                                               cd_vert_mask_offset, diffuse_color);
2224                         }
2225
2226                         GSET_ITER (gs_iter, bm_other_verts) {
2227                                 gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter),
2228                                                               vert_data, &v_index, NULL, NULL,
2229                                                               cd_vert_mask_offset, diffuse_color);
2230                         }
2231
2232                         maxvert = v_index;
2233                 }
2234                 else {
2235                         GSetIterator gs_iter;
2236
2237                         GSET_ITER (gs_iter, bm_faces) {
2238                                 BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
2239
2240                                 BLI_assert(f->len == 3);
2241
2242                                 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
2243                                         BMVert *v[3];
2244                                         float fmask = 0;
2245                                         int i;
2246
2247                                         // BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
2248                                         BM_face_as_array_vert_tri(f, v);
2249
2250                                         /* Average mask value */
2251                                         for (i = 0; i < 3; i++) {
2252                                                 fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset);
2253                                         }
2254                                         fmask /= 3.0f;
2255                                         
2256                                         for (i = 0; i < 3; i++) {
2257                                                 gpu_bmesh_vert_to_buffer_copy(v[i], vert_data,
2258                                                                               &v_index, f->no, &fmask,
2259                                                                               cd_vert_mask_offset, diffuse_color);
2260                                         }
2261                                 }
2262                         }
2263
2264                         buffers->tot_tri = tottri;
2265                 }
2266
2267                 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
2268
2269                 /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */
2270                 bm->elem_index_dirty |= BM_VERT;
2271         }
2272         else {
2273                 /* Memory map failed */
2274                 glDeleteBuffersARB(1, &buffers->vert_buf);
2275                 buffers->vert_buf = 0;
2276                 return;
2277         }
2278
2279         if (buffers->smooth) {
2280                 const int use_short = (maxvert < USHRT_MAX);
2281
2282                 /* Initialize triangle index buffer */
2283                 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
2284                 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
2285                                                 (use_short ?
2286                                                  sizeof(unsigned short) :
2287                                                  sizeof(unsigned int)) * 3 * tottri,
2288                                                 NULL, GL_STATIC_DRAW_ARB);
2289
2290                 /* Fill triangle index buffer */
2291                 tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
2292                 if (tri_data) {
2293                         GSetIterator gs_iter;
2294
2295                         GSET_ITER (gs_iter, bm_faces) {
2296                                 BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
2297
2298                                 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
2299                                         BMLoop *l_iter;
2300                                         BMLoop *l_first;
2301
2302                                         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2303                                         do {
2304                                                 BMVert *v = l_iter->v;
2305                                                 if (use_short) {
2306                                                         unsigned short *elem = tri_data;
2307                                                         (*elem) = BM_elem_index_get(v);
2308                                                         elem++;
2309                                                         tri_data = elem;
2310                                                 }
2311                                                 else {
2312                                                         unsigned int *elem = tri_data;
2313                                                         (*elem) = BM_elem_index_get(v);
2314                                                         elem++;
2315                                                         tri_data = elem;
2316                                                 }
2317                                         } while ((l_iter = l_iter->next) != l_first);
2318                                 }
2319                         }
2320
2321                         glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
2322
2323                         buffers->tot_tri = tottri;
2324                         buffers->index_type = (use_short ?
2325                                                                    GL_UNSIGNED_SHORT :
2326                                                                    GL_UNSIGNED_INT);
2327                 }
2328                 else {
2329                         /* Memory map failed */
2330                         glDeleteBuffersARB(1, &buffers->index_buf);
2331                         buffers->index_buf = 0;
2332                 }
2333         }
2334 }
2335
2336 GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading)
2337 {
2338         GPU_PBVH_Buffers *buffers;
2339
2340         buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
2341         if (smooth_shading)
2342                 glGenBuffersARB(1, &buffers->index_buf);
2343         glGenBuffersARB(1, &buffers->vert_buf);
2344         buffers->use_bmesh = true;
2345         buffers->smooth = smooth_shading;
2346         buffers->show_diffuse_color = false;
2347         buffers->use_matcaps = false;
2348
2349         return buffers;
2350 }
2351
2352 static void gpu_draw_buffers_legacy_mesh(GPU_PBVH_Buffers *buffers)
2353 {
2354         const MVert *mvert = buffers->mvert;
2355         int i, j;
2356         const int has_mask = (buffers->vmask != NULL);
2357         const MFace *face = &buffers->mface[buffers->face_indices[0]];
2358         float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
2359
2360         if (buffers->use_matcaps)
2361                 diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
2362         else if (buffers->show_diffuse_color)
2363                 GPU_material_diffuse_get(face->mat_nr + 1, diffuse_color);
2364
2365         if (has_mask) {
2366                 gpu_colors_enable(VBO_DISABLED);
2367         }
2368
2369         for (i = 0; i < buffers->totface; ++i) {
2370                 MFace *f = buffers->mface + buffers->face_indices[i];
2371                 int S = f->v4 ? 4 : 3;
2372                 unsigned int *fv = &f->v1;
2373
2374                 if (paint_is_face_hidden(f, buffers->mvert))
2375                         continue;
2376
2377                 glBegin((f->v4) ? GL_QUADS : GL_TRIANGLES);
2378
2379                 if (buffers->smooth) {
2380                         for (j = 0; j < S; j++) {
2381                                 if (has_mask) {
2382                                         gpu_color_from_mask_set(buffers->vmask[fv[j]], diffuse_color);
2383                                 }
2384                                 glNormal3sv(mvert[fv[j]].no);
2385                                 glVertex3fv(mvert[fv[j]].co);
2386                         }
2387                 }
2388                 else {
2389                         float fno[3];
2390
2391                         /* calculate face normal */
2392                         if (f->v4) {
2393                                 normal_quad_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co,
2394                                                mvert[fv[2]].co, mvert[fv[3]].co);
2395                         }
2396                         else
2397                                 normal_tri_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co, mvert[fv[2]].co);
2398                         glNormal3fv(fno);
2399
2400                         if (has_mask) {
2401                                 float fmask;
2402
2403                                 /* calculate face mask color */
2404                                 fmask = (buffers->vmask[fv[0]] +
2405                                          buffers->vmask[fv[1]] +
2406                                          buffers->vmask[fv[2]]);
2407                                 if (f->v4)
2408                                         fmask = (fmask + buffers->vmask[fv[3]]) * 0.25f;
2409                                 else
2410                                         fmask /= 3.0f;
2411                                 gpu_color_from_mask_set(fmask, diffuse_color);
2412                         }
2413                         
2414                         for (j = 0; j < S; j++)
2415                                 glVertex3fv(mvert[fv[j]].co);
2416                 }
2417                 
2418                 glEnd();
2419         }
2420
2421         if (has_mask) {
2422                 gpu_colors_disable(VBO_DISABLED);
2423         }
2424 }
2425
2426 static void gpu_draw_buffers_legacy_grids(GPU_PBVH_Buffers *buffers)
2427 {
2428         const CCGKey *key = &buffers->gridkey;
2429         int i, j, x, y, gridsize = buffers->gridkey.grid_size;
2430         const int has_mask = key->has_mask;
2431         const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]];
2432         float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
2433
2434         if (buffers->use_matcaps)
2435                 diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
2436         else if (buffers->show_diffuse_color)
2437                 GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
2438
2439         if (has_mask) {
2440                 gpu_colors_enable(VBO_DISABLED);
2441         }
2442
2443         for (i = 0; i < buffers->totgrid; ++i) {
2444                 int g = buffers->grid_indices[i];
2445                 CCGElem *grid = buffers->grids[g];
2446                 BLI_bitmap *gh = buffers->grid_hidden[g];
2447
2448                 /* TODO: could use strips with hiding as well */
2449
2450                 if (gh) {
2451                         glBegin(GL_QUADS);
2452                         
2453                         for (y = 0; y < gridsize - 1; y++) {
2454                                 for (x = 0; x < gridsize - 1; x++) {
2455                                         CCGElem *e[4] = {
2456                                                 CCG_grid_elem(key, grid, x + 1, y + 1),
2457                                                 CCG_grid_elem(key, grid, x + 1, y),
2458                                                 CCG_grid_elem(key, grid, x, y),
2459                                                 CCG_grid_elem(key, grid, x, y + 1)
2460                                         };
2461
2462                                         /* skip face if any of its corners are hidden */
2463                                         if (paint_is_grid_face_hidden(gh, gridsize, x, y))
2464                                                 continue;
2465
2466                                         if (buffers->smooth) {
2467                                                 for (j = 0; j < 4; j++) {
2468                                                         if (has_mask) {
2469                                                                 gpu_color_from_mask_set(*CCG_elem_mask(key, e[j]), diffuse_color);
2470                                                         }
2471                                                         glNormal3fv(CCG_elem_no(key, e[j]));
2472                                                         glVertex3fv(CCG_elem_co(key, e[j]));
2473                                                 }
2474                                         }
2475                                         else {
2476                                                 float fno[3];
2477                                                 normal_quad_v3(fno,
2478                                                                CCG_elem_co(key, e[0]),
2479                                                                CCG_elem_co(key, e[1]),
2480                                                                CCG_elem_co(key, e[2]),
2481                                                                CCG_elem_co(key, e[3]));
2482                                                 glNormal3fv(fno);
2483
2484                                                 if (has_mask) {
2485                                                         gpu_color_from_mask_quad_set(key, e[0], e[1], e[2], e[3], diffuse_color);
2486                                                 }
2487
2488                                                 for (j = 0; j < 4; j++)
2489                                                         glVertex3fv(CCG_elem_co(key, e[j]));
2490                                         }
2491                                 }
2492                         }
2493
2494                         glEnd();
2495                 }
2496                 else if (buffers->smooth) {
2497                         for (y = 0; y < gridsize - 1; y++) {
2498                                 glBegin(GL_QUAD_STRIP);
2499                                 for (x = 0; x < gridsize; x++) {
2500                                         CCGElem *a = CCG_grid_elem(key, grid, x, y);
2501                                         CCGElem *b = CCG_grid_elem(key, grid, x, y + 1);
2502
2503                                         if (has_mask) {
2504                                                 gpu_color_from_mask_set(*CCG_elem_mask(key, a), diffuse_color);
2505                                         }
2506                                         glNormal3fv(CCG_elem_no(key, a));
2507                                         glVertex3fv(CCG_elem_co(key, a));
2508                                         if (has_mask) {
2509                                                 gpu_color_from_mask_set(*CCG_elem_mask(key, b), diffuse_color);
2510                                         }
2511                                         glNormal3fv(CCG_elem_no(key, b));
2512                                         glVertex3fv(CCG_elem_co(key, b));
2513                                 }
2514                                 glEnd();
2515                         }
2516                 }
2517                 else {
2518                         for (y = 0; y < gridsize - 1; y++) {
2519                                 glBegin(GL_QUAD_STRIP);
2520                                 for (x = 0; x < gridsize; x++) {
2521                                         CCGElem *a = CCG_grid_elem(key, grid, x, y);
2522                                         CCGElem *b = CCG_grid_elem(key, grid, x, y + 1);
2523
2524                                         if (x > 0) {
2525                                                 CCGElem *c = CCG_grid_elem(key, grid, x - 1, y);
2526                                                 CCGElem *d = CCG_grid_elem(key, grid, x - 1, y + 1);
2527
2528                                                 float fno[3];
2529                                                 normal_quad_v3(fno,
2530                                                                CCG_elem_co(key, d),
2531                                                                CCG_elem_co(key, b),
2532                                                                CCG_elem_co(key, a),
2533                                                                CCG_elem_co(key, c));
2534                                                 glNormal3fv(fno);
2535
2536                                                 if (has_mask) {
2537                                                         gpu_color_from_mask_quad_set(key, a, b, c, d, diffuse_color);
2538                                                 }
2539                                         }
2540
2541                                         glVertex3fv(CCG_elem_co(key, a));
2542                                         glVertex3fv(CCG_elem_co(key, b));
2543                                 }
2544                                 glEnd();
2545                         }
2546                 }
2547         }
2548
2549         if (has_mask) {
2550                 gpu_colors_disable(VBO_DISABLED);
2551         }
2552 }
2553
2554 void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
2555                            bool wireframe)
2556 {
2557         /* sets material from the first face, to solve properly face would need to
2558          * be sorted in buckets by materials */
2559         if (setMaterial) {
2560                 if (buffers->totface) {
2561                         const MFace *f = &buffers->mface[buffers->face_indices[0]];
2562                         if (!setMaterial(f->mat_nr + 1, NULL))
2563                                 return;
2564                 }
2565                 else if (buffers->totgrid) {
2566                         const DMFlagMat *f = &buffers->grid_flag_mats[buffers->grid_indices[0]];
2567                         if (!setMaterial(f->mat_nr + 1, NULL))
2568                                 return;
2569                 }
2570                 else {
2571                         if (!setMaterial(1, NULL))
2572                                 return;
2573                 }
2574         }
2575
2576         glShadeModel((buffers->smooth || buffers->totface) ? GL_SMOOTH : GL_FLAT);
2577
2578         if (buffers->vert_buf) {
2579                 glEnableClientState(GL_VERTEX_ARRAY);
2580                 if (!wireframe) {
2581                         glEnableClientState(GL_NORMAL_ARRAY);
2582                         gpu_colors_enable(VBO_ENABLED);
2583                 }
2584
2585                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
2586
2587                 if (buffers->index_buf)
2588                         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
2589
2590                 if (wireframe)
2591                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2592
2593                 if (buffers->tot_quad) {
2594                         const char *offset = 0;
2595                         int i, last = buffers->has_hidden ? 1 : buffers->totgrid;
2596                         for (i = 0; i < last; i++) {
2597                                 glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
2598                                                 offset + offsetof(VertexBufferFormat, co));
2599                                 glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
2600                                                 offset + offsetof(VertexBufferFormat, no));
2601                                 glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
2602                                                offset + offsetof(VertexBufferFormat, color));
2603                                 
2604                                 glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, 0);
2605
2606                                 offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
2607                         }
2608                 }
2609                 else if (buffers->tot_tri) {
2610                         int totelem = buffers->tot_tri * 3;
2611
2612                         glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
2613                                         (void *)offsetof(VertexBufferFormat, co));
2614                         glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
2615                                         (void *)offsetof(VertexBufferFormat, no));
2616                         glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
2617                                        (void *)offsetof(VertexBufferFormat, color));
2618
2619                         if (buffers->index_buf)
2620                                 glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, 0);
2621                         else
2622                                 glDrawArrays(GL_TRIANGLES, 0, totelem);
2623                 }
2624
2625                 if (wireframe)
2626                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2627
2628                 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
2629                 if (buffers->index_buf)
2630                         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
2631
2632                 glDisableClientState(GL_VERTEX_ARRAY);
2633                 if (!wireframe) {
2634                         glDisableClientState(GL_NORMAL_ARRAY);
2635                         gpu_colors_disable(VBO_ENABLED);
2636                 }
2637         }
2638         /* fallbacks if we are out of memory or VBO is disabled */
2639         else if (buffers->totface) {
2640                 gpu_draw_buffers_legacy_mesh(buffers);
2641         }
2642         else if (buffers->totgrid) {
2643                 gpu_draw_buffers_legacy_grids(buffers);
2644         }
2645 }
2646
2647 bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
2648 {
2649         float diffuse_color[4];
2650         bool use_matcaps = GPU_material_use_matcaps_get();
2651
2652         if (buffers->show_diffuse_color != show_diffuse_color)
2653                 return true;
2654
2655         if (buffers->use_matcaps != use_matcaps)
2656                 return true;
2657
2658         if ((buffers->show_diffuse_color == false) || use_matcaps)
2659                 return false;
2660
2661         if (buffers->mface) {
2662                 MFace *f = buffers->mface + buffers->face_indices[0];
2663
2664                 GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
2665         }
2666         else if (buffers->use_bmesh) {
2667                 /* due to dynamc nature of dyntopo, only get first material */
2668                 if (BLI_gset_size(bm_faces) > 0) {
2669                         GSetIterator gs_iter;
2670                         BMFace *f;
2671
2672                         BLI_gsetIterator_init(&gs_iter, bm_faces);
2673                         f = BLI_gsetIterator_getKey(&gs_iter);
2674                         GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
2675                 }
2676                 else {
2677                         return false;
2678                 }
2679         }
2680         else {
2681                 const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]];
2682
2683                 GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
2684         }
2685
2686         return !equals_v3v3(diffuse_color, buffers->diffuse_color);
2687 }
2688
2689 /* release a GPU_PBVH_Buffers id;
2690  *
2691  * Thread-unsafe version for internal usage only.
2692  */
2693 static void gpu_pbvh_buffer_free_intern(GLuint id)
2694 {
2695         GPUBufferPool *pool;
2696
2697         /* zero id is vertex buffers off */
2698         if (!id)
2699                 return;
2700
2701         pool = gpu_get_global_buffer_pool();
2702
2703         /* free the buffers immediately if we are on main thread */
2704         if (BLI_thread_is_main()) {
2705                 glDeleteBuffersARB(1, &id);
2706
2707                 if (pool->totpbvhbufids > 0) {
2708                         glDeleteBuffersARB(pool->totpbvhbufids, pool->pbvhbufids);
2709                         pool->totpbvhbufids = 0;
2710                 }
2711                 return;
2712         }
2713         /* outside of main thread, can't safely delete the
2714          * buffer, so increase pool size */
2715         if (pool->maxpbvhsize == pool->totpbvhbufids) {
2716                 pool->maxpbvhsize += MAX_FREE_GPU_BUFF_IDS;
2717                 pool->pbvhbufids = MEM_reallocN(pool->pbvhbufids,
2718                                                                                 sizeof(*pool->pbvhbufids) * pool->maxpbvhsize);
2719         }
2720
2721         /* insert the buffer into the beginning of the pool */
2722         pool->pbvhbufids[pool->totpbvhbufids++] = id;
2723 }
2724
2725
2726 void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
2727 {
2728         if (buffers) {
2729                 if (buffers->vert_buf)
2730                         gpu_pbvh_buffer_free_intern(buffers->vert_buf);
2731                 if (buffers->index_buf && (buffers->tot_tri || buffers->has_hidden))
2732                         gpu_pbvh_buffer_free_intern(buffers->index_buf);
2733
2734                 MEM_freeN(buffers);
2735         }
2736 }
2737
2738
2739 /* debug function, draws the pbvh BB */
2740 void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf)
2741 {
2742         const float quads[4][4][3] = {
2743             {
2744                 {min[0], min[1], min[2]},
2745                 {max[0], min[1], min[2]},
2746                 {max[0], min[1], max[2]},
2747                 {min[0], min[1], max[2]}
2748             },
2749
2750             {
2751                 {min[0], min[1], min[2]},
2752                 {min[0], max[1], min[2]},
2753                 {min[0], max[1], max[2]},
2754                 {min[0], min[1], max[2]}
2755             },
2756
2757             {
2758                 {max[0], max[1], min[2]},
2759                 {max[0], min[1], min[2]},
2760                 {max[0], min[1], max[2]},
2761                 {max[0], max[1], max[2]}
2762             },
2763
2764             {
2765                 {max[0], max[1], min[2]},
2766                 {min[0], max[1], min[2]},
2767                 {min[0], max[1], max[2]},
2768                 {max[0], max[1], max[2]}
2769             },
2770         };
2771
2772         if (leaf)
2773                 glColor4f(0.0, 1.0, 0.0, 0.5);
2774         else
2775                 glColor4f(1.0, 0.0, 0.0, 0.5);
2776
2777         glVertexPointer(3, GL_FLOAT, 0, &quads[0][0][0]);
2778         glDrawArrays(GL_QUADS, 0, 16);
2779 }
2780
2781 void GPU_init_draw_pbvh_BB(void)
2782 {
2783         glPushAttrib(GL_ENABLE_BIT);
2784         glDisable(GL_CULL_FACE);
2785         glEnableClientState(GL_VERTEX_ARRAY);
2786         glDisableClientState(GL_COLOR_ARRAY);
2787         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2788         glDisable(GL_LIGHTING);
2789         glDisable(GL_COLOR_MATERIAL);
2790         glEnable(GL_BLEND);
2791         glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
2792 }
2793
2794 void GPU_end_draw_pbvh_BB(void)
2795 {
2796         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2797         glPopAttrib();
2798 }