OpenGL: split off framebuffer, shader and texture code into separate files.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sun, 6 Dec 2015 20:20:19 +0000 (21:20 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 8 Dec 2015 18:00:56 +0000 (19:00 +0100)
29 files changed:
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/editderivedmesh.c
source/blender/blenkernel/intern/icons.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/editors/render/render_opengl.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/drawvolume.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/gpu/CMakeLists.txt
source/blender/gpu/GPU_draw.h
source/blender/gpu/GPU_extensions.h
source/blender/gpu/GPU_framebuffer.h [new file with mode: 0644]
source/blender/gpu/GPU_shader.h [new file with mode: 0644]
source/blender/gpu/GPU_texture.h [new file with mode: 0644]
source/blender/gpu/intern/gpu_basic_shader.c
source/blender/gpu/intern/gpu_codegen.c
source/blender/gpu/intern/gpu_compositing.c
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_extensions.c
source/blender/gpu/intern/gpu_framebuffer.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_material.c
source/blender/gpu/intern/gpu_shader.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_texture.c [new file with mode: 0644]
source/blender/python/intern/gpu_offscreen.c
source/gameengine/Ketsji/BL_BlenderShader.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp

index 07a1d3bea7f302ad5604952287ae0a00aedae02b..e26e5148ff639517142ce980df6a84330d04788d 100644 (file)
@@ -74,8 +74,8 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
 #include "BLI_sys_types.h" /* for intptr_t support */
 
 #include "GPU_buffers.h"
-#include "GPU_extensions.h"
 #include "GPU_glew.h"
+#include "GPU_shader.h"
 
 #ifdef WITH_OPENSUBDIV
 #  include "DNA_userdef_types.h"
index 1acb9ad3d20e176eb711bd985a4b1b08cca0319d..836072df67db566929a7d970659748a4f83de102 100644 (file)
@@ -57,8 +57,8 @@
 
 #include "GPU_buffers.h"
 #include "GPU_draw.h"
-#include "GPU_extensions.h"
 #include "GPU_glew.h"
+#include "GPU_shader.h"
 
 #include "WM_api.h"
 
index b6d009deb2a1190e3e51d726c554e5f7230c6790..dc50e39a8623c7c92aba64c6f789db76446168a0 100644 (file)
@@ -55,8 +55,8 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "GPU_extensions.h"
 #include "GPU_glew.h"
+#include "GPU_shader.h"
 
 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
 
index 2171f193bac00080a24e2263187cda3c829025c2..45ebada4d81da075b1ad5fac358d795e21e49bdb 100644 (file)
@@ -55,7 +55,7 @@
 
 #include "BLI_sys_types.h" // for intptr_t support
 
-#include "GPU_extensions.h"
+#include "GPU_texture.h"
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
index 23bc247094553bcca9b4f4d354547cdb5027f637..53da38b2da8e9e64a27fe9a87d1ab9efeafeec6c 100644 (file)
@@ -74,9 +74,9 @@
 #endif
 
 #include "GPU_draw.h"
-#include "GPU_extensions.h"
 #include "GPU_glew.h"
 #include "GPU_buffers.h"
+#include "GPU_shader.h"
 
 #include "CCGSubSurf.h"
 
index f94f3cdf758b7f177a6fcfe4570901ab1935e3bc..5268afae270bab9877af18c9b0ed54d72503cb35 100644 (file)
@@ -69,9 +69,9 @@
 #include "RNA_access.h"
 #include "RNA_define.h"
 
-#include "GPU_extensions.h"
 #include "GPU_glew.h"
 #include "GPU_compositing.h"
+#include "GPU_framebuffer.h"
 
 
 #include "render_intern.h"
index de7a8ed0a7ccf9c819d772a65f1f637e7984e96f..f6e66ca5e90ccba4b5d92390705331c6e1deb60b 100644 (file)
 
 #include "UI_resources.h"
 
-#include "GPU_extensions.h"
 #include "GPU_draw.h"
 #include "GPU_material.h"
 #include "GPU_basic_shader.h"
+#include "GPU_shader.h"
 
 #include "RE_engine.h"
 
index f2240c662ab6dd51ffad3a80002e53397b6e37b4..e03f81742b7d1a6a2cd680289c90f4a54287f02f 100644 (file)
@@ -87,9 +87,9 @@
 #include "BIF_glutil.h"
 
 #include "GPU_draw.h"
-#include "GPU_extensions.h"
 #include "GPU_select.h"
 #include "GPU_basic_shader.h"
+#include "GPU_shader.h"
 
 #include "ED_mesh.h"
 #include "ED_particle.h"
index 3029aaeeef1bb36948975fd2f00aa09d20edcb60..102bfc55a2c0a440697f17717a03d51d6eaf082b 100644 (file)
@@ -46,7 +46,8 @@
 
 #include "BIF_gl.h"
 
-#include "GPU_extensions.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
 
 #include "view3d_intern.h"  // own include
 
index a1c2c8cca17c5bb1a9b9d904b945968b9befc1ae..fa14ca96fe2cca6b9a599298c6622edded1fa23d 100644 (file)
@@ -54,9 +54,9 @@
 #include "ED_space_api.h"
 #include "ED_screen.h"
 
-#include "GPU_extensions.h"
-#include "GPU_material.h"
 #include "GPU_compositing.h"
+#include "GPU_framebuffer.h"
+#include "GPU_material.h"
 
 #include "BIF_gl.h"
 
index 781c848285a373e41121fc3f86775a0cc506ae79..5a839c25e05e7cbb1f59ba5426606e9a1ef34316 100644 (file)
@@ -96,8 +96,8 @@
 #include "UI_resources.h"
 
 #include "GPU_draw.h"
+#include "GPU_framebuffer.h"
 #include "GPU_material.h"
-#include "GPU_extensions.h"
 #include "GPU_compositing.h"
 
 #include "view3d_intern.h"  /* own include */
index 60fa77babd9e69b63b67982116c187c9f25bc0e9..6d3a5d37d66ca50412210adb123816ad62c75b7c 100644 (file)
@@ -46,16 +46,19 @@ set(INC_SYS
 )
 
 set(SRC
+       intern/gpu_basic_shader.c
        intern/gpu_buffers.c
        intern/gpu_codegen.c
+       intern/gpu_compositing.c
+       intern/gpu_debug.c
        intern/gpu_draw.c
        intern/gpu_extensions.c
+       intern/gpu_framebuffer.c
        intern/gpu_init_exit.c
        intern/gpu_material.c
-       intern/gpu_basic_shader.c
        intern/gpu_select.c
-       intern/gpu_compositing.c
-       intern/gpu_debug.c
+       intern/gpu_shader.c
+       intern/gpu_texture.c
 
        shaders/gpu_program_smoke_frag.glsl
        shaders/gpu_program_smoke_color_frag.glsl
@@ -78,16 +81,19 @@ set(SRC
        shaders/gpu_shader_vsm_store_vert.glsl
        shaders/gpu_shader_fx_depth_resolve.glsl
 
+       GPU_basic_shader.h
        GPU_buffers.h
-       GPU_draw.h
+       GPU_compositing.h
        GPU_debug.h
+       GPU_draw.h
        GPU_extensions.h
+       GPU_framebuffer.h
        GPU_glew.h
        GPU_init_exit.h
        GPU_material.h
-       GPU_basic_shader.h
        GPU_select.h
-       GPU_compositing.h
+       GPU_shader.h
+       GPU_texture.h
        intern/gpu_codegen.h
        intern/gpu_private.h
 )
index cb288e9f448f33fc52853600f29dacf8b2b53d87..3e6c26f608cf06b639b105fe1dda008fdb1d9eba 100644 (file)
@@ -129,7 +129,7 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap);
 /* Image updates and free
  * - these deal with images bound as opengl textures */
 
-void GPU_paint_update_image(struct Image *ima, ImageUser *iuser, int x, int y, int w, int h);
+void GPU_paint_update_image(struct Image *ima, struct ImageUser *iuser, 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, struct ImageUser *iuser, int tftile, bool compare, bool mipmap, bool is_data);
index ef582b6d97f27f7ca8125c5586f361005e91d139..f3be52f324b16770ceddef9574683ef66f44e247 100644 (file)
 extern "C" {
 #endif
 
-struct Image;
-struct ImageUser;
-struct PreviewImage;
-       
-struct GPUTexture;
-typedef struct GPUTexture GPUTexture;
-
-struct GPUFrameBuffer;
-typedef struct GPUFrameBuffer GPUFrameBuffer;
-
-struct GPUOffScreen;
-typedef struct GPUOffScreen GPUOffScreen;
-
-struct GPUShader;
-typedef struct GPUShader GPUShader;
-
-struct GPUProgram;
-typedef struct GPUProgram GPUProgram;
-
 /* GPU extensions support */
 
 void GPU_extensions_disable(void);
@@ -65,9 +46,12 @@ bool GPU_full_non_power_of_two_support(void);
 bool GPU_display_list_support(void);
 bool GPU_bicubic_bump_support(void);
 bool GPU_geometry_shader_support(void);
+bool GPU_geometry_shader_support_via_extension(void);
 bool GPU_instanced_drawing_support(void);
 
 int GPU_max_texture_size(void);
+int GPU_max_textures(void);
+int GPU_max_color_texture_samples(void);
 int GPU_color_depth(void);
 void GPU_get_dfdy_factors(float fac[2]);
 
@@ -103,171 +87,6 @@ typedef enum GPUDriverType {
 
 bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
 
-/* 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.
- * - 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
- */
-
-typedef enum GPUHDRType {
-       GPU_HDR_NONE =       0,
-       GPU_HDR_HALF_FLOAT = 1,
-       GPU_HDR_FULL_FLOAT = (1 << 1),
-} GPUHDRType;
-
-GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]);
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels);
-GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
-GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
-GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]);
-GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
-GPUTexture *GPU_texture_from_blender(struct Image *ima,
-       struct ImageUser *iuser, bool is_data, double time, int mipmap);
-GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
-void GPU_invalid_tex_init(void);
-void GPU_invalid_tex_bind(int mode);
-void GPU_invalid_tex_free(void);
-
-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);
-
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter);
-
-GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
-
-int GPU_texture_target(const GPUTexture *tex);
-int GPU_texture_width(const GPUTexture *tex);
-int GPU_texture_height(const GPUTexture *tex);
-int GPU_texture_opengl_bindcode(const 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 */
-
-void GPU_texture_bind_as_framebuffer(GPUTexture *tex);
-
-GPUFrameBuffer *GPU_framebuffer_create(void);
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
-void GPU_framebuffer_texture_detach(GPUTexture *tex);
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
-void GPU_framebuffer_free(GPUFrameBuffer *fb);
-bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
-
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
-
-void GPU_framebuffer_restore(void);
-void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex);
-
-/* GPU OffScreen
- * - wrapper around framebuffer and texture for simple offscreen drawing
- * - changes size if graphics card can't support it */
-
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]);
-void GPU_offscreen_free(GPUOffScreen *ofs);
-void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
-void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
-void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
-int GPU_offscreen_width(const GPUOffScreen *ofs);
-int GPU_offscreen_height(const GPUOffScreen *ofs);
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
-
-/* Builtin/Non-generated shaders */
-typedef enum GPUProgramType {
-       GPU_PROGRAM_TYPE_FRAGMENT = 0
-} GPUProgramType;
-
-/* TODO: remove ARB program support (recode smoke shader in GLSL) */
-GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code);
-void GPU_program_free(GPUProgram *program);
-void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w);
-void GPU_program_bind(GPUProgram *);
-void GPU_program_unbind(GPUProgram *);
-
-/* 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, const char *geocode, const char *libcode, const char *defines, int input, int output, int number);
-enum {
-       GPU_SHADER_FLAGS_NONE = 0,
-       GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV = (1 << 0),
-};
-GPUShader *GPU_shader_create_ex(const char *vertexcode,
-                                const char *fragcode,
-                                const char *geocode,
-                                const char *libcode,
-                                const char *defines,
-                                int input,
-                                int output,
-                                int number,
-                                const int flags);
-void GPU_shader_free(GPUShader *shader);
-
-void GPU_shader_bind(GPUShader *shader);
-void GPU_shader_unbind(void);
-
-int GPU_shader_get_uniform(GPUShader *shader, const char *name);
-void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
-       int arraysize, const float *value);
-void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
-       int arraysize, const int *value);
-
-void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
-void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
-void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
-
-int GPU_shader_get_attribute(GPUShader *shader, const char *name);
-
-/* Builtin/Non-generated shaders */
-typedef enum GPUBuiltinShader {
-       GPU_SHADER_VSM_STORE         = 0,
-       GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
-} GPUBuiltinShader;
-
-typedef enum GPUBuiltinProgram {
-       GPU_PROGRAM_SMOKE         = 0,
-       GPU_PROGRAM_SMOKE_COLORED = 1,
-} GPUBuiltinProgram;
-
-GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
-GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program);
-GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
-
-void GPU_shader_free_builtin_shaders(void);
-
-/* Vertex attributes for shaders */
-
-#define GPU_MAX_ATTRIB 32
-
-typedef struct GPUVertexAttribs {
-       struct {
-               int type;
-               int glindex;
-               int gltexco;
-               int attribid;
-               char name[64];  /* MAX_CUSTOMDATA_LAYER_NAME */
-       } layer[GPU_MAX_ATTRIB];
-
-       int totlayer;
-} GPUVertexAttribs;
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
new file mode 100644 (file)
index 0000000..4a7b045
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
+ */
+
+/** \file GPU_framebuffer.h
+ *  \ingroup gpu
+ */
+
+#ifndef __GPU_FRAMEBUFFER_H__
+#define __GPU_FRAMEBUFFER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct GPUFrameBuffer GPUFrameBuffer;
+typedef struct GPUOffScreen GPUOffScreen;
+typedef struct GPUTexture GPUTexture;
+
+/* 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 */
+
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex);
+
+GPUFrameBuffer *GPU_framebuffer_create(void);
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
+void GPU_framebuffer_texture_detach(GPUTexture *tex);
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
+void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
+void GPU_framebuffer_free(GPUFrameBuffer *fb);
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
+
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
+
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
+
+void GPU_framebuffer_restore(void);
+void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex);
+
+/* GPU OffScreen
+ * - wrapper around framebuffer and texture for simple offscreen drawing
+ * - changes size if graphics card can't support it */
+
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]);
+void GPU_offscreen_free(GPUOffScreen *ofs);
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
+void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
+int GPU_offscreen_width(const GPUOffScreen *ofs);
+int GPU_offscreen_height(const GPUOffScreen *ofs);
+int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __GPU_FRAMEBUFFER_H__ */
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
new file mode 100644 (file)
index 0000000..a7cfd4e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
+ */
+
+/** \file GPU_shader.h
+ *  \ingroup gpu
+ */
+
+#ifndef __GPU_SHADER_H__
+#define __GPU_SHADER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct GPUShader GPUShader;
+typedef struct GPUProgram GPUProgram;
+typedef struct GPUTexture GPUTexture;
+
+/* Builtin/Non-generated shaders */
+typedef enum GPUProgramType {
+       GPU_PROGRAM_TYPE_FRAGMENT = 0
+} GPUProgramType;
+
+/* TODO: remove ARB program support (recode smoke shader in GLSL) */
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code);
+void GPU_program_free(GPUProgram *program);
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w);
+void GPU_program_bind(GPUProgram *);
+void GPU_program_unbind(GPUProgram *);
+
+/* 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, const char *geocode, const char *libcode, const char *defines, int input, int output, int number);
+enum {
+       GPU_SHADER_FLAGS_NONE = 0,
+       GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV = (1 << 0),
+};
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+                                const char *fragcode,
+                                const char *geocode,
+                                const char *libcode,
+                                const char *defines,
+                                int input,
+                                int output,
+                                int number,
+                                const int flags);
+void GPU_shader_free(GPUShader *shader);
+
+void GPU_shader_bind(GPUShader *shader);
+void GPU_shader_unbind(void);
+
+int GPU_shader_get_uniform(GPUShader *shader, const char *name);
+void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
+       int arraysize, const float *value);
+void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
+       int arraysize, const int *value);
+
+void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
+void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
+void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
+
+int GPU_shader_get_attribute(GPUShader *shader, const char *name);
+
+/* Builtin/Non-generated shaders */
+typedef enum GPUBuiltinShader {
+       GPU_SHADER_VSM_STORE         = 0,
+       GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
+} GPUBuiltinShader;
+
+typedef enum GPUBuiltinProgram {
+       GPU_PROGRAM_SMOKE         = 0,
+       GPU_PROGRAM_SMOKE_COLORED = 1,
+} GPUBuiltinProgram;
+
+GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program);
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
+
+void GPU_shader_free_builtin_shaders(void);
+
+/* Vertex attributes for shaders */
+
+#define GPU_MAX_ATTRIB 32
+
+typedef struct GPUVertexAttribs {
+       struct {
+               int type;
+               int glindex;
+               int gltexco;
+               int attribid;
+               char name[64];  /* MAX_CUSTOMDATA_LAYER_NAME */
+       } layer[GPU_MAX_ATTRIB];
+
+       int totlayer;
+} GPUVertexAttribs;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __GPU_SHADER_H__ */
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
new file mode 100644 (file)
index 0000000..a17da53
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
+ */
+
+/** \file GPU_texture.h
+ *  \ingroup gpu
+ */
+
+#ifndef __GPU_TEXTURE_H__
+#define __GPU_TEXTURE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Image;
+struct ImageUser;
+struct PreviewImage;
+       
+typedef struct GPUFrameBuffer GPUFrameBuffer;
+typedef struct GPUTexture GPUTexture;
+
+/* 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.
+ * - 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
+ */
+
+typedef enum GPUHDRType {
+       GPU_HDR_NONE =       0,
+       GPU_HDR_HALF_FLOAT = 1,
+       GPU_HDR_FULL_FLOAT = (1 << 1),
+} GPUHDRType;
+
+GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]);
+GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels);
+GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
+GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
+GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
+GPUTexture *GPU_texture_from_blender(struct Image *ima,
+       struct ImageUser *iuser, bool is_data, double time, int mipmap);
+GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
+void GPU_invalid_tex_init(void);
+void GPU_invalid_tex_bind(int mode);
+void GPU_invalid_tex_free(void);
+
+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);
+int GPU_texture_bound_number(GPUTexture *tex);
+
+void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter);
+
+GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
+int GPU_texture_framebuffer_attachment(GPUTexture *tex);
+void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment);
+
+int GPU_texture_target(const GPUTexture *tex);
+int GPU_texture_width(const GPUTexture *tex);
+int GPU_texture_height(const GPUTexture *tex);
+int GPU_texture_depth(const GPUTexture *tex);
+int GPU_texture_opengl_bindcode(const GPUTexture *tex);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __GPU_TEXTURE_H__ */
index 2dcee877279d1024f2cef0f19519c4b9a7f601fc..6b01ee85170b03c5391f82be9057bee2a57cd0c1 100644 (file)
  * - Optimize for case where no texture matrix is used.
  */
 
