ddb7aa4cf8fa27146b643ea5a0994f826e122141
[blender-staging.git] / source / blender / gpu / intern / gpu_extensions.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_extensions.c
29  *  \ingroup gpu
30  *
31  * Wrap OpenGL features such as textures, shaders and GLSL
32  * with checks for drivers and GPU support.
33  */
34
35
36 #include "DNA_image_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_utildefines.h"
42 #include "BLI_math_base.h"
43 #include "BLI_math_vector.h"
44
45 #include "BKE_global.h"
46
47 #include "GPU_glew.h"
48 #include "GPU_debug.h"
49 #include "GPU_draw.h"
50 #include "GPU_extensions.h"
51 #include "GPU_compositing.h"
52 #include "GPU_simple_shader.h"
53
54 #include "intern/gpu_private.h"
55
56 #include <stdlib.h>
57 #include <stdio.h>
58 #include <string.h>
59
60 #ifdef WIN32
61 #  include "BLI_winstuff.h"
62 #endif
63
64 /* TODO(sergey): Find better default values for this constants. */
65 #define MAX_DEFINE_LENGTH 1024
66 #define MAX_EXT_DEFINE_LENGTH 1024
67
68 /* Extensions support */
69
70 /* -- extension: version of GL that absorbs it
71  * ARB_fragment_program: 2.0
72  * ARB_framebuffer object: 3.0
73  * EXT_framebuffer_multisample: 3.0
74  * EXT_framebuffer_blit: 3.0
75  * EXT_framebuffer_multisample_blit_scaled: ???
76  * ARB_draw_instanced: 3.1
77  * ARB_texture_multisample: 3.2
78  * EXT_geometry_shader4: 3.2
79  * ARB_texture_query_lod: 4.0
80  */
81
82 /* Non-generated shaders */
83 extern char datatoc_gpu_program_smoke_frag_glsl[];
84 extern char datatoc_gpu_program_smoke_color_frag_glsl[];
85 extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
86 extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
87 extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
88 extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
89 extern char datatoc_gpu_shader_fx_vert_glsl[];
90 extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
91 extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
92 extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
93 extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
94 extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
95 extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
96 extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
97 extern char datatoc_gpu_shader_fx_lib_glsl[];
98
99 typedef struct GPUShaders {
100         GPUShader *vsm_store;
101         GPUShader *sep_gaussian_blur;
102         GPUProgram *smoke;
103         GPUProgram *smoke_colored;
104         /* cache for shader fx. Those can exist in combinations so store them here */
105         GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
106 } GPUShaders;
107
108 static struct GPUGlobal {
109         GLint maxtexsize;
110         GLint maxtextures;
111         GLuint currentfb;
112         bool extdisabled;
113         int colordepth;
114         int samples_color_texture_max;
115         GPUDeviceType device;
116         GPUOSType os;
117         GPUDriverType driver;
118         GPUShaders shaders;
119         GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
120         GPUTexture *invalid_tex_2D;
121         GPUTexture *invalid_tex_3D;
122         float dfdyfactors[2]; /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
123                                  calculate dfdy in shader differently when drawing to an offscreen buffer. First
124                                  number is factor on screen and second is off-screen */
125 } GG = {1, 0};
126
127 /* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
128 #define GPU_FB_MAX_SLOTS 4
129
130 struct GPUFrameBuffer {
131         GLuint object;
132         GPUTexture *colortex[GPU_FB_MAX_SLOTS];
133         GPUTexture *depthtex;
134 };
135
136
137 /* GPU Types */
138
139 bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
140 {
141         return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
142 }
143
144 /* GPU Extensions */
145
146 void GPU_extensions_disable(void)
147 {
148         GG.extdisabled = true;
149 }
150
151 int GPU_max_texture_size(void)
152 {
153         return GG.maxtexsize;
154 }
155
156 void GPU_get_dfdy_factors(float fac[2])
157 {
158         copy_v2_v2(fac, GG.dfdyfactors);
159 }
160
161 void gpu_extensions_init(void)
162 {
163         /* BLI_assert(GLEW_VERSION_2_1); */
164         /* ^-- maybe a bit extreme? */
165
166         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
167
168         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
169
170         GLint r, g, b;
171         glGetIntegerv(GL_RED_BITS, &r);
172         glGetIntegerv(GL_GREEN_BITS, &g);
173         glGetIntegerv(GL_BLUE_BITS, &b);
174         GG.colordepth = r + g + b; /* assumes same depth for RGB */
175
176         if (GLEW_VERSION_3_2 || GLEW_ARB_texture_multisample) {
177                 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES , &GG.samples_color_texture_max);
178         }
179
180         const char *vendor = (const char *)glGetString(GL_VENDOR);
181         const char *renderer = (const char *)glGetString(GL_RENDERER);
182         const char *version = (const char *)glGetString(GL_VERSION);
183
184         if (strstr(vendor, "ATI")) {
185                 GG.device = GPU_DEVICE_ATI;
186                 GG.driver = GPU_DRIVER_OFFICIAL;
187         }
188         else if (strstr(vendor, "NVIDIA")) {
189                 GG.device = GPU_DEVICE_NVIDIA;
190                 GG.driver = GPU_DRIVER_OFFICIAL;
191         }
192         else if (strstr(vendor, "Intel") ||
193                 /* src/mesa/drivers/dri/intel/intel_context.c */
194                 strstr(renderer, "Mesa DRI Intel") ||
195                 strstr(renderer, "Mesa DRI Mobile Intel")) {
196                 GG.device = GPU_DEVICE_INTEL;
197                 GG.driver = GPU_DRIVER_OFFICIAL;
198         }
199         else if (strstr(renderer, "Mesa DRI R") || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI "))) {
200                 GG.device = GPU_DEVICE_ATI;
201                 GG.driver = GPU_DRIVER_OPENSOURCE;
202         }
203         else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
204                 GG.device = GPU_DEVICE_NVIDIA;
205                 GG.driver = GPU_DRIVER_OPENSOURCE;
206         }
207         else if (strstr(vendor, "Mesa")) {
208                 GG.device = GPU_DEVICE_SOFTWARE;
209                 GG.driver = GPU_DRIVER_SOFTWARE;
210         }
211         else if (strstr(vendor, "Microsoft")) {
212                 GG.device = GPU_DEVICE_SOFTWARE;
213                 GG.driver = GPU_DRIVER_SOFTWARE;
214         }
215         else if (strstr(renderer, "Apple Software Renderer")) {
216                 GG.device = GPU_DEVICE_SOFTWARE;
217                 GG.driver = GPU_DRIVER_SOFTWARE;
218         }
219         else {
220                 GG.device = GPU_DEVICE_ANY;
221                 GG.driver = GPU_DRIVER_ANY;
222         }
223
224         /* make sure double side isn't used by default and only getting enabled in places where it's
225          * really needed to prevent different unexpected behaviors like with intel gme965 card (sergey) */
226         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
227
228 #ifdef _WIN32
229         GG.os = GPU_OS_WIN;
230 #elif defined(__APPLE__)
231         GG.os = GPU_OS_MAC;
232 #else
233         GG.os = GPU_OS_UNIX;
234 #endif
235
236
237         /* df/dy calculation factors, those are dependent on driver */
238         if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
239                 GG.dfdyfactors[0] = 1.0;
240                 GG.dfdyfactors[1] = -1.0;
241         }
242         else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN  &&
243                 (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
244                  strstr(version, "4.0.0 - Build 9.18.10.3186") ||
245                  strstr(version, "4.0.0 - Build 9.18.10.3165") ||
246                  strstr(version, "3.1.0 - Build 9.17.10.3347") ||
247                  strstr(version, "3.1.0 - Build 9.17.10.4101")))
248         {
249                 GG.dfdyfactors[0] = -1.0;
250                 GG.dfdyfactors[1] = 1.0;
251         }
252         else {
253                 GG.dfdyfactors[0] = 1.0;
254                 GG.dfdyfactors[1] = 1.0;
255         }
256
257
258         GPU_invalid_tex_init();
259         GPU_simple_shaders_init();
260 }
261
262 void gpu_extensions_exit(void)
263 {
264         GPU_simple_shaders_exit();
265         GPU_invalid_tex_free();
266 }
267
268 bool GPU_glsl_support(void)
269 {
270         /* always supported, still queried by game engine */
271         return true;
272 }
273
274 bool GPU_non_power_of_two_support(void)
275 {
276         /* always supported on full GL but still relevant for OpenGL ES */
277         return true;
278 }
279
280 bool GPU_display_list_support(void)
281 {
282         /* deprecated in GL 3
283          * supported on older GL and compatibility profile
284          * still queried by game engine
285          */
286         return true;
287 }
288
289 bool GPU_bicubic_bump_support(void)
290 {
291         return GLEW_VERSION_4_0 || (GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0);
292 }
293
294
295 bool GPU_geometry_shader_support(void)
296 {
297         /* in GL 3.2 geometry shaders are fully supported
298          * core profile clashes with our other shaders so accept compatibility only
299          * other GL versions can use EXT_geometry_shader4 if available
300          */
301         return (GLEW_VERSION_3_2 && GLEW_ARB_compatibility) || GLEW_EXT_geometry_shader4;
302 }
303
304 static bool GPU_geometry_shader_support_via_extension(void)
305 {
306         return GLEW_EXT_geometry_shader4 && !(GLEW_VERSION_3_2 && GLEW_ARB_compatibility);
307 }
308
309 bool GPU_instanced_drawing_support(void)
310 {
311         return GLEW_VERSION_3_1 || GLEW_ARB_draw_instanced;
312 }
313
314 int GPU_color_depth(void)
315 {
316         return GG.colordepth;
317 }
318
319 static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
320 {
321         const char *err = "unknown";
322
323         switch (status) {
324                 case GL_FRAMEBUFFER_COMPLETE_EXT:
325                         break;
326                 case GL_INVALID_OPERATION:
327                         err = "Invalid operation";
328                         break;
329                 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
330                         err = "Incomplete attachment";
331                         break;
332                 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
333                         err = "Unsupported framebuffer format";
334                         break;
335                 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
336                         err = "Missing attachment";
337                         break;
338                 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
339                         err = "Attached images must have same dimensions";
340                         break;
341                 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
342                         err = "Attached images must have same format";
343                         break;
344                 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
345                         err = "Missing draw buffer";
346                         break;
347                 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
348                         err = "Missing read buffer";
349                         break;
350         }
351
352         if (err_out) {
353                 BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
354                         (int)status, err);
355         }
356         else {
357                 fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
358                         (int)status, err);
359         }
360 }
361
362 /* GPUTexture */
363
364 struct GPUTexture {
365         int w, h;           /* width/height */
366         int w_orig, h_orig; /* width/height (before power of 2 is applied) */
367         int number;         /* number for multitexture binding */
368         int refcount;       /* reference count */
369         GLenum target;      /* GL_TEXTURE_* */
370         GLenum target_base; /* same as target, (but no multisample) */
371         GLuint bindcode;    /* opengl identifier for texture */
372         int fromblender;    /* we got the texture from Blender */
373
374         GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
375         int fb_attachment;  /* slot the texture is attached to */
376         int depth;          /* is a depth texture? if 3D how deep? */
377         int depth_orig;     /* depth (before power of 2 is applied) */
378 };
379
380 static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
381 {
382         unsigned char *pixels, *p;
383         const float *fp = fpixels;
384         const int len = 4 * length;
385         int a;
386
387         p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
388
389         for (a = 0; a < len; a++, p++, fp++)
390                 *p = FTOCHAR((*fp));
391
392         return pixels;
393 }
394
395 static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
396 {
397         void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
398
399         if (target == GL_TEXTURE_1D)
400                 glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
401         else
402                 glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
403         
404         MEM_freeN(pixels);
405 }
406
407 static GPUTexture *GPU_texture_create_nD(
408         int w, int h, int n, const float *fpixels, int depth,
409         GPUHDRType hdr_type, int components, int samples,
410         char err_out[256])
411 {
412         GPUTexture *tex;
413         GLenum type, format, internalformat;
414         void *pixels = NULL;
415
416         if (samples) {
417                 CLAMP_MAX(samples, GG.samples_color_texture_max);
418         }
419
420         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
421         tex->w = tex->w_orig = w;
422         tex->h = tex->h_orig = h;
423         tex->number = -1;
424         tex->refcount = 1;
425         tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
426         tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
427         tex->depth = tex->depth_orig = depth;
428         tex->fb_attachment = -1;
429
430         glGenTextures(1, &tex->bindcode);
431
432         if (!tex->bindcode) {
433                 if (err_out) {
434                         BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
435                                 (int)glGetError());
436                 }
437                 else {
438                         fprintf(stderr, "GPUTexture: texture create failed: %d\n",
439                                 (int)glGetError());
440                 }
441                 GPU_texture_free(tex);
442                 return NULL;
443         }
444
445         if (!GPU_non_power_of_two_support()) {
446                 tex->w = power_of_2_max_i(tex->w);
447                 tex->h = power_of_2_max_i(tex->h);
448         }
449
450         tex->number = 0;
451         glBindTexture(tex->target, tex->bindcode);
452
453         if (depth) {
454                 type = GL_UNSIGNED_BYTE;
455                 format = GL_DEPTH_COMPONENT;
456                 internalformat = GL_DEPTH_COMPONENT;
457         }
458         else {
459                 type = GL_FLOAT;
460
461                 if (components == 4) {
462                         format = GL_RGBA;
463                         switch (hdr_type) {
464                                 case GPU_HDR_NONE:
465                                         internalformat = GL_RGBA8;
466                                         break;
467                                 case GPU_HDR_HALF_FLOAT:
468                                         internalformat = GL_RGBA16F;
469                                         break;
470                                 case GPU_HDR_FULL_FLOAT:
471                                         internalformat = GL_RGBA32F;
472                                         break;
473                                 default:
474                                         break;
475                         }
476                 }
477                 else if (components == 2) {
478                         format = GL_RG;
479                         switch (hdr_type) {
480                                 case GPU_HDR_NONE:
481                                         internalformat = GL_RG8;
482                                         break;
483                                 case GPU_HDR_HALF_FLOAT:
484                                         internalformat = GL_RG16F;
485                                         break;
486                                 case GPU_HDR_FULL_FLOAT:
487                                         internalformat = GL_RG32F;
488                                         break;
489                                 default:
490                                         break;
491                         }
492                 }
493
494                 if (fpixels && hdr_type == GPU_HDR_NONE) {
495                         type = GL_UNSIGNED_BYTE;
496                         pixels = GPU_texture_convert_pixels(w*h, fpixels);
497                 }
498         }
499
500         if (tex->target == GL_TEXTURE_1D) {
501                 glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
502
503                 if (fpixels) {
504                         glTexSubImage1D(tex->target, 0, 0, w, format, type,
505                                 pixels ? pixels : fpixels);
506
507                         if (tex->w > w)
508                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0,
509                                         tex->w-w, 1);
510                 }
511         }
512         else {
513                 if (samples) {
514                         glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
515                 }
516                 else {
517                         glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
518                                      format, type, NULL);
519                 }
520
521                 if (fpixels) {
522                         glTexSubImage2D(tex->target, 0, 0, 0, w, h,
523                                 format, type, pixels ? pixels : fpixels);
524
525                         if (tex->w > w)
526                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h);
527                         if (tex->h > h)
528                                 GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h);
529                 }
530         }
531
532         if (pixels)
533                 MEM_freeN(pixels);
534
535         if (depth) {
536                 glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
537                 glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
538                 glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
539                 glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
540                 glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
541         }
542         else {
543                 glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
544                 glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
545         }
546
547         if (tex->target_base != GL_TEXTURE_1D) {
548                 glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
549                 glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
550         }
551         else
552                 glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
553
554         return tex;
555 }
556
557
558 GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
559 {
560         GPUTexture *tex;
561         GLenum type, format, internalformat;
562         void *pixels = NULL;
563         int r_width;
564         bool rescale = false;
565
566         if (!GLEW_VERSION_1_2)
567                 return NULL;
568
569         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
570         tex->w = tex->w_orig = w;
571         tex->h = tex->h_orig = h;
572         tex->depth = tex->depth_orig = depth;
573         tex->number = -1;
574         tex->refcount = 1;
575         tex->target = GL_TEXTURE_3D;
576         tex->target_base = GL_TEXTURE_3D;
577
578         glGenTextures(1, &tex->bindcode);
579
580         if (!tex->bindcode) {
581                 fprintf(stderr, "GPUTexture: texture create failed: %d\n",
582                         (int)glGetError());
583                 GPU_texture_free(tex);
584                 return NULL;
585         }
586
587         if (!GPU_non_power_of_two_support()) {
588                 tex->w = power_of_2_max_i(tex->w);
589                 tex->h = power_of_2_max_i(tex->h);
590                 tex->depth = power_of_2_max_i(tex->depth);
591         }
592
593         tex->number = 0;
594         glBindTexture(tex->target, tex->bindcode);
595
596         GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
597
598         type = GL_FLOAT;
599         if (channels == 4) {
600                 format = GL_RGBA;
601                 internalformat = GL_RGBA;
602         }
603         else {
604                 format = GL_RED;
605                 internalformat = GL_INTENSITY;
606         }
607
608         /* 3D textures are quite heavy, test if it's possible to create them first */
609         glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
610         glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
611
612         while (r_width == 0) {
613                 rescale = true;
614                 tex->w /= 2;
615                 tex->h /= 2;
616                 tex->depth /= 2;
617                 glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
618                 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
619         }
620
621         /* really unlikely to happen but keep this just in case */
622         tex->w = max_ii(tex->w, 1);
623         tex->h = max_ii(tex->h, 1);
624         tex->depth = max_ii(tex->depth, 1);
625
626 #if 0
627         if (fpixels)
628                 pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
629 #endif
630
631         GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
632
633         /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
634          * for gooseberry */
635         if (rescale && fpixels) {
636                 unsigned int i, j, k;
637                 unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
638                 float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d");
639
640                 GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
641
642                 for (k = 0; k < tex->depth; k++) {
643                         for (j = 0; j < tex->h; j++) {
644                                 for (i = 0; i < tex->w; i++) {
645                                         /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */
646                                         float xb = i * xf;
647                                         float yb = j * yf;
648                                         float zb = k * zf;
649                                         unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
650                                         unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
651
652                                         if (channels == 4) {
653                                                 tex3d[offset * 4] = fpixels[offset_orig * 4];
654                                                 tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
655                                                 tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
656                                                 tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
657                                         }
658                                         else
659                                                 tex3d[offset] = fpixels[offset_orig];
660                                 }
661                         }
662                 }
663
664                 glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
665
666                 MEM_freeN(tex3d);
667         }
668         else {
669                 if (fpixels) {
670                         if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
671                                 /* clear first to avoid unitialized pixels */
672                                 float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
673                                 glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
674                                 glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, GL_INTENSITY, GL_FLOAT, zero);
675                                 glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
676                                 MEM_freeN(zero);
677                         }
678                         else {
679                                 glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
680                         }
681
682                         GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
683                 }
684         }
685
686
687         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
688         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
689         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
690         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
691         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
692
693         if (pixels)
694                 MEM_freeN(pixels);
695
696         GPU_texture_unbind(tex);
697
698         return tex;
699 }
700
701 GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data, double time, int mipmap)
702 {
703         GPUTexture *tex;
704         GLint w, h, border, bindcode;
705
706         GPU_update_image_time(ima, time);
707         /* this binds a texture, so that's why to restore it to 0 */
708         bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, is_data);
709
710         if (ima->gputexture) {
711                 ima->gputexture->bindcode = bindcode;
712                 glBindTexture(GL_TEXTURE_2D, 0);
713                 return ima->gputexture;
714         }
715
716         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
717         tex->bindcode = bindcode;
718         tex->number = -1;
719         tex->refcount = 1;
720         tex->target = GL_TEXTURE_2D;
721         tex->target_base = GL_TEXTURE_2D;
722         tex->fromblender = 1;
723
724         ima->gputexture= tex;
725
726         if (!glIsTexture(tex->bindcode)) {
727                 GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
728         }
729         else {
730                 glBindTexture(GL_TEXTURE_2D, tex->bindcode);
731                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
732                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
733                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
734
735                 tex->w = tex->w_orig = w - border;
736                 tex->h = tex->h_orig = h - border;
737         }
738
739         glBindTexture(GL_TEXTURE_2D, 0);
740
741         return tex;
742 }
743
744 GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
745 {
746         GPUTexture *tex = prv->gputexture[0];
747         GLint w, h;
748         GLuint bindcode = 0;
749         
750         if (tex)
751                 bindcode = tex->bindcode;
752         
753         /* this binds a texture, so that's why we restore it to 0 */
754         if (bindcode == 0) {
755                 GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL);
756         }
757         if (tex) {
758                 tex->bindcode = bindcode;
759                 glBindTexture(GL_TEXTURE_2D, 0);
760                 return tex;
761         }
762
763         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
764         tex->bindcode = bindcode;
765         tex->number = -1;
766         tex->refcount = 1;
767         tex->target = GL_TEXTURE_2D;
768         tex->target_base = GL_TEXTURE_2D;
769         
770         prv->gputexture[0] = tex;
771         
772         if (!glIsTexture(tex->bindcode)) {
773                 GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
774         }
775         else {
776                 glBindTexture(GL_TEXTURE_2D, tex->bindcode);
777                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
778                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
779                 
780                 tex->w = tex->w_orig = w;
781                 tex->h = tex->h_orig = h;
782         }
783         
784         glBindTexture(GL_TEXTURE_2D, 0);
785         
786         return tex;
787
788 }
789
790 GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
791 {
792         GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
793
794         if (tex)
795                 GPU_texture_unbind(tex);
796         
797         return tex;
798 }
799
800 GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
801 {
802         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
803
804         if (tex)
805                 GPU_texture_unbind(tex);
806         
807         return tex;
808 }
809 GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
810 {
811         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
812
813         if (tex)
814                 GPU_texture_unbind(tex);
815
816         return tex;
817 }
818
819 GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
820 {
821         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
822
823         if (tex)
824                 GPU_texture_unbind(tex);
825         
826         return tex;
827 }
828 GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
829 {
830         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
831
832         if (tex)
833                 GPU_texture_unbind(tex);
834
835         return tex;
836 }
837
838 /**
839  * A shadow map for VSM needs two components (depth and depth^2)
840  */
841 GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
842 {
843         GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
844
845         if (tex) {
846                 /* Now we tweak some of the settings */
847                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
848                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
849
850                 GPU_texture_unbind(tex);
851         }
852
853         return tex;
854 }
855
856 GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
857 {
858         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
859
860         if (tex) {
861                 /* Now we tweak some of the settings */
862                 if (repeat) {
863                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
864                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
865                 }
866                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
867                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
868
869                 GPU_texture_unbind(tex);
870         }
871
872         return tex;
873 }
874
875 GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
876 {
877         GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
878
879         if (tex) {
880                 /* Now we tweak some of the settings */
881                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
882                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
883                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
884
885                 GPU_texture_unbind(tex);
886         }
887
888         return tex;
889 }
890
891 void GPU_invalid_tex_init(void)
892 {
893         const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
894         GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
895         GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
896         GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
897 }
898
899 void GPU_invalid_tex_bind(int mode)
900 {
901         switch (mode) {
902                 case GL_TEXTURE_1D:
903                         glBindTexture(GL_TEXTURE_1D, GG.invalid_tex_1D->bindcode);
904                         break;
905                 case GL_TEXTURE_2D:
906                         glBindTexture(GL_TEXTURE_2D, GG.invalid_tex_2D->bindcode);
907                         break;
908                 case GL_TEXTURE_3D:
909                         glBindTexture(GL_TEXTURE_3D, GG.invalid_tex_3D->bindcode);
910                         break;
911         }
912 }
913
914 void GPU_invalid_tex_free(void)
915 {
916         if (GG.invalid_tex_1D)
917                 GPU_texture_free(GG.invalid_tex_1D);
918         if (GG.invalid_tex_2D)
919                 GPU_texture_free(GG.invalid_tex_2D);
920         if (GG.invalid_tex_3D)
921                 GPU_texture_free(GG.invalid_tex_3D);
922 }
923
924
925 void GPU_texture_bind(GPUTexture *tex, int number)
926 {
927         GLenum arbnumber;
928
929         if (number >= GG.maxtextures) {
930                 fprintf(stderr, "Not enough texture slots.\n");
931                 return;
932         }
933
934         if ((G.debug & G_DEBUG)) {
935                 if (tex->fb && tex->fb->object == GG.currentfb) {
936                         fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
937                 }
938         }
939
940         if (number < 0)
941                 return;
942
943         GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
944
945         arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
946         if (number != 0) glActiveTexture(arbnumber);
947         if (tex->bindcode != 0) {
948                 glBindTexture(tex->target, tex->bindcode);
949         }
950         else
951                 GPU_invalid_tex_bind(tex->target);
952         glEnable(tex->target);
953         if (number != 0) glActiveTexture(GL_TEXTURE0);
954
955         tex->number = number;
956
957         GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
958 }
959
960 void GPU_texture_unbind(GPUTexture *tex)
961 {
962         GLenum arbnumber;
963
964         if (tex->number >= GG.maxtextures) {
965                 fprintf(stderr, "Not enough texture slots.\n");
966                 return;
967         }
968
969         if (tex->number == -1)
970                 return;
971         
972         GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
973
974         arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
975         if (tex->number != 0) glActiveTexture(arbnumber);
976         glBindTexture(tex->target, 0);
977         glDisable(tex->target_base);
978         if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
979
980         tex->number = -1;
981
982         GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
983 }
984
985 void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
986 {
987         GLenum arbnumber;
988
989         if (tex->number >= GG.maxtextures) {
990                 fprintf(stderr, "Not enough texture slots.\n");
991                 return;
992         }
993
994         if (tex->number == -1)
995                 return;
996
997         GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
998
999         arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
1000         if (tex->number != 0) glActiveTexture(arbnumber);
1001
1002         if (tex->depth) {
1003                 if (compare)
1004                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
1005                 else
1006                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
1007         }
1008
1009         if (use_filter) {
1010                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1011                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1012         }
1013         else {
1014                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1015                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1016         }
1017         if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
1018
1019         GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
1020 }
1021
1022 void GPU_texture_free(GPUTexture *tex)
1023 {
1024         tex->refcount--;
1025
1026         if (tex->refcount < 0)
1027                 fprintf(stderr, "GPUTexture: negative refcount\n");
1028         
1029         if (tex->refcount == 0) {
1030                 if (tex->fb)
1031                         GPU_framebuffer_texture_detach(tex);
1032                 if (tex->bindcode && !tex->fromblender)
1033                         glDeleteTextures(1, &tex->bindcode);
1034
1035                 MEM_freeN(tex);
1036         }
1037 }
1038
1039 void GPU_texture_ref(GPUTexture *tex)
1040 {
1041         tex->refcount++;
1042 }
1043
1044 int GPU_texture_target(const GPUTexture *tex)
1045 {
1046         return tex->target;
1047 }
1048
1049 int GPU_texture_opengl_width(const GPUTexture *tex)
1050 {
1051         return tex->w;
1052 }
1053
1054 int GPU_texture_opengl_height(const GPUTexture *tex)
1055 {
1056         return tex->h;
1057 }
1058
1059 int GPU_texture_opengl_bindcode(const GPUTexture *tex)
1060 {
1061         return tex->bindcode;
1062 }
1063
1064 GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
1065 {
1066         return tex->fb;
1067 }
1068
1069 /* GPUFrameBuffer */
1070
1071 GPUFrameBuffer *GPU_framebuffer_create(void)
1072 {
1073         GPUFrameBuffer *fb;
1074
1075         if (!GLEW_EXT_framebuffer_object)
1076                 return NULL;
1077         
1078         fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
1079         glGenFramebuffersEXT(1, &fb->object);
1080
1081         if (!fb->object) {
1082                 fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
1083                         (int)glGetError());
1084                 GPU_framebuffer_free(fb);
1085                 return NULL;
1086         }
1087
1088         /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
1089         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1090         glReadBuffer(GL_NONE);
1091         glDrawBuffer(GL_NONE);
1092         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1093         
1094         return fb;
1095 }
1096
1097 int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
1098 {
1099         GLenum attachment;
1100         GLenum error;
1101
1102         if (slot >= GPU_FB_MAX_SLOTS) {
1103                 fprintf(stderr,
1104                         "Attaching to index %d framebuffer slot unsupported. "
1105                         "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
1106                 return 0;
1107         }
1108
1109         if ((G.debug & G_DEBUG)) {
1110                 if (tex->number != -1) {
1111                         fprintf(stderr,
1112                                 "Feedback loop warning!: "
1113                                 "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
1114                 }
1115         }
1116
1117         if (tex->depth)
1118                 attachment = GL_DEPTH_ATTACHMENT_EXT;
1119         else
1120                 attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
1121
1122         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1123         GG.currentfb = fb->object;
1124
1125         /* Clean glError buffer. */
1126         while (glGetError() != GL_NO_ERROR) {}
1127
1128         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 
1129                 tex->target, tex->bindcode, 0);
1130
1131         error = glGetError();
1132
1133         if (error == GL_INVALID_OPERATION) {
1134                 GPU_framebuffer_restore();
1135                 GPU_print_framebuffer_error(error, err_out);
1136                 return 0;
1137         }
1138
1139         if (tex->depth)
1140                 fb->depthtex = tex;
1141         else
1142                 fb->colortex[slot] = tex;
1143
1144         tex->fb= fb;
1145         tex->fb_attachment = slot;
1146
1147         return 1;
1148 }
1149
1150 void GPU_framebuffer_texture_detach(GPUTexture *tex)
1151 {
1152         GLenum attachment;
1153         GPUFrameBuffer *fb;
1154
1155         if (!tex->fb)
1156                 return;
1157
1158         fb = tex->fb;
1159
1160         if (GG.currentfb != fb->object) {
1161                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1162                 GG.currentfb = tex->fb->object;
1163         }
1164
1165         if (tex->depth) {
1166                 fb->depthtex = NULL;
1167                 attachment = GL_DEPTH_ATTACHMENT_EXT;
1168         }
1169         else {
1170                 BLI_assert(fb->colortex[tex->fb_attachment] == tex);
1171                 fb->colortex[tex->fb_attachment] = NULL;
1172                 attachment = GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment;
1173         }
1174
1175         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, tex->target, 0, 0);
1176
1177         tex->fb = NULL;
1178         tex->fb_attachment = -1;
1179 }
1180
1181 void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
1182 {
1183         if (!tex->fb) {
1184                 fprintf(stderr, "Error, texture not bound to framebuffer!\n");
1185                 return;
1186         }
1187
1188         /* push attributes */
1189         glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
1190         glDisable(GL_SCISSOR_TEST);
1191
1192         /* bind framebuffer */
1193         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
1194
1195         if (tex->depth) {
1196                 glDrawBuffer(GL_NONE);
1197                 glReadBuffer(GL_NONE);
1198         }
1199         else {
1200                 /* last bound prevails here, better allow explicit control here too */
1201                 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
1202                 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
1203         }
1204         
1205         if (tex->target == GL_TEXTURE_2D_MULTISAMPLE) {
1206                 glEnable(GL_MULTISAMPLE);
1207         }
1208
1209         /* push matrices and set default viewport and matrix */
1210         glViewport(0, 0, tex->w_orig, tex->h_orig);
1211         GG.currentfb = tex->fb->object;
1212
1213         glMatrixMode(GL_PROJECTION);
1214         glPushMatrix();
1215         glMatrixMode(GL_MODELVIEW);
1216         glPushMatrix();
1217 }
1218
1219 void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
1220 {
1221         int numslots = 0, i;
1222         GLenum attachments[4];
1223         
1224         if (!fb->colortex[slot]) {
1225                 fprintf(stderr, "Error, framebuffer slot empty!\n");
1226                 return;
1227         }
1228         
1229         for (i = 0; i < 4; i++) {
1230                 if (fb->colortex[i]) {
1231                         attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
1232                         numslots++;
1233                 }
1234         }
1235         
1236         /* push attributes */
1237         glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
1238         glDisable(GL_SCISSOR_TEST);
1239
1240         /* bind framebuffer */
1241         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1242
1243         /* last bound prevails here, better allow explicit control here too */
1244         glDrawBuffers(numslots, attachments);
1245         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
1246
1247         /* push matrices and set default viewport and matrix */
1248         glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
1249         GG.currentfb = fb->object;
1250
1251         glMatrixMode(GL_PROJECTION);
1252         glPushMatrix();
1253         glMatrixMode(GL_MODELVIEW);
1254         glPushMatrix();
1255 }
1256
1257
1258 void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
1259 {
1260         /* restore matrix */
1261         glMatrixMode(GL_PROJECTION);
1262         glPopMatrix();
1263         glMatrixMode(GL_MODELVIEW);
1264         glPopMatrix();
1265
1266         /* restore attributes */
1267         glPopAttrib();
1268 }
1269
1270 void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
1271 {
1272         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1273         /* last bound prevails here, better allow explicit control here too */
1274         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
1275         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
1276
1277         /* push matrices and set default viewport and matrix */
1278         glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
1279         GG.currentfb = fb->object;
1280         GG.currentfb = fb->object;
1281 }
1282
1283 bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
1284 {
1285         GLenum status;
1286         
1287         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1288         GG.currentfb = fb->object;
1289         
1290         /* Clean glError buffer. */
1291         while (glGetError() != GL_NO_ERROR) {}
1292         
1293         status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1294         
1295         if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1296                 GPU_framebuffer_restore();
1297                 GPU_print_framebuffer_error(status, err_out);
1298                 return false;
1299         }
1300         
1301         return true;
1302 }
1303
1304 void GPU_framebuffer_free(GPUFrameBuffer *fb)
1305 {
1306         int i;
1307         if (fb->depthtex)
1308                 GPU_framebuffer_texture_detach(fb->depthtex);
1309
1310         for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
1311                 if (fb->colortex[i]) {
1312                         GPU_framebuffer_texture_detach(fb->colortex[i]);
1313                 }
1314         }
1315
1316         if (fb->object) {
1317                 glDeleteFramebuffersEXT(1, &fb->object);
1318
1319                 if (GG.currentfb == fb->object) {
1320                         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1321                         GG.currentfb = 0;
1322                 }
1323         }
1324
1325         MEM_freeN(fb);
1326 }
1327
1328 void GPU_framebuffer_restore(void)
1329 {
1330         if (GG.currentfb != 0) {
1331                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1332                 GG.currentfb = 0;
1333         }
1334 }
1335
1336 void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
1337 {
1338         const float scaleh[2] = {1.0f / blurtex->w_orig, 0.0f};
1339         const float scalev[2] = {0.0f, 1.0f / tex->h_orig};
1340
1341         GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
1342         int scale_uniform, texture_source_uniform;
1343
1344         if (!blur_shader)
1345                 return;
1346
1347         scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
1348         texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
1349                 
1350         /* Blurring horizontally */
1351
1352         /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
1353          * pushing unnecessary matrices onto the OpenGL stack. */
1354         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
1355         glDrawBuffer(GL_COLOR_ATTACHMENT0);
1356         
1357         /* avoid warnings from texture binding */
1358         GG.currentfb = blurfb->object;
1359
1360         GPU_shader_bind(blur_shader);
1361         GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
1362         GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
1363         glViewport(0, 0, blurtex->w_orig, blurtex->h_orig);
1364
1365         /* Peparing to draw quad */
1366         glMatrixMode(GL_MODELVIEW);
1367         glLoadIdentity();
1368         glMatrixMode(GL_TEXTURE);
1369         glLoadIdentity();
1370         glMatrixMode(GL_PROJECTION);
1371         glLoadIdentity();
1372
1373         glDisable(GL_DEPTH_TEST);
1374
1375         GPU_texture_bind(tex, 0);
1376
1377         /* Drawing quad */
1378         glBegin(GL_QUADS);
1379         glTexCoord2d(0, 0); glVertex2f(1, 1);
1380         glTexCoord2d(1, 0); glVertex2f(-1, 1);
1381         glTexCoord2d(1, 1); glVertex2f(-1, -1);
1382         glTexCoord2d(0, 1); glVertex2f(1, -1);
1383         glEnd();
1384
1385         /* Blurring vertically */
1386
1387         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
1388         glDrawBuffer(GL_COLOR_ATTACHMENT0);
1389         
1390         GG.currentfb = fb->object;
1391         
1392         glViewport(0, 0, tex->w_orig, tex->h_orig);
1393         GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
1394         GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
1395         GPU_texture_bind(blurtex, 0);
1396
1397         glBegin(GL_QUADS);
1398         glTexCoord2d(0, 0); glVertex2f(1, 1);
1399         glTexCoord2d(1, 0); glVertex2f(-1, 1);
1400         glTexCoord2d(1, 1); glVertex2f(-1, -1);
1401         glTexCoord2d(0, 1); glVertex2f(1, -1);
1402         glEnd();
1403
1404         GPU_shader_unbind();
1405 }
1406
1407 /* GPUOffScreen */
1408
1409 struct GPUOffScreen {
1410         GPUFrameBuffer *fb;
1411         GPUTexture *color;
1412         GPUTexture *depth;
1413 };
1414
1415 GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256])
1416 {
1417         GPUOffScreen *ofs;
1418
1419         ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
1420
1421         ofs->fb = GPU_framebuffer_create();
1422         if (!ofs->fb) {
1423                 GPU_offscreen_free(ofs);
1424                 return NULL;
1425         }
1426
1427         if (samples) {
1428                 if (!GLEW_EXT_framebuffer_multisample ||
1429                     !GLEW_ARB_texture_multisample ||
1430                     /* Only needed for GPU_offscreen_read_pixels.
1431                      * We could add an arg if we intend to use multi-sample
1432                      * offscreen buffers w/o reading their pixels */
1433                     !GLEW_EXT_framebuffer_blit ||
1434                     /* This is required when blitting from a multi-sampled buffers,
1435                      * even though we're not scaling. */
1436                     !GLEW_EXT_framebuffer_multisample_blit_scaled)
1437                 {
1438                         samples = 0;
1439                 }
1440         }
1441
1442         ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out);
1443         if (!ofs->depth) {
1444                 GPU_offscreen_free(ofs);
1445                 return NULL;
1446         }
1447
1448         if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
1449                 GPU_offscreen_free(ofs);
1450                 return NULL;
1451         }
1452
1453         ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
1454         if (!ofs->color) {
1455                 GPU_offscreen_free(ofs);
1456                 return NULL;
1457         }
1458
1459         if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
1460                 GPU_offscreen_free(ofs);
1461                 return NULL;
1462         }
1463         
1464         /* check validity at the very end! */
1465         if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
1466                 GPU_offscreen_free(ofs);
1467                 return NULL;            
1468         }
1469
1470         GPU_framebuffer_restore();
1471
1472         return ofs;
1473 }
1474
1475 void GPU_offscreen_free(GPUOffScreen *ofs)
1476 {
1477         if (ofs->fb)
1478                 GPU_framebuffer_free(ofs->fb);
1479         if (ofs->color)
1480                 GPU_texture_free(ofs->color);
1481         if (ofs->depth)
1482                 GPU_texture_free(ofs->depth);
1483         
1484         MEM_freeN(ofs);
1485 }
1486
1487 void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
1488 {
1489         glDisable(GL_SCISSOR_TEST);
1490         if (save)
1491                 GPU_texture_bind_as_framebuffer(ofs->color);
1492         else {
1493                 GPU_framebuffer_bind_no_save(ofs->fb, 0);
1494         }
1495 }
1496
1497 void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
1498 {
1499         if (restore)
1500                 GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
1501         GPU_framebuffer_restore();
1502         glEnable(GL_SCISSOR_TEST);
1503 }
1504
1505 void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
1506 {
1507         const int w = ofs->color->w_orig;
1508         const int h = ofs->color->h_orig;
1509
1510         if (ofs->color->target == GL_TEXTURE_2D_MULTISAMPLE) {
1511                 /* For a multi-sample texture,
1512                  * we need to create an intermediate buffer to blit to,
1513                  * before its copied using 'glReadPixels' */
1514
1515                 /* not needed since 'ofs' needs to be bound to the framebuffer already */
1516 // #define USE_FBO_CTX_SWITCH
1517
1518                 GLuint fbo_blit = 0;
1519                 GLuint tex_blit = 0;
1520                 GLenum status;
1521
1522                 /* create texture for new 'fbo_blit' */
1523                 glGenTextures(1, &tex_blit);
1524                 if (!tex_blit) {
1525                         goto finally;
1526                 }
1527
1528                 glBindTexture(GL_TEXTURE_2D, tex_blit);
1529                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, type, 0);
1530
1531 #ifdef USE_FBO_CTX_SWITCH
1532                 /* read from multi-sample buffer */
1533                 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
1534                 glFramebufferTexture2DEXT(
1535                         GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
1536                         GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
1537                 status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
1538                 if (status != GL_FRAMEBUFFER_COMPLETE) {
1539                         goto finally;
1540                 }
1541 #endif
1542
1543                 /* write into new single-sample buffer */
1544                 glGenFramebuffersEXT(1, &fbo_blit);
1545                 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
1546                 glFramebufferTexture2DEXT(
1547                         GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1548                         GL_TEXTURE_2D, tex_blit, 0);
1549                 status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1550                 if (status != GL_FRAMEBUFFER_COMPLETE) {
1551                         goto finally;
1552                 }
1553
1554                 /* perform the copy */
1555                 glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1556
1557                 /* read the results */
1558                 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, fbo_blit);
1559                 glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
1560
1561 #ifdef USE_FBO_CTX_SWITCH
1562                 /* restore the original frame-bufer */
1563                 glBindFramebufferEXT(GL_FRAMEBUFFER, ofs->color->fb->object);
1564 #undef USE_FBO_CTX_SWITCH
1565 #endif
1566
1567
1568 finally:
1569                 /* cleanup */
1570                 if (tex_blit) {
1571                         glDeleteTextures(1, &tex_blit);
1572                 }
1573                 if (fbo_blit) {
1574                         glDeleteFramebuffersEXT(1, &fbo_blit);
1575                 }
1576
1577                 GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
1578         }
1579         else {
1580                 glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
1581         }
1582 }
1583
1584 int GPU_offscreen_width(const GPUOffScreen *ofs)
1585 {
1586         return ofs->color->w_orig;
1587 }
1588
1589 int GPU_offscreen_height(const GPUOffScreen *ofs)
1590 {
1591         return ofs->color->h_orig;
1592 }
1593
1594 int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
1595 {
1596         return ofs->color->bindcode;
1597 }
1598
1599 /* GPUShader */
1600
1601 struct GPUShader {
1602         GLuint program;  /* handle for full program (links shader stages below) */
1603
1604         GLuint vertex;   /* handle for vertex shader */
1605         GLuint geometry; /* handle for geometry shader */
1606         GLuint fragment; /* handle for fragment shader */
1607
1608         int totattrib;   /* total number of attributes */
1609         int uniforms;    /* required uniforms */
1610 };
1611
1612 struct GPUProgram {
1613         GPUProgramType type;
1614         GLuint prog;
1615 };
1616
1617
1618 static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
1619 {
1620         int i;
1621         int line = 1;
1622
1623         fprintf(stderr, "GPUShader: %s error:\n", task);
1624
1625         for (i = 0; i < totcode; i++) {
1626                 const char *c, *pos, *end = code[i] + strlen(code[i]);
1627
1628                 if (G.debug & G_DEBUG) {
1629                         fprintf(stderr, "===== shader string %d ====\n", i + 1);
1630
1631                         c = code[i];
1632                         while ((c < end) && (pos = strchr(c, '\n'))) {
1633                                 fprintf(stderr, "%2d  ", line);
1634                                 fwrite(c, (pos + 1) - c, 1, stderr);
1635                                 c = pos + 1;
1636                                 line++;
1637                         }
1638                         
1639                         fprintf(stderr, "%s", c);
1640                 }
1641         }
1642         
1643         fprintf(stderr, "%s\n", log);
1644 }
1645
1646 static const char *gpu_shader_version(void)
1647 {
1648         if (GLEW_VERSION_3_2) {
1649                 if (GLEW_ARB_compatibility) {
1650                         return "#version 150 compatibility\n";
1651                         /* highest version that is widely supported
1652                          * gives us native geometry shaders!
1653                          * use compatibility profile so we can continue using builtin shader input/output names
1654                          */
1655                 }
1656                 else {
1657                         return "#version 130\n";
1658                         /* latest version that is compatible with existing shaders */
1659                 }
1660         }
1661         else if (GLEW_VERSION_3_1) {
1662                 if (GLEW_ARB_compatibility) {
1663                         return "#version 140\n";
1664                         /* also need the ARB_compatibility extension, handled below */
1665                 }
1666                 else {
1667                         return "#version 130\n";
1668                         /* latest version that is compatible with existing shaders */
1669                 }
1670         }
1671         else if (GLEW_VERSION_3_0) {
1672                 return "#version 130\n";
1673                 /* GLSL 1.3 has modern syntax/keywords/datatypes so use if available
1674                  * older features are deprecated but still available without compatibility extension or profile
1675                  */
1676         }
1677         else {
1678                 return "#version 120\n";
1679                 /* minimum supported */
1680         }
1681 }
1682
1683
1684 static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_geometry_shader)
1685 {
1686         /* enable extensions for features that are not part of our base GLSL version
1687          * don't use an extension for something already available!
1688          */
1689
1690         if (GLEW_ARB_texture_query_lod) {
1691                 /* a #version 400 feature, but we use #version 150 maximum so use extension */
1692                 strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
1693         }
1694
1695         if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) {
1696                 strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
1697         }
1698
1699         if (GLEW_VERSION_3_1 && !GLEW_VERSION_3_2 && GLEW_ARB_compatibility) {
1700                 strcat(defines, "#extension GL_ARB_compatibility: enable\n");
1701         }
1702
1703         if (!GLEW_VERSION_3_1) {
1704                 if (GLEW_ARB_draw_instanced) {
1705                         strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
1706                 }
1707
1708                 if (!GLEW_VERSION_3_0 && GLEW_EXT_gpu_shader4) {
1709                         strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
1710                         /* TODO: maybe require this? shaders become so much nicer */
1711                 }
1712         }
1713 }
1714
1715 static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], bool use_opensubdiv)
1716 {
1717         /* some useful defines to detect GPU type */
1718         if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
1719                 strcat(defines, "#define GPU_ATI\n");
1720                 if (GLEW_VERSION_3_0) {
1721                         /* TODO(merwin): revisit this version check; GLEW_VERSION_3_0 means GL 3.0 or newer */
1722                         strcat(defines, "#define CLIP_WORKAROUND\n");
1723                 }
1724         }
1725         else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
1726                 strcat(defines, "#define GPU_NVIDIA\n");
1727         else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
1728                 strcat(defines, "#define GPU_INTEL\n");
1729
1730         if (GPU_bicubic_bump_support())
1731                 strcat(defines, "#define BUMP_BICUBIC\n");
1732
1733 #ifdef WITH_OPENSUBDIV
1734         /* TODO(sergey): Check whether we actually compiling shader for
1735          * the OpenSubdiv mesh.
1736          */
1737         if (use_opensubdiv) {
1738                 strcat(defines, "#define USE_OPENSUBDIV\n");
1739
1740                 /* TODO(sergey): not strictly speaking a define, but this is
1741                  * a global typedef which we don't have better place to define
1742                  * in yet.
1743                  */
1744                 strcat(defines, "struct VertexData {\n"
1745                                 "  vec4 position;\n"
1746                                 "  vec3 normal;\n"
1747                                 "  vec2 uv;"
1748                                 "};\n");
1749         }
1750 #else
1751         UNUSED_VARS(use_opensubdiv);
1752 #endif
1753
1754         return;
1755 }
1756
1757 void GPU_program_bind(GPUProgram *program)
1758 {
1759         glEnable(program->type);
1760         glBindProgramARB(program->type, program->prog);
1761 }
1762
1763 void GPU_program_unbind(GPUProgram *program)
1764 {
1765         glDisable(program->type);
1766         glBindProgramARB(program->type, 0);
1767 }
1768
1769
1770 GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code)
1771 {
1772         /* TODO(merwin): remove ARB program support (recode smoke shader in GLSL) */
1773
1774         GPUProgram *program;
1775         GLint error_pos, is_native;
1776
1777         if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT))
1778                 return NULL;
1779
1780         program = MEM_callocN(sizeof(GPUProgram), "GPUProgram");
1781
1782         switch (type) {
1783                 case GPU_PROGRAM_TYPE_FRAGMENT:
1784                         program->type = GL_FRAGMENT_PROGRAM_ARB;
1785                         break;
1786         }
1787
1788         /* create the object and set its code string */
1789         glGenProgramsARB(1, &program->prog);
1790         glBindProgramARB(program->type, program->prog);
1791
1792         glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code);
1793
1794         glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
1795         glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native);
1796         if ((error_pos == -1) && (is_native == 1)) {
1797                 return program;
1798         }
1799         else {
1800                 /* glGetError is set before that, clear it */
1801                 while (glGetError() != GL_NO_ERROR)
1802                         ;
1803                 shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1);
1804                 MEM_freeN(program);
1805         }
1806
1807         return NULL;
1808 }
1809
1810 void GPU_program_free(GPUProgram *program)
1811 {
1812         glDeleteProgramsARB(1, &program->prog);
1813         MEM_freeN(program);
1814 }
1815
1816 void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w)
1817 {
1818         glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
1819 }
1820
1821 GPUShader *GPU_shader_create(const char *vertexcode,
1822                              const char *fragcode,
1823                              const char *geocode,
1824                              const char *libcode,
1825                              const char *defines,
1826                              int input,
1827                              int output,
1828                              int number)
1829 {
1830         return GPU_shader_create_ex(vertexcode,
1831                                     fragcode,
1832                                     geocode,
1833                                     libcode,
1834                                     defines,
1835                                     input,
1836                                     output,
1837                                     number,
1838                                     GPU_SHADER_FLAGS_NONE);
1839 }
1840
1841 GPUShader *GPU_shader_create_ex(const char *vertexcode,
1842                                 const char *fragcode,
1843                                 const char *geocode,
1844                                 const char *libcode,
1845                                 const char *defines,
1846                                 int input,
1847                                 int output,
1848                                 int number,
1849                                 const int flags)
1850 {
1851 #ifdef WITH_OPENSUBDIV
1852         /* TODO(sergey): used to add #version 150 to the geometry shader.
1853          * Could safely be renamed to "use_geometry_code" since it's very
1854          * likely any of geometry code will want to use GLSL 1.5.
1855          */
1856         bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
1857 #else
1858         UNUSED_VARS(flags);
1859         bool use_opensubdiv = false;
1860 #endif
1861         GLint status;
1862         GLchar log[5000];
1863         GLsizei length = 0;
1864         GPUShader *shader;
1865         char standard_defines[MAX_DEFINE_LENGTH] = "";
1866         char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
1867
1868         if (geocode && !GPU_geometry_shader_support())
1869                 return NULL;
1870
1871         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
1872
1873         if (vertexcode)
1874                 shader->vertex = glCreateShader(GL_VERTEX_SHADER);
1875         if (fragcode)
1876                 shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
1877         if (geocode)
1878                 shader->geometry = glCreateShader(GL_GEOMETRY_SHADER_EXT);
1879
1880         shader->program = glCreateProgram();
1881
1882         if (!shader->program ||
1883             (vertexcode && !shader->vertex) ||
1884             (fragcode && !shader->fragment) ||
1885             (geocode && !shader->geometry))
1886         {
1887                 fprintf(stderr, "GPUShader, object creation failed.\n");
1888                 GPU_shader_free(shader);
1889                 return NULL;
1890         }
1891
1892         gpu_shader_standard_defines(standard_defines, use_opensubdiv);
1893         gpu_shader_standard_extensions(standard_extensions, geocode != NULL);
1894
1895         if (vertexcode) {
1896                 const char *source[5];
1897                 /* custom limit, may be too small, beware */
1898                 int num_source = 0;
1899
1900                 source[num_source++] = gpu_shader_version();
1901                 source[num_source++] = standard_extensions;
1902                 source[num_source++] = standard_defines;
1903
1904                 if (defines) source[num_source++] = defines;
1905                 source[num_source++] = vertexcode;
1906
1907                 glAttachShader(shader->program, shader->vertex);
1908                 glShaderSource(shader->vertex, num_source, source, NULL);
1909
1910                 glCompileShader(shader->vertex);
1911                 glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status);
1912
1913                 if (!status) {
1914                         glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log);
1915                         shader_print_errors("compile", log, source, num_source);
1916
1917                         GPU_shader_free(shader);
1918                         return NULL;
1919                 }
1920         }
1921
1922         if (fragcode) {
1923                 const char *source[7];
1924                 int num_source = 0;
1925
1926                 source[num_source++] = gpu_shader_version();
1927                 source[num_source++] = standard_extensions;
1928                 source[num_source++] = standard_defines;
1929
1930 #ifdef WITH_OPENSUBDIV
1931                 /* TODO(sergey): Move to fragment shader source code generation. */
1932                 if (use_opensubdiv) {
1933                         source[num_source++] =
1934                                 "#ifdef USE_OPENSUBDIV\n"
1935                                 "in block {\n"
1936                                 "       VertexData v;\n"
1937                                 "} inpt;\n"
1938                                 "#endif\n";
1939                 }
1940 #endif
1941
1942                 if (defines) source[num_source++] = defines;
1943                 if (libcode) source[num_source++] = libcode;
1944                 source[num_source++] = fragcode;
1945
1946                 glAttachShader(shader->program, shader->fragment);
1947                 glShaderSource(shader->fragment, num_source, source, NULL);
1948
1949                 glCompileShader(shader->fragment);
1950                 glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status);
1951
1952                 if (!status) {
1953                         glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log);
1954                         shader_print_errors("compile", log, source, num_source);
1955
1956                         GPU_shader_free(shader);
1957                         return NULL;
1958                 }
1959         }
1960
1961         if (geocode) {
1962                 const char *source[6];
1963                 int num_source = 0;
1964
1965                 source[num_source++] = gpu_shader_version();
1966                 source[num_source++] = standard_extensions;
1967                 source[num_source++] = standard_defines;
1968
1969                 if (defines) source[num_source++] = defines;
1970                 source[num_source++] = geocode;
1971
1972                 glAttachShader(shader->program, shader->geometry);
1973                 glShaderSource(shader->geometry, num_source, source, NULL);
1974
1975                 glCompileShader(shader->geometry);
1976                 glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status);
1977
1978                 if (!status) {
1979                         glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log);
1980                         shader_print_errors("compile", log, source, num_source);
1981
1982                         GPU_shader_free(shader);
1983                         return NULL;
1984                 }
1985                 
1986                 if (!use_opensubdiv) {
1987                         GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
1988                 }
1989         }
1990
1991 #ifdef WITH_OPENSUBDIV
1992         if (use_opensubdiv) {
1993                 glBindAttribLocation(shader->program, 0, "position");
1994                 glBindAttribLocation(shader->program, 1, "normal");
1995                 GPU_shader_geometry_stage_primitive_io(shader,
1996                                                        GL_LINES_ADJACENCY_EXT,
1997                                                        GL_TRIANGLE_STRIP,
1998                                                        4);
1999         }
2000 #endif
2001
2002         glLinkProgram(shader->program);
2003         glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
2004         if (!status) {
2005                 glGetProgramInfoLog(shader->program, sizeof(log), &length, log);
2006                 /* print attached shaders in pipeline order */
2007                 if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1);
2008                 if (geocode) shader_print_errors("linking", log, &geocode, 1);
2009                 if (libcode) shader_print_errors("linking", log, &libcode, 1);
2010                 if (fragcode) shader_print_errors("linking", log, &fragcode, 1);
2011
2012                 GPU_shader_free(shader);
2013                 return NULL;
2014         }
2015
2016 #ifdef WITH_OPENSUBDIV
2017         /* TODO(sergey): Find a better place for this. */
2018         if (use_opensubdiv && GLEW_VERSION_4_1) {
2019                 glProgramUniform1i(shader->program,
2020                                    glGetUniformLocation(shader->program, "FVarDataBuffer"),
2021                                    31);  /* GL_TEXTURE31 */
2022         }
2023 #endif
2024
2025         return shader;
2026 }
2027
2028 void GPU_shader_bind(GPUShader *shader)
2029 {
2030         GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
2031         glUseProgram(shader->program);
2032         GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
2033 }
2034
2035 void GPU_shader_unbind(void)
2036 {
2037         GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
2038         glUseProgram(0);
2039         GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
2040 }
2041
2042 void GPU_shader_free(GPUShader *shader)
2043 {
2044         if (shader->vertex)
2045                 glDeleteShader(shader->vertex);
2046         if (shader->geometry)
2047                 glDeleteShader(shader->geometry);
2048         if (shader->fragment)
2049                 glDeleteShader(shader->fragment);
2050         if (shader->program)
2051                 glDeleteProgram(shader->program);
2052         MEM_freeN(shader);
2053 }
2054
2055 int GPU_shader_get_uniform(GPUShader *shader, const char *name)
2056 {
2057         return glGetUniformLocation(shader->program, name);
2058 }
2059
2060 void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
2061 {
2062         if (location == -1 || value == NULL)
2063                 return;
2064
2065         GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
2066
2067         if (length == 1) glUniform1fv(location, arraysize, value);
2068         else if (length == 2) glUniform2fv(location, arraysize, value);
2069         else if (length == 3) glUniform3fv(location, arraysize, value);
2070         else if (length == 4) glUniform4fv(location, arraysize, value);
2071         else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value);
2072         else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value);
2073
2074         GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
2075 }
2076
2077 void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
2078 {
2079         if (location == -1)
2080                 return;
2081
2082         GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
2083
2084         if (length == 1) glUniform1iv(location, arraysize, value);
2085         else if (length == 2) glUniform2iv(location, arraysize, value);
2086         else if (length == 3) glUniform3iv(location, arraysize, value);
2087         else if (length == 4) glUniform4iv(location, arraysize, value);
2088
2089         GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
2090 }
2091
2092 void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
2093 {
2094         if (location == -1)
2095                 return;
2096
2097         GPU_CHECK_ERRORS_AROUND(glUniform1i(location, value));
2098 }
2099
2100 void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
2101 {
2102         if (GPU_geometry_shader_support_via_extension()) {
2103                 /* geometry shaders must provide this info themselves for #version 150 and up */
2104                 glProgramParameteriEXT(shader->program, GL_GEOMETRY_INPUT_TYPE_EXT, input);
2105                 glProgramParameteriEXT(shader->program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
2106                 glProgramParameteriEXT(shader->program, GL_GEOMETRY_VERTICES_OUT_EXT, number);
2107         }
2108 }
2109
2110 void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
2111 {
2112         GLenum arbnumber;
2113
2114         if (tex->number >= GG.maxtextures) {
2115                 fprintf(stderr, "Not enough texture slots.\n");
2116                 return;
2117         }
2118                 
2119         if (tex->number == -1)
2120                 return;
2121
2122         if (location == -1)
2123                 return;
2124
2125         GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
2126
2127         arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
2128
2129         if (tex->number != 0) glActiveTexture(arbnumber);
2130         if (tex->bindcode != 0)
2131                 glBindTexture(tex->target, tex->bindcode);
2132         else
2133                 GPU_invalid_tex_bind(tex->target);
2134         glUniform1i(location, tex->number);
2135         glEnable(tex->target);
2136         if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
2137
2138         GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
2139 }
2140
2141 int GPU_shader_get_attribute(GPUShader *shader, const char *name)
2142 {
2143         int index;
2144         
2145         GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocation(shader->program, name));
2146
2147         return index;
2148 }
2149
2150 GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
2151 {
2152         GPUShader *retval = NULL;
2153
2154         switch (shader) {
2155                 case GPU_SHADER_VSM_STORE:
2156                         if (!GG.shaders.vsm_store)
2157                                 GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
2158                         retval = GG.shaders.vsm_store;
2159                         break;
2160                 case GPU_SHADER_SEP_GAUSSIAN_BLUR:
2161                         if (!GG.shaders.sep_gaussian_blur)
2162                                 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, NULL, 0, 0, 0);
2163                         retval = GG.shaders.sep_gaussian_blur;
2164                         break;
2165         }
2166
2167         if (retval == NULL)
2168                 printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
2169
2170         return retval;
2171 }
2172
2173 GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program)
2174 {
2175         GPUProgram *retval = NULL;
2176
2177         switch (program) {
2178                 case GPU_PROGRAM_SMOKE:
2179                         if (!GG.shaders.smoke)
2180                                 GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl);
2181                         retval = GG.shaders.smoke;
2182                         break;
2183                 case GPU_PROGRAM_SMOKE_COLORED:
2184                         if (!GG.shaders.smoke_colored)
2185                                 GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl);
2186                         retval = GG.shaders.smoke_colored;
2187                         break;
2188         }
2189
2190         if (retval == NULL)
2191                 printf("Unable to create a GPUProgram for builtin program: %u\n", program);
2192
2193         return retval;
2194 }
2195
2196 #define MAX_DEFINES 100
2197
2198 GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
2199 {
2200         int offset;
2201         char defines[MAX_DEFINES] = "";
2202         /* avoid shaders out of range */
2203         if (effects >= MAX_FX_SHADERS)
2204                 return NULL;
2205
2206         offset = 2 * effects;
2207
2208         if (persp) {
2209                 offset += 1;
2210                 strcat(defines, "#define PERSP_MATRIX\n");
2211         }
2212
2213         if (!GG.shaders.fx_shaders[offset]) {
2214                 GPUShader *shader;
2215
2216                 switch (effects) {
2217                         case GPU_SHADER_FX_SSAO:
2218                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
2219                                 break;
2220
2221                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
2222                                 strcat(defines, "#define FIRST_PASS\n");
2223                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
2224                                 break;
2225
2226                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
2227                                 strcat(defines, "#define SECOND_PASS\n");
2228                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
2229                                 break;
2230
2231                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
2232                                 strcat(defines, "#define THIRD_PASS\n");
2233                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
2234                                 break;
2235
2236                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
2237                                 strcat(defines, "#define FOURTH_PASS\n");
2238                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
2239                                 break;
2240
2241                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
2242                                 strcat(defines, "#define FIFTH_PASS\n");
2243                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
2244                                 break;
2245
2246                         case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
2247                                 strcat(defines, "#define FIRST_PASS\n");
2248                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
2249                                 break;
2250
2251                         case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
2252                                 strcat(defines, "#define SECOND_PASS\n");
2253                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
2254                                                                                    defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
2255                                 GG.shaders.fx_shaders[offset] = shader;
2256                                 break;
2257
2258                         case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
2259                                 strcat(defines, "#define THIRD_PASS\n");
2260                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
2261                                 break;
2262
2263                         case GPU_SHADER_FX_DEPTH_RESOLVE:
2264                                 GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
2265                 }
2266         }
2267
2268         return GG.shaders.fx_shaders[offset];
2269 }
2270
2271
2272 void GPU_shader_free_builtin_shaders(void)
2273 {
2274         int i;
2275
2276         if (GG.shaders.vsm_store) {
2277                 GPU_shader_free(GG.shaders.vsm_store);
2278                 GG.shaders.vsm_store = NULL;
2279         }
2280
2281         if (GG.shaders.sep_gaussian_blur) {
2282                 GPU_shader_free(GG.shaders.sep_gaussian_blur);
2283                 GG.shaders.sep_gaussian_blur = NULL;
2284         }
2285
2286         if (GG.shaders.smoke) {
2287                 GPU_program_free(GG.shaders.smoke);
2288                 GG.shaders.smoke = NULL;
2289         }
2290
2291         if (GG.shaders.smoke_colored) {
2292                 GPU_program_free(GG.shaders.smoke_colored);
2293                 GG.shaders.smoke_colored = NULL;
2294         }
2295
2296         for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
2297                 if (GG.shaders.fx_shaders[i]) {
2298                         GPU_shader_free(GG.shaders.fx_shaders[i]);
2299                         GG.shaders.fx_shaders[i] = NULL;
2300                 }
2301         }
2302 }
2303
2304 bool GPU_mem_stats_supported(void)
2305 {
2306         return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
2307 }
2308
2309
2310 void GPU_mem_stats_get(int *totalmem, int *freemem)
2311 {
2312         if (GLEW_NVX_gpu_memory_info) {
2313                 /* returned value in Kb */
2314                 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
2315
2316                 glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
2317         }
2318         else if (GLEW_ATI_meminfo) {
2319                 int stats[4];
2320
2321                 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
2322                 *freemem = stats[0];
2323                 *totalmem = 0;
2324         }
2325         else {
2326                 *totalmem = 0;
2327                 *freemem = 0;
2328         }
2329 }
2330
2331
2332 #if 0 /* unused */
2333
2334 /* GPUPixelBuffer */
2335
2336 typedef struct GPUPixelBuffer {
2337         GLuint bindcode[2];
2338         GLuint current;
2339         int datasize;
2340         int numbuffers;
2341         int halffloat;
2342 } GPUPixelBuffer;
2343
2344 void GPU_pixelbuffer_free(GPUPixelBuffer *pb)
2345 {
2346         if (pb->bindcode[0])
2347                 glDeleteBuffers(pb->numbuffers, pb->bindcode);
2348         MEM_freeN(pb);
2349 }
2350
2351 GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers)
2352 {
2353         GPUPixelBuffer *pb;
2354
2355         pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
2356         pb->datasize = x * y * 4 * (halffloat ? 16 : 8);
2357         pb->numbuffers = numbuffers;
2358         pb->halffloat = halffloat;
2359
2360         glGenBuffers(pb->numbuffers, pb->bindcode);
2361
2362         if (!pb->bindcode[0]) {
2363                 fprintf(stderr, "GPUPixelBuffer allocation failed\n");
2364                 GPU_pixelbuffer_free(pb);
2365                 return NULL;
2366         }
2367
2368         return pb;
2369 }
2370
2371 void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
2372 {
2373         void *pixels;
2374         int i;
2375
2376         glBindTexture(GL_TEXTURE_RECTANGLE, tex->bindcode);
2377
2378         for (i = 0; i < pb->numbuffers; i++) {
2379                 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pb->bindcode[pb->current]);
2380                 glBufferData(GL_PIXEL_UNPACK_BUFFER, pb->datasize, NULL,
2381                 GL_STREAM_DRAW);
2382
2383                 pixels = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
2384
2385 #  if 0
2386                 memcpy(pixels, _oImage.data(), pb->datasize);
2387 #  endif
2388
2389                 if (!glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2390                         fprintf(stderr, "Could not unmap OpenGL PBO\n");
2391                         break;
2392                 }
2393         }
2394
2395         glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2396 }
2397
2398 static int pixelbuffer_map_into_gpu(GLuint bindcode)
2399 {
2400         void *pixels;
2401
2402         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bindcode);
2403         pixels = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
2404
2405         /* do stuff in pixels */
2406
2407         if (!glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2408                 fprintf(stderr, "Could not unmap OpenGL PBO\n");
2409                 return 0;
2410         }
2411         
2412         return 1;
2413 }
2414
2415 static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode)
2416 {
2417         GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE;
2418         glBindTexture(GL_TEXTURE_RECTANGLE, tex->bindcode);
2419         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bindcode);
2420
2421         glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, 0, 0, tex->w, tex->h, GL_RGBA, type, NULL);
2422
2423         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
2424         glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2425 }
2426
2427 void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
2428 {
2429         int newbuffer;
2430
2431         if (pb->numbuffers == 1) {
2432                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]);
2433                 pixelbuffer_map_into_gpu(pb->bindcode[0]);
2434         }
2435         else {
2436                 pb->current = (pb->current + 1) % pb->numbuffers;
2437                 newbuffer = (pb->current + 1) % pb->numbuffers;
2438
2439                 pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
2440                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
2441         }
2442 }
2443 #endif /* unused */
2444