4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2005 Blender Foundation.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): Brecht Van Lommel.
30 * ***** END GPL LICENSE BLOCK *****
37 #include "MEM_guardedalloc.h"
41 #include "DNA_meshdata_types.h"
43 #include "BKE_DerivedMesh.h"
44 #include "BKE_utildefines.h"
46 #include "DNA_userdef_types.h"
48 #include "gpu_buffers.h"
50 #define GPU_BUFFER_VERTEX_STATE 1
51 #define GPU_BUFFER_NORMAL_STATE 2
52 #define GPU_BUFFER_TEXCOORD_STATE 4
53 #define GPU_BUFFER_COLOR_STATE 8
54 #define GPU_BUFFER_ELEMENT_STATE 16
56 #define MAX_GPU_ATTRIB_DATA 32
58 /* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
60 GPUBufferPool *globalPool = 0;
62 GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
64 GPUBufferPool *GPU_buffer_pool_new()
68 DEBUG_VBO("GPU_buffer_pool_new\n");
71 if( GL_ARB_vertex_buffer_object ) {
72 DEBUG_VBO( "Vertex Buffer Objects supported.\n" );
76 DEBUG_VBO( "Vertex Buffer Objects NOT supported.\n" );
81 pool = MEM_callocN(sizeof(GPUBufferPool), "GPU_buffer_pool_new");
86 void GPU_buffer_pool_free(GPUBufferPool *pool)
90 DEBUG_VBO("GPU_buffer_pool_free\n");
97 while( pool->start < 0 )
98 pool->start += MAX_FREE_GPU_BUFFERS;
100 for( i = 0; i < pool->size; i++ ) {
102 glDeleteBuffersARB( 1, &pool->buffers[(pool->start+i)%MAX_FREE_GPU_BUFFERS]->id );
105 MEM_freeN( pool->buffers[(pool->start+i)%MAX_FREE_GPU_BUFFERS]->pointer );
107 MEM_freeN(pool->buffers[(pool->start+i)%MAX_FREE_GPU_BUFFERS]);
112 void GPU_buffer_pool_remove( int index, GPUBufferPool *pool )
116 DEBUG_VBO("GPU_buffer_pool_remove\n");
118 while( pool->start < 0 )
119 pool->start += MAX_FREE_GPU_BUFFERS;
120 for( i = index; i < pool->size-1; i++ ) {
121 pool->buffers[(pool->start+i)%MAX_FREE_GPU_BUFFERS] = pool->buffers[(pool->start+i+1)%MAX_FREE_GPU_BUFFERS];
126 void GPU_buffer_pool_delete_last( GPUBufferPool *pool )
130 DEBUG_VBO("GPU_buffer_pool_delete_last\n");
132 if( pool->size == 0 )
135 last = pool->start+pool->size-1;
137 last += MAX_FREE_GPU_BUFFERS;
138 last = (last+MAX_FREE_GPU_BUFFERS)%MAX_FREE_GPU_BUFFERS;
141 glDeleteBuffersARB(1,&pool->buffers[last]->id);
142 MEM_freeN( pool->buffers[last] );
145 MEM_freeN( pool->buffers[last]->pointer );
146 MEM_freeN( pool->buffers[last] );
151 GPUBuffer *GPU_buffer_alloc( int size, GPUBufferPool *pool )
156 GPUBuffer *allocated;
159 DEBUG_VBO("GPU_buffer_alloc\n");
162 if( globalPool == 0 )
163 globalPool = GPU_buffer_pool_new();
167 while( pool->start < 0 )
168 pool->start += MAX_FREE_GPU_BUFFERS;
170 for( i = 0; i < pool->size; i++ ) {
171 int actuali = (pool->start+i)%MAX_FREE_GPU_BUFFERS;
172 cursize = pool->buffers[actuali]->size;
173 if( cursize == size ) {
174 allocated = pool->buffers[actuali];
175 GPU_buffer_pool_remove(i,pool);
176 DEBUG_VBO("free buffer of exact size found\n");
179 /* smaller buffers won't fit data and buffers at least twice as big are a waste of memory */
180 else if( cursize > size && size > cursize/2 ) {
181 /* is it closer to the required size than the last appropriate buffer found. try to save memory */
182 if( bestfit == -1 || pool->buffers[(pool->start+bestfit)%MAX_FREE_GPU_BUFFERS]->size > cursize ) {
187 if( bestfit == -1 ) {
188 DEBUG_VBO("allocating a new buffer\n");
190 allocated = MEM_mallocN(sizeof(GPUBuffer), "GPU_buffer_alloc");
191 allocated->size = size;
193 glGenBuffersARB( 1, &allocated->id );
194 glBindBufferARB( GL_ARRAY_BUFFER_ARB, allocated->id );
195 glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, 0, GL_STATIC_DRAW_ARB );
196 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
199 allocated->pointer = MEM_mallocN(size, "GPU_buffer_alloc_vertexarray");
200 while( allocated->pointer == 0 && pool->size > 0 ) {
201 GPU_buffer_pool_delete_last(pool);
202 allocated->pointer = MEM_mallocN(size, "GPU_buffer_alloc_vertexarray");
204 if( allocated->pointer == 0 && pool->size == 0 ) {
210 sprintf(buffer,"free buffer found. Wasted %d bytes\n", pool->buffers[(pool->start+bestfit)%MAX_FREE_GPU_BUFFERS]->size-size);
213 allocated = pool->buffers[(pool->start+bestfit)%MAX_FREE_GPU_BUFFERS];
214 GPU_buffer_pool_remove(bestfit,pool);
219 void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool )
223 DEBUG_VBO("GPU_buffer_free\n");
230 globalPool = GPU_buffer_pool_new();
232 while( pool->start < 0 )
233 pool->start += MAX_FREE_GPU_BUFFERS;
234 place = (pool->start-1 + MAX_FREE_GPU_BUFFERS)%MAX_FREE_GPU_BUFFERS;
236 /* free the last used buffer in the queue if no more space */
237 if( pool->size == MAX_FREE_GPU_BUFFERS ) {
238 GPU_buffer_pool_delete_last( pool );
243 pool->buffers[place] = buffer;
246 GPUDrawObject *GPU_drawobject_new( DerivedMesh *dm )
248 GPUDrawObject *object;
251 int numverts[32768]; /* material number is an 16-bit short so there's at most 32768 materials */
252 int redir[32768]; /* material number is an 16-bit short so there's at most 32768 materials */
255 int curmat, curverts, numfaces;
257 DEBUG_VBO("GPU_drawobject_new\n");
259 object = MEM_callocN(sizeof(GPUDrawObject),"GPU_drawobject_new_object");
260 object->nindices = dm->getNumVerts(dm);
261 object->indices = MEM_mallocN(sizeof(IndexLink)*object->nindices, "GPU_drawobject_new_indices");
262 object->nedges = dm->getNumEdges(dm);
264 for( i = 0; i < object->nindices; i++ ) {
265 object->indices[i].element = -1;
266 object->indices[i].next = 0;
268 /*object->legacy = 1;*/
269 memset(numverts,0,sizeof(int)*32768);
271 mvert = dm->getVertArray(dm);
272 mface = dm->getFaceArray(dm);
274 numfaces= dm->getNumFaces(dm);
275 for( i=0; i < numfaces; i++ ) {
277 numverts[mface[i].mat_nr+16383] += 6; /* split every quad into two triangles */
279 numverts[mface[i].mat_nr+16383] += 3;
282 for( i = 0; i < 32768; i++ ) {
283 if( numverts[i] > 0 ) {
284 object->nmaterials++;
285 object->nelements += numverts[i];
288 object->materials = MEM_mallocN(sizeof(GPUBufferMaterial)*object->nmaterials,"GPU_drawobject_new_materials");
289 index = MEM_mallocN(sizeof(int)*object->nmaterials,"GPU_drawobject_new_index");
291 curmat = curverts = 0;
292 for( i = 0; i < 32768; i++ ) {
293 if( numverts[i] > 0 ) {
294 object->materials[curmat].mat_nr = i-16383;
295 object->materials[curmat].start = curverts;
296 index[curmat] = curverts/3;
297 object->materials[curmat].end = curverts+numverts[i];
298 curverts += numverts[i];
302 object->faceRemap = MEM_mallocN(sizeof(int)*object->nelements/3,"GPU_drawobject_new_faceRemap");
303 for( i = 0; i < object->nmaterials; i++ ) {
304 redir[object->materials[i].mat_nr+16383] = i; /* material number -> material index */
307 object->indexMem = MEM_callocN(sizeof(IndexLink)*object->nelements,"GPU_drawobject_new_indexMem");
308 object->indexMemUsage = 0;
310 #define ADDLINK( INDEX, ACTUAL ) \
311 if( object->indices[INDEX].element == -1 ) { \
312 object->indices[INDEX].element = ACTUAL; \
314 IndexLink *lnk = &object->indices[INDEX]; \
315 while( lnk->next != 0 ) lnk = lnk->next; \
316 lnk->next = &object->indexMem[object->indexMemUsage]; \
317 lnk->next->element = ACTUAL; \
318 object->indexMemUsage++; \
321 for( i=0; i < numfaces; i++ ) {
322 int curInd = index[redir[mface[i].mat_nr+16383]];
323 object->faceRemap[curInd] = i;
324 ADDLINK( mface[i].v1, curInd*3 );
325 ADDLINK( mface[i].v2, curInd*3+1 );
326 ADDLINK( mface[i].v3, curInd*3+2 );
328 object->faceRemap[curInd+1] = i;
329 ADDLINK( mface[i].v3, curInd*3+3 );
330 ADDLINK( mface[i].v4, curInd*3+4 );
331 ADDLINK( mface[i].v1, curInd*3+5 );
333 index[redir[mface[i].mat_nr+16383]]+=2;
336 index[redir[mface[i].mat_nr+16383]]++;
340 for( i = 0; i < object->nindices; i++ ) {
341 if( object->indices[i].element == -1 ) {
342 object->indices[i].element = object->nelements + object->nlooseverts;
343 object->nlooseverts++;
352 void GPU_drawobject_free( DerivedMesh *dm )
354 GPUDrawObject *object;
356 DEBUG_VBO("GPU_drawobject_free\n");
360 object = dm->drawObject;
364 MEM_freeN(object->materials);
365 MEM_freeN(object->faceRemap);
366 MEM_freeN(object->indices);
367 MEM_freeN(object->indexMem);
368 GPU_buffer_free( object->vertices, globalPool );
369 GPU_buffer_free( object->normals, globalPool );
370 GPU_buffer_free( object->uv, globalPool );
371 GPU_buffer_free( object->colors, globalPool );
372 GPU_buffer_free( object->edges, globalPool );
373 GPU_buffer_free( object->uvedges, globalPool );
379 GPUBuffer *GPU_buffer_setup( DerivedMesh *dm, GPUDrawObject *object, int size, GLenum target, void *user, void (*copy_f)(DerivedMesh *, float *, int *, int *, void *) )
389 DEBUG_VBO("GPU_buffer_setup\n");
391 if( globalPool == 0 ) {
392 globalPool = GPU_buffer_pool_new();
394 /* somehow GL_NORMAL_ARRAY is enabled on startup and causes edge drawing code to crash */
395 glDisableClientState( GL_VERTEX_ARRAY );
396 glDisableClientState( GL_NORMAL_ARRAY );
397 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
398 glDisableClientState( GL_COLOR_ARRAY );
400 buffer = GPU_buffer_alloc(size,globalPool);
402 dm->drawObject->legacy = 1;
404 if( dm->drawObject->legacy ) {
408 index = MEM_mallocN(sizeof(int)*object->nmaterials,"GPU_buffer_setup");
409 for( i = 0; i < object->nmaterials; i++ ) {
410 index[i] = object->materials[i].start*3;
411 redir[object->materials[i].mat_nr+16383] = i;
416 while( success == 0 ) {
417 glBindBufferARB( target, buffer->id );
418 glBufferDataARB( target, buffer->size, 0, GL_STATIC_DRAW_ARB ); /* discard previous data, avoid stalling gpu */
419 varray = glMapBufferARB( target, GL_WRITE_ONLY_ARB );
421 DEBUG_VBO( "Failed to map buffer to client address space\n" );
422 GPU_buffer_free( buffer, globalPool );
423 GPU_buffer_pool_delete_last( globalPool );
424 if( globalPool->size > 0 ) {
425 GPU_buffer_pool_delete_last( globalPool );
426 buffer = GPU_buffer_alloc( size, globalPool );
428 dm->drawObject->legacy = 1;
433 dm->drawObject->legacy = 1;
442 if( dm->drawObject->legacy == 0 ) {
445 (*copy_f)( dm, varray, index, redir, user );
446 uploaded = glUnmapBufferARB( target ); /* returns false if data got corruped during transfer */
449 glBindBufferARB(target, 0);
452 if( buffer->pointer != 0 ) {
453 varray = buffer->pointer;
454 (*copy_f)( dm, varray, index, redir, user );
457 dm->drawObject->legacy = 1;
466 void GPU_buffer_copy_vertex( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
474 DEBUG_VBO("GPU_buffer_copy_vertex\n");
476 mvert = dm->getVertArray(dm);
477 mface = dm->getFaceArray(dm);
479 numfaces= dm->getNumFaces(dm);
480 for( i=0; i < numfaces; i++ ) {
481 start = index[redir[mface[i].mat_nr+16383]];
483 index[redir[mface[i].mat_nr+16383]] += 18;
485 index[redir[mface[i].mat_nr+16383]] += 9;
488 VECCOPY(&varray[start],mvert[mface[i].v1].co);
489 VECCOPY(&varray[start+3],mvert[mface[i].v2].co);
490 VECCOPY(&varray[start+6],mvert[mface[i].v3].co);
494 VECCOPY(&varray[start+9],mvert[mface[i].v3].co);
495 VECCOPY(&varray[start+12],mvert[mface[i].v4].co);
496 VECCOPY(&varray[start+15],mvert[mface[i].v1].co);
499 j = dm->drawObject->nelements*3;
500 for( i = 0; i < dm->drawObject->nindices; i++ ) {
501 if( dm->drawObject->indices[i].element >= dm->drawObject->nelements ) {
502 VECCOPY(&varray[j],mvert[i].co);
508 GPUBuffer *GPU_buffer_vertex( DerivedMesh *dm )
510 DEBUG_VBO("GPU_buffer_vertex\n");
512 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);
515 void GPU_buffer_copy_normal( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
521 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
522 MVert *mvert = dm->getVertArray(dm);
523 MFace *mface = dm->getFaceArray(dm);
525 DEBUG_VBO("GPU_buffer_copy_normal\n");
527 numfaces= dm->getNumFaces(dm);
528 for( i=0; i < numfaces; i++ ) {
529 start = index[redir[mface[i].mat_nr+16383]];
531 index[redir[mface[i].mat_nr+16383]] += 18;
533 index[redir[mface[i].mat_nr+16383]] += 9;
536 if( mface[i].flag & ME_SMOOTH ) {
537 VECCOPY(&varray[start],mvert[mface[i].v1].no);
538 VECCOPY(&varray[start+3],mvert[mface[i].v2].no);
539 VECCOPY(&varray[start+6],mvert[mface[i].v3].no);
543 VECCOPY(&varray[start],&nors[i*3]);
544 VECCOPY(&varray[start+3],&nors[i*3]);
545 VECCOPY(&varray[start+6],&nors[i*3]);
548 normal_quad_v3( norm,mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co, mvert[mface[i].v4].co);
550 normal_tri_v3( norm,mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co);
551 VECCOPY(&varray[start],norm);
552 VECCOPY(&varray[start+3],norm);
553 VECCOPY(&varray[start+6],norm);
558 if( mface[i].flag & ME_SMOOTH ) {
559 VECCOPY(&varray[start+9],mvert[mface[i].v3].no);
560 VECCOPY(&varray[start+12],mvert[mface[i].v4].no);
561 VECCOPY(&varray[start+15],mvert[mface[i].v1].no);
564 VECCOPY(&varray[start+9],norm);
565 VECCOPY(&varray[start+12],norm);
566 VECCOPY(&varray[start+15],norm);
572 GPUBuffer *GPU_buffer_normal( DerivedMesh *dm )
574 DEBUG_VBO("GPU_buffer_normal\n");
576 return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*3*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, 0, GPU_buffer_copy_normal);
579 void GPU_buffer_copy_uv( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
587 DEBUG_VBO("GPU_buffer_copy_uv\n");
589 mface = dm->getFaceArray(dm);
590 mtface = DM_get_face_data_layer(dm, CD_MTFACE);
593 DEBUG_VBO("Texture coordinates do not exist for this mesh");
597 numfaces= dm->getNumFaces(dm);
598 for( i=0; i < numfaces; i++ ) {
599 start = index[redir[mface[i].mat_nr+16383]];
601 index[redir[mface[i].mat_nr+16383]] += 12;
603 index[redir[mface[i].mat_nr+16383]] += 6;
606 VECCOPY2D(&varray[start],mtface[i].uv[0]);
607 VECCOPY2D(&varray[start+2],mtface[i].uv[1]);
608 VECCOPY2D(&varray[start+4],mtface[i].uv[2]);
612 VECCOPY2D(&varray[start+6],mtface[i].uv[2]);
613 VECCOPY2D(&varray[start+8],mtface[i].uv[3]);
614 VECCOPY2D(&varray[start+10],mtface[i].uv[0]);
619 GPUBuffer *GPU_buffer_uv( DerivedMesh *dm )
621 DEBUG_VBO("GPU_buffer_uv\n");
622 if( DM_get_face_data_layer(dm, CD_MTFACE) != 0 )
623 return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*2*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, 0, GPU_buffer_copy_uv);
628 void GPU_buffer_copy_color3( DerivedMesh *dm, float *varray_, int *index, int *redir, void *user )
631 unsigned char *varray = (unsigned char *)varray_;
632 unsigned char *mcol = (unsigned char *)user;
633 MFace *mface = dm->getFaceArray(dm);
635 DEBUG_VBO("GPU_buffer_copy_color3\n");
637 numfaces= dm->getNumFaces(dm);
638 for( i=0; i < numfaces; i++ ) {
639 int start = index[redir[mface[i].mat_nr+16383]];
641 index[redir[mface[i].mat_nr+16383]] += 18;
643 index[redir[mface[i].mat_nr+16383]] += 9;
646 VECCOPY(&varray[start],&mcol[i*12]);
647 VECCOPY(&varray[start+3],&mcol[i*12+3]);
648 VECCOPY(&varray[start+6],&mcol[i*12+6]);
651 VECCOPY(&varray[start+9],&mcol[i*12+6]);
652 VECCOPY(&varray[start+12],&mcol[i*12+9]);
653 VECCOPY(&varray[start+15],&mcol[i*12]);
658 void GPU_buffer_copy_color4( DerivedMesh *dm, float *varray_, int *index, int *redir, void *user )
661 unsigned char *varray = (unsigned char *)varray_;
662 unsigned char *mcol = (unsigned char *)user;
663 MFace *mface = dm->getFaceArray(dm);
665 DEBUG_VBO("GPU_buffer_copy_color4\n");
667 numfaces= dm->getNumFaces(dm);
668 for( i=0; i < numfaces; i++ ) {
669 int start = index[redir[mface[i].mat_nr+16383]];
671 index[redir[mface[i].mat_nr+16383]] += 18;
673 index[redir[mface[i].mat_nr+16383]] += 9;
676 VECCOPY(&varray[start],&mcol[i*16]);
677 VECCOPY(&varray[start+3],&mcol[i*16+4]);
678 VECCOPY(&varray[start+6],&mcol[i*16+8]);
681 VECCOPY(&varray[start+9],&mcol[i*16+8]);
682 VECCOPY(&varray[start+12],&mcol[i*16+12]);
683 VECCOPY(&varray[start+15],&mcol[i*16]);
688 GPUBuffer *GPU_buffer_color( DerivedMesh *dm )
690 unsigned char *colors;
694 DEBUG_VBO("GPU_buffer_color\n");
696 mcol = DM_get_face_data_layer(dm, CD_ID_MCOL);
697 dm->drawObject->colType = CD_ID_MCOL;
699 mcol = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
700 dm->drawObject->colType = CD_WEIGHT_MCOL;
703 mcol = DM_get_face_data_layer(dm, CD_MCOL);
704 dm->drawObject->colType = CD_MCOL;
707 numfaces= dm->getNumFaces(dm);
708 colors = MEM_mallocN(numfaces*12*sizeof(unsigned char), "GPU_buffer_color");
709 for( i=0; i < numfaces*4; i++ ) {
710 colors[i*3] = mcol[i].b;
711 colors[i*3+1] = mcol[i].g;
712 colors[i*3+2] = mcol[i].r;
715 result = GPU_buffer_setup( dm, dm->drawObject, sizeof(char)*3*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, colors, GPU_buffer_copy_color3 );
721 void GPU_buffer_copy_edge( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
727 unsigned int *varray_ = (unsigned int *)varray;
730 DEBUG_VBO("GPU_buffer_copy_edge\n");
732 mvert = dm->getVertArray(dm);
733 medge = dm->getEdgeArray(dm);
735 numedges= dm->getNumEdges(dm);
736 for(i = 0; i < numedges; i++) {
737 varray_[i*2] = (unsigned int)dm->drawObject->indices[medge[i].v1].element;
738 varray_[i*2+1] = (unsigned int)dm->drawObject->indices[medge[i].v2].element;
742 GPUBuffer *GPU_buffer_edge( DerivedMesh *dm )
744 DEBUG_VBO("GPU_buffer_edge\n");
746 return GPU_buffer_setup( dm, dm->drawObject, sizeof(int)*2*dm->drawObject->nedges, GL_ELEMENT_ARRAY_BUFFER_ARB, 0, GPU_buffer_copy_edge);
749 void GPU_buffer_copy_uvedge( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
751 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
754 DEBUG_VBO("GPU_buffer_copy_uvedge\n");
757 for(i = 0; i < dm->numFaceData; i++, tf++) {
759 dm->getFace(dm,i,&mf);
761 VECCOPY2D(&varray[j],tf->uv[0]);
762 VECCOPY2D(&varray[j+2],tf->uv[1]);
764 VECCOPY2D(&varray[j+4],tf->uv[1]);
765 VECCOPY2D(&varray[j+6],tf->uv[2]);
768 VECCOPY2D(&varray[j+8],tf->uv[2]);
769 VECCOPY2D(&varray[j+10],tf->uv[0]);
772 VECCOPY2D(&varray[j+8],tf->uv[2]);
773 VECCOPY2D(&varray[j+10],tf->uv[3]);
775 VECCOPY2D(&varray[j+12],tf->uv[3]);
776 VECCOPY2D(&varray[j+14],tf->uv[0]);
782 DEBUG_VBO("Could not get MTFACE data layer");
786 GPUBuffer *GPU_buffer_uvedge( DerivedMesh *dm )
788 DEBUG_VBO("GPU_buffer_uvedge\n");
790 return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*2*(dm->drawObject->nelements/3)*2, GL_ARRAY_BUFFER_ARB, 0, GPU_buffer_copy_uvedge);
794 void GPU_vertex_setup( DerivedMesh *dm )
796 DEBUG_VBO("GPU_vertex_setup\n");
797 if( dm->drawObject == 0 )
798 dm->drawObject = GPU_drawobject_new( dm );
799 if( dm->drawObject->vertices == 0 )
800 dm->drawObject->vertices = GPU_buffer_vertex( dm );
801 if( dm->drawObject->vertices == 0 ) {
802 DEBUG_VBO( "Failed to setup vertices\n" );
806 glEnableClientState( GL_VERTEX_ARRAY );
808 glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->vertices->id );
809 glVertexPointer( 3, GL_FLOAT, 0, 0 );
812 glVertexPointer( 3, GL_FLOAT, 0, dm->drawObject->vertices->pointer );
815 GLStates |= GPU_BUFFER_VERTEX_STATE;
818 void GPU_normal_setup( DerivedMesh *dm )
820 DEBUG_VBO("GPU_normal_setup\n");
821 if( dm->drawObject == 0 )
822 dm->drawObject = GPU_drawobject_new( dm );
823 if( dm->drawObject->normals == 0 )
824 dm->drawObject->normals = GPU_buffer_normal( dm );
825 if( dm->drawObject->normals == 0 ) {
826 DEBUG_VBO( "Failed to setup normals\n" );
829 glEnableClientState( GL_NORMAL_ARRAY );
831 glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id );
832 glNormalPointer( GL_FLOAT, 0, 0 );
835 glNormalPointer( GL_FLOAT, 0, dm->drawObject->normals->pointer );
838 GLStates |= GPU_BUFFER_NORMAL_STATE;
841 void GPU_uv_setup( DerivedMesh *dm )
843 DEBUG_VBO("GPU_uv_setup\n");
844 if( dm->drawObject == 0 )
845 dm->drawObject = GPU_drawobject_new( dm );
846 if( dm->drawObject->uv == 0 )
847 dm->drawObject->uv = GPU_buffer_uv( dm );
849 if( dm->drawObject->uv != 0 ) {
850 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
852 glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id );
853 glTexCoordPointer( 2, GL_FLOAT, 0, 0 );
856 glTexCoordPointer( 2, GL_FLOAT, 0, dm->drawObject->uv->pointer );
859 GLStates |= GPU_BUFFER_TEXCOORD_STATE;
863 void GPU_color_setup( DerivedMesh *dm )
865 DEBUG_VBO("GPU_color_setup\n");
866 if( dm->drawObject == 0 )
867 dm->drawObject = GPU_drawobject_new( dm );
868 if( dm->drawObject->colors == 0 )
869 dm->drawObject->colors = GPU_buffer_color( dm );
870 if( dm->drawObject->colors == 0 ) {
871 DEBUG_VBO( "Failed to setup colors\n" );
874 glEnableClientState( GL_COLOR_ARRAY );
876 glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->colors->id );
877 glColorPointer( 3, GL_UNSIGNED_BYTE, 0, 0 );
880 glColorPointer( 3, GL_UNSIGNED_BYTE, 0, dm->drawObject->colors->pointer );
883 GLStates |= GPU_BUFFER_COLOR_STATE;
886 void GPU_edge_setup( DerivedMesh *dm )
888 DEBUG_VBO("GPU_edge_setup\n");
889 if( dm->drawObject == 0 )
890 dm->drawObject = GPU_drawobject_new( dm );
891 if( dm->drawObject->edges == 0 )
892 dm->drawObject->edges = GPU_buffer_edge( dm );
893 if( dm->drawObject->edges == 0 ) {
894 DEBUG_VBO( "Failed to setup edges\n" );
897 if( dm->drawObject->vertices == 0 )
898 dm->drawObject->vertices = GPU_buffer_vertex( dm );
899 if( dm->drawObject->vertices == 0 ) {
900 DEBUG_VBO( "Failed to setup vertices\n" );
904 glEnableClientState( GL_VERTEX_ARRAY );
906 glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->vertices->id );
907 glVertexPointer( 3, GL_FLOAT, 0, 0 );
910 glVertexPointer( 3, GL_FLOAT, 0, dm->drawObject->vertices->pointer );
913 GLStates |= GPU_BUFFER_VERTEX_STATE;
916 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->edges->id );
919 GLStates |= GPU_BUFFER_ELEMENT_STATE;
922 void GPU_uvedge_setup( DerivedMesh *dm )
924 DEBUG_VBO("GPU_uvedge_setup\n");
925 if( dm->drawObject == 0 )
926 dm->drawObject = GPU_drawobject_new( dm );
927 if( dm->drawObject->uvedges == 0 )
928 dm->drawObject->uvedges = GPU_buffer_uvedge( dm );
929 if( dm->drawObject->uvedges == 0 ) {
930 DEBUG_VBO( "Failed to setup UV edges\n" );
934 glEnableClientState( GL_VERTEX_ARRAY );
936 glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->uvedges->id );
937 glVertexPointer( 2, GL_FLOAT, 0, 0 );
940 glVertexPointer( 2, GL_FLOAT, 0, dm->drawObject->uvedges->pointer );
943 GLStates |= GPU_BUFFER_VERTEX_STATE;
946 void GPU_interleaved_setup( GPUBuffer *buffer, int data[] ) {
951 DEBUG_VBO("GPU_interleaved_setup\n");
953 for( i = 0; data[i] != GPU_BUFFER_INTER_END; i++ ) {
955 case GPU_BUFFER_INTER_V3F:
956 elementsize += 3*sizeof(float);
958 case GPU_BUFFER_INTER_N3F:
959 elementsize += 3*sizeof(float);
961 case GPU_BUFFER_INTER_T2F:
962 elementsize += 2*sizeof(float);
964 case GPU_BUFFER_INTER_C3UB:
965 elementsize += 3*sizeof(unsigned char);
967 case GPU_BUFFER_INTER_C4UB:
968 elementsize += 4*sizeof(unsigned char);
971 DEBUG_VBO( "Unknown element in data type array in GPU_interleaved_setup\n" );
976 glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffer->id );
977 for( i = 0; data[i] != GPU_BUFFER_INTER_END; i++ ) {
979 case GPU_BUFFER_INTER_V3F:
980 glEnableClientState( GL_VERTEX_ARRAY );
981 glVertexPointer( 3, GL_FLOAT, elementsize, (void *)offset );
982 GLStates |= GPU_BUFFER_VERTEX_STATE;
983 offset += 3*sizeof(float);
985 case GPU_BUFFER_INTER_N3F:
986 glEnableClientState( GL_NORMAL_ARRAY );
987 glNormalPointer( GL_FLOAT, elementsize, (void *)offset );
988 GLStates |= GPU_BUFFER_NORMAL_STATE;
989 offset += 3*sizeof(float);
991 case GPU_BUFFER_INTER_T2F:
992 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
993 glTexCoordPointer( 2, GL_FLOAT, elementsize, (void *)offset );
994 GLStates |= GPU_BUFFER_TEXCOORD_STATE;
995 offset += 2*sizeof(float);
997 case GPU_BUFFER_INTER_C3UB:
998 glEnableClientState( GL_COLOR_ARRAY );
999 glColorPointer( 3, GL_UNSIGNED_BYTE, elementsize, (void *)offset );
1000 GLStates |= GPU_BUFFER_COLOR_STATE;
1001 offset += 3*sizeof(unsigned char);
1003 case GPU_BUFFER_INTER_C4UB:
1004 glEnableClientState( GL_COLOR_ARRAY );
1005 glColorPointer( 4, GL_UNSIGNED_BYTE, elementsize, (void *)offset );
1006 GLStates |= GPU_BUFFER_COLOR_STATE;
1007 offset += 4*sizeof(unsigned char);
1013 for( i = 0; data[i] != GPU_BUFFER_INTER_END; i++ ) {
1015 case GPU_BUFFER_INTER_V3F:
1016 glEnableClientState( GL_VERTEX_ARRAY );
1017 glVertexPointer( 3, GL_FLOAT, elementsize, offset+(char *)buffer->pointer );
1018 GLStates |= GPU_BUFFER_VERTEX_STATE;
1019 offset += 3*sizeof(float);
1021 case GPU_BUFFER_INTER_N3F:
1022 glEnableClientState( GL_NORMAL_ARRAY );
1023 glNormalPointer( GL_FLOAT, elementsize, offset+(char *)buffer->pointer );
1024 GLStates |= GPU_BUFFER_NORMAL_STATE;
1025 offset += 3*sizeof(float);
1027 case GPU_BUFFER_INTER_T2F:
1028 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1029 glTexCoordPointer( 2, GL_FLOAT, elementsize, offset+(char *)buffer->pointer );
1030 GLStates |= GPU_BUFFER_TEXCOORD_STATE;
1031 offset += 2*sizeof(float);
1033 case GPU_BUFFER_INTER_C3UB:
1034 glEnableClientState( GL_COLOR_ARRAY );
1035 glColorPointer( 3, GL_UNSIGNED_BYTE, elementsize, offset+(char *)buffer->pointer );
1036 GLStates |= GPU_BUFFER_COLOR_STATE;
1037 offset += 3*sizeof(unsigned char);
1039 case GPU_BUFFER_INTER_C4UB:
1040 glEnableClientState( GL_COLOR_ARRAY );
1041 glColorPointer( 4, GL_UNSIGNED_BYTE, elementsize, offset+(char *)buffer->pointer );
1042 GLStates |= GPU_BUFFER_COLOR_STATE;
1043 offset += 4*sizeof(unsigned char);
1050 static int GPU_typesize( int type ) {
1053 return sizeof(float);
1056 case GL_UNSIGNED_INT:
1057 return sizeof(unsigned int);
1059 return sizeof(char);
1060 case GL_UNSIGNED_BYTE:
1061 return sizeof(unsigned char);
1067 int GPU_attrib_element_size( GPUAttrib data[], int numdata ) {
1068 int i, elementsize = 0;
1070 for( i = 0; i < numdata; i++ ) {
1071 int typesize = GPU_typesize(data[i].type);
1073 DEBUG_VBO( "Unknown element in data type array in GPU_attrib_element_size\n" );
1075 elementsize += typesize*data[i].size;
1081 void GPU_interleaved_attrib_setup( GPUBuffer *buffer, GPUAttrib data[], int numdata ) {
1084 intptr_t offset = 0;
1086 DEBUG_VBO("GPU_interleaved_attrib_setup\n");
1088 for( i = 0; i < MAX_GPU_ATTRIB_DATA; i++ ) {
1089 if( attribData[i].index != -1 ) {
1090 glDisableVertexAttribArrayARB( attribData[i].index );
1095 elementsize = GPU_attrib_element_size( data, numdata );
1098 glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffer->id );
1099 for( i = 0; i < numdata; i++ ) {
1100 glEnableVertexAttribArrayARB( data[i].index );
1101 glVertexAttribPointerARB( data[i].index, data[i].size, data[i].type, GL_TRUE, elementsize, (void *)offset );
1102 offset += data[i].size*GPU_typesize(data[i].type);
1104 attribData[i].index = data[i].index;
1105 attribData[i].size = data[i].size;
1106 attribData[i].type = data[i].type;
1108 attribData[numdata].index = -1;
1111 for( i = 0; i < numdata; i++ ) {
1112 glEnableVertexAttribArrayARB( data[i].index );
1113 glVertexAttribPointerARB( data[i].index, data[i].size, data[i].type, GL_TRUE, elementsize, (char *)buffer->pointer + offset );
1114 offset += data[i].size*GPU_typesize(data[i].type);
1120 void GPU_buffer_unbind()
1123 DEBUG_VBO("GPU_buffer_unbind\n");
1125 if( GLStates & GPU_BUFFER_VERTEX_STATE )
1126 glDisableClientState( GL_VERTEX_ARRAY );
1127 if( GLStates & GPU_BUFFER_NORMAL_STATE )
1128 glDisableClientState( GL_NORMAL_ARRAY );
1129 if( GLStates & GPU_BUFFER_TEXCOORD_STATE )
1130 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
1131 if( GLStates & GPU_BUFFER_COLOR_STATE )
1132 glDisableClientState( GL_COLOR_ARRAY );
1133 if( GLStates & GPU_BUFFER_ELEMENT_STATE ) {
1135 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
1138 GLStates &= !(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE | GPU_BUFFER_TEXCOORD_STATE | GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE);
1140 for( i = 0; i < MAX_GPU_ATTRIB_DATA; i++ ) {
1141 if( attribData[i].index != -1 ) {
1142 glDisableVertexAttribArrayARB( attribData[i].index );
1148 DEBUG_VBO( "Some weird OpenGL state is still set. Why?" );
1150 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
1153 void GPU_color3_upload( DerivedMesh *dm, unsigned char *data )
1155 if( dm->drawObject == 0 )
1156 dm->drawObject = GPU_drawobject_new(dm);
1157 GPU_buffer_free(dm->drawObject->colors,globalPool);
1158 dm->drawObject->colors = GPU_buffer_setup( dm, dm->drawObject, sizeof(char)*3*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, data, GPU_buffer_copy_color3 );
1160 void GPU_color4_upload( DerivedMesh *dm, unsigned char *data )
1162 if( dm->drawObject == 0 )
1163 dm->drawObject = GPU_drawobject_new(dm);
1164 GPU_buffer_free(dm->drawObject->colors,globalPool);
1165 dm->drawObject->colors = GPU_buffer_setup( dm, dm->drawObject, sizeof(char)*3*dm->drawObject->nelements, GL_ARRAY_BUFFER_ARB, data, GPU_buffer_copy_color4 );
1168 void GPU_color_switch( int mode )
1171 if( !(GLStates & GPU_BUFFER_COLOR_STATE) )
1172 glEnableClientState( GL_COLOR_ARRAY );
1173 GLStates |= GPU_BUFFER_COLOR_STATE;
1176 if( GLStates & GPU_BUFFER_COLOR_STATE )
1177 glDisableClientState( GL_COLOR_ARRAY );
1178 GLStates &= (!GPU_BUFFER_COLOR_STATE);
1182 int GPU_buffer_legacy( DerivedMesh *dm )
1184 int test= (U.gameflags & USER_DISABLE_VBO);
1188 if( dm->drawObject == 0 )
1189 dm->drawObject = GPU_drawobject_new(dm);
1190 return dm->drawObject->legacy;
1193 void *GPU_buffer_lock( GPUBuffer *buffer )
1197 DEBUG_VBO("GPU_buffer_lock\n");
1199 DEBUG_VBO( "Failed to lock NULL buffer\n" );
1204 glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffer->id );
1205 varray = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
1207 DEBUG_VBO( "Failed to map buffer to client address space\n" );
1212 return buffer->pointer;
1216 void *GPU_buffer_lock_stream( GPUBuffer *buffer )
1220 DEBUG_VBO("GPU_buffer_lock_stream\n");
1222 DEBUG_VBO( "Failed to lock NULL buffer\n" );
1227 glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffer->id );
1228 glBufferDataARB( GL_ARRAY_BUFFER_ARB, buffer->size, 0, GL_STREAM_DRAW_ARB ); /* discard previous data, avoid stalling gpu */
1229 varray = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
1231 DEBUG_VBO( "Failed to map buffer to client address space\n" );
1236 return buffer->pointer;
1240 void GPU_buffer_unlock( GPUBuffer *buffer )
1242 DEBUG_VBO( "GPU_buffer_unlock\n" );
1245 if( glUnmapBufferARB( GL_ARRAY_BUFFER_ARB ) == 0 ) {
1246 DEBUG_VBO( "Failed to copy new data\n" );
1249 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1253 void GPU_buffer_draw_elements( GPUBuffer *elements, unsigned int mode, int start, int count )
1256 glDrawElements( mode, count, GL_UNSIGNED_INT, (void *)(start*sizeof(unsigned int)) );
1259 glDrawElements( mode, count, GL_UNSIGNED_INT, ((int *)elements->pointer)+start );