svn merge -r 16351:16368 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Thu, 4 Sep 2008 23:33:19 +0000 (23:33 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Thu, 4 Sep 2008 23:33:19 +0000 (23:33 +0000)
267 files changed:
blenderplayer/CMakeLists.txt
config/darwin-config.py
extern/glew/SConscript
extern/glew/include/GL/glew.h
extern/glew/src/glew.c
intern/guardedalloc/MEM_guardedalloc.h
intern/guardedalloc/intern/mallocn.c
intern/memutil/MEM_Allocator.h
intern/memutil/MEM_CacheLimiter.h
intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
intern/moto/include/GEN_Map.h
intern/moto/include/MT_Matrix4x4.h
intern/moto/include/MT_Matrix4x4.inl
release/scripts/sysinfo.py
source/Makefile
source/blender/CMakeLists.txt
source/blender/Makefile
source/blender/SConscript
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_bad_level_calls.h
source/blender/blenkernel/BKE_colortools.h
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_texture.h
source/blender/blenkernel/BKE_utildefines.h
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/SConscript
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/Makefile
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/colortools.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenkernel/intern/texture.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/BLI_blenlib.h
source/blender/blenlib/intern/arithb.c
source/blender/blenloader/intern/readfile.c
source/blender/gpu/CMakeLists.txt [new file with mode: 0644]
source/blender/gpu/GPU_draw.h [new file with mode: 0644]
source/blender/gpu/GPU_extensions.h [new file with mode: 0644]
source/blender/gpu/GPU_material.h [new file with mode: 0644]
source/blender/gpu/Makefile [new file with mode: 0644]
source/blender/gpu/SConscript [new file with mode: 0644]
source/blender/gpu/intern/Makefile [new file with mode: 0644]
source/blender/gpu/intern/gpu_codegen.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_codegen.h [new file with mode: 0644]
source/blender/gpu/intern/gpu_draw.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_extensions.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_material.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_shader_material.glsl [new file with mode: 0644]
source/blender/gpu/intern/gpu_shader_material.glsl.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_shader_vertex.glsl [new file with mode: 0644]
source/blender/gpu/intern/gpu_shader_vertex.glsl.c [new file with mode: 0644]
source/blender/include/BDR_drawmesh.h
source/blender/include/BDR_drawobject.h
source/blender/include/BDR_imagepaint.h
source/blender/include/BIF_drawtext.h
source/blender/include/BIF_gl.h
source/blender/include/BIF_meshtools.h
source/blender/include/BSE_drawview.h
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesdna/DNA_brush_types.h
source/blender/makesdna/DNA_group_types.h
source/blender/makesdna/DNA_image_types.h
source/blender/makesdna/DNA_ipo_types.h
source/blender/makesdna/DNA_lamp_types.h
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sensor_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/DNA_world_types.h
source/blender/nodes/CMakeLists.txt
source/blender/nodes/SConscript
source/blender/nodes/intern/CMP_nodes/Makefile
source/blender/nodes/intern/Makefile
source/blender/nodes/intern/SHD_nodes/Makefile
source/blender/nodes/intern/SHD_nodes/SHD_camera.c
source/blender/nodes/intern/SHD_nodes/SHD_curves.c
source/blender/nodes/intern/SHD_nodes/SHD_geom.c
source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c
source/blender/nodes/intern/SHD_nodes/SHD_invert.c
source/blender/nodes/intern/SHD_nodes/SHD_mapping.c
source/blender/nodes/intern/SHD_nodes/SHD_material.c
source/blender/nodes/intern/SHD_nodes/SHD_math.c
source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c
source/blender/nodes/intern/SHD_nodes/SHD_normal.c
source/blender/nodes/intern/SHD_nodes/SHD_output.c
source/blender/nodes/intern/SHD_nodes/SHD_rgb.c
source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c
source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c
source/blender/nodes/intern/SHD_nodes/SHD_texture.c
source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c
source/blender/nodes/intern/SHD_nodes/SHD_value.c
source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c
source/blender/nodes/intern/SHD_util.h
source/blender/python/BPY_interface.c
source/blender/python/CMakeLists.txt
source/blender/python/SConscript
source/blender/python/api2_2x/Blender.c
source/blender/python/api2_2x/Group.c
source/blender/python/api2_2x/Image.c
source/blender/python/api2_2x/Lamp.c
source/blender/python/api2_2x/MTex.c
source/blender/python/api2_2x/Makefile
source/blender/python/api2_2x/Material.c
source/blender/python/api2_2x/doc/Group.py
source/blender/radiosity/CMakeLists.txt
source/blender/radiosity/SConscript
source/blender/radiosity/intern/source/Makefile
source/blender/render/intern/include/render_types.h
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/shadbuf.c
source/blender/render/intern/source/shadeoutput.c
source/blender/render/intern/source/zbuf.c
source/blender/src/CMakeLists.txt
source/blender/src/Makefile
source/blender/src/SConscript
source/blender/src/buttons_logic.c
source/blender/src/buttons_object.c
source/blender/src/buttons_shading.c
source/blender/src/drawarmature.c
source/blender/src/drawmesh.c
source/blender/src/drawobject.c
source/blender/src/drawtext.c
source/blender/src/drawview.c
source/blender/src/editdeform.c
source/blender/src/editface.c
source/blender/src/editipo_lib.c
source/blender/src/editlattice.c
source/blender/src/editmode_undo.c
source/blender/src/editview.c
source/blender/src/header_image.c
source/blender/src/header_info.c
source/blender/src/header_view3d.c
source/blender/src/headerbuttons.c
source/blender/src/imagepaint.c
source/blender/src/meshtools.c
source/blender/src/playanim.c
source/blender/src/previewrender.c
source/blender/src/renderwin.c
source/blender/src/sculptmode.c
source/blender/src/sequence.c
source/blender/src/space.c
source/blender/src/toets.c
source/blender/src/usiblender.c
source/blender/src/verse_image.c
source/blender/yafray/intern/export_File.cpp
source/blender/yafray/intern/export_Plugin.cpp
source/creator/CMakeLists.txt
source/creator/Makefile
source/creator/SConscript
source/creator/creator.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/BlenderRoutines/CMakeLists.txt
source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
source/gameengine/BlenderRoutines/KX_BlenderGL.h
source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
source/gameengine/BlenderRoutines/Makefile
source/gameengine/BlenderRoutines/SConscript
source/gameengine/Converter/BL_ArmatureObject.cpp
source/gameengine/Converter/BL_ArmatureObject.h
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/BL_DeformableGameObject.cpp
source/gameengine/Converter/BL_MeshDeformer.cpp
source/gameengine/Converter/BL_MeshDeformer.h
source/gameengine/Converter/BL_ShapeActionActuator.cpp
source/gameengine/Converter/BL_ShapeDeformer.cpp
source/gameengine/Converter/BL_ShapeDeformer.h
source/gameengine/Converter/BL_SkinDeformer.cpp
source/gameengine/Converter/BL_SkinDeformer.h
source/gameengine/Converter/BL_SkinMeshObject.cpp
source/gameengine/Converter/BL_SkinMeshObject.h
source/gameengine/Converter/CMakeLists.txt
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/Converter/KX_BlenderSceneConverter.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Converter/Makefile
source/gameengine/Converter/SConscript
source/gameengine/GamePlayer/common/CMakeLists.txt
source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
source/gameengine/GamePlayer/common/GPC_RenderTools.h
source/gameengine/GamePlayer/common/Makefile
source/gameengine/GamePlayer/common/SConscript
source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h
source/gameengine/GamePlayer/ghost/CMakeLists.txt
source/gameengine/GamePlayer/ghost/GPG_Application.cpp
source/gameengine/GamePlayer/ghost/GPG_Application.h
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
source/gameengine/GamePlayer/ghost/Makefile
source/gameengine/GamePlayer/ghost/SConscript
source/gameengine/Ketsji/BL_BlenderShader.cpp
source/gameengine/Ketsji/BL_BlenderShader.h
source/gameengine/Ketsji/BL_Material.h
source/gameengine/Ketsji/BL_Shader.cpp
source/gameengine/Ketsji/BL_Shader.h
source/gameengine/Ketsji/CMakeLists.txt
source/gameengine/Ketsji/KX_BlenderMaterial.cpp
source/gameengine/Ketsji/KX_BlenderMaterial.h
source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_ISceneConverter.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_KetsjiEngine.h
source/gameengine/Ketsji/KX_Light.cpp
source/gameengine/Ketsji/KX_Light.h
source/gameengine/Ketsji/KX_MeshProxy.cpp
source/gameengine/Ketsji/KX_PolyProxy.cpp
source/gameengine/Ketsji/KX_PolygonMaterial.cpp
source/gameengine/Ketsji/KX_PolygonMaterial.h
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_PythonInit.h
source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_Scene.h
source/gameengine/Ketsji/KX_VertexProxy.cpp
source/gameengine/Ketsji/KX_VisibilityActuator.cpp
source/gameengine/Ketsji/Makefile
source/gameengine/Ketsji/SConscript
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/PyDoc/GameLogic.py
source/gameengine/PyDoc/Rasterizer.py
source/gameengine/Rasterizer/Makefile
source/gameengine/Rasterizer/RAS_BucketManager.cpp
source/gameengine/Rasterizer/RAS_BucketManager.h
source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
source/gameengine/Rasterizer/RAS_IRasterizer.h
source/gameengine/Rasterizer/RAS_IRenderTools.cpp
source/gameengine/Rasterizer/RAS_IRenderTools.h
source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
source/gameengine/Rasterizer/RAS_MaterialBucket.h
source/gameengine/Rasterizer/RAS_MeshObject.cpp
source/gameengine/Rasterizer/RAS_MeshObject.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
source/gameengine/Rasterizer/RAS_Polygon.cpp
source/gameengine/Rasterizer/RAS_Polygon.h
source/gameengine/Rasterizer/RAS_TexVert.cpp
source/gameengine/Rasterizer/RAS_TexVert.h
source/gameengine/Rasterizer/SConscript
source/kernel/gen_system/GEN_Map.h
source/nan_definitions.mk
tools/btools.py

index d90639562d22ca21210f19c1b07360929cf2c63d..e32390466c757eaeeb2575c819cc1597f36f421c 100644 (file)
@@ -90,6 +90,7 @@ IF(UNIX)
     bf_soundsystem 
     bf_kernel 
     bf_nodes
+       bf_gpu
     bf_imbuf
     bf_avi 
     kx_network 
index 8fd6c3251ba64b46be82667cea44b90c0ac87f93..48455d2ce8cc739459da428a3a4747cad459885c 100644 (file)
@@ -143,7 +143,6 @@ BF_FTGL_LIB = 'extern_ftgl'
 
 WITH_BF_GAMEENGINE='true'
 WITH_BF_PLAYER='true'
-WITH_BF_GLEXT= '1'
 
 WITH_BF_ODE = 'false'
 BF_ODE = LIBDIR + '/ode'
index 32b3b478113f22cf2e3eb8ef59e28cd39ed4e199..3badbeb040ef080559903506c4d9279d3ea3a77e 100644 (file)
@@ -9,4 +9,4 @@ sources = ['src/glew.c']
 defs = ''
 incs = 'include'
 
-env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['intern', 'player'], priority=[25, 50])
+env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['blender', 'player'], priority=[50, 50])
index fd3fe10b93822efc3b322ad58bd8a6ba1bfcb32d..6b88e6eb4c91b69d0c06efad6d865f4ea89cfa46 100644 (file)
 ** version 1.2.1 Specification.
 */
 
-/* added this here for blender, should be moved elsewhere */
+#define BLENDER_CHANGES
+
+#ifdef BLENDER_CHANGES
 #define GLEW_STATIC
+#endif
 
 #ifndef __glew_h__
 #define __glew_h__
@@ -1805,6 +1808,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuin
 typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v);
 typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
 
+#ifndef BLENDER_CHANGES
 #define glAttachShader GLEW_GET_FUN(__glewAttachShader)
 #define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation)
 #define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate)
@@ -1898,6 +1902,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint si
 #define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv)
 #define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv)
 #define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer)
+#endif
 
 #define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0)
 
index 593f0e58f7c32c0b880d80804da5319171fa0d09..f20463630dc13d312f9a45f322ba189036bc4128 100644 (file)
@@ -1836,6 +1836,7 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT)
 {
   GLboolean r = GL_FALSE;
 
+#ifndef BLENDER_CHANGES
   r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r;
   r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r;
   r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r;
@@ -1929,6 +1930,7 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT)
   r = ((glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uiv")) == NULL) || r;
   r = ((glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usv")) == NULL) || r;
   r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r;
+#endif
 
   return r;
 }
index d004e7952cc1f427ebe888f26a96732fb9b38b50..1d4c753802b7f3612579a58f774d3ddee54e8513 100644 (file)
@@ -58,8 +58,8 @@
 #ifndef MEM_MALLOCN_H
 #define MEM_MALLOCN_H
 
-/* Needed for FILE* */
-#include "stdio.h"
+#include "stdio.h" /* needed for FILE* */
+#include "BLO_sys_types.h" /* needed for uintptr_t */
 
 #ifdef __cplusplus
 extern "C" {
@@ -123,6 +123,12 @@ extern "C" {
        /** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */
        void MEM_set_memory_debug(void);
 
+       /* Memory usage stats
+        * - MEM_get_memory_in_use is all memory
+        * - MEM_get_mapped_memory_in_use is a subset of all memory */
+       uintptr_t MEM_get_memory_in_use(void);
+       uintptr_t MEM_get_mapped_memory_in_use(void);
+       int MEM_get_memory_blocks_in_use(void);
 
 #ifdef __cplusplus
 }
index a36549d0cc75eb779c61f025d4e78d46f7a89ee2..7bdca7339fcce39879c4adb7491e8e8d2b388dcf 100644 (file)
@@ -49,8 +49,6 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "BLO_sys_types.h" // needed for intptr_t
-
 /* --------------------------------------------------------------------- */
 /* Data definition                                                       */
 /* --------------------------------------------------------------------- */
@@ -113,8 +111,8 @@ static const char *check_memlist(MemHead *memh);
 /* --------------------------------------------------------------------- */
        
 
-volatile int totblock= 0;
-volatile uintptr_t mem_in_use= 0, mmap_in_use= 0;
+static volatile int totblock= 0;
+static volatile uintptr_t mem_in_use= 0, mmap_in_use= 0;
 
 static volatile struct localListBase _membase;
 static volatile struct localListBase *membase = &_membase;
@@ -698,4 +696,19 @@ static const char *check_memlist(MemHead *memh)
        return(name);
 }
 
+uintptr_t MEM_get_memory_in_use(void)
+{
+       return mem_in_use;
+}
+
+uintptr_t MEM_get_mapped_memory_in_use(void)
+{
+       return mmap_in_use;
+}
+
+int MEM_get_memory_blocks_in_use(void)
+{
+       return totblock;
+}
+
 /* eof */
index d5ae94cc6b868727e062f38c392080ca5b3e6453..b2c3c5e82e25544a0f71cd96e1b3dcbe68650b8f 100644 (file)
@@ -25,6 +25,7 @@
 #define __MEM_Allocator_h_included__ 1
 
 #include "guardedalloc/MEM_guardedalloc.h"
+#include "guardedalloc/BLO_sys_types.h"
 
 #ifdef _MSC_VER
 #if _MSC_VER < 1300 // 1200 == VC++ 6.0 according to boost
index cada06ae523f9c673d11610292d2d5c6662fa0ec..43149efc977b3652d5e62e2572cc68460ba5cd80 100644 (file)
@@ -61,11 +61,8 @@ class MEM_CacheLimiter;
 
 #ifndef __MEM_cache_limiter_c_api_h_included__
 extern "C" {
-       extern void MEM_CacheLimiter_set_maximum(int m);
-       extern int MEM_CacheLimiter_get_maximum();
-        // this is rather _ugly_!
-        extern int mem_in_use;
-       extern int mmap_in_use;
+       extern void MEM_CacheLimiter_set_maximum(intptr_t m);
+       extern intptr_t MEM_CacheLimiter_get_maximum();
 };
 #endif
 
@@ -141,7 +138,10 @@ public:
                delete handle;
        }
        void enforce_limits() {
-               int max = MEM_CacheLimiter_get_maximum();
+               intptr_t max = MEM_CacheLimiter_get_maximum();
+               intptr_t mem_in_use= MEM_get_memory_in_use();
+               intptr_t mmap_in_use= MEM_get_mapped_memory_in_use();
+
                if (max == 0) {
                        return;
                }
index 4cf0ef305d415a0353391a747ce368d4f36d5639..d998c9a3e80db05787c367a2d7811694ac80dd39 100644 (file)
 #include "MEM_CacheLimiter.h"
 #include "MEM_CacheLimiterC-Api.h"
 
-static int & get_max() 
+static intptr_t & get_max() 
 {
-       static int m = 32*1024*1024;
+       static intptr_t m = 32*1024*1024;
        return m;
 }
 
-void MEM_CacheLimiter_set_maximum(int m)
+void MEM_CacheLimiter_set_maximum(intptr_t m)
 {
        get_max() = m;
 }
 
-int MEM_CacheLimiter_get_maximum()
+intptr_t MEM_CacheLimiter_get_maximum()
 {
        return get_max();
 }
index 9f56924419ea32be776a65f4345e26d01a140841..d85e9af175b42f5eec446ec868dc84b1530885b6 100644 (file)
@@ -50,6 +50,19 @@ public:
             m_buckets[i] = 0;
         }
     }
+
+       GEN_Map(const GEN_Map& map)
+       {
+               m_num_buckets = map.m_num_buckets;
+               m_buckets = new Entry *[m_num_buckets];
+
+               for (int i = 0; i < m_num_buckets; ++i) {
+                       m_buckets[i] = 0;
+
+                       for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next)
+                               insert(entry->m_key, entry->m_value);
+               }
+       }
     
     int size() { 
         int count=0;
index 823541347b747f57123b5ed8b1f7240bdc7cc1d8..b4ee84a718b5a081a2cfc30ddafd6da93243f982 100644 (file)
@@ -212,6 +212,7 @@ public:
        MT_Matrix4x4 transposed() const; 
        void         transpose();
 
+       MT_Matrix4x4 inverse() const;
        void         invert();
   
 protected:
index a2aa893a6b3045f11bc89a746e55c5b1292d9cd5..074bd6e4b05e66d981c480c85fa192c47bb7009e 100644 (file)
@@ -52,14 +52,14 @@ GEN_INLINE void MT_Matrix4x4::invert()  {
                }
 }
 
