Merge of first part of changes from the apricot branch, especially
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 4 Sep 2008 20:51:28 +0000 (20:51 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 4 Sep 2008 20:51:28 +0000 (20:51 +0000)
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:

* GLSL support in the viewport and game engine, enable in the game
  menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
  gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
  storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.

* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
  An extra texture slot shows up once the last slot is used.

* Memory limit for undo, not enabled by default yet because it
  needs the .B.blend to be changed.
* Multiple undo for image painting.

* An offset for dupligroups, so not all objects in a group have to
  be at the origin.

258 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_gl.h
source/blender/include/BIF_meshtools.h
source/blender/include/BSE_drawview.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_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/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_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/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/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 d906395..e323904 100644 (file)
@@ -90,6 +90,7 @@ IF(UNIX)
     bf_soundsystem 
     bf_kernel 
     bf_nodes
+       bf_gpu
     bf_imbuf
     bf_avi 
     kx_network 
index 8fd6c32..48455d2 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 32b3b47..3badbeb 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 fd3fe10..6b88e6e 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 593f0e5..f204636 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 d004e79..1d4c753 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 a36549d..7bdca73 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 d5ae94c..b2c3c5e 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 cada06a..43149ef 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 4cf0ef3..d998c9a 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 9f56924..d85e9af 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 8235413..b4ee84a 100644 (file)
@@ -212,6 +212,7 @@ public:
        MT_Matrix4x4 transposed() const; 
        void         transpose();
 
+       MT_Matrix4x4 inverse() const;
        void         invert();
   
 protected:
index a2aa893..074bd6e 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 9f24885..3a671e7 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 91dd17d..aebeb8f 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 966bf5f..a21eadf 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 937512f..52abd2c 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 56a6612..25745c0 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 7dc10c5..171a73f 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 3e45749..8dee9a2 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 e788822..555b467 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 8c9634c..1cc336d 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 d4ae76e..2ca4b3a 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 b3b68a9..01c5466 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 c162a04..cfcae3c 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 f389521..d647a74 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 9088b41..0345711 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 1bb9823..db67251 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 561d8d7..4b6cb5e 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 1dabab9..328dcad 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 74c6c55..8921ea5 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 5b96bf1..2648233 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 1592c3e..e2ce4b9 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 aca51e5..1fe6447 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 472df3d..9d5dcb8 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 295b8fe..45b8bb7 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 07537e3..27fa00a 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 1a6c8f5..e8a25aa 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 3983eec..f05b84f 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 43e48c3..77b9ea4 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 4e36df3..4dfe651 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 7b36e46..8879b49 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 bba79bd..f334fc3 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 936381c..bb72688 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 c22b6f7..4448231 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 e24ccad..c59cd2d 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 8bd7ad4..50f8ba0 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 6affec0..a2b1828 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->w-w, tex->h);
+                       if (tex->h > h)
+                               GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h);
+               }
+       }
+
+       if (pixels)
+               MEM_freeN(pixels);
+
+       if(depth) {
+               glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+               glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
+               glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+               glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);  
+       }
+       else {
+               glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       }
+
+       if (tex->target != GL_TEXTURE_1D) {
+               /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
+               GLenum wrapmode = (depth)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
+               glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
+               glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
+
+#if 0
+               float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+               glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); 
+#endif
+       }
+       else
+               glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
+       return tex;
+}
+
+GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, double time)
+{
+       GPUTexture *tex;
+       GLint w, h, border, lastbindcode, bindcode;
+
+       glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
+
+       GPU_update_image_time(ima, time);
+       bindcode = GPU_verify_image(ima, 0, 0, 0);
+
+       if(ima->gputexture) {
+               ima->gputexture->bindcode = bindcode;
+               glBindTexture(GL_TEXTURE_2D, lastbindcode);
+               return ima->gputexture;
+       }
+
+       if(!bindcode) {
+               glBindTexture(GL_TEXTURE_2D, lastbindcode);
+               return NULL;
+       }
+
+       tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+       tex->bindcode = bindcode;
+       tex->number = -1;
+       tex->refcount = 1;
+       tex->target = GL_TEXTURE_2D;
+       tex->fromblender = 1;
+
+       ima->gputexture= tex;
+
+       if (!glIsTexture(tex->bindcode)) {
+               GPU_print_error("Blender Texture");
+       }
+       else {
+               glBindTexture(GL_TEXTURE_2D, tex->bindcode);
+               glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
+               glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
+               glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
+
+               tex->w = w - border;
+               tex->h = h - border;
+       }
+
+       glBindTexture(GL_TEXTURE_2D, lastbindcode);
+
+       return tex;
+}
+
+GPUTexture *GPU_texture_create_1D(int w, float *fpixels)
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0);
+
+       if (tex)
+               GPU_texture_unbind(tex);
+       
+       return tex;
+}
+
+GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels)
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0);
+
+       if (tex)
+               GPU_texture_unbind(tex);
+       
+       return tex;
+}
+
+GPUTexture *GPU_texture_create_depth(int w, int h)
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1);
+
+       if (tex)
+               GPU_texture_unbind(tex);
+       
+       return tex;
+}
+
+void GPU_texture_bind(GPUTexture *tex, int number)
+{
+       GLenum arbnumber;
+
+       if (number >= GG.maxtextures) {
+               GPU_print_error("Not enough texture slots.");
+               return;
+       }
+
+       if(number == -1)
+               return;
+
+       GPU_print_error("Pre Texture Bind");
+
+       arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number);
+       if (number != 0) glActiveTextureARB(arbnumber);
+       glBindTexture(tex->target, tex->bindcode);
+       glEnable(tex->target);
+       if (number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
+
+       tex->number = number;
+
+       GPU_print_error("Post Texture Bind");
+}
+
+void GPU_texture_unbind(GPUTexture *tex)
+{
+       GLenum arbnumber;
+
+       if (tex->number >= GG.maxtextures) {
+               GPU_print_error("Not enough texture slots.");
+               return;
+       }
+
+       if(tex->number == -1)
+               return;
+       
+    &nbs