-#include "GPU_glew.h"
-
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
 
-#include "GPU_extensions.h"
 #include "GPU_basic_shader.h"
+#include "GPU_glew.h"
+#include "GPU_shader.h"
 
 /* State */
 
index c7f770111972835785a76249726c5e9a529d510a..800ed9399a905d7cd93d4c7abeb02afdd05519fc 100644 (file)
 #include "BLI_dynstr.h"
 #include "BLI_ghash.h"
 
+#include "GPU_extensions.h"
 #include "GPU_glew.h"
 #include "GPU_material.h"
-#include "GPU_extensions.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
 
 #include "BLI_sys_types.h" /* for intptr_t support */
 
index dfea4a5a72bbc142f1fa77c8249e1c3878118550..05968bf1e4c04555604592886bd1bbc1810e1a0f 100644 (file)
 #include "DNA_camera_types.h"
 #include "DNA_gpu_types.h"
 
-#include "GPU_extensions.h"
 #include "GPU_compositing.h"
-
+#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
 #include "GPU_glew.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
 
 #include "MEM_guardedalloc.h"
 
index 469e2aebad266eedc789ef9ff3fd2235b180ab2b..05d115496569d5a30db483839d321d4a7570b766 100644 (file)
 #include "BKE_subsurf.h"
 #include "BKE_DerivedMesh.h"
 
+#include "GPU_basic_shader.h"
 #include "GPU_buffers.h"
 #include "GPU_draw.h"
 #include "GPU_extensions.h"
 #include "GPU_material.h"
-#include "GPU_basic_shader.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
 
 #include "PIL_time.h"
 
index 3aab5f5421f47b70b78e005ac23387beb19bd47a..c855c53ace4862f3446cd833463c6b5f4c2238df 100644 (file)
@@ -32,9 +32,6 @@
  * with checks for drivers and GPU support.
  */
 
-
-#include "DNA_image_types.h"
-
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
 
 #include "BKE_global.h"
 
-#include "GPU_glew.h"
-#include "GPU_debug.h"
+#include "GPU_basic_shader.h"
 #include "GPU_draw.h"
 #include "GPU_extensions.h"
-#include "GPU_compositing.h"
-#include "GPU_basic_shader.h"
+#include "GPU_glew.h"
+#include "GPU_texture.h"
 
 #include "intern/gpu_private.h"
 
 #  include "BLI_winstuff.h"
 #endif
 
-/* TODO(sergey): Find better default values for this constants. */
-#define MAX_DEFINE_LENGTH 1024
-#define MAX_EXT_DEFINE_LENGTH 1024
-
 /* Extensions support */
 
 /* -- extension: version of GL that absorbs it
  * ARB_texture_query_lod: 4.0
  */
 
-/* Non-generated shaders */
-extern char datatoc_gpu_program_smoke_frag_glsl[];
-extern char datatoc_gpu_program_smoke_color_frag_glsl[];
-extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
-extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
-extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
-extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
-extern char datatoc_gpu_shader_fx_vert_glsl[];
-extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
-extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
-extern char datatoc_gpu_shader_fx_lib_glsl[];
-
-typedef struct GPUShaders {
-       GPUShader *vsm_store;
-       GPUShader *sep_gaussian_blur;
-       GPUProgram *smoke;
-       GPUProgram *smoke_colored;
-       /* cache for shader fx. Those can exist in combinations so store them here */
-       GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
-} GPUShaders;
-
 static struct GPUGlobal {
        GLint maxtexsize;
        GLint maxtextures;
-       GLuint currentfb;
        bool extdisabled;
        int colordepth;
        int samples_color_texture_max;
        GPUDeviceType device;
        GPUOSType os;
        GPUDriverType driver;
-       GPUShaders shaders;
-       GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
-       GPUTexture *invalid_tex_2D;
-       GPUTexture *invalid_tex_3D;
        float dfdyfactors[2]; /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
                                 calculate dfdy in shader differently when drawing to an offscreen buffer. First
                                 number is factor on screen and second is off-screen */
 } GG = {1, 0};
 
-/* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
-#define GPU_FB_MAX_SLOTS 4
-
-struct GPUFrameBuffer {
-       GLuint object;
-       GPUTexture *colortex[GPU_FB_MAX_SLOTS];
-       GPUTexture *depthtex;
-};
-
-
 /* GPU Types */
 
 bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
@@ -154,6 +105,16 @@ int GPU_max_texture_size(void)
        return GG.maxtexsize;
 }
 
+int GPU_max_textures(void)
+{
+       return GG.maxtextures;
+}
+
+int GPU_max_color_texture_samples(void)
+{
+       return GG.samples_color_texture_max;
+}
+
 void GPU_get_dfdy_factors(float fac[2])
 {
        copy_v2_v2(fac, GG.dfdyfactors);
@@ -323,7 +284,7 @@ bool GPU_geometry_shader_support(void)
        return (GLEW_VERSION_3_2 && GPU_legacy_support()) || GLEW_EXT_geometry_shader4;
 }
 
-static bool GPU_geometry_shader_support_via_extension(void)
+bool GPU_geometry_shader_support_via_extension(void)
 {
        return GLEW_EXT_geometry_shader4 && !(GLEW_VERSION_3_2 && GPU_legacy_support());
 }
@@ -338,1990 +299,26 @@ int GPU_color_depth(void)
        return GG.colordepth;
 }
 
-static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
-{
-       const char *err = "unknown";
-
-       switch (status) {
-               case GL_FRAMEBUFFER_COMPLETE_EXT:
-                       break;
-               case GL_INVALID_OPERATION:
-                       err = "Invalid operation";
-                       break;
-               case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
-                       err = "Incomplete attachment";
-                       break;
-               case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
-                       err = "Unsupported framebuffer format";
-                       break;
-               case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
-                       err = "Missing attachment";
-                       break;
-               case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
-                       err = "Attached images must have same dimensions";
-                       break;
-               case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
-                       err = "Attached images must have same format";
-                       break;
-               case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
-                       err = "Missing draw buffer";
-                       break;
-               case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
-                       err = "Missing read buffer";
-                       break;
-       }
-
-       if (err_out) {
-               BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
-                       (int)status, err);
-       }
-       else {
-               fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
-                       (int)status, err);
-       }
-}
-
-/* GPUTexture */
-
-struct GPUTexture {
-       int w, h;           /* width/height */
-       int number;         /* number for multitexture binding */
-       int refcount;       /* reference count */
-       GLenum target;      /* GL_TEXTURE_* */
-       GLenum target_base; /* same as target, (but no multisample) */
-       GLuint bindcode;    /* opengl identifier for texture */
-       int fromblender;    /* we got the texture from Blender */
-
-       GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
-       int fb_attachment;  /* slot the texture is attached to */
-       int depth;          /* is a depth texture? if 3D how deep? */
-};
-
-static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
-{
-       unsigned char *pixels, *p;
-       const float *fp = fpixels;
-       const int len = 4 * length;
-       int a;
-
-       p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
-
-       for (a = 0; a < len; a++, p++, fp++)
-               *p = FTOCHAR((*fp));
-
-       return pixels;
-}
-
-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, const float *fpixels, int depth,
-        GPUHDRType hdr_type, int components, int samples,
-        char err_out[256])
-{
-       GPUTexture *tex;
-       GLenum type, format, internalformat;
-       void *pixels = NULL;
-
-       if (samples) {
-               CLAMP_MAX(samples, GG.samples_color_texture_max);
-       }
-
-       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 : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
-       tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
-       tex->depth = depth;
-       tex->fb_attachment = -1;
-
-       glGenTextures(1, &tex->bindcode);
-
-       if (!tex->bindcode) {
-               if (err_out) {
-                       BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
-                               (int)glGetError());
-               }
-               else {
-                       fprintf(stderr, "GPUTexture: texture create failed: %d\n",
-                               (int)glGetError());
-               }
-               GPU_texture_free(tex);
-               return NULL;
-       }
-
-       if (!GPU_full_non_power_of_two_support()) {
-               tex->w = power_of_2_max_i(tex->w);
-               tex->h = power_of_2_max_i(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_FLOAT;
-
-               if (components == 4) {
-                       format = GL_RGBA;
-                       switch (hdr_type) {
-                               case GPU_HDR_NONE:
-                                       internalformat = GL_RGBA8;
-                                       break;
-                               /* the following formats rely on ARB_texture_float or OpenGL 3.0 */
-                               case GPU_HDR_HALF_FLOAT:
-                                       internalformat = GL_RGBA16F_ARB;
-                                       break;
-                               case GPU_HDR_FULL_FLOAT:
-                                       internalformat = GL_RGBA32F_ARB;
-                                       break;
-                               default:
-                                       break;
-                       }
-               }
-               else if (components == 2) {
-                       /* these formats rely on ARB_texture_rg or OpenGL 3.0 */
-                       format = GL_RG;
-                       switch (hdr_type) {
-                               case GPU_HDR_NONE:
-                                       internalformat = GL_RG8;
-                                       break;
-                               case GPU_HDR_HALF_FLOAT:
-                                       internalformat = GL_RG16F;
-                                       break;
-                               case GPU_HDR_FULL_FLOAT:
-                                       internalformat = GL_RG32F;
-                                       break;
-                               default:
-                                       break;
-                       }
-               }
-
-               if (fpixels && hdr_type == GPU_HDR_NONE) {
-                       type = GL_UNSIGNED_BYTE;
-                       pixels = GPU_texture_convert_pixels(w*h, fpixels);
-               }
-       }
-
-       if (tex->target == GL_TEXTURE_1D) {
-               glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
-
-               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 {
-               if (samples) {
-                       glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
-               }
-               else {
-                       glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
-                                    format, type, NULL);
-               }
-
-               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_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-               glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-               glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
-               glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
-               glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
-       }
-       else {
-               glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-       }
-
-       if (tex->target_base != GL_TEXTURE_1D) {
-               glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-               glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-       }
-       else
-               glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-
-       return tex;
-}
-
-
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
-{
-       GPUTexture *tex;
-       GLenum type, format, internalformat;
-       void *pixels = NULL;
-       int r_width;
-       bool rescale = false;
-
-       tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
-       tex->w = w;
-       tex->h = h;
-       tex->depth = depth;
-       tex->number = -1;
-       tex->refcount = 1;
-       tex->target = GL_TEXTURE_3D;
-       tex->target_base = GL_TEXTURE_3D;
-
-       glGenTextures(1, &tex->bindcode);
-
-       if (!tex->bindcode) {
-               fprintf(stderr, "GPUTexture: texture create failed: %d\n",
-                       (int)glGetError());
-               GPU_texture_free(tex);
-               return NULL;
-       }
-
-       tex->number = 0;
-       glBindTexture(tex->target, tex->bindcode);
-
-       GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
-
-       type = GL_FLOAT;
-       if (channels == 4) {
-               format = GL_RGBA;
-               internalformat = GL_RGBA8;
-       }
-       else {
-               format = GL_RED;
-               internalformat = GL_INTENSITY8;
-       }
-
-       /* 3D textures are quite heavy, test if it's possible to create them first */
-       glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
-       glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
-
-       while (r_width == 0) {
-               rescale = true;
-               tex->w /= 2;
-               tex->h /= 2;
-               tex->depth /= 2;
-               glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
-               glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
-       }
-
-       /* really unlikely to happen but keep this just in case */
-       tex->w = max_ii(tex->w, 1);
-       tex->h = max_ii(tex->h, 1);
-       tex->depth = max_ii(tex->depth, 1);
-
-#if 0
-       if (fpixels)
-               pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
-#endif
-
-       GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
-
-       /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
-        * for gooseberry */
-       if (rescale && fpixels) {
-               unsigned int i, j, k;
-               unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
-               float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d");
-
-               GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
-
-               for (k = 0; k < tex->depth; k++) {
-                       for (j = 0; j < tex->h; j++) {
-                               for (i = 0; i < tex->w; i++) {
-                                       /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */
-                                       float xb = i * xf;
-                                       float yb = j * yf;
-                                       float zb = k * zf;
-                                       unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
-                                       unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
-
-                                       if (channels == 4) {
-                                               tex3d[offset * 4] = fpixels[offset_orig * 4];
-                                               tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
-                                               tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
-                                               tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
-                                       }
-                                       else
-                                               tex3d[offset] = fpixels[offset_orig];
-                               }
-                       }
-               }
-
-               glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
-
-               MEM_freeN(tex3d);
-       }
-       else {
-               if (fpixels) {
-                       glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
-                       GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
-               }
-       }
-
-
-       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
-       if (pixels)
-               MEM_freeN(pixels);
-
-       GPU_texture_unbind(tex);
-
-       return tex;
-}
-
-GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data, double time, int mipmap)
-{
-       GPUTexture *tex;
-       GLint w, h, border, bindcode;
-
-       GPU_update_image_time(ima, time);
-       /* this binds a texture, so that's why to restore it to 0 */
-       bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, is_data);
-
-       if (ima->gputexture) {
-               ima->gputexture->bindcode = bindcode;
-               glBindTexture(GL_TEXTURE_2D, 0);
-               return ima->gputexture;
-       }
-
-       tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
-       tex->bindcode = bindcode;
-       tex->number = -1;
-       tex->refcount = 1;
-       tex->target = GL_TEXTURE_2D;
-       tex->target_base = GL_TEXTURE_2D;
-       tex->fromblender = 1;
-
-       ima->gputexture= tex;
-
-       if (!glIsTexture(tex->bindcode)) {
-               GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
-       }
-       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, 0);
-
-       return tex;
-}
-
-GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
-{
-       GPUTexture *tex = prv->gputexture[0];
-       GLint w, h;
-       GLuint bindcode = 0;
-       
-       if (tex)
-               bindcode = tex->bindcode;
-       
-       /* this binds a texture, so that's why we restore it to 0 */
-       if (bindcode == 0) {
-               GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL);
-       }
-       if (tex) {
-               tex->bindcode = bindcode;
-               glBindTexture(GL_TEXTURE_2D, 0);
-               return tex;
-       }
-
-       tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
-       tex->bindcode = bindcode;
-       tex->number = -1;
-       tex->refcount = 1;
-       tex->target = GL_TEXTURE_2D;
-       tex->target_base = GL_TEXTURE_2D;
-       
-       prv->gputexture[0] = tex;
-       
-       if (!glIsTexture(tex->bindcode)) {
-               GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
-       }
-       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);
-               
-               tex->w = w;
-               tex->h = h;
-       }
-       
-       glBindTexture(GL_TEXTURE_2D, 0);
-       
-       return tex;
-}
-
-GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
-{
-       GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
-
-       if (tex)
-               GPU_texture_unbind(tex);
-       
-       return tex;
-}
-
-GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
-{
-       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
-
-       if (tex)
-               GPU_texture_unbind(tex);
-       
-       return tex;
-}
-GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
-{
-       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
-
-       if (tex)
-               GPU_texture_unbind(tex);
-
-       return tex;
-}
-
-GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
-{
-       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
-
-       if (tex)
-               GPU_texture_unbind(tex);
-       
-       return tex;
-}
-GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
-{
-       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
-
-       if (tex)
-               GPU_texture_unbind(tex);
-
-       return tex;
-}
-
-/**
- * A shadow map for VSM needs two components (depth and depth^2)
- */
-GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
-{
-       GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
-
-       if (tex) {
-               /* Now we tweak some of the settings */
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-               GPU_texture_unbind(tex);
-       }
-
-       return tex;
-}
-
-GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
-{
-       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
-
-       if (tex) {
-               /* Now we tweak some of the settings */
-               if (repeat) {
-                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-               }
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
-               GPU_texture_unbind(tex);
-       }
-
-       return tex;
-}
-
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
-{
-       GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
-
-       if (tex) {
-               /* Now we tweak some of the settings */
-               glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-               glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-               glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
-               GPU_texture_unbind(tex);
-       }
-
-       return tex;
-}
-
-void GPU_invalid_tex_init(void)
-{
-       const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
-       GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
-       GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
-       GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
-}
-
-void GPU_invalid_tex_bind(int mode)
-{
-       switch (mode) {
-               case GL_TEXTURE_1D:
-                       glBindTexture(GL_TEXTURE_1D, GG.invalid_tex_1D->bindcode);
-                       break;
-               case GL_TEXTURE_2D:
-                       glBindTexture(GL_TEXTURE_2D, GG.invalid_tex_2D->bindcode);
-                       break;
-               case GL_TEXTURE_3D:
-                       glBindTexture(GL_TEXTURE_3D, GG.invalid_tex_3D->bindcode);
-                       break;
-       }
-}
-
-void GPU_invalid_tex_free(void)
-{
-       if (GG.invalid_tex_1D)
-               GPU_texture_free(GG.invalid_tex_1D);
-       if (GG.invalid_tex_2D)
-               GPU_texture_free(GG.invalid_tex_2D);
-       if (GG.invalid_tex_3D)
-               GPU_texture_free(GG.invalid_tex_3D);
-}
-
-
-void GPU_texture_bind(GPUTexture *tex, int number)
+bool GPU_mem_stats_supported(void)
 {
-       GLenum arbnumber;
-
-       if (number >= GG.maxtextures) {
-               fprintf(stderr, "Not enough texture slots.\n");
-               return;
-       }
-
-       if ((G.debug & G_DEBUG)) {
-               if (tex->fb && tex->fb->object == GG.currentfb) {
-                       fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
-               }
-       }
-
-       if (number < 0)
-               return;
-
-       GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
-
-       arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
-       if (number != 0) glActiveTexture(arbnumber);
-       if (tex->bindcode != 0) {
-               glBindTexture(tex->target, tex->bindcode);
-       }
-       else
-               GPU_invalid_tex_bind(tex->target);
-       glEnable(tex->target);
-       if (number != 0) glActiveTexture(GL_TEXTURE0);
-
-       tex->number = number;
-
-       GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
+       return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
 }
 
