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