-/* We do things slightly different here, because the invert() modifies
- * the buffer itself. This makes it impossible to make this op right
- * away. Like other, still missing facilities, I will repair this
- * later. */
-/* GEN_INLINE T_Matrix4x4 MT_Matrix4x4::inverse() const */
-/*  { */
-/*  } */
+GEN_INLINE MT_Matrix4x4 MT_Matrix4x4::inverse() const
+{
+       MT_Matrix4x4 invmat = *this;
+
+       invmat.invert();
 
+       return invmat;
+}
 
 GEN_INLINE MT_Matrix4x4& MT_Matrix4x4::operator*=(const MT_Matrix4x4& m)
 {
index 9f24885829c76c4107b1340fe6526f0d8faca6bc..3a671e7221e49cb58d1b5c469be1794b3e3ef335 100644 (file)
@@ -94,6 +94,8 @@ output = Blender.Text.New(output_filename)
 
 output.write(header + "\n\n")
 
+output.write("%s\n\n" % Blender.Get('buildinfo'))
+
 output.write("Platform: %s\n========\n\n" % sys.platform)
 
 output.write("Python:\n======\n\n")
index 91dd17d73dd49d211789e65b8e62dc6b26fe674e..aebeb8f30c2dd47e677bbc14b6508c498e5bbc8b 100644 (file)
@@ -104,6 +104,8 @@ COMLIB += $(NAN_OPENNL)/lib/$(DEBUG_DIR)libopennl.a
 COMLIB += $(NAN_SUPERLU)/lib/$(DEBUG_DIR)libsuperlu.a  
 COMLIB += $(OCGDIR)/blender/avi/$(DEBUG_DIR)libavi.a
 COMLIB += $(NAN_JPEG)/lib/libjpeg.a
+COMLIB += $(OCGDIR)/blender/gpu/$(DEBUG_DIR)libgpu.a
+COMLIB += $(NAN_GLEW)/lib/libglew.a
 
 ifneq ($(NAN_NO_KETSJI),true)
     COMLIB += $(OCGDIR)/gameengine/bloutines/$(DEBUG_DIR)libbloutines.a
@@ -157,7 +159,6 @@ COMLIB += $(NAN_BMFONT)/lib/$(DEBUG_DIR)libbmfont.a
 COMLIB += $(NAN_PNG)/lib/libpng.a
 COMLIB += $(OCGDIR)/blender/yafray/$(DEBUG_DIR)libyafrayexport.a
 COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
-COMLIB += $(NAN_GLEW)/lib/libglew.a
 
 ifeq ($(WITH_QUICKTIME), true)
     COMLIB += $(OCGDIR)/blender/blenderqt/$(DEBUG_DIR)libblenderqt.a
index 966bf5f7be4231b80eecb63d831a93aa3a50be58..a21eadf15fa830432af8bc39c74aa00a7dafb849 100644 (file)
@@ -24,7 +24,7 @@
 #
 # ***** END GPL LICENSE BLOCK *****
 
-SUBDIRS(avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon makesdna python radiosity readblenfile render src yafray)
+SUBDIRS(avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon gpu makesdna python radiosity readblenfile render src yafray)
 
 IF(WITH_INTERNATIONAL)
   SUBDIRS(ftfont)
index 937512f34bd65a3d423262d186e2799ad9928c27..52abd2cdddb60ee06ee013dbd1e63f91c8370a6f 100644 (file)
@@ -33,7 +33,7 @@ include nan_definitions.mk
 DIRS = blenloader readblenfile
 DIRS += avi imbuf render radiosity blenlib blenkernel blenpluginapi
 DIRS += makesdna src yafray
-DIRS += python nodes
+DIRS += python nodes gpu
 
 ifeq ($(WITH_FREETYPE2), true)
        DIRS += ftfont
index 56a661238f810756e48650907e36b7ed2dd5f953..25745c0e51a2c399449aef4929c030badeab47d2 100644 (file)
@@ -7,6 +7,7 @@ SConscript(['avi/SConscript',
             'blenlib/SConscript',
             'blenloader/SConscript',
             'blenpluginapi/SConscript',
+            'gpu/SConscript',
             'imbuf/SConscript',
             'imbuf/intern/cineon/SConscript',
             'makesdna/SConscript',
index 7dc10c53e22909e1a3548259879112b2de818a03..171a73f72c45fa3d2fc4625e7924659f30e392d4 100644 (file)
@@ -55,6 +55,7 @@ struct EditMesh;
 struct ModifierData;
 struct MCol;
 struct ColorBand;
+struct GPUVertexAttribs;
 
 /* number of sub-elements each mesh element has (for interpolation) */
 #define SUB_ELEMS_VERT 0
@@ -198,7 +199,8 @@ struct DerivedMesh {
         *
         * Also called for *final* editmode DerivedMeshes
         */
-       void (*drawFacesSolid)(DerivedMesh *dm, int (*setMaterial)(int));
+       void (*drawFacesSolid)(DerivedMesh *dm,
+                              int (*setMaterial)(int, void *attribs));
 
        /* Draw all faces
         *  o If useTwoSided, draw front and back using col arrays
@@ -215,6 +217,13 @@ struct DerivedMesh {
                             int (*setDrawOptions)(struct MTFace *tface,
                             struct MCol *mcol, int matnr));
 
+       /* Draw all faces with GLSL materials
+        *  o setMaterial is called for every different material nr
+        *  o Only if setMaterial returns true
+        */
+       void (*drawFacesGLSL)(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs));
+
        /* Draw mapped faces (no color, or texture)
         *  o Only if !setDrawOptions or
         *    setDrawOptions(userData, mapped-face-index, drawSmooth_r)
@@ -241,6 +250,15 @@ struct DerivedMesh {
                                                         int index),
                                   void *userData);
 
+       /* Draw mapped faces with GLSL materials
+        *  o setMaterial is called for every different material nr
+        *  o setDrawOptions is called for every face
+        *  o Only if setMaterial and setDrawOptions return true
+        */
+       void (*drawMappedFacesGLSL)(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs),
+               int (*setDrawOptions)(void *userData, int index), void *userData);
+
        /* Draw mapped edges as lines
         *  o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge)
         *    returns true
@@ -437,6 +455,35 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb);
 /* determines required DerivedMesh data according to view and edit modes */
 CustomDataMask get_viewedit_datamask();
 
+/* convert layers requested by a GLSL material to actually available layers in
+ * the DerivedMesh, with both a pointer for arrays and an offset for editmesh */
+typedef struct DMVertexAttribs {
+       struct {
+               struct MTFace *array;
+               int emOffset, glIndex;
+       } tface[MAX_MTFACE];
+
+       struct {
+               struct MCol *array;
+               int emOffset, glIndex;
+       } mcol[MAX_MCOL];
+
+       struct {
+               float (*array)[3];
+               int emOffset, glIndex;
+       } tang;
+
+       struct {
+               float (*array)[3];
+               int emOffset, glIndex;
+       } orco;
+
+       int tottface, totmcol, tottang, totorco;
+} DMVertexAttribs;
+
+void DM_vertex_attributes_from_gpu(DerivedMesh *dm,
+       struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
+
 void DM_add_tangent_layer(DerivedMesh *dm);
 
 #endif
index 3e45749c26abacb9f629d7100fc704888d48d4f1..8dee9a27f49cba1ea1ed4cabaa9b680efd4453d8 100644 (file)
@@ -115,10 +115,6 @@ void free_editArmature(void);
 void docenter_new(void);
 int saveover(char *str);
 
-/* image.c */
-#include "DNA_image_types.h"
-void free_realtime_image(Image *ima); // has to become a callback, opengl stuff
-
 /* ipo.c */
 void copy_view3d_lock(short val);      // was a hack, to make scene layer ipo's possible
 
index e78882220a9264ee4e0578ed9d9b63a1cfd28ae3..555b467b1d6ae44a91be12fd381803f117185461 100644 (file)
@@ -57,6 +57,7 @@ void                          curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf);
 void                           curvemapping_premultiply(struct CurveMapping *cumap, int restore);
 int                                    curvemapping_RGBA_does_something(struct CurveMapping *cumap);
 void                           curvemapping_initialize(struct CurveMapping *cumap);
+void                           curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size);
 
 #endif
 
index 8c9634cba06051e5df877e3be8ef539bc14497ec..1cc336db69e640be86dabada852f7bef973426ce 100644 (file)
@@ -218,8 +218,15 @@ typedef struct Global {
 #define G_FILE_NO_UI                    (1 << 10)
 #define G_FILE_GAME_TO_IPO              (1 << 11)
 #define G_FILE_GAME_MAT                         (1 << 12)
-#define G_FILE_DIAPLAY_LISTS    (1 << 13)
+#define G_FILE_DISPLAY_LISTS    (1 << 13)
 #define G_FILE_SHOW_PHYSICS             (1 << 14)
+#define G_FILE_GAME_MAT_GLSL    (1 << 15)
+#define G_FILE_GLSL_NO_LIGHTS   (1 << 16)
+#define G_FILE_GLSL_NO_SHADERS  (1 << 17)
+#define G_FILE_GLSL_NO_SHADOWS  (1 << 18)
+#define G_FILE_GLSL_NO_RAMPS    (1 << 19)
+#define G_FILE_GLSL_NO_NODES    (1 << 20)
+#define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21)
 
 /* G.windowstate */
 #define G_WINDOWSTATE_USERDEF          0
index d4ae76e89848066df2566dd6054f9f133717604b..2ca4b3aa39a3d9b1f07845d9e0303e33d2d99cb9 100644 (file)
@@ -68,7 +68,6 @@ void mball_to_mesh(struct ListBase *lb, struct Mesh *me);
 void nurbs_to_mesh(struct Object *ob);
 void free_dverts(struct MDeformVert *dvert, int totvert);
 void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */
-int update_realtime_texture(struct MTFace *tface, double time);
 void mesh_delete_material_index(struct Mesh *me, int index);
 void mesh_set_smooth_flag(struct Object *meshOb, int enableSmooth);
 
index b3b68a9b3ff21c5c9bb04be75433909578957ecb..01c54663c6d9e34b43a62eecd9d7a09ad40448b7 100644 (file)
@@ -47,6 +47,9 @@ struct rctf;
 struct ListBase;
 struct RenderData;
 struct Scene;
+struct GPUMaterial;
+struct GPUNode;
+struct GPUNodeStack;
 
 #define SOCK_IN                1
 #define SOCK_OUT       2
@@ -91,6 +94,9 @@ typedef struct bNodeType {
        void *pynode; /* holds pointer to python script */
        void *pydict; /* holds pointer to python script dictionary (scope)*/
 
+       /* gpu */
+       int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out);
+
 } bNodeType;
 
 /* node->exec, now in use for composites (#define for break is same as ready yes) */
@@ -252,6 +258,8 @@ void                        nodeShaderSynchronizeID(struct bNode *node, int copyto);
 extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
 void                   set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *));
 
+void                   ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
+
 
 /* ************** COMPOSITE NODES *************** */
 
index c162a04e0557a7859302a0d69ec7e16890049ab5..cfcae3c44bc5a17a8932737c9a28cd5bbb4e63db 100644 (file)
@@ -53,6 +53,7 @@ void free_plugin_tex(struct PluginTex *pit);
 void init_colorband(struct ColorBand *coba, int rangetype);
 struct ColorBand *add_colorband(int rangetype);
 int do_colorband(struct ColorBand *coba, float in, float out[4]);
+void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size);
 
 void default_tex(struct Tex *tex);
 struct Tex *add_texture(char *name);
index f389521ffa0f0a9501be694a1105dfb3469d1d4b..d647a74c6e282f7b943c2f8cd98e990387b9a8fc 100644 (file)
@@ -55,6 +55,8 @@
 #define ELEM7(a, b, c, d, e, f, g, h)   ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) )
 #define ELEM8(a, b, c, d, e, f, g, h, i)        ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) )
 #define ELEM9(a, b, c, d, e, f, g, h, i, j)        ( ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) )
+#define ELEM10(a, b, c, d, e, f, g, h, i, j, k)        ( ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) )
+#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l)        ( ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) )
 
 /* shift around elements */
 #define SHIFT3(type, a, b, c) { type tmp; tmp = a; a = c; c = b; b = tmp; }
index 9088b410e27abc6b7a3266757ba687725169fdf8..0345711c9c348ee474943443bd6e449759bc2882 100644 (file)
@@ -32,7 +32,7 @@ SET(INC
   ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern
   ../../../intern/iksolver/extern ../blenloader ../quicktime
   ../../../intern/bmfont ../../../extern/bullet2/src
-  ../nodes
+  ../nodes ../../../extern/glew/include ../gpu
   ${SDL_INC}
   ${ZLIB_INC}
   ${PYTHON_INC}
index 1bb98239a6868b3bd19773b0bd63342bfdf48fd7..db67251f44efa9073478c33da20ad4251048d6ab 100644 (file)
@@ -10,6 +10,7 @@ incs += ' #/intern/iksolver/extern ../blenloader ../quicktime'
 incs += ' #/extern/bullet2/src'
 incs += ' #/intern/bmfont'
 incs += ' #/intern/opennl/extern'
+incs += ' ../gpu #/extern/glew/include'
 
 incs += ' ' + env['BF_PYTHON_INC']
 incs += ' ' + env['BF_OPENGL_INC']
index 561d8d7c2a6bda1c843898f112ff3f971a776f71..4b6cb5e0999b1bd22ddd90789dbc317349e4bfac 100644 (file)
@@ -176,10 +176,6 @@ void free_editMesh(struct EditMesh *em){}
 void docenter_new(void){}
 int saveover(char *str){ return 0;}
 
-/* image.c */
-#include "DNA_image_types.h"
-void free_realtime_image(Image *ima){} // has to become a callback, opengl stuff
-
 /* ipo.c */
 void copy_view3d_lock(short val){}     // was a hack, to make scene layer ipo's possible
 
index 1dabab98a6e78ec95484c0b126ca1f86bb394ec2..328dcada01a94764dcab111c81004cc9b939ab25 100644 (file)
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
 // headers for fluidsim bobj meshes
 #include <stdlib.h>
 #include "LBM_fluidsim.h"
@@ -411,6 +415,8 @@ void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices)
        CustomData_swap(&dm->faceData, index, corner_indices);
 }
 
+///
+
 static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
 {
        DerivedMesh *dm = CDDM_from_mesh(me, ob);
@@ -894,6 +900,162 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void
        emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
 }
 
+static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs),
+               int (*setDrawOptions)(void *userData, int index), void *userData) 
+{
+       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditMesh *em= emdm->em;
+       float (*vertexCos)[3]= emdm->vertexCos;
+       float (*vertexNos)[3]= emdm->vertexNos;
+       EditVert *eve;
+       EditFace *efa;
+       DMVertexAttribs attribs;
+       GPUVertexAttribs gattribs;
+       MTFace *tf;
+       int transp, new_transp, orig_transp, tfoffset;
+       int i, b, matnr, new_matnr, dodraw, layer;
+
+       dodraw = 0;
+       matnr = -1;
+
+       transp = GPU_get_material_blend_mode();
+       orig_transp = transp;
+       layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE);
+       tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset;
+
+       memset(&attribs, 0, sizeof(attribs));
+
+       /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
+       glShadeModel(GL_SMOOTH);
+
+       for (i=0,eve=em->verts.first; eve; eve= eve->next)
+               eve->tmp.l = (long) i++;
+
+#define PASSATTRIB(efa, eve, vert) {                                                                                   \
+       if(attribs.totorco) {                                                                                                           \
+               float *orco = attribs.orco.array[eve->tmp.l];                                                   \
+               glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.tottface; b++) {                                                                         \
+               MTFace *tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset);   \
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.totmcol; b++) {                                                                          \
+               MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset);                \
+               GLubyte col[4];                                                                                                                 \
+               col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
+               glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
+       }                                                                                                                                                       \
+       if(attribs.tottang) {                                                                                                           \
+               float *tang = attribs.tang.array[i*4 + vert];                                                   \
+               glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
+       }                                                                                                                                                       \
+}
+
+       for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
+               int drawSmooth= (efa->flag & ME_SMOOTH);
+
+               if(setDrawOptions && !setDrawOptions(userData, i))
+                       continue;
+
+               new_matnr = efa->mat_nr + 1;
+               if(new_matnr != matnr) {
+                       dodraw = setMaterial(matnr = new_matnr, &gattribs);
+                       if(dodraw)
+                               DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+               }
+
+               if(tfoffset != -1) {
+                       tf = (MTFace*)((char*)efa->data)+tfoffset;
+                       new_transp = tf->transp;
+
+                       if(new_transp != transp) {
+                               if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+                                       GPU_set_material_blend_mode(orig_transp);
+                               else
+                                       GPU_set_material_blend_mode(new_transp);
+                               transp = new_transp;
+                       }
+               }
+
+               if(dodraw) {
+                       glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+                       if (!drawSmooth) {
+                               if(vertexCos) glNormal3fv(emdm->faceNos[i]);
+                               else glNormal3fv(efa->n);
+
+                               PASSATTRIB(efa, efa->v1, 0);
+                               if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                               else glVertex3fv(efa->v1->co);
+
+                               PASSATTRIB(efa, efa->v2, 1);
+                               if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                               else glVertex3fv(efa->v2->co);
+
+                               PASSATTRIB(efa, efa->v3, 2);
+                               if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                               else glVertex3fv(efa->v3->co);
+
+                               if(efa->v4) {
+                                       PASSATTRIB(efa, efa->v4, 3);
+                                       if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                       else glVertex3fv(efa->v4->co);
+                               }
+                       } else {
+                               PASSATTRIB(efa, efa->v1, 0);
+                               if(vertexCos) {
+                                       glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                               }
+                               else {
+                                       glNormal3fv(efa->v1->no);
+                                       glVertex3fv(efa->v1->co);
+                               }
+
+                               PASSATTRIB(efa, efa->v2, 1);
+                               if(vertexCos) {
+                                       glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                               }
+                               else {
+                                       glNormal3fv(efa->v2->no);
+                                       glVertex3fv(efa->v2->co);
+                               }
+
+                               PASSATTRIB(efa, efa->v3, 2);
+                               if(vertexCos) {
+                                       glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                               }
+                               else {
+                                       glNormal3fv(efa->v3->no);
+                                       glVertex3fv(efa->v3->co);
+                               }
+
+                               if(efa->v4) {
+                                       PASSATTRIB(efa, efa->v4, 3);
+                                       if(vertexCos) {
+                                               glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
+                                               glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                       }
+                                       else {
+                                               glNormal3fv(efa->v4->no);
+                                               glVertex3fv(efa->v4->co);
+                                       }
+                               }
+                       }
+                       glEnd();
+               }
+       }
+}
+
+static void emDM_drawFacesGLSL(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs))
+{
+       dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -1099,6 +1261,43 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
        }
 }
 
+static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
+{
+       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditMesh *em= emdm->em;
+       EditFace *efa;
+       char *data, *emdata;
+       void *datalayer;
+       int index, offset, size;
+
+       datalayer = DM_get_face_data_layer(dm, type);
+       if(datalayer)
+               return datalayer;
+
+       /* layers are store per face for editmesh, we convert to a temporary
+        * data layer array in the derivedmesh when these are requested */
+       if(type == CD_MTFACE || type == CD_MCOL) {
+               index = CustomData_get_layer_index(&em->fdata, type);
+
+               if(index != -1) {
+                       offset = em->fdata.layers[index].offset;
+                       size = CustomData_sizeof(type);
+
+                       DM_add_face_layer(dm, type, CD_CALLOC, NULL);
+                       index = CustomData_get_layer_index(&dm->faceData, type);
+                       dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
+
+                       data = datalayer = DM_get_face_data_layer(dm, type);
+                       for(efa=em->faces.first; efa; efa=efa->next, data+=size) {
+                               emdata = CustomData_em_get(&em->fdata, efa->data, type);
+                               memcpy(data, emdata, size);
+                       }
+               }
+       }
+
+       return datalayer;
+}
+
 static void emDM_release(DerivedMesh *dm)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -1134,6 +1333,7 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
        emdm->dm.copyVertArray = emDM_copyVertArray;
        emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
        emdm->dm.copyFaceArray = emDM_copyFaceArray;
+       emdm->dm.getFaceDataArray = emDM_getFaceDataArray;
 
        emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
        emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
@@ -1144,7 +1344,9 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
        emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
        emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
        emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
+       emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
        emdm->dm.drawFacesTex = emDM_drawFacesTex;
+       emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
        emdm->dm.drawUVEdges = emDM_drawUVEdges;
 
        emdm->dm.release = emDM_release;
@@ -1574,7 +1776,7 @@ static void vDM_drawUVEdges(DerivedMesh *dm)
 }
 
 /* draw all VerseFaces */
-static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
 {
        VDerivedMesh *vdm = (VDerivedMesh*)dm;
        struct VerseFace *vface;
@@ -1674,6 +1876,8 @@ static void vDM_drawMappedFacesTex(
                int (*setDrawParams)(void *userData, int index),
                void *userData)
 {
+       /* not supported yet */
+       vDM_drawFacesTex(dm, NULL);
 }
 
 /**/
@@ -1815,19 +2019,23 @@ CustomDataMask get_viewedit_datamask()
        ScrArea *sa;
 
        /* check if we need tfaces & mcols due to face select or texture paint */
-       if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) {
+       if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT)
                mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
-       } else {
-               /* check if we need tfaces & mcols due to view mode */
-               for(sa = G.curscreen->areabase.first; sa; sa = sa->next) {
-                       if(sa->spacetype == SPACE_VIEW3D) {
-                               View3D *view = sa->spacedata.first;
-                               if(view->drawtype == OB_SHADED) {
-                                       /* this includes normals for mesh_create_shadedColors */
-                                       mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
-                               }
-                               if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
-                                       mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+
+       /* check if we need tfaces & mcols due to view mode */
+       for(sa = G.curscreen->areabase.first; sa; sa = sa->next) {
+               if(sa->spacetype == SPACE_VIEW3D) {
+                       View3D *view = sa->spacedata.first;
+                       if(view->drawtype == OB_SHADED) {
+                               /* this includes normals for mesh_create_shadedColors */
+                               mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
+                       }
+                       if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
+                               mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+
+                               if((G.fileflags & G_FILE_GAME_MAT) &&
+                                  (G.fileflags & G_FILE_GAME_MAT_GLSL)) {
+                                       mask |= CD_MASK_ORCO;
                                }
                        }
                }
@@ -1840,13 +2048,41 @@ CustomDataMask get_viewedit_datamask()
        return mask;
 }
 
-static DerivedMesh *create_orco_dm(Object *ob, Mesh *me)
+static float *get_editmesh_orco_verts(EditMesh *em)
+{
+       EditVert *eve;
+       float *orco;
+       int a, totvert;
+
+       /* these may not really be the orco's, but it's only for preview.
+        * could be solver better once, but isn't simple */
+
+       totvert= 0;
+       for(eve=em->verts.first; eve; eve=eve->next)
+               totvert++;
+       
+       orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco");
+
+       for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3)
+               VECCOPY(orco+a, eve->co);
+       
+       return orco;
+}
+
+static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em)
 {
        DerivedMesh *dm;
        float (*orco)[3];
 
-       dm= CDDM_from_mesh(me, ob);
-       orco= (float(*)[3])get_mesh_orco_verts(ob);
+       if(em) {
+               dm= CDDM_from_editmesh(em, me);
+               orco= (float(*)[3])get_editmesh_orco_verts(em);
+       }
+       else {
+               dm= CDDM_from_mesh(me, ob);
+               orco= (float(*)[3])get_mesh_orco_verts(ob);
+       }
+
        CDDM_apply_vert_coords(dm, orco);
        CDDM_calc_normals(dm);
        MEM_freeN(orco);
@@ -1854,7 +2090,7 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me)
        return dm;
 }
 
-static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
+static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm)
 {
        float (*orco)[3], (*layerorco)[3];
        int totvert;
@@ -1869,8 +2105,10 @@ static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
                else
                        dm->getVertCos(dm, orco);
        }
-       else
-               orco= (float(*)[3])get_mesh_orco_verts(ob);
+       else {
+               if(em) orco= (float(*)[3])get_editmesh_orco_verts(em);
+               else orco= (float(*)[3])get_mesh_orco_verts(ob);
+       }
 
        transform_mesh_orco_verts(ob->data, orco, totvert, 0);
 
@@ -2016,7 +2254,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                if(dm && mti->requiredDataMask) {
                        mask = mti->requiredDataMask(md);
                        if(mask & CD_MASK_ORCO)
-                               add_orco_dm(ob, dm, orcodm);
+                               add_orco_dm(ob, NULL, dm, orcodm);
                }
 
                /* How to apply modifier depends on (a) what we already have as
@@ -2069,7 +2307,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                        mask= (CustomDataMask)curr->link;
                        if(mask & CD_MASK_ORCO) {
                                if(!orcodm)
-                                       orcodm= create_orco_dm(ob, me);
+                                       orcodm= create_orco_dm(ob, me, NULL);
 
                                mask &= ~CD_MASK_ORCO;
                                DM_set_only_copy(orcodm, mask);
@@ -2146,10 +2384,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
 
        /* add an orco layer if needed */
        if(dataMask & CD_MASK_ORCO) {
-               add_orco_dm(ob, finaldm, orcodm);
+               add_orco_dm(ob, NULL, finaldm, orcodm);
 
                if(deform_r && *deform_r)
-                       add_orco_dm(ob, *deform_r, NULL);
+                       add_orco_dm(ob, NULL, *deform_r, NULL);
        }
 
        *final_r = finaldm;