-void GPU_texture_unbind(GPUTexture *tex)
-{
-       GLenum arbnumber;
-
-       if (tex->number >= GG.maxtextures) {
-               fprintf(stderr, "Not enough texture slots.\n");
-               return;
-       }
-
-       if (tex->number == -1)
-               return;
-       
-       GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
-
-       arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
-       if (tex->number != 0) glActiveTexture(arbnumber);
-       glBindTexture(tex->target, 0);
-       glDisable(tex->target_base);
-       if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
 
-       tex->number = -1;
-
-       GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
-}
-
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
+void GPU_mem_stats_get(int *totalmem, int *freemem)
 {
-       GLenum arbnumber;
-
-       if (tex->number >= GG.maxtextures) {
-               fprintf(stderr, "Not enough texture slots.\n");
-               return;
-       }
-
-       if (tex->number == -1)
-               return;
-
-       GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
-
-       arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
-       if (tex->number != 0) glActiveTexture(arbnumber);
+       if (GLEW_NVX_gpu_memory_info) {
+               /* returned value in Kb */
+               glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
 
-       if (tex->depth) {
-               if (compare)
-                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
-               else
-                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+               glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
        }
+       else if (GLEW_ATI_meminfo) {
+               int stats[4];
 
-       if (use_filter) {
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-       }
-       else {
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-       }
-       if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
-
-       GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
-}
-
-void GPU_texture_free(GPUTexture *tex)
-{
-       tex->refcount--;
-
-       if (tex->refcount < 0)
-               fprintf(stderr, "GPUTexture: negative refcount\n");
-       
-       if (tex->refcount == 0) {
-               if (tex->fb)
-                       GPU_framebuffer_texture_detach(tex);
-               if (tex->bindcode && !tex->fromblender)
-                       glDeleteTextures(1, &tex->bindcode);
-
-               MEM_freeN(tex);
-       }
-}
-
-void GPU_texture_ref(GPUTexture *tex)
-{
-       tex->refcount++;
-}
-
-int GPU_texture_target(const GPUTexture *tex)
-{
-       return tex->target;
-}
-
-int GPU_texture_width(const GPUTexture *tex)
-{
-       return tex->w;
-}
-
-int GPU_texture_height(const GPUTexture *tex)
-{
-       return tex->h;
-}
-
-int GPU_texture_opengl_bindcode(const GPUTexture *tex)
-{
-       return tex->bindcode;
-}
-
-GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
-{
-       return tex->fb;
-}
-
-/* GPUFrameBuffer */
-
-GPUFrameBuffer *GPU_framebuffer_create(void)
-{
-       GPUFrameBuffer *fb;
-
-       if (!(GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object || (GLEW_EXT_framebuffer_object && GLEW_EXT_framebuffer_blit)))
-               return NULL;
-       
-       fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
-       glGenFramebuffersEXT(1, &fb->object);
-
-       if (!fb->object) {
-               fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
-                       (int)glGetError());
-               GPU_framebuffer_free(fb);
-               return NULL;
-       }
-
-       /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
-       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
-       glReadBuffer(GL_NONE);
-       glDrawBuffer(GL_NONE);
-       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-       
-       return fb;
-}
-
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
-{
-       GLenum attachment;
-       GLenum error;
-
-       if (slot >= GPU_FB_MAX_SLOTS) {
-               fprintf(stderr,
-                       "Attaching to index %d framebuffer slot unsupported. "
-                       "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
-               return 0;
-       }
-
-       if ((G.debug & G_DEBUG)) {
-               if (tex->number != -1) {
-                       fprintf(stderr,
-                               "Feedback loop warning!: "
-                               "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
-               }
-       }
-
-       if (tex->depth)
-               attachment = GL_DEPTH_ATTACHMENT_EXT;
-       else
-               attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
-
-       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
-       GG.currentfb = fb->object;
-
-       /* Clean glError buffer. */
-       while (glGetError() != GL_NO_ERROR) {}
-
-       glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 
-               tex->target, tex->bindcode, 0);
-
-       error = glGetError();
-
-       if (error == GL_INVALID_OPERATION) {
-               GPU_framebuffer_restore();
-               GPU_print_framebuffer_error(error, err_out);
-               return 0;
-       }
-
-       if (tex->depth)
-               fb->depthtex = tex;
-       else
-               fb->colortex[slot] = tex;
-
-       tex->fb= fb;
-       tex->fb_attachment = slot;
-
-       return 1;
-}
-
-void GPU_framebuffer_texture_detach(GPUTexture *tex)
-{
-       GLenum attachment;
-       GPUFrameBuffer *fb;
-
-       if (!tex->fb)
-               return;
-
-       fb = tex->fb;
-
-       if (GG.currentfb != fb->object) {
-               glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
-               GG.currentfb = tex->fb->object;
-       }
-
-       if (tex->depth) {
-               fb->depthtex = NULL;
-               attachment = GL_DEPTH_ATTACHMENT_EXT;
-       }
-       else {
-               BLI_assert(fb->colortex[tex->fb_attachment] == tex);
-               fb->colortex[tex->fb_attachment] = NULL;
-               attachment = GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment;
-       }
-
-       glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, tex->target, 0, 0);
-
-       tex->fb = NULL;
-       tex->fb_attachment = -1;
-}
-
-void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
-{
-       if (!tex->fb) {
-               fprintf(stderr, "Error, texture not bound to framebuffer!\n");
-               return;
-       }
-
-       /* push attributes */
-       glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
-       glDisable(GL_SCISSOR_TEST);
-
-       /* bind framebuffer */
-       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
-
-       if (tex->depth) {
-               glDrawBuffer(GL_NONE);
-               glReadBuffer(GL_NONE);
-       }
-       else {
-               /* last bound prevails here, better allow explicit control here too */
-               glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
-               glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
-       }
-       
-       if (tex->target == GL_TEXTURE_2D_MULTISAMPLE) {
-               glEnable(GL_MULTISAMPLE);
-       }
-
-       /* push matrices and set default viewport and matrix */
-       glViewport(0, 0, tex->w, tex->h);
-       GG.currentfb = tex->fb->object;
-
-       glMatrixMode(GL_PROJECTION);
-       glPushMatrix();
-       glMatrixMode(GL_MODELVIEW);
-       glPushMatrix();
-}
-
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
-{
-       int numslots = 0, i;
-       GLenum attachments[4];
-       
-       if (!fb->colortex[slot]) {
-               fprintf(stderr, "Error, framebuffer slot empty!\n");
-               return;
-       }
-       
-       for (i = 0; i < 4; i++) {
-               if (fb->colortex[i]) {
-                       attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
-                       numslots++;
-               }
-       }
-       
-       /* push attributes */
-       glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
-       glDisable(GL_SCISSOR_TEST);
-
-       /* bind framebuffer */
-       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
-
-       /* last bound prevails here, better allow explicit control here too */
-       glDrawBuffers(numslots, attachments);
-       glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
-
-       /* push matrices and set default viewport and matrix */
-       glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
-       GG.currentfb = fb->object;
-
-       glMatrixMode(GL_PROJECTION);
-       glPushMatrix();
-       glMatrixMode(GL_MODELVIEW);
-       glPushMatrix();
-}
-
-
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
-{
-       /* restore matrix */
-       glMatrixMode(GL_PROJECTION);
-       glPopMatrix();
-       glMatrixMode(GL_MODELVIEW);
-       glPopMatrix();
-
-       /* restore attributes */
-       glPopAttrib();
-}
-
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
-{
-       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
-       /* last bound prevails here, better allow explicit control here too */
-       glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
-       glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
-
-       /* push matrices and set default viewport and matrix */
-       glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
-       GG.currentfb = fb->object;
-       GG.currentfb = fb->object;
-}
-
-bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
-{
-       GLenum status;
-       
-       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
-       GG.currentfb = fb->object;
-       
-       /* Clean glError buffer. */
-       while (glGetError() != GL_NO_ERROR) {}
-       
-       status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-       
-       if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
-               GPU_framebuffer_restore();
-               GPU_print_framebuffer_error(status, err_out);
-               return false;
-       }
-       
-       return true;
-}
-
-void GPU_framebuffer_free(GPUFrameBuffer *fb)
-{
-       int i;
-       if (fb->depthtex)
-               GPU_framebuffer_texture_detach(fb->depthtex);
-
-       for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
-               if (fb->colortex[i]) {
-                       GPU_framebuffer_texture_detach(fb->colortex[i]);
-               }
-       }
-
-       if (fb->object) {
-               glDeleteFramebuffersEXT(1, &fb->object);
-
-               if (GG.currentfb == fb->object) {
-                       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-                       GG.currentfb = 0;
-               }
-       }
-
-       MEM_freeN(fb);
-}
-
-void GPU_framebuffer_restore(void)
-{
-       if (GG.currentfb != 0) {
-               glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-               GG.currentfb = 0;
-       }
-}
-
-void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
-{
-       const float scaleh[2] = {1.0f / blurtex->w, 0.0f};
-       const float scalev[2] = {0.0f, 1.0f / tex->h};
-
-       GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
-       int scale_uniform, texture_source_uniform;
-
-       if (!blur_shader)
-               return;
-
-       scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
-       texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
-               
-       /* Blurring horizontally */
-
-       /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
-        * pushing unnecessary matrices onto the OpenGL stack. */
-       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
-       glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-       
-       /* avoid warnings from texture binding */
-       GG.currentfb = blurfb->object;
-
-       GPU_shader_bind(blur_shader);
-       GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
-       GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
-       glViewport(0, 0, blurtex->w, blurtex->h);
-
-       /* Peparing to draw quad */
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
-       glMatrixMode(GL_TEXTURE);
-       glLoadIdentity();
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-
-       glDisable(GL_DEPTH_TEST);
-
-       GPU_texture_bind(tex, 0);
-
-       /* Drawing quad */
-       glBegin(GL_QUADS);
-       glTexCoord2d(0, 0); glVertex2f(1, 1);
-       glTexCoord2d(1, 0); glVertex2f(-1, 1);
-       glTexCoord2d(1, 1); glVertex2f(-1, -1);
-       glTexCoord2d(0, 1); glVertex2f(1, -1);
-       glEnd();
-
-       /* Blurring vertically */
-
-       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
-       glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-       
-       GG.currentfb = fb->object;
-       
-       glViewport(0, 0, tex->w, tex->h);
-       GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
-       GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
-       GPU_texture_bind(blurtex, 0);
-
-       glBegin(GL_QUADS);
-       glTexCoord2d(0, 0); glVertex2f(1, 1);
-       glTexCoord2d(1, 0); glVertex2f(-1, 1);
-       glTexCoord2d(1, 1); glVertex2f(-1, -1);
-       glTexCoord2d(0, 1); glVertex2f(1, -1);
-       glEnd();
-
-       GPU_shader_unbind();
-}
-
-/* GPUOffScreen */
-
-struct GPUOffScreen {
-       GPUFrameBuffer *fb;
-       GPUTexture *color;
-       GPUTexture *depth;
-};
-
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256])
-{
-       GPUOffScreen *ofs;
-
-       ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
-
-       ofs->fb = GPU_framebuffer_create();
-       if (!ofs->fb) {
-               GPU_offscreen_free(ofs);
-               return NULL;
-       }
-
-       if (samples) {
-               if (!GLEW_EXT_framebuffer_multisample ||
-                   !GLEW_ARB_texture_multisample ||
-                   /* Only needed for GPU_offscreen_read_pixels.
-                    * We could add an arg if we intend to use multi-sample
-                    * offscreen buffers w/o reading their pixels */
-                   !GLEW_EXT_framebuffer_blit ||
-                   /* This is required when blitting from a multi-sampled buffers,
-                    * even though we're not scaling. */
-                   !GLEW_EXT_framebuffer_multisample_blit_scaled)
-               {
-                       samples = 0;
-               }
-       }
-
-       ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out);
-       if (!ofs->depth) {
-               GPU_offscreen_free(ofs);
-               return NULL;
-       }
-
-       if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
-               GPU_offscreen_free(ofs);
-               return NULL;
-       }
-
-       ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
-       if (!ofs->color) {
-               GPU_offscreen_free(ofs);
-               return NULL;
-       }
-
-       if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
-               GPU_offscreen_free(ofs);
-               return NULL;
-       }
-       
-       /* check validity at the very end! */
-       if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
-               GPU_offscreen_free(ofs);
-               return NULL;            
-       }
-
-       GPU_framebuffer_restore();
-
-       return ofs;
-}
-
-void GPU_offscreen_free(GPUOffScreen *ofs)
-{
-       if (ofs->fb)
-               GPU_framebuffer_free(ofs->fb);
-       if (ofs->color)
-               GPU_texture_free(ofs->color);
-       if (ofs->depth)
-               GPU_texture_free(ofs->depth);
-       
-       MEM_freeN(ofs);
-}
-
-void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
-{
-       glDisable(GL_SCISSOR_TEST);
-       if (save)
-               GPU_texture_bind_as_framebuffer(ofs->color);
-       else {
-               GPU_framebuffer_bind_no_save(ofs->fb, 0);
-       }
-}
-
-void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
-{
-       if (restore)
-               GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
-       GPU_framebuffer_restore();
-       glEnable(GL_SCISSOR_TEST);
-}
-
-void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
-{
-       const int w = ofs->color->w;
-       const int h = ofs->color->h;
-
-       if (ofs->color->target == GL_TEXTURE_2D_MULTISAMPLE) {
-               /* For a multi-sample texture,
-                * we need to create an intermediate buffer to blit to,
-                * before its copied using 'glReadPixels' */
-
-               /* not needed since 'ofs' needs to be bound to the framebuffer already */
-// #define USE_FBO_CTX_SWITCH
-
-               GLuint fbo_blit = 0;
-               GLuint tex_blit = 0;
-               GLenum status;
-
-               /* create texture for new 'fbo_blit' */
-               glGenTextures(1, &tex_blit);
-               if (!tex_blit) {
-                       goto finally;
-               }
-
-               glBindTexture(GL_TEXTURE_2D, tex_blit);
-               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, type, 0);
-
-#ifdef USE_FBO_CTX_SWITCH
-               /* read from multi-sample buffer */
-               glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, ofs->color->fb->object);
-               glFramebufferTexture2DEXT(
-                       GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + ofs->color->fb_attachment,
-                       GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
-               status = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT);
-               if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
-                       goto finally;
-               }
-#endif
-
-               /* write into new single-sample buffer */
-               glGenFramebuffersEXT(1, &fbo_blit);
-               glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_blit);
-               glFramebufferTexture2DEXT(
-                       GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-                       GL_TEXTURE_2D, tex_blit, 0);
-               status = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
-               if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
-                       goto finally;
-               }
-
-               /* perform the copy */
-               glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
-
-               /* read the results */
-               glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo_blit);
-               glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
-
-#ifdef USE_FBO_CTX_SWITCH
-               /* restore the original frame-bufer */
-               glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ofs->color->fb->object);
-#undef USE_FBO_CTX_SWITCH
-#endif
-
-
-finally:
-               /* cleanup */
-               if (tex_blit) {
-                       glDeleteTextures(1, &tex_blit);
-               }
-               if (fbo_blit) {
-                       glDeleteFramebuffersEXT(1, &fbo_blit);
-               }
-
-               GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
-       }
-       else {
-               glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
-       }
-}
-
-int GPU_offscreen_width(const GPUOffScreen *ofs)
-{
-       return ofs->color->w;
-}
-
-int GPU_offscreen_height(const GPUOffScreen *ofs)
-{
-       return ofs->color->h;
-}
-
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
-{
-       return ofs->color->bindcode;
-}
-
-/* GPUShader */
-
-struct GPUShader {
-       GLuint program;  /* handle for full program (links shader stages below) */
-
-       GLuint vertex;   /* handle for vertex shader */
-       GLuint geometry; /* handle for geometry shader */
-       GLuint fragment; /* handle for fragment shader */
-
-       int totattrib;   /* total number of attributes */
-       int uniforms;    /* required uniforms */
-};
-
-struct GPUProgram {
-       GPUProgramType type;
-       GLuint prog;
-};
-
-
-static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
-{
-       int i;
-       int line = 1;
-
-       fprintf(stderr, "GPUShader: %s error:\n", task);
-
-       for (i = 0; i < totcode; i++) {
-               const char *c, *pos, *end = code[i] + strlen(code[i]);
-
-               if (G.debug & G_DEBUG) {
-                       fprintf(stderr, "===== shader string %d ====\n", i + 1);
-
-                       c = code[i];
-                       while ((c < end) && (pos = strchr(c, '\n'))) {
-                               fprintf(stderr, "%2d  ", line);
-                               fwrite(c, (pos + 1) - c, 1, stderr);
-                               c = pos + 1;
-                               line++;
-                       }
-                       
-                       fprintf(stderr, "%s", c);
-               }
-       }
-       
-       fprintf(stderr, "%s\n", log);
-}
-
-static const char *gpu_shader_version(void)
-{
-       if (GLEW_VERSION_3_2) {
-               if (GPU_legacy_support()) {
-                       return "#version 150 compatibility\n";
-                       /* highest version that is widely supported
-                        * gives us native geometry shaders!
-                        * use compatibility profile so we can continue using builtin shader input/output names
-                        */
-               }
-               else {
-                       return "#version 130\n";
-                       /* latest version that is compatible with existing shaders */
-               }
-       }
-       else if (GLEW_VERSION_3_1) {
-               if (GLEW_ARB_compatibility) {
-                       return "#version 140\n";
-                       /* also need the ARB_compatibility extension, handled below */
-               }
-               else {
-                       return "#version 130\n";
-                       /* latest version that is compatible with existing shaders */
-               }
-       }
-       else if (GLEW_VERSION_3_0) {
-               return "#version 130\n";
-               /* GLSL 1.3 has modern syntax/keywords/datatypes so use if available
-                * older features are deprecated but still available without compatibility extension or profile
-                */
-       }
-       else {
-               return "#version 120\n";
-               /* minimum supported */
-       }
-}
-
-
-static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_geometry_shader)
-{
-       /* enable extensions for features that are not part of our base GLSL version
-        * don't use an extension for something already available!
-        */
-
-       if (GLEW_ARB_texture_query_lod) {
-               /* a #version 400 feature, but we use #version 150 maximum so use extension */
-               strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
-       }
-
-       if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) {
-               strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
-       }
-
-       if (GLEW_VERSION_3_1 && !GLEW_VERSION_3_2 && GLEW_ARB_compatibility) {
-               strcat(defines, "#extension GL_ARB_compatibility: enable\n");
-       }
-
-       if (!GLEW_VERSION_3_1) {
-               if (GLEW_ARB_draw_instanced) {
-                       strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
-               }
-
-               if (!GLEW_VERSION_3_0 && GLEW_EXT_gpu_shader4) {
-                       strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
-                       /* TODO: maybe require this? shaders become so much nicer */
-               }
-       }
-}
-
-static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], bool use_opensubdiv)
-{
-       /* some useful defines to detect GPU type */
-       if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
-               strcat(defines, "#define GPU_ATI\n");
-               if (GLEW_VERSION_3_0) {
-                       /* TODO(merwin): revisit this version check; GLEW_VERSION_3_0 means GL 3.0 or newer */
-                       strcat(defines, "#define CLIP_WORKAROUND\n");
-               }
-       }
-       else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
-               strcat(defines, "#define GPU_NVIDIA\n");
-       else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
-               strcat(defines, "#define GPU_INTEL\n");
-
-       if (GPU_bicubic_bump_support())
-               strcat(defines, "#define BUMP_BICUBIC\n");
-
-#ifdef WITH_OPENSUBDIV
-       /* TODO(sergey): Check whether we actually compiling shader for
-        * the OpenSubdiv mesh.
-        */
-       if (use_opensubdiv) {
-               strcat(defines, "#define USE_OPENSUBDIV\n");
-
-               /* TODO(sergey): not strictly speaking a define, but this is
-                * a global typedef which we don't have better place to define
-                * in yet.
-                */
-               strcat(defines, "struct VertexData {\n"
-                               "  vec4 position;\n"
-                               "  vec3 normal;\n"
-                               "  vec2 uv;"
-                               "};\n");
-       }
-#else
-       UNUSED_VARS(use_opensubdiv);
-#endif
-
-       return;
-}
-
-void GPU_program_bind(GPUProgram *program)
-{
-       glEnable(program->type);
-       glBindProgramARB(program->type, program->prog);
-}
-
-void GPU_program_unbind(GPUProgram *program)
-{
-       glDisable(program->type);
-       glBindProgramARB(program->type, 0);
-}
-
-
-GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code)
-{
-       /* TODO(merwin): remove ARB program support (recode smoke shader in GLSL) */
-
-       GPUProgram *program;
-       GLint error_pos, is_native;
-
-       if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT))
-               return NULL;
-
-       program = MEM_callocN(sizeof(GPUProgram), "GPUProgram");
-
-       switch (type) {
-               case GPU_PROGRAM_TYPE_FRAGMENT:
-                       program->type = GL_FRAGMENT_PROGRAM_ARB;
-                       break;
-       }
-
-       /* create the object and set its code string */
-       glGenProgramsARB(1, &program->prog);
-       glBindProgramARB(program->type, program->prog);
-
-       glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code);
-
-       glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
-       glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native);
-       if ((error_pos == -1) && (is_native == 1)) {
-               return program;
-       }
-       else {
-               /* glGetError is set before that, clear it */
-               while (glGetError() != GL_NO_ERROR)
-                       ;
-               shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1);
-               MEM_freeN(program);
-       }
-
-       return NULL;
-}
-
-void GPU_program_free(GPUProgram *program)
-{
-       glDeleteProgramsARB(1, &program->prog);
-       MEM_freeN(program);
-}
-
-void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w)
-{
-       glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
-}
-
-GPUShader *GPU_shader_create(const char *vertexcode,
-                             const char *fragcode,
-                             const char *geocode,
-                             const char *libcode,
-                             const char *defines,
-                             int input,
-                             int output,
-                             int number)
-{
-       return GPU_shader_create_ex(vertexcode,
-                                   fragcode,
-                                   geocode,
-                                   libcode,
-                                   defines,
-                                   input,
-                                   output,
-                                   number,
-                                   GPU_SHADER_FLAGS_NONE);
-}
-
-GPUShader *GPU_shader_create_ex(const char *vertexcode,
-                                const char *fragcode,
-                                const char *geocode,
-                                const char *libcode,
-                                const char *defines,
-                                int input,
-                                int output,
-                                int number,
-                                const int flags)
-{
-#ifdef WITH_OPENSUBDIV
-       /* TODO(sergey): used to add #version 150 to the geometry shader.
-        * Could safely be renamed to "use_geometry_code" since it's very
-        * likely any of geometry code will want to use GLSL 1.5.
-        */
-       bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
-#else
-       UNUSED_VARS(flags);
-       bool use_opensubdiv = false;
-#endif
-       GLint status;
-       GLchar log[5000];
-       GLsizei length = 0;
-       GPUShader *shader;
-       char standard_defines[MAX_DEFINE_LENGTH] = "";
-       char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
-
-       if (geocode && !GPU_geometry_shader_support())
-               return NULL;
-
-       shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
-
-       if (vertexcode)
-               shader->vertex = glCreateShader(GL_VERTEX_SHADER);
-       if (fragcode)
-               shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
-       if (geocode)
-               shader->geometry = glCreateShader(GL_GEOMETRY_SHADER_EXT);
-
-       shader->program = glCreateProgram();
-
-       if (!shader->program ||
-           (vertexcode && !shader->vertex) ||
-           (fragcode && !shader->fragment) ||
-           (geocode && !shader->geometry))
-       {
-               fprintf(stderr, "GPUShader, object creation failed.\n");
-               GPU_shader_free(shader);
-               return NULL;
-       }
-
-       gpu_shader_standard_defines(standard_defines, use_opensubdiv);
-       gpu_shader_standard_extensions(standard_extensions, geocode != NULL);
-
-       if (vertexcode) {
-               const char *source[5];
-               /* custom limit, may be too small, beware */
-               int num_source = 0;
-
-               source[num_source++] = gpu_shader_version();
-               source[num_source++] = standard_extensions;
-               source[num_source++] = standard_defines;
-
-               if (defines) source[num_source++] = defines;
-               source[num_source++] = vertexcode;
-
-               glAttachShader(shader->program, shader->vertex);
-               glShaderSource(shader->vertex, num_source, source, NULL);
-
-               glCompileShader(shader->vertex);
-               glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status);
-
-               if (!status) {
-                       glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log);
-                       shader_print_errors("compile", log, source, num_source);
-
-                       GPU_shader_free(shader);
-                       return NULL;
-               }
-       }
-
-       if (fragcode) {
-               const char *source[7];
-               int num_source = 0;
-
-               source[num_source++] = gpu_shader_version();
-               source[num_source++] = standard_extensions;
-               source[num_source++] = standard_defines;
-
-#ifdef WITH_OPENSUBDIV
-               /* TODO(sergey): Move to fragment shader source code generation. */
-               if (use_opensubdiv) {
-                       source[num_source++] =
-                               "#ifdef USE_OPENSUBDIV\n"
-                               "in block {\n"
-                               "       VertexData v;\n"
-                               "} inpt;\n"
-                               "#endif\n";
-               }
-#endif
-
-               if (defines) source[num_source++] = defines;
-               if (libcode) source[num_source++] = libcode;
-               source[num_source++] = fragcode;
-
-               glAttachShader(shader->program, shader->fragment);
-               glShaderSource(shader->fragment, num_source, source, NULL);
-
-               glCompileShader(shader->fragment);
-               glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status);
-
-               if (!status) {
-                       glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log);
-                       shader_print_errors("compile", log, source, num_source);
-
-                       GPU_shader_free(shader);
-                       return NULL;
-               }
-       }
-
-       if (geocode) {
-               const char *source[6];
-               int num_source = 0;
-
-               source[num_source++] = gpu_shader_version();
-               source[num_source++] = standard_extensions;
-               source[num_source++] = standard_defines;
-
-               if (defines) source[num_source++] = defines;
-               source[num_source++] = geocode;
-
-               glAttachShader(shader->program, shader->geometry);
-               glShaderSource(shader->geometry, num_source, source, NULL);
-
-               glCompileShader(shader->geometry);
-               glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status);
-
-               if (!status) {
-                       glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log);
-                       shader_print_errors("compile", log, source, num_source);
-
-                       GPU_shader_free(shader);
-                       return NULL;
-               }
-               
-               if (!use_opensubdiv) {
-                       GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
-               }
-       }
-
-#ifdef WITH_OPENSUBDIV
-       if (use_opensubdiv) {
-               glBindAttribLocation(shader->program, 0, "position");
-               glBindAttribLocation(shader->program, 1, "normal");
-               GPU_shader_geometry_stage_primitive_io(shader,
-                                                      GL_LINES_ADJACENCY_EXT,
-                                                      GL_TRIANGLE_STRIP,
-                                                      4);
-       }
-#endif
-
-       glLinkProgram(shader->program);
-       glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
-       if (!status) {
-               glGetProgramInfoLog(shader->program, sizeof(log), &length, log);
-               /* print attached shaders in pipeline order */
-               if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1);
-               if (geocode) shader_print_errors("linking", log, &geocode, 1);
-               if (libcode) shader_print_errors("linking", log, &libcode, 1);
-               if (fragcode) shader_print_errors("linking", log, &fragcode, 1);
-
-               GPU_shader_free(shader);
-               return NULL;
-       }
-
-#ifdef WITH_OPENSUBDIV
-       /* TODO(sergey): Find a better place for this. */
-       if (use_opensubdiv && GLEW_VERSION_4_1) {
-               glProgramUniform1i(shader->program,
-                                  glGetUniformLocation(shader->program, "FVarDataBuffer"),
-                                  31);  /* GL_TEXTURE31 */
-       }
-#endif
-
-       return shader;
-}
-
-void GPU_shader_bind(GPUShader *shader)
-{
-       GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
-       glUseProgram(shader->program);
-       GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
-}
-
-void GPU_shader_unbind(void)
-{
-       GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
-       glUseProgram(0);
-       GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
-}
-
-void GPU_shader_free(GPUShader *shader)
-{
-       if (shader->vertex)
-               glDeleteShader(shader->vertex);
-       if (shader->geometry)
-               glDeleteShader(shader->geometry);
-       if (shader->fragment)
-               glDeleteShader(shader->fragment);
-       if (shader->program)
-               glDeleteProgram(shader->program);
-       MEM_freeN(shader);
-}
-
-int GPU_shader_get_uniform(GPUShader *shader, const char *name)
-{
-       return glGetUniformLocation(shader->program, name);
-}
-
-void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
-{
-       if (location == -1 || value == NULL)
-               return;
-
-       GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
-       if (length == 1) glUniform1fv(location, arraysize, value);
-       else if (length == 2) glUniform2fv(location, arraysize, value);
-       else if (length == 3) glUniform3fv(location, arraysize, value);
-       else if (length == 4) glUniform4fv(location, arraysize, value);
-       else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value);
-       else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value);
-
-       GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
-}
-
-void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
-{
-       if (location == -1)
-               return;
-
-       GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
-       if (length == 1) glUniform1iv(location, arraysize, value);
-       else if (length == 2) glUniform2iv(location, arraysize, value);
-       else if (length == 3) glUniform3iv(location, arraysize, value);
-       else if (length == 4) glUniform4iv(location, arraysize, value);
-
-       GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
-}
-
-void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
-{
-       if (location == -1)
-               return;
-
-       GPU_CHECK_ERRORS_AROUND(glUniform1i(location, value));
-}
-
-void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
-{
-       if (GPU_geometry_shader_support_via_extension()) {
-               /* geometry shaders must provide this info themselves for #version 150 and up */
-               glProgramParameteriEXT(shader->program, GL_GEOMETRY_INPUT_TYPE_EXT, input);
-               glProgramParameteriEXT(shader->program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
-               glProgramParameteriEXT(shader->program, GL_GEOMETRY_VERTICES_OUT_EXT, number);
-       }
-}
-
-void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
-{
-       GLenum arbnumber;
-
-       if (tex->number >= GG.maxtextures) {
-               fprintf(stderr, "Not enough texture slots.\n");
-               return;
-       }
-
-       if (tex->number == -1)
-               return;
-
-       if (location == -1)
-               return;
-
-       GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
-
-       arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
-
-       if (tex->number != 0) glActiveTexture(arbnumber);
-       if (tex->bindcode != 0)
-               glBindTexture(tex->target, tex->bindcode);
-       else
-               GPU_invalid_tex_bind(tex->target);
-       glUniform1i(location, tex->number);
-       glEnable(tex->target);
-       if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
-
-       GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
-}
-
-int GPU_shader_get_attribute(GPUShader *shader, const char *name)
-{
-       int index;
-       
-       GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocation(shader->program, name));
-
-       return index;
-}
-
-GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
-{
-       GPUShader *retval = NULL;
-
-       switch (shader) {
-               case GPU_SHADER_VSM_STORE:
-                       if (!GG.shaders.vsm_store)
-                               GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
-                       retval = GG.shaders.vsm_store;
-                       break;
-               case GPU_SHADER_SEP_GAUSSIAN_BLUR:
-                       if (!GG.shaders.sep_gaussian_blur)
-                               GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
-                       retval = GG.shaders.sep_gaussian_blur;
-                       break;
-       }
-
-       if (retval == NULL)
-               printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
-
-       return retval;
-}
-
-GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program)
-{
-       GPUProgram *retval = NULL;
-
-       switch (program) {
-               case GPU_PROGRAM_SMOKE:
-                       if (!GG.shaders.smoke)
-                               GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl);
-                       retval = GG.shaders.smoke;
-                       break;
-               case GPU_PROGRAM_SMOKE_COLORED:
-                       if (!GG.shaders.smoke_colored)
-                               GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl);
-                       retval = GG.shaders.smoke_colored;
-                       break;
-       }
-
-       if (retval == NULL)
-               printf("Unable to create a GPUProgram for builtin program: %u\n", program);
-
-       return retval;
-}
-
-#define MAX_DEFINES 100
-
-GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
-{
-       int offset;
-       char defines[MAX_DEFINES] = "";
-       /* avoid shaders out of range */
-       if (effects >= MAX_FX_SHADERS)
-               return NULL;
-
-       offset = 2 * effects;
-
-       if (persp) {
-               offset += 1;
-               strcat(defines, "#define PERSP_MATRIX\n");
-       }
-
-       if (!GG.shaders.fx_shaders[offset]) {
-               GPUShader *shader;
-
-               switch (effects) {
-                       case GPU_SHADER_FX_SSAO:
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
-                               break;
-
-                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
-                               strcat(defines, "#define FIRST_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
-                               break;
-
-                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
-                               strcat(defines, "#define SECOND_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
-                               break;
-
-                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
-                               strcat(defines, "#define THIRD_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
-                               break;
-
-                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
-                               strcat(defines, "#define FOURTH_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
-                               break;
-
-                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
-                               strcat(defines, "#define FIFTH_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
-                               break;
-
-                       case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
-                               strcat(defines, "#define FIRST_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
-                               break;
-
-                       case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
-                               strcat(defines, "#define SECOND_PASS\n");
-                               shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
-                                                                                  defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
-                               GG.shaders.fx_shaders[offset] = shader;
-                               break;
-
-                       case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
-                               strcat(defines, "#define THIRD_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
-                               break;
-
-                       case GPU_SHADER_FX_DEPTH_RESOLVE:
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
-               }
-       }
-
-       return GG.shaders.fx_shaders[offset];
-}
-
-
-void GPU_shader_free_builtin_shaders(void)
-{
-       int i;
-
-       if (GG.shaders.vsm_store) {
-               GPU_shader_free(GG.shaders.vsm_store);
-               GG.shaders.vsm_store = NULL;
-       }
-
-       if (GG.shaders.sep_gaussian_blur) {
-               GPU_shader_free(GG.shaders.sep_gaussian_blur);
-               GG.shaders.sep_gaussian_blur = NULL;
-       }
-
-       if (GG.shaders.smoke) {
-               GPU_program_free(GG.shaders.smoke);
-               GG.shaders.smoke = NULL;
-       }
-
-       if (GG.shaders.smoke_colored) {
-               GPU_program_free(GG.shaders.smoke_colored);
-               GG.shaders.smoke_colored = NULL;
-       }
-
-       for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
-               if (GG.shaders.fx_shaders[i]) {
-                       GPU_shader_free(GG.shaders.fx_shaders[i]);
-                       GG.shaders.fx_shaders[i] = NULL;
-               }
-       }
-}
-
-bool GPU_mem_stats_supported(void)
-{
-       return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
-}
-
-
-void GPU_mem_stats_get(int *totalmem, int *freemem)
-{
-       if (GLEW_NVX_gpu_memory_info) {
-               /* returned value in Kb */
-               glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
-
-               glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
-       }
-       else if (GLEW_ATI_meminfo) {
-               int stats[4];
-
-               glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
-               *freemem = stats[0];
-               *totalmem = 0;
+               glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
+               *freemem = stats[0];
+               *totalmem = 0;
        }
        else {
                *totalmem = 0;
@@ -2329,117 +326,3 @@ void GPU_mem_stats_get(int *totalmem, int *freemem)
        }
 }
 
-
-#if 0 /* unused */
-
-/* GPUPixelBuffer */
-
-typedef struct GPUPixelBuffer {
-       GLuint bindcode[2];
-       GLuint current;
-       int datasize;
-       int numbuffers;
-       int halffloat;
-} GPUPixelBuffer;
-
-void GPU_pixelbuffer_free(GPUPixelBuffer *pb)
-{
-       if (pb->bindcode[0])
-               glDeleteBuffers(pb->numbuffers, pb->bindcode);
-       MEM_freeN(pb);
-}
-
-GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers)
-{
-       GPUPixelBuffer *pb;
-
-       pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
-       pb->datasize = x * y * 4 * (halffloat ? 16 : 8);
-       pb->numbuffers = numbuffers;
-       pb->halffloat = halffloat;
-
-       glGenBuffers(pb->numbuffers, pb->bindcode);
-
-       if (!pb->bindcode[0]) {
-               fprintf(stderr, "GPUPixelBuffer allocation failed\n");
-               GPU_pixelbuffer_free(pb);
-               return NULL;
-       }
-
-       return pb;
-}
-
-void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
-{
-       void *pixels;
-       int i;
-
-       glBindTexture(GL_TEXTURE_RECTANGLE, tex->bindcode);
-
-       for (i = 0; i < pb->numbuffers; i++) {
-               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pb->bindcode[pb->current]);
-               glBufferData(GL_PIXEL_UNPACK_BUFFER, pb->datasize, NULL,
-               GL_STREAM_DRAW);
-
-               pixels = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
-
-#  if 0
-               memcpy(pixels, _oImage.data(), pb->datasize);
-#  endif
-
-               if (!glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)) {
-                       fprintf(stderr, "Could not unmap OpenGL PBO\n");
-                       break;
-               }
-       }
-
-       glBindTexture(GL_TEXTURE_RECTANGLE, 0);
-}
-
-static int pixelbuffer_map_into_gpu(GLuint bindcode)
-{
-       void *pixels;
-
-       glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bindcode);
-       pixels = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
-
-       /* do stuff in pixels */
-
-       if (!glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)) {
-               fprintf(stderr, "Could not unmap OpenGL PBO\n");
-               return 0;
-       }
-       
-       return 1;
-}
-
-static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode)
-{
-       GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE;
-       glBindTexture(GL_TEXTURE_RECTANGLE, tex->bindcode);
-       glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bindcode);
-
-       glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, 0, 0, tex->w, tex->h, GL_RGBA, type, NULL);
-
-       glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-       glBindTexture(GL_TEXTURE_RECTANGLE, 0);
-}
-
-void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
-{
-       int newbuffer;
-
-       if (pb->numbuffers == 1) {
-               pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]);
-               pixelbuffer_map_into_gpu(pb->bindcode[0]);
-       }
-       else {
-               pb->current = (pb->current + 1) % pb->numbuffers;
-               newbuffer = (pb->current + 1) % pb->numbuffers;
-
-               pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
-               pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
-       }
-}
-#endif /* unused */
-
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
new file mode 100644 (file)
index 0000000..4ef7611
--- /dev/null
@@ -0,0 +1,633 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_global.h"
+
+#include "GPU_debug.h"
+#include "GPU_glew.h"
+#include "GPU_framebuffer.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+static struct GPUFrameBufferGlobal {
+       GLuint currentfb;
+} GG = {0};
+
+/* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
+#define GPU_FB_MAX_SLOTS 4
+
+struct GPUFrameBuffer {
+       GLuint object;
+       GPUTexture *colortex[GPU_FB_MAX_SLOTS];
+       GPUTexture *depthtex;
+};
+
+static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
+{
+       const char *err = "unknown";
+
+       switch (status) {
+               case GL_FRAMEBUFFER_COMPLETE_EXT:
+                       break;
+               case GL_INVALID_OPERATION:
+                       err = "Invalid operation";
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
+                       err = "Incomplete attachment";
+                       break;
+               case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
+                       err = "Unsupported framebuffer format";
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+                       err = "Missing attachment";
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+                       err = "Attached images must have same dimensions";
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
+                       err = "Attached images must have same format";
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
+                       err = "Missing draw buffer";
+                       break;
+               case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
+                       err = "Missing read buffer";
+                       break;
+       }
+
+       if (err_out) {
+               BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
+                       (int)status, err);
+       }
+       else {
+               fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
+                       (int)status, err);
+       }
+}
+
+/* GPUFrameBuffer */
+
+GPUFrameBuffer *GPU_framebuffer_create(void)
+{
+       GPUFrameBuffer *fb;
+
+       if (!(GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object || (GLEW_EXT_framebuffer_object && GLEW_EXT_framebuffer_blit)))
+               return NULL;
+       
+       fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
+       glGenFramebuffersEXT(1, &fb->object);
+
+       if (!fb->object) {
+               fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
+                       (int)glGetError());
+               GPU_framebuffer_free(fb);
+               return NULL;
+       }
+
+       /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+       glReadBuffer(GL_NONE);
+       glDrawBuffer(GL_NONE);
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+       
+       return fb;
+}
+
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
+{
+       GLenum attachment;
+       GLenum error;
+
+       if (slot >= GPU_FB_MAX_SLOTS) {
+               fprintf(stderr,
+                       "Attaching to index %d framebuffer slot unsupported. "
+                       "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
+               return 0;
+       }
+
+       if ((G.debug & G_DEBUG)) {
+               if (GPU_texture_bound_number(tex) != -1) {
+                       fprintf(stderr,
+                               "Feedback loop warning!: "
+                               "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
+               }
+       }
+
+       if (GPU_texture_depth(tex))
+               attachment = GL_DEPTH_ATTACHMENT_EXT;
+       else
+               attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
+
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+       GG.currentfb = fb->object;
+
+       /* Clean glError buffer. */
+       while (glGetError() != GL_NO_ERROR) {}
+
+       glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 
+               GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0);
+
+       error = glGetError();
+
+       if (error == GL_INVALID_OPERATION) {
+               GPU_framebuffer_restore();
+               GPU_print_framebuffer_error(error, err_out);
+               return 0;
+       }
+
+       if (GPU_texture_depth(tex))
+               fb->depthtex = tex;
+       else
+               fb->colortex[slot] = tex;
+
+       GPU_texture_framebuffer_set(tex, fb, slot);
+
+       return 1;
+}
+
+void GPU_framebuffer_texture_detach(GPUTexture *tex)
+{
+       GLenum attachment;
+       GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
+       int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+
+       if (!fb)
+               return;
+
+       if (GG.currentfb != fb->object) {
+               glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+               GG.currentfb = fb->object;
+       }
+
+       if (GPU_texture_depth(tex)) {
+               fb->depthtex = NULL;
+               attachment = GL_DEPTH_ATTACHMENT_EXT;
+       }
+       else {
+               BLI_assert(fb->colortex[fb_attachment] == tex);
+               fb->colortex[fb_attachment] = NULL;
+               attachment = GL_COLOR_ATTACHMENT0_EXT + fb_attachment;
+       }
+
+       glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GPU_texture_target(tex), 0, 0);
+
+       GPU_texture_framebuffer_set(tex, NULL, -1);
+}
+
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
+{
+       GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
+       int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+
+       if (!fb) {
+               fprintf(stderr, "Error, texture not bound to framebuffer!\n");
+               return;
+       }
+
+       /* push attributes */
+       glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+       glDisable(GL_SCISSOR_TEST);
+
+       /* bind framebuffer */
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+
+       if (GPU_texture_depth(tex)) {
+               glDrawBuffer(GL_NONE);
+               glReadBuffer(GL_NONE);
+       }
+       else {
+               /* last bound prevails here, better allow explicit control here too */
+               glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
+               glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
+       }
+       
+       if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
+               glEnable(GL_MULTISAMPLE);
+       }
+
+       /* push matrices and set default viewport and matrix */
+       glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
+       GG.currentfb = fb->object;
+
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+}
+
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
+{
+       int numslots = 0, i;
+       GLenum attachments[4];
+       
+       if (!fb->colortex[slot]) {
+               fprintf(stderr, "Error, framebuffer slot empty!\n");
+               return;
+       }
+       
+       for (i = 0; i < 4; i++) {
+               if (fb->colortex[i]) {
+                       attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
+                       numslots++;
+               }
+       }
+       
+       /* push attributes */
+       glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+       glDisable(GL_SCISSOR_TEST);
+
+       /* bind framebuffer */
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+
+       /* last bound prevails here, better allow explicit control here too */
+       glDrawBuffers(numslots, attachments);
+       glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+       /* push matrices and set default viewport and matrix */
+       glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
+       GG.currentfb = fb->object;
+
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+}
+
+
+void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
+{
+       /* restore matrix */
+       glMatrixMode(GL_PROJECTION);
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+
+       /* restore attributes */
+       glPopAttrib();
+}
+
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
+{
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+       /* last bound prevails here, better allow explicit control here too */
+       glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+       glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+       /* push matrices and set default viewport and matrix */
+       glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
+       GG.currentfb = fb->object;
+       GG.currentfb = fb->object;
+}
+
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
+{
+       return fb->object == GG.currentfb;
+}
+
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
+{
+       GLenum status;
+       
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+       GG.currentfb = fb->object;
+       
+       /* Clean glError buffer. */
+       while (glGetError() != GL_NO_ERROR) {}
+       
+       status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+       
+       if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+               GPU_framebuffer_restore();
+               GPU_print_framebuffer_error(status, err_out);
+               return false;
+       }
+       
+       return true;
+}
+
+void GPU_framebuffer_free(GPUFrameBuffer *fb)
+{
+       int i;
+       if (fb->depthtex)
+               GPU_framebuffer_texture_detach(fb->depthtex);
+
+       for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
+               if (fb->colortex[i]) {
+                       GPU_framebuffer_texture_detach(fb->colortex[i]);
+               }
+       }
+
+       if (fb->object) {
+               glDeleteFramebuffersEXT(1, &fb->object);
+
+               if (GG.currentfb == fb->object) {
+                       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+                       GG.currentfb = 0;
+               }
+       }
+
+       MEM_freeN(fb);
+}
+
+void GPU_framebuffer_restore(void)
+{
+       if (GG.currentfb != 0) {
+               glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+               GG.currentfb = 0;
+       }
+}
+
+void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
+{
+       const float scaleh[2] = {1.0f / GPU_texture_width(blurtex), 0.0f};
+       const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(tex)};
+
+       GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
+       int scale_uniform, texture_source_uniform;
+
+       if (!blur_shader)
+               return;
+
+       scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
+       texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
+               
+       /* Blurring horizontally */
+
+       /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
+        * pushing unnecessary matrices onto the OpenGL stack. */
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
+       glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+       
+       /* avoid warnings from texture binding */
+       GG.currentfb = blurfb->object;
+
+       GPU_shader_bind(blur_shader);
+       GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
+       GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
+       glViewport(0, 0, GPU_texture_width(blurtex), GPU_texture_height(blurtex));
+
+       /* Peparing to draw quad */
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       glMatrixMode(GL_TEXTURE);
+       glLoadIdentity();
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+
+       glDisable(GL_DEPTH_TEST);
+
+       GPU_texture_bind(tex, 0);
+
+       /* Drawing quad */
+       glBegin(GL_QUADS);
+       glTexCoord2d(0, 0); glVertex2f(1, 1);
+       glTexCoord2d(1, 0); glVertex2f(-1, 1);
+       glTexCoord2d(1, 1); glVertex2f(-1, -1);
+       glTexCoord2d(0, 1); glVertex2f(1, -1);
+       glEnd();
+
+       /* Blurring vertically */
+
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+       glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+       
+       GG.currentfb = fb->object;
+       
+       glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
+       GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
+       GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
+       GPU_texture_bind(blurtex, 0);
+
+       glBegin(GL_QUADS);
+       glTexCoord2d(0, 0); glVertex2f(1, 1);
+       glTexCoord2d(1, 0); glVertex2f(-1, 1);
+       glTexCoord2d(1, 1); glVertex2f(-1, -1);
+       glTexCoord2d(0, 1); glVertex2f(1, -1);
+       glEnd();
+
+       GPU_shader_unbind();
+}
+
+/* GPUOffScreen */
+
+struct GPUOffScreen {
+       GPUFrameBuffer *fb;
+       GPUTexture *color;
+       GPUTexture *depth;
+};
+
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256])
+{
+       GPUOffScreen *ofs;
+
+       ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
+
+       ofs->fb = GPU_framebuffer_create();
+       if (!ofs->fb) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+
+       if (samples) {
+               if (!GLEW_EXT_framebuffer_multisample ||
+                   !GLEW_ARB_texture_multisample ||
+                   /* Only needed for GPU_offscreen_read_pixels.
+                    * We could add an arg if we intend to use multi-sample
+                    * offscreen buffers w/o reading their pixels */
+                   !GLEW_EXT_framebuffer_blit ||
+                   /* This is required when blitting from a multi-sampled buffers,
+                    * even though we're not scaling. */
+                   !GLEW_EXT_framebuffer_multisample_blit_scaled)
+               {
+                       samples = 0;
+               }
+       }
+
+       ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out);
+       if (!ofs->depth) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+
+       if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+
+       ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
+       if (!ofs->color) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+
+       if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+       
+       /* check validity at the very end! */
+       if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
+               GPU_offscreen_free(ofs);
+               return NULL;            
+       }
+
+       GPU_framebuffer_restore();
+
+       return ofs;
+}
+
+void GPU_offscreen_free(GPUOffScreen *ofs)
+{
+       if (ofs->fb)
+               GPU_framebuffer_free(ofs->fb);
+       if (ofs->color)
+               GPU_texture_free(ofs->color);
+       if (ofs->depth)
+               GPU_texture_free(ofs->depth);
+       
+       MEM_freeN(ofs);
+}
+
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
+{
+       glDisable(GL_SCISSOR_TEST);
+       if (save)
+               GPU_texture_bind_as_framebuffer(ofs->color);
+       else {
+               GPU_framebuffer_bind_no_save(ofs->fb, 0);
+       }
+}
+
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
+{
+       if (restore)
+               GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
+       GPU_framebuffer_restore();
+       glEnable(GL_SCISSOR_TEST);
+}
+
+void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
+{
+       const int w = GPU_texture_width(ofs->color);
+       const int h = GPU_texture_height(ofs->color);
+
+       if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) {
+               /* For a multi-sample texture,
+                * we need to create an intermediate buffer to blit to,
+                * before its copied using 'glReadPixels' */
+
+               /* not needed since 'ofs' needs to be bound to the framebuffer already */
+// #define USE_FBO_CTX_SWITCH
+
+               GLuint fbo_blit = 0;
+               GLuint tex_blit = 0;
+               GLenum status;
+
+               /* create texture for new 'fbo_blit' */
+               glGenTextures(1, &tex_blit);
+               if (!tex_blit) {
+                       goto finally;
+               }
+
+               glBindTexture(GL_TEXTURE_2D, tex_blit);
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, type, 0);
+
+#ifdef USE_FBO_CTX_SWITCH
+               /* read from multi-sample buffer */
+               glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, ofs->color->fb->object);
+               glFramebufferTexture2DEXT(
+                       GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + ofs->color->fb_attachment,
+                       GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
+               status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER_EXT);
+               if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+                       goto finally;
+               }
+#endif
+
+               /* write into new single-sample buffer */
+               glGenFramebuffersEXT(1, &fbo_blit);
+               glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, fbo_blit);
+               glFramebufferTexture2DEXT(
+                       GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0,
+                       GL_TEXTURE_2D, tex_blit, 0);
+               status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER_EXT);
+               if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+                       goto finally;
+               }
+
+               /* perform the copy */
+               glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+               /* read the results */
+               glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo_blit);
+               glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+
+#ifdef USE_FBO_CTX_SWITCH
+               /* restore the original frame-bufer */
+               glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ofs->color->fb->object);
+#undef USE_FBO_CTX_SWITCH
+#endif
+
+
+finally:
+               /* cleanup */
+               if (tex_blit) {
+                       glDeleteTextures(1, &tex_blit);
+               }
+               if (fbo_blit) {
+                       glDeleteFramebuffersEXT(1, &fbo_blit);
+               }
+
+               GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
+       }
+       else {
+               glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+       }
+}
+
+int GPU_offscreen_width(const GPUOffScreen *ofs)
+{
+       return GPU_texture_width(ofs->color);
+}
+
+int GPU_offscreen_height(const GPUOffScreen *ofs)
+{
+       return GPU_texture_height(ofs->color);
+}
+
+int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
+{
+       return GPU_texture_opengl_bindcode(ofs->color);
+}
+
index 8926e6914ecec08dea5f508635ce212fdd30f5fc..a176297de280127ca04246ca403ed66b817f138c 100644 (file)
 #include "IMB_imbuf_types.h"
 
 #include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
 #include "GPU_material.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
 
 #include "gpu_codegen.h"
 
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
new file mode 100644 (file)
index 0000000..83413df
--- /dev/null
@@ -0,0 +1,783 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_global.h"
+
+#include "GPU_compositing.h"
+#include "GPU_debug.h"
+#include "GPU_extensions.h"
+#include "GPU_glew.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+/* TODO(sergey): Find better default values for this constants. */
+#define MAX_DEFINE_LENGTH 1024
+#define MAX_EXT_DEFINE_LENGTH 1024
+
+/* Non-generated shaders */
+extern char datatoc_gpu_program_smoke_frag_glsl[];
+extern char datatoc_gpu_program_smoke_color_frag_glsl[];
+extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
+extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
+extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
+extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
+extern char datatoc_gpu_shader_fx_vert_glsl[];
+extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
+extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
+extern char datatoc_gpu_shader_fx_lib_glsl[];
+
+static struct GPUShadersGlobal {
+       struct {
+               GPUShader *vsm_store;
+               GPUShader *sep_gaussian_blur;
+               GPUProgram *smoke;
+               GPUProgram *smoke_colored;
+               /* cache for shader fx. Those can exist in combinations so store them here */
+               GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
+       } shaders;
+} GG = {{NULL}};
+
+/* GPUShader */
+
+struct GPUShader {
+       GLuint program;  /* handle for full program (links shader stages below) */
+
+       GLuint vertex;   /* handle for vertex shader */
+       GLuint geometry; /* handle for geometry shader */
+       GLuint fragment; /* handle for fragment shader */
+
+       int totattrib;   /* total number of attributes */
+       int uniforms;    /* required uniforms */
+};
+
+struct GPUProgram {
+       GPUProgramType type;
+       GLuint prog;
+};
+
+static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
+{
+       int i;
+       int line = 1;
+
+       fprintf(stderr, "GPUShader: %s error:\n", task);
+
+       for (i = 0; i < totcode; i++) {
+               const char *c, *pos, *end = code[i] + strlen(code[i]);
+
+               if (G.debug & G_DEBUG) {
+                       fprintf(stderr, "===== shader string %d ====\n", i + 1);
+
+                       c = code[i];
+                       while ((c < end) && (pos = strchr(c, '\n'))) {
+                               fprintf(stderr, "%2d  ", line);
+                               fwrite(c, (pos + 1) - c, 1, stderr);
+                               c = pos + 1;
+                               line++;
+                       }
+                       
+                       fprintf(stderr, "%s", c);
+               }
+       }
+       
+       fprintf(stderr, "%s\n", log);
+}
+
+static const char *gpu_shader_version(void)
+{
+       if (GLEW_VERSION_3_2) {
+               if (GLEW_ARB_compatibility) {
+                       return "#version 150 compatibility\n";
+                       /* highest version that is widely supported
+                        * gives us native geometry shaders!
+                        * use compatibility profile so we can continue using builtin shader input/output names
+                        */
+               }
+               else {
+                       return "#version 130\n";
+                       /* latest version that is compatible with existing shaders */
+               }
+       }
+       else if (GLEW_VERSION_3_1) {
+               if (GLEW_ARB_compatibility) {
+                       return "#version 140\n";
+                       /* also need the ARB_compatibility extension, handled below */
+               }
+               else {
+                       return "#version 130\n";
+                       /* latest version that is compatible with existing shaders */
+               }
+       }
+       else if (GLEW_VERSION_3_0) {
+               return "#version 130\n";
+               /* GLSL 1.3 has modern syntax/keywords/datatypes so use if available
+                * older features are deprecated but still available without compatibility extension or profile
+                */
+       }
+       else {
+               return "#version 120\n";
+               /* minimum supported */
+       }
+}
+
+
+static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_geometry_shader)
+{
+       /* enable extensions for features that are not part of our base GLSL version
+        * don't use an extension for something already available!
+        */
+
+       if (GLEW_ARB_texture_query_lod) {
+               /* a #version 400 feature, but we use #version 150 maximum so use extension */
+               strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
+       }
+
+       if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) {
+               strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
+       }
+
+       if (GLEW_VERSION_3_1 && !GLEW_VERSION_3_2 && GLEW_ARB_compatibility) {
+               strcat(defines, "#extension GL_ARB_compatibility: enable\n");
+       }
+
+       if (!GLEW_VERSION_3_1) {
+               if (GLEW_ARB_draw_instanced) {
+                       strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
+               }
+
+               if (!GLEW_VERSION_3_0 && GLEW_EXT_gpu_shader4) {
+                       strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
+                       /* TODO: maybe require this? shaders become so much nicer */
+               }
+       }
+}
+
+static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], bool use_opensubdiv)
+{
+       /* some useful defines to detect GPU type */
+       if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+               strcat(defines, "#define GPU_ATI\n");
+               if (GLEW_VERSION_3_0) {
+                       /* TODO(merwin): revisit this version check; GLEW_VERSION_3_0 means GL 3.0 or newer */
+                       strcat(defines, "#define CLIP_WORKAROUND\n");
+               }
+       }
+       else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
+               strcat(defines, "#define GPU_NVIDIA\n");
+       else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
+               strcat(defines, "#define GPU_INTEL\n");
+
+       if (GPU_bicubic_bump_support())
+               strcat(defines, "#define BUMP_BICUBIC\n");
+
+#ifdef WITH_OPENSUBDIV
+       /* TODO(sergey): Check whether we actually compiling shader for
+        * the OpenSubdiv mesh.
+        */
+       if (use_opensubdiv) {
+               strcat(defines, "#define USE_OPENSUBDIV\n");
+
+               /* TODO(sergey): not strictly speaking a define, but this is
+                * a global typedef which we don't have better place to define
+                * in yet.
+                */
+               strcat(defines, "struct VertexData {\n"
+                               "  vec4 position;\n"
+                               "  vec3 normal;\n"
+                               "  vec2 uv;"
+                               "};\n");
+       }
+#else
+       UNUSED_VARS(use_opensubdiv);
+#endif
+
+       return;
+}
+
+void GPU_program_bind(GPUProgram *program)
+{
+       glEnable(program->type);
+       glBindProgramARB(program->type, program->prog);
+}
+
+void GPU_program_unbind(GPUProgram *program)
+{
+       glDisable(program->type);
+       glBindProgramARB(program->type, 0);
+}
+
+
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code)
+{
+       /* TODO(merwin): remove ARB program support (recode smoke shader in GLSL) */
+
+       GPUProgram *program;
+       GLint error_pos, is_native;
+
+       if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT))
+               return NULL;
+
+       program = MEM_callocN(sizeof(GPUProgram), "GPUProgram");
+
+       switch (type) {
+               case GPU_PROGRAM_TYPE_FRAGMENT:
+                       program->type = GL_FRAGMENT_PROGRAM_ARB;
+                       break;
+       }
+
+       /* create the object and set its code string */
+       glGenProgramsARB(1, &program->prog);
+       glBindProgramARB(program->type, program->prog);
+
+       glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code);
+
+       glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
+       glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native);
+       if ((error_pos == -1) && (is_native == 1)) {
+               return program;
+       }
+       else {
+               /* glGetError is set before that, clear it */
+               while (glGetError() != GL_NO_ERROR)
+                       ;
+               shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1);
+               MEM_freeN(program);
+       }
+
+       return NULL;
+}
+
+void GPU_program_free(GPUProgram *program)
+{
+       glDeleteProgramsARB(1, &program->prog);
+       MEM_freeN(program);
+}
+
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w)
+{
+       glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
+}
+
+GPUShader *GPU_shader_create(const char *vertexcode,
+                             const char *fragcode,
+                             const char *geocode,
+                             const char *libcode,
+                             const char *defines,
+                             int input,
+                             int output,
+                             int number)
+{
+       return GPU_shader_create_ex(vertexcode,
+                                   fragcode,
+                                   geocode,
+                                   libcode,
+                                   defines,
+                                   input,
+                                   output,
+                                   number,
+                                   GPU_SHADER_FLAGS_NONE);
+}
+
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+                                const char *fragcode,
+                                const char *geocode,
+                                const char *libcode,
+                                const char *defines,
+                                int input,
+                                int output,
+                                int number,
+                                const int flags)
+{
+#ifdef WITH_OPENSUBDIV
+       /* TODO(sergey): used to add #version 150 to the geometry shader.
+        * Could safely be renamed to "use_geometry_code" since it's very
+        * likely any of geometry code will want to use GLSL 1.5.
+        */
+       bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
+#else
+       UNUSED_VARS(flags);
+       bool use_opensubdiv = false;
+#endif
+       GLint status;
+       GLchar log[5000];
+       GLsizei length = 0;
+       GPUShader *shader;
+       char standard_defines[MAX_DEFINE_LENGTH] = "";
+       char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
+
+       if (geocode && !GPU_geometry_shader_support())
+               return NULL;
+
+       shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
+
+       if (vertexcode)
+               shader->vertex = glCreateShader(GL_VERTEX_SHADER);
+       if (fragcode)
+               shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
+       if (geocode)
+               shader->geometry = glCreateShader(GL_GEOMETRY_SHADER_EXT);
+
+       shader->program = glCreateProgram();
+
+       if (!shader->program ||
+           (vertexcode && !shader->vertex) ||
+           (fragcode && !shader->fragment) ||
+           (geocode && !shader->geometry))
+       {
+               fprintf(stderr, "GPUShader, object creation failed.\n");
+               GPU_shader_free(shader);
+               return NULL;
+       }
+
+       gpu_shader_standard_defines(standard_defines, use_opensubdiv);
+       gpu_shader_standard_extensions(standard_extensions, geocode != NULL);
+
+       if (vertexcode) {
+               const char *source[5];
+               /* custom limit, may be too small, beware */
+               int num_source = 0;
+
+               source[num_source++] = gpu_shader_version();
+               source[num_source++] = standard_extensions;
+               source[num_source++] = standard_defines;
+
+               if (defines) source[num_source++] = defines;
+               source[num_source++] = vertexcode;
+
+               glAttachShader(shader->program, shader->vertex);
+               glShaderSource(shader->vertex, num_source, source, NULL);
+
+               glCompileShader(shader->vertex);
+               glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status);
+
+               if (!status) {
+                       glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log);
+                       shader_print_errors("compile", log, source, num_source);
+
+                       GPU_shader_free(shader);
+                       return NULL;
+               }
+       }
+
+       if (fragcode) {
+               const char *source[7];
+               int num_source = 0;
+
+               source[num_source++] = gpu_shader_version();
+               source[num_source++] = standard_extensions;
+               source[num_source++] = standard_defines;
+
+#ifdef WITH_OPENSUBDIV
+               /* TODO(sergey): Move to fragment shader source code generation. */
+               if (use_opensubdiv) {
+                       source[num_source++] =
+                               "#ifdef USE_OPENSUBDIV\n"
+                               "in block {\n"
+                               "       VertexData v;\n"
+                               "} inpt;\n"
+                               "#endif\n";
+               }
+#endif
+
+               if (defines) source[num_source++] = defines;
+               if (libcode) source[num_source++] = libcode;
+               source[num_source++] = fragcode;
+
+               glAttachShader(shader->program, shader->fragment);
+               glShaderSource(shader->fragment, num_source, source, NULL);
+
+               glCompileShader(shader->fragment);
+               glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status);
+
+               if (!status) {
+                       glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log);
+                       shader_print_errors("compile", log, source, num_source);
+
+                       GPU_shader_free(shader);
+                       return NULL;
+               }
+       }
+
+       if (geocode) {
+               const char *source[6];
+               int num_source = 0;
+
+               source[num_source++] = gpu_shader_version();
+               source[num_source++] = standard_extensions;
+               source[num_source++] = standard_defines;
+
+               if (defines) source[num_source++] = defines;
+               source[num_source++] = geocode;
+
+               glAttachShader(shader->program, shader->geometry);
+               glShaderSource(shader->geometry, num_source, source, NULL);
+
+               glCompileShader(shader->geometry);
+               glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status);
+
+               if (!status) {
+                       glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log);
+                       shader_print_errors("compile", log, source, num_source);
+
+                       GPU_shader_free(shader);
+                       return NULL;
+               }
+               
+               if (!use_opensubdiv) {
+                       GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
+               }
+       }
+
+#ifdef WITH_OPENSUBDIV
+       if (use_opensubdiv) {
+               glBindAttribLocation(shader->program, 0, "position");
+               glBindAttribLocation(shader->program, 1, "normal");
+               GPU_shader_geometry_stage_primitive_io(shader,
+                                                      GL_LINES_ADJACENCY_EXT,
+                                                      GL_TRIANGLE_STRIP,
+                                                      4);
+       }
+#endif
+
+       glLinkProgram(shader->program);
+       glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
+       if (!status) {
+               glGetProgramInfoLog(shader->program, sizeof(log), &length, log);
+               /* print attached shaders in pipeline order */
+               if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1);
+               if (geocode) shader_print_errors("linking", log, &geocode, 1);
+               if (libcode) shader_print_errors("linking", log, &libcode, 1);
+               if (fragcode) shader_print_errors("linking", log, &fragcode, 1);
+
+               GPU_shader_free(shader);
+               return NULL;
+       }
+
+#ifdef WITH_OPENSUBDIV
+       /* TODO(sergey): Find a better place for this. */
+       if (use_opensubdiv && GLEW_VERSION_4_1) {
+               glProgramUniform1i(shader->program,
+                                  glGetUniformLocation(shader->program, "FVarDataBuffer"),
+                                  31);  /* GL_TEXTURE31 */
+       }
+#endif
+
+       return shader;
+}
+
+void GPU_shader_bind(GPUShader *shader)
+{
+       GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
+       glUseProgram(shader->program);
+       GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
+}
+
+void GPU_shader_unbind(void)
+{
+       GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
+       glUseProgram(0);
+       GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
+}
+
+void GPU_shader_free(GPUShader *shader)
+{
+       if (shader->vertex)
+               glDeleteShader(shader->vertex);
+       if (shader->geometry)
+               glDeleteShader(shader->geometry);
+       if (shader->fragment)
+               glDeleteShader(shader->fragment);
+       if (shader->program)
+               glDeleteProgram(shader->program);
+       MEM_freeN(shader);
+}
+
+int GPU_shader_get_uniform(GPUShader *shader, const char *name)
+{
+       return glGetUniformLocation(shader->program, name);
+}
+
+void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
+{
+       if (location == -1 || value == NULL)
+               return;
+
+       GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
+
+       if (length == 1) glUniform1fv(location, arraysize, value);
+       else if (length == 2) glUniform2fv(location, arraysize, value);
+       else if (length == 3) glUniform3fv(location, arraysize, value);
+       else if (length == 4) glUniform4fv(location, arraysize, value);
+       else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value);
+       else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value);
+
+       GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
+}
+
+void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
+{
+       if (location == -1)
+               return;
+
+       GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
+
+       if (length == 1) glUniform1iv(location, arraysize, value);
+       else if (length == 2) glUniform2iv(location, arraysize, value);
+       else if (length == 3) glUniform3iv(location, arraysize, value);
+       else if (length == 4) glUniform4iv(location, arraysize, value);
+
+       GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
+}
+
+void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
+{
+       if (location == -1)
+               return;
+
+       GPU_CHECK_ERRORS_AROUND(glUniform1i(location, value));
+}
+
+void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
+{
+       if (GPU_geometry_shader_support_via_extension()) {
+               /* geometry shaders must provide this info themselves for #version 150 and up */
+               glProgramParameteriEXT(shader->program, GL_GEOMETRY_INPUT_TYPE_EXT, input);
+               glProgramParameteriEXT(shader->program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
+               glProgramParameteriEXT(shader->program, GL_GEOMETRY_VERTICES_OUT_EXT, number);
+       }
+}
+
+void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
+{
+       GLenum arbnumber;
+       int number = GPU_texture_bound_number(tex);
+       int bindcode = GPU_texture_opengl_bindcode(tex);
+       int target = GPU_texture_target(tex);
+
+       if (number >= GPU_max_textures()) {
+               fprintf(stderr, "Not enough texture slots.\n");
+               return;
+       }
+               
+       if (number == -1)
+               return;
+
+       if (location == -1)
+               return;
+
+       GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
+
+       arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
+
+       if (number != 0) glActiveTexture(arbnumber);
+       if (bindcode != 0)
+               glBindTexture(target, bindcode);
+       else
+               GPU_invalid_tex_bind(target);
+       glUniform1i(location, number);
+       glEnable(target);
+       if (number != 0) glActiveTexture(GL_TEXTURE0);
+
+       GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
+}
+
+int GPU_shader_get_attribute(GPUShader *shader, const char *name)
+{
+       int index;
+       
+       GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocation(shader->program, name));
+
+       return index;
+}
+
+GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
+{
+       GPUShader *retval = NULL;
+
+       switch (shader) {
+               case GPU_SHADER_VSM_STORE:
+                       if (!GG.shaders.vsm_store)
+                               GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
+                       retval = GG.shaders.vsm_store;
+                       break;
+               case GPU_SHADER_SEP_GAUSSIAN_BLUR:
+                       if (!GG.shaders.sep_gaussian_blur)
+                               GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
+                       retval = GG.shaders.sep_gaussian_blur;
+                       break;
+       }
+
+       if (retval == NULL)
+               printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
+
+       return retval;
+}
+
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program)
+{
+       GPUProgram *retval = NULL;
+
+       switch (program) {
+               case GPU_PROGRAM_SMOKE:
+                       if (!GG.shaders.smoke)
+                               GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl);
+                       retval = GG.shaders.smoke;
+                       break;
+               case GPU_PROGRAM_SMOKE_COLORED:
+                       if (!GG.shaders.smoke_colored)
+                               GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl);
+                       retval = GG.shaders.smoke_colored;
+                       break;
+       }
+
+       if (retval == NULL)
+               printf("Unable to create a GPUProgram for builtin program: %u\n", program);
+
+       return retval;
+}
+
+#define MAX_DEFINES 100
+
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
+{
+       int offset;
+       char defines[MAX_DEFINES] = "";
+       /* avoid shaders out of range */
+       if (effects >= MAX_FX_SHADERS)
+               return NULL;
+
+       offset = 2 * effects;
+
+       if (persp) {
+               offset += 1;
+               strcat(defines, "#define PERSP_MATRIX\n");
+       }
+
+       if (!GG.shaders.fx_shaders[offset]) {
+               GPUShader *shader;
+
+               switch (effects) {
+                       case GPU_SHADER_FX_SSAO:
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
+                               strcat(defines, "#define FIRST_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
+                               strcat(defines, "#define SECOND_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
+                               strcat(defines, "#define THIRD_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
+                               strcat(defines, "#define FOURTH_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
+                               strcat(defines, "#define FIFTH_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
+                               strcat(defines, "#define FIRST_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
+                               strcat(defines, "#define SECOND_PASS\n");
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
+                                                                                  defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
+                               GG.shaders.fx_shaders[offset] = shader;
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
+                               strcat(defines, "#define THIRD_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_RESOLVE:
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
+               }
+       }
+
+       return GG.shaders.fx_shaders[offset];
+}
+
+
+void GPU_shader_free_builtin_shaders(void)
+{
+       int i;
+
+       if (GG.shaders.vsm_store) {
+               GPU_shader_free(GG.shaders.vsm_store);
+               GG.shaders.vsm_store = NULL;
+       }
+
+       if (GG.shaders.sep_gaussian_blur) {
+               GPU_shader_free(GG.shaders.sep_gaussian_blur);
+               GG.shaders.sep_gaussian_blur = NULL;
+       }
+
+       if (GG.shaders.smoke) {
+               GPU_program_free(GG.shaders.smoke);
+               GG.shaders.smoke = NULL;
+       }
+
+       if (GG.shaders.smoke_colored) {
+               GPU_program_free(GG.shaders.smoke_colored);
+               GG.shaders.smoke_colored = NULL;
+       }
+
+       for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
+               if (GG.shaders.fx_shaders[i]) {
+                       GPU_shader_free(GG.shaders.fx_shaders[i]);
+                       GG.shaders.fx_shaders[i] = NULL;
+               }
+       }
+}
+
+
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
new file mode 100644 (file)
index 0000000..7803c0d
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "MEM_guardedalloc.h"
+
+#include "DNA_image_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_global.h"
+
+#include "GPU_debug.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+#include "GPU_texture.h"
+
+static struct GPUTextureGlobal {
+       GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
+       GPUTexture *invalid_tex_2D;
+       GPUTexture *invalid_tex_3D;
+} GG = {NULL, NULL, NULL};
+
+/* GPUTexture */
+
+struct GPUTexture {
+       int w, h;           /* width/height */
+       int number;         /* number for multitexture binding */
+       int refcount;       /* reference count */
+       GLenum target;      /* GL_TEXTURE_* */
+       GLenum target_base; /* same as target, (but no multisample) */
+       GLuint bindcode;    /* opengl identifier for texture */
+       int fromblender;    /* we got the texture from Blender */
+
+       GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
+       int fb_attachment;  /* slot the texture is attached to */
+       int depth;          /* is a depth texture? if 3D how deep? */
+};
+
+static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
+{
+       unsigned char *pixels, *p;
+       const float *fp = fpixels;
+       const int len = 4 * length;
+       int a;
+
+       p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
+
+       for (a = 0; a < len; a++, p++, fp++)
+               *p = FTOCHAR((*fp));
+
+       return pixels;
+}
+
+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, const float *fpixels, int depth,
+        GPUHDRType hdr_type, int components, int samples,
+        char err_out[256])
+{
+       GPUTexture *tex;
+       GLenum type, format, internalformat;
+       void *pixels = NULL;
+
+       if (samples) {
+               CLAMP_MAX(samples, GPU_max_color_texture_samples());
+       }
+
+       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 : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
+       tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
+       tex->depth = depth;
+       tex->fb_attachment = -1;
+
+       glGenTextures(1, &tex->bindcode);
+
+       if (!tex->bindcode) {
+               if (err_out) {
+                       BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
+                               (int)glGetError());
+               }
+               else {
+                       fprintf(stderr, "GPUTexture: texture create failed: %d\n",
+                               (int)glGetError());
+               }
+               GPU_texture_free(tex);
+               return NULL;
+       }
+
+       if (!GPU_full_non_power_of_two_support()) {
+               tex->w = power_of_2_max_i(tex->w);
+               tex->h = power_of_2_max_i(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_FLOAT;
+
+               if (components == 4) {
+                       format = GL_RGBA;
+                       switch (hdr_type) {
+                               case GPU_HDR_NONE:
+                                       internalformat = GL_RGBA8;
+                                       break;
+                               /* the following formats rely on ARB_texture_float or OpenGL 3.0 */
+                               case GPU_HDR_HALF_FLOAT:
+                                       internalformat = GL_RGBA16F_ARB;
+                                       break;
+                               case GPU_HDR_FULL_FLOAT:
+                                       internalformat = GL_RGBA32F_ARB;
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+               else if (components == 2) {
+                       /* these formats rely on ARB_texture_rg or OpenGL 3.0 */
+                       format = GL_RG;
+                       switch (hdr_type) {
+                               case GPU_HDR_NONE:
+                                       internalformat = GL_RG8;
+                                       break;
+                               case GPU_HDR_HALF_FLOAT:
+                                       internalformat = GL_RG16F;
+                                       break;
+                               case GPU_HDR_FULL_FLOAT:
+                                       internalformat = GL_RG32F;
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+
+               if (fpixels && hdr_type == GPU_HDR_NONE) {
+                       type = GL_UNSIGNED_BYTE;
+                       pixels = GPU_texture_convert_pixels(w*h, fpixels);
+               }
+       }
+
+       if (tex->target == GL_TEXTURE_1D) {
+               glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
+
+               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 {
+               if (samples) {
+                       glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
+               }
+               else {
+                       glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
+                                    format, type, NULL);
+               }
+
+               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_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+               glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+               glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+               glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
+       }
+       else {
+               glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       }
+
+       if (tex->target_base != GL_TEXTURE_1D) {
+               glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+               glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       }
+       else
+               glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
+       return tex;
+}
+
+
+GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
+{
+       GPUTexture *tex;
+       GLenum type, format, internalformat;
+       void *pixels = NULL;
+       int r_width;
+       bool rescale = false;
+
+       if (!GLEW_VERSION_1_2)
+               return NULL;
+
+       tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+       tex->w = w;
+       tex->h = h;
+       tex->depth = depth;
+       tex->number = -1;
+       tex->refcount = 1;
+       tex->target = GL_TEXTURE_3D;
+       tex->target_base = GL_TEXTURE_3D;
+
+       glGenTextures(1, &tex->bindcode);
+
+       if (!tex->bindcode) {
+               fprintf(stderr, "GPUTexture: texture create failed: %d\n",
+                       (int)glGetError());
+               GPU_texture_free(tex);
+               return NULL;
+       }
+
+       tex->number = 0;
+       glBindTexture(tex->target, tex->bindcode);
+
+       GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
+
+       type = GL_FLOAT;
+       if (channels == 4) {
+               format = GL_RGBA;
+               internalformat = GL_RGBA8;
+       }
+       else {
+               format = GL_RED;
+               internalformat = GL_INTENSITY8;
+       }
+
+       /* 3D textures are quite heavy, test if it's possible to create them first */
+       glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+       glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+
+       while (r_width == 0) {
+               rescale = true;
+               tex->w /= 2;
+               tex->h /= 2;
+               tex->depth /= 2;
+               glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+               glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+       }
+
+       /* really unlikely to happen but keep this just in case */
+       tex->w = max_ii(tex->w, 1);
+       tex->h = max_ii(tex->h, 1);
+       tex->depth = max_ii(tex->depth, 1);
+
+#if 0
+       if (fpixels)
+               pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
+#endif
+
+       GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
+
+       /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
+        * for gooseberry */
+       if (rescale && fpixels) {
+               unsigned int i, j, k;
+               unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
+               float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d");
+
+               GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
+
+               for (k = 0; k < tex->depth; k++) {
+                       for (j = 0; j < tex->h; j++) {
+                               for (i = 0; i < tex->w; i++) {
+                                       /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */
+                                       float xb = i * xf;
+                                       float yb = j * yf;
+                                       float zb = k * zf;
+                                       unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
+                                       unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
+
+                                       if (channels == 4) {
+                                               tex3d[offset * 4] = fpixels[offset_orig * 4];
+                                               tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
+                                               tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
+                                               tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
+                                       }
+                                       else
+                                               tex3d[offset] = fpixels[offset_orig];
+                               }
+                       }
+               }
+
+               glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
+
+               MEM_freeN(tex3d);
+       }
+       else {
+               if (fpixels) {
+                       glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
+                       GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
+               }
+       }
+
+
+       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+       if (pixels)
+               MEM_freeN(pixels);
+
+       GPU_texture_unbind(tex);
+
+       return tex;
+}
+
+GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data, double time, int mipmap)
+{
+       GPUTexture *tex;
+       GLint w, h, border, bindcode;
+
+       GPU_update_image_time(ima, time);
+       /* this binds a texture, so that's why to restore it to 0 */
+       bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, is_data);
+
+       if (ima->gputexture) {
+               ima->gputexture->bindcode = bindcode;
+               glBindTexture(GL_TEXTURE_2D, 0);
+               return ima->gputexture;
+       }
+
+       tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+       tex->bindcode = bindcode;
+       tex->number = -1;
+       tex->refcount = 1;
+       tex->target = GL_TEXTURE_2D;
+       tex->target_base = GL_TEXTURE_2D;
+       tex->fromblender = 1;
+
+       ima->gputexture= tex;
+
+       if (!glIsTexture(tex->bindcode)) {
+               GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+       }
+       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, 0);
+
+       return tex;
+}
+
+GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
+{
+       GPUTexture *tex = prv->gputexture[0];
+       GLint w, h;
+       GLuint bindcode = 0;
+       
+       if (tex)
+               bindcode = tex->bindcode;
+       
+       /* this binds a texture, so that's why we restore it to 0 */
+       if (bindcode == 0) {
+               GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL);
+       }
+       if (tex) {
+               tex->bindcode = bindcode;
+               glBindTexture(GL_TEXTURE_2D, 0);
+               return tex;
+       }
+
+       tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+       tex->bindcode = bindcode;
+       tex->number = -1;
+       tex->refcount = 1;
+       tex->target = GL_TEXTURE_2D;
+       tex->target_base = GL_TEXTURE_2D;
+       
+       prv->gputexture[0] = tex;
+       
+       if (!glIsTexture(tex->bindcode)) {
+               GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+       }
+       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);
+               
+               tex->w = w;
+               tex->h = h;
+       }
+       
+       glBindTexture(GL_TEXTURE_2D, 0);
+       
+       return tex;
+
+}
+
+GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
+
+       if (tex)
+               GPU_texture_unbind(tex);
+       
+       return tex;
+}
+
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
+
+       if (tex)
+               GPU_texture_unbind(tex);
+       
+       return tex;
+}
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
+
+       if (tex)
+               GPU_texture_unbind(tex);
+
+       return tex;
+}
+
+GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
+
+       if (tex)
+               GPU_texture_unbind(tex);
+       
+       return tex;
+}
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
+
+       if (tex)
+               GPU_texture_unbind(tex);
+
+       return tex;
+}
+
+/**
+ * A shadow map for VSM needs two components (depth and depth^2)
+ */
+GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
+
+       if (tex) {
+               /* Now we tweak some of the settings */
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+               GPU_texture_unbind(tex);
+       }
+
+       return tex;
+}
+
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
+
+       if (tex) {
+               /* Now we tweak some of the settings */
+               if (repeat) {
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+               }
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+               GPU_texture_unbind(tex);
+       }
+
+       return tex;
+}
+
+GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
+
+       if (tex) {
+               /* Now we tweak some of the settings */
+               glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+               glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+               glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+               GPU_texture_unbind(tex);
+       }
+
+       return tex;
+}
+
+void GPU_invalid_tex_init(void)
+{
+       const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
+       GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
+       GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
+       GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
+}
+
+void GPU_invalid_tex_bind(int mode)
+{
+       switch (mode) {
+               case GL_TEXTURE_1D:
+                       glBindTexture(GL_TEXTURE_1D, GG.invalid_tex_1D->bindcode);
+                       break;
+               case GL_TEXTURE_2D:
+                       glBindTexture(GL_TEXTURE_2D, GG.invalid_tex_2D->bindcode);
+                       break;
+               case GL_TEXTURE_3D:
+                       glBindTexture(GL_TEXTURE_3D, GG.invalid_tex_3D->bindcode);
+                       break;
+       }
+}
+
+void GPU_invalid_tex_free(void)
+{
+       if (GG.invalid_tex_1D)
+               GPU_texture_free(GG.invalid_tex_1D);
+       if (GG.invalid_tex_2D)
+               GPU_texture_free(GG.invalid_tex_2D);
+       if (GG.invalid_tex_3D)
+               GPU_texture_free(GG.invalid_tex_3D);
+}
+
+
+void GPU_texture_bind(GPUTexture *tex, int number)
+{
+       GLenum arbnumber;
+
+       if (number >= GPU_max_textures()) {
+               fprintf(stderr, "Not enough texture slots.\n");
+               return;
+       }
+
+       if ((G.debug & G_DEBUG)) {
+               if (tex->fb && GPU_framebuffer_bound(tex->fb)) {
+                       fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
+               }
+       }
+
+       if (number < 0)
+               return;
+
+       GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
+
+       arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
+       if (number != 0) glActiveTexture(arbnumber);
+       if (tex->bindcode != 0) {
+               glBindTexture(tex->target, tex->bindcode);
+       }
+       else
+               GPU_invalid_tex_bind(tex->target);
+       glEnable(tex->target);
+       if (number != 0) glActiveTexture(GL_TEXTURE0);
+
+       tex->number = number;
+
+       GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
+}
+
+void GPU_texture_unbind(GPUTexture *tex)
+{
+       GLenum arbnumber;
+
+       if (tex->number >= GPU_max_textures()) {
+               fprintf(stderr, "Not enough texture slots.\n");
+               return;
+       }
+
+       if (tex->number == -1)
+               return;
+       
+       GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
+
+       arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
+       if (tex->number != 0) glActiveTexture(arbnumber);
+       glBindTexture(tex->target, 0);
+       glDisable(tex->target_base);
+       if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
+
+       tex->number = -1;
+
+       GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
+}
+
+int GPU_texture_bound_number(GPUTexture *tex)
+{
+       return tex->number;
+}
+
+void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
+{
+       GLenum arbnumber;
+
+       if (tex->number >= GPU_max_textures()) {
+               fprintf(stderr, "Not enough texture slots.\n");
+               return;
+       }
+
+       if (tex->number == -1)
+               return;
+
+       GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
+
+       arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
+       if (tex->number != 0) glActiveTexture(arbnumber);
+
+       if (tex->depth) {
+               if (compare)
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+               else
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+       }
+
+       if (use_filter) {
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+       }
+       else {
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       }
+       if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
+
+       GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
+}
+
+void GPU_texture_free(GPUTexture *tex)
+{
+       tex->refcount--;
+
+       if (tex->refcount < 0)
+               fprintf(stderr, "GPUTexture: negative refcount\n");
+       
+       if (tex->refcount == 0) {
+               if (tex->fb)
+                       GPU_framebuffer_texture_detach(tex);
+               if (tex->bindcode && !tex->fromblender)
+                       glDeleteTextures(1, &tex->bindcode);
+
+               MEM_freeN(tex);
+       }
+}
+
+void GPU_texture_ref(GPUTexture *tex)
+{
+       tex->refcount++;
+}
+
+int GPU_texture_target(const GPUTexture *tex)
+{
+       return tex->target;
+}
+
+int GPU_texture_width(const GPUTexture *tex)
+{
+       return tex->w;
+}
+
+int GPU_texture_height(const GPUTexture *tex)
+{
+       return tex->h;
+}
+
+int GPU_texture_depth(const GPUTexture *tex)
+{
+       return tex->depth;
+}
+
+int GPU_texture_opengl_bindcode(const GPUTexture *tex)
+{
+       return tex->bindcode;
+}
+
+GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
+{
+       return tex->fb;
+}
+
+int GPU_texture_framebuffer_attachment(GPUTexture *tex)
+{
+       return tex->fb_attachment;
+}
+
+void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
+{
+       tex->fb = fb;
+       tex->fb_attachment = attachment;
+}
+
index ed31ac052c6d925a68b94d92e9c4fe1b66ba3e53..c4863b2a92fff562e7b32e7a1c23b20d0dec2b4a 100644 (file)
@@ -37,8 +37,8 @@
 
 #include "ED_screen.h"
 
-#include "GPU_extensions.h"
 #include "GPU_compositing.h"
+#include "GPU_framebuffer.h"
 
 #include "../mathutils/mathutils.h"
 
index b5151615f3b4094400ae92c4015f3f22305642de..0f71f8d3bac3238b16487d7a7d16337be6974265 100644 (file)
@@ -35,8 +35,8 @@
 #include "BL_BlenderShader.h"
 #include "BL_Material.h"
 
-#include "GPU_extensions.h"
 #include "GPU_material.h"
+#include "GPU_shader.h"
 
 #include "RAS_BucketManager.h"
 #include "RAS_MeshObject.h"
index da5229f1441c69a44b993ce1c18999ebd2cb1712..bbdf17b5bc4d89de6a2bfb7d9bb7ceb0f3d34bbb 100644 (file)
@@ -51,8 +51,9 @@
 #include "RAS_StorageVBO.h"
 
 #include "GPU_draw.h"
-#include "GPU_material.h"
 #include "GPU_extensions.h"
+#include "GPU_material.h"
+#include "GPU_shader.h"
 
 extern "C"{
        #include "BLF_api.h"