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