@@ -2205,7 +2443,8 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
        EditMesh *em = G.editMesh;
        ModifierData *md;
        float (*deformedVerts)[3] = NULL;
-       DerivedMesh *dm;
+       CustomDataMask mask;
+       DerivedMesh *dm, *orcodm = NULL;
        int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
        LinkNode *datamasks, *curr;
 
@@ -2230,6 +2469,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
                if(!editmesh_modifier_is_enabled(md, dm))
                        continue;
 
+               /* add an orco layer if needed by this modifier */
+               if(dm && mti->requiredDataMask) {
+                       mask = mti->requiredDataMask(md);
+                       if(mask & CD_MASK_ORCO)
+                               add_orco_dm(ob, em, dm, orcodm);
+               }
+
                /* How to apply modifier depends on (a) what we already have as
                 * a result of previous modifiers (could be a DerivedMesh or just
                 * deformed vertices) and (b) what type the modifier is.
@@ -2280,6 +2526,23 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
                                }
                        }
 
+                       /* create an orco derivedmesh in parallel */
+                       mask= (CustomDataMask)curr->link;
+                       if(mask & CD_MASK_ORCO) {
+                               if(!orcodm)
+                                       orcodm= create_orco_dm(ob, ob->data, em);
+
+                               mask &= ~CD_MASK_ORCO;
+                               DM_set_only_copy(orcodm, mask);
+                               ndm = mti->applyModifierEM(md, ob, em, orcodm);
+
+                               if(ndm) {
+                                       /* if the modifier returned a new dm, release the old one */
+                                       if(orcodm && orcodm != ndm) orcodm->release(orcodm);
+                                       orcodm = ndm;
+                               }
+                       }
+
                        /* set the DerivedMesh to only copy needed data */
                        DM_set_only_copy(dm, (CustomDataMask)curr->link);
 
@@ -2338,6 +2601,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
                deformedVerts = NULL;
        }
 
+       /* add an orco layer if needed */
+       if(dataMask & CD_MASK_ORCO)
+               add_orco_dm(ob, em, *final_r, orcodm);
+
+       if(orcodm)
+               orcodm->release(orcodm);
+
        if(deformedVerts)
                MEM_freeN(deformedVerts);
 }
@@ -2632,7 +2902,7 @@ void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_c
                        old->release(old);
 
                        if(dataMask & CD_MASK_ORCO)
-                               add_orco_dm(ob, *dm, NULL);
+                               add_orco_dm(ob, NULL, *dm, NULL);
 
                        /* Restore the original verts */
                        me->mr->newlvl= BLI_countlist(&me->mr->levels);
@@ -2847,6 +3117,8 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo
        return numleft;
 }
 
+/* ******************* GLSL ******************** */
+
 void DM_add_tangent_layer(DerivedMesh *dm)
 {
        /* mesh vars */
@@ -2967,6 +3239,91 @@ void DM_add_tangent_layer(DerivedMesh *dm)
        MEM_freeN(vtangents);
 }
 
+void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs)
+{
+       CustomData *vdata, *fdata, *tfdata = NULL;
+       int a, b, layer;
+
+       /* From the layers requested by the GLSL shader, figure out which ones are
+        * actually available for this derivedmesh, and retrieve the pointers */
+
+       memset(attribs, 0, sizeof(DMVertexAttribs));
+
+       vdata = &dm->vertData;
+       fdata = &dm->faceData;
+
+       /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we
+        * can use offsets instead */
+       if(dm->release == emDM_release)
+               tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata;
+       else
+               tfdata = fdata;
+
+       /* add a tangent layer if necessary */
+       for(b = 0; b < gattribs->totlayer; b++)
+               if(gattribs->layer[b].type == CD_TANGENT)
+                       if(CustomData_get_layer_index(fdata, CD_TANGENT) == -1)
+                               DM_add_tangent_layer(dm);
+
+       for(b = 0; b < gattribs->totlayer; b++) {
+               if(gattribs->layer[b].type == CD_MTFACE) {
+                       /* uv coordinates */
+                       if(gattribs->layer[b].name[0])
+                               layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE,
+                                       gattribs->layer[b].name);
+                       else
+                               layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE);
+
+                       if(layer != -1) {
+                               a = attribs->tottface++;
+
+                               attribs->tface[a].array = tfdata->layers[layer].data;
+                               attribs->tface[a].emOffset = tfdata->layers[layer].offset;
+                               attribs->tface[a].glIndex = gattribs->layer[b].glindex;
+                       }
+               }
+               else if(gattribs->layer[b].type == CD_MCOL) {
+                       /* vertex colors */
+                       if(gattribs->layer[b].name[0])
+                               layer = CustomData_get_named_layer_index(tfdata, CD_MCOL,
+                                       gattribs->layer[b].name);
+                       else
+                               layer = CustomData_get_active_layer_index(tfdata, CD_MCOL);
+
+                       if(layer != -1) {
+                               a = attribs->totmcol++;
+
+                               attribs->mcol[a].array = tfdata->layers[layer].data;
+                               attribs->mcol[a].emOffset = tfdata->layers[layer].offset;
+                               attribs->mcol[a].glIndex = gattribs->layer[b].glindex;
+                       }
+               }
+               else if(gattribs->layer[b].type == CD_TANGENT) {
+                       /* tangents */
+                       layer = CustomData_get_layer_index(fdata, CD_TANGENT);
+
+                       if(layer != -1) {
+                               attribs->tottang = 1;
+
+                               attribs->tang.array = fdata->layers[layer].data;
+                               attribs->tang.emOffset = fdata->layers[layer].offset;
+                               attribs->tang.glIndex = gattribs->layer[b].glindex;
+                       }
+               }
+               else if(gattribs->layer[b].type == CD_ORCO) {
+                       /* original coordinates */
+                       layer = CustomData_get_layer_index(vdata, CD_ORCO);
+
+                       if(layer != -1) {
+                               attribs->totorco = 1;
+
+                               attribs->orco.array = vdata->layers[layer].data;
+                               attribs->orco.emOffset = vdata->layers[layer].offset;
+                               attribs->orco.glIndex = gattribs->layer[b].glindex;
+                       }
+               }
+       }
+}
 
 /* ************************* fluidsim bobj file handling **************************** */
 
index 74c6c551a831eb58e2e39d4dfde25aa137fe8217..8921ea5d3b7b287297515b9efd68ddc11364d956 100644 (file)
@@ -36,6 +36,7 @@ include nan_compile.mk
 CFLAGS += $(LEVEL_1_C_WARNINGS)
 
 # OpenGL and Python
+CPPFLAGS += -I$(NAN_GLEW)/include
 CPPFLAGS += -I$(OPENGL_HEADERS)
 CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
 
@@ -74,6 +75,9 @@ CPPFLAGS += -I$(NAN_ZLIB)/include
 #path to nodes
 CPPFLAGS += -I../../nodes
 
+#path to gpu
+CPPFLAGS += -I../../gpu
+
 # path to our own external headerfiles
 CPPFLAGS += -I..
 
index 5b96bf110566cecceb0fb21dba124d84ec07a60e..2648233aca592e652870b4763c822dec4b60800b 100644 (file)
@@ -347,6 +347,8 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan
        VECCOPY(pchan->loc, chan->loc);
        VECCOPY(pchan->size, chan->size);
        QUATCOPY(pchan->quat, chan->quat);
+       Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat);
+       Mat4CpyMat4(pchan->pose_mat, (float(*)[4])chan->pose_mat);
        pchan->flag= chan->flag;
        
        con= chan->constraints.first;
index 1592c3e55042b2289c41581fd87ddcde7c84155d..e2ce4b9f6f3a7892df20f6bf08665c60dba9a6d2 100644 (file)
@@ -303,7 +303,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated)
        DupliObject *dob;
        Group *group;
        GroupObject *go;
-       float mat[4][4];
+       float mat[4][4], tmat[4][4];
        
        if(ob->dup_group==NULL) return;
        group= ob->dup_group;
@@ -320,7 +320,15 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated)
                /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
                if(go->ob!=ob) {
                        
-                       Mat4MulMat4(mat, go->ob->obmat, ob->obmat);
+                       /* Group Dupli Offset, should apply after everything else */
+                       if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) {
+                               Mat4CpyMat4(tmat, go->ob->obmat);
+                               VecSubf(tmat[3], tmat[3], group->dupli_ofs);
+                               Mat4MulMat4(mat, tmat, ob->obmat);
+                       } else {
+                               Mat4MulMat4(mat, go->ob->obmat, ob->obmat);
+                       }
+                       
                        dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated);
                        dob->no_draw= (dob->origlay & group->layer)==0;
                        
@@ -1059,7 +1067,8 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist,
        }
 }
 
-/* note; group dupli's already set transform matrix. see note in group_duplilist() */
+/* Returns a list of DupliObject
+ * note; group dupli's already set transform matrix. see note in group_duplilist() */
 ListBase *object_duplilist(Scene *sce, Object *ob)
 {
        ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist");
index aca51e56c6e5363fd4d3cf84534abe0d5ce2a048..1fe6447752e72f37dd51c11d09663925e3b7cb19 100644 (file)
@@ -525,6 +525,7 @@ typedef struct UndoElem {
        char str[FILE_MAXDIR+FILE_MAXFILE];
        char name[MAXUNDONAME];
        MemFile memfile;
+       uintptr_t undosize;
 } UndoElem;
 
 static ListBase undobase={NULL, NULL};
@@ -555,6 +556,7 @@ static int read_undosave(UndoElem *uel)
 /* name can be a dynamic string */
 void BKE_write_undo(char *name)
 {
+       uintptr_t maxmem, totmem, memused;
        int nr, success;
        UndoElem *uel;
        
@@ -616,8 +618,36 @@ void BKE_write_undo(char *name)
                
                if(curundo->prev) prevfile= &(curundo->prev->memfile);
                
+               memused= MEM_get_memory_in_use();
                success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err);
-               
+               curundo->undosize= MEM_get_memory_in_use() - memused;
+       }
+
+       if(U.undomemory != 0) {
+               /* limit to maximum memory (afterwards, we can't know in advance) */
+               totmem= 0;
+               maxmem= ((uintptr_t)U.undomemory)*1024*1024;
+
+               /* keep at least two (original + other) */
+               uel= undobase.last;
+               while(uel && uel->prev) {
+                       totmem+= uel->undosize;
+                       if(totmem>maxmem) break;
+                       uel= uel->prev;
+               }
+
+               if(uel) {
+                       if(uel->prev && uel->prev->prev)
+                               uel= uel->prev;
+
+                       while(undobase.first!=uel) {
+                               UndoElem *first= undobase.first;
+                               BLI_remlink(&undobase, first);
+                               /* the merge is because of compression */
+                               BLO_merge_memfile(&first->memfile, &first->next->memfile);
+                               MEM_freeN(first);
+                       }
+               }
        }
 }
 
@@ -683,14 +713,14 @@ char *BKE_undo_menu_string(void)
        UndoElem *uel;
        DynStr *ds= BLI_dynstr_new();
        char *menu;
-       
+
        BLI_dynstr_append(ds, "Global Undo History %t");
        
        for(uel= undobase.first; uel; uel= uel->next) {
                BLI_dynstr_append(ds, "|");
                BLI_dynstr_append(ds, uel->name);
        }
-       
+
        menu= BLI_dynstr_get_cstring(ds);
        BLI_dynstr_free(ds);
 
index 472df3d0f262f80f771af9b59f0d4601fa4f51c4..9d5dcb8109b12a9e3b0587574147a489f38e5988 100644 (file)
 
 #include "MEM_guardedalloc.h"
 
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
 #include <string.h>
 #include <limits.h>
 
@@ -243,7 +247,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm)
        glEnd();
 }
 
-static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
 {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
        MVert *mvert = cddm->mvert;
@@ -271,7 +275,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
                   || new_shademodel != shademodel) {
                        glEnd();
 
-                       drawCurrentMat = setMaterial(matnr = new_matnr);
+                       drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
 
                        glShadeModel(shademodel = new_shademodel);
                        glBegin(glmode = new_glmode);
@@ -556,6 +560,134 @@ static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void
        cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
 }
 
+static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+       CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
+       GPUVertexAttribs gattribs;
+       DMVertexAttribs attribs;
+       MVert *mvert = cddm->mvert;
+       MFace *mface = cddm->mface;
+       MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
+       float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
+       int a, b, dodraw, smoothnormal, matnr, new_matnr;
+       int transp, new_transp, orig_transp;
+       int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+
+       matnr = -1;
+       smoothnormal = 0;
+       dodraw = 0;
+       transp = GPU_get_material_blend_mode();
+       orig_transp = transp;
+
+       memset(&attribs, 0, sizeof(attribs));
+
+       glShadeModel(GL_SMOOTH);
+       glBegin(GL_QUADS);
+
+       for(a = 0; a < dm->numFaceData; a++, mface++) {
+               new_matnr = mface->mat_nr + 1;
+
+               if(new_matnr != matnr) {
+                       glEnd();
+
+                       dodraw = setMaterial(matnr = new_matnr, &gattribs);
+                       if(dodraw)
+                               DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+
+                       glBegin(GL_QUADS);
+               }
+
+               if(!dodraw) {
+                       continue;
+               }
+               else if(setDrawOptions) {
+                       orig = index[a];
+
+                       if(orig == ORIGINDEX_NONE)
+                               continue;
+                       else if(!setDrawOptions(userData, orig))
+                               continue;
+               }
+
+               if(tf) {
+                       new_transp = tf[a].transp;
+
+                       if(new_transp != transp) {
+                               glEnd();
+
+                               if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+                                       GPU_set_material_blend_mode(orig_transp);
+                               else
+                                       GPU_set_material_blend_mode(new_transp);
+                               transp = new_transp;
+
+                               glBegin(GL_QUADS);
+                       }
+               }
+
+               smoothnormal = (mface->flag & ME_SMOOTH);
+
+               if(!smoothnormal) {
+                       if(nors) {
+                               glNormal3fv(nors[a]);
+                       }
+                       else {
+                               /* TODO ideally a normal layer should always be available */
+                               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);
+                       }
+               }
+
+#define PASSVERT(index, vert) {                                                                                                        \
+       if(attribs.totorco)                                                                                                                     \
+               glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
+       for(b = 0; b < attribs.tottface; b++) {                                                                         \
+               MTFace *tf = &attribs.tface[b].array[a];                                                                \
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.totmcol; b++) {                                                                          \
+               MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
+               GLubyte col[4];                                                                                                                 \
+               col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
+               glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
+       }                                                                                                                                                       \
+       if(attribs.tottang) {                                                                                                           \
+               float *tang = attribs.tang.array[a*4 + vert];                                                   \
+               glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
+       }                                                                                                                                                       \
+       if(smoothnormal)                                                                                                                        \
+               glNormal3sv(mvert[index].no);                                                                                   \
+       glVertex3fv(mvert[index].co);                                                                                           \
+}
+
+               PASSVERT(mface->v1, 0);
+               PASSVERT(mface->v2, 1);
+               PASSVERT(mface->v3, 2);
+               if(mface->v4)
+                       PASSVERT(mface->v4, 3)
+               else
+                       PASSVERT(mface->v3, 2)
+
+#undef PASSVERT
+       }
+       glEnd();
+
+       glShadeModel(GL_FLAT);
+}
+
+static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
+{
+       dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
 {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
@@ -713,8 +845,10 @@ static CDDerivedMesh *cdDM_create(const char *desc)
        dm->drawFacesSolid = cdDM_drawFacesSolid;
        dm->drawFacesColored = cdDM_drawFacesColored;
        dm->drawFacesTex = cdDM_drawFacesTex;
+       dm->drawFacesGLSL = cdDM_drawFacesGLSL;
        dm->drawMappedFaces = cdDM_drawMappedFaces;
        dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
+       dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
 
        dm->foreachMappedVert = cdDM_foreachMappedVert;
        dm->foreachMappedEdge = cdDM_foreachMappedEdge;
index 295b8fe3552fadfa7b7d871cc38f7bbdea67dd99..45b8bb7935cbbf32a5b11da0d7cf98a699cc64de 100644 (file)
@@ -730,3 +730,24 @@ void curvemapping_initialize(CurveMapping *cumap)
                        curvemap_make_table(cumap->cm+a, &cumap->clipr);
        }
 }
+
+void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size)
+{
+       int a;
+       
+       *size = CM_TABLE+1;
+       *array = MEM_callocN(sizeof(float)*(*size)*4, "CurveMapping");
+       curvemapping_initialize(cumap);
+
+       for(a=0; a<*size; a++) {
+               if(cumap->cm[0].table)
+                       (*array)[a*4+0]= cumap->cm[0].table[a].y;
+               if(cumap->cm[1].table)
+                       (*array)[a*4+1]= cumap->cm[1].table[a].y;
+               if(cumap->cm[2].table)
+                       (*array)[a*4+2]= cumap->cm[2].table[a].y;
+               if(cumap->cm[3].table)
+                       (*array)[a*4+3]= cumap->cm[3].table[a].y;
+       }
+}
+
index 07537e3a81c6b4fa8cafbb6b5809e15d4021d74f..27fa00ac239b1b8ce693f82cfb54c07ff7cf026c 100644 (file)
@@ -53,6 +53,7 @@
 #include "DNA_packedFile_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_sequence_types.h"
 #include "DNA_texture_types.h"
 #include "DNA_userdef_types.h"
 
 
 #include "RE_pipeline.h"
 
-/* bad level; call to free_realtime_image */
-#include "BKE_bad_level_calls.h"       
-
 /* for stamp drawing to an image */
 #include "BMF_Api.h"
 
 #include "blendef.h"
 #include "BSE_time.h"
 
+#include "GPU_extensions.h"
+#include "GPU_draw.h"
+
 #include "BLO_sys_types.h" // for intptr_t support
 
 /* max int, to indicate we don't store sequences in ibuf */
@@ -240,7 +241,7 @@ static void image_free_buffers(Image *ima)
                ima->rr= NULL;
        }       
        
-       free_realtime_image(ima);
+       GPU_free_image(ima);
        
        ima->ok= IMA_OK;
 }
@@ -620,7 +621,7 @@ void free_old_images()
                           This gives textures a "second chance" to be used before dying.
                        */
                        if(ima->bindcode || ima->repbind) {
-                               free_realtime_image(ima);
+                               GPU_free_image(ima);
                                ima->lastused = ctime;
                        }
                        /* Otherwise, just kill the buffers */
index 1a6c8f51d9c20d1872264a266ca1816a27c5b683..e8a25aaaf807997f4f55e72cad1d1d3b8bd88b56 100644 (file)
@@ -1390,6 +1390,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
                        else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7];
                        else if(icu->adrcode & MA_MAP9) mtex= ma->mtex[8];
                        else if(icu->adrcode & MA_MAP10) mtex= ma->mtex[9];
+                       else if(icu->adrcode & MA_MAP12) mtex= ma->mtex[11];
+                       else if(icu->adrcode & MA_MAP11) mtex= ma->mtex[10];
+                       else if(icu->adrcode & MA_MAP13) mtex= ma->mtex[12];
+                       else if(icu->adrcode & MA_MAP14) mtex= ma->mtex[13];
+                       else if(icu->adrcode & MA_MAP15) mtex= ma->mtex[14];
+                       else if(icu->adrcode & MA_MAP16) mtex= ma->mtex[15];
+                       else if(icu->adrcode & MA_MAP17) mtex= ma->mtex[16];
+                       else if(icu->adrcode & MA_MAP18) mtex= ma->mtex[17];
                        
                        if(mtex) {
                                poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
@@ -1479,7 +1487,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
                        else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7];
                        else if(icu->adrcode & MA_MAP9) mtex= wo->mtex[8];
                        else if(icu->adrcode & MA_MAP10) mtex= wo->mtex[9];
-                       
+                       else if(icu->adrcode & MA_MAP11) mtex= wo->mtex[10];
+                       else if(icu->adrcode & MA_MAP12) mtex= wo->mtex[11];
+                       else if(icu->adrcode & MA_MAP13) mtex= wo->mtex[12];
+                       else if(icu->adrcode & MA_MAP14) mtex= wo->mtex[13];
+                       else if(icu->adrcode & MA_MAP15) mtex= wo->mtex[14];
+                       else if(icu->adrcode & MA_MAP16) mtex= wo->mtex[15];
+                       else if(icu->adrcode & MA_MAP17) mtex= wo->mtex[16];
+                       else if(icu->adrcode & MA_MAP18) mtex= wo->mtex[17];
                        if(mtex) {
                                poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
                        }
@@ -1524,6 +1539,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
                        else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7];
                        else if(icu->adrcode & MA_MAP9) mtex= la->mtex[8];
                        else if(icu->adrcode & MA_MAP10) mtex= la->mtex[9];
+                       else if(icu->adrcode & MA_MAP11) mtex= la->mtex[10];
+                       else if(icu->adrcode & MA_MAP12) mtex= la->mtex[11];
+                       else if(icu->adrcode & MA_MAP13) mtex= la->mtex[12];
+                       else if(icu->adrcode & MA_MAP14) mtex= la->mtex[13];
+                       else if(icu->adrcode & MA_MAP15) mtex= la->mtex[14];
+                       else if(icu->adrcode & MA_MAP16) mtex= la->mtex[15];
+                       else if(icu->adrcode & MA_MAP17) mtex= la->mtex[16];
+                       else if(icu->adrcode & MA_MAP18) mtex= la->mtex[17];
                        
                        if(mtex) {
                                poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
index 3983eecdaba5b39d6bf0f379d2da0657346c20df..f05b84f6e90ddc8727c9af9467fbbd015feb17a5 100644 (file)
@@ -61,6 +61,8 @@
 
 #include "BPY_extern.h"
 
+#include "GPU_material.h"
+
 /* used in UI and render */
 Material defmaterial;
 
@@ -96,6 +98,9 @@ void free_material(Material *ma)
                ntreeFreeTree(ma->nodetree);
                MEM_freeN(ma->nodetree);
        }
