39
39
#include "MEM_guardedalloc.h"
41
#include "BLI_bitmap.h"
43
#include "BLI_utildefines.h"
41
44
#include "BLI_ghash.h"
43
45
#include "BLI_threads.h"
45
47
#include "DNA_meshdata_types.h"
47
49
#include "BKE_DerivedMesh.h"
48
#include "BKE_utildefines.h"
50
#include "BKE_paint.h"
51
#include "BKE_subsurf.h"
50
53
#include "DNA_userdef_types.h"
52
55
#include "GPU_buffers.h"
54
#define GPU_BUFFER_VERTEX_STATE 1
55
#define GPU_BUFFER_NORMAL_STATE 2
56
#define GPU_BUFFER_TEXCOORD_STATE 4
57
#define GPU_BUFFER_COLOR_STATE 8
58
#define GPU_BUFFER_ELEMENT_STATE 16
58
GPU_BUFFER_VERTEX_STATE = 1,
59
GPU_BUFFER_NORMAL_STATE = 2,
60
GPU_BUFFER_TEXCOORD_STATE = 4,
61
GPU_BUFFER_COLOR_STATE = 8,
62
GPU_BUFFER_ELEMENT_STATE = 16,
60
65
#define MAX_GPU_ATTRIB_DATA 32
67
/* material number is an 16-bit short and the range of short is from -16383 to 16383 (assume material number is non-negative) */
68
#define MAX_MATERIALS 16384
62
70
/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
64
GPUBufferPool *globalPool = 0;
66
GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
68
GPUBufferPool *GPU_buffer_pool_new()
71
static int useVBOs = -1;
72
static GPUBufferState GLStates = 0;
73
static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
75
/* stores recently-deleted buffers so that new buffers won't have to
76
* be recreated as often
78
* only one instance of this pool is created, stored in
81
* note that the number of buffers in the pool is usually limited to
82
* MAX_FREE_GPU_BUFFERS, but this limit may be exceeded temporarily
83
* when a GPUBuffer is released outside the main thread; due to OpenGL
84
* restrictions it cannot be immediately released
86
typedef struct GPUBufferPool {
87
/* number of allocated buffers stored */
89
/* actual allocated length of the array */
93
#define MAX_FREE_GPU_BUFFERS 8
95
/* create a new GPUBufferPool */
96
static GPUBufferPool *gpu_buffer_pool_new(void)
70
98
GPUBufferPool *pool;
72
DEBUG_VBO("GPU_buffer_pool_new\n");
75
if( GL_ARB_vertex_buffer_object ) {
76
DEBUG_VBO( "Vertex Buffer Objects supported.\n" );
80
DEBUG_VBO( "Vertex Buffer Objects NOT supported.\n" );
85
pool = MEM_callocN(sizeof(GPUBufferPool), "GPU_buffer_pool_new");
100
/* enable VBOs if supported */
102
useVBOs = (GLEW_ARB_vertex_buffer_object ? 1 : 0);
104
pool = MEM_callocN(sizeof(GPUBufferPool), "GPUBuffer");
86
106
pool->maxsize = MAX_FREE_GPU_BUFFERS;
87
pool->buffers = MEM_callocN(sizeof(GPUBuffer*)*pool->maxsize, "GPU_buffer_pool_new buffers");
107
pool->buffers = MEM_callocN(sizeof(GPUBuffer*)*pool->maxsize,
108
"GPUBuffer.buffers");
92
void GPU_buffer_pool_remove( int index, GPUBufferPool *pool )
113
/* remove a GPUBuffer from the pool (does not free the GPUBuffer) */
114
static void gpu_buffer_pool_remove_index(GPUBufferPool *pool, int index)
96
if( index >= pool->size || index < 0 ) {
97
ERROR_VBO("Wrong index, out of bounds in call to GPU_buffer_pool_remove");
118
if (!pool || index < 0 || index >= pool->totbuf)
100
DEBUG_VBO("GPU_buffer_pool_remove\n");
102
for( i = index; i < pool->size-1; i++ ) {
121
/* shift entries down, overwriting the buffer at `index' */
122
for (i = index; i < pool->totbuf - 1; i++)
103
123
pool->buffers[i] = pool->buffers[i+1];
106
pool->buffers[pool->size-1] = 0;
111
void GPU_buffer_pool_delete_last( GPUBufferPool *pool )
115
DEBUG_VBO("GPU_buffer_pool_delete_last\n");
117
if( pool->size <= 0 )
122
if( pool->buffers[last] != 0 ) {
124
glDeleteBuffersARB(1,&pool->buffers[last]->id);
125
MEM_freeN( pool->buffers[last] );
128
MEM_freeN( pool->buffers[last]->pointer );
129
MEM_freeN( pool->buffers[last] );
131
pool->buffers[last] = 0;
133
DEBUG_VBO("Why are we accessing a null buffer?\n");
138
void GPU_buffer_pool_free(GPUBufferPool *pool)
140
DEBUG_VBO("GPU_buffer_pool_free\n");
125
/* clear the last entry */
126
if (pool->totbuf > 0)
127
pool->buffers[pool->totbuf - 1] = NULL;
132
/* delete the last entry in the pool */
133
static void gpu_buffer_pool_delete_last(GPUBufferPool *pool)
137
if (pool->totbuf <= 0)
140
/* get the last entry */
141
if (!(last = pool->buffers[pool->totbuf - 1]))
144
/* delete the buffer's data */
146
glDeleteBuffersARB(1, &last->id);
148
MEM_freeN(last->pointer);
150
/* delete the buffer and remove from pool */
153
pool->buffers[pool->totbuf] = NULL;
156
/* free a GPUBufferPool; also frees the data in the pool's
158
static void gpu_buffer_pool_free(GPUBufferPool *pool)
148
GPU_buffer_pool_delete_last(pool);
164
gpu_buffer_pool_delete_last(pool);
150
166
MEM_freeN(pool->buffers);
154
void GPU_buffer_pool_free_unused(GPUBufferPool *pool)
156
DEBUG_VBO("GPU_buffer_pool_free_unused\n");
163
while( pool->size > MAX_FREE_GPU_BUFFERS )
164
GPU_buffer_pool_delete_last(pool);
167
GPUBuffer *GPU_buffer_alloc( int size, GPUBufferPool *pool )
172
GPUBuffer *allocated;
175
DEBUG_VBO("GPU_buffer_alloc\n");
178
if( globalPool == 0 )
179
globalPool = GPU_buffer_pool_new();
183
for( i = 0; i < pool->size; i++ ) {
184
cursize = pool->buffers[i]->size;
185
if( cursize == size ) {
186
allocated = pool->buffers[i];
187
GPU_buffer_pool_remove(i,pool);
188
DEBUG_VBO("free buffer of exact size found\n");
170
static GPUBufferPool *gpu_buffer_pool = NULL;
171
static GPUBufferPool *gpu_get_global_buffer_pool(void)
173
/* initialize the pool */
174
if (!gpu_buffer_pool)
175
gpu_buffer_pool = gpu_buffer_pool_new();
177
return gpu_buffer_pool;
180
void GPU_global_buffer_pool_free(void)
182
gpu_buffer_pool_free(gpu_buffer_pool);
183
gpu_buffer_pool = NULL;
186
/* get a GPUBuffer of at least `size' bytes; uses one from the buffer
187
* pool if possible, otherwise creates a new one */
188
GPUBuffer *GPU_buffer_alloc(int size)
192
int i, bufsize, bestfit = -1;
194
pool = gpu_get_global_buffer_pool();
196
/* not sure if this buffer pool code has been profiled much,
197
* seems to me that the graphics driver and system memory
198
* management might do this stuff anyway. --nicholas
201
/* check the global buffer pool for a recently-deleted buffer
202
* that is at least as big as the request, but not more than
204
for (i = 0; i < pool->totbuf; i++) {
205
bufsize = pool->buffers[i]->size;
207
/* check for an exact size match */
208
if (bufsize == size) {
191
/* smaller buffers won't fit data and buffers at least twice as big are a waste of memory */
192
else if( cursize > size && size > cursize/2 ) {
193
/* is it closer to the required size than the last appropriate buffer found. try to save memory */
194
if( bestfit == -1 || pool->buffers[bestfit]->size > cursize ) {
212
/* smaller buffers won't fit data and buffers at least
213
* twice as big are a waste of memory */
214
else if (bufsize > size && size > (bufsize / 2)) {
215
/* is it closer to the required size than the
216
* last appropriate buffer found. try to save
218
if (bestfit == -1 || pool->buffers[bestfit]->size > bufsize) {
199
if( bestfit == -1 ) {
200
DEBUG_VBO("allocating a new buffer\n");
202
allocated = MEM_mallocN(sizeof(GPUBuffer), "GPU_buffer_alloc");
203
allocated->size = size;
205
glGenBuffersARB( 1, &allocated->id );
206
glBindBufferARB( GL_ARRAY_BUFFER_ARB, allocated->id );
207
glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, 0, GL_STATIC_DRAW_ARB );
208
glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
211
allocated->pointer = MEM_mallocN(size, "GPU_buffer_alloc_vertexarray");
212
while( allocated->pointer == 0 && pool->size > 0 ) {
213
GPU_buffer_pool_delete_last(pool);
214
allocated->pointer = MEM_mallocN(size, "GPU_buffer_alloc_vertexarray");
216
if( allocated->pointer == 0 && pool->size == 0 ) {
224
/* if an acceptable buffer was found in the pool, remove it
225
* from the pool and return it */
227
buf = pool->buffers[bestfit];
228
gpu_buffer_pool_remove_index(pool, bestfit);
232
/* no acceptable buffer found in the pool, create a new one */
233
buf = MEM_callocN(sizeof(GPUBuffer), "GPUBuffer");
237
/* create a new VBO and initialize it to the requested
239
glGenBuffersARB(1, &buf->id);
240
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf->id);
241
glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB);
242
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
222
sprintf(buffer,"free buffer found. Wasted %d bytes\n", pool->buffers[bestfit]->size-size);
245
buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
247
/* purpose of this seems to be dealing with
248
* out-of-memory errors? looks a bit iffy to me
249
* though, at least on Linux I expect malloc() would
250
* just overcommit. --nicholas */
251
while (!buf->pointer && pool->totbuf > 0) {
252
gpu_buffer_pool_delete_last(pool);
253
buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
225
allocated = pool->buffers[bestfit];
226
GPU_buffer_pool_remove(bestfit,pool);
231
void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool )
262
/* release a GPUBuffer; does not free the actual buffer or its data,
263
* but rather moves it to the pool of recently-freed buffers for
265
void GPU_buffer_free(GPUBuffer *buffer)
235
DEBUG_VBO("GPU_buffer_free\n");
242
globalPool = GPU_buffer_pool_new();
273
pool = gpu_get_global_buffer_pool();
244
275
/* free the last used buffer in the queue if no more space, but only
245
if we are in the main thread. for e.g. rendering or baking it can
246
happen that we are in other thread and can't call OpenGL, in that
247
case cleanup will be done GPU_buffer_pool_free_unused */
248
if( BLI_thread_is_main() ) {
249
while( pool->size >= MAX_FREE_GPU_BUFFERS )
250
GPU_buffer_pool_delete_last( pool );
276
* if we are in the main thread. for e.g. rendering or baking it can
277
* happen that we are in other thread and can't call OpenGL, in that
278
* case cleanup will be done GPU_buffer_pool_free_unused */
279
if (BLI_thread_is_main()) {
280
/* in main thread, safe to decrease size of pool back
281
* down to MAX_FREE_GPU_BUFFERS */
282
while (pool->totbuf >= MAX_FREE_GPU_BUFFERS)
283
gpu_buffer_pool_delete_last(pool);
253
if( pool->maxsize == pool->size ) {
286
/* outside of main thread, can't safely delete the
287
* buffer, so increase pool size */
288
if (pool->maxsize == pool->totbuf) {
254
289
pool->maxsize += MAX_FREE_GPU_BUFFERS;
255
pool->buffers = MEM_reallocN(pool->buffers, sizeof(GPUBuffer*)*pool->maxsize);
290
pool->buffers = MEM_reallocN(pool->buffers,
291
sizeof(GPUBuffer*) * pool->maxsize);
259
for( i =pool->size; i > 0; i-- ) {
295
/* shift pool entries up by one */
296
for (i = pool->totbuf; i > 0; i--)
260
297
pool->buffers[i] = pool->buffers[i-1];
299
/* insert the buffer into the beginning of the pool */
262
300
pool->buffers[0] = buffer;
304
typedef struct GPUVertPointLink {
305
struct GPUVertPointLink *next;
306
/* -1 means uninitialized */
310
/* add a new point to the list of points related to a particular
312
static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
314
GPUVertPointLink *lnk;
316
lnk = &gdo->vert_points[vert_index];
318
/* if first link is in use, add a new link at the end */
319
if (lnk->point_index != -1) {
321
for (; lnk->next; lnk = lnk->next);
323
/* add a new link from the pool */
324
lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage];
325
gdo->vert_points_usage++;
328
lnk->point_index = point_index;
331
/* update the vert_points and triangle_to_mface fields with a new
333
static void gpu_drawobject_add_triangle(GPUDrawObject *gdo,
334
int base_point_index,
336
int v1, int v2, int v3)
338
int i, v[3] = {v1, v2, v3};
339
for (i = 0; i < 3; i++)
340
gpu_drawobject_add_vert_point(gdo, v[i], base_point_index + i);
341
gdo->triangle_to_mface[base_point_index / 3] = face_index;
344
/* for each vertex, build a list of points related to it; these lists
345
* are stored in an array sized to the number of vertices */
346
static void gpu_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int totface)
348
GPUBufferMaterial *mat;
349
int i, mat_orig_to_new[MAX_MATERIALS];
351
/* allocate the array and space for links */
352
gdo->vert_points = MEM_callocN(sizeof(GPUVertPointLink) * gdo->totvert,
353
"GPUDrawObject.vert_points");
354
gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point,
355
"GPUDrawObject.vert_points_mem");
356
gdo->vert_points_usage = 0;
358
/* build a map from the original material indices to the new
359
* GPUBufferMaterial indices */
360
for (i = 0; i < gdo->totmaterial; i++)
361
mat_orig_to_new[gdo->materials[i].mat_nr] = i;
363
/* -1 indicates the link is not yet used */
364
for (i = 0; i < gdo->totvert; i++)
365
gdo->vert_points[i].point_index = -1;
367
for (i = 0; i < totface; i++, f++) {
368
mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
371
gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
372
i, f->v1, f->v2, f->v3);
375
/* add second triangle for quads */
377
gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
378
i, f->v3, f->v4, f->v1);
383
/* map any unused vertices to loose points */
384
for (i = 0; i < gdo->totvert; i++) {
385
if (gdo->vert_points[i].point_index == -1) {
386
gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point;
387
gdo->tot_loose_point++;
392
/* see GPUDrawObject's structure definition for a description of the
393
* data being initialized here */
266
394
GPUDrawObject *GPU_drawobject_new( DerivedMesh *dm )
268
GPUDrawObject *object;
271
int numverts[32768]; /* material number is an 16-bit short so there's at most 32768 materials */
272
int redir[32768]; /* material number is an 16-bit short so there's at most 32768 materials */
275
int curmat, curverts, numfaces;
277
DEBUG_VBO("GPU_drawobject_new\n");
279
object = MEM_callocN(sizeof(GPUDrawObject),"GPU_drawobject_new_object");
280
object->nindices = dm->getNumVerts(dm);
281
object->indices = MEM_mallocN(sizeof(IndexLink)*object->nindices, "GPU_drawobject_new_indices");
282
object->nedges = dm->getNumEdges(dm);
284
for( i = 0; i < object->nindices; i++ ) {
285
object->indices[i].element = -1;
286
object->indices[i].next = 0;
288
/*object->legacy = 1;*/
289
memset(numverts,0,sizeof(int)*32768);
291
mvert = dm->getVertArray(dm);
292
mface = dm->getFaceArray(dm);
294
numfaces= dm->getNumFaces(dm);
295
for( i=0; i < numfaces; i++ ) {
297
numverts[mface[i].mat_nr+16383] += 6; /* split every quad into two triangles */
299
numverts[mface[i].mat_nr+16383] += 3;
302
for( i = 0; i < 32768; i++ ) {
303
if( numverts[i] > 0 ) {
304
object->nmaterials++;
305
object->nelements += numverts[i];
308
object->materials = MEM_mallocN(sizeof(GPUBufferMaterial)*object->nmaterials,"GPU_drawobject_new_materials");
309
index = MEM_mallocN(sizeof(int)*object->nmaterials,"GPU_drawobject_new_index");
311
curmat = curverts = 0;
312
for( i = 0; i < 32768; i++ ) {
313
if( numverts[i] > 0 ) {
314
object->materials[curmat].mat_nr = i-16383;
315
object->materials[curmat].start = curverts;
316
index[curmat] = curverts/3;
317
object->materials[curmat].end = curverts+numverts[i];
318
curverts += numverts[i];
398
int points_per_mat[MAX_MATERIALS];
399
int i, curmat, curpoint, totface;
401
mface = dm->getTessFaceArray(dm);
402
totface= dm->getNumTessFaces(dm);
404
/* get the number of points used by each material, treating
405
* each quad as two triangles */
406
memset(points_per_mat, 0, sizeof(int)*MAX_MATERIALS);
407
for (i = 0; i < totface; i++)
408
points_per_mat[mface[i].mat_nr] += mface[i].v4 ? 6 : 3;
410
/* create the GPUDrawObject */
411
gdo = MEM_callocN(sizeof(GPUDrawObject),"GPUDrawObject");
412
gdo->totvert = dm->getNumVerts(dm);
413
gdo->totedge = dm->getNumEdges(dm);
415
/* count the number of materials used by this DerivedMesh */
416
for (i = 0; i < MAX_MATERIALS; i++) {
417
if (points_per_mat[i] > 0)
421
/* allocate an array of materials used by this DerivedMesh */
422
gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
423
"GPUDrawObject.materials");
425
/* initialize the materials array */
426
for (i = 0, curmat = 0, curpoint = 0; i < MAX_MATERIALS; i++) {
427
if (points_per_mat[i] > 0) {
428
gdo->materials[curmat].start = curpoint;
429
gdo->materials[curmat].totpoint = 0;
430
gdo->materials[curmat].mat_nr = i;
432
curpoint += points_per_mat[i];
322
object->faceRemap = MEM_mallocN(sizeof(int)*object->nelements/3,"GPU_drawobject_new_faceRemap");
323
for( i = 0; i < object->nmaterials; i++ ) {
324
redir[object->materials[i].mat_nr+16383] = i; /* material number -> material index */
327
object->indexMem = MEM_callocN(sizeof(IndexLink)*object->nelements,"GPU_drawobject_new_indexMem");
328
object->indexMemUsage = 0;
330
#define ADDLINK( INDEX, ACTUAL ) \
331
if( object->indices[INDEX].element == -1 ) { \
332
object->indices[INDEX].element = ACTUAL; \
334
IndexLink *lnk = &object->indices[INDEX]; \
335
while( lnk->next != 0 ) lnk = lnk->next; \
336
lnk->next = &object->indexMem[object->indexMemUsage]; \
337
lnk->next->element = ACTUAL; \
338
object->indexMemUsage++; \
341
for( i=0; i < numfaces; i++ ) {
342
int curInd = index[redir[mface[i].mat_nr+16383]];
343
object->faceRemap[curInd] = i;
344
ADDLINK( mface[i].v1, curInd*3 );
345
ADDLINK( mface[i].v2, curInd*3+1 );
346
ADDLINK( mface[i].v3, curInd*3+2 );
348
object->faceRemap[curInd+1] = i;
349
ADDLINK( mface[i].v3, curInd*3+3 );
350
ADDLINK( mface[i].v4, curInd*3+4 );
351
ADDLINK( mface[i].v1, curInd*3+5 );
353
index[redir[mface[i].mat_nr+16383]]+=2;
356
index[redir[mface[i].mat_nr+16383]]++;
360
for( i = 0; i < object->nindices; i++ ) {
361
if( object->indices[i].element == -1 ) {
362
object->indices[i].element = object->nelements + object->nlooseverts;
363
object->nlooseverts++;
372
void GPU_drawobject_free( DerivedMesh *dm )
374
GPUDrawObject *object;
376
DEBUG_VBO("GPU_drawobject_free\n");
380
object = dm->drawObject;
384
MEM_freeN(object->materials);
385
MEM_freeN(object->faceRemap);
386
MEM_freeN(object->indices);
387
MEM_freeN(object->indexMem);
388
GPU_buffer_free( object->vertices, globalPool );
389
GPU_buffer_free( object->normals, globalPool );
390
GPU_buffer_free( object->uv, globalPool );
391
GPU_buffer_free( object->colors, globalPool );
392
GPU_buffer_free( object->edges, globalPool );
393
GPU_buffer_free( object->uvedges, globalPool );
437
/* store total number of points used for triangles */
438
gdo->tot_triangle_point = curpoint;
440
gdo->triangle_to_mface = MEM_mallocN(sizeof(int) * (gdo->tot_triangle_point / 3),
441
"GPUDrawObject.triangle_to_mface");
443
gpu_drawobject_init_vert_points(gdo, mface, totface);
448
void GPU_drawobject_free(DerivedMesh *dm)
452
if (!dm || !(gdo = dm->drawObject))
455
MEM_freeN(gdo->materials);
456
MEM_freeN(gdo->triangle_to_mface);
457
MEM_freeN(gdo->vert_points);
458
MEM_freeN(gdo->vert_points_mem);
459
GPU_buffer_free(gdo->points);
460
GPU_buffer_free(gdo->normals);
461
GPU_buffer_free(gdo->uv);
462
GPU_buffer_free(gdo->colors);
463
GPU_buffer_free(gdo->edges);
464
GPU_buffer_free(gdo->uvedges);
467
dm->drawObject = NULL;
470
typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
471
int *mat_orig_to_new, void *user_data);
473
static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
474
int vector_size, int size, GLenum target,
475
void *user, GPUBufferCopyFunc copy_f)
480
int mat_orig_to_new[MAX_MATERIALS];
481
int *cur_index_per_mat;
486
pool = gpu_get_global_buffer_pool();
488
/* alloc a GPUBuffer; fall back to legacy mode on failure */
489
if (!(buffer = GPU_buffer_alloc(size)))
490
dm->drawObject->legacy = 1;
492
/* nothing to do for legacy mode */
493
if (dm->drawObject->legacy)
496
cur_index_per_mat = MEM_mallocN(sizeof(int)*object->totmaterial,
497
"GPU_buffer_setup.cur_index_per_mat");
498
for (i = 0; i < object->totmaterial; i++) {
499
/* for each material, the current index to copy data to */
500
cur_index_per_mat[i] = object->materials[i].start * vector_size;
502
/* map from original material index to new
503
* GPUBufferMaterial index */
504
mat_orig_to_new[object->materials[i].mat_nr] = i;
511
/* bind the buffer and discard previous data,
512
* avoids stalling gpu */
513
glBindBufferARB(target, buffer->id);
514
glBufferDataARB(target, buffer->size, NULL, GL_STATIC_DRAW_ARB);
516
/* attempt to map the buffer */
517
if (!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) {
518
/* failed to map the buffer; delete it */
519
GPU_buffer_free(buffer);
520
gpu_buffer_pool_delete_last(pool);
523
/* try freeing an entry from the pool
524
* and reallocating the buffer */
525
if (pool->totbuf > 0) {
526
gpu_buffer_pool_delete_last(pool);
527
buffer = GPU_buffer_alloc(size);
530
/* allocation still failed; fall back
533
dm->drawObject->legacy = 1;
542
/* check legacy fallback didn't happen */
543
if (dm->drawObject->legacy == 0) {
545
/* attempt to upload the data to the VBO */
546
while (uploaded == GL_FALSE) {
547
(*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
548
/* glUnmapBuffer returns GL_FALSE if
549
* the data store is corrupted; retry
551
uploaded = glUnmapBufferARB(target);
554
glBindBufferARB(target, 0);
557
/* VBO not supported, use vertex array fallback */
558
if (buffer->pointer) {
559
varray = buffer->pointer;
560
(*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
563
dm->drawObject->legacy = 1;
567
MEM_freeN(cur_index_per_mat);
572
static void GPU_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
576
int i, j, start, totface;
578
mvert = dm->getVertArray(dm);
579
f = dm->getTessFaceArray(dm);
581
totface= dm->getNumTessFaces(dm);
582
for (i = 0; i < totface; i++, f++) {
583
start = index[mat_orig_to_new[f->mat_nr]];
586
copy_v3_v3(&varray[start], mvert[f->v1].co);
587
copy_v3_v3(&varray[start+3], mvert[f->v2].co);
588
copy_v3_v3(&varray[start+6], mvert[f->v3].co);
589
index[mat_orig_to_new[f->mat_nr]] += 9;
593
copy_v3_v3(&varray[start+9], mvert[f->v3].co);
594
copy_v3_v3(&varray[start+12], mvert[f->v4].co);
595
copy_v3_v3(&varray[start+15], mvert[f->v1].co);
596
index[mat_orig_to_new[f->mat_nr]] += 9;
600
/* copy loose points */
601
j = dm->drawObject->tot_triangle_point*3;
602
for (i = 0; i < dm->drawObject->totvert; i++) {
603
if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) {
604
copy_v3_v3(&varray[j],mvert[i].co);
610
static void GPU_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
616
float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
617
MVert *mvert = dm->getVertArray(dm);
618
MFace *f = dm->getTessFaceArray(dm);
620
totface= dm->getNumTessFaces(dm);
621
for (i = 0; i < totface; i++, f++) {
622
const int smoothnormal = (f->flag & ME_SMOOTH);
624
start = index[mat_orig_to_new[f->mat_nr]];
625
index[mat_orig_to_new[f->mat_nr]] += f->v4 ? 18 : 9;
628
/* copy vertex normal */
629
normal_short_to_float_v3(&varray[start], mvert[f->v1].no);
630
normal_short_to_float_v3(&varray[start+3], mvert[f->v2].no);
631
normal_short_to_float_v3(&varray[start+6], mvert[f->v3].no);
634
normal_short_to_float_v3(&varray[start+9], mvert[f->v3].no);
635
normal_short_to_float_v3(&varray[start+12], mvert[f->v4].no);
636
normal_short_to_float_v3(&varray[start+15], mvert[f->v1].no);
640
/* copy cached face normal */
641
copy_v3_v3(&varray[start], &nors[i*3]);
642
copy_v3_v3(&varray[start+3], &nors[i*3]);
643
copy_v3_v3(&varray[start+6], &nors[i*3]);
646
copy_v3_v3(&varray[start+9], &nors[i*3]);
647
copy_v3_v3(&varray[start+12], &nors[i*3]);
648
copy_v3_v3(&varray[start+15], &nors[i*3]);
652
/* calculate face normal */
654
normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
656
normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
658
copy_v3_v3(&varray[start], f_no);
659
copy_v3_v3(&varray[start+3], f_no);
660
copy_v3_v3(&varray[start+6], f_no);
663
copy_v3_v3(&varray[start+9], f_no);
664
copy_v3_v3(&varray[start+12], f_no);
665
copy_v3_v3(&varray[start+15], f_no);
671
static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
679
if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
681
f = dm->getTessFaceArray(dm);
683
totface = dm->getNumTessFaces(dm);
684
for (i = 0; i < totface; i++, f++) {
685
start = index[mat_orig_to_new[f->mat_nr]];
688
copy_v2_v2(&varray[start],mtface[i].uv[0]);
689
copy_v2_v2(&varray[start+2],mtface[i].uv[1]);
690
copy_v2_v2(&varray[start+4],mtface[i].uv[2]);
691
index[mat_orig_to_new[f->mat_nr]] += 6;
695
copy_v2_v2(&varray[start+6],mtface[i].uv[2]);
696
copy_v2_v2(&varray[start+8],mtface[i].uv[3]);
697
copy_v2_v2(&varray[start+10],mtface[i].uv[0]);
698
index[mat_orig_to_new[f->mat_nr]] += 6;
704
static void GPU_buffer_copy_color3(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user)
707
char *varray = (char *)varray_;
708
char *mcol = (char *)user;
709
MFace *f = dm->getTessFaceArray(dm);
711
totface= dm->getNumTessFaces(dm);
712
for (i=0; i < totface; i++, f++) {
713
int start = index[mat_orig_to_new[f->mat_nr]];
716
copy_v3_v3_char(&varray[start], &mcol[i*12]);
717
copy_v3_v3_char(&varray[start+3], &mcol[i*12+3]);
718
copy_v3_v3_char(&varray[start+6], &mcol[i*12+6]);
719
index[mat_orig_to_new[f->mat_nr]] += 9;
723
copy_v3_v3_char(&varray[start+9], &mcol[i*12+6]);
724
copy_v3_v3_char(&varray[start+12], &mcol[i*12+9]);
725
copy_v3_v3_char(&varray[start+15], &mcol[i*12]);
726
index[mat_orig_to_new[f->mat_nr]] += 9;
731
static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
738
/* treat varray_ as an array of MCol, four MCol's per face */
739
static void GPU_buffer_copy_mcol(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user)
742
unsigned char *varray = (unsigned char *)varray_;
743
unsigned char *mcol = (unsigned char *)user;
744
MFace *f = dm->getTessFaceArray(dm);
746
totface= dm->getNumTessFaces(dm);
747
for (i=0; i < totface; i++, f++) {
748
int start = index[mat_orig_to_new[f->mat_nr]];
751
copy_mcol_uc3(&varray[start], &mcol[i*16]);
752
copy_mcol_uc3(&varray[start+3], &mcol[i*16+4]);
753
copy_mcol_uc3(&varray[start+6], &mcol[i*16+8]);
754
index[mat_orig_to_new[f->mat_nr]] += 9;
758
copy_mcol_uc3(&varray[start+9], &mcol[i*16+8]);
759
copy_mcol_uc3(&varray[start+12], &mcol[i*16+12]);
760
copy_mcol_uc3(&varray[start+15], &mcol[i*16]);
761
index[mat_orig_to_new[f->mat_nr]] += 9;
766
static void GPU_buffer_copy_edge(DerivedMesh *dm, float *varray_, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
769
unsigned int *varray = (unsigned int *)varray_;
772
medge = dm->getEdgeArray(dm);
773
totedge = dm->getNumEdges(dm);
775
for (i = 0; i < totedge; i++, medge++) {
776
varray[i*2] = dm->drawObject->vert_points[medge->v1].point_index;
777
varray[i*2+1] = dm->drawObject->vert_points[medge->v2].point_index;
781
static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
783
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
789
for (i = 0; i < dm->numTessFaceData; i++, tf++) {
791
dm->getTessFace(dm,i,&mf);
793
copy_v2_v2(&varray[j],tf->uv[0]);
794
copy_v2_v2(&varray[j+2],tf->uv[1]);
796
copy_v2_v2(&varray[j+4],tf->uv[1]);
797
copy_v2_v2(&varray[j+6],tf->uv[2]);
800
copy_v2_v2(&varray[j+8],tf->uv[2]);
801
copy_v2_v2(&varray[j+10],tf->uv[0]);
805
copy_v2_v2(&varray[j+8],tf->uv[2]);
806
copy_v2_v2(&varray[j+10],tf->uv[3]);
808
copy_v2_v2(&varray[j+12],tf->uv[3]);
809
copy_v2_v2(&varray[j+14],tf->uv[0]);
815
/* get the DerivedMesh's MCols; choose (in decreasing order of
816
* preference) from CD_ID_MCOL, CD_PREVIEW_MCOL, or CD_MCOL */
817
static MCol *gpu_buffer_color_type(DerivedMesh *dm)
823
c = DM_get_tessface_data_layer(dm, type);
825
type = CD_PREVIEW_MCOL;
826
c = DM_get_tessface_data_layer(dm, type);
829
c = DM_get_tessface_data_layer(dm, type);
833
dm->drawObject->colType = type;
838
GPU_BUFFER_VERTEX = 0,
847
GPUBufferCopyFunc copy;
848
GLenum gl_buffer_type;
850
} GPUBufferTypeSettings;
852
const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
853
{GPU_buffer_copy_vertex, GL_ARRAY_BUFFER_ARB, 3},
854
{GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
855
{GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
856
{GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
857
{GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
858
{GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
861
/* get the GPUDrawObject buffer associated with a type */
862
static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBufferType type)
865
case GPU_BUFFER_VERTEX:
867
case GPU_BUFFER_NORMAL:
868
return &gdo->normals;
869
case GPU_BUFFER_COLOR:
873
case GPU_BUFFER_EDGE:
875
case GPU_BUFFER_UVEDGE:
876
return &gdo->uvedges;
882
/* get the amount of space to allocate for a buffer of a particular type */
883
static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
886
case GPU_BUFFER_VERTEX:
887
return sizeof(float)*3 * (dm->drawObject->tot_triangle_point + dm->drawObject->tot_loose_point);
888
case GPU_BUFFER_NORMAL:
889
return sizeof(float)*3*dm->drawObject->tot_triangle_point;
890
case GPU_BUFFER_COLOR:
891
return sizeof(char)*3*dm->drawObject->tot_triangle_point;
893
return sizeof(float)*2*dm->drawObject->tot_triangle_point;
894
case GPU_BUFFER_EDGE:
895
return sizeof(int)*2*dm->drawObject->totedge;
896
case GPU_BUFFER_UVEDGE:
897
/* each face gets 3 points, 3 edges per triangle, and
898
* each edge has its own, non-shared coords, so each
899
* tri corner needs minimum of 4 floats, quads used
900
* less so here we can over allocate and assume all
902
return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
908
/* call gpu_buffer_setup with settings for a particular type of buffer */
909
static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
911
const GPUBufferTypeSettings *ts;
912
void *user_data = NULL;
915
ts = &gpu_buffer_type_settings[type];
917
/* special handling for MCol and UV buffers */
918
if (type == GPU_BUFFER_COLOR) {
919
if (!(user_data = gpu_buffer_color_type(dm)))
922
else if (type == GPU_BUFFER_UV) {
923
if (!DM_get_tessface_data_layer(dm, CD_MTFACE))
927
buf = gpu_buffer_setup(dm, dm->drawObject, ts->vector_size,
928
gpu_buffer_size_from_type(dm, type),
929
ts->gl_buffer_type, user_data, ts->copy);
934
/* get the buffer of `type', initializing the GPUDrawObject and
935
* buffer if needed */
936
static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type)
941
dm->drawObject = GPU_drawobject_new(dm);
943
buf = gpu_drawobject_buffer_from_type(dm->drawObject, type);
945
*buf = gpu_buffer_setup_type(dm, type);
950
void GPU_vertex_setup(DerivedMesh *dm)
952
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX))
955
glEnableClientState(GL_VERTEX_ARRAY);
957
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
958
glVertexPointer(3, GL_FLOAT, 0, 0);
961
glVertexPointer(3, GL_FLOAT, 0, dm->drawObject->points->pointer);
964
GLStates |= GPU_BUFFER_VERTEX_STATE;
967
void GPU_normal_setup(DerivedMesh *dm)
969
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_NORMAL))
972
glEnableClientState(GL_NORMAL_ARRAY);
974
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id);
975
glNormalPointer(GL_FLOAT, 0, 0);
978
glNormalPointer(GL_FLOAT, 0, dm->drawObject->normals->pointer);
981
GLStates |= GPU_BUFFER_NORMAL_STATE;
984
void GPU_uv_setup(DerivedMesh *dm)
986
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV))
989
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
991
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
992
glTexCoordPointer(2, GL_FLOAT, 0, 0);
995
glTexCoordPointer(2, GL_FLOAT, 0, dm->drawObject->uv->pointer);
998
GLStates |= GPU_BUFFER_TEXCOORD_STATE;
1001
void GPU_color_setup(DerivedMesh *dm)
1003
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_COLOR))
1006
glEnableClientState(GL_COLOR_ARRAY);
1008
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->colors->id);
1009
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
1012
glColorPointer(3, GL_UNSIGNED_BYTE, 0, dm->drawObject->colors->pointer);
1015
GLStates |= GPU_BUFFER_COLOR_STATE;
1018
void GPU_edge_setup(DerivedMesh *dm)
1020
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_EDGE))
1023
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX))
1026
glEnableClientState(GL_VERTEX_ARRAY);
1028
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
1029
glVertexPointer(3, GL_FLOAT, 0, 0);
1032
glVertexPointer(3, GL_FLOAT, 0, dm->drawObject->points->pointer);
1035
GLStates |= GPU_BUFFER_VERTEX_STATE;
1038
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->edges->id);
1040
GLStates |= GPU_BUFFER_ELEMENT_STATE;
1043
void GPU_uvedge_setup(DerivedMesh *dm)
1045
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UVEDGE))
1048
glEnableClientState(GL_VERTEX_ARRAY);
1050
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uvedges->id);
1051
glVertexPointer(2, GL_FLOAT, 0, 0);
1054
glVertexPointer(2, GL_FLOAT, 0, dm->drawObject->uvedges->pointer);
1057
GLStates |= GPU_BUFFER_VERTEX_STATE;
1060
static int GPU_typesize(int type)
1064
return sizeof(float);
1067
case GL_UNSIGNED_INT:
1068
return sizeof(unsigned int);
1070
return sizeof(char);
1071
case GL_UNSIGNED_BYTE:
1072
return sizeof(unsigned char);
1078
int GPU_attrib_element_size(GPUAttrib data[], int numdata)
1080
int i, elementsize = 0;
1082
for (i = 0; i < numdata; i++) {
1083
int typesize = GPU_typesize(data[i].type);
1085
elementsize += typesize*data[i].size;
1090
void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata)
1094
intptr_t offset = 0;
1096
for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
1097
if (attribData[i].index != -1) {
1098
glDisableVertexAttribArrayARB(attribData[i].index);
1103
elementsize = GPU_attrib_element_size(data, numdata);
1106
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
1107
for (i = 0; i < numdata; i++) {
1108
glEnableVertexAttribArrayARB(data[i].index);
1109
glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
1110
GL_FALSE, elementsize, (void *)offset);
1111
offset += data[i].size*GPU_typesize(data[i].type);
1113
attribData[i].index = data[i].index;
1114
attribData[i].size = data[i].size;
1115
attribData[i].type = data[i].type;
1117
attribData[numdata].index = -1;
1120
for (i = 0; i < numdata; i++) {
1121
glEnableVertexAttribArrayARB(data[i].index);
1122
glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
1123
GL_FALSE, elementsize, (char *)buffer->pointer + offset);
1124
offset += data[i].size*GPU_typesize(data[i].type);
1130
void GPU_buffer_unbind(void)
1134
if (GLStates & GPU_BUFFER_VERTEX_STATE)
1135
glDisableClientState(GL_VERTEX_ARRAY);
1136
if (GLStates & GPU_BUFFER_NORMAL_STATE)
1137
glDisableClientState(GL_NORMAL_ARRAY);
1138
if (GLStates & GPU_BUFFER_TEXCOORD_STATE)
1139
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1140
if (GLStates & GPU_BUFFER_COLOR_STATE)
1141
glDisableClientState(GL_COLOR_ARRAY);
1142
if (GLStates & GPU_BUFFER_ELEMENT_STATE) {
1144
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1147
GLStates &= !(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE |
1148
GPU_BUFFER_TEXCOORD_STATE | GPU_BUFFER_COLOR_STATE |
1149
GPU_BUFFER_ELEMENT_STATE);
1151
for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
1152
if (attribData[i].index != -1) {
1153
glDisableVertexAttribArrayARB(attribData[i].index);
1160
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1163
/* confusion: code in cdderivedmesh calls both GPU_color_setup and
1164
* GPU_color3_upload; both of these set the `colors' buffer, so seems
1165
* like it will just needlessly overwrite? --nicholas */
1166
void GPU_color3_upload(DerivedMesh *dm, unsigned char *data)
1168
if (dm->drawObject == 0)
1169
dm->drawObject = GPU_drawobject_new(dm);
1170
GPU_buffer_free(dm->drawObject->colors);
1172
dm->drawObject->colors = gpu_buffer_setup(dm, dm->drawObject, 3,
1173
sizeof(char)*3*dm->drawObject->tot_triangle_point,
1174
GL_ARRAY_BUFFER_ARB, data, GPU_buffer_copy_color3);
1177
void GPU_color_switch(int mode)
1180
if (!(GLStates & GPU_BUFFER_COLOR_STATE))
1181
glEnableClientState(GL_COLOR_ARRAY);
1182
GLStates |= GPU_BUFFER_COLOR_STATE;
1185
if (GLStates & GPU_BUFFER_COLOR_STATE)
1186
glDisableClientState(GL_COLOR_ARRAY);
1187
GLStates &= (!GPU_BUFFER_COLOR_STATE);
1191
/* return 1 if drawing should be done using old immediate-mode
1192
* code, 0 otherwise */
1193
int GPU_buffer_legacy(DerivedMesh *dm)
1195
int test= (U.gameflags & USER_DISABLE_VBO);
1199
if (dm->drawObject == 0)
1200
dm->drawObject = GPU_drawobject_new(dm);
1201
return dm->drawObject->legacy;
1204
void *GPU_buffer_lock(GPUBuffer *buffer)
1212
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
1213
varray = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1217
return buffer->pointer;
1221
void *GPU_buffer_lock_stream(GPUBuffer *buffer)
1229
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
1230
/* discard previous data, avoid stalling gpu */
1231
glBufferDataARB(GL_ARRAY_BUFFER_ARB, buffer->size, 0, GL_STREAM_DRAW_ARB);
1232
varray = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1236
return buffer->pointer;
1240
void GPU_buffer_unlock(GPUBuffer *buffer)
1244
/* note: this operation can fail, could return
1245
* an error code from this function? */
1246
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
1248
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1252
/* used for drawing edges */
1253
void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count)
1255
glDrawElements(mode, count, GL_UNSIGNED_INT,
1257
(void*)(start * sizeof(unsigned int)) :
1258
((int*)elements->pointer) + start));
1262
/* XXX: the rest of the code in this file is used for optimized PBVH
1263
* drawing and doesn't interact at all with the buffer code above */
399
1265
/* Convenience struct for building the VBO. */
400
1266
typedef struct {
586
1457
buffers->grid_indices = grid_indices;
587
1458
buffers->totgrid = totgrid;
588
1459
buffers->gridsize = gridsize;
590
//printf("node updated %p\n", buffers_v);
593
void *GPU_build_grid_buffers(DMGridData **grids,
594
int *grid_indices, int totgrid, int gridsize)
1460
buffers->grid_flag_mats = grid_flag_mats;
1462
//printf("node updated %p\n", buffers);
1465
/* Returns the number of visible quads in the nodes' grids. */
1466
static int gpu_count_grid_quads(BLI_bitmap *grid_hidden,
1467
int *grid_indices, int totgrid,
1470
int gridarea = (gridsize-1) * (gridsize-1);
1471
int i, x, y, totquad;
1473
/* grid hidden layer is present, so have to check each grid for
1476
for (i = 0, totquad = 0; i < totgrid; i++) {
1477
const BLI_bitmap gh = grid_hidden[grid_indices[i]];
1480
/* grid hidden are present, have to check each element */
1481
for (y = 0; y < gridsize-1; y++) {
1482
for (x = 0; x < gridsize-1; x++) {
1483
if (!paint_is_grid_face_hidden(gh, gridsize, x, y))
1489
totquad += gridarea;
1495
/* Build the element array buffer of grid indices using either
1496
* unsigned shorts or unsigned ints. */
1497
#define FILL_QUAD_BUFFER(type_, tot_quad_, buffer_) \
1503
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \
1504
sizeof(type_) * (tot_quad_) * 4, NULL, \
1505
GL_STATIC_DRAW_ARB); \
1507
/* Fill the quad buffer */ \
1508
quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \
1509
GL_WRITE_ONLY_ARB); \
1511
for (i = 0; i < totgrid; ++i) { \
1512
BLI_bitmap gh = NULL; \
1514
gh = grid_hidden[(grid_indices)[i]]; \
1516
for (j = 0; j < gridsize-1; ++j) { \
1517
for (k = 0; k < gridsize-1; ++k) { \
1518
/* Skip hidden grid face */ \
1520
paint_is_grid_face_hidden(gh, \
1524
*(quad_data++)= offset + j*gridsize + k+1; \
1525
*(quad_data++)= offset + j*gridsize + k; \
1526
*(quad_data++)= offset + (j+1)*gridsize + k; \
1527
*(quad_data++)= offset + (j+1)*gridsize + k+1; \
1531
offset += gridsize*gridsize; \
1533
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); \
1536
glDeleteBuffersARB(1, &(buffer_)); \
1540
/* end FILL_QUAD_BUFFER */
1542
static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad)
1544
static int prev_gridsize = -1;
1545
static GLenum prev_index_type = 0;
1546
static GLuint buffer = 0;
1547
static unsigned prev_totquad;
1549
/* used in the FILL_QUAD_BUFFER macro */
1550
const BLI_bitmap *grid_hidden = NULL;
1551
int *grid_indices = NULL;
1554
/* VBO is disabled; delete the previous buffer (if it exists) and
1555
* return an invalid handle */
1556
if (!GLEW_ARB_vertex_buffer_object || (U.gameflags & USER_DISABLE_VBO)) {
1558
glDeleteBuffersARB(1, &buffer);
1562
/* VBO is already built */
1563
if (buffer && prev_gridsize == gridsize) {
1564
*index_type = prev_index_type;
1565
*totquad = prev_totquad;
1570
glGenBuffersARB(1, &buffer);
1572
*totquad= (gridsize-1)*(gridsize-1);
1574
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer);
1576
if (gridsize * gridsize < USHRT_MAX) {
1577
*index_type = GL_UNSIGNED_SHORT;
1578
FILL_QUAD_BUFFER(unsigned short, *totquad, buffer);
1581
*index_type = GL_UNSIGNED_INT;
1582
FILL_QUAD_BUFFER(unsigned int, *totquad, buffer);
1585
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1588
prev_gridsize = gridsize;
1589
prev_index_type = *index_type;
1590
prev_totquad = *totquad;
1594
GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid,
1595
BLI_bitmap *grid_hidden, int gridsize)
596
1597
GPU_Buffers *buffers;
597
int i, j, k, totquad, offset= 0;
1599
int fully_visible_totquad = (gridsize-1) * (gridsize-1) * totgrid;
599
1601
buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers");
1602
buffers->grid_hidden = grid_hidden;
1603
buffers->gridsize = gridsize;
1604
buffers->totgrid = totgrid;
601
1606
/* Count the number of quads */
602
totquad= (gridsize-1)*(gridsize-1)*totgrid;
1607
totquad= gpu_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize);
604
/* Generate index buffer object */
605
if(GL_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO))
1609
if (totquad == fully_visible_totquad) {
1610
buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad);
1611
buffers->has_hidden = 0;
1613
else if (GLEW_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO)) {
606
1615
glGenBuffersARB(1, &buffers->index_buf);
608
if(buffers->index_buf) {
609
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
611
if(totquad < USHRT_MAX) {
612
unsigned short *quad_data;
614
buffers->index_type = GL_UNSIGNED_SHORT;
615
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
616
sizeof(unsigned short) * totquad * 4, NULL, GL_STATIC_DRAW_ARB);
618
/* Fill the quad buffer */
619
quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
621
for(i = 0; i < totgrid; ++i) {
622
for(j = 0; j < gridsize-1; ++j) {
623
for(k = 0; k < gridsize-1; ++k) {
624
*(quad_data++)= offset + j*gridsize + k+1;
625
*(quad_data++)= offset + j*gridsize + k;
626
*(quad_data++)= offset + (j+1)*gridsize + k;
627
*(quad_data++)= offset + (j+1)*gridsize + k+1;
631
offset += gridsize*gridsize;
633
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
636
glDeleteBuffersARB(1, &buffers->index_buf);
637
buffers->index_buf = 0;
641
unsigned int *quad_data;
643
buffers->index_type = GL_UNSIGNED_INT;
644
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
645
sizeof(unsigned int) * totquad * 4, NULL, GL_STATIC_DRAW_ARB);
647
/* Fill the quad buffer */
648
quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
651
for(i = 0; i < totgrid; ++i) {
652
for(j = 0; j < gridsize-1; ++j) {
653
for(k = 0; k < gridsize-1; ++k) {
654
*(quad_data++)= offset + j*gridsize + k+1;
655
*(quad_data++)= offset + j*gridsize + k;
656
*(quad_data++)= offset + (j+1)*gridsize + k;
657
*(quad_data++)= offset + (j+1)*gridsize + k+1;
661
offset += gridsize*gridsize;
663
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
666
glDeleteBuffersARB(1, &buffers->index_buf);
667
buffers->index_buf = 0;
671
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1616
if (buffers->index_buf) {
1617
buffers->tot_quad= totquad;
1619
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
1621
if (totgrid * gridsize * gridsize < USHRT_MAX) {
1622
buffers->index_type = GL_UNSIGNED_SHORT;
1623
FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf);
1626
buffers->index_type = GL_UNSIGNED_INT;
1627
FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf);
1630
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1633
buffers->has_hidden = 1;
675
if(buffers->index_buf)
1636
/* Build coord/normal VBO */
1637
if (buffers->index_buf)
676
1638
glGenBuffersARB(1, &buffers->vert_buf);
678
buffers->tot_quad = totquad;
683
void GPU_draw_buffers(void *buffers_v)
685
GPU_Buffers *buffers = buffers_v;
687
if(buffers->vert_buf && buffers->index_buf) {
1643
#undef FILL_QUAD_BUFFER
1645
static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth)
1647
const MVert *mvert = buffers->mvert;
1650
for (i = 0; i < buffers->totface; ++i) {
1651
MFace *f = buffers->mface + buffers->face_indices[i];
1652
int S = f->v4 ? 4 : 3;
1653
unsigned int *fv = &f->v1;
1655
if (paint_is_face_hidden(f, buffers->mvert))
1658
glBegin((f->v4)? GL_QUADS: GL_TRIANGLES);
1661
for (j = 0; j < S; j++) {
1662
glNormal3sv(mvert[fv[j]].no);
1663
glVertex3fv(mvert[fv[j]].co);
1669
/* calculate face normal */
1671
normal_quad_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co,
1672
mvert[fv[2]].co, mvert[fv[3]].co);
1675
normal_tri_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co, mvert[fv[2]].co);
1678
for (j = 0; j < S; j++)
1679
glVertex3fv(mvert[fv[j]].co);
1686
static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth)
1688
int i, j, x, y, gridsize = buffers->gridsize;
1690
for (i = 0; i < buffers->totgrid; ++i) {
1691
int g = buffers->grid_indices[i];
1692
const DMGridData *grid = buffers->grids[g];
1693
BLI_bitmap gh = buffers->grid_hidden[g];
1695
/* TODO: could use strips with hiding as well */
1700
for (y = 0; y < gridsize-1; y++) {
1701
for (x = 0; x < gridsize-1; x++) {
1702
const DMGridData *e[4] = {
1703
&grid[y*gridsize + x],
1704
&grid[(y+1)*gridsize + x],
1705
&grid[(y+1)*gridsize + x+1],
1706
&grid[y*gridsize + x+1]
1709
/* skip face if any of its corners are hidden */
1710
if (paint_is_grid_face_hidden(gh, gridsize, x, y))
1714
for (j = 0; j < 4; j++) {
1715
glNormal3fv(e[j]->no);
1716
glVertex3fv(e[j]->co);
1721
normal_quad_v3(fno, e[0]->co, e[1]->co, e[2]->co, e[3]->co);
1724
for (j = 0; j < 4; j++)
1725
glVertex3fv(e[j]->co);
1733
for (y = 0; y < gridsize-1; y++) {
1734
glBegin(GL_QUAD_STRIP);
1735
for (x = 0; x < gridsize; x++) {
1736
const DMGridData *a = &grid[y*gridsize + x];
1737
const DMGridData *b = &grid[(y+1)*gridsize + x];
1748
for (y = 0; y < gridsize-1; y++) {
1749
glBegin(GL_QUAD_STRIP);
1750
for (x = 0; x < gridsize; x++) {
1751
const DMGridData *a = &grid[y*gridsize + x];
1752
const DMGridData *b = &grid[(y+1)*gridsize + x];
1755
const DMGridData *c = &grid[y*gridsize + x-1];
1756
const DMGridData *d = &grid[(y+1)*gridsize + x-1];
1758
normal_quad_v3(fno, d->co, b->co, a->co, c->co);
1771
void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
1775
if (buffers->totface) {
1776
const MFace *f = &buffers->mface[buffers->face_indices[0]];
1777
if (!setMaterial(f->mat_nr + 1, NULL))
1780
smooth = f->flag & ME_SMOOTH;
1781
glShadeModel(smooth ? GL_SMOOTH: GL_FLAT);
1783
else if (buffers->totgrid) {
1784
const DMFlagMat *f = &buffers->grid_flag_mats[buffers->grid_indices[0]];
1785
if (!setMaterial(f->mat_nr + 1, NULL))
1788
smooth = f->flag & ME_SMOOTH;
1789
glShadeModel(smooth ? GL_SMOOTH: GL_FLAT);
1792
if (buffers->vert_buf && buffers->index_buf) {
688
1793
glEnableClientState(GL_VERTEX_ARRAY);
689
1794
glEnableClientState(GL_NORMAL_ARRAY);
691
1796
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
692
1797
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
694
if(buffers->tot_quad) {
695
glVertexPointer(3, GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, co));
696
glNormalPointer(GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, no));
1799
if (buffers->tot_quad) {
1800
unsigned offset = 0;
1801
int i, last = buffers->has_hidden ? 1 : buffers->totgrid;
1802
for (i = 0; i < last; i++) {
1803
glVertexPointer(3, GL_FLOAT, sizeof(DMGridData), offset + (char*)offsetof(DMGridData, co));
1804
glNormalPointer(GL_FLOAT, sizeof(DMGridData), offset + (char*)offsetof(DMGridData, no));
1806
glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0);
698
glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0);
1808
offset += buffers->gridsize * buffers->gridsize * sizeof(DMGridData);
701
1812
glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), (void*)offsetof(VertexBufferFormat, co));
710
1821
glDisableClientState(GL_VERTEX_ARRAY);
711
1822
glDisableClientState(GL_NORMAL_ARRAY);
713
else if(buffers->totface) {
714
/* fallback if we are out of memory */
717
for(i = 0; i < buffers->totface; ++i) {
718
MFace *f = buffers->mface + buffers->face_indices[i];
720
glBegin((f->v4)? GL_QUADS: GL_TRIANGLES);
721
glNormal3sv(buffers->mvert[f->v1].no);
722
glVertex3fv(buffers->mvert[f->v1].co);
723
glNormal3sv(buffers->mvert[f->v2].no);
724
glVertex3fv(buffers->mvert[f->v2].co);
725
glNormal3sv(buffers->mvert[f->v3].no);
726
glVertex3fv(buffers->mvert[f->v3].co);
728
glNormal3sv(buffers->mvert[f->v4].no);
729
glVertex3fv(buffers->mvert[f->v4].co);
1824
/* fallbacks if we are out of memory or VBO is disabled */
1825
else if (buffers->totface) {
1826
gpu_draw_buffers_legacy_mesh(buffers, smooth);
734
else if(buffers->totgrid) {
735
int i, x, y, gridsize = buffers->gridsize;
737
for(i = 0; i < buffers->totgrid; ++i) {
738
DMGridData *grid = buffers->grids[buffers->grid_indices[i]];
740
for(y = 0; y < gridsize-1; y++) {
741
glBegin(GL_QUAD_STRIP);
742
for(x = 0; x < gridsize; x++) {
743
DMGridData *a = &grid[y*gridsize + x];
744
DMGridData *b = &grid[(y+1)*gridsize + x];
1828
else if (buffers->totgrid) {
1829
gpu_draw_buffers_legacy_grids(buffers, smooth);
757
void GPU_free_buffers(void *buffers_v)
1833
void GPU_free_buffers(GPU_Buffers *buffers)
760
GPU_Buffers *buffers = buffers_v;
762
if(buffers->vert_buf)
1836
if (buffers->vert_buf)
763
1837
glDeleteBuffersARB(1, &buffers->vert_buf);
764
if(buffers->index_buf)
1838
if (buffers->index_buf && (buffers->tot_tri || buffers->has_hidden))
765
1839
glDeleteBuffersARB(1, &buffers->index_buf);
767
1841
MEM_freeN(buffers);
771
GPUBuffer *GPU_buffer_setup( DerivedMesh *dm, GPUDrawObject *object, int size, GLenum target, void *user, void (*copy_f)(DerivedMesh *, float *, int *, int *, void *) )
781
DEBUG_VBO("GPU_buffer_setup\n");
783
if( globalPool == 0 )
784
globalPool = GPU_buffer_pool_new();
786
buffer = GPU_buffer_alloc(size,globalPool);
788
dm->drawObject->legacy = 1;
790
if( dm->drawObject->legacy ) {
794
index = MEM_mallocN(sizeof(int)*object->nmaterials,"GPU_buffer_setup");
795
for( i = 0; i < object->nmaterials; i++ ) {
796
index[i] = object->materials[i].start*3;
797
redir[object->materials[i].mat_nr+16383] = i;
802
while( success == 0 ) {
803
glBindBufferARB( target, buffer->id );
804
glBufferDataARB( target, buffer->size, 0, GL_STATIC_DRAW_ARB ); /* discard previous data, avoid stalling gpu */
805
varray = glMapBufferARB( target, GL_WRITE_ONLY_ARB );
807
DEBUG_VBO( "Failed to map buffer to client address space\n" );
808
GPU_buffer_free( buffer, globalPool );
809
GPU_buffer_pool_delete_last( globalPool );
811
if( globalPool->size > 0 ) {
812
GPU_buffer_pool_delete_last( globalPool );
813
buffer = GPU_buffer_alloc( size, globalPool );
815
dm->drawObject->legacy = 1;
820
dm->drawObject->legacy = 1;
829
if( dm->drawObject->legacy == 0 ) {
832
(*copy_f)( dm, varray, index, redir, user );
833
uploaded = glUnmapBufferARB( target ); /* returns false if data got corruped during transfer */
836
glBindBufferARB(target, 0);
839
if( buffer->pointer != 0 ) {
840
varray = buffer->pointer;
841
(*copy_f)( dm, varray, index, redir, user );
844
dm->drawObject->legacy = 1;
853
void GPU_buffer_copy_vertex( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
861
DEBUG_VBO("GPU_buffer_copy_vertex\n");
863
mvert = dm->getVertArray(dm);
864
mface = dm->getFaceArray(dm);
866
numfaces= dm->getNumFaces(dm);
867
for( i=0; i < numfaces; i++ ) {
868
start = index[redir[mface[i].mat_nr+16383]];
870
index[redir[mface[i].mat_nr+16383]] += 18;
872
index[redir[mface[i].mat_nr+16383]] += 9;
875
VECCOPY(&varray[start],mvert[mface[i].v1].co);
876
VECCOPY(&varray[start+3],mvert[mface[i].v2].co);
877
VECCOPY(&varray[start+6],mvert[mface[i].v3].co);
881
VECCOPY(&varray[start+9],mvert[mface[i].v3].co);
882
VECCOPY(&varray[start+12],mvert[mface[i].v4].co);
883
VECCOPY(&varray[start+15],mvert[mface[i].v1].co);
886
j = dm->drawObject->nelements*3;
887
for( i = 0; i < dm->drawObject->nindices; i++ ) {
888
if( dm->drawObject->indices[i].element >= dm->drawObject->nelements ) {
889
VECCOPY(&varray[j],mvert[i].co);
895
GPUBuffer *GPU_buffer_vertex( DerivedMesh *dm )
897
DEBUG_VBO("GPU_buffer_vertex\n");
899
return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*3*(dm->drawObject->nelements+dm->drawObject->nlooseverts), GL_ARRAY_BUFFER_ARB, 0, GPU_buffer_copy_vertex);
902
void GPU_buffer_copy_normal( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
908
float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
909
MVert *mvert = dm->getVertArray(dm);
910
MFace *mface = dm->getFaceArray(dm);
912
DEBUG_VBO("GPU_buffer_copy_normal\n");
914
numfaces= dm->getNumFaces(dm);
915
for( i=0; i < numfaces; i++ ) {
916
start = index[redir[mface[i].mat_nr+16383]];
918
index[redir[mface[i].mat_nr+16383]] += 18;
920
index[redir[mface[i].mat_nr+16383]] += 9;
923
if( mface[i].flag & ME_SMOOTH ) {
924
VECCOPY(&varray[start],mvert[mface[i].v1].no);
925
VECCOPY(&varray[start+3],mvert[mface[i].v2].no);
926
VECCOPY(&varray[start+6],mvert[mface[i].v3].no);
930
VECCOPY(&varray[start],&nors[i*3]);
931
VECCOPY(&varray[start+3],&nors[i*3]);
932
VECCOPY(&varray[start+6],&nors[i*3]);
935
normal_quad_v3( norm,mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co, mvert[mface[i].v4].co);
937
normal_tri_v3( norm,mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co);
938
VECCOPY(&varray[start],norm);
939
VECCOPY(&varray[start+3],norm);
940
VECCOPY(&varray[start+6],norm);
945
if( mface[i].flag & ME_SMOOTH ) {
946
VECCOPY(&varray[start+9],mvert[mface[i].v3].no);
947
VECCOPY(&varray[start+12],mvert[mface[i].v4].no);
948
VECCOPY(&varray[start+15],mvert[mface[i].v1].no);
951
VECCOPY(&varray[start+9],norm);
952
VECCOPY(&varray[start+12],norm);
953
VECCOPY(&varray[start+15],norm);
959
GPUBuffer *GPU_buffer_normal( DerivedMesh *dm )
961
DEBUG_VBO("GPU_buffer_normal\n");
963
return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*3*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, 0, GPU_buffer_copy_normal);
966
void GPU_buffer_copy_uv( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
974
DEBUG_VBO("GPU_buffer_copy_uv\n");
976
mface = dm->getFaceArray(dm);
977
mtface = DM_get_face_data_layer(dm, CD_MTFACE);
980
DEBUG_VBO("Texture coordinates do not exist for this mesh");
984
numfaces= dm->getNumFaces(dm);
985
for( i=0; i < numfaces; i++ ) {
986
start = index[redir[mface[i].mat_nr+16383]];
988
index[redir[mface[i].mat_nr+16383]] += 12;
990
index[redir[mface[i].mat_nr+16383]] += 6;
993
VECCOPY2D(&varray[start],mtface[i].uv[0]);
994
VECCOPY2D(&varray[start+2],mtface[i].uv[1]);
995
VECCOPY2D(&varray[start+4],mtface[i].uv[2]);
999
VECCOPY2D(&varray[start+6],mtface[i].uv[2]);
1000
VECCOPY2D(&varray[start+8],mtface[i].uv[3]);
1001
VECCOPY2D(&varray[start+10],mtface[i].uv[0]);
1006
GPUBuffer *GPU_buffer_uv( DerivedMesh *dm )
1008
DEBUG_VBO("GPU_buffer_uv\n");
1009
if( DM_get_face_data_layer(dm, CD_MTFACE) != 0 ) /* was sizeof(float)*2 but caused buffer overrun */
1010
return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*3*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, 0, GPU_buffer_copy_uv);
1015
void GPU_buffer_copy_color3( DerivedMesh *dm, float *varray_, int *index, int *redir, void *user )
1018
unsigned char *varray = (unsigned char *)varray_;
1019
unsigned char *mcol = (unsigned char *)user;
1020
MFace *mface = dm->getFaceArray(dm);
1022
DEBUG_VBO("GPU_buffer_copy_color3\n");
1024
numfaces= dm->getNumFaces(dm);
1025
for( i=0; i < numfaces; i++ ) {
1026
int start = index[redir[mface[i].mat_nr+16383]];
1028
index[redir[mface[i].mat_nr+16383]] += 18;
1030
index[redir[mface[i].mat_nr+16383]] += 9;
1033
VECCOPY(&varray[start],&mcol[i*12]);
1034
VECCOPY(&varray[start+3],&mcol[i*12+3]);
1035
VECCOPY(&varray[start+6],&mcol[i*12+6]);
1038
VECCOPY(&varray[start+9],&mcol[i*12+6]);
1039
VECCOPY(&varray[start+12],&mcol[i*12+9]);
1040
VECCOPY(&varray[start+15],&mcol[i*12]);
1045
void GPU_buffer_copy_color4( DerivedMesh *dm, float *varray_, int *index, int *redir, void *user )
1048
unsigned char *varray = (unsigned char *)varray_;
1049
unsigned char *mcol = (unsigned char *)user;
1050
MFace *mface = dm->getFaceArray(dm);
1052
DEBUG_VBO("GPU_buffer_copy_color4\n");
1054
numfaces= dm->getNumFaces(dm);
1055
for( i=0; i < numfaces; i++ ) {
1056
int start = index[redir[mface[i].mat_nr+16383]];
1058
index[redir[mface[i].mat_nr+16383]] += 18;
1060
index[redir[mface[i].mat_nr+16383]] += 9;
1063
VECCOPY(&varray[start],&mcol[i*16]);
1064
VECCOPY(&varray[start+3],&mcol[i*16+4]);
1065
VECCOPY(&varray[start+6],&mcol[i*16+8]);
1068
VECCOPY(&varray[start+9],&mcol[i*16+8]);
1069
VECCOPY(&varray[start+12],&mcol[i*16+12]);
1070
VECCOPY(&varray[start+15],&mcol[i*16]);
1075
GPUBuffer *GPU_buffer_color( DerivedMesh *dm )
1077
unsigned char *colors;
1081
DEBUG_VBO("GPU_buffer_color\n");
1083
mcol = DM_get_face_data_layer(dm, CD_ID_MCOL);
1084
dm->drawObject->colType = CD_ID_MCOL;
1086
mcol = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
1087
dm->drawObject->colType = CD_WEIGHT_MCOL;
1090
mcol = DM_get_face_data_layer(dm, CD_MCOL);
1091
dm->drawObject->colType = CD_MCOL;
1094
numfaces= dm->getNumFaces(dm);
1095
colors = MEM_mallocN(numfaces*12*sizeof(unsigned char), "GPU_buffer_color");
1096
for( i=0; i < numfaces*4; i++ ) {
1097
colors[i*3] = mcol[i].b;
1098
colors[i*3+1] = mcol[i].g;
1099
colors[i*3+2] = mcol[i].r;
1102
result = GPU_buffer_setup( dm, dm->drawObject, sizeof(char)*3*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, colors, GPU_buffer_copy_color3 );
1108
void GPU_buffer_copy_edge( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
1114
unsigned int *varray_ = (unsigned int *)varray;
1117
DEBUG_VBO("GPU_buffer_copy_edge\n");
1119
mvert = dm->getVertArray(dm);
1120
medge = dm->getEdgeArray(dm);
1122
numedges= dm->getNumEdges(dm);
1123
for(i = 0; i < numedges; i++) {
1124
varray_[i*2] = (unsigned int)dm->drawObject->indices[medge[i].v1].element;
1125
varray_[i*2+1] = (unsigned int)dm->drawObject->indices[medge[i].v2].element;
1129
GPUBuffer *GPU_buffer_edge( DerivedMesh *dm )
1131
DEBUG_VBO("GPU_buffer_edge\n");
1133
return GPU_buffer_setup( dm, dm->drawObject, sizeof(int)*2*dm->drawObject->nedges, GL_ELEMENT_ARRAY_BUFFER_ARB, 0, GPU_buffer_copy_edge);
1136
void GPU_buffer_copy_uvedge( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
1138
MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
1141
DEBUG_VBO("GPU_buffer_copy_uvedge\n");
1144
for(i = 0; i < dm->numFaceData; i++, tf++) {
1146
dm->getFace(dm,i,&mf);
1148
VECCOPY2D(&varray[j],tf->uv[0]);
1149
VECCOPY2D(&varray[j+2],tf->uv[1]);
1151
VECCOPY2D(&varray[j+4],tf->uv[1]);
1152
VECCOPY2D(&varray[j+6],tf->uv[2]);
1155
VECCOPY2D(&varray[j+8],tf->uv[2]);
1156
VECCOPY2D(&varray[j+10],tf->uv[0]);
1159
VECCOPY2D(&varray[j+8],tf->uv[2]);
1160
VECCOPY2D(&varray[j+10],tf->uv[3]);
1162
VECCOPY2D(&varray[j+12],tf->uv[3]);
1163
VECCOPY2D(&varray[j+14],tf->uv[0]);
1169
DEBUG_VBO("Could not get MTFACE data layer");
1173
GPUBuffer *GPU_buffer_uvedge( DerivedMesh *dm )
1175
DEBUG_VBO("GPU_buffer_uvedge\n");
1177
return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*2*(dm->drawObject->nelements/3)*2, GL_ARRAY_BUFFER_ARB, 0, GPU_buffer_copy_uvedge);
1181
void GPU_vertex_setup( DerivedMesh *dm )
1183
DEBUG_VBO("GPU_vertex_setup\n");
1184
if( dm->drawObject == 0 )
1185
dm->drawObject = GPU_drawobject_new( dm );
1186
if( dm->drawObject->vertices == 0 )
1187
dm->drawObject->vertices = GPU_buffer_vertex( dm );
1188
if( dm->drawObject->vertices == 0 ) {
1189
DEBUG_VBO( "Failed to setup vertices\n" );
1193
glEnableClientState( GL_VERTEX_ARRAY );
1195
glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->vertices->id );
1196
glVertexPointer( 3, GL_FLOAT, 0, 0 );
1199
glVertexPointer( 3, GL_FLOAT, 0, dm->drawObject->vertices->pointer );
1202
GLStates |= GPU_BUFFER_VERTEX_STATE;
1205
void GPU_normal_setup( DerivedMesh *dm )
1207
DEBUG_VBO("GPU_normal_setup\n");
1208
if( dm->drawObject == 0 )
1209
dm->drawObject = GPU_drawobject_new( dm );
1210
if( dm->drawObject->normals == 0 )
1211
dm->drawObject->normals = GPU_buffer_normal( dm );
1212
if( dm->drawObject->normals == 0 ) {
1213
DEBUG_VBO( "Failed to setup normals\n" );
1216
glEnableClientState( GL_NORMAL_ARRAY );
1218
glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id );
1219
glNormalPointer( GL_FLOAT, 0, 0 );
1222
glNormalPointer( GL_FLOAT, 0, dm->drawObject->normals->pointer );
1225
GLStates |= GPU_BUFFER_NORMAL_STATE;
1228
void GPU_uv_setup( DerivedMesh *dm )
1230
DEBUG_VBO("GPU_uv_setup\n");
1231
if( dm->drawObject == 0 )
1232
dm->drawObject = GPU_drawobject_new( dm );
1233
if( dm->drawObject->uv == 0 )
1234
dm->drawObject->uv = GPU_buffer_uv( dm );
1236
if( dm->drawObject->uv != 0 ) {
1237
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1239
glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id );
1240
glTexCoordPointer( 2, GL_FLOAT, 0, 0 );
1243
glTexCoordPointer( 2, GL_FLOAT, 0, dm->drawObject->uv->pointer );
1246
GLStates |= GPU_BUFFER_TEXCOORD_STATE;
1250
void GPU_color_setup( DerivedMesh *dm )
1252
DEBUG_VBO("GPU_color_setup\n");
1253
if( dm->drawObject == 0 )
1254
dm->drawObject = GPU_drawobject_new( dm );
1255
if( dm->drawObject->colors == 0 )
1256
dm->drawObject->colors = GPU_buffer_color( dm );
1257
if( dm->drawObject->colors == 0 ) {
1258
DEBUG_VBO( "Failed to setup colors\n" );
1261
glEnableClientState( GL_COLOR_ARRAY );
1263
glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->colors->id );
1264
glColorPointer( 3, GL_UNSIGNED_BYTE, 0, 0 );
1267
glColorPointer( 3, GL_UNSIGNED_BYTE, 0, dm->drawObject->colors->pointer );
1270
GLStates |= GPU_BUFFER_COLOR_STATE;
1273
void GPU_edge_setup( DerivedMesh *dm )
1275
DEBUG_VBO("GPU_edge_setup\n");
1276
if( dm->drawObject == 0 )
1277
dm->drawObject = GPU_drawobject_new( dm );
1278
if( dm->drawObject->edges == 0 )
1279
dm->drawObject->edges = GPU_buffer_edge( dm );
1280
if( dm->drawObject->edges == 0 ) {
1281
DEBUG_VBO( "Failed to setup edges\n" );
1284
if( dm->drawObject->vertices == 0 )
1285
dm->drawObject->vertices = GPU_buffer_vertex( dm );
1286
if( dm->drawObject->vertices == 0 ) {
1287
DEBUG_VBO( "Failed to setup vertices\n" );
1291
glEnableClientState( GL_VERTEX_ARRAY );
1293
glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->vertices->id );
1294
glVertexPointer( 3, GL_FLOAT, 0, 0 );
1297
glVertexPointer( 3, GL_FLOAT, 0, dm->drawObject->vertices->pointer );
1300
GLStates |= GPU_BUFFER_VERTEX_STATE;
1303
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->edges->id );
1306
GLStates |= GPU_BUFFER_ELEMENT_STATE;
1309
void GPU_uvedge_setup( DerivedMesh *dm )
1311
DEBUG_VBO("GPU_uvedge_setup\n");
1312
if( dm->drawObject == 0 )
1313
dm->drawObject = GPU_drawobject_new( dm );
1314
if( dm->drawObject->uvedges == 0 )
1315
dm->drawObject->uvedges = GPU_buffer_uvedge( dm );
1316
if( dm->drawObject->uvedges == 0 ) {
1317
DEBUG_VBO( "Failed to setup UV edges\n" );
1321
glEnableClientState( GL_VERTEX_ARRAY );
1323
glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->uvedges->id );
1324
glVertexPointer( 2, GL_FLOAT, 0, 0 );
1327
glVertexPointer( 2, GL_FLOAT, 0, dm->drawObject->uvedges->pointer );
1330
GLStates |= GPU_BUFFER_VERTEX_STATE;
1333
void GPU_interleaved_setup( GPUBuffer *buffer, int data[] ) {
1335
int elementsize = 0;
1336
intptr_t offset = 0;
1338
DEBUG_VBO("GPU_interleaved_setup\n");
1340
for( i = 0; data[i] != GPU_BUFFER_INTER_END; i++ ) {
1342
case GPU_BUFFER_INTER_V3F:
1343
elementsize += 3*sizeof(float);
1345
case GPU_BUFFER_INTER_N3F:
1346
elementsize += 3*sizeof(float);
1348
case GPU_BUFFER_INTER_T2F:
1349
elementsize += 2*sizeof(float);
1351
case GPU_BUFFER_INTER_C3UB:
1352
elementsize += 3*sizeof(unsigned char);
1354
case GPU_BUFFER_INTER_C4UB:
1355
elementsize += 4*sizeof(unsigned char);
1358
DEBUG_VBO( "Unknown element in data type array in GPU_interleaved_setup\n" );
1363
glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffer->id );
1364
for( i = 0; data[i] != GPU_BUFFER_INTER_END; i++ ) {
1366
case GPU_BUFFER_INTER_V3F:
1367
glEnableClientState( GL_VERTEX_ARRAY );
1368
glVertexPointer( 3, GL_FLOAT, elementsize, (void *)offset );
1369
GLStates |= GPU_BUFFER_VERTEX_STATE;
1370
offset += 3*sizeof(float);
1372
case GPU_BUFFER_INTER_N3F:
1373
glEnableClientState( GL_NORMAL_ARRAY );
1374
glNormalPointer( GL_FLOAT, elementsize, (void *)offset );
1375
GLStates |= GPU_BUFFER_NORMAL_STATE;
1376
offset += 3*sizeof(float);
1378
case GPU_BUFFER_INTER_T2F:
1379
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1380
glTexCoordPointer( 2, GL_FLOAT, elementsize, (void *)offset );
1381
GLStates |= GPU_BUFFER_TEXCOORD_STATE;
1382
offset += 2*sizeof(float);
1384
case GPU_BUFFER_INTER_C3UB:
1385
glEnableClientState( GL_COLOR_ARRAY );
1386
glColorPointer( 3, GL_UNSIGNED_BYTE, elementsize, (void *)offset );
1387
GLStates |= GPU_BUFFER_COLOR_STATE;
1388
offset += 3*sizeof(unsigned char);
1390
case GPU_BUFFER_INTER_C4UB:
1391
glEnableClientState( GL_COLOR_ARRAY );
1392
glColorPointer( 4, GL_UNSIGNED_BYTE, elementsize, (void *)offset );
1393
GLStates |= GPU_BUFFER_COLOR_STATE;
1394
offset += 4*sizeof(unsigned char);
1400
for( i = 0; data[i] != GPU_BUFFER_INTER_END; i++ ) {
1402
case GPU_BUFFER_INTER_V3F:
1403
glEnableClientState( GL_VERTEX_ARRAY );
1404
glVertexPointer( 3, GL_FLOAT, elementsize, offset+(char *)buffer->pointer );
1405
GLStates |= GPU_BUFFER_VERTEX_STATE;
1406
offset += 3*sizeof(float);
1408
case GPU_BUFFER_INTER_N3F:
1409
glEnableClientState( GL_NORMAL_ARRAY );
1410
glNormalPointer( GL_FLOAT, elementsize, offset+(char *)buffer->pointer );
1411
GLStates |= GPU_BUFFER_NORMAL_STATE;
1412
offset += 3*sizeof(float);
1414
case GPU_BUFFER_INTER_T2F:
1415
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1416
glTexCoordPointer( 2, GL_FLOAT, elementsize, offset+(char *)buffer->pointer );
1417
GLStates |= GPU_BUFFER_TEXCOORD_STATE;
1418
offset += 2*sizeof(float);
1420
case GPU_BUFFER_INTER_C3UB:
1421
glEnableClientState( GL_COLOR_ARRAY );
1422
glColorPointer( 3, GL_UNSIGNED_BYTE, elementsize, offset+(char *)buffer->pointer );
1423
GLStates |= GPU_BUFFER_COLOR_STATE;
1424
offset += 3*sizeof(unsigned char);
1426
case GPU_BUFFER_INTER_C4UB:
1427
glEnableClientState( GL_COLOR_ARRAY );
1428
glColorPointer( 4, GL_UNSIGNED_BYTE, elementsize, offset+(char *)buffer->pointer );
1429
GLStates |= GPU_BUFFER_COLOR_STATE;
1430
offset += 4*sizeof(unsigned char);
1437
static int GPU_typesize( int type ) {
1440
return sizeof(float);
1443
case GL_UNSIGNED_INT:
1444
return sizeof(unsigned int);
1446
return sizeof(char);
1447
case GL_UNSIGNED_BYTE:
1448
return sizeof(unsigned char);
1454
int GPU_attrib_element_size( GPUAttrib data[], int numdata ) {
1455
int i, elementsize = 0;
1457
for( i = 0; i < numdata; i++ ) {
1458
int typesize = GPU_typesize(data[i].type);
1460
DEBUG_VBO( "Unknown element in data type array in GPU_attrib_element_size\n" );
1462
elementsize += typesize*data[i].size;
1468
void GPU_interleaved_attrib_setup( GPUBuffer *buffer, GPUAttrib data[], int numdata ) {
1471
intptr_t offset = 0;
1473
DEBUG_VBO("GPU_interleaved_attrib_setup\n");
1475
for( i = 0; i < MAX_GPU_ATTRIB_DATA; i++ ) {
1476
if( attribData[i].index != -1 ) {
1477
glDisableVertexAttribArrayARB( attribData[i].index );
1482
elementsize = GPU_attrib_element_size( data, numdata );
1485
glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffer->id );
1486
for( i = 0; i < numdata; i++ ) {
1487
glEnableVertexAttribArrayARB( data[i].index );
1488
glVertexAttribPointerARB( data[i].index, data[i].size, data[i].type, GL_TRUE, elementsize, (void *)offset );
1489
offset += data[i].size*GPU_typesize(data[i].type);
1491
attribData[i].index = data[i].index;
1492
attribData[i].size = data[i].size;
1493
attribData[i].type = data[i].type;
1495
attribData[numdata].index = -1;
1498
for( i = 0; i < numdata; i++ ) {
1499
glEnableVertexAttribArrayARB( data[i].index );
1500
glVertexAttribPointerARB( data[i].index, data[i].size, data[i].type, GL_TRUE, elementsize, (char *)buffer->pointer + offset );
1501
offset += data[i].size*GPU_typesize(data[i].type);
1507
void GPU_buffer_unbind()
1510
DEBUG_VBO("GPU_buffer_unbind\n");
1512
if( GLStates & GPU_BUFFER_VERTEX_STATE )
1513
glDisableClientState( GL_VERTEX_ARRAY );
1514
if( GLStates & GPU_BUFFER_NORMAL_STATE )
1515
glDisableClientState( GL_NORMAL_ARRAY );
1516
if( GLStates & GPU_BUFFER_TEXCOORD_STATE )
1517
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
1518
if( GLStates & GPU_BUFFER_COLOR_STATE )
1519
glDisableClientState( GL_COLOR_ARRAY );
1520
if( GLStates & GPU_BUFFER_ELEMENT_STATE ) {
1522
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
1525
GLStates &= !(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE | GPU_BUFFER_TEXCOORD_STATE | GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE);
1527
for( i = 0; i < MAX_GPU_ATTRIB_DATA; i++ ) {
1528
if( attribData[i].index != -1 ) {
1529
glDisableVertexAttribArrayARB( attribData[i].index );
1534
if( GLStates != 0 ) {
1535
DEBUG_VBO( "Some weird OpenGL state is still set. Why?" );
1538
glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
1541
void GPU_color3_upload( DerivedMesh *dm, unsigned char *data )
1543
if( dm->drawObject == 0 )
1544
dm->drawObject = GPU_drawobject_new(dm);
1545
GPU_buffer_free(dm->drawObject->colors,globalPool);
1546
dm->drawObject->colors = GPU_buffer_setup( dm, dm->drawObject, sizeof(char)*3*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, data, GPU_buffer_copy_color3 );
1548
void GPU_color4_upload( DerivedMesh *dm, unsigned char *data )
1550
if( dm->drawObject == 0 )
1551
dm->drawObject = GPU_drawobject_new(dm);
1552
GPU_buffer_free(dm->drawObject->colors,globalPool);
1553
dm->drawObject->colors = GPU_buffer_setup( dm, dm->drawObject, sizeof(char)*3*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, data, GPU_buffer_copy_color4 );
1556
void GPU_color_switch( int mode )
1559
if( !(GLStates & GPU_BUFFER_COLOR_STATE) )
1560
glEnableClientState( GL_COLOR_ARRAY );
1561
GLStates |= GPU_BUFFER_COLOR_STATE;
1564
if( GLStates & GPU_BUFFER_COLOR_STATE )
1565
glDisableClientState( GL_COLOR_ARRAY );
1566
GLStates &= (!GPU_BUFFER_COLOR_STATE);
1570
int GPU_buffer_legacy( DerivedMesh *dm )
1572
int test= (U.gameflags & USER_DISABLE_VBO);
1576
if( dm->drawObject == 0 )
1577
dm->drawObject = GPU_drawobject_new(dm);
1578
return dm->drawObject->legacy;
1581
void *GPU_buffer_lock( GPUBuffer *buffer )
1585
DEBUG_VBO("GPU_buffer_lock\n");
1587
DEBUG_VBO( "Failed to lock NULL buffer\n" );
1592
glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffer->id );
1593
varray = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
1595
DEBUG_VBO( "Failed to map buffer to client address space\n" );
1600
return buffer->pointer;
1604
void *GPU_buffer_lock_stream( GPUBuffer *buffer )
1608
DEBUG_VBO("GPU_buffer_lock_stream\n");
1610
DEBUG_VBO( "Failed to lock NULL buffer\n" );
1615
glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffer->id );
1616
glBufferDataARB( GL_ARRAY_BUFFER_ARB, buffer->size, 0, GL_STREAM_DRAW_ARB ); /* discard previous data, avoid stalling gpu */
1617
varray = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
1619
DEBUG_VBO( "Failed to map buffer to client address space\n" );
1624
return buffer->pointer;
1628
void GPU_buffer_unlock( GPUBuffer *buffer )
1630
DEBUG_VBO( "GPU_buffer_unlock\n" );
1633
if( glUnmapBufferARB( GL_ARRAY_BUFFER_ARB ) == 0 ) {
1634
DEBUG_VBO( "Failed to copy new data\n" );
1637
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1641
void GPU_buffer_draw_elements( GPUBuffer *elements, unsigned int mode, int start, int count )
1644
glDrawElements( mode, count, GL_UNSIGNED_INT, (void *)(start*sizeof(unsigned int)) );
1647
glDrawElements( mode, count, GL_UNSIGNED_INT, ((int *)elements->pointer)+start );