Added -d debug option for blenderplayer, and remove some
[blender.git] / source / blender / gpu / intern / gpu_extensions.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2005 Blender Foundation.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): Brecht Van Lommel.
29  *
30  * ***** END GPL LICENSE BLOCK *****
31  */
32
33 #include "GL/glew.h"
34
35 #include "DNA_listBase.h"
36 #include "DNA_image_types.h"
37 #include "DNA_userdef_types.h"
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BKE_image.h"
42 #include "BKE_global.h"
43
44 #include "IMB_imbuf.h"
45 #include "IMB_imbuf_types.h"
46
47 #include "BLI_blenlib.h"
48
49 #include "GPU_draw.h"
50 #include "GPU_extensions.h"
51
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <string.h>
55
56 /* Extensions support */
57
58 /* extensions used:
59         - texture border clamp: 1.3 core
60         - fragement shader: 2.0 core
61         - framebuffer object: ext specification
62         - multitexture 1.3 core
63         - arb non power of two: 2.0 core
64         - pixel buffer objects? 2.1 core
65         - arb draw buffers? 2.0 core
66 */
67
68 struct GPUGlobal {
69         GLint maxtextures;
70         GLuint currentfb;
71         int minimumsupport;
72 } GG = {1, 0, 0};
73
74 void GPU_extensions_init()
75 {
76         glewInit();
77
78         /* glewIsSupported("GL_VERSION_2_0") */
79
80         if (GLEW_ARB_multitexture)
81                 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &GG.maxtextures);
82
83         GG.minimumsupport = 1;
84         if (!GLEW_ARB_multitexture) GG.minimumsupport = 0;
85         if (!GLEW_ARB_vertex_shader) GG.minimumsupport = 0;
86         if (!GLEW_ARB_fragment_shader) GG.minimumsupport = 0;
87 }
88
89 int GPU_extensions_minimum_support()
90 {
91         return GG.minimumsupport;
92 }
93
94 int GPU_print_error(char *str)
95 {
96         GLenum errCode;
97
98         if (G.f & G_DEBUG) {
99                 if ((errCode = glGetError()) != GL_NO_ERROR) {
100             fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode));
101                         return 1;
102                 }
103         }
104
105         return 0;
106 }
107
108 static void GPU_print_framebuffer_error(GLenum status)
109 {
110         fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d\n",
111                 (int)status);
112
113         switch(status) {
114                 case GL_FRAMEBUFFER_COMPLETE_EXT:
115                         break;
116                 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
117                         fprintf(stderr, "Incomplete attachment.\n");
118                         break;
119                 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
120                         fprintf(stderr, "Unsupported framebuffer format.\n");
121                         break;
122                 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
123                         fprintf(stderr, "Missing attachment.\n");
124                         break;
125                 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
126                         fprintf(stderr, "Attached images must have same dimensions.\n");
127                         break;
128                 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
129                          fprintf(stderr, "Attached images must have same format.\n");
130                         break;
131                 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
132                         fprintf(stderr, "Missing draw buffer.\n");
133                         break;
134                 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
135                         fprintf(stderr, "Missing read buffer.\n");
136                         break;
137                 default:
138                         fprintf(stderr, "Unknown.\n");
139                         break;
140         }
141 }
142
143 /* GPUTexture */
144
145 struct GPUTexture {
146         int w, h;                               /* width/height */
147         int number;                             /* number for multitexture binding */
148         int refcount;                   /* reference count */
149         GLenum target;                  /* GL_TEXTURE_* */
150         GLuint bindcode;                /* opengl identifier for texture */
151         int fromblender;                /* we got the texture from Blender */
152
153         GPUFrameBuffer *fb;             /* GPUFramebuffer this texture is attached to */
154         int depth;                              /* is a depth texture? */
155 };
156
157 #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
158 static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels)
159 {
160         unsigned char *pixels, *p;
161         float *fp;
162         int a, len;
163
164         len = 4*length;
165         fp = fpixels;
166         p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels");
167
168         for (a=0; a<len; a++, p++, fp++)
169                 *p = FTOCHAR((*fp));
170
171         return pixels;
172 }
173
174 static int is_pow2(int n)
175 {
176         return ((n)&(n-1))==0;
177 }
178
179 static int larger_pow2(int n)
180 {
181         if (is_pow2(n))
182                 return n;
183
184         while(!is_pow2(n))
185                 n= n&(n-1);
186
187         return n*2;
188 }
189
190 static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
191 {
192         void *pixels = MEM_callocN(sizeof(char)*4*w*h, "GPUTextureEmptyPixels");
193
194         if (target == GL_TEXTURE_1D)
195                 glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
196         else
197                 glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
198         
199         MEM_freeN(pixels);
200 }
201
202 static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth)
203 {
204         GPUTexture *tex;
205         GLenum type, format, internalformat;
206         void *pixels = NULL;
207
208         if(depth && !GLEW_ARB_depth_texture)
209                 return NULL;
210
211         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
212         tex->w = w;
213         tex->h = h;
214         tex->number = -1;
215         tex->refcount = 1;
216         tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
217         tex->depth = depth;
218
219         glGenTextures(1, &tex->bindcode);
220
221         if (!tex->bindcode) {
222                 fprintf(stderr, "GPUTexture: texture create failed: %d\n",
223                         (int)glGetError());
224                 GPU_texture_free(tex);
225                 return NULL;
226         }
227
228         if (!GLEW_ARB_texture_non_power_of_two) {
229                 tex->w = larger_pow2(tex->w);
230                 tex->h = larger_pow2(tex->h);
231         }
232
233         tex->number = 0;
234         glBindTexture(tex->target, tex->bindcode);
235
236         if(depth) {
237                 type = GL_UNSIGNED_BYTE;
238                 format = GL_DEPTH_COMPONENT;
239                 internalformat = GL_DEPTH_COMPONENT;
240         }
241         else {
242                 type = GL_UNSIGNED_BYTE;
243                 format = GL_RGBA;
244                 internalformat = GL_RGBA8;
245
246                 if (fpixels)
247                         pixels = GPU_texture_convert_pixels(w*h, fpixels);
248         }
249
250         if (tex->target == GL_TEXTURE_1D) {
251                 glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, 0);
252
253                 if (fpixels) {
254                         glTexSubImage1D(tex->target, 0, 0, w, format, type,
255                                 pixels? pixels: fpixels);
256
257                         if (tex->w > w)
258                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0,
259                                         tex->w-w, 1);
260                 }
261         }
262         else {
263                 glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
264                         format, type, 0);
265
266                 if (fpixels) {
267                         glTexSubImage2D(tex->target, 0, 0, 0, w, h,
268                                 format, type, pixels? pixels: fpixels);
269
270                         if (tex->w > w)
271                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h);
272                         if (tex->h > h)
273                                 GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h);
274                 }
275         }
276
277         if (pixels)
278                 MEM_freeN(pixels);
279
280         if(depth) {
281                 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
282                 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
283                 glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
284                 glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
285                 glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);  
286         }
287         else {
288                 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
289                 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
290         }
291
292         if (tex->target != GL_TEXTURE_1D) {
293                 /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
294                 GLenum wrapmode = (depth)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
295                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
296                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
297
298 #if 0
299                 float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
300                 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); 
301 #endif
302         }
303         else
304                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
305
306         return tex;
307 }
308
309 GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, double time)
310 {
311         GPUTexture *tex;
312         GLint w, h, border, lastbindcode, bindcode;
313
314         glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
315
316         GPU_update_image_time(ima, time);
317         bindcode = GPU_verify_image(ima, 0, 0, 0);
318
319         if(ima->gputexture) {
320                 ima->gputexture->bindcode = bindcode;
321                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
322                 return ima->gputexture;
323         }
324
325         if(!bindcode) {
326                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
327                 return NULL;
328         }
329
330         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
331         tex->bindcode = bindcode;
332         tex->number = -1;
333         tex->refcount = 1;
334         tex->target = GL_TEXTURE_2D;
335         tex->fromblender = 1;
336
337         ima->gputexture= tex;
338
339         if (!glIsTexture(tex->bindcode)) {
340                 GPU_print_error("Blender Texture");
341         }
342         else {
343                 glBindTexture(GL_TEXTURE_2D, tex->bindcode);
344                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
345                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
346                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
347
348                 tex->w = w - border;
349                 tex->h = h - border;
350         }
351
352         glBindTexture(GL_TEXTURE_2D, lastbindcode);
353
354         return tex;
355 }
356
357 GPUTexture *GPU_texture_create_1D(int w, float *fpixels)
358 {
359         GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0);
360
361         if (tex)
362                 GPU_texture_unbind(tex);
363         
364         return tex;
365 }
366
367 GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels)
368 {
369         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0);
370
371         if (tex)
372                 GPU_texture_unbind(tex);
373         
374         return tex;
375 }
376
377 GPUTexture *GPU_texture_create_depth(int w, int h)
378 {
379         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1);
380
381         if (tex)
382                 GPU_texture_unbind(tex);
383         
384         return tex;
385 }
386
387 void GPU_texture_bind(GPUTexture *tex, int number)
388 {
389         GLenum arbnumber;
390
391         if (number >= GG.maxtextures) {
392                 GPU_print_error("Not enough texture slots.");
393                 return;
394         }
395
396         if(number == -1)
397                 return;
398
399         GPU_print_error("Pre Texture Bind");
400
401         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number);
402         if (number != 0) glActiveTextureARB(arbnumber);
403         glBindTexture(tex->target, tex->bindcode);
404         glEnable(tex->target);
405         if (number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
406
407         tex->number = number;
408
409         GPU_print_error("Post Texture Bind");
410 }
411
412 void GPU_texture_unbind(GPUTexture *tex)
413 {
414         GLenum arbnumber;
415
416         if (tex->number >= GG.maxtextures) {
417                 GPU_print_error("Not enough texture slots.");
418                 return;
419         }
420
421         if(tex->number == -1)
422                 return;
423         
424         GPU_print_error("Pre Texture Unbind");
425
426         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
427         if (tex->number != 0) glActiveTextureARB(arbnumber);
428         glBindTexture(tex->target, 0);
429         glDisable(tex->target);
430         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
431
432         tex->number = -1;
433
434         GPU_print_error("Post Texture Unbind");
435 }
436
437 void GPU_texture_free(GPUTexture *tex)
438 {
439         tex->refcount--;
440
441         if (tex->refcount < 0)
442                 fprintf(stderr, "GPUTexture: negative refcount\n");
443         
444         if (tex->refcount == 0) {
445                 if (tex->fb)
446                         GPU_framebuffer_texture_detach(tex->fb, tex);
447                 if (tex->bindcode && !tex->fromblender)
448                         glDeleteTextures(1, &tex->bindcode);
449
450                 MEM_freeN(tex);
451         }
452 }
453
454 void GPU_texture_ref(GPUTexture *tex)
455 {
456         tex->refcount++;
457 }
458
459 int GPU_texture_target(GPUTexture *tex)
460 {
461         return tex->target;
462 }
463
464 int GPU_texture_opengl_width(GPUTexture *tex)
465 {
466         return tex->w;
467 }
468
469 int GPU_texture_opengl_height(GPUTexture *tex)
470 {
471         return tex->h;
472 }
473
474 GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
475 {
476         return tex->fb;
477 }
478
479 /* GPUFrameBuffer */
480
481 struct GPUFrameBuffer {
482         GLuint object;
483         GPUTexture *colortex;
484         GPUTexture *depthtex;
485 };
486
487 GPUFrameBuffer *GPU_framebuffer_create()
488 {
489         GPUFrameBuffer *fb;
490
491         if (!GLEW_EXT_framebuffer_object)
492                 return NULL;
493         
494         fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
495         glGenFramebuffersEXT(1, &fb->object);
496
497         if (!fb->object) {
498                 fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
499                         (int)glGetError());
500                 GPU_framebuffer_free(fb);
501                 return NULL;
502         }
503
504         return fb;
505 }
506
507 int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex)
508 {
509         GLenum status;
510         GLenum attachment;
511
512         if(tex->depth)
513                 attachment = GL_DEPTH_ATTACHMENT_EXT;
514         else
515                 attachment = GL_COLOR_ATTACHMENT0_EXT;
516
517         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
518         GG.currentfb = fb->object;
519
520         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 
521                 tex->target, tex->bindcode, 0);
522
523         if(tex->depth) {
524                 glDrawBuffer(GL_NONE);
525                 glReadBuffer(GL_NONE);
526         }
527         else {
528                 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
529                 glReadBuffer(GL_NONE);
530         }
531
532         status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
533
534         if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
535                 GPU_framebuffer_restore();
536                 GPU_print_framebuffer_error(status);
537                 return 0;
538         }
539
540         if(tex->depth)
541                 fb->depthtex = tex;
542         else
543                 fb->colortex = tex;
544
545         tex->fb= fb;
546
547         return 1;
548 }
549
550 void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
551 {
552         GLenum attachment;
553
554         if(!tex->fb)
555                 return;
556
557         if(GG.currentfb != tex->fb->object) {
558                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
559                 GG.currentfb = tex->fb->object;
560         }
561
562         if(tex->depth) {
563                 fb->depthtex = NULL;
564                 attachment = GL_DEPTH_ATTACHMENT_EXT;
565         }
566         else {
567                 fb->colortex = NULL;
568                 attachment = GL_COLOR_ATTACHMENT0_EXT;
569         }
570
571         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
572                 tex->target, 0, 0);
573
574         tex->fb = NULL;
575 }
576
577 void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex)
578 {
579         /* push attributes */
580         glPushAttrib(GL_ENABLE_BIT);
581         glPushAttrib(GL_VIEWPORT_BIT);
582         glDisable(GL_SCISSOR_TEST);
583
584         /* bind framebuffer */
585         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
586
587         /* push matrices and set default viewport and matrix */
588         glViewport(0, 0, tex->w, tex->h);
589         GG.currentfb = tex->fb->object;
590
591         glMatrixMode(GL_PROJECTION);
592         glPushMatrix();
593         glLoadIdentity();
594         glMatrixMode(GL_MODELVIEW);
595         glPushMatrix();
596         glLoadIdentity();
597 }
598
599 void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex)
600 {
601         /* restore matrix */
602         glMatrixMode(GL_PROJECTION);
603         glPopMatrix();
604         glMatrixMode(GL_MODELVIEW);
605         glPopMatrix();
606
607         /* restore attributes */
608         glPopAttrib();
609         glPopAttrib();
610         glEnable(GL_SCISSOR_TEST);
611 }
612
613 void GPU_framebuffer_free(GPUFrameBuffer *fb)
614 {
615         if(fb->depthtex)
616                 GPU_framebuffer_texture_detach(fb, fb->depthtex);
617         if(fb->colortex)
618                 GPU_framebuffer_texture_detach(fb, fb->colortex);
619
620         if(fb->object) {
621                 glDeleteFramebuffersEXT(1, &fb->object);
622
623                 if (GG.currentfb == fb->object) {
624                         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
625                         GG.currentfb = 0;
626                 }
627         }
628
629         MEM_freeN(fb);
630 }
631
632 void GPU_framebuffer_restore()
633 {
634         if (GG.currentfb != 0) {
635                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
636                 GG.currentfb = 0;
637         }
638 }
639
640 /* GPUShader */
641
642 struct GPUShader {
643         GLhandleARB object;             /* handle for full shader */
644         GLhandleARB vertex;             /* handle for vertex shader */
645         GLhandleARB fragment;   /* handle for fragment shader */
646         GLhandleARB lib;                /* handle for libment shader */
647         int totattrib;                  /* total number of attributes */
648 };
649
650 static void shader_print_errors(char *task, char *log, const char *code)
651 {
652         const char *c, *pos, *end = code + strlen(code);
653         int line = 1;
654
655         fprintf(stderr, "GPUShader: %s error:\n", task);
656
657         if(G.f & G_DEBUG) {
658                 c = code;
659                 while ((c < end) && (pos = strchr(c, '\n'))) {
660                         fprintf(stderr, "%2d  ", line);
661                         fwrite(c, (pos+1)-c, 1, stderr);
662                         c = pos+1;
663                         line++;
664                 }
665
666                 fprintf(stderr, "%s", c);
667         }
668
669         fprintf(stderr, "%s\n", log);
670 }
671
672 GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUShader *lib)
673 {
674         GLint status;
675         GLcharARB log[5000];
676         GLsizei length = 0;
677         GPUShader *shader;
678
679         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
680                 return NULL;
681
682         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
683
684         if(vertexcode)
685                 shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
686         if(fragcode)
687                 shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
688         shader->object = glCreateProgramObjectARB();
689
690         if (!shader->object ||
691                 (vertexcode && !shader->vertex) ||
692                 (fragcode && !shader->fragment)) {
693                 fprintf(stderr, "GPUShader, object creation failed.\n");
694                 GPU_shader_free(shader);
695                 return NULL;
696         }
697
698         if(lib && lib->lib)
699                 glAttachObjectARB(shader->object, lib->lib);
700
701         if(vertexcode) {
702                 glAttachObjectARB(shader->object, shader->vertex);
703                 glShaderSourceARB(shader->vertex, 1, (const char**)&vertexcode, NULL);
704
705                 glCompileShaderARB(shader->vertex);
706                 glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status);
707
708                 if (!status) {
709                         glGetInfoLogARB(shader->vertex, sizeof(log), &length, log);
710                         shader_print_errors("compile", log, vertexcode);
711
712                         GPU_shader_free(shader);
713                         return NULL;
714                 }
715         }
716
717         if(fragcode) {
718                 glAttachObjectARB(shader->object, shader->fragment);
719                 glShaderSourceARB(shader->fragment, 1, (const char**)&fragcode, NULL);
720
721                 glCompileShaderARB(shader->fragment);
722                 glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status);
723
724                 if (!status) {
725                         glGetInfoLogARB(shader->fragment, sizeof(log), &length, log);
726                         shader_print_errors("compile", log, fragcode);
727
728                         GPU_shader_free(shader);
729                         return NULL;
730                 }
731         }
732
733         glLinkProgramARB(shader->object);
734         glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status);
735         if (!status) {
736                 glGetInfoLogARB(shader->object, sizeof(log), &length, log);
737                 shader_print_errors("linking", log, fragcode);
738
739                 GPU_shader_free(shader);
740                 return NULL;
741         }
742
743         return shader;
744 }
745
746 GPUShader *GPU_shader_create_lib(const char *code)
747 {
748         GLint status;
749         GLcharARB log[5000];
750         GLsizei length = 0;
751         GPUShader *shader;
752
753         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
754                 return NULL;
755
756         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
757
758         shader->lib = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
759
760         if (!shader->lib) {
761                 fprintf(stderr, "GPUShader, object creation failed.\n");
762                 GPU_shader_free(shader);
763                 return NULL;
764         }
765
766         glShaderSourceARB(shader->lib, 1, (const char**)&code, NULL);
767
768         glCompileShaderARB(shader->lib);
769         glGetObjectParameterivARB(shader->lib, GL_OBJECT_COMPILE_STATUS_ARB, &status);
770
771         if (!status) {
772                 glGetInfoLogARB(shader->lib, sizeof(log), &length, log);
773                 shader_print_errors("compile", log, code);
774
775                 GPU_shader_free(shader);
776                 return NULL;
777         }
778
779         return shader;
780 }
781
782 void GPU_shader_bind(GPUShader *shader)
783 {
784         GPU_print_error("Pre Shader Bind");
785         glUseProgramObjectARB(shader->object);
786         GPU_print_error("Post Shader Bind");
787 }
788
789 void GPU_shader_unbind()
790 {
791         GPU_print_error("Pre Shader Unbind");
792         glUseProgramObjectARB(0);
793         GPU_print_error("Post Shader Unbind");
794 }
795
796 void GPU_shader_free(GPUShader *shader)
797 {
798         if (shader->lib)
799                 glDeleteObjectARB(shader->lib);
800         if (shader->vertex)
801                 glDeleteObjectARB(shader->vertex);
802         if (shader->fragment)
803                 glDeleteObjectARB(shader->fragment);
804         if (shader->object)
805                 glDeleteObjectARB(shader->object);
806         MEM_freeN(shader);
807 }
808
809 int GPU_shader_get_uniform(GPUShader *shader, char *name)
810 {
811         return glGetUniformLocationARB(shader->object, name);
812 }
813
814 void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, float *value)
815 {
816         if(location == -1)
817                 return;
818
819         GPU_print_error("Pre Uniform Vector");
820
821         if (length == 1) glUniform1fvARB(location, arraysize, value);
822         else if (length == 2) glUniform2fvARB(location, arraysize, value);
823         else if (length == 3) glUniform3fvARB(location, arraysize, value);
824         else if (length == 4) glUniform4fvARB(location, arraysize, value);
825         else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value);
826         else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value);
827
828         GPU_print_error("Post Uniform Vector");
829 }
830
831 void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex)
832 {
833         GLenum arbnumber;
834
835         if (tex->number >= GG.maxtextures) {
836                 GPU_print_error("Not enough texture slots.");
837                 return;
838         }
839                 
840         if(tex->number == -1)
841                 return;
842
843         if(location == -1)
844                 return;
845
846         GPU_print_error("Pre Uniform Texture");
847
848         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
849
850         if (tex->number != 0) glActiveTextureARB(arbnumber);
851         glBindTexture(tex->target, tex->bindcode);
852         glUniform1iARB(location, tex->number);
853         glEnable(tex->target);
854         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
855
856         GPU_print_error("Post Uniform Texture");
857 }
858
859 int GPU_shader_get_attribute(GPUShader *shader, char *name)
860 {
861         int index;
862         
863         GPU_print_error("Pre Get Attribute");
864
865         index = glGetAttribLocationARB(shader->object, name);
866
867         GPU_print_error("Post Get Attribute");
868
869         return index;
870 }
871
872 #if 0
873 /* GPUPixelBuffer */
874
875 typedef struct GPUPixelBuffer {
876         GLuint bindcode[2];
877         GLuint current;
878         int datasize;
879         int numbuffers;
880         int halffloat;
881 } GPUPixelBuffer;
882
883 void GPU_pixelbuffer_free(GPUPixelBuffer *pb)
884 {
885         if (pb->bindcode[0])
886                 glDeleteBuffersARB(pb->numbuffers, pb->bindcode);
887         MEM_freeN(pb);
888 }
889
890 GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers)
891 {
892         GPUPixelBuffer *pb;
893
894         if (!GLEW_ARB_multitexture || !GLEW_EXT_pixel_buffer_object)
895                 return NULL;
896         
897         pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
898         pb->datasize = x*y*4*((halffloat)? 16: 8);
899         pb->numbuffers = numbuffers;
900         pb->halffloat = halffloat;
901
902         glGenBuffersARB(pb->numbuffers, pb->bindcode);
903
904         if (!pb->bindcode[0]) {
905                 fprintf(stderr, "GPUPixelBuffer allocation failed\n");
906                 GPU_pixelbuffer_free(pb);
907                 return NULL;
908         }
909
910         return pb;
911 }
912
913 void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
914 {
915         void *pixels;
916         int i;
917
918     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
919  
920         for (i = 0; i < pb->numbuffers; i++) {
921                 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->bindcode[pb->current]);
922                 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->datasize, NULL,
923                         GL_STREAM_DRAW_ARB);
924     
925                 pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
926                 /*memcpy(pixels, _oImage.data(), pb->datasize);*/
927     
928                 if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
929                         fprintf(stderr, "Could not unmap opengl PBO\n");
930                         break;
931                 }
932         }
933
934     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
935 }
936
937 static int pixelbuffer_map_into_gpu(GLuint bindcode)
938 {
939         void *pixels;
940
941     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
942         pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
943
944         /* do stuff in pixels */
945
946     if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
947                 fprintf(stderr, "Could not unmap opengl PBO\n");
948                 return 0;
949     }
950         
951         return 1;
952 }
953
954 static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode)
955 {
956         GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE;
957     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
958     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
959
960     glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h,
961                     GL_RGBA, type, NULL);
962
963         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
964     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
965 }
966
967 void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
968 {
969         int newbuffer;
970
971         if (pb->numbuffers == 1) {
972                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]);
973                 pixelbuffer_map_into_gpu(pb->bindcode[0]);
974         }
975         else {
976                 pb->current = (pb->current+1)%pb->numbuffers;
977                 newbuffer = (pb->current+1)%pb->numbuffers;
978
979                 pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
980                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
981     }
982 }
983 #endif
984