merge from 21113 to 21377
authorLukas Steiblys <imbusy@imbusy.org>
Mon, 6 Jul 2009 14:40:38 +0000 (14:40 +0000)
committerLukas Steiblys <imbusy@imbusy.org>
Mon, 6 Jul 2009 14:40:38 +0000 (14:40 +0000)
config/win64-vc-config.py
projectfiles_vc9/blender/blender.sln
projectfiles_vc9/blender/gpu/BL_gpu.vcproj
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/editors/space_view3d/drawobject.c
source/blender/gpu/SConscript
source/blender/gpu/gpu_buffers.h [new file with mode: 0644]
source/blender/gpu/intern/gpu_buffers.c [new file with mode: 0644]

index 83e27a855740d214c5ea7a57b7b7ae41f89e697e..d1533038082b3c6b8c83a4c7cf260ba6b56ef6c7 100644 (file)
@@ -1,3 +1,210 @@
+<<<<<<< .working
+LCGDIR = '#../lib/win64'
+LIBDIR = '${LCGDIR}'
+
+# enable ffmpeg  support
+WITH_BF_FFMPEG = False # -DWITH_FFMPEG
+BF_FFMPEG = LIBDIR +'/ffmpeg'
+BF_FFMPEG_INC = '${BF_FFMPEG}/include'
+BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
+BF_FFMPEG_LIB = 'avformat-52.lib avcodec-51.lib avdevice-52.lib avutil-49.lib swscale-0.lib'
+
+BF_PYTHON = LIBDIR + '/python'
+BF_PYTHON_VERSION = '3.0'
+BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
+BF_PYTHON_BINARY = 'python'
+BF_PYTHON_LIB = 'python30'
+BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
+
+WITH_BF_OPENAL = False 
+WITH_BF_STATICOPENAL = False
+BF_OPENAL = LIBDIR + '/openal'
+BF_OPENAL_INC = '${BF_OPENAL}/include ${BF_OPENAL}/include/AL '
+BF_OPENAL_LIB = 'dxguid openal_static'
+BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
+
+# TODO - are these useful on win32?
+# BF_CXX = '/usr'
+# WITH_BF_STATICCXX = False
+# BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
+
+WITH_BF_ICONV = True
+BF_ICONV = LIBDIR + '/iconv'
+BF_ICONV_INC = '${BF_ICONV}/include'
+BF_ICONV_LIB = 'iconv'
+BF_ICONV_LIBPATH = '${BF_ICONV}/lib'
+
+WITH_BF_SDL = True
+BF_SDL = LIBDIR + '/sdl'
+BF_SDL_INC = '${BF_SDL}/include'
+BF_SDL_LIB = 'SDL.lib'
+BF_SDL_LIBPATH = '${BF_SDL}/lib'
+
+BF_PTHREADS = LIBDIR + '/pthreads'
+BF_PTHREADS_INC = '${BF_PTHREADS}/include'
+BF_PTHREADS_LIB = 'pthreadVC2'
+BF_PTHREADS_LIBPATH = '${BF_PTHREADS}/lib'
+
+WITH_BF_FMOD = False
+BF_FMOD = LIBDIR + '/fmod'
+
+WITH_BF_OPENEXR = True
+WITH_BF_STATICOPENEXR = False
+BF_OPENEXR = LIBDIR + '/openexr'
+BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath '
+BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread '
+BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib_vs2008'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
+
+WITH_BF_DDS = True
+
+WITH_BF_JPEG = True
+BF_JPEG = LIBDIR + '/jpeg'
+BF_JPEG_INC = '${BF_JPEG}/include'
+BF_JPEG_LIB = 'libjpeg'
+BF_JPEG_LIBPATH = '${BF_JPEG}/lib'
+
+WITH_BF_PNG = True
+BF_PNG = LIBDIR + '/png'
+BF_PNG_INC = '${BF_PNG}/include'
+BF_PNG_LIB = 'libpng'
+BF_PNG_LIBPATH = '${BF_PNG}/lib'
+
+BF_TIFF = LIBDIR + '/tiff'
+BF_TIFF_INC = '${BF_TIFF}/include'
+BF_TIFF_LIB = 'libtiff'
+BF_TIFF_LIBPATH = '${BF_TIFF}/lib'
+
+WITH_BF_ZLIB = True
+BF_ZLIB = LIBDIR + '/zlib'
+BF_ZLIB_INC = '${BF_ZLIB}/include'
+BF_ZLIB_LIB = 'libz'
+BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib'
+
+WITH_BF_INTERNATIONAL = False
+
+BF_GETTEXT = LIBDIR + '/gettext'
+BF_GETTEXT_INC = '${BF_GETTEXT}/include'
+BF_GETTEXT_LIB = 'gettext'
+BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
+
+WITH_BF_GAMEENGINE = True
+WITH_BF_PLAYER = False
+
+WITH_BF_ODE = True
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = BF_ODE + '/include'
+BF_ODE_LIB = BF_ODE + '/lib/libode.a'
+
+WITH_BF_BULLET = True
+BF_BULLET = '#extern/bullet2/src'
+BF_BULLET_INC = '${BF_BULLET}'
+BF_BULLET_LIB = 'extern_bullet'
+
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
+BF_WINTAB = LIBDIR + '/wintab'
+BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE'
+
+WITH_BF_BINRELOC = False
+
+#WITH_BF_NSPR = True
+#BF_NSPR = $(LIBDIR)/nspr
+#BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr
+#BF_NSPR_LIB = 
+
+# Uncomment the following line to use Mozilla inplace of netscape
+#CPPFLAGS += -DMOZ_NOT_NET
+# Location of MOZILLA/Netscape header files...
+#BF_MOZILLA = $(LIBDIR)/mozilla
+#BF_MOZILLA_INC = -I$(BF_MOZILLA)/include/mozilla/nspr -I$(BF_MOZILLA)/include/mozilla -I$(BF_MOZILLA)/include/mozilla/xpcom -I$(BF_MOZILLA)/include/mozilla/idl
+#BF_MOZILLA_LIB =
+# Will fall back to look in BF_MOZILLA_INC/nspr and BF_MOZILLA_LIB
+# if this is not set.
+#
+# Be paranoid regarding library creation (do not update archives)
+#BF_PARANOID = True
+
+# enable freetype2 support for text objects
+BF_WITH_FREETYPE = True
+BF_FREETYPE = LIBDIR + '/freetype'
+BF_FREETYPE_INC = '${BF_FREETYPE}/include ${BF_FREETYPE}/include/freetype2'
+BF_FREETYPE_LIB = 'freetype2ST'
+BF_FREETYPE_LIBPATH = '${BF_FREETYPE}/lib'
+
+WITH_BF_QUICKTIME = False # -DWITH_QUICKTIME
+BF_QUICKTIME = LIBDIR + '/QTDevWin'
+BF_QUICKTIME_INC = '${BF_QUICKTIME}/CIncludes'
+BF_QUICKTIME_LIB = 'qtmlClient'
+BF_QUICKTIME_LIBPATH = '${BF_QUICKTIME}/Libraries'
+
+WITH_BF_OPENJPEG = False
+BF_OPENJPEG = '#extern/libopenjpeg'
+BF_OPENJPEG_LIB = ''
+BF_OPENJPEG_INC = '${BF_OPENJPEG}'
+BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib'
+
+WITH_BF_REDCODE = False  
+BF_REDCODE_INC = '#extern'
+
+WITH_BF_STATICOPENGL = False
+BF_OPENGL_INC = '${BF_OPENGL}/include'
+BF_OPENGL_LIBINC = '${BF_OPENGL}/lib'
+BF_OPENGL_LIB = 'opengl32 glu32'
+BF_OPENGL_LIB_STATIC = [ '${BF_OPENGL}/lib/libGL.a', '${BF_OPENGL}/lib/libGLU.a',
+                         '${BF_OPENGL}/lib/libXmu.a', '${BF_OPENGL}/lib/libXext.a',
+                         '${BF_OPENGL}/lib/libX11.a', '${BF_OPENGL}/lib/libXi.a' ]
+CC = 'cl.exe'
+CXX = 'cl.exe'
+
+CCFLAGS = ['/nologo', '/Ob1', '/J', '/W3', '/Gd', '/MT']
+CXXFLAGS = ['/EHsc']
+
+BF_DEBUG_CCFLAGS = ['/Zi', '/FR${TARGET}.sbr']
+
+CPPFLAGS = ['-DWIN32','-D_CONSOLE', '-D_LIB', '-DFTGL_LIBRARY_STATIC', '-D_CRT_SECURE_NO_DEPRECATE']
+REL_CFLAGS = ['-O2', '-DNDEBUG']
+REL_CCFLAGS = ['-O2', '-DNDEBUG']
+REL_CXXFLAGS = ['-O2', '-DNDEBUG']
+
+C_WARN = []
+CC_WARN = []
+CXX_WARN = []
+
+LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid']
+
+WITH_BF_DOCS=False
+
+BF_DEBUG=False
+BF_BSC=False
+CFLAGS = []
+CCFLAGS = ['/nologo', '/Ob1', '/J', '/W3', '/Gd', '/MT', '/openmp']
+CXXFLAGS = ['/EHsc']
+
+if BF_DEBUG:
+       BF_NUMJOBS=1
+else:
+       BF_NUMJOBS=6
+
+PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:X64','/ENTRY:mainCRTStartup','/INCREMENTAL:NO','/NODEFAULTLIB:"msvcprt.lib"','/NODEFAULTLIB:"glut32.lib"','/NODEFAULTLIB:"libc.lib"','/NODEFAULTLIB:"libcd.lib"','/NODEFAULTLIB:"libcpd.lib"','/NODEFAULTLIB:"libcp.lib"','/LARGEADDRESSAWARE']
+
+BF_BUILDDIR = '..\\build\\blender25-win64-vc'
+BF_INSTALLDIR='..\\install\\blender25-win64-vc'
+BF_DOCDIR='..\\install\\blender25-win64-vc\\doc'
+
+
+
+######################### MERGE WITH ABOVE ################################
+
+
+
+
+=======
 LCGDIR = '#../lib/win64'
 LIBDIR = '${LCGDIR}'
 