+
+       if(ma->gpumaterial.first)
+               GPU_material_free(ma);
 }
 
 void init_material(Material *ma)
@@ -207,6 +212,8 @@ Material *copy_material(Material *ma)
        if(ma->nodetree) {
                man->nodetree= ntreeCopyTree(ma->nodetree, 0);  /* 0 == full new tree */
        }
+
+       man->gpumaterial.first= man->gpumaterial.last= NULL;
        
        return man;
 }
index 43e48c3bacd377121366167e955127749a5e7f00..77b9ea4fa2dd3de99b9cf28a28c139cbe464c646 100644 (file)
 #include "BLI_editVert.h"
 #include "BLI_arithb.h"
 
-int update_realtime_texture(MTFace *tface, double time)
-{
-       Image *ima;
-       int     inc = 0;
-       float   diff;
-       int     newframe;
-
-       ima = tface->tpage;
-
-       if (!ima)
-               return 0;
-
-       if (ima->lastupdate<0)
-               ima->lastupdate = 0;
-
-       if (ima->lastupdate>time)
-               ima->lastupdate=(float)time;
-
-       if(ima->tpageflag & IMA_TWINANIM) {
-               if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
-               
-               /* check: is the bindcode not in the array? Then free. (still to do) */
-               
-               diff = (float)(time-ima->lastupdate);
-
-               inc = (int)(diff*(float)ima->animspeed);
-
-               ima->lastupdate+=((float)inc/(float)ima->animspeed);
-
-               newframe = ima->lastframe+inc;
-
-               if (newframe > (int)ima->twend)
-                       newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
-
-               ima->lastframe = newframe;
-       }
-       return inc;
-}
-
 void mesh_update_customdata_pointers(Mesh *me)
 {
        me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
index 4e36df35a1492022a66b1cce81ddd856241e2076..4dfe651c01fafcc617341a20d61375d77d172b78 100644 (file)
@@ -68,6 +68,9 @@
 
 #include "SHD_node.h"
 
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
 static ListBase empty_list = {NULL, NULL};
 ListBase node_all_composit = {NULL, NULL};
 ListBase node_all_shaders = {NULL, NULL};
@@ -2352,6 +2355,117 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
        ntreeEndExecTree(ntree);
 }
 
+/* GPU material from shader nodes */
+
+static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+{
+       bNodeSocket *sock;
+       int i;
+
+       for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
+               memset(&gs[i], 0, sizeof(gs[i]));
+
+       QUATCOPY(gs[i].vec, ns[i]->vec);
+               gs[i].link= ns[i]->data;
+
+               if (sock->type == SOCK_VALUE)
+                       gs[i].type= GPU_FLOAT;
+               else if (sock->type == SOCK_VECTOR)
+                       gs[i].type= GPU_VEC3;
+               else if (sock->type == SOCK_RGBA)
+                       gs[i].type= GPU_VEC4;
+               else
+                       gs[i].type= GPU_NONE;
+
+               gs[i].name = "";
+               gs[i].hasinput= ns[i]->hasinput;
+               gs[i].hasoutput= ns[i]->hasinput;
+               gs[i].sockettype= ns[i]->sockettype;
+       }
+
+       gs[i].type= GPU_NONE;
+}
+
+static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+{
+       bNodeSocket *sock;
+       int i;
+
+       for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
+               ns[i]->data= gs[i].link;
+               ns[i]->hasinput= gs[i].hasinput;
+               ns[i]->hasoutput= gs[i].hasoutput;
+               ns[i]->sockettype= gs[i].sockettype;
+       }
+}
+
+static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in, bNodeStack **out)
+{
+       bNode *node;
+       bNodeTree *ntree= (bNodeTree *)gnode->id;
+       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
+       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
+       GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
+       int doit = 0;
+       
+       if(ntree==NULL) return;
+       
+       stack+= gnode->stack_index;
+               
+       for(node= ntree->nodes.first; node; node= node->next) {
+               if(node->typeinfo->gpufunc) {
+                       group_node_get_stack(node, stack, nsin, nsout, in, out);
+
+                       doit = 0;
+                       
+                       /* for groups, only execute outputs for edited group */
+                       if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+                               if(gnode->flag & NODE_GROUP_EDIT)
+                                       if(node->flag & NODE_DO_OUTPUT)
+                                               doit = 1;
+                       }
+                       else
+                               doit = 1;
+
+                       if(doit)  {
+                               gpu_from_node_stack(&node->inputs, nsin, gpuin);
+                               gpu_from_node_stack(&node->outputs, nsout, gpuout);
+                               if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
+                                       data_from_gpu_stack(&node->outputs, nsout, gpuout);
+                       }
+               }
+       }
+}
+
+void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
+{
+       bNode *node;
+       bNodeStack *stack;
+       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
+       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
+       GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
+
+       if((ntree->init & NTREE_EXEC_INIT)==0)
+               ntreeBeginExecTree(ntree);
+
+       stack= ntree->stack;
+
+       for(node= ntree->nodes.first; node; node= node->next) {
+               if(node->typeinfo->gpufunc) {
+                       node_get_stack(node, stack, nsin, nsout);
+                       gpu_from_node_stack(&node->inputs, nsin, gpuin);
+                       gpu_from_node_stack(&node->outputs, nsout, gpuout);
+                       if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
+                               data_from_gpu_stack(&node->outputs, nsout, gpuout);
+               }
+        else if(node->type==NODE_GROUP && node->id) {
+                       node_get_stack(node, stack, nsin, nsout);
+                       gpu_node_group_execute(stack, mat, node, nsin, nsout);
+               }
+       }
+
+       ntreeEndExecTree(ntree);
+}
 
 /* **************** call to switch lamploop for material node ************ */
 
index 7b36e46d45e078011edac6d9c574155392bddc81..8879b498ad9a931a6e2a7b36718b4ea0a2f881e1 100644 (file)
 
 #include "BPY_extern.h"
 
+#include "GPU_material.h"
+
 #include "blendef.h"
 
 /* Local function protos */
@@ -268,6 +270,7 @@ void free_object(Object *ob)
        }
        if(ob->soft) sbFree(ob->soft);
        if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings);
+       if(ob->gpulamp.first) GPU_lamp_free(ob);
 }
 
 static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@@ -918,7 +921,7 @@ Object *add_only_object(int type, char *name)
        QuatOne(ob->dquat);
 #endif 
 
-       ob->col[0]= ob->col[1]= ob->col[2]= 0.0;
+       ob->col[0]= ob->col[1]= ob->col[2]= 1.0;
        ob->col[3]= 1.0;
 
        ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0;
@@ -1226,6 +1229,7 @@ Object *copy_object(Object *ob)
        obn->vnode = NULL;
 #endif
 
+       obn->gpulamp.first = obn->gpulamp.last = NULL;
 
        return obn;
 }
index bba79bd6d287bf7f507e27ddf7abc7964c460b6e..f334fc39daa1c351ecb66c9e10ac69d404b64eaa 100644 (file)
 
 #include "BIF_gl.h"
 
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
 #include "CCGSubSurf.h"
 
 typedef struct _VertData {
@@ -1599,7 +1603,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
 }
 
        /* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
+static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
@@ -1621,7 +1625,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
                        mat_nr= 0;
                }
                
-               if (!setMaterial(mat_nr+1))
+               if (!setMaterial(mat_nr+1, NULL))
                        continue;
 
                glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
@@ -1666,6 +1670,168 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
 
        ccgFaceIterator_free(fi);
 }
+
+       /* Only used by non-editmesh types */
+static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
+       CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+       CCGSubSurf *ss = ccgdm->ss;
+       CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
+       GPUVertexAttribs gattribs;
+       DMVertexAttribs attribs;
+       MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
+       int gridSize = ccgSubSurf_getGridSize(ss);
+       int gridFaces = gridSize - 1;
+       int edgeSize = ccgSubSurf_getEdgeSize(ss);
+       int transp, orig_transp, new_transp;
+       char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS);
+       int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
+
+       doDraw = 0;
+       numVerts = 0;
+       matnr = -1;
+       transp = GPU_get_material_blend_mode();
+       orig_transp = transp;
+
+       memset(&attribs, 0, sizeof(attribs));
+
+#define PASSATTRIB(dx, dy, vert) {                                                                                             \
+       if(attribs.totorco) {                                                                                                           \
+               index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize);                 \
+               glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.tottface; b++) {                                                                         \
+               MTFace *tf = &attribs.tface[b].array[a];                                                                \
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.totmcol; b++) {                                                                          \
+               MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
+               GLubyte col[4];                                                                                                                 \
+               col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
+               glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
+       }                                                                                                                                                       \
+       if(attribs.tottang) {                                                                                                           \
+               float *tang = attribs.tang.array[a*4 + vert];                                                   \
+               glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
+       }                                                                                                                                                       \
+}
+
+       totface = ccgSubSurf_getNumFaces(ss);
+       for(a = 0, i = 0; i < totface; i++) {
+               CCGFace *f = ccgdm->faceMap[i].face;
+               int S, x, y, drawSmooth;
+               int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
+               int origIndex = ccgDM_getFaceMapIndex(ccgdm, ss, f);
+               
+               numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+               if(faceFlags) {
+                       drawSmooth = (faceFlags[index*4] & ME_SMOOTH);
+                       new_matnr= faceFlags[index*4 + 1] + 1;
+               }
+               else {
+                       drawSmooth = 1;
+                       new_matnr= 1;
+               }
+
+               if(new_matnr != matnr) {
+                       doDraw = setMaterial(matnr = new_matnr, &gattribs);
+                       if(doDraw)
+                               DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+               }
+
+               if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) {
+                       a += gridFaces*gridFaces*numVerts;
+                       continue;
+               }
+
+               if(tf) {
+                       new_transp = tf[i].transp;
+
+                       if(new_transp != transp) {
+                               if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+                                       GPU_set_material_blend_mode(orig_transp);
+                               else
+                                       GPU_set_material_blend_mode(new_transp);
+                               transp = new_transp;
+                       }
+               }
+
+               glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
+               for (S=0; S<numVerts; S++) {
+                       VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+                       VertData *vda, *vdb;
+
+                       if (drawSmooth) {
+                               for (y=0; y<gridFaces; y++) {
+                                       glBegin(GL_QUAD_STRIP);
+                                       for (x=0; x<gridFaces; x++) {
+                                               vda = &faceGridData[(y+0)*gridSize + x];
+                                               vdb = &faceGridData[(y+1)*gridSize + x];
+                                               
+                                               PASSATTRIB(0, 0, 0);
+                                               glNormal3fv(vda->no);
+                                               glVertex3fv(vda->co);
+
+                                               PASSATTRIB(0, 1, 1);
+                                               glNormal3fv(vdb->no);
+                                               glVertex3fv(vdb->co);
+
+                                               if(x != gridFaces-1)
+                                                       a++;
+                                       }
+
+                                       vda = &faceGridData[(y+0)*gridSize + x];
+                                       vdb = &faceGridData[(y+1)*gridSize + x];
+
+                                       PASSATTRIB(0, 0, 3);
+                                       glNormal3fv(vda->no);
+                                       glVertex3fv(vda->co);
+
+                                       PASSATTRIB(0, 1, 2);
+                                       glNormal3fv(vdb->no);
+                                       glVertex3fv(vdb->co);
+
+                                       glEnd();
+
+                                       a++;
+                               }
+                       } else {
+                               glBegin(GL_QUADS);
+                               for (y=0; y<gridFaces; y++) {
+                                       for (x=0; x<gridFaces; x++) {
+                                               float *aco = faceGridData[(y+0)*gridSize + x].co;
+                                               float *bco = faceGridData[(y+0)*gridSize + x + 1].co;
+                                               float *cco = faceGridData[(y+1)*gridSize + x + 1].co;
+                                               float *dco = faceGridData[(y+1)*gridSize + x].co;
+
+                                               ccgDM_glNormalFast(aco, bco, cco, dco);
+
+                                               PASSATTRIB(0, 1, 1);
+                                               glVertex3fv(dco);
+                                               PASSATTRIB(1, 1, 2);
+                                               glVertex3fv(cco);
+                                               PASSATTRIB(1, 0, 3);
+                                               glVertex3fv(bco);
+                                               PASSATTRIB(0, 0, 0);
+                                               glVertex3fv(aco);
+                                               
+                                               a++;
+                                       }
+                               }
+                               glEnd();
+                       }
+               }
+       }
+
+#undef PASSATTRIB
+
+       ccgFaceIterator_free(fi);
+}
+
+static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
+       dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
 static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
@@ -2143,8 +2309,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
        ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
        ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
+       ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
        ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
        ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
+       ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
        ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
 
        ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
index 936381c85cc41c0e2ba6851a249974937670f19b..bb726887d32770a0a43b510324e8c3136b75be27 100644 (file)
@@ -53,6 +53,7 @@
 #include "DNA_world_types.h"
 #include "DNA_brush_types.h"
 #include "DNA_node_types.h"
+#include "DNA_color_types.h"
 #include "DNA_scene_types.h"
 
 #include "IMB_imbuf_types.h"
@@ -390,6 +391,17 @@ int do_colorband(ColorBand *coba, float in, float out[4])
        return 1;       /* OK */
 }
 
+void colorband_table_RGBA(ColorBand *coba, float **array, int *size)
+{
+       int a;
+       
+       *size = CM_TABLE+1;
+       *array = MEM_callocN(sizeof(float)*(*size)*4, "ColorBand");
+
+       for(a=0; a<*size; a++)
+               do_colorband(coba, (float)a/(float)CM_TABLE, &(*array)[a*4]);
+}
+
 /* ******************* TEX ************************ */
 
 void free_texture(Tex *tex)
index c22b6f79e08f91c86eee4054db39a96808ec6b05..4448231b2b4d80744a947a6e1b4851937c2558f0 100644 (file)
@@ -260,6 +260,7 @@ void Vec2Mulf(float *v1, float f);
 void Vec2Addf(float *v, float *v1, float *v2);
 void Vec2Subf(float *v, float *v1, float *v2);
 void Vec2Copyf(float *v1, float *v2);
+void Vec2Lerpf(float *target, float *a, float *b, float t);
 
 void AxisAngleToQuat(float *q, float *axis, float angle);
 void vectoquat(float *vec, short axis, short upflag, float *q);
index e24ccad12fb28f6cc376fd06c7b8882493ccf4c5..c59cd2dab4ee9cc71ab9229e98bda9b0f1a5fe83 100644 (file)
@@ -73,7 +73,6 @@ extern ListBase fillvertbase;
  * @attention Defined in scanfill.c
  */
 extern ListBase filledgebase;
-extern int totblock;
 
 extern char btempdir[]; /* creator.c temp dir used instead of U.tempdir, set with BLI_where_is_temp( btempdir, 1 ); */
 
index 8bd7ad405af82b5e2ef492a69830c83051ad65bc..50f8ba0fcde8e26602fceac38c6f943a8ae3fd14 100644 (file)
@@ -2113,6 +2113,14 @@ void VecLerpf(float *target, float *a, float *b, float t)
        target[2]= s*a[2] + t*b[2];
 }
 
