Fix again for the NVidia driver bug. This time I'm just giving up
[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,*/ const char *libcode)
673 {
674         GLint status;
675         GLcharARB log[5000];
676         const char *fragsource[2];
677         GLsizei length = 0;
678         GLint count;
679         GPUShader *shader;
680
681         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
682                 return NULL;
683
684         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
685
686         if(vertexcode)
687                 shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
688         if(fragcode)
689                 shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
690         shader->object = glCreateProgramObjectARB();
691
692         if (!shader->object ||
693                 (vertexcode && !shader->vertex) ||
694                 (fragcode && !shader->fragment)) {
695                 fprintf(stderr, "GPUShader, object creation failed.\n");
696                 GPU_shader_free(shader);
697                 return NULL;
698         }
699
700         if(vertexcode) {
701                 glAttachObjectARB(shader->object, shader->vertex);
702                 glShaderSourceARB(shader->vertex, 1, (const char**)&vertexcode, NULL);
703
704                 glCompileShaderARB(shader->vertex);
705                 glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status);
706
707                 if (!status) {
708                         glGetInfoLogARB(shader->vertex, sizeof(log), &length, log);
709                         shader_print_errors("compile", log, vertexcode);
710
711                         GPU_shader_free(shader);
712                         return NULL;
713                 }
714         }
715
716         if(fragcode) {
717                 count = 0;
718                 if(libcode) fragsource[count++] = libcode;
719                 if(fragcode) fragsource[count++] = fragcode;
720
721                 glAttachObjectARB(shader->object, shader->fragment);
722                 glShaderSourceARB(shader->fragment, count, fragsource, NULL);
723
724                 glCompileShaderARB(shader->fragment);
725                 glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status);
726
727                 if (!status) {
728                         glGetInfoLogARB(shader->fragment, sizeof(log), &length, log);
729                         shader_print_errors("compile", log, fragcode);
730
731                         GPU_shader_free(shader);
732                         return NULL;
733                 }
734         }
735
736         /*if(lib && lib->lib)
737                 glAttachObjectARB(shader->object, lib->lib);*/
738
739         glLinkProgramARB(shader->object);
740         glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status);
741         if (!status) {
742                 glGetInfoLogARB(shader->object, sizeof(log), &length, log);
743                 shader_print_errors("linking", log, fragcode);
744
745                 GPU_shader_free(shader);
746                 return NULL;
747         }
748
749         return shader;
750 }
751
752 #if 0
753 GPUShader *GPU_shader_create_lib(const char *code)
754 {
755         GLint status;
756         GLcharARB log[5000];
757         GLsizei length = 0;
758         GPUShader *shader;
759
760         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
761                 return NULL;
762
763         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
764
765         shader->lib = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
766
767         if (!shader->lib) {
768                 fprintf(stderr, "GPUShader, object creation failed.\n");
769                 GPU_shader_free(shader);
770                 return NULL;
771         }
772
773         glShaderSourceARB(shader->lib, 1, (const char**)&code, NULL);
774
775         glCompileShaderARB(shader->lib);
776         glGetObjectParameterivARB(shader->lib, GL_OBJECT_COMPILE_STATUS_ARB, &status);
777
778         if (!status) {
779                 glGetInfoLogARB(shader->lib, sizeof(log), &length, log);
780                 shader_print_errors("compile", log, code);
781
782                 GPU_shader_free(shader);
783                 return NULL;
784         }
785
786         return shader;
787 }
788 #endif
789
790 void GPU_shader_bind(GPUShader *shader)
791 {
792         GPU_print_error("Pre Shader Bind");
793         glUseProgramObjectARB(shader->object);
794         GPU_print_error("Post Shader Bind");
795 }
796
797 void GPU_shader_unbind()
798 {
799         GPU_print_error("Pre Shader Unbind");
800         glUseProgramObjectARB(0);
801         GPU_print_error("Post Shader Unbind");
802 }
803
804 void GPU_shader_free(GPUShader *shader)
805 {
806         if (shader->lib)
807                 glDeleteObjectARB(shader->lib);
808         if (shader->vertex)
809                 glDeleteObjectARB(shader->vertex);
810         if (shader->fragment)
811                 glDeleteObjectARB(shader->fragment);
812         if (shader->object)
813                 glDeleteObjectARB(shader->object);
814         MEM_freeN(shader);
815 }
816
817 int GPU_shader_get_uniform(GPUShader *shader, char *name)
818 {
819         return glGetUniformLocationARB(shader->object, name);
820 }
821
822 void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, float *value)
823 {
824         if(location == -1)
825                 return;
826
827         GPU_print_error("Pre Uniform Vector");
828
829         if (length == 1) glUniform1fvARB(location, arraysize, value);
830         else if (length == 2) glUniform2fvARB(location, arraysize, value);
831         else if (length == 3) glUniform3fvARB(location, arraysize, value);
832         else if (length == 4) glUniform4fvARB(location, arraysize, value);
833         else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value);
834         else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value);
835
836         GPU_print_error("Post Uniform Vector");
837 }
838
839 void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex)
840 {
841         GLenum arbnumber;
842
843         if (tex->number >= GG.maxtextures) {
844                 GPU_print_error("Not enough texture slots.");
845                 return;
846         }
847                 
848         if(tex->number == -1)
849                 return;
850
851         if(location == -1)
852                 return;
853
854         GPU_print_error("Pre Uniform Texture");
855
856         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
857
858         if (tex->number != 0) glActiveTextureARB(arbnumber);
859         glBindTexture(tex->target, tex->bindcode);
860         glUniform1iARB(location, tex->number);
861         glEnable(tex->target);
862         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
863
864         GPU_print_error("Post Uniform Texture");
865 }
866
867 int GPU_shader_get_attribute(GPUShader *shader, char *name)
868 {
869         int index;
870         
871         GPU_print_error("Pre Get Attribute");
872
873         index = glGetAttribLocationARB(shader->object, name);
874
875         GPU_print_error("Post Get Attribute");
876
877         return index;
878 }
879
880 #if 0
881 /* GPUPixelBuffer */
882
883 typedef struct GPUPixelBuffer {
884         GLuint bindcode[2];
885         GLuint current;
886         int datasize;
887         int numbuffers;
888         int halffloat;
889 } GPUPixelBuffer;
890
891 void GPU_pixelbuffer_free(GPUPixelBuffer *pb)
892 {
893         if (pb->bindcode[0])
894                 glDeleteBuffersARB(pb->numbuffers, pb->bindcode);
895         MEM_freeN(pb);
896 }
897
898 GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers)
899 {
900         GPUPixelBuffer *pb;
901
902         if (!GLEW_ARB_multitexture || !GLEW_EXT_pixel_buffer_object)
903                 return NULL;
904         
905         pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
906         pb->datasize = x*y*4*((halffloat)? 16: 8);
907         pb->numbuffers = numbuffers;
908         pb->halffloat = halffloat;
909
910         glGenBuffersARB(pb->numbuffers, pb->bindcode);
911
912         if (!pb->bindcode[0]) {
913                 fprintf(stderr, "GPUPixelBuffer allocation failed\n");
914                 GPU_pixelbuffer_free(pb);
915                 return NULL;
916         }
917
918         return pb;
919 }
920
921 void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
922 {
923         void *pixels;
924         int i;
925
926     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
927  
928         for (i = 0; i < pb->numbuffers; i++) {
929                 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->bindcode[pb->current]);
930                 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->datasize, NULL,
931                         GL_STREAM_DRAW_ARB);
932     
933                 pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
934                 /*memcpy(pixels, _oImage.data(), pb->datasize);*/
935     
936                 if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
937                         fprintf(stderr, "Could not unmap opengl PBO\n");
938                         break;
939                 }
940         }
941
942     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
943 }
944
945 static int pixelbuffer_map_into_gpu(GLuint bindcode)
946 {
947         void *pixels;
948
949     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
950         pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
951
952         /* do stuff in pixels */
953
954     if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
955                 fprintf(stderr, "Could not unmap opengl PBO\n");
956                 return 0;
957     }
958         
959         return 1;
960 }
961
962 static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode)
963 {
964         GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE;
965     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
966     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
967
968     glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h,
969                     GL_RGBA, type, NULL);
970
971         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
972     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
973 }
974
975 void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
976 {
977         int newbuffer;
978
979         if (pb->numbuffers == 1) {
980                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]);
981                 pixelbuffer_map_into_gpu(pb->bindcode[0]);
982         }
983         else {
984                 pb->current = (pb->current+1)%pb->numbuffers;
985                 newbuffer = (pb->current+1)%pb->numbuffers;
986
987                 pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
988                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
989     }
990 }
991 #endif
992