@@ -194,3 +401,4 @@ BF_DOCDIR='..\\install\\blender25-win64-vc\\doc'
 
 
 
+>>>>>>> .merge-right.r21114
index b8a478671150cf4940a601f6e98b362bc4f9999a..e808caf75c2f5bbab2266d8ccbd64ebf86216e63 100644 (file)
@@ -1,5 +1,5 @@
 Microsoft Visual Studio Solution File, Format Version 10.00\r
-# Visual Studio 2008\r
+# Visual C++ Express 2008\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj", "{F78B7FC9-DE32-465E-9F26-BB0B6B7A2EAF}"\r
        ProjectSection(ProjectDependencies) = postProject\r
                {E5F2F004-C704-4DCC-A08F-6EB1E38EAB9F} = {E5F2F004-C704-4DCC-A08F-6EB1E38EAB9F}\r
@@ -985,8 +985,8 @@ Global
                {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.3D Plugin Debug|Win32.Build.0 = 3DPlugin Debug|Win32\r
                {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.3D Plugin Release|Win32.ActiveCfg = 3DPlugin Debug|Win32\r
                {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.3D Plugin Release|Win32.Build.0 = 3DPlugin Debug|Win32\r
-               {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32\r
-               {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.Blender Debug|Win32.Build.0 = Blender Debug|Win32\r
+               {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.Blender Debug|Win32.ActiveCfg = Blender Release|Win32\r
+               {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.Blender Debug|Win32.Build.0 = Blender Release|Win32\r
                {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.Blender Release|Win32.ActiveCfg = Blender Release|Win32\r
                {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.Blender Release|Win32.Build.0 = Blender Release|Win32\r
                {76D90B92-ECC7-409C-9F98-A8814B90F3C0}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32\r
index eb404e27f24ab9e3389be91d260958ca157e84dc..59edf299b850f779325dc4b1a5c11c0085595be4 100644 (file)
                        Name="Source Files"\r
                        Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
                        >\r
+                       <File\r
+                               RelativePath="..\..\..\source\blender\gpu\intern\gpu_buffers.c"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\source\blender\gpu\intern\gpu_codegen.c"\r
                                >\r
                        Name="Header Files"\r
                        Filter="h;hpp;hxx;hm;inl"\r
                        >\r
+                       <File\r
+                               RelativePath="..\..\..\source\blender\gpu\gpu_buffers.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\source\blender\gpu\intern\gpu_codegen.h"\r
                                >\r
index 06103596be1026ebb02bb158837dac4df76dd05e..076747cb8454cf498b1e9fd2f3945ffeb39a2c95 100644 (file)
@@ -58,6 +58,7 @@ struct ModifierData;
 struct MCol;
 struct ColorBand;
 struct GPUVertexAttribs;
+struct GPUDrawObject;
 
 /* number of sub-elements each mesh element has (for interpolation) */
 #define SUB_ELEMS_VERT 0
@@ -72,6 +73,7 @@ struct DerivedMesh {
        int needsFree; /* checked on ->release, is set to 0 for cached results */
        int deformedOnly; /* set by modifier stack if only deformed from original */
        BVHCache bvhCache;
+       struct GPUDrawObject *drawObject;
 
        /* Misc. Queries */
 
index 090f256ab9fd52802976f777043fca80d8331781..ea6b8daf18455aa4d309ece2d7cfdcae23faa12a 100644 (file)
@@ -83,6 +83,7 @@
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "gpu_buffers.h"
 #include "GPU_draw.h"
 #include "GPU_extensions.h"
 #include "GPU_material.h"
@@ -217,7 +218,7 @@ int DM_release(DerivedMesh *dm)
 {
        if (dm->needsFree) {
                bvhcache_free(&dm->bvhCache);
-
+               GPU_drawobject_free( dm->drawObject );
                CustomData_free(&dm->vertData, dm->numVertData);
                CustomData_free(&dm->edgeData, dm->numEdgeData);
                CustomData_free(&dm->faceData, dm->numFaceData);
index 706eece108cd1261ee8944d79ea00f172f5743a1..16f6936935aa2ec994270fd8ea69347e7c7e3a8f 100644 (file)
@@ -60,6 +60,7 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "gpu_buffers.h"
 #include "GPU_draw.h"
 #include "GPU_extensions.h"
 #include "GPU_material.h"
@@ -266,58 +267,73 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *a
        glVertex3fv(mvert[index].co);   \
 }
 
-       glBegin(glmode = GL_QUADS);
-       for(a = 0; a < dm->numFaceData; a++, mface++) {
-               int new_glmode, new_matnr, new_shademodel;
+       if( GPU_buffer_legacy(dm) ) {
+               DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
+               glBegin(glmode = GL_QUADS);
+               for(a = 0; a < dm->numFaceData; a++, mface++) {
+                       int new_glmode, new_matnr, new_shademodel;
 
-               new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
-               new_matnr = mface->mat_nr + 1;
-               new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
-               
-               if(new_glmode != glmode || new_matnr != matnr
-                  || new_shademodel != shademodel) {
-                       glEnd();
+                       new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
+                       new_matnr = mface->mat_nr + 1;
+                       new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
+                       
+                       if(new_glmode != glmode || new_matnr != matnr
+                          || new_shademodel != shademodel) {
+                               glEnd();
 
-                       drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
+                               drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
 
-                       glShadeModel(shademodel = new_shademodel);
-                       glBegin(glmode = new_glmode);
-               } 
-               
-               if(drawCurrentMat) {
-                       if(shademodel == GL_FLAT) {
-                               if (nors) {
-                                       glNormal3fv(nors);
-                               }
-                               else {
-                                       /* TODO make this better (cache facenormals as layer?) */
-                                       float nor[3];
-                                       if(mface->v4) {
-                                               CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
-                                                                          mvert[mface->v3].co, mvert[mface->v4].co,
-                                                                          nor);
-                                       } else {
-                                               CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
-                                                                         mvert[mface->v3].co, nor);
+                               glShadeModel(shademodel = new_shademodel);
+                               glBegin(glmode = new_glmode);
+                       } 
+                       
+                       if(drawCurrentMat) {
+                               if(shademodel == GL_FLAT) {
+                                       if (nors) {
+                                               glNormal3fv(nors);
+                                       }
+                                       else {
+                                               /* TODO make this better (cache facenormals as layer?) */
+                                               float nor[3];
+                                               if(mface->v4) {
+                                                       CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
+                                                                                  mvert[mface->v3].co, mvert[mface->v4].co,
+                                                                                  nor);
+                                               } else {
+                                                       CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
+                                                                                 mvert[mface->v3].co, nor);
+                                               }
+                                               glNormal3fv(nor);
                                        }
-                                       glNormal3fv(nor);
+                               }
+
+                               PASSVERT(mface->v1);
+                               PASSVERT(mface->v2);
+                               PASSVERT(mface->v3);
+                               if(mface->v4) {
+                                       PASSVERT(mface->v4);
                                }
                        }
 
-                       PASSVERT(mface->v1);
-                       PASSVERT(mface->v2);
-                       PASSVERT(mface->v3);
-                       if(mface->v4) {
-                               PASSVERT(mface->v4);
+                       if(nors) nors += 3;
+               }
+               glEnd();
+       }
+       else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
+               GPU_vertex_setup( dm );
+               GPU_normal_setup( dm );
+               if( !GPU_buffer_legacy(dm) ) {
+                       glShadeModel(GL_SMOOTH);
+                       for( a = 0; a < dm->drawObject->nmaterials; a++ ) {
+                               setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL);
+                               glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
                        }
                }
-
-               if(nors) nors += 3;
+               GPU_buffer_unbind( );
        }
-       glEnd();
 
-       glShadeModel(GL_FLAT);
 #undef PASSVERT
+       glShadeModel(GL_FLAT);
 }
 
 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
@@ -341,43 +357,64 @@ static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha
        /* we need that as mesh option builtin, next to double sided lighting */
        if(col1 && col2)
                glEnable(GL_CULL_FACE);
-       
-       glShadeModel(GL_SMOOTH);
-       glBegin(glmode = GL_QUADS);
-       for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
-               int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
 
-               if(new_glmode != glmode) {
-                       glEnd();
-                       glBegin(glmode = new_glmode);
-               }
-                       
-               glColor3ub(cp1[0], cp1[1], cp1[2]);
-               glVertex3fv(mvert[mface->v1].co);
-               glColor3ub(cp1[4], cp1[5], cp1[6]);
-               glVertex3fv(mvert[mface->v2].co);
-               glColor3ub(cp1[8], cp1[9], cp1[10]);
-               glVertex3fv(mvert[mface->v3].co);
-               if(mface->v4) {
-                       glColor3ub(cp1[12], cp1[13], cp1[14]);
-                       glVertex3fv(mvert[mface->v4].co);
-               }
-                       
-               if(useTwoSided) {
-                       glColor3ub(cp2[8], cp2[9], cp2[10]);
-                       glVertex3fv(mvert[mface->v3].co );
-                       glColor3ub(cp2[4], cp2[5], cp2[6]);
-                       glVertex3fv(mvert[mface->v2].co );
-                       glColor3ub(cp2[0], cp2[1], cp2[2]);
-                       glVertex3fv(mvert[mface->v1].co );
+       if( GPU_buffer_legacy(dm) ) {
+               DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
+               glShadeModel(GL_SMOOTH);
+               glBegin(glmode = GL_QUADS);
+               for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
+                       int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
+
+                       if(new_glmode != glmode) {
+                               glEnd();
+                               glBegin(glmode = new_glmode);
+                       }
+                               
+                       glColor3ub(cp1[0], cp1[1], cp1[2]);
+                       glVertex3fv(mvert[mface->v1].co);
+                       glColor3ub(cp1[4], cp1[5], cp1[6]);
+                       glVertex3fv(mvert[mface->v2].co);
+                       glColor3ub(cp1[8], cp1[9], cp1[10]);
+                       glVertex3fv(mvert[mface->v3].co);
                        if(mface->v4) {
-                               glColor3ub(cp2[12], cp2[13], cp2[14]);
-                               glVertex3fv(mvert[mface->v4].co );
+                               glColor3ub(cp1[12], cp1[13], cp1[14]);
+                               glVertex3fv(mvert[mface->v4].co);
                        }
+                               
+                       if(useTwoSided) {
+                               glColor3ub(cp2[8], cp2[9], cp2[10]);
+                               glVertex3fv(mvert[mface->v3].co );
+                               glColor3ub(cp2[4], cp2[5], cp2[6]);
+                               glVertex3fv(mvert[mface->v2].co );
+                               glColor3ub(cp2[0], cp2[1], cp2[2]);
+                               glVertex3fv(mvert[mface->v1].co );
+                               if(mface->v4) {
+                                       glColor3ub(cp2[12], cp2[13], cp2[14]);
+                                       glVertex3fv(mvert[mface->v4].co );
+                               }
+                       }
+                       if(col2) cp2 += 16;
                }
-               if(col2) cp2 += 16;
+               glEnd();
+       }
+       else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
+               GPU_color4_upload(dm,cp1);
+               GPU_vertex_setup(dm);
+               GPU_color_setup(dm);
+               if( !GPU_buffer_legacy(dm) ) {
+                       glShadeModel(GL_SMOOTH);
+                       glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
+
+                       if( useTwoSided ) {
+                               GPU_color4_upload(dm,cp2);
+                               GPU_color_setup(dm);
+                               glCullFace(GL_FRONT);
+                               glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
+                               glCullFace(GL_BACK);
+                       }
+               }
+               GPU_buffer_unbind();
        }
-       glEnd();
 
        glShadeModel(GL_FLAT);
        glDisable(GL_CULL_FACE);
@@ -395,80 +432,147 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
        float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
        MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
        int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+       int startFace = 0, lastFlag = 0xdeadbeef;
 
-       for(i = 0; i < dm->numFaceData; i++, mf++) {
-               MVert *mvert;
-               int flag;
-               unsigned char *cp = NULL;
+       if( GPU_buffer_legacy(dm) ) {
+               DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
+               for(i = 0; i < dm->numFaceData; i++, mf++) {
+                       MVert *mvert;
+                       int flag;
+                       unsigned char *cp = NULL;
+
+                       if(drawParams) {
+                               flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
+                       }
+                       else {
+                               if(index) {
+                                       orig = *index++;
+                                       if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
+                                       if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
+                                       else    { if(nors) nors += 3; continue; }
+                               }
+                               else
+                                       if(drawParamsMapped) flag = drawParamsMapped(userData, i);
+                                       else    { if(nors) nors += 3; continue; }
+                       }
+                       
+                       if(flag != 0) {
+                               if (flag==1 && mcol)
+                                       cp= (unsigned char*) &mcol[i*4];
+
+                               if(!(mf->flag&ME_SMOOTH)) {
+                                       if (nors) {
+                                               glNormal3fv(nors);
+                                       }
+                                       else {
+                                               float nor[3];
+                                               if(mf->v4) {
+                                                       CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
+                                                                                  mv[mf->v3].co, mv[mf->v4].co,
+                                                                                  nor);
+                                               } else {
+                                                       CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
+                                                                                 mv[mf->v3].co, nor);
+                                               }
+                                               glNormal3fv(nor);
+                                       }
+                               }
+
+                               glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
+                               if(tf) glTexCoord2fv(tf[i].uv[0]);
+                               if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+                               mvert = &mv[mf->v1];
+                               if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+                               glVertex3fv(mvert->co);
+                                       
+                               if(tf) glTexCoord2fv(tf[i].uv[1]);
+                               if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+                               mvert = &mv[mf->v2];
+                               if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+                               glVertex3fv(mvert->co);
+
+                               if(tf) glTexCoord2fv(tf[i].uv[2]);
+                               if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+                               mvert = &mv[mf->v3];
+                               if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+                               glVertex3fv(mvert->co);
 
-               if(drawParams) {
-                       flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
+                               if(mf->v4) {
+                                       if(tf) glTexCoord2fv(tf[i].uv[3]);
+                                       if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+                                       mvert = &mv[mf->v4];
+                                       if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+                                       glVertex3fv(mvert->co);
+                               }
+                               glEnd();
+                       }
+                       
+                       if(nors) nors += 3;
                }
-               else {
-                       if(index) {
-                               orig = *index++;
-                               if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
-                               if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
-                               else    { if(nors) nors += 3; continue; }
+       } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
+               GPU_vertex_setup( dm );
+               GPU_normal_setup( dm );
+               GPU_uv_setup( dm );
+               if( mcol != 0 ) {
+                       if( dm->drawObject->colType != CD_MCOL ) {
+                               unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
+                               for( i=0; i < dm->getNumFaces(dm); i++ ) {
+                                       colors[i*3] = mcol[i].r;
+                                       colors[i*3+1] = mcol[i].g;
+                                       colors[i*3+2] = mcol[i].b;
+                               }
+                               GPU_color3_upload(dm,colors);
+                               MEM_freeN(colors);
+                               dm->drawObject->colType = CD_MCOL;
                        }
-                       else
-                               if(drawParamsMapped) flag = drawParamsMapped(userData, i);
-                               else    { if(nors) nors += 3; continue; }
+                       GPU_color_setup( dm );
                }
-               
-               if(flag != 0) { /* if the flag is 0 it means the face is hidden or invisible */
-                       if (flag==1 && mcol)
-                               cp= (unsigned char*) &mcol[i*4];
-
-                       if(!(mf->flag&ME_SMOOTH)) {
-                               if (nors) {
-                                       glNormal3fv(nors);
+               if( !GPU_buffer_legacy(dm) ) {
+                       glShadeModel( GL_SMOOTH );
+                       for(i = 0; i < dm->drawObject->nelements/3; i++) {
+                               int actualFace = dm->drawObject->faceRemap[i];
+                               int flag;
+                               unsigned char *cp = NULL;
+
+                               if(drawParams) {
+                                       flag = drawParams(tf? &tf[actualFace]: NULL, mcol? &mcol[actualFace*4]: NULL, mf[actualFace].mat_nr);
                                }
                                else {
-                                       /* TODO make this better (cache facenormals as layer?) */
-                                       float nor[3];
-                                       if(mf->v4) {
-                                               CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
-                                                                          mv[mf->v3].co, mv[mf->v4].co,
-                                                                          nor);
-                                       } else {
-                                               CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
-                                                                         mv[mf->v3].co, nor);
+                                       if(index) {
+                                               orig = index[actualFace];
+                                               if(drawParamsMapped)
+                                                       flag = drawParamsMapped(userData, orig);
                                        }
-                                       glNormal3fv(nor);
+                                       else
+                                               if(drawParamsMapped)
+                                                       flag = drawParamsMapped(userData, actualFace);
+                               }
+                               if( flag != lastFlag ) {
+                                       if( startFace < i ) {
+                                               if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
+                                                       if (lastFlag==1 && mcol)
+                                                               GPU_color_switch(1);
+                                                       else
+                                                               GPU_color_switch(0);
+                                                       glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
+                                               }
+                                       }
+                                       lastFlag = flag;
+                                       startFace = i;
                                }
                        }
-
-                       glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
-                       if(tf) glTexCoord2fv(tf[i].uv[0]);
-                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                       mvert = &mv[mf->v1];
-                       if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
-                       glVertex3fv(mvert->co);
-                               
-                       if(tf) glTexCoord2fv(tf[i].uv[1]);
-                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                       mvert = &mv[mf->v2];
-                       if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
-                       glVertex3fv(mvert->co);
-
-                       if(tf) glTexCoord2fv(tf[i].uv[2]);
-                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                       mvert = &mv[mf->v3];
-                       if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
-                       glVertex3fv(mvert->co);
-
-                       if(mf->v4) {
-                               if(tf) glTexCoord2fv(tf[i].uv[3]);
-                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                               mvert = &mv[mf->v4];
-                               if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
-                               glVertex3fv(mvert->co);
+                       if( startFace < dm->drawObject->nelements/3 ) {
+                               if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
+                                       if (lastFlag==1 && mcol)
+                                               GPU_color_switch(1);
+                                       else
+                                               GPU_color_switch(0);
+                                       glDrawArrays(GL_TRIANGLES,startFace*3,dm->drawObject->nelements-startFace*3);
+                               }
                        }
-                       glEnd();
                }
-               
-               if(nors) nors += 3;
+               GPU_buffer_unbind();
+               glShadeModel( GL_FLAT );
        }
 }
 
@@ -490,75 +594,124 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
        if(!mc)
                mc = DM_get_face_data_layer(dm, CD_MCOL);
 
-       for(i = 0; i < dm->numFaceData; i++, mf++) {
-               int drawSmooth = (mf->flag & ME_SMOOTH);
+       if( GPU_buffer_legacy(dm) ) {
+               DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
+               for(i = 0; i < dm->numFaceData; i++, mf++) {
+                       int drawSmooth = (mf->flag & ME_SMOOTH);
 
-               if(index) {
-                       orig = *index++;
-                       if(setDrawOptions && orig == ORIGINDEX_NONE)
-                               { if(nors) nors += 3; continue; }
-               }
-               else
-                       orig = i;
+                       if(index) {
+                               orig = *index++;
+                               if(setDrawOptions && orig == ORIGINDEX_NONE)
+                                       { if(nors) nors += 3; continue; }
+                       }
+                       else
+                               orig = i;
 
-               if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
-                       unsigned char *cp = NULL;
+                       if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
+                               unsigned char *cp = NULL;
 
-                       if(useColors && mc)
-                               cp = (unsigned char *)&mc[i * 4];
+                               if(useColors && mc)
+                                       cp = (unsigned char *)&mc[i * 4];
 
-                       glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
-                       glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
+                               glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+                               glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
 
-                       if (!drawSmooth) {
-                               if (nors) {
-                                       glNormal3fv(nors);
-                               }
-                               else {
-                                       /* TODO make this better (cache facenormals as layer?) */
-                                       float nor[3];
+                               if (!drawSmooth) {
+                                       if (nors) {
+                                               glNormal3fv(nors);
+                                       }
+                                       else {
+                                               float nor[3];
+                                               if(mf->v4) {
+                                                       CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
+                                                                                  mv[mf->v3].co, mv[mf->v4].co,
+                                                                                  nor);
+                                               } else {
+                                                       CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
+                                                                                 mv[mf->v3].co, nor);
+                                               }
+                                               glNormal3fv(nor);
+                                       }
+
+                                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+                                       glVertex3fv(mv[mf->v1].co);
+                                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+                                       glVertex3fv(mv[mf->v2].co);
+                                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+                                       glVertex3fv(mv[mf->v3].co);
                                        if(mf->v4) {
-                                               CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
-                                                                          mv[mf->v3].co, mv[mf->v4].co,
-                                                                          nor);
-                                       } else {
-                                               CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
-                                                                         mv[mf->v3].co, nor);
+                                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+                                               glVertex3fv(mv[mf->v4].co);
+                                       }
+                               } else {
+                                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+                                       glNormal3sv(mv[mf->v1].no);
+                                       glVertex3fv(mv[mf->v1].co);
+                                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+                                       glNormal3sv(mv[mf->v2].no);
+                                       glVertex3fv(mv[mf->v2].co);
+                                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+                                       glNormal3sv(mv[mf->v3].no);
+                                       glVertex3fv(mv[mf->v3].co);
+                                       if(mf->v4) {
+                                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+                                               glNormal3sv(mv[mf->v4].no);
+                                               glVertex3fv(mv[mf->v4].co);
                                        }
-                                       glNormal3fv(nor);
                                }
 
-                               if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                               glVertex3fv(mv[mf->v1].co);
-                               if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                               glVertex3fv(mv[mf->v2].co);
-                               if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                               glVertex3fv(mv[mf->v3].co);
-                               if(mf->v4) {
-                                       if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                                       glVertex3fv(mv[mf->v4].co);
+                               glEnd();
+                       }
+                       
+                       if (nors) nors += 3;
+               }
+       }
+       else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
+               int state = 1;
+               int prevstate = 1;
+               int prevstart = 0;
+               GPU_vertex_setup(dm);
+               GPU_normal_setup(dm);
+               if( useColors && mc )
+                       GPU_color_setup(dm);
+               if( !GPU_buffer_legacy(dm) ) {
+                       glShadeModel(GL_SMOOTH);
+                       for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
+                               int actualFace = dm->drawObject->faceRemap[i];
+                               int drawSmooth = (mf[actualFace].flag & ME_SMOOTH);
+                               int dontdraw = 0;
+                               if(index) {
+                                       orig = index[actualFace];
+                                       if(setDrawOptions && orig == ORIGINDEX_NONE)
+                                               dontdraw = 1;
                                }
-                       } else {
-                               if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                               glNormal3sv(mv[mf->v1].no);
-                               glVertex3fv(mv[mf->v1].co);
-                               if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                               glNormal3sv(mv[mf->v2].no);
-                               glVertex3fv(mv[mf->v2].co);
-                               if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                               glNormal3sv(mv[mf->v3].no);
-                               glVertex3fv(mv[mf->v3].co);
-                               if(mf->v4) {
-                                       if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                                       glNormal3sv(mv[mf->v4].no);
-                                       glVertex3fv(mv[mf->v4].co);
+                               else
+                                       orig = i;
+                               if( dontdraw ) {
+                                       state = 0;
+                               }
+                               else {
+                                       if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
+                                               state = 1;
+                                       }
+                                       else {
+                                               state = 0;
+                                       }
+                               }
+                               if( prevstate != state && prevstate == 1 ) {
+                                       if( i-prevstart > 0 ) {
+                                               glDrawArrays(GL_TRIANGLES,prevstart*3,(i-prevstart)*3);
+                                       }
+                                       prevstart = i;
                                }
+                               prevstate = state;
                        }
-
-                       glEnd();
+                       if(state==1) {
+                               glDrawArrays(GL_TRIANGLES,prevstart*3,dm->drawObject->nelements-prevstart*3);
+                       }
+                       glShadeModel(GL_FLAT);
                }
-               
-               if (nors) nors += 3;
+               GPU_buffer_unbind();
        }
 }
 
index b38575b5cebb25625ee242da6471a63785b9cc3c..3eeb095f0297647285d9c4cb6404b2bc4ddfaf9d 100644 (file)
@@ -95,6 +95,7 @@
 #include "GPU_draw.h"
 #include "GPU_material.h"
 #include "GPU_extensions.h"
+#include "gpu_buffers.h"
 
 #include "ED_mesh.h"
 #include "ED_particle.h"
index 63f5fe532388c4d73519d9a5c085c607af0e771e..f72decfeada119d38c114823771e9463c586bd6c 100644 (file)
@@ -8,4 +8,4 @@ incs += ' #/extern/glew/include #intern/guardedalloc ../imbuf .'
 
 incs += ' ' + env['BF_OPENGL_INC']
 
-env.BlenderLib ( 'bf_gpu', sources, Split(incs), [], libtype=['core', 'player'], priority=[160, 20] )
+env.BlenderLib ( 'bf_gpu', sources, Split(incs), [], libtype=['core', 'player'], priority=[166, 20] )
diff --git a/source/blender/gpu/gpu_buffers.h b/source/blender/gpu/gpu_buffers.h
new file mode 100644 (file)
index 0000000..b3c700a
--- /dev/null
@@ -0,0 +1,113 @@
+/**
+ * $Id: gpu_buffers.h 20687 2009-06-07 11:26:46Z imbusy $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GPU_BUFFERS_H__
+#define __GPU_BUFFERS_H__
+
+#define MAX_FREE_GPU_BUFFERS 8
+
+#ifdef _DEBUG
+#define DEBUG_VBO(X) printf(X)
+#else
+#define DEBUG_VBO(X)
+#endif
+
+struct DerivedMesh;
+
+typedef struct GPUBuffer
+{
+       int size;       /* in bytes */
+       void *pointer;  /* used with vertex arrays */
+       unsigned int id;        /* used with vertex buffer objects */
+} GPUBuffer;
+
+typedef struct GPUBufferPool
+{
+       int size;       /* number of allocated buffers stored */
+       int start;      /* for a queue like structure */
+                               /* when running out of space for storing buffers,
+                               the last one used will be thrown away */
+
+       GPUBuffer* buffers[MAX_FREE_GPU_BUFFERS];
+} GPUBufferPool;
+
+typedef struct GPUBufferMaterial
+{
+       int start;      /* at which vertex in the buffer the material starts */
+       int end;        /* at which vertex it ends */
+       char mat_nr;
+} GPUBufferMaterial;
+
+typedef struct GPUDrawObject
+{
+       GPUBuffer *vertices;
+       GPUBuffer *normals;
+       GPUBuffer *uv;
+       GPUBuffer *colors;
+       int     *faceRemap;             /* at what index was the face originally in DerivedMesh */
+       int colType;
+
+       GPUBufferMaterial *materials;
+
+       int nmaterials;
+       int nelements;
+       int legacy;     /* if there was a failure allocating some buffer, use old rendering code */
+} GPUDrawObject;
+
+GPUBufferPool *GPU_buffer_pool_new();
+void GPU_buffer_pool_free( GPUBufferPool *pool );      /* TODO: Find a place where to call this function on exit */
+
+GPUBuffer *GPU_buffer_alloc( int size, GPUBufferPool *pool );
+void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool );
+
+GPUDrawObject *GPU_drawobject_new( struct DerivedMesh *dm );
+void GPU_drawobject_free( GPUDrawObject *object );
+
+/* called before drawing */
+void GPU_vertex_setup( struct DerivedMesh *dm );
+void GPU_normal_setup( struct DerivedMesh *dm );
+void GPU_uv_setup( struct DerivedMesh *dm );
+void GPU_color_setup( struct DerivedMesh *dm );
+
+/* upload three unsigned chars, representing RGB colors, for each vertex. Resets dm->drawObject->colType to -1 */
+void GPU_color3_upload( struct DerivedMesh *dm, char *data );
+/* upload four unsigned chars, representing RGBA colors, for each vertex. Resets dm->drawObject->colType to -1 */
+void GPU_color4_upload( struct DerivedMesh *dm, char *data );
+/* switch color rendering on=1/off=0 */
+void GPU_color_switch( int mode );
+
+/* called after drawing */
+void GPU_buffer_unbind();
+
+int GPU_buffer_legacy( struct DerivedMesh *dm );
+
+#endif
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
new file mode 100644 (file)
index 0000000..25cd862
--- /dev/null
@@ -0,0 +1,766 @@
+/**
+ * $Id: gpu_buffers.c 19820 2009-04-20 15:06:46Z imbusy $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#include "GL/glew.h"
+
+#include "gpu_buffers.h"
+#include "MEM_guardedalloc.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_utildefines.h"
+#include "DNA_meshdata_types.h"
+#include "BLI_arithb.h"
+
+#define GPU_BUFFER_VERTEX_STATE 1
+#define GPU_BUFFER_NORMAL_STATE 2
+#define GPU_BUFFER_TEXCOORD_STATE 4
+#define GPU_BUFFER_COLOR_STATE 8
+
+/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
+int useVBOs = -1;
+GPUBufferPool *globalPool = 0;
+int GLStates = 0;
+
+GPUBufferPool *GPU_buffer_pool_new()
+{
+       GPUBufferPool *pool;
+
+       DEBUG_VBO("GPU_buffer_pool_new\n");
+
+       if( useVBOs < 0 ) {
+               if( GL_ARB_vertex_buffer_object ) {
+                       DEBUG_VBO( "Vertex Buffer Objects supported.\n" );
+                       useVBOs = 1;
+               }
+               else {
+                       DEBUG_VBO( "Vertex Buffer Objects NOT supported.\n" );
+                       useVBOs = 0;
+               }
+       }
+
+       pool = MEM_callocN(sizeof(GPUBufferPool), "GPU_buffer_pool_new");
+
+       return pool;
+}
+
+void GPU_buffer_pool_free(GPUBufferPool *pool)
+{
+       int i;
+
+       DEBUG_VBO("GPU_buffer_pool_free\n");
+
+       while( pool->start < 0 )
+               pool->start += MAX_FREE_GPU_BUFFERS;
+
+       for( i = 0; i < pool->size; i++ ) {
+               if( useVBOs ) {
+                       glDeleteBuffersARB( 1, &pool->buffers[(pool->start+i)%MAX_FREE_GPU_BUFFERS]->id );
+               }
+               else {
+                       MEM_freeN( pool->buffers[(pool->start+i) % MAX_FREE_GPU_BUFFERS ]->pointer );
+               }
+       }
+}
+
+void GPU_buffer_pool_remove( int index, GPUBufferPool *pool )
+{
+       int i;
+
+       DEBUG_VBO("GPU_buffer_pool_remove\n");
+
+       while( pool->start < 0 )
+               pool->start += MAX_FREE_GPU_BUFFERS;
+       for( i = index; i < pool->size-1; i++ ) {
+               pool->buffers[(pool->start+i)%MAX_FREE_GPU_BUFFERS] = pool->buffers[(pool->start+i+1)%MAX_FREE_GPU_BUFFERS];
+       }
+       pool->size--;
+}
+
+void GPU_buffer_pool_delete_last( GPUBufferPool *pool )
+{
+       int last;
+
+       DEBUG_VBO("GPU_buffer_pool_delete_last\n");
+
+       if( pool->size == 0 )
+               return;
+
+       last = pool->start+pool->size-1;
+       while( last < 0 )
+               last += MAX_FREE_GPU_BUFFERS;
+       last = (last+MAX_FREE_GPU_BUFFERS)%MAX_FREE_GPU_BUFFERS;
+
+       if( useVBOs ) {
+               glDeleteBuffersARB(1,&pool->buffers[last]->id);
+               MEM_freeN( pool->buffers[last] );
+       }
+       else {
+               MEM_freeN( pool->buffers[last]->pointer );
+               MEM_freeN( pool->buffers[last] );
+       }
+       pool->size--;
+}
+
+GPUBuffer *GPU_buffer_alloc( int size, GPUBufferPool *pool )
+{
+       char buffer[60];
+       int i;
+       int cursize;
+       GPUBuffer *allocated;
+       int bestfit = -1;
+
+       DEBUG_VBO("GPU_buffer_alloc\n");
+
+       while( pool->start < 0 )
+               pool->start += MAX_FREE_GPU_BUFFERS;
+
+       for( i = 0; i < pool->size; i++ ) {
+               int actuali = (pool->start+i)%MAX_FREE_GPU_BUFFERS;
+               cursize = pool->buffers[actuali]->size;
+               if( cursize == size ) {
+                       allocated = pool->buffers[actuali];
+                       GPU_buffer_pool_remove(i,pool);
+                       DEBUG_VBO("free buffer of exact size found\n");
+                       return allocated;
+               }
+               /* smaller buffers won't fit data and buffers at least twice as big are a waste of memory */
+               else if( cursize > size && size > cursize/2 ) {
+                       /* is it closer to the required size than the last appropriate buffer found. try to save memory */
+                       if( bestfit == -1 || pool->buffers[(pool->start+bestfit)%MAX_FREE_GPU_BUFFERS]->size > cursize ) {
+                               bestfit = i;
+                       }
+               }
+       }
+       if( bestfit == -1 ) {
+               DEBUG_VBO("allocating a new buffer\n");
+
+               allocated = MEM_mallocN(sizeof(GPUBuffer), "GPU_buffer_alloc");
+               allocated->size = size;
+               if( useVBOs == 1 ) {
+                       glGenBuffersARB( 1, &allocated->id );
+                       glBindBufferARB( GL_ARRAY_BUFFER_ARB, allocated->id );
+                       glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, 0, GL_STATIC_DRAW_ARB );
+                       glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
+               }
+               else {
+                       allocated->pointer = MEM_mallocN(size, "GPU_buffer_alloc_vertexarray");
+                       while( allocated->pointer == 0 && pool->size > 0 ) {
+                               GPU_buffer_pool_delete_last(pool);
+                               allocated->pointer = MEM_mallocN(size, "GPU_buffer_alloc_vertexarray");
+                       }
+                       if( allocated->pointer == 0 && pool->size == 0 ) {
+                               return 0;
+                       }
+               }
+       }
+       else {
+               sprintf(buffer,"free buffer found. Wasted %d bytes\n", pool->buffers[(pool->start+bestfit)%MAX_FREE_GPU_BUFFERS]->size-size);
+               DEBUG_VBO(buffer);
+
+               allocated = pool->buffers[(pool->start+bestfit)%MAX_FREE_GPU_BUFFERS];
+               GPU_buffer_pool_remove(bestfit,pool);
+       }
+       return allocated;
+}
+
+void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool )
+{
+       int place;
+
+       DEBUG_VBO("GPU_buffer_free\n");
+
+       if( buffer == 0 )
+               return;
+       if( pool == 0 )
+               pool = globalPool;
+       if( pool == 0 )
+               globalPool = GPU_buffer_pool_new();
+
+       while( pool->start < 0 )
+               pool->start += MAX_FREE_GPU_BUFFERS;
+       place = (pool->start-1 + MAX_FREE_GPU_BUFFERS)%MAX_FREE_GPU_BUFFERS;
+
+       /* free the last used buffer in the queue if no more space */
+       if( pool->size == MAX_FREE_GPU_BUFFERS ) {
+               GPU_buffer_pool_delete_last( pool );
+       }
+
+       pool->size++;
+       pool->start = place;
+       pool->buffers[place] = buffer;
+}
+
+GPUDrawObject *GPU_drawobject_new( DerivedMesh *dm )
+{
+       GPUDrawObject *object;
+       MVert *mvert;
+       MFace *mface;
+       int numverts[256];      /* material number is an 8-bit char so there's at most 256 materials */
+       int redir[256];         /* material number is an 8-bit char so there's at most 256 materials */
+       int *index;
+       int i;
+       int curmat, curverts;
+
+       DEBUG_VBO("GPU_drawobject_new\n");
+
+       object = MEM_callocN(sizeof(GPUDrawObject),"GPU_drawobject_new");
+
+       memset(numverts,0,sizeof(int)*256);
+
+       mvert = dm->getVertArray(dm);
+       mface = dm->getFaceArray(dm);
+
+       for( i=0; i < dm->getNumFaces(dm); i++ ) {
+               if( mface[i].v4 )
+                       numverts[mface[i].mat_nr+127] += 6;     /* split every quad into two triangles */
+               else
+                       numverts[mface[i].mat_nr+127] += 3;
+       }
+
+       for( i = 0; i < 256; i++ ) {
+               if( numverts[i] > 0 ) {
+                       object->nmaterials++;
+                       object->nelements += numverts[i];
+               }
+       }
+       object->materials = MEM_mallocN(sizeof(GPUBufferMaterial)*object->nmaterials,"GPU_drawobject_new_materials");
+       index = MEM_mallocN(sizeof(int)*object->nmaterials,"GPU_buffer_setup_index");
+
+       curmat = curverts = 0;
+       for( i = 0; i < 256; i++ ) {
+               if( numverts[i] > 0 ) {
+                       object->materials[curmat].mat_nr = i-127;
+                       object->materials[curmat].start = curverts;
+                       index[curmat] = curverts/3;
+                       object->materials[curmat].end = curverts+numverts[i];
+                       curverts += numverts[i];
+                       curmat++;
+               }
+       }
+       object->faceRemap = MEM_mallocN(sizeof(int)*object->nelements/3,"GPU_drawobject_new_faceRemap");
+       for( i = 0; i < object->nmaterials; i++ ) {
+               redir[object->materials[i].mat_nr+127] = i;     /* material number -> material index */
+       }
+
+       for( i=0; i < dm->getNumFaces(dm); i++ ) {
+               object->faceRemap[index[redir[mface[i].mat_nr+127]]] = i; 
+               if( mface[i].v4 ) {
+                       object->faceRemap[index[redir[mface[i].mat_nr+127]]+1] = i;
+                       index[redir[mface[i].mat_nr+127]]+=2;
+               }
+               else
+               {
+                       index[redir[mface[i].mat_nr+127]]++;
+               }
+       }
+       MEM_freeN(index);
+       return object;
+}
+
+void GPU_drawobject_free( GPUDrawObject *object )
+{
+       if( object == 0 )
+               return;
+
+       DEBUG_VBO("GPU_drawobject_free\n");
+
+       MEM_freeN(object->materials);
+       MEM_freeN(object->faceRemap);
+       GPU_buffer_free( object->vertices, globalPool );
+       GPU_buffer_free( object->normals, globalPool );
+       GPU_buffer_free( object->uv, globalPool );
+       GPU_buffer_free( object->colors, globalPool );
+
+       MEM_freeN(object);
+}
+
+GPUBuffer *GPU_buffer_setup( DerivedMesh *dm, GPUDrawObject *object, int size, void *user, void (*copy_f)(DerivedMesh *, float *, int *, int *, void *) )
+{
+       GPUBuffer *buffer;
+       float *varray;
+       int redir[256];
+       int *index;
+       int i;
+       int success;
+       GLboolean uploaded;
+
+       DEBUG_VBO("GPU_buffer_setup\n");
+
+       if( globalPool == 0 )
+               globalPool = GPU_buffer_pool_new();
+       buffer = GPU_buffer_alloc(size,globalPool);
+       if( buffer == 0 ) {
+               dm->drawObject->legacy = 1;
+       }
+       if( dm->drawObject->legacy ) {
+               return 0;
+       }
+
+       index = MEM_mallocN(sizeof(int)*object->nmaterials,"GPU_buffer_setup");
+       for( i = 0; i < object->nmaterials; i++ ) {
+               index[i] = object->materials[i].start*3;
+               redir[object->materials[i].mat_nr+127] = i;
+       }
+
+       if( useVBOs ) {
+               success = 0;
+               while( success == 0 ) {
+                       glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffer->id );
+                       glBufferDataARB( GL_ARRAY_BUFFER_ARB, buffer->size, 0, GL_STATIC_DRAW_ARB );    /* discard previous data, avoid stalling gpu */
+                       varray = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
+                       if( varray == 0 ) {
+                               DEBUG_VBO( "Failed to map buffer to client address space\n" ); 
+                               GPU_buffer_free( buffer, globalPool );
+                               GPU_buffer_pool_delete_last( globalPool );
+                               if( globalPool->size > 0 ) {
+                                       GPU_buffer_pool_delete_last( globalPool );
+                                       buffer = GPU_buffer_alloc( size, globalPool );
+                                       if( buffer == 0 ) {
+                                               dm->drawObject->legacy = 1;
+                                               success = 1;
+                                       }
+                               }
+                               else {
+                                       dm->drawObject->legacy = 1;
+                                       success = 1;
+                               }
+                       }
+                       else {
+                               success = 1;
+                       }
+               }
+
+               if( dm->drawObject->legacy == 0 ) {
+                       uploaded = GL_FALSE;
+                       while( !uploaded ) {
+                               (*copy_f)( dm, varray, index, redir, user );
+                               uploaded = glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );     /* returns false if data got corruped during transfer */
+                       }
+               }
+               glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+       }
+       else {
+               if( buffer->pointer != 0 ) {
+                       varray = buffer->pointer;
+                       (*copy_f)( dm, varray, index, redir, user );
+               }
+               else {
+                       dm->drawObject->legacy = 1;
+               }
+       }
+
+       MEM_freeN(index);
+
+       return buffer;
+}
+
+void GPU_buffer_copy_vertex( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
+{
+       int start;
+       int i;
+
+       MVert *mvert;
+       MFace *mface;
+
+       DEBUG_VBO("GPU_buffer_copy_vertex\n");
+
+       mvert = dm->getVertArray(dm);
+       mface = dm->getFaceArray(dm);
+
+       for( i=0; i < dm->getNumFaces(dm); i++ ) {
+               start = index[redir[mface[i].mat_nr+127]];
+               if( mface[i].v4 )
+                       index[redir[mface[i].mat_nr+127]] += 18;
+               else
+                       index[redir[mface[i].mat_nr+127]] += 9;
+
+               /* v1 v2 v3 */
+               VECCOPY(&varray[start],mvert[mface[i].v1].co);
+               VECCOPY(&varray[start+3],mvert[mface[i].v2].co);
+               VECCOPY(&varray[start+6],mvert[mface[i].v3].co);
+
+               if( mface[i].v4 ) {
+                       /* v3 v4 v1 */
+                       VECCOPY(&varray[start+9],mvert[mface[i].v3].co);
+                       VECCOPY(&varray[start+12],mvert[mface[i].v4].co);
+                       VECCOPY(&varray[start+15],mvert[mface[i].v1].co);
+               }
+       }
+}
+
+GPUBuffer *GPU_buffer_vertex( DerivedMesh *dm )
+{
+       DEBUG_VBO("GPU_buffer_vertex\n");
+
+       return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*3*dm->drawObject->nelements, 0, GPU_buffer_copy_vertex);
+}
+
+void GPU_buffer_copy_normal( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
+{
+       int i;
+       int start;
+       float norm[3];
+
+       MVert *mvert;
+       MFace *mface;
+
+       DEBUG_VBO("GPU_buffer_copy_normal\n");
+
+       mvert = dm->getVertArray(dm);
+       mface = dm->getFaceArray(dm);
+
+       for( i=0; i < dm->getNumFaces(dm); i++ ) {
+               start = index[redir[mface[i].mat_nr+127]];
+               if( mface[i].v4 )
+                       index[redir[mface[i].mat_nr+127]] += 18;
+               else
+                       index[redir[mface[i].mat_nr+127]] += 9;
+
+               /* v1 v2 v3 */
+               if( mface->flag & ME_SMOOTH ) {
+                       VECCOPY(&varray[start],mvert[mface[i].v1].no);
+                       VECCOPY(&varray[start+3],mvert[mface[i].v2].no);
+                       VECCOPY(&varray[start+6],mvert[mface[i].v3].no);
+               }
+               else {
+                       if( mface[i].v4 )
+                               CalcNormFloat4(mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co, mvert[mface[i].v4].co, norm);
+                       else
+                               CalcNormFloat(mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co, norm);
+                       VECCOPY(&varray[start],norm);
+                       VECCOPY(&varray[start+3],norm);
+                       VECCOPY(&varray[start+6],norm);
+               }
+
+               if( mface[i].v4 ) {
+                       /* v3 v4 v1 */
+                       if( mface->flag & ME_SMOOTH ) {
+                               VECCOPY(&varray[start+9],mvert[mface[i].v3].no);
+                               VECCOPY(&varray[start+12],mvert[mface[i].v4].no);
+                               VECCOPY(&varray[start+15],mvert[mface[i].v1].no);
+                       }
+                       else {
+                               VECCOPY(&varray[start+9],norm);
+                               VECCOPY(&varray[start+12],norm);
+                               VECCOPY(&varray[start+15],norm);
+                       }
+               }
+       }
+}
+
+GPUBuffer *GPU_buffer_normal( DerivedMesh *dm )
+{
+       DEBUG_VBO("GPU_buffer_normal\n");
+
+       return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*3*dm->drawObject->nelements, 0, GPU_buffer_copy_normal);
+}
+
+void GPU_buffer_copy_uv( DerivedMesh *dm, float *varray, int *index, int *redir, void *user )
+{
+       int start;
+       int i;
+
+       MTFace *mtface;
+       MFace *mface;
+
+       DEBUG_VBO("GPU_buffer_copy_uv\n");
+
+       mface = dm->getFaceArray(dm);
+       mtface = DM_get_face_data_layer(dm, CD_MTFACE);
+
+       if( mtface == 0 ) {
+               DEBUG_VBO("Texture coordinates do not exist for this mesh");
+               return;
+       }
+               
+       for( i=0; i < dm->getNumFaces(dm); i++ ) {
+               start = index[redir[mface[i].mat_nr+127]];
+               if( mface[i].v4 )
+                       index[redir[mface[i].mat_nr+127]] += 12;
+               else
+                       index[redir[mface[i].mat_nr+127]] += 6;
+
+               /* v1 v2 v3 */
+               VECCOPY2D(&varray[start],mtface[i].uv[0]);
+               VECCOPY2D(&varray[start+2],mtface[i].uv[1]);
+               VECCOPY2D(&varray[start+4],mtface[i].uv[2]);
+
+               if( mface[i].v4 ) {
+                       /* v3 v4 v1 */
+                       VECCOPY2D(&varray[start+6],mtface[i].uv[2]);
+                       VECCOPY2D(&varray[start+8],mtface[i].uv[3]);
+                       VECCOPY2D(&varray[start+10],mtface[i].uv[0]);
+               }
+       }
+}
+
+GPUBuffer *GPU_buffer_uv( DerivedMesh *dm )
+{
+       DEBUG_VBO("GPU_buffer_uv\n");
+       if( DM_get_face_data_layer(dm, CD_MTFACE) != 0 )
+               return GPU_buffer_setup( dm, dm->drawObject, sizeof(float)*2*dm->drawObject->nelements, 0, GPU_buffer_copy_uv);
+       else
+               return 0;
+}
+
+void GPU_buffer_copy_color3( DerivedMesh *dm, float *varray_, int *index, int *redir, void *user )
+{
+       int i;
+       unsigned char *varray = varray_;
+       unsigned char *mcol = user;
+       MFace *mface = dm->getFaceArray(dm);
+
+       DEBUG_VBO("GPU_buffer_copy_color3\n");
+
+       for( i=0; i < dm->getNumFaces(dm); i++ ) {
+               int start = index[redir[mface[i].mat_nr+127]];
+               if( mface[i].v4 )
+                       index[redir[mface[i].mat_nr+127]] += 18;
+               else
+                       index[redir[mface[i].mat_nr+127]] += 9;
+
+               /* v1 v2 v3 */
+               VECCOPY(&varray[start],&mcol[i*12]);
+               VECCOPY(&varray[start+3],&mcol[i*12+3]);
+               VECCOPY(&varray[start+6],&mcol[i*12+6]);
+               if( mface[i].v4 ) {
+                       /* v3 v4 v1 */
+                       VECCOPY(&varray[start+9],&mcol[i*12+6]);
+                       VECCOPY(&varray[start+12],&mcol[i*12+9]);
+                       VECCOPY(&varray[start+15],&mcol[i*12]);
+               }
+       }
+}
+
+void GPU_buffer_copy_color4( DerivedMesh *dm, float *varray_, int *index, int *redir, void *user )
+{
+       int i;
+       unsigned char *varray = varray_;
+       unsigned char *mcol = user;
+       MFace *mface = dm->getFaceArray(dm);
+
+       DEBUG_VBO("GPU_buffer_copy_color4\n");
+
+       for( i=0; i < dm->getNumFaces(dm); i++ ) {
+               int start = index[redir[mface[i].mat_nr+127]];
+               if( mface[i].v4 )
+                       index[redir[mface[i].mat_nr+127]] += 18;
+               else
+                       index[redir[mface[i].mat_nr+127]] += 9;
+
+               /* v1 v2 v3 */
+               VECCOPY(&varray[start],&mcol[i*16]);
+               VECCOPY(&varray[start+3],&mcol[i*16+4]);
+               VECCOPY(&varray[start+6],&mcol[i*16+8]);
+               if( mface[i].v4 ) {
+                       /* v3 v4 v1 */
+                       VECCOPY(&varray[start+9],&mcol[i*16+8]);
+                       VECCOPY(&varray[start+12],&mcol[i*16+12]);
+                       VECCOPY(&varray[start+15],&mcol[i*16]);
+               }
+       }
+}
+
+GPUBuffer *GPU_buffer_color( DerivedMesh *dm )
+{
+       unsigned char *colors;
+       int i;
+       MCol *mcol;
+       GPUBuffer *result;
+       DEBUG_VBO("GPU_buffer_color\n");
+
+       mcol = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
+       dm->drawObject->colType = CD_WEIGHT_MCOL;
+       if(!mcol) {
+               mcol = DM_get_face_data_layer(dm, CD_MCOL);
+               dm->drawObject->colType = CD_MCOL;
+       }
+
+       colors = MEM_mallocN(dm->getNumFaces(dm)*12*sizeof(unsigned char), "GPU_buffer_color");
+       for( i=0; i < dm->getNumFaces(dm)*4; i++ ) {
+               colors[i*3] = mcol[i].b;
+               colors[i*3+1] = mcol[i].g;
+               colors[i*3+2] = mcol[i].r;
+       }
+
+       result = GPU_buffer_setup( dm, dm->drawObject, sizeof(char)*3*dm->drawObject->nelements, colors, GPU_buffer_copy_color3 );
+
+       MEM_freeN(colors);
+       return result;
+}
+
+void GPU_vertex_setup( DerivedMesh *dm )
+{
+       DEBUG_VBO("GPU_buffer_vertex_setup\n");
+       if( dm->drawObject == 0 )
+               dm->drawObject = GPU_drawobject_new( dm );
+       if( dm->drawObject->vertices == 0 )
+               dm->drawObject->vertices = GPU_buffer_vertex( dm );
+       if( dm->drawObject->vertices == 0 ) {
+               DEBUG_VBO( "Failed to setup vertices\n" );
+               return;
+       }
+
+       glEnableClientState( GL_VERTEX_ARRAY );
+       if( useVBOs ) {
+               glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->vertices->id );
+               glVertexPointer( 3, GL_FLOAT, 0, 0 );
+       }
+       else {
+               glVertexPointer( 3, GL_FLOAT, 0, dm->drawObject->vertices->pointer );
+       }
+       
+       GLStates |= GPU_BUFFER_VERTEX_STATE;
+}
+
+void GPU_normal_setup( DerivedMesh *dm )
+{
+       DEBUG_VBO("GPU_buffer_normal_setup\n");
+       if( dm->drawObject == 0 )
+               dm->drawObject = GPU_drawobject_new( dm );
+       if( dm->drawObject->normals == 0 )
+               dm->drawObject->normals = GPU_buffer_normal( dm );
+       if( dm->drawObject->normals == 0 ) {
+               DEBUG_VBO( "Failed to setup normals\n" );
+               return;
+       }
+       glEnableClientState( GL_NORMAL_ARRAY );
+       if( useVBOs ) {
+               glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id );
+               glNormalPointer( GL_FLOAT, 0, 0 );
+       }
+       else {
+               glNormalPointer( GL_FLOAT, 0, dm->drawObject->normals->pointer );
+       }
+
+       GLStates |= GPU_BUFFER_NORMAL_STATE;
+}
+
+void GPU_uv_setup( DerivedMesh *dm )
+{
+       DEBUG_VBO("GPU_buffer_uv_setup\n");
+       if( dm->drawObject == 0 )
+               dm->drawObject = GPU_drawobject_new( dm );
+       if( dm->drawObject->uv == 0 )
+               dm->drawObject->uv = GPU_buffer_uv( dm );
+       
+       if( dm->drawObject->uv != 0 ) {
+               glEnableClientState( GL_TEXTURE_COORD_ARRAY );
+               if( useVBOs ) {
+                       glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id );
+                       glTexCoordPointer( 2, GL_FLOAT, 0, 0 );
+               }
+               else {
+                       glTexCoordPointer( 2, GL_FLOAT, 0, dm->drawObject->uv->pointer );
+               }
+
+               GLStates |= GPU_BUFFER_TEXCOORD_STATE;
+       }
+}
+
+void GPU_color_setup( DerivedMesh *dm )
+{
+       DEBUG_VBO("GPU_buffer_color_setup\n");
+       if( dm->drawObject == 0 )
+               dm->drawObject = GPU_drawobject_new( dm );
+       if( dm->drawObject->colors == 0 )
+               dm->drawObject->colors = GPU_buffer_color( dm );
+       if( dm->drawObject->colors == 0 ) {
+               DEBUG_VBO( "Failed to setup colors\n" );
+               return;
+       }
+       glEnableClientState( GL_COLOR_ARRAY );
+       if( useVBOs ) {
+               glBindBufferARB( GL_ARRAY_BUFFER_ARB, dm->drawObject->colors->id );
+               glColorPointer( 3, GL_UNSIGNED_BYTE, 0, 0 );
+       }
+       else {
+               glColorPointer( 3, GL_UNSIGNED_BYTE, 0, dm->drawObject->colors->pointer );
+       }
+
+       GLStates |= GPU_BUFFER_COLOR_STATE;
+}
+
+void GPU_buffer_unbind()
+{
+       DEBUG_VBO("GPU_buffer_unbind\n");
+
+       if( GLStates & GPU_BUFFER_VERTEX_STATE )
+               glDisableClientState( GL_VERTEX_ARRAY );
+       if( GLStates & GPU_BUFFER_NORMAL_STATE )
+               glDisableClientState( GL_NORMAL_ARRAY );
+       if( GLStates & GPU_BUFFER_TEXCOORD_STATE )
+               glDisableClientState( GL_TEXTURE_COORD_ARRAY );
+       if( GLStates & GPU_BUFFER_COLOR_STATE )
+               glDisableClientState( GL_COLOR_ARRAY );
+       GLStates &= !(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE | GPU_BUFFER_TEXCOORD_STATE | GPU_BUFFER_COLOR_STATE );
+
+       if( useVBOs )
+               glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
+}
+
+void GPU_color3_upload( DerivedMesh *dm, char *data )
+{
+       if( dm->drawObject == 0 )
+               dm->drawObject = GPU_drawobject_new(dm);
+       GPU_buffer_free(dm->drawObject->colors,globalPool);
+       dm->drawObject->colors = GPU_buffer_setup( dm, dm->drawObject, sizeof(char)*3*dm->drawObject->nelements, data, GPU_buffer_copy_color3 );
+}
+void GPU_color4_upload( DerivedMesh *dm, char *data )
+{
+       if( dm->drawObject == 0 )
+               dm->drawObject = GPU_drawobject_new(dm);
+       GPU_buffer_free(dm->drawObject->colors,globalPool);
+       dm->drawObject->colors = GPU_buffer_setup( dm, dm->drawObject, sizeof(char)*3*dm->drawObject->nelements, data, GPU_buffer_copy_color4 );
+}
+
+void GPU_color_switch( int mode )
+{
+       if( mode ) {
+               if( !GLStates & GPU_BUFFER_COLOR_STATE )
+                       glEnableClientState( GL_COLOR_ARRAY );
+               GLStates |= GPU_BUFFER_COLOR_STATE;
+       }
+       else {
+               if( GLStates & GPU_BUFFER_COLOR_STATE )
+                       glDisableClientState( GL_COLOR_ARRAY );
+               GLStates &= (!GPU_BUFFER_COLOR_STATE);
+       }
+}
+
+int GPU_buffer_legacy( DerivedMesh *dm )
+{
+       if( dm->drawObject == 0 )
+               dm->drawObject = GPU_drawobject_new(dm);
+       return dm->drawObject->legacy;
+}
\ No newline at end of file