+void Vec2Lerpf(float *target, float *a, float *b, float t)
+{
+       float s = 1.0f-t;
+
+       target[0]= s*a[0] + t*b[0];
+       target[1]= s*a[1] + t*b[1];
+}
+
 void VecMidf(float *v, float *v1, float *v2)
 {
        v[0]= 0.5f*(v1[0]+ v2[0]);
index 6affec0e104221ee1c1dcd36b7163e1ea729f497..a2b1828c39948b7023a6c4844c10d271ff1acb07 100644 (file)
@@ -1138,6 +1138,8 @@ void blo_make_image_pointer_map(FileData *fd)
                Link *ibuf= ima->ibufs.first;
                for(; ibuf; ibuf= ibuf->next) 
                        oldnewmap_insert(fd->imamap, ibuf, ibuf, 0);
+               if(ima->gputexture)
+                       oldnewmap_insert(fd->imamap, ima->gputexture, ima->gputexture, 0);
        }
        for(; sce; sce= sce->id.next) {
                if(sce->nodetree) {
@@ -1172,8 +1174,11 @@ void blo_end_image_pointer_map(FileData *fd)
                        if(NULL==newimaadr(fd, ibuf)) { /* so was restored */
                                BLI_remlink(&ima->ibufs, ibuf);
                                ima->bindcode= 0;
+                               ima->gputexture= NULL;
                        }
                }
+
+               ima->gputexture= newimaadr(fd, ima->gputexture);
        }
        for(; sce; sce= sce->id.next) {
                if(sce->nodetree) {
@@ -2340,8 +2345,10 @@ static void direct_link_image(FileData *fd, Image *ima)
                ima->ibufs.first= ima->ibufs.last= NULL;
        
        /* if not restored, we keep the binded opengl index */
-       if(ima->ibufs.first==NULL)
+       if(ima->ibufs.first==NULL) {
                ima->bindcode= 0;
+               ima->gputexture= NULL;
+       }
        
        ima->anim= NULL;
        ima->rr= NULL;
@@ -2552,6 +2559,7 @@ static void direct_link_material(FileData *fd, Material *ma)
                direct_link_nodetree(fd, ma->nodetree);
 
        ma->preview = direct_link_preview_image(fd, ma->preview);
+       ma->gpumaterial.first = ma->gpumaterial.last = NULL;
 }
 
 /* ************ READ PARTICLE SETTINGS ***************** */
@@ -3390,6 +3398,7 @@ static void direct_link_object(FileData *fd, Object *ob)
        ob->bb= NULL;
        ob->derivedDeform= NULL;
        ob->derivedFinal= NULL;
+       ob->gpulamp.first= ob->gpulamp.last= NULL;
 }
 
 /* ************ READ SCENE ***************** */
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4d376f4
--- /dev/null
@@ -0,0 +1,34 @@
+# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $
+# ***** 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.
+#
+# 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) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+FILE(GLOB SRC intern/*.c)
+
+SET(INC 
+  . ../blenlib ../blenkernel ../makesdna ../include
+  ../../../extern/glew/include ../../../intern/guardedalloc ../imbuf)
+
+BLENDERLIB(bf_gpu "${SRC}" "${INC}")
+
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
new file mode 100644 (file)
index 0000000..2399e7b
--- /dev/null
@@ -0,0 +1,116 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This shader 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 shader 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 shader; 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_GAME_H
+#define GPU_GAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct MTFace;
+struct Image;
+struct Scene;
+struct Object;
+
+/* OpenGL drawing functions related to shading. These are also
+ * shared with the game engine, where there were previously
+ * duplicates of some of these functions. */
+
+/* Initialize
+ * - sets the default Blender opengl state, if in doubt, check
+ *   the contents of this function
+ * - this is called when starting Blender, for opengl rendering,
+ *   and for switching back from the game engine for example. */
+
+void GPU_state_init(void);
+
+/* Material drawing
+ * - first the state is initialized by a particular object and
+ *   it's materials
+ * - after this, materials can be quickly enabled by their number,
+ *   GPU_enable_material returns 0 if drawing should be skipped
+ * - after drawing, the material must be disabled again */
+
+void GPU_set_object_materials(struct Scene *scene, struct Object *ob,
+       int glsl, int *do_alpha_pass);
+int GPU_enable_material(int nr, void *attribs);
+void GPU_disable_material(void);
+
+void GPU_set_material_blend_mode(int blendmode);
+int GPU_get_material_blend_mode(void);
+
+/* TexFace drawing
+ * - this is mutually exclusive with material drawing, a mesh should
+ *   be drawn using one or the other
+ * - passing NULL clears the state again */
+
+int GPU_set_tpage(struct MTFace *tface);
+
+/* Lights
+ * - returns how many lights were enabled
+ * - this affects fixed functions materials and texface, not glsl */
+
+int GPU_default_lights(void);
+int GPU_scene_object_lights(struct Scene *scene, struct Object *ob,
+       int lay, float viewmat[][4]);
+
+/* Text render
+ * - based on moving uv coordinates */
+
+void GPU_render_text(struct MTFace *tface, int mode,
+       const char *textstr, int textlen, unsigned int *col,
+       float *v1, float *v2, float *v3, float *v4, int glattrib);
+
+/* Mipmap settings
+ * - these will free textures on changes */
+
+void GPU_set_mipmap(int mipmap);
+void GPU_set_linear_mipmap(int linear);
+void GPU_paint_set_mipmap(int mipmap);
+
+/* Image updates and free
+ * - these deal with images bound as opengl textures */
+
+void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h);
+void GPU_update_images_framechange(void);
+int GPU_update_image_time(struct Image *ima, double time);
+int GPU_verify_image(struct Image *ima, int tftile, int tfmode, int compare);
+void GPU_free_image(struct Image *ima);
+void GPU_free_images(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
new file mode 100644 (file)
index 0000000..d3faa81
--- /dev/null
@@ -0,0 +1,144 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This shader 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 shader 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 shader; 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_EXTENSIONS_H
+#define GPU_EXTENSIONS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* GPU extensions support */
+
+struct Image;
+struct ImageUser;
+
+struct GPUTexture;
+typedef struct GPUTexture GPUTexture;
+
+struct GPUFrameBuffer;
+typedef struct GPUFrameBuffer GPUFrameBuffer;
+
+struct GPUShader;
+typedef struct GPUShader GPUShader;
+
+void GPU_extensions_init(void); /* call this before running any of the functions below */
+void GPU_extensions_exit(void);
+int GPU_extensions_minimum_support(void);
+int GPU_print_error(char *str);
+
+/* GPU Texture
+   - always returns unsigned char RGBA textures
+   - if texture with non square dimensions is created, depending on the
+     graphics card capabilities the texture may actually be stored in a
+        larger texture with power of two dimensions. the actual dimensions
+        may be querd with GPU_texture_opengl_width/height. GPU_texture_coord_2f
+        calls glTexCoord2f with the coordinates adjust for this.
+   - can use reference counting:
+       - reference counter after GPU_texture_create is 1
+       - GPU_texture_ref increases by one
+       - GPU_texture_free decreases by one, and frees if 0
+       - if created with from_blender, will not free the texture
+*/
+
+GPUTexture *GPU_texture_create_1D(int w, float *pixels);
+GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels);
+GPUTexture *GPU_texture_create_depth(int w, int h);
+GPUTexture *GPU_texture_from_blender(struct Image *ima,
+       struct ImageUser *iuser, double time);
+void GPU_texture_free(GPUTexture *tex);
+
+void GPU_texture_ref(GPUTexture *tex);
+
+void GPU_texture_bind(GPUTexture *tex, int number);
+void GPU_texture_unbind(GPUTexture *tex);
+
+GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
+
+int GPU_texture_target(GPUTexture *tex);
+int GPU_texture_opengl_width(GPUTexture *tex);
+int GPU_texture_opengl_height(GPUTexture *tex);
+
+/* GPU Framebuffer
+   - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
+     multiple FBO's may be created, to get around limitations on the number
+        of attached textures and the dimension requirements.
+   - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
+     be called before rendering to the window framebuffer again */
+
+GPUFrameBuffer *GPU_framebuffer_create();
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex);
+void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex);
+void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex);
+void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
+void GPU_framebuffer_free(GPUFrameBuffer *fb);
+
+void GPU_framebuffer_restore();
+
+/* GPU Shader
+   - only for fragment shaders now
+   - must call texture bind before setting a texture as uniform! */
+
+GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUShader *lib);
+GPUShader *GPU_shader_create_lib(const char *code);
+void GPU_shader_free(GPUShader *shader);
+
+void GPU_shader_bind(GPUShader *shader);
+void GPU_shader_unbind();
+
+int GPU_shader_get_uniform(GPUShader *shader, char *name);
+void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
+       int arraysize, float *value);
+void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
+
+int GPU_shader_get_attribute(GPUShader *shader, char *name);
+
+/* Vertex attributes for shaders */
+
+#define GPU_MAX_ATTRIB         32
+
+typedef struct GPUVertexAttribs {
+       struct {
+               int type;
+               int glindex;
+               char name[32];
+       } layer[GPU_MAX_ATTRIB];
+
+       int totlayer;
+} GPUVertexAttribs;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
new file mode 100644 (file)
index 0000000..560421f
--- /dev/null
@@ -0,0 +1,169 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This shader 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 shader 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 shader; 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_MATERIAL__
+#define __GPU_MATERIAL__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Image;
+struct ImageUser;
+struct Material;
+struct Object;
+struct Lamp;
+struct bNode;
+struct LinkNode;
+struct Scene;
+struct GPUVertexAttribs;
+struct GPUNode;
+struct GPUNodeLink;
+struct GPUNodeStack;
+struct GPUMaterial;
+struct GPUTexture;
+struct GPULamp;
+
+typedef struct GPUNode GPUNode;
+typedef struct GPUNodeLink GPUNodeLink;
+typedef struct GPUMaterial GPUMaterial;
+typedef struct GPULamp GPULamp;
+
+/* Functions to create GPU Materials nodes */
+
+typedef enum GPUType {
+       GPU_NONE = 0,
+       GPU_FLOAT = 1,
+       GPU_VEC2 = 2,
+       GPU_VEC3 = 3,
+       GPU_VEC4 = 4,
+       GPU_MAT3 = 9,
+       GPU_MAT4 = 16,
+       GPU_TEX1D = 1001,
+       GPU_TEX2D = 1002,
+       GPU_SHADOW2D = 1003,
+       GPU_ATTRIB = 3001
+} GPUType;
+
+typedef enum GPUBuiltin {
+       GPU_VIEW_MATRIX = 1,
+       GPU_OBJECT_MATRIX = 2,
+       GPU_INVERSE_VIEW_MATRIX = 4,
+       GPU_INVERSE_OBJECT_MATRIX = 8,
+       GPU_VIEW_POSITION = 16,
+       GPU_VIEW_NORMAL = 32,
+       GPU_OBCOLOR = 64
+} GPUBuiltin;
+
+typedef enum GPUBlendMode {
+       GPU_BLEND_SOLID = 0,
+       GPU_BLEND_ADD = 1,
+       GPU_BLEND_ALPHA = 2,
+       GPU_BLEND_CLIP = 4
+} GPUBlendMode;
+
+typedef struct GPUNodeStack {
+       GPUType type;
+       char *name;
+       float vec[4];
+       struct GPUNodeLink *link;
+       short hasinput;
+       short hasoutput;
+       short sockettype;
+} GPUNodeStack;
+
+GPUNodeLink *GPU_attribute(int type, char *name);
+GPUNodeLink *GPU_uniform(float *num);
+GPUNodeLink *GPU_dynamic_uniform(float *num);
+GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser);
+GPUNodeLink *GPU_texture(int size, float *pixels);
+GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex);
+GPUNodeLink *GPU_socket(GPUNodeStack *sock);
+GPUNodeLink *GPU_builtin(GPUBuiltin builtin);
+
+int GPU_link(GPUMaterial *mat, char *name, ...);
+int GPU_stack_link(GPUMaterial *mat, char *name, GPUNodeStack *in, GPUNodeStack *out, ...);
+
+void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link);
+void GPU_material_enable_alpha(GPUMaterial *material);
+GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[4]);
+
+/* High level functions to create and use GPU materials */
+
+GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma);
+void GPU_material_free(struct Material *ma);
+
+void GPU_materials_free();
+
+void GPU_material_bind(GPUMaterial *material, int lay, double time);
+void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]);
+void GPU_material_unbind(GPUMaterial *material);
+int GPU_material_bound(GPUMaterial *material);
+
+void GPU_material_vertex_attributes(GPUMaterial *material,
+       struct GPUVertexAttribs *attrib);
+
+/* Exported shading */
+
+typedef struct GPUShadeInput {
+       GPUMaterial *gpumat;
+       struct Material *mat;
+
+       GPUNodeLink *rgb, *specrgb, *vn, *view, *vcol, *ref;
+       GPUNodeLink *alpha, *refl, *spec, *emit, *har, *amb;
+} GPUShadeInput;
+
+typedef struct GPUShadeResult {
+       GPUNodeLink *diff, *spec, *combined, *alpha;
+} GPUShadeResult;
+
+void GPU_shadeinput_set(GPUMaterial *mat, struct Material *ma, GPUShadeInput *shi);
+void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr);
+
+/* Lamps */
+
+GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
+void GPU_lamp_free(struct Object *ob);
+
+int GPU_lamp_has_shadow_buffer(GPULamp *lamp);
+void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4]);
+void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp);
+
+void GPU_lamp_update(GPULamp *lamp, float obmat[][4]);
+int GPU_lamp_shadow_layer(GPULamp *lamp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__GPU_MATERIAL__*/
+
diff --git a/source/blender/gpu/Makefile b/source/blender/gpu/Makefile
new file mode 100644 (file)
index 0000000..b9bde14
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL 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) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+SOURCEDIR = source/blender/gpu
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
new file mode 100644 (file)
index 0000000..8ccd4b7
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('intern/*.c')
+
+incs = '../blenlib ../blenkernel ../makesdna ../include'
+incs += ' #/extern/glew/include #intern/guardedalloc ../imbuf .'
+
+incs += ' ' + env['BF_OPENGL_INC']
+
+env.BlenderLib ( 'bf_gpu', sources, Split(incs), [], libtype=['core', 'player'], priority=[65, 20] )
diff --git a/source/blender/gpu/intern/Makefile b/source/blender/gpu/intern/Makefile
new file mode 100644 (file)
index 0000000..733ee3f
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL 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) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+
+LIBNAME = gpu
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+    CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I../
+
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
new file mode 100644 (file)
index 0000000..b628591
--- /dev/null
@@ -0,0 +1,1439 @@
+/**
+ * $Id$
+ *
+ * ***** 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 "GL/glew.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_customdata_types.h"
+#include "DNA_image_types.h"
+#include "DNA_listBase.h"
+#include "DNA_material_types.h"
+
+#include "BLI_dynstr.h"
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_heap.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "GPU_material.h"
+#include "GPU_extensions.h"
+
+#include "gpu_codegen.h"
+
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+#ifndef vsnprintf
+#define _vsnprintf vsnprintf
+#endif
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
+#endif
+
+extern char datatoc_gpu_shader_material_glsl[];
+extern char datatoc_gpu_shader_vertex_glsl[];
+
+/* structs and defines */
+
+typedef enum GPUDataSource {
+       GPU_SOURCE_VEC_UNIFORM,
+       GPU_SOURCE_BUILTIN,
+       GPU_SOURCE_TEX_PIXEL,
+       GPU_SOURCE_TEX,
+       GPU_SOURCE_ATTRIB
+} GPUDataSource;
+
+static char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
+       0, 0, 0, 0, "mat3", 0, 0, 0, 0, 0, 0, "mat4"};
+
+struct GPUNode {
+       struct GPUNode *next, *prev;
+
+       char *name;
+       int tag;
+
+       ListBase inputs;
+       ListBase outputs;
+};
+
+struct GPUNodeLink {
+       GPUNodeStack *socket;
+
+       int attribtype;
+       char *attribname;
+
+       int image;
+
+       int texture;
+       int texturesize;
+
+       void *ptr1, *ptr2;
+
+       int dynamic;
+
+       int type;
+       int users;
+
+       GPUTexture *dynamictex;
+
+       GPUBuiltin builtin;
+
+       struct GPUOutput *output;
+};
+
+typedef struct GPUOutput {
+       struct GPUOutput *next, *prev;
+
+       GPUNode *node;
+       int type;                               /* data type = length of vector/matrix */
+       GPUNodeLink *link;              /* output link */
+       int id;                                 /* unique id as created by code generator */
+} GPUOutput;
+
+typedef struct GPUInput {
+       struct GPUInput *next, *prev;
+
+       GPUNode *node;
+
+       int type;                               /* datatype */
+       int source;                             /* data source */
+
+       int id;                                 /* unique id as created by code generator */
+       int texid;                              /* number for multitexture */
+       int attribid;                   /* id for vertex attributes */
+       int bindtex;                    /* input is responsible for binding the texture? */
+       int definetex;                  /* input is responsible for defining the pixel? */
+       int textarget;                  /* GL_TEXTURE_* */
+       int textype;                    /* datatype */
+
+       struct Image *ima;              /* image */
+       struct ImageUser *iuser;/* image user */
+       float *dynamicvec;              /* vector data in case it is dynamic */
+       GPUTexture *tex;                /* input texture, only set at runtime */
+       int shaderloc;                  /* id from opengl */
+       char shadername[32];    /* name in shader */
+
+       float vec[16];                  /* vector data */
+       GPUNodeLink *link;
+       int dynamictex;                 /* dynamic? */
+       int attribtype;                 /* attribute type */
+       char attribname[32];    /* attribute name */
+       int attribfirst;                /* this is the first one that is bound */
+       GPUBuiltin builtin;             /* builtin uniform */
+} GPUInput;
+
+struct GPUPass {
+       struct GPUPass *next, *prev;
+
+       ListBase inputs;
+       struct GPUOutput *output;
+       struct GPUShader *shader;
+};
+
+/* Strings utility */
+
+static void BLI_dynstr_printf(DynStr *dynstr, const char *format, ...)
+{
+       va_list args;
+       int retval;
+       char str[2048];
+
+       va_start(args, format);
+       retval = vsnprintf(str, sizeof(str), format, args);
+       va_end(args);
+
+       if (retval >= sizeof(str))
+               fprintf(stderr, "BLI_dynstr_printf: limit exceeded\n");
+       else
+               BLI_dynstr_append(dynstr, str);
+}
+
+/* GLSL code parsing for finding function definitions.
+ * These are stored in a hash for lookup when creating a material. */
+
+static GHash *FUNCTION_HASH= NULL;
+static char *FUNCTION_PROTOTYPES= NULL;
+static GPUShader *FUNCTION_LIB= NULL;
+
+static int gpu_str_prefix(char *str, char *prefix)
+{
+       while(*str && *prefix) {
+               if(*str != *prefix)
+                       return 0;
+
+               str++;
+               prefix++;
+       }
+       
+       return (*prefix == '\0');
+}
+
+static char *gpu_str_skip_token(char *str, char *token, int max)
+{
+       int len = 0;
+
+       /* skip a variable/function name */
+       while(*str) {
+               if(ELEM6(*str, ' ', '(', ')', ',', '\t', '\n'))
+                       break;
+               else {
+                       if(token && len < max-1) {
+                               *token= *str;
+                               token++;
+                               len++;
+                       }
+                       str++;
+               }
+       }
+
+       if(token)
+               *token= '\0';
+
+       /* skip the next special characters:
+        * note the missing ')' */
+       while(*str) {
+               if(ELEM5(*str, ' ', '(', ',', '\t', '\n'))
+                       str++;
+               else
+                       break;
+       }
+
+       return str;
+}
+
+static void gpu_parse_functions_string(GHash *hash, char *code)
+{
+       GPUFunction *function;
+       int i, type, qual;
+
+       while((code = strstr(code, "void "))) {
+               function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
+
+               code = gpu_str_skip_token(code, NULL, 0);
+               code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
+
+               /* get parameters */
+               while(*code && *code != ')') {
+                       /* test if it's an input or output */
+                       qual = FUNCTION_QUAL_IN;
+                       if(gpu_str_prefix(code, "out "))
+                               qual = FUNCTION_QUAL_OUT;
+                       if(gpu_str_prefix(code, "inout "))
+                               qual = FUNCTION_QUAL_INOUT;
+                       if((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in "))
+                               code = gpu_str_skip_token(code, NULL, 0);
+
+                       /* test for type */
+                       type= 0;
+                       for(i=1; i<=16; i++) {
+                               if(GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
+                                       type= i;
+                                       break;
+                               }
+                       }
+
+                       if(!type && gpu_str_prefix(code, "sampler2DShadow"))
+                               type= GPU_SHADOW2D;
+                       if(!type && gpu_str_prefix(code, "sampler1D"))
+                               type= GPU_TEX1D;
+                       if(!type && gpu_str_prefix(code, "sampler2D"))
+                               type= GPU_TEX2D;
+
+                       if(type) {
+                               /* add paramater */
+                               code = gpu_str_skip_token(code, NULL, 0);
+                               code = gpu_str_skip_token(code, NULL, 0);
+                               function->paramqual[function->totparam]= qual;
+                               function->paramtype[function->totparam]= type;
+                               function->totparam++;
+                       }
+                       else {
+                               fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
+                               break;
+                       }
+               }
+
+               if(strlen(function->name) == 0 || function->totparam == 0) {
+                       fprintf(stderr, "GPU functions parse error.\n");
+                       MEM_freeN(function);
+                       break;
+               }
+
+               BLI_ghash_insert(hash, function->name, function);
+       }
+}
+
+static char *gpu_generate_function_prototyps(GHash *hash)
+{
+       DynStr *ds = BLI_dynstr_new();
+       GHashIterator *ghi;
+       GPUFunction *function;
+       char *name, *prototypes;
+       int a;
+       
+       /* automatically generate function prototypes to add to the top of the
+        * generated code, to avoid have to add the actual code & recompile all */
+       ghi = BLI_ghashIterator_new(hash);
+
+       for(; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
+               name = BLI_ghashIterator_getValue(ghi);
+               function = BLI_ghashIterator_getValue(ghi);
+
+               BLI_dynstr_printf(ds, "void %s(", name);
+               for(a=0; a<function->totparam; a++) {
+                       if(function->paramqual[a] == FUNCTION_QUAL_OUT)
+                               BLI_dynstr_append(ds, "out ");
+                       else if(function->paramqual[a] == FUNCTION_QUAL_INOUT)
+                               BLI_dynstr_append(ds, "inout ");
+
+                       if(function->paramtype[a] == GPU_TEX1D)
+                               BLI_dynstr_append(ds, "sampler1D");
+                       else if(function->paramtype[a] == GPU_TEX2D)
+                               BLI_dynstr_append(ds, "sampler2D");
+                       else if(function->paramtype[a] == GPU_SHADOW2D)
+                               BLI_dynstr_append(ds, "sampler2DShadow");
+                       else
+                               BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
+                               
+                       BLI_dynstr_printf(ds, " param%d", a);
+                       
+                       if(a != function->totparam-1)
+                               BLI_dynstr_append(ds, ", ");
+               }
+               BLI_dynstr_append(ds, ");\n");
+       }
+
+       BLI_dynstr_append(ds, "\n");
+
+       prototypes = BLI_dynstr_get_cstring(ds);
+       BLI_dynstr_free(ds);
+
+       return prototypes;
+}
+
+GPUFunction *GPU_lookup_function(char *name)
+{
+       if(!FUNCTION_HASH) {
+               FUNCTION_HASH = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
+               gpu_parse_functions_string(FUNCTION_HASH, datatoc_gpu_shader_material_glsl);
+               FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH);
+               FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl);
+       }
+
+       return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, name);
+}
+
+void GPU_extensions_exit(void)
+{
+       extern Material defmaterial;    // render module abuse...
+
+       if(defmaterial.gpumaterial.first)
+               GPU_material_free(&defmaterial);
+
+       if(FUNCTION_HASH) {
+               BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN);
+               FUNCTION_HASH = NULL;
+       }
+       if(FUNCTION_PROTOTYPES) {
+               MEM_freeN(FUNCTION_PROTOTYPES);
+               FUNCTION_PROTOTYPES = NULL;
+       }
+       if(FUNCTION_LIB) {
+               GPU_shader_free(FUNCTION_LIB);
+               FUNCTION_LIB = NULL;
+       }
+}
+
+/* GLSL code generation */
+
+static void codegen_convert_datatype(DynStr *ds, int from, int to, char *tmp, int id)
+{
+       char name[1024];
+
+       snprintf(name, sizeof(name), "%s%d", tmp, id);
+
+       if (from == to) {
+               BLI_dynstr_append(ds, name);
+       }
+       else if (to == GPU_FLOAT) {
+               if (from == GPU_VEC4)
+                       BLI_dynstr_printf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
+               else if (from == GPU_VEC3)
+                       BLI_dynstr_printf(ds, "dot(%s, vec3(0.33))", name);
+               else if (from == GPU_VEC2)
+                       BLI_dynstr_printf(ds, "%s.r", name);
+       }
+       else if (to == GPU_VEC2) {
+               if (from == GPU_VEC4)
+                       BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
+               else if (from == GPU_VEC3)
+                       BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
+               else if (from == GPU_FLOAT)
+                       BLI_dynstr_printf(ds, "vec2(%s, 1.0)", name);
+       }
+       else if (to == GPU_VEC3) {
+               if (from == GPU_VEC4)
+                       BLI_dynstr_printf(ds, "%s.rgb", name);
+               else if (from == GPU_VEC2)
+                       BLI_dynstr_printf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name);
+               else if (from == GPU_FLOAT)
+                       BLI_dynstr_printf(ds, "vec3(%s, %s, %s)", name, name, name);
+       }
+       else {
+               if (from == GPU_VEC3)
+                       BLI_dynstr_printf(ds, "vec4(%s, 1.0)", name);
+               else if (from == GPU_VEC2)
+                       BLI_dynstr_printf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
+               else if (from == GPU_FLOAT)
+                       BLI_dynstr_printf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
+       }
+}
+
+static void codegen_print_datatype(DynStr *ds, int type, float *data)
+{
+       int i;
+
+       BLI_dynstr_printf(ds, "%s(", GPU_DATATYPE_STR[type]);
+
+       for(i=0; i<type; i++) {
+               BLI_dynstr_printf(ds, "%f", data[i]);
+               if(i == type-1)
+                       BLI_dynstr_append(ds, ")");
+               else
+                       BLI_dynstr_append(ds, ", ");
+       }
+}
+
+static int codegen_input_has_texture(GPUInput *input)
+{
+       if (input->link)
+               return 0;
+       else if(input->ima)
+               return 1;
+       else
+               return input->tex != 0;
+}
+
+char *GPU_builtin_name(GPUBuiltin builtin)
+{
+       if(builtin == GPU_VIEW_MATRIX)
+               return "unfviewmat";
+       else if(builtin == GPU_OBJECT_MATRIX)
+               return "unfobmat";
+       else if(builtin == GPU_INVERSE_VIEW_MATRIX)
+               return "unfinvviewmat";
+       else if(builtin == GPU_INVERSE_OBJECT_MATRIX)
+               return "unfinvobmat";
+       else if(builtin == GPU_VIEW_POSITION)
+               return "varposition";
+       else if(builtin == GPU_VIEW_NORMAL)
+               return "varnormal";
+       else if(builtin == GPU_OBCOLOR)
+               return "unfobcolor";
+       else
+               return "";
+}
+
+static void codegen_set_unique_ids(ListBase *nodes)
+{
+       GHash *bindhash, *definehash;
+       GPUNode *node;
+       GPUInput *input;
+       GPUOutput *output;
+       int id = 1, texid = 0;
+
+       bindhash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+       definehash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+       for (node=nodes->first; node; node=node->next) {
+               for (input=node->inputs.first; input; input=input->next) {
+                       /* set id for unique names of uniform variables */
+                       input->id = id++;
+                       input->bindtex = 0;
+                       input->definetex = 0;
+
+                       /* set texid used for settings texture slot with multitexture */
+                       if (codegen_input_has_texture(input) &&
+                           ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL))) {
+                               if (input->link) {
+                                       /* input is texture from buffer, assign only one texid per
+                                          buffer to avoid sampling the same texture twice */
+                                       if (!BLI_ghash_haskey(bindhash, input->link)) {
+                                               input->texid = texid++;
+                                               input->bindtex = 1;
+                                               BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid));
+                                       }
+                                       else
+                                               input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link));
+                               }
+                               else if(input->ima) {
+                                       /* input is texture from image, assign only one texid per
+                                          buffer to avoid sampling the same texture twice */
+                                       if (!BLI_ghash_haskey(bindhash, input->ima)) {
+                                               input->texid = texid++;
+                                               input->bindtex = 1;
+                                               BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid));
+                                       }
+                                       else
+                                               input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima));
+                               }
+                               else {
+                                       /* input is user created texture, we know there there is
+                                          only one, so assign new texid */
+                                       input->bindtex = 1;
+                                       input->texid = texid++;
+                               }
+
+                               /* make sure this pixel is defined exactly once */
+                               if (input->source == GPU_SOURCE_TEX_PIXEL) {
+                                       if(input->ima) {
+                                               if (!BLI_ghash_haskey(definehash, input->ima)) {
+                                                       input->definetex = 1;
+                                                       BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
+                                               }
+                                       }
+                                       else {
+                                               if (!BLI_ghash_haskey(definehash, input->link)) {
+                                                       input->definetex = 1;
+                                                       BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               for (output=node->outputs.first; output; output=output->next)
+                       /* set id for unique names of tmp variables storing output */
+                       output->id = id++;
+       }
+
+       BLI_ghash_free(bindhash, NULL, NULL);
+       BLI_ghash_free(definehash, NULL, NULL);
+}
+
+static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
+{
+       GPUNode *node;
+       GPUInput *input;
+       char *name;
+       int builtins = 0;
+
+       /* print uniforms */
+       for (node=nodes->first; node; node=node->next) {
+               for (input=node->inputs.first; input; input=input->next) {
+                       if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
+                               /* create exactly one sampler for each texture */
+                               if (codegen_input_has_texture(input) && input->bindtex)
+                                       BLI_dynstr_printf(ds, "uniform %s samp%d;\n",
+                                               (input->textype == GPU_TEX1D)? "sampler1D":
+                                               (input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow",
+                                               input->texid);
+                       }
+                       else if(input->source == GPU_SOURCE_BUILTIN) {
+                               /* only define each builting uniform/varying once */
+                               if(!(builtins & input->builtin)) {
+                                       builtins |= input->builtin;
+                                       name = GPU_builtin_name(input->builtin);
+
+                                       if(gpu_str_prefix(name, "unf")) {
+                                               BLI_dynstr_printf(ds, "uniform %s %s;\n",
+                                                       GPU_DATATYPE_STR[input->type], name);
+                                       }
+                                       else {
+                                               BLI_dynstr_printf(ds, "varying %s %s;\n",
+                                                       GPU_DATATYPE_STR[input->type], name);
+                                       }
+                               }
+                       }
+                       else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
+                               if(input->dynamicvec) {
+                                       /* only create uniforms for dynamic vectors */
+                                       BLI_dynstr_printf(ds, "uniform %s unf%d;\n",
+                                               GPU_DATATYPE_STR[input->type], input->id);
+                               }
+                               else {
+                                       /* for others use const so the compiler can do folding */
+                                       BLI_dynstr_printf(ds, "const %s cons%d = ",
+                                               GPU_DATATYPE_STR[input->type], input->id);
+                                       codegen_print_datatype(ds, input->type, input->vec);
+                                       BLI_dynstr_append(ds, ";\n");
+                               }
+                       }
+                       else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+                               BLI_dynstr_printf(ds, "varying %s var%d;\n",
+                                       GPU_DATATYPE_STR[input->type], input->attribid);
+                       }
+               }
+       }
+
+       BLI_dynstr_append(ds, "\n");
+}
+
+static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
+{
+       GPUNode *node;
+       GPUInput *input;
+       GPUOutput *output;
+
+       for (node=nodes->first; node; node=node->next) {
+               /* load pixels from textures */
+               for (input=node->inputs.first; input; input=input->next) {
+                       if (input->source == GPU_SOURCE_TEX_PIXEL) {
+                               if (codegen_input_has_texture(input) && input->definetex) {
+                                       BLI_dynstr_printf(ds, "\tvec4 tex%d = texture2D(", input->texid);
+                                       BLI_dynstr_printf(ds, "samp%d, gl_TexCoord[%d].st);\n",
+                                               input->texid, input->texid);
+                               }
+                       }
+               }
+
+               /* declare temporary variables for node output storage */
+               for (output=node->outputs.first; output; output=output->next)
+                       BLI_dynstr_printf(ds, "\t%s tmp%d;\n",
+                               GPU_DATATYPE_STR[output->type], output->id);
+       }
+
+       BLI_dynstr_append(ds, "\n");
+}
+
+static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
+{
+       GPUNode *node;
+       GPUInput *input;
+       GPUOutput *output;
+
+       for (node=nodes->first; node; node=node->next) {
+               BLI_dynstr_printf(ds, "\t%s(", node->name);
+               
+               for (input=node->inputs.first; input; input=input->next) {
+                       if (input->source == GPU_SOURCE_TEX) {
+                               BLI_dynstr_printf(ds, "samp%d", input->texid);
+                               if (input->link)
+                                       BLI_dynstr_printf(ds, ", gl_TexCoord[%d].st", input->texid);
+                       }
+                       else if (input->source == GPU_SOURCE_TEX_PIXEL) {
+                               if (input->link && input->link->output)
+                                       codegen_convert_datatype(ds, input->link->output->type, input->type,
+                                               "tmp", input->link->output->id);
+                               else
+                                       codegen_convert_datatype(ds, input->link->output->type, input->type,
+                                               "tex", input->texid);
+                       }
+                       else if(input->source == GPU_SOURCE_BUILTIN)
+                               BLI_dynstr_printf(ds, "%s", GPU_builtin_name(input->builtin));
+                       else if(input->source == GPU_SOURCE_VEC_UNIFORM) {
+                               if(input->dynamicvec)
+                                       BLI_dynstr_printf(ds, "unf%d", input->id);
+                               else
+                                       BLI_dynstr_printf(ds, "cons%d", input->id);
+                       }
+                       else if (input->source == GPU_SOURCE_ATTRIB)
+                               BLI_dynstr_printf(ds, "var%d", input->attribid);
+
+                       BLI_dynstr_append(ds, ", ");
+               }
+
+               for (output=node->outputs.first; output; output=output->next) {
+                       BLI_dynstr_printf(ds, "tmp%d", output->id);
+                       if (output->next)
+                               BLI_dynstr_append(ds, ", ");
+               }
+
+               BLI_dynstr_append(ds, ");\n");
+       }
+
+       BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
+       codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
+       BLI_dynstr_append(ds, ";\n");
+}
+
+static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *name)
+{
+       DynStr *ds = BLI_dynstr_new();
+       char *code;
+
+       BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);
+
+       codegen_set_unique_ids(nodes);
+       codegen_print_uniforms_functions(ds, nodes);
+
+       //if(G.f & G_DEBUG)
+       //      BLI_dynstr_printf(ds, "/* %s */\n", name);
+
+       BLI_dynstr_append(ds, "void main(void)\n");
+       BLI_dynstr_append(ds, "{\n");
+
+       codegen_declare_tmps(ds, nodes);
+       codegen_call_functions(ds, nodes, output);
+
+       BLI_dynstr_append(ds, "}\n");
+
+       /* create shader */
+       code = BLI_dynstr_get_cstring(ds);
+       BLI_dynstr_free(ds);
+
+       //if(G.f & G_DEBUG) printf("%s\n", code);
+
+       return code;
+}
+
+static char *code_generate_vertex(ListBase *nodes)
+{
+       DynStr *ds = BLI_dynstr_new();
+       GPUNode *node;
+       GPUInput *input;
+       char *code;
+       
+       for (node=nodes->first; node; node=node->next) {
+               for (input=node->inputs.first; input; input=input->next) {
+                       if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+                               BLI_dynstr_printf(ds, "attribute %s att%d;\n",
+                                       GPU_DATATYPE_STR[input->type], input->attribid);
+                               BLI_dynstr_printf(ds, "varying %s var%d;\n",
+                                       GPU_DATATYPE_STR[input->type], input->attribid);
+                       }
+               }
+       }
+
+       BLI_dynstr_append(ds, "\n");
+       BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
+
+       for (node=nodes->first; node; node=node->next)
+               for (input=node->inputs.first; input; input=input->next)
+                       if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+                               if(input->attribtype == CD_TANGENT) /* silly exception */
+                                       BLI_dynstr_printf(ds, "\tvar%d = gl_NormalMatrix * ", input->attribid);
+                               else
+                                       BLI_dynstr_printf(ds, "\tvar%d = ", input->attribid);
+
+                               BLI_dynstr_printf(ds, "att%d;\n", input->attribid);
+                       }
+
+       BLI_dynstr_append(ds, "}\n\n");
+
+       code = BLI_dynstr_get_cstring(ds);
+
+       BLI_dynstr_free(ds);
+
+       //if(G.f & G_DEBUG) printf("%s\n", code);
+
+       return code;
+}
+
+/* GPU pass binding/unbinding */
+
+GPUShader *GPU_pass_shader(GPUPass *pass)
+{
+       return pass->shader;
+}
+
+void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
+{
+       GPUShader *shader = pass->shader;
+       GPUNode *node;
+       GPUInput *next, *input;
+       ListBase *inputs = &pass->inputs;
+       int extract, z;
+
+       memset(inputs, 0, sizeof(*inputs));
+
+       if(!shader)
+               return;
+
+       GPU_shader_bind(shader);
+
+       for (node=nodes->first; node; node=node->next) {
+               z = 0;
+               for (input=node->inputs.first; input; input=next, z++) {
+                       next = input->next;
+
+                       /* attributes don't need to be bound, they already have
+                        * an id that the drawing functions will use */
+                       if(input->source == GPU_SOURCE_ATTRIB ||
+                          input->source == GPU_SOURCE_BUILTIN)
+                               continue;
+
+                       if (input->ima || input->tex)
+                               snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
+                       else
+                               snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
+
+                       /* pass non-dynamic uniforms to opengl */
+                       extract = 0;
+
+                       if(input->ima || input->tex) {
+                               if (input->bindtex)
+                                       extract = 1;
+                       }
+                       else if(input->dynamicvec)
+                               extract = 1;
+
+                       if(extract)
+                               input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
+
+                       /* extract nodes */
+                       if(extract) {
+                               BLI_remlink(&node->inputs, input);
+                               BLI_addtail(inputs, input);
+                       }
+               }
+       }
+
+       GPU_shader_unbind(shader);
+}
+
+void GPU_pass_bind(GPUPass *pass, double time)
+{
+       GPUInput *input;
+       GPUShader *shader = pass->shader;
+       ListBase *inputs = &pass->inputs;
+
+       if (!shader)
+               return;
+
+       GPU_shader_bind(shader);
+
+       /* now bind the textures */
+       for (input=inputs->first; input; input=input->next) {
+               if (input->ima)
+                       input->tex = GPU_texture_from_blender(input->ima, input->iuser, time);
+
+               if(input->ima || input->tex) {
+                       if(input->tex) {
+                               GPU_texture_bind(input->tex, input->texid);
+                               GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
+                       }
+               }
+       }
+}
+
+void GPU_pass_update_uniforms(GPUPass *pass)
+{
+       GPUInput *input;
+       GPUShader *shader = pass->shader;
+       ListBase *inputs = &pass->inputs;
+
+       if (!shader)
+               return;
+
+       /* pass dynamic inputs to opengl, others were removed */
+       for (input=inputs->first; input; input=input->next)
+               if(!(input->ima || input->tex))
+                       GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
+                               input->dynamicvec);
+}
+
+void GPU_pass_unbind(GPUPass *pass)
+{
+       GPUInput *input;
+       GPUShader *shader = pass->shader;
+       ListBase *inputs = &pass->inputs;
+
+       if (!shader)
+               return;
+
+       for (input=inputs->first; input; input=input->next) {
+               if (input->tex)
+                       if(input->bindtex)
+                               GPU_texture_unbind(input->tex);
+               if (input->ima)
+                       input->tex = 0;
+       }
+       
+       GPU_shader_unbind(shader);
+}
+
+/* Node Link Functions */
+
+GPUNodeLink *GPU_node_link_create(int type)
+{
+       GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
+       link->type = type;
+       link->users++;
+
+       return link;
+}
+
+void GPU_node_link_free(GPUNodeLink *link)
+{
+       link->users--;
+
+       if (link->users < 0)
+               fprintf(stderr, "GPU_node_link_free: negative refcount\n");
+       
+       if (link->users == 0) {
+               if (link->output)
+                       link->output->link = NULL;
+               MEM_freeN(link);
+       }
+}
+
+/* Node Functions */
+
+GPUNode *GPU_node_begin(char *name)
+{
+       GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
+
+       node->name = name;
+
+       return node;
+}
+
+void GPU_node_end(GPUNode *node)
+{
+       /* empty */
+}
+
+static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
+{
+       GPUInput *input;
+       GPUNode *outnode;
+       char *name;
+
+       if(link->output) {
+               outnode = link->output->node;
+               name = outnode->name;
+
+               if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
+                       input = MEM_dupallocN(outnode->inputs.first);
+                       input->type = type;
+                       if(input->link)
+                               input->link->users++;
+                       BLI_addtail(&node->inputs, input);
+                       return;
+               }
+       }
+       
+       input = MEM_callocN(sizeof(GPUInput), "GPUInput");
+       input->node = node;
+
+       if(link->builtin) {
+               /* builtin uniform */
+               input->type = type;
+               input->source = GPU_SOURCE_BUILTIN;
+               input->builtin = link->builtin;
+
+               MEM_freeN(link);
+       }
+       else if(link->output) {
+               /* link to a node output */
+               input->type = type;
+               input->source = GPU_SOURCE_TEX_PIXEL;
+               input->link = link;
+               link->users++;
+       }
+       else if(link->dynamictex) {
+               /* dynamic texture, GPUTexture is updated/deleted externally */
+               input->type = type;
+               input->source = GPU_SOURCE_TEX;
+
+               input->tex = link->dynamictex;
+               input->textarget = GL_TEXTURE_2D;
+               input->textype = type;
+               input->dynamictex = 1;
+               MEM_freeN(link);
+       }
+       else if(link->texture) {
+               /* small texture created on the fly, like for colorbands */
+               input->type = GPU_VEC4;
+               input->source = GPU_SOURCE_TEX;
+               input->textype = type;
+
+               if (type == GPU_TEX1D) {
+                       input->tex = GPU_texture_create_1D(link->texturesize, link->ptr1);
+                       input->textarget = GL_TEXTURE_1D;
+               }
+               else {
+                       input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2);
+                       input->textarget = GL_TEXTURE_2D;
+               }
+
+               MEM_freeN(link->ptr1);
+               MEM_freeN(link);
+       }
+       else if(link->image) {
+               /* blender image */
+               input->type = GPU_VEC4;
+               input->source = GPU_SOURCE_TEX;
+
+               input->ima = link->ptr1;
+               input->textarget = GL_TEXTURE_2D;
+               input->textype = GPU_TEX2D;
+               MEM_freeN(link);
+       }
+       else if(link->attribtype) {
+               /* vertex attribute */
+               input->type = type;
+               input->source = GPU_SOURCE_ATTRIB;
+
+               input->attribtype = link->attribtype;
+               BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
+               MEM_freeN(link);
+       }
+       else {
+               /* uniform vector */
+               input->type = type;
+               input->source = GPU_SOURCE_VEC_UNIFORM;
+
+               memcpy(input->vec, link->ptr1, type*sizeof(float));
+               if(link->dynamic)
+                       input->dynamicvec= link->ptr1;
+               MEM_freeN(link);
+       }
+
+       BLI_addtail(&node->inputs, input);
+}
+
+static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
+{
+       GPUNodeLink *link;
+
+       if(sock->link) {
+               gpu_node_input_link(node, sock->link, sock->type);
+       }
+       else {
+               link = GPU_node_link_create(0);
+               link->ptr1 = sock->vec;
+               gpu_node_input_link(node, link, sock->type);
+       }
+}
+
+void GPU_node_output(GPUNode *node, int type, char *name, GPUNodeLink **link)
+{
+       GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
+
+       output->type = type;
+       output->node = node;
+
+       if (link) {
+               *link = output->link = GPU_node_link_create(type);
+               output->link->output = output;
+
+               /* note: the caller owns the reference to the linkfer, GPUOutput
+                  merely points to it, and if the node is destroyed it will
+                  set that pointer to NULL */
+       }
+
+       BLI_addtail(&node->outputs, output);
+}
+
+void GPU_inputs_free(ListBase *inputs)
+{
+       GPUInput *input;
+
+       for(input=inputs->first; input; input=input->next) {
+               if(input->link)
+                       GPU_node_link_free(input->link);
+               else if(input->tex && !input->dynamictex)
+                       GPU_texture_free(input->tex);
+       }
+
+       BLI_freelistN(inputs);
+}
+
+void GPU_node_free(GPUNode *node)
+{
+       GPUOutput *output;
+
+       GPU_inputs_free(&node->inputs);
+
+       for (output=node->outputs.first; output; output=output->next)
+               if (output->link) {
+                       output->link->output = NULL;
+                       GPU_node_link_free(output->link);
+               }
+
+       BLI_freelistN(&node->outputs);
+       MEM_freeN(node);
+}
+
+void GPU_nodes_free(ListBase *nodes)
+{
+       GPUNode *node;
+
+       while (nodes->first) {
+               node = nodes->first;
+               BLI_remlink(nodes, node);
+               GPU_node_free(node);
+       }
+}
+
+/* vertex attributes */
+
+void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
+{
+       GPUNode *node;
+       GPUInput *input;
+       int a;
+
+       /* convert attributes requested by node inputs to an array of layers,
+        * checking for duplicates and assigning id's starting from zero. */
+
+       memset(attribs, 0, sizeof(*attribs));
+
+       for(node=nodes->first; node; node=node->next) {
+               for(input=node->inputs.first; input; input=input->next) {
+                       if(input->source == GPU_SOURCE_ATTRIB) {
+                               for(a=0; a<attribs->totlayer; a++) {
+                                       if(attribs->layer[a].type == input->attribtype &&
+                                               strcmp(attribs->layer[a].name, input->attribname) == 0)
+                                               break;
+                               }
+
+                               if(a == attribs->totlayer && a < GPU_MAX_ATTRIB) {
+                                       input->attribid = attribs->totlayer++;
+                                       input->attribfirst = 1;
+
+                                       attribs->layer[a].type = input->attribtype;
+                                       attribs->layer[a].glindex = input->attribid;
+                                       BLI_strncpy(attribs->layer[a].name, input->attribname,
+                                               sizeof(attribs->layer[a].name));
+                               }
+                               else
+                                       input->attribid = attribs->layer[a].glindex;
+                       }
+               }
+       }
+}
+
+void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
+{
+       GPUNode *node;
+       GPUInput *input;
+       
+       *builtin= 0;
+
+       for(node=nodes->first; node; node=node->next)
+               for(input=node->inputs.first; input; input=input->next)
+                       if(input->source == GPU_SOURCE_BUILTIN)
+                               *builtin |= input->builtin;
+}
+
+/* varargs linking  */
+
+GPUNodeLink *GPU_attribute(int type, char *name)
+{
+       GPUNodeLink *link = GPU_node_link_create(0);
+
+       link->attribtype= type;
+       link->attribname= name;
+
+       return link;
+}
+
+GPUNodeLink *GPU_uniform(float *num)
+{
+       GPUNodeLink *link = GPU_node_link_create(0);
+
+       link->ptr1= num;
+       link->ptr2= NULL;
+
+       return link;
+}
+
+GPUNodeLink *GPU_dynamic_uniform(float *num)
+{
+       GPUNodeLink *link = GPU_node_link_create(0);
+
+       link->ptr1= num;
+       link->ptr2= NULL;
+       link->dynamic= 1;
+
+       return link;
+}
+
+GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
+{
+       GPUNodeLink *link = GPU_node_link_create(0);
+
+       link->image= 1;
+       link->ptr1= ima;
+       link->ptr2= iuser;
+
+       return link;
+}
+
+GPUNodeLink *GPU_texture(int size, float *pixels)
+{
+       GPUNodeLink *link = GPU_node_link_create(0);
+
+       link->texture = 1;
+       link->texturesize = size;
+       link->ptr1= pixels;
+
+       return link;
+}
+
+GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex)
+{
+       GPUNodeLink *link = GPU_node_link_create(0);
+
+       link->dynamic = 1;
+       link->dynamictex = tex;
+
+       return link;
+}
+
+GPUNodeLink *GPU_socket(GPUNodeStack *sock)
+{
+       GPUNodeLink *link = GPU_node_link_create(0);
+
+       link->socket= sock;
+
+       return link;
+}
+
+GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
+{
+       GPUNodeLink *link = GPU_node_link_create(0);
+
+       link->builtin= builtin;
+
+       return link;
+}
+
+int GPU_link(GPUMaterial *mat, char *name, ...)
+{
+       GPUNode *node;
+       GPUFunction *function;
+       GPUNodeLink *link, **linkptr;
+       va_list params;
+       int i;
+
+       function = GPU_lookup_function(name);
+       if(!function) {
+               fprintf(stderr, "GPU failed to find function %s\n", name);
+               return 0;
+       }
+
+       node = GPU_node_begin(name);
+
+       va_start(params, name);
+       for(i=0; i<function->totparam; i++) {
+               if(function->paramqual[i] != FUNCTION_QUAL_IN) {
+                       linkptr= va_arg(params, GPUNodeLink**);
+                       GPU_node_output(node, function->paramtype[i], "", linkptr);
+               }
+               else {
+                       link= va_arg(params, GPUNodeLink*);
+                       gpu_node_input_link(node, link, function->paramtype[i]);
+               }
+       }
+       va_end(params);
+
+       GPU_node_end(node);
+
+       gpu_material_add_node(mat, node);
+
+       return 1;
+}
+
+int GPU_stack_link(GPUMaterial *mat, char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
+{
+       GPUNode *node;
+       GPUFunction *function;
+       GPUNodeLink *link, **linkptr;
+       va_list params;
+       int i, totin, totout;
+
+       function = GPU_lookup_function(name);
+       if(!function) {
+               fprintf(stderr, "GPU failed to find function %s\n", name);
+               return 0;
+       }
+
+       node = GPU_node_begin(name);
+       totin = 0;
+       totout = 0;
+
+       if(in) {
+               for(i = 0; in[i].type != GPU_NONE; i++) {
+                       gpu_node_input_socket(node, &in[i]);
+                       totin++;
+               }
+       }
+       
+       if(out) {
+               for(i = 0; out[i].type != GPU_NONE; i++) {
+                       GPU_node_output(node, out[i].type, out[i].name, &out[i].link);
+                       totout++;
+               }
+       }
+
+       va_start(params, out);
+       for(i=0; i<function->totparam; i++) {
+               if(function->paramqual[i] != FUNCTION_QUAL_IN) {
+                       if(totout == 0) {
+                               linkptr= va_arg(params, GPUNodeLink**);
+                               GPU_node_output(node, function->paramtype[i], "", linkptr);
+                       }
+                       else
+                               totout--;
+               }
+               else {
+                       if(totin == 0) {
+                               link= va_arg(params, GPUNodeLink*);
+                               if(link->socket)
+                                       gpu_node_input_socket(node, link->socket);
+                               else
+                                       gpu_node_input_link(node, link, function->paramtype[i]);
+                       }
+                       else
+                               totin--;
+               }
+       }
+       va_end(params);
+
+       GPU_node_end(node);
+
+       gpu_material_add_node(mat, node);
+       
+       return 1;
+}
+
+int GPU_link_changed(GPUNodeLink *link)
+{
+       GPUNode *node;
+       GPUInput *input;
+       char *name;
+
+       if(link->output) {
+               node = link->output->node;
+               name = node->name;
+
+               if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
+                       input = node->inputs.first;
+                       return (input->link != NULL);
+               }
+
+               return 1;
+       }
+       else
+               return 0;
+}
+
+/* Pass create/free */
+
+void gpu_nodes_tag(GPUNodeLink *link)
+{
+       GPUNode *node;
+       GPUInput *input;
+
+       if(!link->output)
+               return;
+
+       node = link->output->node;
+       if(node->tag)
+               return;
+       
+       node->tag= 1;
+       for(input=node->inputs.first; input; input=input->next)
+               if(input->link)
+                       gpu_nodes_tag(input->link);
+}
+
+void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
+{
+       GPUNode *node, *next;
+
+       for(node=nodes->first; node; node=node->next)
+               node->tag= 0;
+
+       gpu_nodes_tag(outlink);
+
+       for(node=nodes->first; node; node=next) {
+               next = node->next;
+
+               if(!node->tag) {
+                       BLI_remlink(nodes, node);
+                       GPU_node_free(node);
+               }
+       }
+}
+
+GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
+{
+       GPUShader *shader;
+       GPUPass *pass;
+       char *vertexcode, *fragmentcode;
+
+       if(!FUNCTION_LIB) {
+               GPU_nodes_free(nodes);
+               return NULL;
+       }
+
+       /* prune unused nodes */
+       gpu_nodes_prune(nodes, outlink);
+
+       gpu_nodes_get_vertex_attributes(nodes, attribs);
+       gpu_nodes_get_builtin_flag(nodes, builtins);
+
+       /* generate code and compile with opengl */
+       fragmentcode = code_generate_fragment(nodes, outlink->output, name);
+       vertexcode = code_generate_vertex(nodes);
+       shader = GPU_shader_create(vertexcode, fragmentcode, FUNCTION_LIB);
+       MEM_freeN(fragmentcode);
+       MEM_freeN(vertexcode);
+
+       /* failed? */
+       if (!shader) {
+               memset(attribs, 0, sizeof(*attribs));
+               memset(builtins, 0, sizeof(*builtins));
+               GPU_nodes_free(nodes);
+               return NULL;
+       }
+       
+       /* create pass */
+       pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
+
+       pass->output = outlink->output;
+       pass->shader = shader;
+
+       /* extract dynamic inputs and throw away nodes */
+       GPU_nodes_extract_dynamic_inputs(pass, nodes);
+       GPU_nodes_free(nodes);
+
+       return pass;
+}
+
+void GPU_pass_free(GPUPass *pass)
+{
+       GPU_shader_free(pass->shader);
+       GPU_inputs_free(&pass->inputs);
+       MEM_freeN(pass);
+}
+
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
new file mode 100644 (file)
index 0000000..53b52f2
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * $Id$
+ *
+ * ***** 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_CODEGEN_H__
+#define __GPU_CODEGEN_H__
+
+#include "DNA_listBase.h"
+
+struct ListBase;
+struct GPUShader;
+struct GPUOutput;
+struct GPUNode;
+struct GPUVertexAttribs;
+
+#define MAX_FUNCTION_NAME      64
+#define MAX_PARAMETER          32
+
+#define FUNCTION_QUAL_IN       0
+#define FUNCTION_QUAL_OUT      1
+#define FUNCTION_QUAL_INOUT    2
+
+typedef struct GPUFunction {
+       char name[MAX_FUNCTION_NAME];
+       int paramtype[MAX_PARAMETER];
+       int paramqual[MAX_PARAMETER];
+       int totparam;
+} GPUFunction;
+
+GPUFunction *GPU_lookup_function(char *name);
+
+/* Pass Generation
+   - Takes a list of nodes and a desired output, and makes a pass. This
+     will take ownership of the nodes and free them early if unused or
+        at the end if used.
+*/
+
+struct GPUPass;
+typedef struct GPUPass GPUPass;
+
+GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
+       struct GPUVertexAttribs *attribs, int *builtin, const char *name);
+
+struct GPUShader *GPU_pass_shader(GPUPass *pass);
+
+void GPU_pass_bind(GPUPass *pass, double time);
+void GPU_pass_update_uniforms(GPUPass *pass);
+void GPU_pass_unbind(GPUPass *pass);
+
+void GPU_pass_free(GPUPass *pass);
+
+/* Material calls */
+
+char *GPU_builtin_name(GPUBuiltin builtin);
+void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node);
+int GPU_link_changed(struct GPUNodeLink *link);
+
+#endif
+
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
new file mode 100644 (file)
index 0000000..3ff8e7f
--- /dev/null
@@ -0,0 +1,1167 @@
+/**
+ * $Id$
+ *
+ * ***** 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 "DNA_image_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BKE_bmfont.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+#include "GPU_draw.h"
+
+/* These are some obscure rendering functions shared between the
+ * game engine and the blender, in this module to avoid duplicaten
+ * and abstract them away from the rest a bit */
+
+/* Text Rendering */
+
+static void gpu_mcol(unsigned int ucol)
+{
+       /* mcol order is swapped */
+       char *cp= (char *)&ucol;
+       glColor3ub(cp[3], cp[2], cp[1]);
+}
+
+void GPU_render_text(MTFace *tface, int mode,
+       const char *textstr, int textlen, unsigned int *col,
+       float *v1, float *v2, float *v3, float *v4, int glattrib)
+{
+       if (mode & TF_BMFONT) {
+               Image* ima;
+               int characters, index, character;
+               float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
+
+               characters = textlen;
+
+               ima = (Image*)tface->tpage;
+               if (ima == NULL)
+                       characters = 0;
+
+               // color has been set
+               if (tface->mode & TF_OBCOL)
+                       col= NULL;
+               else if (!col)
+                       glColor3f(1.0f, 1.0f, 1.0f);
+
+               glPushMatrix();
+               for (index = 0; index < characters; index++) {
+                       float uv[4][2];
+
+                       // lets calculate offset stuff
+                       character = textstr[index];
+                       
+                       // space starts at offset 1
+                       // character = character - ' ' + 1;
+                       matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, &centery,
+                               &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
+
+                       uv[0][0] = (tface->uv[0][0] - centerx) * sizex + transx;
+                       uv[0][1] = (tface->uv[0][1] - centery) * sizey + transy;
+                       uv[1][0] = (tface->uv[1][0] - centerx) * sizex + transx;
+                       uv[1][1] = (tface->uv[1][1] - centery) * sizey + transy;
+                       uv[2][0] = (tface->uv[2][0] - centerx) * sizex + transx;
+                       uv[2][1] = (tface->uv[2][1] - centery) * sizey + transy;
+                       
+                       glBegin(GL_POLYGON);
+                       if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[0]);
+                       else glTexCoord2fv(uv[0]);
+                       if(col) gpu_mcol(col[0]);
+                       glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
+                       
+                       if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[1]);
+                       else glTexCoord2fv(uv[1]);
+                       if(col) gpu_mcol(col[1]);
+                       glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
+
+                       if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[2]);
+                       else glTexCoord2fv(uv[2]);
+                       if(col) gpu_mcol(col[2]);
+                       glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
+
+                       if(v4) {
+                               uv[3][0] = (tface->uv[3][0] - centerx) * sizex + transx;
+                               uv[3][1] = (tface->uv[3][1] - centery) * sizey + transy;
+
+                               if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[3]);
+                               else glTexCoord2fv(uv[3]);
+                               if(col) gpu_mcol(col[3]);
+                               glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
+                       }
+                       glEnd();
+
+                       glTranslatef(advance, 0.0, 0.0);
+               }
+               glPopMatrix();
+       }
+}
+
+/* Checking powers of two for images since opengl 1.x requires it */
+
+static int is_pow2(int num)
+{
+       /* (n&(n-1)) zeros the least significant bit of n */
+       return ((num)&(num-1))==0;
+}
+
+static int smaller_pow2(int num)
+{
+       while (!is_pow2(num))
+               num= num&(num-1);
+
+       return num;     
+}
+
+static int is_pow2_limit(int num)
+{
+       /* take texture clamping into account */
+       if (U.glreslimit != 0 && num > U.glreslimit)
+               return 0;
+
+       return ((num)&(num-1))==0;
+}
+
+static int smaller_pow2_limit(int num)
+{
+       /* take texture clamping into account */
+       if (U.glreslimit != 0 && num > U.glreslimit)
+               return U.glreslimit;
+
+       return smaller_pow2(num);
+}
+
+/* Current OpenGL state caching for GPU_set_tpage */
+
+static struct GPUTextureState {
+       int curtile, tile;
+       int curtilemode, tilemode;
+       int curtileXRep, tileXRep;
+       int curtileYRep, tileYRep;
+       Image *ima, *curima;
+
+       int domipmap, linearmipmap;
+
+       int alphamode;
+       MTFace *lasttface;
+} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, NULL};
+
+/* Mipmap settings */
+
+void GPU_set_mipmap(int mipmap)
+{
+       if (GTS.domipmap != (mipmap != 0)) {
+               GPU_free_images();
+               GTS.domipmap = mipmap != 0;
+       }
+}
+
+void GPU_set_linear_mipmap(int linear)
+{
+       if (GTS.linearmipmap != (linear != 0)) {
+               GPU_free_images();
+               GTS.linearmipmap = linear != 0;
+       }
+}
+
+static int gpu_get_mipmap(void)
+{
+       return GTS.domipmap && (!(G.f & G_TEXTUREPAINT));
+}
+
+static GLenum gpu_get_mipmap_filter()
+{
+       return GTS.linearmipmap? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
+}
+
+/* Set OpenGL state for an MTFace */
+
+static void gpu_make_repbind(Image *ima)
+{
+       ImBuf *ibuf;
+       
+       ibuf = BKE_image_get_ibuf(ima, NULL);
+       if(ibuf==NULL)
+               return;
+
+       if(ima->repbind) {
+               glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
+               MEM_freeN(ima->repbind);
+               ima->repbind= 0;
+               ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
+       }
+
+       ima->totbind= ima->xrep*ima->yrep;
+
+       if(ima->totbind>1)
+               ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
+}
+
+static void gpu_clear_tpage()
+{
+       if(GTS.lasttface==0)
+               return;
+       
+       GTS.lasttface= 0;
+       GTS.curtile= 0;
+       GTS.curima= 0;
+       if(GTS.curtilemode!=0) {
+               glMatrixMode(GL_TEXTURE);
+               glLoadIdentity();
+               glMatrixMode(GL_MODELVIEW);
+       }
+       GTS.curtilemode= 0;
+       GTS.curtileXRep=0;
+       GTS.curtileYRep=0;
+       GTS.alphamode= -1;
+       
+       glDisable(GL_BLEND);
+       glDisable(GL_TEXTURE_2D);
+       glDisable(GL_TEXTURE_GEN_S);
+       glDisable(GL_TEXTURE_GEN_T);
+       glDisable(GL_ALPHA_TEST);
+}
+
+static void gpu_set_blend_mode(GPUBlendMode blendmode)
+{
+       if(blendmode == GPU_BLEND_SOLID) {
+               glDisable(GL_BLEND);
+               glDisable(GL_ALPHA_TEST);
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       }
+       else if(blendmode==GPU_BLEND_ADD) {
+               glEnable(GL_BLEND);
+               glBlendFunc(GL_ONE, GL_ONE);
+               glDisable(GL_ALPHA_TEST);
+       }
+       else if(blendmode==GPU_BLEND_ALPHA) {
+               glEnable(GL_BLEND);
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               
+               /* if U.glalphaclip == 1.0, some cards go bonkers...
+                * turn off alpha test in this case */
+
+               /* added after 2.45 to clip alpha */
+               if(U.glalphaclip == 1.0) {
+                       glDisable(GL_ALPHA_TEST);
+               }
+               else {
+                       glEnable(GL_ALPHA_TEST);
+                       glAlphaFunc(GL_GREATER, U.glalphaclip);
+               }
+       }
+       else if(blendmode==GPU_BLEND_CLIP) {
+               glDisable(GL_BLEND); 
+               glEnable(GL_ALPHA_TEST);
+               glAlphaFunc(GL_GREATER, 0.5f);
+       }
+}
+
+static void gpu_verify_alpha_mode(MTFace *tface)
+{
+       /* verify alpha blending modes */
+       if(GTS.alphamode == tface->transp)
+               return;
+
+       gpu_set_blend_mode(tface->transp);
+       GTS.alphamode= tface->transp;
+}
+
+static void gpu_verify_reflection(Image *ima)
+{
+       if (ima && (ima->flag & IMA_REFLECT)) {
+               /* enable reflection mapping */
+               glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+               glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+
+               glEnable(GL_TEXTURE_GEN_S);
+               glEnable(GL_TEXTURE_GEN_T);
+       }
+       else {
+               /* disable reflection mapping */
+               glDisable(GL_TEXTURE_GEN_S);
+               glDisable(GL_TEXTURE_GEN_T);
+       }
+}
+
+int GPU_verify_image(Image *ima, int tftile, int tfmode, int compare)
+{
+       ImBuf *ibuf = NULL;
+       unsigned int *bind = NULL;
+       int rectw, recth, tpx=0, tpy=0, y;
+       unsigned int *rectrow, *tilerectrow;
+       unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL;
+       short texwindx, texwindy, texwinsx, texwinsy;
+
+       /* initialize tile mode and number of repeats */
+       GTS.ima = ima;
+       GTS.tilemode= (tfmode & TF_TILES) || (ima && (ima->tpageflag & IMA_TWINANIM));
+       GTS.tileXRep = 0;
+       GTS.tileYRep = 0;
+
+       /* setting current tile according to frame */
+       if(ima && (ima->tpageflag & IMA_TWINANIM))
+               GTS.tile= ima->lastframe;
+       else
+               GTS.tile= tftile;
+
+       if(ima) {
+               GTS.tileXRep = ima->xrep;
+               GTS.tileYRep = ima->yrep;
+       }
+
+       /* if same image & tile, we're done */
+       if(compare && ima == GTS.curima && GTS.curtile == GTS.tile &&
+          GTS.tilemode == GTS.curtilemode && GTS.curtileXRep == GTS.tileXRep &&
+          GTS.curtileYRep == GTS.tileYRep)
+               return (ima!=0);
+
+       /* if tiling mode or repeat changed, change texture matrix to fit */
+       if(GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep ||
+          GTS.curtileYRep != GTS.tileYRep) {
+
+               glMatrixMode(GL_TEXTURE);
+               glLoadIdentity();
+
+               if((tfmode & TF_TILES) && ima!=NULL)
+                       glScalef(ima->xrep, ima->yrep, 1.0);
+
+               glMatrixMode(GL_MODELVIEW);
+       }
+
+       /* check if we have a valid image */
+       if(ima==NULL || ima->ok==0)
+               return 0;
+
+       /* check if we have a valid image buffer */
+       ibuf= BKE_image_get_ibuf(ima, NULL);
+
+       if(ibuf==NULL)
+               return 0;
+
+       /* ensure we have a char buffer and not only float */
+       if ((ibuf->rect==NULL) && ibuf->rect_float)
+               IMB_rect_from_float(ibuf);
+
+       if(GTS.tilemode) {
+               /* tiled mode */
+               if(ima->repbind==0) gpu_make_repbind(ima);
+               if(GTS.tile>=ima->totbind) GTS.tile= 0;
+               
+               /* this happens when you change repeat buttons */
+               if(ima->repbind) bind= &ima->repbind[GTS.tile];
+               else bind= &ima->bindcode;
+               
+               if(*bind==0) {
+                       
+                       texwindx= ibuf->x/ima->xrep;
+                       texwindy= ibuf->y/ima->yrep;
+                       
+                       if(GTS.tile>=ima->xrep*ima->yrep)
+                               GTS.tile= ima->xrep*ima->yrep-1;
+       
+                       texwinsy= GTS.tile / ima->xrep;
+                       texwinsx= GTS.tile - texwinsy*ima->xrep;
+       
+                       texwinsx*= texwindx;
+                       texwinsy*= texwindy;
+       
+                       tpx= texwindx;
+                       tpy= texwindy;
+
+                       rect= ibuf->rect + texwinsy*ibuf->x + texwinsx;
+               }
+       }
+       else {
+               /* regular image mode */
+               bind= &ima->bindcode;
+               
+               if(*bind==0) {
+                       tpx= ibuf->x;
+                       tpy= ibuf->y;
+                       rect= ibuf->rect;
+               }
+       }
+
+       if(*bind != 0) {
+               /* enable opengl drawing with textures */
+               glBindTexture(GL_TEXTURE_2D, *bind);
+               return *bind;
+       }
+
+       rectw = tpx;
+       recth = tpy;
+
+       /* for tiles, copy only part of image into buffer */
+       if (GTS.tilemode) {
+               tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
+
+               for (y=0; y<recth; y++) {
+                       rectrow= &rect[y*ibuf->x];
+                       tilerectrow= &tilerect[y*rectw];
+                               
+                       memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
+               }
+                       
+               rect= tilerect;
+       }
+
+       /* scale if not a power of two */
+       if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) {
+               rectw= smaller_pow2_limit(rectw);
+               recth= smaller_pow2_limit(recth);
+               
+               scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
+               gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
+               rect= scalerect;
+       }
+
+       /* create image */
+       glGenTextures(1, (GLuint *)bind);
+       glBindTexture( GL_TEXTURE_2D, *bind);
+
+       if (!gpu_get_mipmap()) {
+               glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       }
+       else {
+               gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter());
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+               ima->tpageflag |= IMA_MIPMAP_COMPLETE;
+       }
+
+       /* set to modulate with vertex color */
+       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+               
+       /* clean up */
+       if (tilerect)
+               MEM_freeN(tilerect);
+       if (scalerect)
+               MEM_freeN(scalerect);
+
+       return *bind;
+}
+
+static void gpu_verify_repeat(Image *ima)
+{
+       /* set either clamp or repeat in X/Y */
+       if (ima->tpageflag & IMA_CLAMP_U)
+          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+       else
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+
+       if (ima->tpageflag & IMA_CLAMP_V)
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       else
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+}
+
+int GPU_set_tpage(MTFace *tface)
+{
+       Image *ima;
+       
+       /* check if we need to clear the state */
+       if(tface==0) {
+               gpu_clear_tpage();
+               return 0;
+       }
+
+       ima= tface->tpage;
+       GTS.lasttface= tface;
+
+       gpu_verify_alpha_mode(tface);
+       gpu_verify_reflection(ima);
+
+       if(GPU_verify_image(ima, tface->tile, tface->mode, 1)) {
+               GTS.curtile= GTS.tile;
+               GTS.curima= GTS.ima;
+               GTS.curtilemode= GTS.tilemode;
+               GTS.curtileXRep = GTS.tileXRep;
+               GTS.curtileYRep = GTS.tileYRep;
+
+               glEnable(GL_TEXTURE_2D);
+       }
+       else {
+               glDisable(GL_TEXTURE_2D);
+               
+               GTS.curtile= 0;
+               GTS.curima= 0;
+               GTS.curtilemode= 0;
+               GTS.curtileXRep = 0;
+               GTS.curtileYRep = 0;
+
+               return 0;
+       }
+       
+       gpu_verify_repeat(ima);
+       
+       /* Did this get lost in the image recode? */
+       /* tag_image_time(ima);*/
+
+       return 1;
+}
+
+/* these two functions are called on entering and exiting texture paint mode,
+   temporary disabling/enabling mipmapping on all images for quick texture
+   updates with glTexSubImage2D. images that didn't change don't have to be
+   re-uploaded to OpenGL */
+void GPU_paint_set_mipmap(int mipmap)
+{
+       Image* ima;
+       
+       if(!GTS.domipmap)
+               return;
+
+       if(mipmap) {
+               for(ima=G.main->image.first; ima; ima=ima->id.next) {
+                       if(ima->bindcode) {
+                               if(ima->tpageflag & IMA_MIPMAP_COMPLETE) {
+                                       glBindTexture(GL_TEXTURE_2D, ima->bindcode);
+                                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter());
+                                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                               }
+                               else
+                                       GPU_free_image(ima);
+                       }
+               }
+
+       }
+       else {
+               for(ima=G.main->image.first; ima; ima=ima->id.next) {
+                       if(ima->bindcode) {
+                               glBindTexture(GL_TEXTURE_2D, ima->bindcode);
+                               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+                               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                       }
+               }
+       }
+}
+
+void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
+{
+       ImBuf *ibuf;
+       
+       ibuf = BKE_image_get_ibuf(ima, NULL);
+       
+       if (ima->repbind || gpu_get_mipmap() || !ima->bindcode || !ibuf ||
+               (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) ||
+               (w == 0) || (h == 0)) {
+               /* these cases require full reload still */
+               GPU_free_image(ima);
+       }
+       else {
+               /* for the special case, we can do a partial update
+                * which is much quicker for painting */
+               GLint row_length, skip_pixels, skip_rows;
+
+               glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
+               glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
+               glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
+
+               if ((ibuf->rect==NULL) && ibuf->rect_float)
+                       IMB_rect_from_float(ibuf);
+
+               glBindTexture(GL_TEXTURE_2D, ima->bindcode);
+
+               glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);
+               glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
+               glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
+
+               glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
+                       GL_UNSIGNED_BYTE, ibuf->rect);
+
+               glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+               glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
+               glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
+
+               if(ima->tpageflag & IMA_MIPMAP_COMPLETE)
+                       ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
+       }
+}
+
+void GPU_update_images_framechange(void)
+{
+       Image *ima;
+       
+       for(ima=G.main->image.first; ima; ima=ima->id.next) {
+               if(ima->tpageflag & IMA_TWINANIM) {
+                       if(ima->twend >= ima->xrep*ima->yrep)
+                               ima->twend= ima->xrep*ima->yrep-1;
+               
+                       /* check: is bindcode not in the array? free. (to do) */
+                       
+                       ima->lastframe++;
+                       if(ima->lastframe > ima->twend)
+                               ima->lastframe= ima->twsta;
+               }
+       }
+}
+
+int GPU_update_image_time(Image *ima, double time)
+{
+       int     inc = 0;
+       float   diff;
+       int     newframe;
+
+       if (!ima)
+               return 0;
+
+       if (ima->lastupdate<0)
+               ima->lastupdate = 0;
+
+       if (ima->lastupdate>time)
+               ima->lastupdate=(float)time;
+
+       if(ima->tpageflag & IMA_TWINANIM) {
+               if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
+               
+               /* check: is the bindcode not in the array? Then free. (still to do) */
+               
+               diff = (float)(time-ima->lastupdate);
+               inc = (int)(diff*(float)ima->animspeed);
+
+               ima->lastupdate+=((float)inc/(float)ima->animspeed);
+
+               newframe = ima->lastframe+inc;
+
+               if(newframe > (int)ima->twend) {
+                       if(ima->twend-ima->twsta != 0)
+                               newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
+                       else
+                               newframe = ima->twsta;
+               }
+
+               ima->lastframe = newframe;
+       }
+
+       return inc;
+}
+
+void GPU_free_image(Image *ima)
+{
+       /* free regular image binding */
+       if(ima->bindcode) {
+               glDeleteTextures(1, (GLuint *)&ima->bindcode);
+               ima->bindcode= 0;
+               ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
+       }
+
+       /* free glsl image binding */
+       if(ima->gputexture) {
+               GPU_texture_free(ima->gputexture);
+               ima->gputexture= NULL;
+       }
+
+       /* free repeated image binding */
+       if(ima->repbind) {
+               glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
+       
+               MEM_freeN(ima->repbind);
+               ima->repbind= NULL;
+               ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
+       }
+}
+
+void GPU_free_images(void)
+{
+       Image* ima;
+
+       for(ima=G.main->image.first; ima; ima=ima->id.next)
+               GPU_free_image(ima);
+}
+
+/* OpenGL Materials */
+
+/* materials start counting at # one.... */
+#define MAXMATBUF (MAXMAT+1)
+
+/* OpenGL state caching for materials */
+
+static struct GPUMaterialState {
+       float matbuf[MAXMATBUF][2][4];
+       int totmat;
+
+       Material *gmatbuf[MAXMATBUF];
+       Material *gboundmat;
+       Object *gob;
+       Scene *gscene;
+
+       GPUBlendMode blendmode[MAXMATBUF];
+       int alphapass;
+
+       int lastmatnr, lastretval;
+       GPUBlendMode lastblendmode;
+} GMS;
+
+Material *gpu_active_node_material(Material *ma)
+{
+       if(ma && ma->use_nodes && ma->nodetree) {
+               bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
+
+               if(node)
+                       return (Material *)node->id;
+               else
+                       return NULL;
+       }
+
+       return ma;
+}
+
+void GPU_set_object_materials(Scene *scene, Object *ob, int glsl, int *do_alpha_pass)
+{
+       extern Material defmaterial; /* from material.c */
+       Material *ma;
+       GPUMaterial *gpumat;
+       GPUBlendMode blendmode;
+       int a;
+       
+       /* initialize state */
+       memset(&GMS, 0, sizeof(GMS));
+       GMS.lastmatnr = -1;
+       GMS.lastretval = -1;
+       GMS.lastblendmode = GPU_BLEND_SOLID;
+
+       GMS.gob = ob;
+       GMS.gscene = scene;
+       GMS.totmat= ob->totcol;
+
+       GMS.alphapass = (G.vd && G.vd->transp);
+       if(do_alpha_pass)
+               *do_alpha_pass = 0;
+
+       /* no materials assigned? */
+       if(ob->totcol==0) {
+               GMS.matbuf[0][0][0]= defmaterial.r;
+               GMS.matbuf[0][0][1]= defmaterial.g;
+               GMS.matbuf[0][0][2]= defmaterial.b;
+               GMS.matbuf[0][0][3]= 1.0;
+
+               GMS.matbuf[0][1][0]= defmaterial.specr;
+               GMS.matbuf[0][1][1]= defmaterial.specg;
+               GMS.matbuf[0][1][2]= defmaterial.specb;
+               GMS.matbuf[0][1][3]= 1.0;
+               
+               /* do material 1 too, for displists! */
+               QUATCOPY(GMS.matbuf[1][0], GMS.matbuf[0][0]);
+               QUATCOPY(GMS.matbuf[1][1], GMS.matbuf[0][1]);
+
+               if(glsl) {
+                       GMS.gmatbuf[0]= &defmaterial;
+                       GPU_material_from_blender(GMS.gscene, &defmaterial);
+               }
+
+               GMS.blendmode[0]= GPU_BLEND_SOLID;
+       }
+       
+       /* setup materials */
+       for(a=1; a<=ob->totcol; a++) {
+               /* find a suitable material */
+               ma= give_current_material(ob, a);
+               if(!glsl) ma= gpu_active_node_material(ma);
+               if(ma==NULL) ma= &defmaterial;
+
+               /* this shouldn't happen .. */
+               if(a>=MAXMATBUF)
+                       continue;
+
+               /* create glsl material if requested */
+               gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
+
+               if(gpumat) {
+                       /* do glsl only if creating it succeed, else fallback */
+                       GMS.gmatbuf[a]= ma;
+                       blendmode = GPU_material_blend_mode(gpumat, ob->col);
+               }
+               else {
+                       /* fixed function opengl materials */
+                       if (ma->mode & MA_SHLESS) {
+                               GMS.matbuf[a][0][0]= ma->r;
+                               GMS.matbuf[a][0][1]= ma->g;
+                               GMS.matbuf[a][0][2]= ma->b;
+                       } else {
+                               GMS.matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r;
+                               GMS.matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g;
+                               GMS.matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b;
+
+                               GMS.matbuf[a][1][0]= ma->spec*ma->specr;
+                               GMS.matbuf[a][1][1]= ma->spec*ma->specg;
+                               GMS.matbuf[a][1][2]= ma->spec*ma->specb;
+                               GMS.matbuf[a][1][3]= 1.0;
+                       }
+
+                       blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
+                       if(do_alpha_pass && GMS.alphapass)
+                               GMS.matbuf[a][0][3]= ma->alpha;
+                       else
+                               GMS.matbuf[a][0][3]= 1.0f;
+               }
+
+               /* setting do_alpha_pass = 1 indicates this object needs to be
+                * drawn in a second alpha pass for improved blending */
+               if(do_alpha_pass) {
+                       GMS.blendmode[a]= blendmode;
+                       if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass)
+                               *do_alpha_pass= 1;
+               }
+       }
+
+       /* let's start with a clean state */
+       GPU_disable_material();
+}
+
+int GPU_enable_material(int nr, void *attribs)
+{
+       GPUVertexAttribs *gattribs = attribs;
+       GPUMaterial *gpumat;
+       GPUBlendMode blendmode;
+
+       /* prevent index to use un-initialized array items */
+       if(nr>GMS.totmat)
+               nr= GMS.totmat;
+
+       if(gattribs)
+               memset(gattribs, 0, sizeof(*gattribs));
+
+       /* keep current material */
+       if(nr>=MAXMATBUF || nr==GMS.lastmatnr)
+               return GMS.lastretval;
+
+       /* unbind glsl material */
+       if(GMS.gboundmat) {
+               if(GMS.alphapass) glDepthMask(0);
+               GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
+               GMS.gboundmat= NULL;
+       }
+
+       /* draw materials with alpha in alpha pass */
+       GMS.lastmatnr = nr;
+       GMS.lastretval = ELEM(GMS.blendmode[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
+       if(GMS.alphapass)
+               GMS.lastretval = !GMS.lastretval;
+
+       if(GMS.lastretval) {
+               if(gattribs && GMS.gmatbuf[nr]) {
+                       /* bind glsl material and get attributes */
+                       Material *mat = GMS.gmatbuf[nr];
+
+                       gpumat = GPU_material_from_blender(GMS.gscene, mat);
+                       GPU_material_vertex_attributes(gpumat, gattribs);
+                       GPU_material_bind(gpumat, GMS.gob->lay, 1.0);
+                       GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, G.vd->viewmat, G.vd->viewinv, GMS.gob->col);
+                       GMS.gboundmat= mat;
+
+                       if(GMS.alphapass) glDepthMask(1);
+               }
+               else {
+                       /* or do fixed function opengl material */
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr][0]);
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr][1]);
+               }
+
+               /* set (alpha) blending mode */
+               blendmode = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID;
+               GPU_set_material_blend_mode(blendmode);
+       }
+
+       return GMS.lastretval;
+}
+
+void GPU_set_material_blend_mode(int blendmode)
+{
+       if(GMS.lastblendmode == blendmode)
+               return;
+       
+       gpu_set_blend_mode(blendmode);
+       GMS.lastblendmode = blendmode;
+}
+
+int GPU_get_material_blend_mode(void)
+{
+       return GMS.lastblendmode;
+}
+
+void GPU_disable_material(void)
+{
+       GMS.lastmatnr= -1;
+       GMS.lastretval= 1;
+
+       if(GMS.gboundmat) {
+               if(GMS.alphapass) glDepthMask(0);
+               GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
+               GMS.gboundmat= NULL;
+       }
+
+       GPU_set_material_blend_mode(GPU_BLEND_SOLID);
+}
+
+/* Lights */
+
+int GPU_default_lights(void)
+{
+       int a, count = 0;
+       
+       /* initialize */
+       if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) {
+               U.light[0].flag= 1;
+               U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9;
+               U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8;
+               U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5;
+               U.light[0].spec[3]= 1.0;
+               
+               U.light[1].flag= 0;
+               U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1;
+               U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8;
+               U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5;
+               U.light[1].spec[3]= 1.0;
+       
+               U.light[2].flag= 0;
+               U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2;
+               U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4;
+               U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3;
+               U.light[2].spec[3]= 1.0;
+       }
+
+       glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); 
+       glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); 
+       glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); 
+
+       glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); 
+       glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); 
+       glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); 
+
+       glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); 
+       glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); 
+       glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); 
+
+       for(a=0; a<8; a++) {
+               if(a<3) {
+                       if(U.light[a].flag) {
+                               glEnable(GL_LIGHT0+a);
+                               count++;
+                       }
+                       else
+                               glDisable(GL_LIGHT0+a);
+                       
+                       // clear stuff from other opengl lamp usage
+                       glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0);
+                       glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0);
+                       glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0);
+               }
+               else
+                       glDisable(GL_LIGHT0+a);
+       }
+       
+       glDisable(GL_LIGHTING);
+
+       glDisable(GL_COLOR_MATERIAL);
+
+       return count;
+}
+
+int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4])
+{
+       Base *base;
+       Lamp *la;
+       int count;
+       float position[4], direction[4], energy[4];
+       
+       /* disable all lights */
+       for(count=0; count<8; count++)
+               glDisable(GL_LIGHT0+count);
+       
+       count= 0;
+       
+       for(base=scene->base.first; base; base=base->next) {
+               if(base->object->type!=OB_LAMP)
+                       continue;
+
+               if(!(base->lay & lay) || !(base->lay & ob->lay))
+                       continue;
+
+               la= base->object->data;
+               
+               /* setup lamp transform */
+               glPushMatrix();
+               glLoadMatrixf((float *)viewmat);
+               
+               where_is_object_simul(base->object);
+               
+               if(la->type==LA_SUN) {
+                       /* sun lamp */
+                       VECCOPY(position, base->object->obmat[2]);
+                       direction[3]= 0.0;
+
+                       glLightfv(GL_LIGHT0+count, GL_POSITION, direction); 
+               }
+               else {
+                       /* other lamps with attenuation */
+                       VECCOPY(position, base->object->obmat[3]);
+                       position[3]= 1.0f;
+
+                       glLightfv(GL_LIGHT0+count, GL_POSITION, position); 
+                       glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
+                       glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist);
+                       glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist));
+                       
+                       if(la->type==LA_SPOT) {
+                               /* spot lamp */
+                               direction[0]= -base->object->obmat[2][0];
+                               direction[1]= -base->object->obmat[2][1];
+                               direction[2]= -base->object->obmat[2][2];
+                               glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction);
+                               glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0);
+                               glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend);
+                       }
+                       else
+                               glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0);
+               }
+               
+               /* setup energy */
+               energy[0]= la->energy*la->r;
+               energy[1]= la->energy*la->g;
+               energy[2]= la->energy*la->b;
+               energy[3]= 1.0;
+
+               glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy); 
+               glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy);
+               glEnable(GL_LIGHT0+count);
+               
+               glPopMatrix();                                  
+               
+               count++;
+               if(count==8)
+                       break;
+       }
+
+       return count;
+}
+
+/* Default OpenGL State */
+
+void GPU_state_init(void)
+{
+       /* also called when doing opengl rendering and in the game engine */
+       float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
+       float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
+       float mat_shininess[] = { 35.0 };
+       int a, x, y;
+       GLubyte pat[32*32];
+       const GLubyte *patc= pat;
+       
+       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
+       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
+       glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
+       glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
+
+       GPU_default_lights();
+       
+       /* no local viewer, looks ugly in ortho mode */
+       /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
+       
+       glDepthFunc(GL_LEQUAL);
+       /* scaling matrices */
+       glEnable(GL_NORMALIZE);
+
+       glShadeModel(GL_FLAT);
+
+       glDisable(GL_ALPHA_TEST);
+       glDisable(GL_BLEND);
+       glDisable(GL_DEPTH_TEST);
+       glDisable(GL_FOG);
+       glDisable(GL_LIGHTING);
+       glDisable(GL_LOGIC_OP);
+       glDisable(GL_STENCIL_TEST);
+       glDisable(GL_TEXTURE_1D);
+       glDisable(GL_TEXTURE_2D);
+
+       /* default on, disable/enable should be local per function */
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_NORMAL_ARRAY);
+       
+       glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
+       glPixelTransferi(GL_RED_SCALE, 1);
+       glPixelTransferi(GL_RED_BIAS, 0);
+       glPixelTransferi(GL_GREEN_SCALE, 1);
+       glPixelTransferi(GL_GREEN_BIAS, 0);
+       glPixelTransferi(GL_BLUE_SCALE, 1);
+       glPixelTransferi(GL_BLUE_BIAS, 0);
+       glPixelTransferi(GL_ALPHA_SCALE, 1);
+       glPixelTransferi(GL_ALPHA_BIAS, 0);
+       
+       glPixelTransferi(GL_DEPTH_BIAS, 0);
+       glPixelTransferi(GL_DEPTH_SCALE, 1);
+       glDepthRange(0.0, 1.0);
+       
+       a= 0;
+       for(x=0; x<32; x++) {
+               for(y=0; y<4; y++) {
+                       if( (x) & 1) pat[a++]= 0x88;
+                       else pat[a++]= 0x22;
+               }
+       }
+       
+       glPolygonStipple(patc);
+
+       glMatrixMode(GL_TEXTURE);
+       glLoadIdentity();
+       glMatrixMode(GL_MODELVIEW);
+
+       glFrontFace(GL_CCW);
+       glCullFace(GL_BACK);
+       glDisable(GL_CULL_FACE);
+}
+
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
new file mode 100644 (file)
index 0000000..d900f9c
--- /dev/null
@@ -0,0 +1,987 @@
+/**
+ * $Id$
+ *
+ * ***** 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 "GL/glew.h"
+
+#include "DNA_listBase.h"
+#include "DNA_image_types.h"
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_image.h"
+#include "BKE_global.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Extensions support */
+
+/* extensions used:
+       - texture border clamp: 1.3 core
+       - fragement shader: 2.0 core
+       - framebuffer object: ext specification
+       - multitexture 1.3 core
+       - arb non power of two: 2.0 core
+       - pixel buffer objects? 2.1 core
+       - arb draw buffers? 2.0 core
+*/
+
+struct GPUGlobal {
+       GLint maxtextures;
+       GLuint currentfb;
+       int minimumsupport;
+} GG = {1, 0, 0};
+
+void GPU_extensions_init()
+{
+       glewInit();
+
+       /* glewIsSupported("GL_VERSION_2_0") */
+
+       if (GLEW_ARB_multitexture)
+               glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &GG.maxtextures);
+
+       GG.minimumsupport = 1;
+       if (!GLEW_ARB_multitexture) GG.minimumsupport = 0;
+       if (!GLEW_ARB_vertex_shader) GG.minimumsupport = 0;
+       if (!GLEW_ARB_fragment_shader) GG.minimumsupport = 0;
+}
+
+int GPU_extensions_minimum_support()
+{
+       return GG.minimumsupport;
+}
+
+int GPU_print_error(char *str)
+{
+       GLenum errCode;
+
+       if (G.f & G_DEBUG) {
+               if ((errCode = glGetError()) != GL_NO_ERROR) {
+           fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode));
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static void GPU_print_framebuffer_error(GLenum status)
+{
+       fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d\n",
+               (int)status);
+
+       switch(status) {
+               case GL_FRAMEBUFFER_COMPLETE_EXT:
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
+                       fprintf(stderr, "Incomplete attachment.\n");
+                       break;
+               case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
+                       fprintf(stderr, "Unsupported framebuffer format.\n");
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+                       fprintf(stderr, "Missing attachment.\n");
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+                       fprintf(stderr, "Attached images must have same dimensions.\n");
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
+                        fprintf(stderr, "Attached images must have same format.\n");
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
+                       fprintf(stderr, "Missing draw buffer.\n");
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
+                       fprintf(stderr, "Missing read buffer.\n");
+                       break;
+               default:
+                       fprintf(stderr, "Unknown.\n");
+                       break;
+       }
+}
+
+/* GPUTexture */
+
+struct GPUTexture {
+       int w, h;                               /* width/height */
+       int number;                             /* number for multitexture binding */
+       int refcount;                   /* reference count */
+       GLenum target;                  /* GL_TEXTURE_* */
+       GLuint bindcode;                /* opengl identifier for texture */
+       int fromblender;                /* we got the texture from Blender */
+
+       GPUFrameBuffer *fb;             /* GPUFramebuffer this texture is attached to */
+       int depth;                              /* is a depth texture? */
+};
+
+#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
+static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels)
+{
+       unsigned char *pixels, *p;
+       float *fp;
+       int a, len;
+
+       len = 4*length;
+       fp = fpixels;
+       p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels");
+
+       for (a=0; a<len; a++, p++, fp++)
+               *p = FTOCHAR((*fp));
+
+       return pixels;
+}
+
+static int is_pow2(int n)
+{
+       return ((n)&(n-1))==0;
+}
+
+static int larger_pow2(int n)
+{
+       if (is_pow2(n))
+               return n;
+
+       while(!is_pow2(n))
+               n= n&(n-1);
+
+       return n*2;
+}
+
+static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
+{
+       void *pixels = MEM_callocN(sizeof(char)*4*w*h, "GPUTextureEmptyPixels");
+
+       if (target == GL_TEXTURE_1D)
+               glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
+       else
+               glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
+       
+       MEM_freeN(pixels);
+}
+
+static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth)
+{
+       GPUTexture *tex;
+       GLenum type, format, internalformat;
+       void *pixels = NULL;
+
+       if(depth && !GLEW_ARB_depth_texture)
+               return NULL;
+
+       tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+       tex->w = w;
+       tex->h = h;
+       tex->number = -1;
+       tex->refcount = 1;
+       tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
+       tex->depth = depth;
+
+       glGenTextures(1, &tex->bindcode);
+
+       if (!tex->bindcode) {
+               fprintf(stderr, "GPUTexture: texture create failed: %d\n",
+                       (int)glGetError());
+               GPU_texture_free(tex);
+               return NULL;
+       }
+
+       if (!GLEW_ARB_texture_non_power_of_two) {
+               tex->w = larger_pow2(tex->w);
+               tex->h = larger_pow2(tex->h);
+       }
+
+       tex->number = 0;
+       glBindTexture(tex->target, tex->bindcode);
+
+       if(depth) {
+               type = GL_UNSIGNED_BYTE;
+               format = GL_DEPTH_COMPONENT;
+               internalformat = GL_DEPTH_COMPONENT;
+       }
+       else {
+               type = GL_UNSIGNED_BYTE;
+               format = GL_RGBA;
+               internalformat = GL_RGBA8;
+
+               if (fpixels)
+                       pixels = GPU_texture_convert_pixels(w*h, fpixels);
+       }
+
+       if (tex->target == GL_TEXTURE_1D) {
+               glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, 0);
+
+               if (fpixels) {
+                       glTexSubImage1D(tex->target, 0, 0, w, format, type,
+                               pixels? pixels: fpixels);
+
+                       if (tex->w > w)
+                               GPU_glTexSubImageEmpty(tex->target, format, w, 0,
+                                       tex->w-w, 1);
+               }
+       }
+       else {
+               glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
+                       format, type, 0);
+
+               if (fpixels) {
+                       glTexSubImage2D(tex->target, 0, 0, 0, w, h,
+                               format, type, pixels? pixels: fpixels);
+
+                       if (tex->w > w)
+                               GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex