f16b1525622dc852a2d0969dc38927a0771e1375
[blender.git] / source / blender / gpu / intern / gpu_extensions.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_extensions.c
29  *  \ingroup gpu
30  *
31  * Wrap OpenGL features such as textures, shaders and GLSL
32  * with checks for drivers and GPU support.
33  */
34
35
36 #include "DNA_image_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_utildefines.h"
42 #include "BLI_math_base.h"
43
44 #include "BKE_global.h"
45
46 #include "GPU_glew.h"
47 #include "GPU_debug.h"
48 #include "GPU_draw.h"
49 #include "GPU_extensions.h"
50 #include "GPU_compositing.h"
51 #include "GPU_simple_shader.h"
52
53 #include "intern/gpu_private.h"
54
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h>
58
59 #ifdef WIN32
60 #  include "BLI_winstuff.h"
61 #endif
62
63 #define MAX_DEFINE_LENGTH 72
64
65 /* Extensions support */
66
67 /* extensions used:
68  * - texture border clamp: 1.3 core
69  * - fragment shader: 2.0 core
70  * - framebuffer object: ext specification
71  * - multitexture 1.3 core
72  * - arb non power of two: 2.0 core
73  * - pixel buffer objects? 2.1 core
74  * - arb draw buffers? 2.0 core
75  */
76
77 /* Non-generated shaders */
78 extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
79 extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
80 extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
81 extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
82 extern char datatoc_gpu_shader_fx_vert_glsl[];
83 extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
84 extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
85 extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
86 extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
87 extern char datatoc_gpu_shader_fx_lib_glsl[];
88
89 typedef struct GPUShaders {
90         GPUShader *vsm_store;
91         GPUShader *sep_gaussian_blur;
92         /* cache for shader fx. Those can exist in combinations so store them here */
93         GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
94 } GPUShaders;
95
96 static struct GPUGlobal {
97         GLint maxtexsize;
98         GLint maxtextures;
99         GLuint currentfb;
100         int glslsupport;
101         int extdisabled;
102         int colordepth;
103         int npotdisabled; /* ATI 3xx-5xx (and more) chipsets support NPoT partially (== not enough) */
104         int dlistsdisabled; /* Legacy ATI driver does not support display lists well */
105         GPUDeviceType device;
106         GPUOSType os;
107         GPUDriverType driver;
108         GPUShaders shaders;
109         GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
110         GPUTexture *invalid_tex_2D;
111         GPUTexture *invalid_tex_3D;
112 } GG = {1, 0};
113
114 /* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
115 #define GPU_FB_MAX_SLOTS 4
116
117 struct GPUFrameBuffer {
118         GLuint object;
119         GPUTexture *colortex[GPU_FB_MAX_SLOTS];
120         GPUTexture *depthtex;
121 };
122
123
124 /* GPU Types */
125
126 bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
127 {
128         return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
129 }
130
131 /* GPU Extensions */
132
133 void GPU_extensions_disable(void)
134 {
135         GG.extdisabled = 1;
136 }
137
138 int GPU_max_texture_size(void)
139 {
140         return GG.maxtexsize;
141 }
142
143 void gpu_extensions_init(void)
144 {
145         GLint r, g, b;
146         const char *vendor, *renderer;
147
148         /* glewIsSupported("GL_VERSION_2_0") */
149
150         if (GLEW_ARB_multitexture)
151                 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &GG.maxtextures);
152
153         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
154
155         GG.glslsupport = 1;
156         if (!GLEW_ARB_multitexture) GG.glslsupport = 0;
157         if (!GLEW_ARB_vertex_shader) GG.glslsupport = 0;
158         if (!GLEW_ARB_fragment_shader) GG.glslsupport = 0;
159
160         glGetIntegerv(GL_RED_BITS, &r);
161         glGetIntegerv(GL_GREEN_BITS, &g);
162         glGetIntegerv(GL_BLUE_BITS, &b);
163         GG.colordepth = r+g+b; /* assumes same depth for RGB */
164
165         vendor = (const char *)glGetString(GL_VENDOR);
166         renderer = (const char *)glGetString(GL_RENDERER);
167
168         if (strstr(vendor, "ATI")) {
169                 GG.device = GPU_DEVICE_ATI;
170                 GG.driver = GPU_DRIVER_OFFICIAL;
171         }
172         else if (strstr(vendor, "NVIDIA")) {
173                 GG.device = GPU_DEVICE_NVIDIA;
174                 GG.driver = GPU_DRIVER_OFFICIAL;
175         }
176         else if (strstr(vendor, "Intel") ||
177                 /* src/mesa/drivers/dri/intel/intel_context.c */
178                 strstr(renderer, "Mesa DRI Intel") ||
179                 strstr(renderer, "Mesa DRI Mobile Intel")) {
180                 GG.device = GPU_DEVICE_INTEL;
181                 GG.driver = GPU_DRIVER_OFFICIAL;
182         }
183         else if (strstr(renderer, "Mesa DRI R") || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI "))) {
184                 GG.device = GPU_DEVICE_ATI;
185                 GG.driver = GPU_DRIVER_OPENSOURCE;
186         }
187         else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
188                 GG.device = GPU_DEVICE_NVIDIA;
189                 GG.driver = GPU_DRIVER_OPENSOURCE;
190         }
191         else if (strstr(vendor, "Mesa")) {
192                 GG.device = GPU_DEVICE_SOFTWARE;
193                 GG.driver = GPU_DRIVER_SOFTWARE;
194         }
195         else if (strstr(vendor, "Microsoft")) {
196                 GG.device = GPU_DEVICE_SOFTWARE;
197                 GG.driver = GPU_DRIVER_SOFTWARE;
198         }
199         else if (strstr(renderer, "Apple Software Renderer")) {
200                 GG.device = GPU_DEVICE_SOFTWARE;
201                 GG.driver = GPU_DRIVER_SOFTWARE;
202         }
203         else {
204                 GG.device = GPU_DEVICE_ANY;
205                 GG.driver = GPU_DRIVER_ANY;
206         }
207
208         if (GG.device == GPU_DEVICE_ATI) {
209                 /* ATI 9500 to X2300 cards support NPoT textures poorly
210                  * Incomplete list http://dri.freedesktop.org/wiki/ATIRadeon
211                  * New IDs from MESA's src/gallium/drivers/r300/r300_screen.c
212                  */
213                 /* This list is close enough to those using the legacy driver which
214                  * has a bug with display lists and glVertexAttrib 
215                  */
216                 if (strstr(renderer, "R3") || strstr(renderer, "RV3") ||
217                     strstr(renderer, "R4") || strstr(renderer, "RV4") ||
218                     strstr(renderer, "RS4") || strstr(renderer, "RC4") ||
219                     strstr(renderer, "R5") || strstr(renderer, "RV5") ||
220                     strstr(renderer, "RS600") || strstr(renderer, "RS690") ||
221                     strstr(renderer, "RS740") || strstr(renderer, "X1") ||
222                     strstr(renderer, "X2") || strstr(renderer, "Radeon 9") ||
223                     strstr(renderer, "RADEON 9"))
224                 {
225                         GG.npotdisabled = 1;
226                         GG.dlistsdisabled = 1;
227                 }
228         }
229
230         /* make sure double side isn't used by default and only getting enabled in places where it's
231          * really needed to prevent different unexpected behaviors like with intel gme965 card (sergey) */
232         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
233
234 #ifdef _WIN32
235         GG.os = GPU_OS_WIN;
236 #elif defined(__APPLE__)
237         GG.os = GPU_OS_MAC;
238 #else
239         GG.os = GPU_OS_UNIX;
240 #endif
241
242
243         GPU_invalid_tex_init();
244         GPU_simple_shaders_init();
245 }
246
247 void gpu_extensions_exit(void)
248 {
249         GPU_simple_shaders_exit();
250         GPU_invalid_tex_free();
251 }
252
253 bool GPU_glsl_support(void)
254 {
255         return !GG.extdisabled && GG.glslsupport;
256 }
257
258 bool GPU_non_power_of_two_support(void)
259 {
260         if (GG.npotdisabled)
261                 return false;
262
263         return GLEW_ARB_texture_non_power_of_two;
264 }
265
266 bool GPU_vertex_buffer_support(void)
267 {
268         return GLEW_ARB_vertex_buffer_object || GLEW_VERSION_1_5;
269 }
270
271 bool GPU_display_list_support(void)
272 {
273         return !GG.dlistsdisabled;
274 }
275
276 bool GPU_bicubic_bump_support(void)
277 {
278         return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
279 }
280
281 int GPU_color_depth(void)
282 {
283         return GG.colordepth;
284 }
285
286 static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
287 {
288         const char *err= "unknown";
289
290         switch (status) {
291                 case GL_FRAMEBUFFER_COMPLETE_EXT:
292                         break;
293                 case GL_INVALID_OPERATION:
294                         err= "Invalid operation";
295                         break;
296                 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
297                         err= "Incomplete attachment";
298                         break;
299                 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
300                         err= "Unsupported framebuffer format";
301                         break;
302                 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
303                         err= "Missing attachment";
304                         break;
305                 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
306                         err= "Attached images must have same dimensions";
307                         break;
308                 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
309                         err= "Attached images must have same format";
310                         break;
311                 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
312                         err= "Missing draw buffer";
313                         break;
314                 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
315                         err= "Missing read buffer";
316                         break;
317         }
318
319         if (err_out) {
320                 BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
321                         (int)status, err);
322         }
323         else {
324                 fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
325                         (int)status, err);
326         }
327 }
328
329 /* GPUTexture */
330
331 struct GPUTexture {
332         int w, h;                               /* width/height */
333         int number;                             /* number for multitexture binding */
334         int refcount;                   /* reference count */
335         GLenum target;                  /* GL_TEXTURE_* */
336         GLuint bindcode;                /* opengl identifier for texture */
337         int fromblender;                /* we got the texture from Blender */
338
339         GPUFrameBuffer *fb;             /* GPUFramebuffer this texture is attached to */
340         int fb_attachment;              /* slot the texture is attached to */
341         int depth;                              /* is a depth texture? if 3D how deep? */
342 };
343
344 static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
345 {
346         unsigned char *pixels, *p;
347         const float *fp = fpixels;
348         const int len = 4*length;
349         int a;
350
351         p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels");
352
353         for (a=0; a<len; a++, p++, fp++)
354                 *p = FTOCHAR((*fp));
355
356         return pixels;
357 }
358
359 static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
360 {
361         void *pixels = MEM_callocN(sizeof(char)*4*w*h, "GPUTextureEmptyPixels");
362
363         if (target == GL_TEXTURE_1D)
364                 glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
365         else
366                 glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
367         
368         MEM_freeN(pixels);
369 }
370
371 static GPUTexture *GPU_texture_create_nD(
372         int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components,
373         char err_out[256])
374 {
375         GPUTexture *tex;
376         GLenum type, format, internalformat;
377         void *pixels = NULL;
378
379         if (depth && !GLEW_ARB_depth_texture)
380                 return NULL;
381
382         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
383         tex->w = w;
384         tex->h = h;
385         tex->number = -1;
386         tex->refcount = 1;
387         tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
388         tex->depth = depth;
389         tex->fb_attachment = -1;
390
391         glGenTextures(1, &tex->bindcode);
392
393         if (!tex->bindcode) {
394                 if (err_out) {
395                         BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
396                                 (int)glGetError());
397                 }
398                 else {
399                         fprintf(stderr, "GPUTexture: texture create failed: %d\n",
400                                 (int)glGetError());
401                 }
402                 GPU_texture_free(tex);
403                 return NULL;
404         }
405
406         if (!GPU_non_power_of_two_support()) {
407                 tex->w = power_of_2_max_i(tex->w);
408                 tex->h = power_of_2_max_i(tex->h);
409         }
410
411         tex->number = 0;
412         glBindTexture(tex->target, tex->bindcode);
413
414         if (depth) {
415                 type = GL_UNSIGNED_BYTE;
416                 format = GL_DEPTH_COMPONENT;
417                 internalformat = GL_DEPTH_COMPONENT;
418         }
419         else {
420                 type = GL_FLOAT;
421
422                 if (components == 4) {
423                         format = GL_RGBA;
424                         switch (hdr_type) {
425                                 case GPU_HDR_NONE:
426                                         internalformat = GL_RGBA8;
427                                         break;
428                                 case GPU_HDR_HALF_FLOAT:
429                                         internalformat = GL_RGBA16F;
430                                         break;
431                                 case GPU_HDR_FULL_FLOAT:
432                                         internalformat = GL_RGBA32F;
433                                         break;
434                                 default:
435                                         break;
436                         }
437                 }
438                 else if (components == 2) {
439                         format = GL_RG;
440                         switch (hdr_type) {
441                                 case GPU_HDR_NONE:
442                                         internalformat = GL_RG8;
443                                         break;
444                                 case GPU_HDR_HALF_FLOAT:
445                                         internalformat = GL_RG16F;
446                                         break;
447                                 case GPU_HDR_FULL_FLOAT:
448                                         internalformat = GL_RG32F;
449                                         break;
450                                 default:
451                                         break;
452                         }
453                 }
454
455                 if (fpixels && hdr_type == GPU_HDR_NONE) {
456                         type = GL_UNSIGNED_BYTE;
457                         pixels = GPU_texture_convert_pixels(w*h, fpixels);
458                 }
459         }
460
461         if (tex->target == GL_TEXTURE_1D) {
462                 glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
463
464                 if (fpixels) {
465                         glTexSubImage1D(tex->target, 0, 0, w, format, type,
466                                 pixels ? pixels : fpixels);
467
468                         if (tex->w > w)
469                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0,
470                                         tex->w-w, 1);
471                 }
472         }
473         else {
474                 glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
475                              format, type, NULL);
476
477                 if (fpixels) {
478                         glTexSubImage2D(tex->target, 0, 0, 0, w, h,
479                                 format, type, pixels ? pixels : fpixels);
480
481                         if (tex->w > w)
482                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h);
483                         if (tex->h > h)
484                                 GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h);
485                 }
486         }
487
488         if (pixels)
489                 MEM_freeN(pixels);
490
491         if (depth) {
492                 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
493                 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
494                 glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
495                 glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
496                 glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);  
497         }
498         else {
499                 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
500                 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
501         }
502
503         if (tex->target != GL_TEXTURE_1D) {
504                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
505                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
506         }
507         else
508                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
509
510         return tex;
511 }
512
513
514 GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
515 {
516         GPUTexture *tex;
517         GLenum type, format, internalformat;
518         void *pixels = NULL;
519         const float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
520
521         if (!GLEW_VERSION_1_2)
522                 return NULL;
523
524         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
525         tex->w = w;
526         tex->h = h;
527         tex->depth = depth;
528         tex->number = -1;
529         tex->refcount = 1;
530         tex->target = GL_TEXTURE_3D;
531
532         glGenTextures(1, &tex->bindcode);
533
534         if (!tex->bindcode) {
535                 fprintf(stderr, "GPUTexture: texture create failed: %d\n",
536                         (int)glGetError());
537                 GPU_texture_free(tex);
538                 return NULL;
539         }
540
541         if (!GPU_non_power_of_two_support()) {
542                 tex->w = power_of_2_max_i(tex->w);
543                 tex->h = power_of_2_max_i(tex->h);
544                 tex->depth = power_of_2_max_i(tex->depth);
545         }
546
547         tex->number = 0;
548         glBindTexture(tex->target, tex->bindcode);
549
550         GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
551
552         type = GL_FLOAT;
553         if (channels == 4) {
554                 format = GL_RGBA;
555                 internalformat = GL_RGBA;
556         }
557         else {
558                 format = GL_RED;
559                 internalformat = GL_INTENSITY;
560         }
561
562         //if (fpixels)
563         //      pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
564
565         glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
566
567         GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
568
569         if (fpixels) {
570                 if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
571                         /* clear first to avoid unitialized pixels */
572                         float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
573                         glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero);
574                         MEM_freeN(zero);
575                 }
576
577                 glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
578                 GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
579         }
580
581
582         glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor);
583         GPU_ASSERT_NO_GL_ERRORS("3D GL_TEXTURE_BORDER_COLOR");
584         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
585         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
586         GPU_ASSERT_NO_GL_ERRORS("3D GL_LINEAR");
587         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
588         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
589         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
590         GPU_ASSERT_NO_GL_ERRORS("3D GL_CLAMP_TO_BORDER");
591
592         if (pixels)
593                 MEM_freeN(pixels);
594
595         GPU_texture_unbind(tex);
596
597         return tex;
598 }
599
600 GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data, double time, int mipmap)
601 {
602         GPUTexture *tex;
603         GLint w, h, border, lastbindcode, bindcode;
604
605         glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
606
607         GPU_update_image_time(ima, time);
608         /* this binds a texture, so that's why to restore it with lastbindcode */
609         bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, is_data);
610
611         if (ima->gputexture) {
612                 ima->gputexture->bindcode = bindcode;
613                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
614                 return ima->gputexture;
615         }
616
617         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
618         tex->bindcode = bindcode;
619         tex->number = -1;
620         tex->refcount = 1;
621         tex->target = GL_TEXTURE_2D;
622         tex->fromblender = 1;
623
624         ima->gputexture= tex;
625
626         if (!glIsTexture(tex->bindcode)) {
627                 GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
628         }
629         else {
630                 glBindTexture(GL_TEXTURE_2D, tex->bindcode);
631                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
632                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
633                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
634
635                 tex->w = w - border;
636                 tex->h = h - border;
637         }
638
639         glBindTexture(GL_TEXTURE_2D, lastbindcode);
640
641         return tex;
642 }
643
644 GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
645 {
646         GPUTexture *tex = prv->gputexture[0];
647         GLint w, h, lastbindcode;
648         GLuint bindcode = 0;
649         
650         glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
651         
652         if (tex)
653                 bindcode = tex->bindcode;
654         
655         /* this binds a texture, so that's why to restore it */
656         if (bindcode == 0) {
657                 GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL);
658         }
659         if (tex) {
660                 tex->bindcode = bindcode;
661                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
662                 return tex;
663         }
664
665         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
666         tex->bindcode = bindcode;
667         tex->number = -1;
668         tex->refcount = 1;
669         tex->target = GL_TEXTURE_2D;
670         
671         prv->gputexture[0]= tex;
672         
673         if (!glIsTexture(tex->bindcode)) {
674                 GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
675         }
676         else {
677                 glBindTexture(GL_TEXTURE_2D, tex->bindcode);
678                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
679                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
680                 
681                 tex->w = w;
682                 tex->h = h;
683         }
684         
685         glBindTexture(GL_TEXTURE_2D, lastbindcode);
686         
687         return tex;
688
689 }
690
691 GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
692 {
693         GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, err_out);
694
695         if (tex)
696                 GPU_texture_unbind(tex);
697         
698         return tex;
699 }
700
701 GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
702 {
703         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, err_out);
704
705         if (tex)
706                 GPU_texture_unbind(tex);
707         
708         return tex;
709 }
710
711 GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
712 {
713         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, err_out);
714
715         if (tex)
716                 GPU_texture_unbind(tex);
717         
718         return tex;
719 }
720
721 /**
722  * A shadow map for VSM needs two components (depth and depth^2)
723  */
724 GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
725 {
726         GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, err_out);
727
728         if (tex) {
729                 /* Now we tweak some of the settings */
730                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
731                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
732
733                 GPU_texture_unbind(tex);
734         }
735
736         return tex;
737 }
738
739 GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, char err_out[256])
740 {
741         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
742
743         if (tex) {
744                 /* Now we tweak some of the settings */
745                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
746                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
747                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
748                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
749
750                 GPU_texture_unbind(tex);
751         }
752
753         return tex;
754 }
755
756 GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
757 {
758         GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
759
760         if (tex) {
761                 /* Now we tweak some of the settings */
762                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
763                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
764                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
765
766                 GPU_texture_unbind(tex);
767         }
768
769         return tex;
770 }
771
772 void GPU_invalid_tex_init(void)
773 {
774         const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
775         GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
776         GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
777         GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
778 }
779
780 void GPU_invalid_tex_bind(int mode)
781 {
782         switch (mode) {
783                 case GL_TEXTURE_1D:
784                         glBindTexture(GL_TEXTURE_1D, GG.invalid_tex_1D->bindcode);
785                         break;
786                 case GL_TEXTURE_2D:
787                         glBindTexture(GL_TEXTURE_2D, GG.invalid_tex_2D->bindcode);
788                         break;
789                 case GL_TEXTURE_3D:
790                         glBindTexture(GL_TEXTURE_3D, GG.invalid_tex_3D->bindcode);
791                         break;
792         }
793 }
794
795 void GPU_invalid_tex_free(void)
796 {
797         if (GG.invalid_tex_1D)
798                 GPU_texture_free(GG.invalid_tex_1D);
799         if (GG.invalid_tex_2D)
800                 GPU_texture_free(GG.invalid_tex_2D);
801         if (GG.invalid_tex_3D)
802                 GPU_texture_free(GG.invalid_tex_3D);
803 }
804
805
806 void GPU_texture_bind(GPUTexture *tex, int number)
807 {
808         GLenum arbnumber;
809
810         if (number >= GG.maxtextures) {
811                 fprintf(stderr, "Not enough texture slots.");
812                 return;
813         }
814
815         if ((G.debug & G_DEBUG)) {
816                 if (tex->fb && tex->fb->object == GG.currentfb) {
817                         fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
818                 }
819         }
820
821         if (number < 0)
822                 return;
823
824         GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
825
826         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number);
827         if (number != 0) glActiveTextureARB(arbnumber);
828         if (tex->bindcode != 0) {
829                 glBindTexture(tex->target, tex->bindcode);
830         }
831         else
832                 GPU_invalid_tex_bind(tex->target);
833         glEnable(tex->target);
834         if (number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
835
836         tex->number = number;
837
838         GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
839 }
840
841 void GPU_texture_unbind(GPUTexture *tex)
842 {
843         GLenum arbnumber;
844
845         if (tex->number >= GG.maxtextures) {
846                 fprintf(stderr, "Not enough texture slots.");
847                 return;
848         }
849
850         if (tex->number == -1)
851                 return;
852         
853         GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
854
855         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
856         if (tex->number != 0) glActiveTextureARB(arbnumber);
857         glBindTexture(tex->target, 0);
858         glDisable(tex->target);
859         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
860
861         tex->number = -1;
862
863         GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
864 }
865
866 void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter)
867 {
868         GLenum arbnumber;
869
870         if (tex->number >= GG.maxtextures) {
871                 fprintf(stderr, "Not enough texture slots.");
872                 return;
873         }
874
875         if (!tex->depth) {
876                 fprintf(stderr, "Not a depth texture.");
877                 return;
878         }
879
880         if (tex->number == -1)
881                 return;
882
883         GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
884
885         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
886         if (tex->number != 0) glActiveTextureARB(arbnumber);
887         if (compare)
888                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
889         else
890                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
891
892         if (use_filter) {
893                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
894                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
895         }
896         else {
897                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
898                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
899         }
900         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
901
902         GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
903 }
904
905 void GPU_texture_free(GPUTexture *tex)
906 {
907         tex->refcount--;
908
909         if (tex->refcount < 0)
910                 fprintf(stderr, "GPUTexture: negative refcount\n");
911         
912         if (tex->refcount == 0) {
913                 if (tex->fb)
914                         GPU_framebuffer_texture_detach(tex);
915                 if (tex->bindcode && !tex->fromblender)
916                         glDeleteTextures(1, &tex->bindcode);
917
918                 MEM_freeN(tex);
919         }
920 }
921
922 void GPU_texture_ref(GPUTexture *tex)
923 {
924         tex->refcount++;
925 }
926
927 int GPU_texture_target(const GPUTexture *tex)
928 {
929         return tex->target;
930 }
931
932 int GPU_texture_opengl_width(const GPUTexture *tex)
933 {
934         return tex->w;
935 }
936
937 int GPU_texture_opengl_height(const GPUTexture *tex)
938 {
939         return tex->h;
940 }
941
942 int GPU_texture_opengl_bindcode(const GPUTexture *tex)
943 {
944         return tex->bindcode;
945 }
946
947 GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
948 {
949         return tex->fb;
950 }
951
952 /* GPUFrameBuffer */
953
954 GPUFrameBuffer *GPU_framebuffer_create(void)
955 {
956         GPUFrameBuffer *fb;
957
958         if (!GLEW_EXT_framebuffer_object)
959                 return NULL;
960         
961         fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
962         glGenFramebuffersEXT(1, &fb->object);
963
964         if (!fb->object) {
965                 fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
966                         (int)glGetError());
967                 GPU_framebuffer_free(fb);
968                 return NULL;
969         }
970
971         /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
972         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
973         glReadBuffer(GL_NONE);
974         glDrawBuffer(GL_NONE);
975         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
976         
977         return fb;
978 }
979
980 int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
981 {
982         GLenum attachment;
983         GLenum error;
984
985         if (slot >= GPU_FB_MAX_SLOTS) {
986                 fprintf(stderr, "Attaching to index %d framebuffer slot unsupported in blender use at most %d\n", slot, GPU_FB_MAX_SLOTS);
987                 return 0;
988         }
989
990         if ((G.debug & G_DEBUG)) {
991                 if (tex->number != -1) {
992                         fprintf(stderr, "Feedback loop warning!: Attempting to attach texture to framebuffer while still bound to texture unit for drawing!");
993                 }
994         }
995
996         if (tex->depth)
997                 attachment = GL_DEPTH_ATTACHMENT_EXT;
998         else
999                 attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
1000
1001         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1002         GG.currentfb = fb->object;
1003
1004         /* Clean glError buffer. */
1005         while (glGetError() != GL_NO_ERROR) {}
1006
1007         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 
1008                 tex->target, tex->bindcode, 0);
1009
1010         error = glGetError();
1011
1012         if (error == GL_INVALID_OPERATION) {
1013                 GPU_framebuffer_restore();
1014                 GPU_print_framebuffer_error(error, err_out);
1015                 return 0;
1016         }
1017
1018         if (tex->depth)
1019                 fb->depthtex = tex;
1020         else
1021                 fb->colortex[slot] = tex;
1022
1023         tex->fb= fb;
1024         tex->fb_attachment = slot;
1025
1026         return 1;
1027 }
1028
1029 void GPU_framebuffer_texture_detach(GPUTexture *tex)
1030 {
1031         GLenum attachment;
1032         GPUFrameBuffer *fb;
1033
1034         if (!tex->fb)
1035                 return;
1036
1037         fb = tex->fb;
1038
1039         if (GG.currentfb != fb->object) {
1040                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1041                 GG.currentfb = tex->fb->object;
1042         }
1043
1044         if (tex->depth) {
1045                 fb->depthtex = NULL;
1046                 attachment = GL_DEPTH_ATTACHMENT_EXT;
1047         }
1048         else {
1049                 BLI_assert(fb->colortex[tex->fb_attachment] == tex);
1050                 fb->colortex[tex->fb_attachment] = NULL;
1051                 attachment = GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment;
1052         }
1053
1054         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
1055                 tex->target, 0, 0);
1056
1057         tex->fb = NULL;
1058         tex->fb_attachment = -1;
1059 }
1060
1061 void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
1062 {
1063         if (!tex->fb) {
1064                 fprintf(stderr, "Error, texture not bound to framebuffer!");
1065                 return;
1066         }
1067
1068         /* push attributes */
1069         glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
1070         glDisable(GL_SCISSOR_TEST);
1071
1072         /* bind framebuffer */
1073         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
1074
1075         if (tex->depth) {
1076                 glDrawBuffer(GL_NONE);
1077                 glReadBuffer(GL_NONE);
1078         }
1079         else {
1080                 /* last bound prevails here, better allow explicit control here too */
1081                 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
1082                 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
1083         }
1084         
1085         /* push matrices and set default viewport and matrix */
1086         glViewport(0, 0, tex->w, tex->h);
1087         GG.currentfb = tex->fb->object;
1088
1089         glMatrixMode(GL_PROJECTION);
1090         glPushMatrix();
1091         glMatrixMode(GL_MODELVIEW);
1092         glPushMatrix();
1093 }
1094
1095 void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
1096 {
1097         int numslots = 0, i;
1098         GLenum attachments[4];
1099         
1100         if (!fb->colortex[slot]) {
1101                 fprintf(stderr, "Error, framebuffer slot empty!");
1102                 return;
1103         }
1104         
1105         for (i = 0 ; i < 4; i++) {
1106                 if (fb->colortex[i]) {
1107                         attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
1108                         numslots++;
1109                 }
1110         }
1111         
1112         /* push attributes */
1113         glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
1114         glDisable(GL_SCISSOR_TEST);
1115
1116         /* bind framebuffer */
1117         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1118
1119         /* last bound prevails here, better allow explicit control here too */
1120         glDrawBuffers(numslots, attachments);
1121         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
1122
1123         /* push matrices and set default viewport and matrix */
1124         glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
1125         GG.currentfb = fb->object;
1126
1127         glMatrixMode(GL_PROJECTION);
1128         glPushMatrix();
1129         glMatrixMode(GL_MODELVIEW);
1130         glPushMatrix();
1131 }
1132
1133
1134 void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
1135 {
1136         /* restore matrix */
1137         glMatrixMode(GL_PROJECTION);
1138         glPopMatrix();
1139         glMatrixMode(GL_MODELVIEW);
1140         glPopMatrix();
1141
1142         /* restore attributes */
1143         glPopAttrib();
1144 }
1145
1146 void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
1147 {
1148         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1149         /* last bound prevails here, better allow explicit control here too */
1150         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
1151         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
1152
1153         /* push matrices and set default viewport and matrix */
1154         glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
1155         GG.currentfb = fb->object;
1156         GG.currentfb = fb->object;
1157 }
1158
1159 bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
1160 {
1161         GLenum status;
1162         
1163         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1164         GG.currentfb = fb->object;
1165         
1166         /* Clean glError buffer. */
1167         while (glGetError() != GL_NO_ERROR) {}
1168         
1169         status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1170         
1171         if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1172                 GPU_framebuffer_restore();
1173                 GPU_print_framebuffer_error(status, err_out);
1174                 return false;
1175         }
1176         
1177         return true;
1178 }
1179
1180 void GPU_framebuffer_free(GPUFrameBuffer *fb)
1181 {
1182         int i;
1183         if (fb->depthtex)
1184                 GPU_framebuffer_texture_detach(fb->depthtex);
1185
1186         for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
1187                 if (fb->colortex[i]) {
1188                         GPU_framebuffer_texture_detach(fb->colortex[i]);
1189                 }
1190         }
1191
1192         if (fb->object) {
1193                 glDeleteFramebuffersEXT(1, &fb->object);
1194
1195                 if (GG.currentfb == fb->object) {
1196                         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1197                         GG.currentfb = 0;
1198                 }
1199         }
1200
1201         MEM_freeN(fb);
1202 }
1203
1204 void GPU_framebuffer_restore(void)
1205 {
1206         if (GG.currentfb != 0) {
1207                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1208                 GG.currentfb = 0;
1209         }
1210 }
1211
1212 void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
1213 {
1214         const float scaleh[2] = {1.0f / GPU_texture_opengl_width(blurtex), 0.0f};
1215         const float scalev[2] = {0.0f, 1.0f / GPU_texture_opengl_height(tex)};
1216
1217         GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
1218         int scale_uniform, texture_source_uniform;
1219
1220         if (!blur_shader)
1221                 return;
1222
1223         scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
1224         texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
1225                 
1226         /* Blurring horizontally */
1227
1228         /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
1229          * pushing unnecessary matrices onto the OpenGL stack. */
1230         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
1231         glDrawBuffer(GL_COLOR_ATTACHMENT0);
1232         
1233         /* avoid warnings from texture binding */
1234         GG.currentfb = blurfb->object;
1235
1236         GPU_shader_bind(blur_shader);
1237         GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
1238         GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
1239         glViewport(0, 0, GPU_texture_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
1240
1241         /* Peparing to draw quad */
1242         glMatrixMode(GL_MODELVIEW);
1243         glLoadIdentity();
1244         glMatrixMode(GL_TEXTURE);
1245         glLoadIdentity();
1246         glMatrixMode(GL_PROJECTION);
1247         glLoadIdentity();
1248
1249         glDisable(GL_DEPTH_TEST);
1250
1251         GPU_texture_bind(tex, 0);
1252
1253         /* Drawing quad */
1254         glBegin(GL_QUADS);
1255         glTexCoord2d(0, 0); glVertex2f(1, 1);
1256         glTexCoord2d(1, 0); glVertex2f(-1, 1);
1257         glTexCoord2d(1, 1); glVertex2f(-1, -1);
1258         glTexCoord2d(0, 1); glVertex2f(1, -1);
1259         glEnd();
1260
1261         /* Blurring vertically */
1262
1263         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1264         glDrawBuffer(GL_COLOR_ATTACHMENT0);
1265         
1266         GG.currentfb = fb->object;
1267         
1268         glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
1269         GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
1270         GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
1271         GPU_texture_bind(blurtex, 0);
1272
1273         glBegin(GL_QUADS);
1274         glTexCoord2d(0, 0); glVertex2f(1, 1);
1275         glTexCoord2d(1, 0); glVertex2f(-1, 1);
1276         glTexCoord2d(1, 1); glVertex2f(-1, -1);
1277         glTexCoord2d(0, 1); glVertex2f(1, -1);
1278         glEnd();
1279
1280         GPU_shader_unbind();
1281 }
1282
1283 /* GPUOffScreen */
1284
1285 struct GPUOffScreen {
1286         GPUFrameBuffer *fb;
1287         GPUTexture *color;
1288         GPUTexture *depth;
1289 };
1290
1291 GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
1292 {
1293         GPUOffScreen *ofs;
1294
1295         ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
1296
1297         ofs->fb = GPU_framebuffer_create();
1298         if (!ofs->fb) {
1299                 GPU_offscreen_free(ofs);
1300                 return NULL;
1301         }
1302
1303         ofs->depth = GPU_texture_create_depth(width, height, err_out);
1304         if (!ofs->depth) {
1305                 GPU_offscreen_free(ofs);
1306                 return NULL;
1307         }
1308
1309         if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
1310                 GPU_offscreen_free(ofs);
1311                 return NULL;
1312         }
1313
1314         ofs->color = GPU_texture_create_2D(width, height, NULL, GPU_HDR_NONE, err_out);
1315         if (!ofs->color) {
1316                 GPU_offscreen_free(ofs);
1317                 return NULL;
1318         }
1319
1320         if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
1321                 GPU_offscreen_free(ofs);
1322                 return NULL;
1323         }
1324         
1325         /* check validity at the very end! */
1326         if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
1327                 GPU_offscreen_free(ofs);
1328                 return NULL;            
1329         }
1330
1331         GPU_framebuffer_restore();
1332
1333         return ofs;
1334 }
1335
1336 void GPU_offscreen_free(GPUOffScreen *ofs)
1337 {
1338         if (ofs->fb)
1339                 GPU_framebuffer_free(ofs->fb);
1340         if (ofs->color)
1341                 GPU_texture_free(ofs->color);
1342         if (ofs->depth)
1343                 GPU_texture_free(ofs->depth);
1344         
1345         MEM_freeN(ofs);
1346 }
1347
1348 void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
1349 {
1350         glDisable(GL_SCISSOR_TEST);
1351         if (save)
1352                 GPU_texture_bind_as_framebuffer(ofs->color);
1353         else {
1354                 GPU_framebuffer_bind_no_save(ofs->fb, 0);
1355         }
1356 }
1357
1358 void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
1359 {
1360         if (restore)
1361                 GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
1362         GPU_framebuffer_restore();
1363         glEnable(GL_SCISSOR_TEST);
1364 }
1365
1366 void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
1367 {
1368         glReadPixels(0, 0, ofs->color->w, ofs->color->h, GL_RGBA, type, pixels);
1369 }
1370
1371 int GPU_offscreen_width(const GPUOffScreen *ofs)
1372 {
1373         return ofs->color->w;
1374 }
1375
1376 int GPU_offscreen_height(const GPUOffScreen *ofs)
1377 {
1378         return ofs->color->h;
1379 }
1380
1381 /* GPUShader */
1382
1383 struct GPUShader {
1384         GLhandleARB object;             /* handle for full shader */
1385         GLhandleARB vertex;             /* handle for vertex shader */
1386         GLhandleARB fragment;   /* handle for fragment shader */
1387         GLhandleARB lib;                /* handle for libment shader */
1388         int totattrib;                  /* total number of attributes */
1389         int uniforms;                   /* required uniforms */
1390 };
1391
1392 static void shader_print_errors(const char *task, char *log, const char **code, int totcode)
1393 {
1394         int i;
1395
1396         fprintf(stderr, "GPUShader: %s error:\n", task);
1397
1398         for (i = 0; i < totcode; i++) {
1399                 const char *c, *pos, *end = code[i] + strlen(code[i]);
1400                 int line = 1;
1401
1402                 if ((G.debug & G_DEBUG)) {
1403                         fprintf(stderr, "===== shader string %d ====\n", i + 1);
1404
1405                         c = code[i];
1406                         while ((c < end) && (pos = strchr(c, '\n'))) {
1407                                 fprintf(stderr, "%2d  ", line);
1408                                 fwrite(c, (pos+1)-c, 1, stderr);
1409                                 c = pos+1;
1410                                 line++;
1411                         }
1412                         
1413                         fprintf(stderr, "%s", c);
1414                 }
1415         }
1416         
1417         fprintf(stderr, "%s\n", log);
1418 }
1419
1420 static const char *gpu_shader_version(void)
1421 {
1422         /* turn on glsl 1.30 for bicubic bump mapping and ATI clipping support */
1423         if (GLEW_VERSION_3_0 &&
1424             (GPU_bicubic_bump_support() || GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)))
1425         {
1426                 return "#version 130\n";
1427         }
1428
1429         return "";
1430 }
1431
1432
1433 static const char *gpu_shader_standard_extensions(void)
1434 {
1435         /* need this extensions for high quality bump mapping */
1436         if (GPU_bicubic_bump_support())
1437                 return "#extension GL_ARB_texture_query_lod: enable\n";
1438
1439         return "";
1440 }
1441
1442 static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
1443 {
1444         /* some useful defines to detect GPU type */
1445         if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
1446                 strcat(defines, "#define GPU_ATI\n");
1447                 if (GLEW_VERSION_3_0)
1448                         strcat(defines, "#define CLIP_WORKAROUND\n");
1449         }
1450         else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
1451                 strcat(defines, "#define GPU_NVIDIA\n");
1452         else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
1453                 strcat(defines, "#define GPU_INTEL\n");
1454
1455         if (GPU_bicubic_bump_support())
1456                 strcat(defines, "#define BUMP_BICUBIC\n");
1457         return;
1458 }
1459
1460 GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines)
1461 {
1462         GLint status;
1463         GLcharARB log[5000];
1464         GLsizei length = 0;
1465         GPUShader *shader;
1466         char standard_defines[MAX_DEFINE_LENGTH] = "";
1467
1468         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
1469                 return NULL;
1470
1471         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
1472
1473         if (vertexcode)
1474                 shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
1475         if (fragcode)
1476                 shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
1477         shader->object = glCreateProgramObjectARB();
1478
1479         if (!shader->object ||
1480             (vertexcode && !shader->vertex) ||
1481             (fragcode && !shader->fragment))
1482         {
1483                 fprintf(stderr, "GPUShader, object creation failed.\n");
1484                 GPU_shader_free(shader);
1485                 return NULL;
1486         }
1487
1488         gpu_shader_standard_defines(standard_defines);
1489
1490         if (vertexcode) {
1491                 const char *source[5];
1492                 /* custom limit, may be too small, beware */
1493                 int num_source = 0;
1494
1495                 source[num_source++] = gpu_shader_version();
1496                 source[num_source++] = gpu_shader_standard_extensions();
1497                 source[num_source++] = standard_defines;
1498
1499                 if (defines) source[num_source++] = defines;
1500                 if (vertexcode) source[num_source++] = vertexcode;
1501
1502                 glAttachObjectARB(shader->object, shader->vertex);
1503                 glShaderSourceARB(shader->vertex, num_source, source, NULL);
1504
1505                 glCompileShaderARB(shader->vertex);
1506                 glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status);
1507
1508                 if (!status) {
1509                         glGetInfoLogARB(shader->vertex, sizeof(log), &length, log);
1510                         shader_print_errors("compile", log, source, num_source);
1511
1512                         GPU_shader_free(shader);
1513                         return NULL;
1514                 }
1515         }
1516
1517         if (fragcode) {
1518                 const char *source[6];
1519                 int num_source = 0;
1520
1521                 source[num_source++] = gpu_shader_version();
1522                 source[num_source++] = gpu_shader_standard_extensions();
1523                 source[num_source++] = standard_defines;
1524
1525                 if (defines) source[num_source++] = defines;
1526                 if (libcode) source[num_source++] = libcode;
1527                 if (fragcode) source[num_source++] = fragcode;
1528
1529                 glAttachObjectARB(shader->object, shader->fragment);
1530                 glShaderSourceARB(shader->fragment, num_source, source, NULL);
1531
1532                 glCompileShaderARB(shader->fragment);
1533                 glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status);
1534
1535                 if (!status) {
1536                         glGetInfoLogARB(shader->fragment, sizeof(log), &length, log);
1537                         shader_print_errors("compile", log, source, num_source);
1538
1539                         GPU_shader_free(shader);
1540                         return NULL;
1541                 }
1542         }
1543
1544 #if 0
1545         if (lib && lib->lib)
1546                 glAttachObjectARB(shader->object, lib->lib);
1547 #endif
1548
1549         glLinkProgramARB(shader->object);
1550         glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status);
1551         if (!status) {
1552                 glGetInfoLogARB(shader->object, sizeof(log), &length, log);
1553                 if (fragcode) shader_print_errors("linking", log, &fragcode, 1);
1554                 else if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1);
1555                 else if (libcode) shader_print_errors("linking", log, &libcode, 1);
1556
1557                 GPU_shader_free(shader);
1558                 return NULL;
1559         }
1560
1561         return shader;
1562 }
1563
1564 #if 0
1565 GPUShader *GPU_shader_create_lib(const char *code)
1566 {
1567         GLint status;
1568         GLcharARB log[5000];
1569         GLsizei length = 0;
1570         GPUShader *shader;
1571
1572         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
1573                 return NULL;
1574
1575         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
1576
1577         shader->lib = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
1578
1579         if (!shader->lib) {
1580                 fprintf(stderr, "GPUShader, object creation failed.\n");
1581                 GPU_shader_free(shader);
1582                 return NULL;
1583         }
1584
1585         glShaderSourceARB(shader->lib, 1, (const char**)&code, NULL);
1586
1587         glCompileShaderARB(shader->lib);
1588         glGetObjectParameterivARB(shader->lib, GL_OBJECT_COMPILE_STATUS_ARB, &status);
1589
1590         if (!status) {
1591                 glGetInfoLogARB(shader->lib, sizeof(log), &length, log);
1592                 shader_print_errors("compile", log, code);
1593
1594                 GPU_shader_free(shader);
1595                 return NULL;
1596         }
1597
1598         return shader;
1599 }
1600 #endif
1601
1602 void GPU_shader_bind(GPUShader *shader)
1603 {
1604         GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
1605         glUseProgramObjectARB(shader->object);
1606         GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
1607 }
1608
1609 void GPU_shader_unbind(void)
1610 {
1611         GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
1612         glUseProgramObjectARB(0);
1613         GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
1614 }
1615
1616 void GPU_shader_free(GPUShader *shader)
1617 {
1618         if (shader->lib)
1619                 glDeleteObjectARB(shader->lib);
1620         if (shader->vertex)
1621                 glDeleteObjectARB(shader->vertex);
1622         if (shader->fragment)
1623                 glDeleteObjectARB(shader->fragment);
1624         if (shader->object)
1625                 glDeleteObjectARB(shader->object);
1626         MEM_freeN(shader);
1627 }
1628
1629 int GPU_shader_get_uniform(GPUShader *shader, const char *name)
1630 {
1631         return glGetUniformLocationARB(shader->object, name);
1632 }
1633
1634 void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
1635 {
1636         if (location == -1)
1637                 return;
1638
1639         GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
1640
1641         if (length == 1) glUniform1fvARB(location, arraysize, value);
1642         else if (length == 2) glUniform2fvARB(location, arraysize, value);
1643         else if (length == 3) glUniform3fvARB(location, arraysize, value);
1644         else if (length == 4) glUniform4fvARB(location, arraysize, value);
1645         else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value);
1646         else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value);
1647
1648         GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
1649 }
1650
1651 void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
1652 {
1653         if (location == -1)
1654                 return;
1655
1656         GPU_CHECK_ERRORS_AROUND(glUniform1iARB(location, value));
1657 }
1658
1659 void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
1660 {
1661         GLenum arbnumber;
1662
1663         if (tex->number >= GG.maxtextures) {
1664                 fprintf(stderr, "Not enough texture slots.");
1665                 return;
1666         }
1667                 
1668         if (tex->number == -1)
1669                 return;
1670
1671         if (location == -1)
1672                 return;
1673
1674         GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
1675
1676         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
1677
1678         if (tex->number != 0) glActiveTextureARB(arbnumber);
1679         if (tex->bindcode != 0)
1680                 glBindTexture(tex->target, tex->bindcode);
1681         else
1682                 GPU_invalid_tex_bind(tex->target);
1683         glUniform1iARB(location, tex->number);
1684         glEnable(tex->target);
1685         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
1686
1687         GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
1688 }
1689
1690 int GPU_shader_get_attribute(GPUShader *shader, const char *name)
1691 {
1692         int index;
1693         
1694         GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocationARB(shader->object, name));
1695
1696         return index;
1697 }
1698
1699 GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
1700 {
1701         GPUShader *retval = NULL;
1702
1703         switch (shader) {
1704                 case GPU_SHADER_VSM_STORE:
1705                         if (!GG.shaders.vsm_store)
1706                                 GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL);
1707                         retval = GG.shaders.vsm_store;
1708                         break;
1709                 case GPU_SHADER_SEP_GAUSSIAN_BLUR:
1710                         if (!GG.shaders.sep_gaussian_blur)
1711                                 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);
1712                         retval = GG.shaders.sep_gaussian_blur;
1713                         break;
1714         }
1715
1716         if (retval == NULL)
1717                 printf("Unable to create a GPUShader for builtin shader: %d\n", shader);
1718
1719         return retval;
1720 }
1721
1722 #define MAX_DEFINES 100
1723
1724 GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
1725 {
1726         int offset;
1727         char defines[MAX_DEFINES] = "";
1728         /* avoid shaders out of range */
1729         if (effects >= MAX_FX_SHADERS)
1730                 return NULL;
1731
1732         offset = 2 * effects;
1733
1734         if (persp) {
1735                 offset += 1;
1736                 strcat(defines, "#define PERSP_MATRIX\n");
1737         }
1738
1739         if (!GG.shaders.fx_shaders[offset]) {
1740                 switch(effects) {
1741                         case GPU_SHADER_FX_SSAO:
1742                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
1743                                 break;
1744
1745                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
1746                                 strcat(defines, "#define FIRST_PASS\n");
1747                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
1748                                 break;
1749
1750                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
1751                                 strcat(defines, "#define SECOND_PASS\n");
1752                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
1753                                 break;
1754
1755                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
1756                                 strcat(defines, "#define THIRD_PASS\n");
1757                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
1758                                 break;
1759
1760                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
1761                                 strcat(defines, "#define FOURTH_PASS\n");
1762                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
1763                                 break;
1764
1765                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
1766                                 strcat(defines, "#define FIFTH_PASS\n");
1767                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
1768                                 break;
1769
1770                         case GPU_SHADER_FX_DEPTH_RESOLVE:
1771                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, defines);
1772                 }
1773         }
1774
1775         return GG.shaders.fx_shaders[offset];
1776 }
1777
1778
1779 void GPU_shader_free_builtin_shaders(void)
1780 {
1781         int i;
1782
1783         if (GG.shaders.vsm_store) {
1784                 MEM_freeN(GG.shaders.vsm_store);
1785                 GG.shaders.vsm_store = NULL;
1786         }
1787
1788         if (GG.shaders.sep_gaussian_blur) {
1789                 MEM_freeN(GG.shaders.sep_gaussian_blur);
1790                 GG.shaders.sep_gaussian_blur = NULL;
1791         }
1792
1793         for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
1794                 if (GG.shaders.fx_shaders[i]) {
1795                         MEM_freeN(GG.shaders.fx_shaders[i]);
1796                         GG.shaders.fx_shaders[i] = NULL;
1797                 }
1798         }
1799 }
1800
1801 #if 0
1802 /* GPUPixelBuffer */
1803
1804 typedef struct GPUPixelBuffer {
1805         GLuint bindcode[2];
1806         GLuint current;
1807         int datasize;
1808         int numbuffers;
1809         int halffloat;
1810 } GPUPixelBuffer;
1811
1812 void GPU_pixelbuffer_free(GPUPixelBuffer *pb)
1813 {
1814         if (pb->bindcode[0])
1815                 glDeleteBuffersARB(pb->numbuffers, pb->bindcode);
1816         MEM_freeN(pb);
1817 }
1818
1819 GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers)
1820 {
1821         GPUPixelBuffer *pb;
1822
1823         if (!GLEW_ARB_multitexture || !GLEW_EXT_pixel_buffer_object)
1824                 return NULL;
1825         
1826         pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
1827         pb->datasize = x*y*4*((halffloat)? 16: 8);
1828         pb->numbuffers = numbuffers;
1829         pb->halffloat = halffloat;
1830
1831         glGenBuffersARB(pb->numbuffers, pb->bindcode);
1832
1833         if (!pb->bindcode[0]) {
1834                 fprintf(stderr, "GPUPixelBuffer allocation failed\n");
1835                 GPU_pixelbuffer_free(pb);
1836                 return NULL;
1837         }
1838
1839         return pb;
1840 }
1841
1842 void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
1843 {
1844         void *pixels;
1845         int i;
1846
1847         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
1848
1849         for (i = 0; i < pb->numbuffers; i++) {
1850                 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->bindcode[pb->current]);
1851                 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->datasize, NULL,
1852                 GL_STREAM_DRAW_ARB);
1853
1854                 pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
1855                 /*memcpy(pixels, _oImage.data(), pb->datasize);*/
1856
1857                 if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
1858                         fprintf(stderr, "Could not unmap opengl PBO\n");
1859                         break;
1860                 }
1861         }
1862
1863         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
1864 }
1865
1866 static int pixelbuffer_map_into_gpu(GLuint bindcode)
1867 {
1868         void *pixels;
1869
1870         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
1871         pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
1872
1873         /* do stuff in pixels */
1874
1875         if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
1876                 fprintf(stderr, "Could not unmap opengl PBO\n");
1877                 return 0;
1878         }
1879         
1880         return 1;
1881 }
1882
1883 static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode)
1884 {
1885         GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE;
1886         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
1887         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
1888
1889         glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h,
1890                                         GL_RGBA, type, NULL);
1891
1892         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
1893         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
1894 }
1895
1896 void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
1897 {
1898         int newbuffer;
1899
1900         if (pb->numbuffers == 1) {
1901                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]);
1902                 pixelbuffer_map_into_gpu(pb->bindcode[0]);
1903         }
1904         else {
1905                 pb->current = (pb->current+1)%pb->numbuffers;
1906                 newbuffer = (pb->current+1)%pb->numbuffers;
1907
1908                 pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
1909                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
1910         }
1911 }
1912 #endif
1913