style cleanup
[blender-staging.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
32
33 #include "GL/glew.h"
34
35 #include "DNA_image_types.h"
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_utildefines.h"
41 #include "BLI_math_base.h"
42
43 #include "BKE_global.h"
44
45 #include "GPU_draw.h"
46 #include "GPU_extensions.h"
47 #include "GPU_simple_shader.h"
48 #include "gpu_codegen.h"
49
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53
54 #ifdef WIN32
55 #  include "BLI_winstuff.h"
56 #endif
57
58 /* Extensions support */
59
60 /* extensions used:
61  * - texture border clamp: 1.3 core
62  * - fragment shader: 2.0 core
63  * - framebuffer object: ext specification
64  * - multitexture 1.3 core
65  * - arb non power of two: 2.0 core
66  * - pixel buffer objects? 2.1 core
67  * - arb draw buffers? 2.0 core
68  */
69
70 /* Non-generated shaders */
71 extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
72 extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
73 extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
74 extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
75
76 typedef struct GPUShaders {
77         GPUShader *vsm_store;
78         GPUShader *sep_gaussian_blur;
79 } GPUShaders;
80
81 static struct GPUGlobal {
82         GLint maxtexsize;
83         GLint maxtextures;
84         GLuint currentfb;
85         int glslsupport;
86         int extdisabled;
87         int colordepth;
88         int npotdisabled; /* ATI 3xx-5xx (and more) chipsets support NPoT partially (== not enough) */
89         GPUDeviceType device;
90         GPUOSType os;
91         GPUDriverType driver;
92         GPUShaders shaders;
93 } GG = {1, 0};
94
95 /* GPU Types */
96
97 int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
98 {
99         return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
100 }
101
102 /* GPU Extensions */
103
104 static int gpu_extensions_init = 0;
105
106 void GPU_extensions_disable(void)
107 {
108         GG.extdisabled = 1;
109 }
110
111 int GPU_max_texture_size(void)
112 {
113         return GG.maxtexsize;
114 }
115
116 void GPU_extensions_init(void)
117 {
118         GLint r, g, b;
119         const char *vendor, *renderer;
120
121         /* can't avoid calling this multiple times, see wm_window_add_ghostwindow */
122         if (gpu_extensions_init) return;
123         gpu_extensions_init= 1;
124
125         glewInit();
126         GPU_codegen_init();
127
128         /* glewIsSupported("GL_VERSION_2_0") */
129
130         if (GLEW_ARB_multitexture)
131                 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &GG.maxtextures);
132
133         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
134
135         GG.glslsupport = 1;
136         if (!GLEW_ARB_multitexture) GG.glslsupport = 0;
137         if (!GLEW_ARB_vertex_shader) GG.glslsupport = 0;
138         if (!GLEW_ARB_fragment_shader) GG.glslsupport = 0;
139
140         glGetIntegerv(GL_RED_BITS, &r);
141         glGetIntegerv(GL_GREEN_BITS, &g);
142         glGetIntegerv(GL_BLUE_BITS, &b);
143         GG.colordepth = r+g+b; /* assumes same depth for RGB */
144
145         vendor = (const char *)glGetString(GL_VENDOR);
146         renderer = (const char *)glGetString(GL_RENDERER);
147
148         if (strstr(vendor, "ATI")) {
149                 GG.device = GPU_DEVICE_ATI;
150                 GG.driver = GPU_DRIVER_OFFICIAL;
151         }
152         else if (strstr(vendor, "NVIDIA")) {
153                 GG.device = GPU_DEVICE_NVIDIA;
154                 GG.driver = GPU_DRIVER_OFFICIAL;
155         }
156         else if (strstr(vendor, "Intel") ||
157                 /* src/mesa/drivers/dri/intel/intel_context.c */
158                 strstr(renderer, "Mesa DRI Intel") ||
159                 strstr(renderer, "Mesa DRI Mobile Intel")) {
160                 GG.device = GPU_DEVICE_INTEL;
161                 GG.driver = GPU_DRIVER_OFFICIAL;
162         }
163         else if (strstr(renderer, "Mesa DRI R") || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI "))) {
164                 GG.device = GPU_DEVICE_ATI;
165                 GG.driver = GPU_DRIVER_OPENSOURCE;
166         }
167         else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
168                 GG.device = GPU_DEVICE_NVIDIA;
169                 GG.driver = GPU_DRIVER_OPENSOURCE;
170         }
171         else if (strstr(vendor, "Mesa")) {
172                 GG.device = GPU_DEVICE_SOFTWARE;
173                 GG.driver = GPU_DRIVER_SOFTWARE;
174         }
175         else if (strstr(vendor, "Microsoft")) {
176                 GG.device = GPU_DEVICE_SOFTWARE;
177                 GG.driver = GPU_DRIVER_SOFTWARE;
178         }
179         else if (strstr(renderer, "Apple Software Renderer")) {
180                 GG.device = GPU_DEVICE_SOFTWARE;
181                 GG.driver = GPU_DRIVER_SOFTWARE;
182         }
183         else {
184                 GG.device = GPU_DEVICE_ANY;
185                 GG.driver = GPU_DRIVER_ANY;
186         }
187
188         if (GG.device == GPU_DEVICE_ATI) {
189                 /* ATI 9500 to X2300 cards support NPoT textures poorly
190                  * Incomplete list http://dri.freedesktop.org/wiki/ATIRadeon
191                  * New IDs from MESA's src/gallium/drivers/r300/r300_screen.c
192                  */
193                 if (strstr(renderer, "R3") || strstr(renderer, "RV3") ||
194                     strstr(renderer, "R4") || strstr(renderer, "RV4") ||
195                     strstr(renderer, "RS4") || strstr(renderer, "RC4") ||
196                     strstr(renderer, "R5") || strstr(renderer, "RV5") ||
197                     strstr(renderer, "RS600") || strstr(renderer, "RS690") ||
198                     strstr(renderer, "RS740") || strstr(renderer, "X1") ||
199                     strstr(renderer, "X2") || strstr(renderer, "Radeon 9") ||
200                     strstr(renderer, "RADEON 9"))
201                 {
202                         GG.npotdisabled = 1;
203                 }
204         }
205
206         /* make sure double side isn't used by default and only getting enabled in places where it's
207          * really needed to prevent different unexpected behaviors like with intel gme965 card (sergey) */
208         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
209
210 #ifdef _WIN32
211         GG.os = GPU_OS_WIN;
212 #elif defined(__APPLE__)
213         GG.os = GPU_OS_MAC;
214 #else
215         GG.os = GPU_OS_UNIX;
216 #endif
217
218         GPU_simple_shaders_init();
219 }
220
221 void GPU_extensions_exit(void)
222 {
223         gpu_extensions_init = 0;
224         GPU_codegen_exit();
225         GPU_simple_shaders_exit();
226 }
227
228 int GPU_glsl_support(void)
229 {
230         return !GG.extdisabled && GG.glslsupport;
231 }
232
233 int GPU_non_power_of_two_support(void)
234 {
235         if (GG.npotdisabled)
236                 return 0;
237
238         return GLEW_ARB_texture_non_power_of_two;
239 }
240
241 int GPU_color_depth(void)
242 {
243         return GG.colordepth;
244 }
245
246 int GPU_print_error(const char *str)
247 {
248         GLenum errCode;
249
250         if (G.debug & G_DEBUG) {
251                 if ((errCode = glGetError()) != GL_NO_ERROR) {
252                         fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode));
253                         return 1;
254                 }
255         }
256
257         return 0;
258 }
259
260 static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
261 {
262         const char *err= "unknown";
263
264         switch (status) {
265                 case GL_FRAMEBUFFER_COMPLETE_EXT:
266                         break;
267                 case GL_INVALID_OPERATION:
268                         err= "Invalid operation";
269                         break;
270                 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
271                         err= "Incomplete attachment";
272                         break;
273                 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
274                         err= "Unsupported framebuffer format";
275                         break;
276                 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
277                         err= "Missing attachment";
278                         break;
279                 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
280                         err= "Attached images must have same dimensions";
281                         break;
282                 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
283                         err= "Attached images must have same format";
284                         break;
285                 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
286                         err= "Missing draw buffer";
287                         break;
288                 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
289                         err= "Missing read buffer";
290                         break;
291         }
292
293         if (err_out) {
294                 BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
295                         (int)status, err);
296         }
297         else {
298                 fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
299                         (int)status, err);
300         }
301 }
302
303 /* GPUTexture */
304
305 struct GPUTexture {
306         int w, h;                               /* width/height */
307         int number;                             /* number for multitexture binding */
308         int refcount;                   /* reference count */
309         GLenum target;                  /* GL_TEXTURE_* */
310         GLuint bindcode;                /* opengl identifier for texture */
311         int fromblender;                /* we got the texture from Blender */
312
313         GPUFrameBuffer *fb;             /* GPUFramebuffer this texture is attached to */
314         int depth;                              /* is a depth texture? */
315 };
316
317 static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels)
318 {
319         unsigned char *pixels, *p;
320         float *fp;
321         int a, len;
322
323         len = 4*length;
324         fp = fpixels;
325         p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels");
326
327         for (a=0; a<len; a++, p++, fp++)
328                 *p = FTOCHAR((*fp));
329
330         return pixels;
331 }
332
333 static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
334 {
335         void *pixels = MEM_callocN(sizeof(char)*4*w*h, "GPUTextureEmptyPixels");
336
337         if (target == GL_TEXTURE_1D)
338                 glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
339         else
340                 glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
341         
342         MEM_freeN(pixels);
343 }
344
345 static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth, char err_out[256])
346 {
347         GPUTexture *tex;
348         GLenum type, format, internalformat;
349         void *pixels = NULL;
350
351         if (depth && !GLEW_ARB_depth_texture)
352                 return NULL;
353
354         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
355         tex->w = w;
356         tex->h = h;
357         tex->number = -1;
358         tex->refcount = 1;
359         tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
360         tex->depth = depth;
361
362         glGenTextures(1, &tex->bindcode);
363
364         if (!tex->bindcode) {
365                 if (err_out) {
366                         BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
367                                 (int)glGetError());
368                 }
369                 else {
370                         fprintf(stderr, "GPUTexture: texture create failed: %d\n",
371                                 (int)glGetError());
372                 }
373                 GPU_texture_free(tex);
374                 return NULL;
375         }
376
377         if (!GPU_non_power_of_two_support()) {
378                 tex->w = power_of_2_max_i(tex->w);
379                 tex->h = power_of_2_max_i(tex->h);
380         }
381
382         tex->number = 0;
383         glBindTexture(tex->target, tex->bindcode);
384
385         if (depth) {
386                 type = GL_UNSIGNED_BYTE;
387                 format = GL_DEPTH_COMPONENT;
388                 internalformat = GL_DEPTH_COMPONENT;
389         }
390         else {
391                 type = GL_UNSIGNED_BYTE;
392                 format = GL_RGBA;
393                 internalformat = GL_RGBA8;
394
395                 if (fpixels)
396                         pixels = GPU_texture_convert_pixels(w*h, fpixels);
397         }
398
399         if (tex->target == GL_TEXTURE_1D) {
400                 glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
401
402                 if (fpixels) {
403                         glTexSubImage1D(tex->target, 0, 0, w, format, type,
404                                 pixels ? pixels : fpixels);
405
406                         if (tex->w > w)
407                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0,
408                                         tex->w-w, 1);
409                 }
410         }
411         else {
412                 glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
413                              format, type, NULL);
414
415                 if (fpixels) {
416                         glTexSubImage2D(tex->target, 0, 0, 0, w, h,
417                                 format, type, pixels ? pixels : fpixels);
418
419                         if (tex->w > w)
420                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h);
421                         if (tex->h > h)
422                                 GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h);
423                 }
424         }
425
426         if (pixels)
427                 MEM_freeN(pixels);
428
429         if (depth) {
430                 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
431                 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
432                 glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
433                 glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
434                 glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);  
435         }
436         else {
437                 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
438                 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
439         }
440
441         if (tex->target != GL_TEXTURE_1D) {
442                 /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
443                 GLenum wrapmode = (depth || tex->h == 1)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
444                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
445                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
446
447 #if 0
448                 float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
449                 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); 
450 #endif
451         }
452         else
453                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
454
455         return tex;
456 }
457
458
459 GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels)
460 {
461         GPUTexture *tex;
462         GLenum type, format, internalformat;
463         void *pixels = NULL;
464         float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
465
466         if (!GLEW_VERSION_1_2)
467                 return NULL;
468
469         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
470         tex->w = w;
471         tex->h = h;
472         tex->depth = depth;
473         tex->number = -1;
474         tex->refcount = 1;
475         tex->target = GL_TEXTURE_3D;
476
477         glGenTextures(1, &tex->bindcode);
478
479         if (!tex->bindcode) {
480                 fprintf(stderr, "GPUTexture: texture create failed: %d\n",
481                         (int)glGetError());
482                 GPU_texture_free(tex);
483                 return NULL;
484         }
485
486         if (!GPU_non_power_of_two_support()) {
487                 tex->w = power_of_2_max_i(tex->w);
488                 tex->h = power_of_2_max_i(tex->h);
489                 tex->depth = power_of_2_max_i(tex->depth);
490         }
491
492         tex->number = 0;
493         glBindTexture(tex->target, tex->bindcode);
494
495         GPU_print_error("3D glBindTexture");
496
497         type = GL_FLOAT;
498         if (channels == 4) {
499                 format = GL_RGBA;
500                 internalformat = GL_RGBA;
501         }
502         else {
503                 format = GL_RED;
504                 internalformat = GL_INTENSITY;
505         }
506
507         //if (fpixels)
508         //      pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
509
510         glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
511
512         GPU_print_error("3D glTexImage3D");
513
514         if (fpixels) {
515                 if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
516                         /* clear first to avoid unitialized pixels */
517                         float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
518                         glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero);
519                         MEM_freeN(zero);
520                 }
521
522                 glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
523                 GPU_print_error("3D glTexSubImage3D");
524         }
525
526
527         glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor);
528         GPU_print_error("3D GL_TEXTURE_BORDER_COLOR");
529         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
530         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
531         GPU_print_error("3D GL_LINEAR");
532         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
533         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
534         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
535         GPU_print_error("3D GL_CLAMP_TO_BORDER");
536
537         if (pixels)
538                 MEM_freeN(pixels);
539
540         GPU_texture_unbind(tex);
541
542         return tex;
543 }
544
545 GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, double time, int mipmap)
546 {
547         GPUTexture *tex;
548         GLint w, h, border, lastbindcode, bindcode;
549
550         glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
551
552         GPU_update_image_time(ima, time);
553         /* this binds a texture, so that's why to restore it with lastbindcode */
554         bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, isdata);
555
556         if (ima->gputexture) {
557                 ima->gputexture->bindcode = bindcode;
558                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
559                 return ima->gputexture;
560         }
561
562         if (!bindcode) {
563                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
564                 return NULL;
565         }
566
567         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
568         tex->bindcode = bindcode;
569         tex->number = -1;
570         tex->refcount = 1;
571         tex->target = GL_TEXTURE_2D;
572         tex->fromblender = 1;
573
574         ima->gputexture= tex;
575
576         if (!glIsTexture(tex->bindcode)) {
577                 GPU_print_error("Blender Texture");
578         }
579         else {
580                 glBindTexture(GL_TEXTURE_2D, tex->bindcode);
581                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
582                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
583                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
584
585                 tex->w = w - border;
586                 tex->h = h - border;
587         }
588
589         glBindTexture(GL_TEXTURE_2D, lastbindcode);
590
591         return tex;
592 }
593
594 GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
595 {
596         GPUTexture *tex = prv->gputexture[0];
597         GLint w, h, lastbindcode;
598         GLuint bindcode = 0;
599         
600         glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
601         
602         if (tex)
603                 bindcode = tex->bindcode;
604         
605         /* this binds a texture, so that's why to restore it */
606         if (bindcode == 0) {
607                 GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL);
608         }
609         if (tex) {
610                 tex->bindcode = bindcode;
611                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
612                 return tex;
613         }
614
615         /* error binding anything */
616         if (!bindcode) {
617                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
618                 return NULL;
619         }
620         
621         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
622         tex->bindcode = bindcode;
623         tex->number = -1;
624         tex->refcount = 1;
625         tex->target = GL_TEXTURE_2D;
626         
627         prv->gputexture[0]= tex;
628         
629         if (!glIsTexture(tex->bindcode)) {
630                 GPU_print_error("Blender Texture");
631         }
632         else {
633                 glBindTexture(GL_TEXTURE_2D, tex->bindcode);
634                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
635                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
636                 
637                 tex->w = w;
638                 tex->h = h;
639         }
640         
641         glBindTexture(GL_TEXTURE_2D, lastbindcode);
642         
643         return tex;
644
645 }
646
647 GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
648 {
649         GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out);
650
651         if (tex)
652                 GPU_texture_unbind(tex);
653         
654         return tex;
655 }
656
657 GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256])
658 {
659         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, err_out);
660
661         if (tex)
662                 GPU_texture_unbind(tex);
663         
664         return tex;
665 }
666
667 GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
668 {
669         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, err_out);
670
671         if (tex)
672                 GPU_texture_unbind(tex);
673         
674         return tex;
675 }
676
677 /**
678  * A shadow map for VSM needs two components (depth and depth^2)
679  */
680 GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
681 {
682         GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, err_out);
683
684         if (tex) {
685                 /* Now we tweak some of the settings */
686                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
687                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
688                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, size, size, 0, GL_RG, GL_FLOAT, NULL);
689
690                 GPU_texture_unbind(tex);
691         }
692
693         return tex;
694 }
695
696 void GPU_texture_bind(GPUTexture *tex, int number)
697 {
698         GLenum arbnumber;
699
700         if (number >= GG.maxtextures) {
701                 GPU_print_error("Not enough texture slots.");
702                 return;
703         }
704
705         if (number == -1)
706                 return;
707
708         GPU_print_error("Pre Texture Bind");
709
710         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number);
711         if (number != 0) glActiveTextureARB(arbnumber);
712         glBindTexture(tex->target, tex->bindcode);
713         glEnable(tex->target);
714         if (number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
715
716         tex->number = number;
717
718         GPU_print_error("Post Texture Bind");
719 }
720
721 void GPU_texture_unbind(GPUTexture *tex)
722 {
723         GLenum arbnumber;
724
725         if (tex->number >= GG.maxtextures) {
726                 GPU_print_error("Not enough texture slots.");
727                 return;
728         }
729
730         if (tex->number == -1)
731                 return;
732         
733         GPU_print_error("Pre Texture Unbind");
734
735         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
736         if (tex->number != 0) glActiveTextureARB(arbnumber);
737         glBindTexture(tex->target, 0);
738         glDisable(tex->target);
739         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
740
741         tex->number = -1;
742
743         GPU_print_error("Post Texture Unbind");
744 }
745
746 void GPU_texture_free(GPUTexture *tex)
747 {
748         tex->refcount--;
749
750         if (tex->refcount < 0)
751                 fprintf(stderr, "GPUTexture: negative refcount\n");
752         
753         if (tex->refcount == 0) {
754                 if (tex->fb)
755                         GPU_framebuffer_texture_detach(tex->fb, tex);
756                 if (tex->bindcode && !tex->fromblender)
757                         glDeleteTextures(1, &tex->bindcode);
758
759                 MEM_freeN(tex);
760         }
761 }
762
763 void GPU_texture_ref(GPUTexture *tex)
764 {
765         tex->refcount++;
766 }
767
768 int GPU_texture_target(GPUTexture *tex)
769 {
770         return tex->target;
771 }
772
773 int GPU_texture_opengl_width(GPUTexture *tex)
774 {
775         return tex->w;
776 }
777
778 int GPU_texture_opengl_height(GPUTexture *tex)
779 {
780         return tex->h;
781 }
782
783 int GPU_texture_opengl_bindcode(GPUTexture *tex)
784 {
785         return tex->bindcode;
786 }
787
788 GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
789 {
790         return tex->fb;
791 }
792
793 /* GPUFrameBuffer */
794
795 struct GPUFrameBuffer {
796         GLuint object;
797         GPUTexture *colortex;
798         GPUTexture *depthtex;
799 };
800
801 GPUFrameBuffer *GPU_framebuffer_create(void)
802 {
803         GPUFrameBuffer *fb;
804
805         if (!GLEW_EXT_framebuffer_object)
806                 return NULL;
807         
808         fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
809         glGenFramebuffersEXT(1, &fb->object);
810
811         if (!fb->object) {
812                 fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
813                         (int)glGetError());
814                 GPU_framebuffer_free(fb);
815                 return NULL;
816         }
817
818         return fb;
819 }
820
821 int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256])
822 {
823         GLenum status;
824         GLenum attachment;
825         GLenum error;
826
827         if (tex->depth)
828                 attachment = GL_DEPTH_ATTACHMENT_EXT;
829         else
830                 attachment = GL_COLOR_ATTACHMENT0_EXT;
831
832         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
833         GG.currentfb = fb->object;
834
835         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 
836                 tex->target, tex->bindcode, 0);
837
838         error = glGetError();
839
840         if (error == GL_INVALID_OPERATION) {
841                 GPU_framebuffer_restore();
842                 GPU_print_framebuffer_error(error, err_out);
843                 return 0;
844         }
845
846         if (tex->depth) {
847                 glDrawBuffer(GL_NONE);
848                 glReadBuffer(GL_NONE);
849         }
850         else {
851                 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
852                 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
853         }
854
855         status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
856
857         if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
858                 GPU_framebuffer_restore();
859                 GPU_print_framebuffer_error(status, err_out);
860                 return 0;
861         }
862
863         if (tex->depth)
864                 fb->depthtex = tex;
865         else
866                 fb->colortex = tex;
867
868         tex->fb= fb;
869
870         return 1;
871 }
872
873 void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
874 {
875         GLenum attachment;
876
877         if (!tex->fb)
878                 return;
879
880         if (GG.currentfb != tex->fb->object) {
881                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
882                 GG.currentfb = tex->fb->object;
883         }
884
885         if (tex->depth) {
886                 fb->depthtex = NULL;
887                 attachment = GL_DEPTH_ATTACHMENT_EXT;
888         }
889         else {
890                 fb->colortex = NULL;
891                 attachment = GL_COLOR_ATTACHMENT0_EXT;
892         }
893
894         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
895                 tex->target, 0, 0);
896
897         tex->fb = NULL;
898 }
899
900 void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, int w, int h)
901 {
902         /* push attributes */
903         glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
904         glDisable(GL_SCISSOR_TEST);
905
906         /* bind framebuffer */
907         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
908
909         /* push matrices and set default viewport and matrix */
910         glViewport(0, 0, w, h);
911         GG.currentfb = tex->fb->object;
912
913         glMatrixMode(GL_PROJECTION);
914         glPushMatrix();
915         glMatrixMode(GL_MODELVIEW);
916         glPushMatrix();
917 }
918
919 void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
920 {
921         /* restore matrix */
922         glMatrixMode(GL_PROJECTION);
923         glPopMatrix();
924         glMatrixMode(GL_MODELVIEW);
925         glPopMatrix();
926
927         /* restore attributes */
928         glPopAttrib();
929         glEnable(GL_SCISSOR_TEST);
930 }
931
932 void GPU_framebuffer_free(GPUFrameBuffer *fb)
933 {
934         if (fb->depthtex)
935                 GPU_framebuffer_texture_detach(fb, fb->depthtex);
936         if (fb->colortex)
937                 GPU_framebuffer_texture_detach(fb, fb->colortex);
938
939         if (fb->object) {
940                 glDeleteFramebuffersEXT(1, &fb->object);
941
942                 if (GG.currentfb == fb->object) {
943                         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
944                         GG.currentfb = 0;
945                 }
946         }
947
948         MEM_freeN(fb);
949 }
950
951 void GPU_framebuffer_restore(void)
952 {
953         if (GG.currentfb != 0) {
954                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
955                 GG.currentfb = 0;
956         }
957 }
958
959 void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
960 {
961         float scaleh[2] = {1.0f/GPU_texture_opengl_width(blurtex), 0.0f};
962         float scalev[2] = {0.0f, 1.0f/GPU_texture_opengl_height(tex)};
963
964         GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
965         int scale_uniform, texture_source_uniform;
966
967         if (!blur_shader)
968                 return;
969
970         scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
971         texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
972                 
973         /* Blurring horizontally */
974
975         /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
976          * pushing unnecessary matrices onto the OpenGL stack. */
977         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
978
979         GPU_shader_bind(blur_shader);
980         GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scaleh);
981         GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
982         glViewport(0, 0, GPU_texture_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
983
984         /* Peparing to draw quad */
985         glMatrixMode(GL_MODELVIEW);
986         glLoadIdentity();
987         glMatrixMode(GL_TEXTURE);
988         glLoadIdentity();
989         glMatrixMode(GL_PROJECTION);
990         glLoadIdentity();
991
992         GPU_texture_bind(tex, 0);
993
994         /* Drawing quad */
995         glBegin(GL_QUADS);
996         glTexCoord2d(0, 0); glVertex2f(1, 1);
997         glTexCoord2d(1, 0); glVertex2f(-1, 1);
998         glTexCoord2d(1, 1); glVertex2f(-1, -1);
999         glTexCoord2d(0, 1); glVertex2f(1, -1);
1000         glEnd();
1001                 
1002         /* Blurring vertically */
1003
1004         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1005         glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
1006         GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scalev);
1007         GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
1008         GPU_texture_bind(blurtex, 0);
1009
1010         glBegin(GL_QUADS);
1011         glTexCoord2d(0, 0); glVertex2f(1, 1);
1012         glTexCoord2d(1, 0); glVertex2f(-1, 1);
1013         glTexCoord2d(1, 1); glVertex2f(-1, -1);
1014         glTexCoord2d(0, 1); glVertex2f(1, -1);
1015         glEnd();
1016
1017         GPU_shader_unbind();
1018 }
1019
1020 /* GPUOffScreen */
1021
1022 struct GPUOffScreen {
1023         GPUFrameBuffer *fb;
1024         GPUTexture *color;
1025         GPUTexture *depth;
1026
1027         /* requested width/height, may be smaller than actual texture size due
1028          * to missing non-power of two support, so we compensate for that */
1029         int w, h;
1030 };
1031
1032 GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
1033 {
1034         GPUOffScreen *ofs;
1035
1036         ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
1037         ofs->w= width;
1038         ofs->h= height;
1039
1040         ofs->fb = GPU_framebuffer_create();
1041         if (!ofs->fb) {
1042                 GPU_offscreen_free(ofs);
1043                 return NULL;
1044         }
1045
1046         ofs->depth = GPU_texture_create_depth(width, height, err_out);
1047         if (!ofs->depth) {
1048                 GPU_offscreen_free(ofs);
1049                 return NULL;
1050         }
1051
1052         if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) {
1053                 GPU_offscreen_free(ofs);
1054                 return NULL;
1055         }
1056
1057         ofs->color = GPU_texture_create_2D(width, height, NULL, err_out);
1058         if (!ofs->color) {
1059                 GPU_offscreen_free(ofs);
1060                 return NULL;
1061         }
1062
1063         if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, err_out)) {
1064                 GPU_offscreen_free(ofs);
1065                 return NULL;
1066         }
1067
1068         GPU_framebuffer_restore();
1069
1070         return ofs;
1071 }
1072
1073 void GPU_offscreen_free(GPUOffScreen *ofs)
1074 {
1075         if (ofs->fb)
1076                 GPU_framebuffer_free(ofs->fb);
1077         if (ofs->color)
1078                 GPU_texture_free(ofs->color);
1079         if (ofs->depth)
1080                 GPU_texture_free(ofs->depth);
1081         
1082         MEM_freeN(ofs);
1083 }
1084
1085 void GPU_offscreen_bind(GPUOffScreen *ofs)
1086 {
1087         glDisable(GL_SCISSOR_TEST);
1088         GPU_framebuffer_texture_bind(ofs->fb, ofs->color, ofs->w, ofs->h);
1089 }
1090
1091 void GPU_offscreen_unbind(GPUOffScreen *ofs)
1092 {
1093         GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
1094         GPU_framebuffer_restore();
1095         glEnable(GL_SCISSOR_TEST);
1096 }
1097
1098 void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
1099 {
1100         glReadPixels(0, 0, ofs->w, ofs->h, GL_RGBA, type, pixels);
1101 }
1102
1103 int GPU_offscreen_width(GPUOffScreen *ofs)
1104 {
1105         return ofs->w;
1106 }
1107
1108 int GPU_offscreen_height(GPUOffScreen *ofs)
1109 {
1110         return ofs->h;
1111 }
1112
1113 /* GPUShader */
1114
1115 struct GPUShader {
1116         GLhandleARB object;             /* handle for full shader */
1117         GLhandleARB vertex;             /* handle for vertex shader */
1118         GLhandleARB fragment;   /* handle for fragment shader */
1119         GLhandleARB lib;                /* handle for libment shader */
1120         int totattrib;                  /* total number of attributes */
1121 };
1122
1123 static void shader_print_errors(const char *task, char *log, const char *code)
1124 {
1125         const char *c, *pos, *end = code + strlen(code);
1126         int line = 1;
1127
1128         fprintf(stderr, "GPUShader: %s error:\n", task);
1129
1130         if (G.debug & G_DEBUG) {
1131                 c = code;
1132                 while ((c < end) && (pos = strchr(c, '\n'))) {
1133                         fprintf(stderr, "%2d  ", line);
1134                         fwrite(c, (pos+1)-c, 1, stderr);
1135                         c = pos+1;
1136                         line++;
1137                 }
1138
1139                 fprintf(stderr, "%s", c);
1140         }
1141
1142         fprintf(stderr, "%s\n", log);
1143 }
1144
1145 static const char *gpu_shader_standard_extensions(void)
1146 {
1147         /* need this extensions for high quality bump mapping */
1148         if (GPU_bicubic_bump_support()) {
1149                 return "#version 130\n"
1150                        "#extension GL_ARB_texture_query_lod: enable\n"
1151                        "#define BUMP_BICUBIC\n";
1152         }
1153
1154         return "";
1155 }
1156
1157 static const char *gpu_shader_standard_defines(void)
1158 {
1159         /* some useful defines to detect GPU type */
1160         if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY))
1161                 return "#define GPU_ATI\n";
1162         else if(GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
1163                 return "#define GPU_NVIDIA\n";
1164         else if(GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
1165                 return "#define GPU_INTEL\n";
1166         
1167         return "";
1168 }
1169
1170 GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines)
1171 {
1172         GLint status;
1173         GLcharARB log[5000];
1174         GLsizei length = 0;
1175         GPUShader *shader;
1176
1177         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
1178                 return NULL;
1179
1180         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
1181
1182         if (vertexcode)
1183                 shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
1184         if (fragcode)
1185                 shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
1186         shader->object = glCreateProgramObjectARB();
1187
1188         if (!shader->object ||
1189             (vertexcode && !shader->vertex) ||
1190             (fragcode && !shader->fragment))
1191         {
1192                 fprintf(stderr, "GPUShader, object creation failed.\n");
1193                 GPU_shader_free(shader);
1194                 return NULL;
1195         }
1196
1197         if (vertexcode) {
1198                 const char *source[4];
1199                 int num_source = 0;
1200
1201                 source[num_source++] = gpu_shader_standard_extensions();
1202                 source[num_source++] = gpu_shader_standard_defines();
1203
1204                 if (defines) source[num_source++] = defines;
1205                 if (vertexcode) source[num_source++] = vertexcode;
1206
1207                 glAttachObjectARB(shader->object, shader->vertex);
1208                 glShaderSourceARB(shader->vertex, num_source, source, NULL);
1209
1210                 glCompileShaderARB(shader->vertex);
1211                 glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status);
1212
1213                 if (!status) {
1214                         glGetInfoLogARB(shader->vertex, sizeof(log), &length, log);
1215                         shader_print_errors("compile", log, vertexcode);
1216
1217                         GPU_shader_free(shader);
1218                         return NULL;
1219                 }
1220         }
1221
1222         if (fragcode) {
1223                 const char *source[5];
1224                 int num_source = 0;
1225
1226                 source[num_source++] = gpu_shader_standard_extensions();
1227                 source[num_source++] = gpu_shader_standard_defines();
1228
1229                 if (defines) source[num_source++] = defines;
1230                 if (libcode) source[num_source++] = libcode;
1231                 if (fragcode) source[num_source++] = fragcode;
1232
1233                 glAttachObjectARB(shader->object, shader->fragment);
1234                 glShaderSourceARB(shader->fragment, num_source, source, NULL);
1235
1236                 glCompileShaderARB(shader->fragment);
1237                 glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status);
1238
1239                 if (!status) {
1240                         glGetInfoLogARB(shader->fragment, sizeof(log), &length, log);
1241                         shader_print_errors("compile", log, fragcode);
1242
1243                         GPU_shader_free(shader);
1244                         return NULL;
1245                 }
1246         }
1247
1248 #if 0
1249         if (lib && lib->lib)
1250                 glAttachObjectARB(shader->object, lib->lib);
1251 #endif
1252
1253         glLinkProgramARB(shader->object);
1254         glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status);
1255         if (!status) {
1256                 glGetInfoLogARB(shader->object, sizeof(log), &length, log);
1257                 if (fragcode) shader_print_errors("linking", log, fragcode);
1258                 else if (vertexcode) shader_print_errors("linking", log, vertexcode);
1259                 else if (libcode) shader_print_errors("linking", log, libcode);
1260
1261                 GPU_shader_free(shader);
1262                 return NULL;
1263         }
1264
1265         return shader;
1266 }
1267
1268 #if 0
1269 GPUShader *GPU_shader_create_lib(const char *code)
1270 {
1271         GLint status;
1272         GLcharARB log[5000];
1273         GLsizei length = 0;
1274         GPUShader *shader;
1275
1276         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
1277                 return NULL;
1278
1279         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
1280
1281         shader->lib = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
1282
1283         if (!shader->lib) {
1284                 fprintf(stderr, "GPUShader, object creation failed.\n");
1285                 GPU_shader_free(shader);
1286                 return NULL;
1287         }
1288
1289         glShaderSourceARB(shader->lib, 1, (const char**)&code, NULL);
1290
1291         glCompileShaderARB(shader->lib);
1292         glGetObjectParameterivARB(shader->lib, GL_OBJECT_COMPILE_STATUS_ARB, &status);
1293
1294         if (!status) {
1295                 glGetInfoLogARB(shader->lib, sizeof(log), &length, log);
1296                 shader_print_errors("compile", log, code);
1297
1298                 GPU_shader_free(shader);
1299                 return NULL;
1300         }
1301
1302         return shader;
1303 }
1304 #endif
1305
1306 void GPU_shader_bind(GPUShader *shader)
1307 {
1308         GPU_print_error("Pre Shader Bind");
1309         glUseProgramObjectARB(shader->object);
1310         GPU_print_error("Post Shader Bind");
1311 }
1312
1313 void GPU_shader_unbind(void)
1314 {
1315         GPU_print_error("Pre Shader Unbind");
1316         glUseProgramObjectARB(0);
1317         GPU_print_error("Post Shader Unbind");
1318 }
1319
1320 void GPU_shader_free(GPUShader *shader)
1321 {
1322         if (shader->lib)
1323                 glDeleteObjectARB(shader->lib);
1324         if (shader->vertex)
1325                 glDeleteObjectARB(shader->vertex);
1326         if (shader->fragment)
1327                 glDeleteObjectARB(shader->fragment);
1328         if (shader->object)
1329                 glDeleteObjectARB(shader->object);
1330         MEM_freeN(shader);
1331 }
1332
1333 int GPU_shader_get_uniform(GPUShader *shader, const char *name)
1334 {
1335         return glGetUniformLocationARB(shader->object, name);
1336 }
1337
1338 void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, float *value)
1339 {
1340         if (location == -1)
1341                 return;
1342
1343         GPU_print_error("Pre Uniform Vector");
1344
1345         if (length == 1) glUniform1fvARB(location, arraysize, value);
1346         else if (length == 2) glUniform2fvARB(location, arraysize, value);
1347         else if (length == 3) glUniform3fvARB(location, arraysize, value);
1348         else if (length == 4) glUniform4fvARB(location, arraysize, value);
1349         else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value);
1350         else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value);
1351
1352         GPU_print_error("Post Uniform Vector");
1353 }
1354
1355 void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
1356 {
1357         if (location == -1)
1358                 return;
1359
1360         GPU_print_error("Pre Uniform Int");
1361         glUniform1iARB(location, value);
1362         GPU_print_error("Post Uniform Int");
1363 }
1364
1365 void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
1366 {
1367         GLenum arbnumber;
1368
1369         if (tex->number >= GG.maxtextures) {
1370                 GPU_print_error("Not enough texture slots.");
1371                 return;
1372         }
1373                 
1374         if (tex->number == -1)
1375                 return;
1376
1377         if (location == -1)
1378                 return;
1379
1380         GPU_print_error("Pre Uniform Texture");
1381
1382         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
1383
1384         if (tex->number != 0) glActiveTextureARB(arbnumber);
1385         glBindTexture(tex->target, tex->bindcode);
1386         glUniform1iARB(location, tex->number);
1387         glEnable(tex->target);
1388         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
1389
1390         GPU_print_error("Post Uniform Texture");
1391 }
1392
1393 int GPU_shader_get_attribute(GPUShader *shader, const char *name)
1394 {
1395         int index;
1396         
1397         GPU_print_error("Pre Get Attribute");
1398
1399         index = glGetAttribLocationARB(shader->object, name);
1400
1401         GPU_print_error("Post Get Attribute");
1402
1403         return index;
1404 }
1405
1406 GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
1407 {
1408         GPUShader *retval = NULL;
1409
1410         switch (shader) {
1411                 case GPU_SHADER_VSM_STORE:
1412                         if (!GG.shaders.vsm_store)
1413                                 GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL);
1414                         retval = GG.shaders.vsm_store;
1415                         break;
1416                 case GPU_SHADER_SEP_GAUSSIAN_BLUR:
1417                         if (!GG.shaders.sep_gaussian_blur)
1418                                 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);
1419                         retval = GG.shaders.sep_gaussian_blur;
1420                         break;
1421         }
1422
1423         if (retval == NULL)
1424                 printf("Unable to create a GPUShader for builtin shader: %d\n", shader);
1425
1426         return retval;
1427 }
1428
1429 void GPU_shader_free_builtin_shaders(void)
1430 {
1431         if (GG.shaders.vsm_store) {
1432                 MEM_freeN(GG.shaders.vsm_store);
1433                 GG.shaders.vsm_store = NULL;
1434         }
1435
1436         if (GG.shaders.sep_gaussian_blur) {
1437                 MEM_freeN(GG.shaders.sep_gaussian_blur);
1438                 GG.shaders.sep_gaussian_blur = NULL;
1439         }
1440 }
1441
1442 #if 0
1443 /* GPUPixelBuffer */
1444
1445 typedef struct GPUPixelBuffer {
1446         GLuint bindcode[2];
1447         GLuint current;
1448         int datasize;
1449         int numbuffers;
1450         int halffloat;
1451 } GPUPixelBuffer;
1452
1453 void GPU_pixelbuffer_free(GPUPixelBuffer *pb)
1454 {
1455         if (pb->bindcode[0])
1456                 glDeleteBuffersARB(pb->numbuffers, pb->bindcode);
1457         MEM_freeN(pb);
1458 }
1459
1460 GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers)
1461 {
1462         GPUPixelBuffer *pb;
1463
1464         if (!GLEW_ARB_multitexture || !GLEW_EXT_pixel_buffer_object)
1465                 return NULL;
1466         
1467         pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
1468         pb->datasize = x*y*4*((halffloat)? 16: 8);
1469         pb->numbuffers = numbuffers;
1470         pb->halffloat = halffloat;
1471
1472         glGenBuffersARB(pb->numbuffers, pb->bindcode);
1473
1474         if (!pb->bindcode[0]) {
1475                 fprintf(stderr, "GPUPixelBuffer allocation failed\n");
1476                 GPU_pixelbuffer_free(pb);
1477                 return NULL;
1478         }
1479
1480         return pb;
1481 }
1482
1483 void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
1484 {
1485         void *pixels;
1486         int i;
1487
1488         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
1489
1490         for (i = 0; i < pb->numbuffers; i++) {
1491                 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->bindcode[pb->current]);
1492                 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->datasize, NULL,
1493                 GL_STREAM_DRAW_ARB);
1494
1495                 pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
1496                 /*memcpy(pixels, _oImage.data(), pb->datasize);*/
1497
1498                 if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
1499                         fprintf(stderr, "Could not unmap opengl PBO\n");
1500                         break;
1501                 }
1502         }
1503
1504         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
1505 }
1506
1507 static int pixelbuffer_map_into_gpu(GLuint bindcode)
1508 {
1509         void *pixels;
1510
1511         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
1512         pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
1513
1514         /* do stuff in pixels */
1515
1516         if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
1517                 fprintf(stderr, "Could not unmap opengl PBO\n");
1518                 return 0;
1519         }
1520         
1521         return 1;
1522 }
1523
1524 static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode)
1525 {
1526         GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE;
1527         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
1528         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
1529
1530         glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h,
1531                                         GL_RGBA, type, NULL);
1532
1533         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
1534         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
1535 }
1536
1537 void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
1538 {
1539         int newbuffer;
1540
1541         if (pb->numbuffers == 1) {
1542                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]);
1543                 pixelbuffer_map_into_gpu(pb->bindcode[0]);
1544         }
1545         else {
1546                 pb->current = (pb->current+1)%pb->numbuffers;
1547                 newbuffer = (pb->current+1)%pb->numbuffers;
1548
1549                 pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
1550                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
1551         }
1552 }
1553 #endif
1554