Blender  V2.59
gpu_extensions.c
Go to the documentation of this file.
00001 /*
00002  * $Id: gpu_extensions.c 36276 2011-04-21 15:53:30Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. The Blender
00010  * Foundation also sells licenses for use in proprietary software under
00011  * the Blender License.  See http://www.blender.org/BL/ for information
00012  * about this.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software Foundation,
00021  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022  *
00023  * The Original Code is Copyright (C) 2005 Blender Foundation.
00024  * All rights reserved.
00025  *
00026  * The Original Code is: all of this file.
00027  *
00028  * Contributor(s): Brecht Van Lommel.
00029  *
00030  * ***** END GPL LICENSE BLOCK *****
00031  */
00032 
00038 #include "GL/glew.h"
00039 
00040 #include "DNA_image_types.h"
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "BKE_global.h"
00045 
00046 
00047 #include "BLI_blenlib.h"
00048 #include "BLI_utildefines.h"
00049 
00050 #include "GPU_draw.h"
00051 #include "GPU_extensions.h"
00052 
00053 #include <stdlib.h>
00054 #include <stdio.h>
00055 #include <string.h>
00056 
00057 #include "BLI_winstuff.h"
00058 
00059 /* Extensions support */
00060 
00061 /* extensions used:
00062         - texture border clamp: 1.3 core
00063         - fragement shader: 2.0 core
00064         - framebuffer object: ext specification
00065         - multitexture 1.3 core
00066         - arb non power of two: 2.0 core
00067         - pixel buffer objects? 2.1 core
00068         - arb draw buffers? 2.0 core
00069 */
00070 
00071 static struct GPUGlobal {
00072         GLint maxtextures;
00073         GLuint currentfb;
00074         int glslsupport;
00075         int extdisabled;
00076         int colordepth;
00077         int npotdisabled; /* ATI 3xx-5xx (and more) chipsets support NPoT partially (== not enough) */
00078         GPUDeviceType device;
00079         GPUOSType os;
00080         GPUDriverType driver;
00081 } GG = {1, 0, 0, 0, 0};
00082 
00083 /* GPU Types */
00084 
00085 int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
00086 {
00087         return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
00088 }
00089 
00090 /* GPU Extensions */
00091 
00092 void GPU_extensions_disable(void)
00093 {
00094         GG.extdisabled = 1;
00095 }
00096 
00097 void GPU_extensions_init(void)
00098 {
00099         GLint r, g, b;
00100         const char *vendor, *renderer;
00101 
00102         /* can't avoid calling this multiple times, see wm_window_add_ghostwindow */
00103         static char init= 0;
00104         if(init) return;
00105         init= 1;
00106 
00107         glewInit();
00108 
00109         /* glewIsSupported("GL_VERSION_2_0") */
00110 
00111         if (GLEW_ARB_multitexture)
00112                 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &GG.maxtextures);
00113 
00114         GG.glslsupport = 1;
00115         if (!GLEW_ARB_multitexture) GG.glslsupport = 0;
00116         if (!GLEW_ARB_vertex_shader) GG.glslsupport = 0;
00117         if (!GLEW_ARB_fragment_shader) GG.glslsupport = 0;
00118 
00119         glGetIntegerv(GL_RED_BITS, &r);
00120         glGetIntegerv(GL_GREEN_BITS, &g);
00121         glGetIntegerv(GL_BLUE_BITS, &b);
00122         GG.colordepth = r+g+b; /* assumes same depth for RGB */
00123 
00124         vendor = (const char*)glGetString(GL_VENDOR);
00125         renderer = (const char*)glGetString(GL_RENDERER);
00126 
00127         if(strstr(vendor, "ATI")) {
00128                 GG.device = GPU_DEVICE_ATI;
00129                 GG.driver = GPU_DRIVER_OFFICIAL;
00130 
00131                 /* ATI X1xxx cards (R500 chipset) lack full support for npot textures
00132                  * although they report the GLEW_ARB_texture_non_power_of_two extension.
00133                  */
00134                 if(strstr(renderer, "X1"))
00135                         GG.npotdisabled = 1;
00136         }
00137         else if(strstr(vendor, "NVIDIA")) {
00138                 GG.device = GPU_DEVICE_NVIDIA;
00139                 GG.driver = GPU_DRIVER_OFFICIAL;
00140         }
00141         else if(strstr(vendor, "Intel") ||
00142                 /* src/mesa/drivers/dri/intel/intel_context.c */
00143                 strstr(renderer, "Mesa DRI Intel") ||
00144                 strstr(renderer, "Mesa DRI Mobile Intel")) {
00145                 GG.device = GPU_DEVICE_INTEL;
00146                 GG.driver = GPU_DRIVER_OFFICIAL;
00147         }
00148         else if(strstr(renderer, "Mesa DRI R") || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI "))) {
00149                 GG.device = GPU_DEVICE_ATI;
00150                 GG.driver = GPU_DRIVER_OPENSOURCE;
00151                 /* ATI 9500 to X2300 cards support NPoT textures poorly
00152                  * Incomplete list http://dri.freedesktop.org/wiki/ATIRadeon
00153                  * New IDs from MESA's src/gallium/drivers/r300/r300_screen.c
00154                  */
00155                 if(strstr(renderer, "R3") || strstr(renderer, "RV3") ||
00156                    strstr(renderer, "R4") || strstr(renderer, "RV4") ||
00157                    strstr(renderer, "RS4") || strstr(renderer, "RC4") ||
00158                    strstr(renderer, "R5") || strstr(renderer, "RV5") ||
00159                    strstr(renderer, "RS600") || strstr(renderer, "RS690") ||
00160                    strstr(renderer, "RS740"))
00161                         GG.npotdisabled = 1;
00162         }
00163         else if(strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
00164                 GG.device = GPU_DEVICE_NVIDIA;
00165                 GG.driver = GPU_DRIVER_OPENSOURCE;
00166         }
00167         else if(strstr(vendor, "Mesa")) {
00168                 GG.device = GPU_DEVICE_SOFTWARE;
00169                 GG.driver = GPU_DRIVER_SOFTWARE;
00170         }
00171         else if(strstr(vendor, "Microsoft")) {
00172                 GG.device = GPU_DEVICE_SOFTWARE;
00173                 GG.driver = GPU_DRIVER_SOFTWARE;
00174         }
00175         else if(strstr(renderer, "Apple Software Renderer")) {
00176                 GG.device = GPU_DEVICE_SOFTWARE;
00177                 GG.driver = GPU_DRIVER_SOFTWARE;
00178         }
00179         else {
00180                 GG.device = GPU_DEVICE_ANY;
00181                 GG.driver = GPU_DRIVER_ANY;
00182         }
00183 
00184         GG.os = GPU_OS_UNIX;
00185 #ifdef _WIN32
00186         GG.os = GPU_OS_WIN;
00187 #endif
00188 #ifdef __APPLE__
00189         GG.os = GPU_OS_MAC;
00190 #endif
00191 }
00192 
00193 int GPU_glsl_support(void)
00194 {
00195         return !GG.extdisabled && GG.glslsupport;
00196 }
00197 
00198 int GPU_non_power_of_two_support(void)
00199 {
00200         /* Exception for buggy ATI/Apple driver in Mac OS X 10.5/10.6,
00201          * they claim to support this but can cause system freeze */
00202         if(GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_MAC, GPU_DRIVER_OFFICIAL))
00203                 return 0;
00204 
00205         if(GG.npotdisabled)
00206                 return 0;
00207 
00208         return GLEW_ARB_texture_non_power_of_two;
00209 }
00210 
00211 int GPU_color_depth(void)
00212 {
00213         return GG.colordepth;
00214 }
00215 
00216 int GPU_print_error(const char *str)
00217 {
00218         GLenum errCode;
00219 
00220         if (G.f & G_DEBUG) {
00221                 if ((errCode = glGetError()) != GL_NO_ERROR) {
00222                         fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode));
00223                         return 1;
00224                 }
00225         }
00226 
00227         return 0;
00228 }
00229 
00230 static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
00231 {
00232         const char *err= "unknown";
00233 
00234         switch(status) {
00235                 case GL_FRAMEBUFFER_COMPLETE_EXT:
00236                         break;
00237                 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
00238                         err= "Incomplete attachment";
00239                         break;
00240                 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
00241                         err= "Unsupported framebuffer format";
00242                         break;
00243                 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
00244                         err= "Missing attachment";
00245                         break;
00246                 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
00247                         err= "Attached images must have same dimensions";
00248                         break;
00249                 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
00250                         err= "Attached images must have same format";
00251                         break;
00252                 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
00253                         err= "Missing draw buffer";
00254                         break;
00255                 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
00256                         err= "Missing read buffer";
00257                         break;
00258         }
00259 
00260         if(err_out) {
00261                 BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
00262                         (int)status, err);
00263         }
00264         else {
00265                 fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
00266                         (int)status, err);
00267         }
00268 }
00269 
00270 /* GPUTexture */
00271 
00272 struct GPUTexture {
00273         int w, h;                               /* width/height */
00274         int number;                             /* number for multitexture binding */
00275         int refcount;                   /* reference count */
00276         GLenum target;                  /* GL_TEXTURE_* */
00277         GLuint bindcode;                /* opengl identifier for texture */
00278         int fromblender;                /* we got the texture from Blender */
00279 
00280         GPUFrameBuffer *fb;             /* GPUFramebuffer this texture is attached to */
00281         int depth;                              /* is a depth texture? */
00282 };
00283 
00284 static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels)
00285 {
00286         unsigned char *pixels, *p;
00287         float *fp;
00288         int a, len;
00289 
00290         len = 4*length;
00291         fp = fpixels;
00292         p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels");
00293 
00294         for (a=0; a<len; a++, p++, fp++)
00295                 *p = FTOCHAR((*fp));
00296 
00297         return pixels;
00298 }
00299 
00300 static int is_pow2(int n)
00301 {
00302         return ((n)&(n-1))==0;
00303 }
00304 
00305 static int larger_pow2(int n)
00306 {
00307         if (is_pow2(n))
00308                 return n;
00309 
00310         while(!is_pow2(n))
00311                 n= n&(n-1);
00312 
00313         return n*2;
00314 }
00315 
00316 static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
00317 {
00318         void *pixels = MEM_callocN(sizeof(char)*4*w*h, "GPUTextureEmptyPixels");
00319 
00320         if (target == GL_TEXTURE_1D)
00321                 glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
00322         else
00323                 glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
00324         
00325         MEM_freeN(pixels);
00326 }
00327 
00328 static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth, char err_out[256])
00329 {
00330         GPUTexture *tex;
00331         GLenum type, format, internalformat;
00332         void *pixels = NULL;
00333 
00334         if(depth && !GLEW_ARB_depth_texture)
00335                 return NULL;
00336 
00337         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
00338         tex->w = w;
00339         tex->h = h;
00340         tex->number = -1;
00341         tex->refcount = 1;
00342         tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
00343         tex->depth = depth;
00344 
00345         glGenTextures(1, &tex->bindcode);
00346 
00347         if (!tex->bindcode) {
00348                 if(err_out) {
00349                         BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
00350                                 (int)glGetError());
00351                 }
00352                 else {
00353                         fprintf(stderr, "GPUTexture: texture create failed: %d\n",
00354                                 (int)glGetError());
00355                 }
00356                 GPU_texture_free(tex);
00357                 return NULL;
00358         }
00359 
00360         if (!GPU_non_power_of_two_support()) {
00361                 tex->w = larger_pow2(tex->w);
00362                 tex->h = larger_pow2(tex->h);
00363         }
00364 
00365         tex->number = 0;
00366         glBindTexture(tex->target, tex->bindcode);
00367 
00368         if(depth) {
00369                 type = GL_UNSIGNED_BYTE;
00370                 format = GL_DEPTH_COMPONENT;
00371                 internalformat = GL_DEPTH_COMPONENT;
00372         }
00373         else {
00374                 type = GL_UNSIGNED_BYTE;
00375                 format = GL_RGBA;
00376                 internalformat = GL_RGBA8;
00377 
00378                 if (fpixels)
00379                         pixels = GPU_texture_convert_pixels(w*h, fpixels);
00380         }
00381 
00382         if (tex->target == GL_TEXTURE_1D) {
00383                 glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
00384 
00385                 if (fpixels) {
00386                         glTexSubImage1D(tex->target, 0, 0, w, format, type,
00387                                 pixels? pixels: fpixels);
00388 
00389                         if (tex->w > w)
00390                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0,
00391                                         tex->w-w, 1);
00392                 }
00393         }
00394         else {
00395                 glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
00396                         format, type, NULL);
00397 
00398                 if (fpixels) {
00399                         glTexSubImage2D(tex->target, 0, 0, 0, w, h,
00400                                 format, type, pixels? pixels: fpixels);
00401 
00402                         if (tex->w > w)
00403                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h);
00404                         if (tex->h > h)
00405                                 GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h);
00406                 }
00407         }
00408 
00409         if (pixels)
00410                 MEM_freeN(pixels);
00411 
00412         if(depth) {
00413                 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00414                 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00415                 glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
00416                 glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
00417                 glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);  
00418         }
00419         else {
00420                 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00421                 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00422         }
00423 
00424         if (tex->target != GL_TEXTURE_1D) {
00425                 /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
00426                 GLenum wrapmode = (depth)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
00427                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
00428                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
00429 
00430 #if 0
00431                 float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
00432                 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); 
00433 #endif
00434         }
00435         else
00436                 glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00437 
00438         return tex;
00439 }
00440 
00441 
00442 GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels)
00443 {
00444         GPUTexture *tex;
00445         GLenum type, format, internalformat;
00446         void *pixels = NULL;
00447         float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
00448 
00449         if(!GLEW_VERSION_1_2)
00450                 return NULL;
00451 
00452         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
00453         tex->w = w;
00454         tex->h = h;
00455         tex->depth = depth;
00456         tex->number = -1;
00457         tex->refcount = 1;
00458         tex->target = GL_TEXTURE_3D;
00459 
00460         glGenTextures(1, &tex->bindcode);
00461 
00462         if (!tex->bindcode) {
00463                 fprintf(stderr, "GPUTexture: texture create failed: %d\n",
00464                         (int)glGetError());
00465                 GPU_texture_free(tex);
00466                 return NULL;
00467         }
00468 
00469         if (!GPU_non_power_of_two_support()) {
00470                 tex->w = larger_pow2(tex->w);
00471                 tex->h = larger_pow2(tex->h);
00472                 tex->depth = larger_pow2(tex->depth);
00473         }
00474 
00475         tex->number = 0;
00476         glBindTexture(tex->target, tex->bindcode);
00477 
00478         GPU_print_error("3D glBindTexture");
00479 
00480         type = GL_FLOAT; // GL_UNSIGNED_BYTE
00481         format = GL_RED;
00482         internalformat = GL_INTENSITY;
00483 
00484         //if (fpixels)
00485         //      pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
00486 
00487         glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, 0);
00488 
00489         GPU_print_error("3D glTexImage3D");
00490 
00491         if (fpixels) {
00492                 if(!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
00493                         /* clear first to avoid unitialized pixels */
00494                         float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
00495                         glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero);
00496                         MEM_freeN(zero);
00497                 }
00498 
00499                 glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
00500                 GPU_print_error("3D glTexSubImage3D");
00501         }
00502 
00503 
00504         glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor);
00505         GPU_print_error("3D GL_TEXTURE_BORDER_COLOR");
00506         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00507         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00508         GPU_print_error("3D GL_LINEAR");
00509         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00510         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00511         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00512         GPU_print_error("3D GL_CLAMP_TO_BORDER");
00513 
00514         if (pixels)
00515                 MEM_freeN(pixels);
00516 
00517         if (tex)
00518                 GPU_texture_unbind(tex);
00519 
00520         return tex;
00521 }
00522 
00523 GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, double time, int mipmap)
00524 {
00525         GPUTexture *tex;
00526         GLint w, h, border, lastbindcode, bindcode;
00527 
00528         glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
00529 
00530         GPU_update_image_time(ima, time);
00531         bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap);
00532 
00533         if(ima->gputexture) {
00534                 ima->gputexture->bindcode = bindcode;
00535                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
00536                 return ima->gputexture;
00537         }
00538 
00539         if(!bindcode) {
00540                 glBindTexture(GL_TEXTURE_2D, lastbindcode);
00541                 return NULL;
00542         }
00543 
00544         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
00545         tex->bindcode = bindcode;
00546         tex->number = -1;
00547         tex->refcount = 1;
00548         tex->target = GL_TEXTURE_2D;
00549         tex->fromblender = 1;
00550 
00551         ima->gputexture= tex;
00552 
00553         if (!glIsTexture(tex->bindcode)) {
00554                 GPU_print_error("Blender Texture");
00555         }
00556         else {
00557                 glBindTexture(GL_TEXTURE_2D, tex->bindcode);
00558                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
00559                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
00560                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
00561 
00562                 tex->w = w - border;
00563                 tex->h = h - border;
00564         }
00565 
00566         glBindTexture(GL_TEXTURE_2D, lastbindcode);
00567 
00568         return tex;
00569 }
00570 
00571 GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
00572 {
00573         GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out);
00574 
00575         if (tex)
00576                 GPU_texture_unbind(tex);
00577         
00578         return tex;
00579 }
00580 
00581 GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256])
00582 {
00583         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, err_out);
00584 
00585         if (tex)
00586                 GPU_texture_unbind(tex);
00587         
00588         return tex;
00589 }
00590 
00591 GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
00592 {
00593         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, err_out);
00594 
00595         if (tex)
00596                 GPU_texture_unbind(tex);
00597         
00598         return tex;
00599 }
00600 
00601 void GPU_texture_bind(GPUTexture *tex, int number)
00602 {
00603         GLenum arbnumber;
00604 
00605         if (number >= GG.maxtextures) {
00606                 GPU_print_error("Not enough texture slots.");
00607                 return;
00608         }
00609 
00610         if(number == -1)
00611                 return;
00612 
00613         GPU_print_error("Pre Texture Bind");
00614 
00615         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number);
00616         if (number != 0) glActiveTextureARB(arbnumber);
00617         glBindTexture(tex->target, tex->bindcode);
00618         glEnable(tex->target);
00619         if (number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
00620 
00621         tex->number = number;
00622 
00623         GPU_print_error("Post Texture Bind");
00624 }
00625 
00626 void GPU_texture_unbind(GPUTexture *tex)
00627 {
00628         GLenum arbnumber;
00629 
00630         if (tex->number >= GG.maxtextures) {
00631                 GPU_print_error("Not enough texture slots.");
00632                 return;
00633         }
00634 
00635         if(tex->number == -1)
00636                 return;
00637         
00638         GPU_print_error("Pre Texture Unbind");
00639 
00640         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
00641         if (tex->number != 0) glActiveTextureARB(arbnumber);
00642         glBindTexture(tex->target, 0);
00643         glDisable(tex->target);
00644         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
00645 
00646         tex->number = -1;
00647 
00648         GPU_print_error("Post Texture Unbind");
00649 }
00650 
00651 void GPU_texture_free(GPUTexture *tex)
00652 {
00653         tex->refcount--;
00654 
00655         if (tex->refcount < 0)
00656                 fprintf(stderr, "GPUTexture: negative refcount\n");
00657         
00658         if (tex->refcount == 0) {
00659                 if (tex->fb)
00660                         GPU_framebuffer_texture_detach(tex->fb, tex);
00661                 if (tex->bindcode && !tex->fromblender)
00662                         glDeleteTextures(1, &tex->bindcode);
00663 
00664                 MEM_freeN(tex);
00665         }
00666 }
00667 
00668 void GPU_texture_ref(GPUTexture *tex)
00669 {
00670         tex->refcount++;
00671 }
00672 
00673 int GPU_texture_target(GPUTexture *tex)
00674 {
00675         return tex->target;
00676 }
00677 
00678 int GPU_texture_opengl_width(GPUTexture *tex)
00679 {
00680         return tex->w;
00681 }
00682 
00683 int GPU_texture_opengl_height(GPUTexture *tex)
00684 {
00685         return tex->h;
00686 }
00687 
00688 GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
00689 {
00690         return tex->fb;
00691 }
00692 
00693 /* GPUFrameBuffer */
00694 
00695 struct GPUFrameBuffer {
00696         GLuint object;
00697         GPUTexture *colortex;
00698         GPUTexture *depthtex;
00699 };
00700 
00701 GPUFrameBuffer *GPU_framebuffer_create(void)
00702 {
00703         GPUFrameBuffer *fb;
00704 
00705         if (!GLEW_EXT_framebuffer_object)
00706                 return NULL;
00707         
00708         fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
00709         glGenFramebuffersEXT(1, &fb->object);
00710 
00711         if (!fb->object) {
00712                 fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
00713                         (int)glGetError());
00714                 GPU_framebuffer_free(fb);
00715                 return NULL;
00716         }
00717 
00718         return fb;
00719 }
00720 
00721 int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256])
00722 {
00723         GLenum status;
00724         GLenum attachment;
00725 
00726         if(tex->depth)
00727                 attachment = GL_DEPTH_ATTACHMENT_EXT;
00728         else
00729                 attachment = GL_COLOR_ATTACHMENT0_EXT;
00730 
00731         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
00732         GG.currentfb = fb->object;
00733 
00734         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 
00735                 tex->target, tex->bindcode, 0);
00736 
00737         if(tex->depth) {
00738                 glDrawBuffer(GL_NONE);
00739                 glReadBuffer(GL_NONE);
00740         }
00741         else {
00742                 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
00743                 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
00744         }
00745 
00746         status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
00747 
00748         if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
00749                 GPU_framebuffer_restore();
00750                 GPU_print_framebuffer_error(status, err_out);
00751                 return 0;
00752         }
00753 
00754         if(tex->depth)
00755                 fb->depthtex = tex;
00756         else
00757                 fb->colortex = tex;
00758 
00759         tex->fb= fb;
00760 
00761         return 1;
00762 }
00763 
00764 void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
00765 {
00766         GLenum attachment;
00767 
00768         if(!tex->fb)
00769                 return;
00770 
00771         if(GG.currentfb != tex->fb->object) {
00772                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
00773                 GG.currentfb = tex->fb->object;
00774         }
00775 
00776         if(tex->depth) {
00777                 fb->depthtex = NULL;
00778                 attachment = GL_DEPTH_ATTACHMENT_EXT;
00779         }
00780         else {
00781                 fb->colortex = NULL;
00782                 attachment = GL_COLOR_ATTACHMENT0_EXT;
00783         }
00784 
00785         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
00786                 tex->target, 0, 0);
00787 
00788         tex->fb = NULL;
00789 }
00790 
00791 void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex)
00792 {
00793         /* push attributes */
00794         glPushAttrib(GL_ENABLE_BIT);
00795         glPushAttrib(GL_VIEWPORT_BIT);
00796         glDisable(GL_SCISSOR_TEST);
00797 
00798         /* bind framebuffer */
00799         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
00800 
00801         /* push matrices and set default viewport and matrix */
00802         glViewport(0, 0, tex->w, tex->h);
00803         GG.currentfb = tex->fb->object;
00804 
00805         glMatrixMode(GL_PROJECTION);
00806         glPushMatrix();
00807         glLoadIdentity();
00808         glMatrixMode(GL_MODELVIEW);
00809         glPushMatrix();
00810         glLoadIdentity();
00811 }
00812 
00813 void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
00814 {
00815         /* restore matrix */
00816         glMatrixMode(GL_PROJECTION);
00817         glPopMatrix();
00818         glMatrixMode(GL_MODELVIEW);
00819         glPopMatrix();
00820 
00821         /* restore attributes */
00822         glPopAttrib();
00823         glPopAttrib();
00824         glEnable(GL_SCISSOR_TEST);
00825 }
00826 
00827 void GPU_framebuffer_free(GPUFrameBuffer *fb)
00828 {
00829         if(fb->depthtex)
00830                 GPU_framebuffer_texture_detach(fb, fb->depthtex);
00831         if(fb->colortex)
00832                 GPU_framebuffer_texture_detach(fb, fb->colortex);
00833 
00834         if(fb->object) {
00835                 glDeleteFramebuffersEXT(1, &fb->object);
00836 
00837                 if (GG.currentfb == fb->object) {
00838                         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00839                         GG.currentfb = 0;
00840                 }
00841         }
00842 
00843         MEM_freeN(fb);
00844 }
00845 
00846 void GPU_framebuffer_restore(void)
00847 {
00848         if (GG.currentfb != 0) {
00849                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00850                 GG.currentfb = 0;
00851         }
00852 }
00853 
00854 /* GPUOffScreen */
00855 
00856 struct GPUOffScreen {
00857         GPUFrameBuffer *fb;
00858         GPUTexture *color;
00859         GPUTexture *depth;
00860 };
00861 
00862 GPUOffScreen *GPU_offscreen_create(int *width, int *height, char err_out[256])
00863 {
00864         GPUOffScreen *ofs;
00865 
00866         ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
00867 
00868         ofs->fb = GPU_framebuffer_create();
00869         if(!ofs->fb) {
00870                 GPU_offscreen_free(ofs);
00871                 return NULL;
00872         }
00873 
00874         ofs->depth = GPU_texture_create_depth(*width, *height, err_out);
00875         if(!ofs->depth) {
00876                 GPU_offscreen_free(ofs);
00877                 return NULL;
00878         }
00879 
00880         if(*width!=ofs->depth->w || *height!=ofs->depth->h) {
00881                 *width= ofs->depth->w;
00882                 *height= ofs->depth->h;
00883                 printf("Offscreen size differs from given size!\n");
00884         }
00885         
00886         if(!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) {
00887                 GPU_offscreen_free(ofs);
00888                 return NULL;
00889         }
00890 
00891         ofs->color = GPU_texture_create_2D(*width, *height, NULL, err_out);
00892         if(!ofs->color) {
00893                 GPU_offscreen_free(ofs);
00894                 return NULL;
00895         }
00896 
00897         if(!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, err_out)) {
00898                 GPU_offscreen_free(ofs);
00899                 return NULL;
00900         }
00901 
00902         GPU_framebuffer_restore();
00903 
00904         return ofs;
00905 }
00906 
00907 void GPU_offscreen_free(GPUOffScreen *ofs)
00908 {
00909         if(ofs->fb)
00910                 GPU_framebuffer_free(ofs->fb);
00911         if(ofs->color)
00912                 GPU_texture_free(ofs->color);
00913         if(ofs->depth)
00914                 GPU_texture_free(ofs->depth);
00915         
00916         MEM_freeN(ofs);
00917 }
00918 
00919 void GPU_offscreen_bind(GPUOffScreen *ofs)
00920 {
00921         glDisable(GL_SCISSOR_TEST);
00922         GPU_framebuffer_texture_bind(ofs->fb, ofs->color);
00923 }
00924 
00925 void GPU_offscreen_unbind(GPUOffScreen *ofs)
00926 {
00927         GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
00928         GPU_framebuffer_restore();
00929         glEnable(GL_SCISSOR_TEST);
00930 }
00931 
00932 /* GPUShader */
00933 
00934 struct GPUShader {
00935         GLhandleARB object;             /* handle for full shader */
00936         GLhandleARB vertex;             /* handle for vertex shader */
00937         GLhandleARB fragment;   /* handle for fragment shader */
00938         GLhandleARB lib;                /* handle for libment shader */
00939         int totattrib;                  /* total number of attributes */
00940 };
00941 
00942 static void shader_print_errors(const char *task, char *log, const char *code)
00943 {
00944         const char *c, *pos, *end = code + strlen(code);
00945         int line = 1;
00946 
00947         fprintf(stderr, "GPUShader: %s error:\n", task);
00948 
00949         if(G.f & G_DEBUG) {
00950                 c = code;
00951                 while ((c < end) && (pos = strchr(c, '\n'))) {
00952                         fprintf(stderr, "%2d  ", line);
00953                         fwrite(c, (pos+1)-c, 1, stderr);
00954                         c = pos+1;
00955                         line++;
00956                 }
00957 
00958                 fprintf(stderr, "%s", c);
00959         }
00960 
00961         fprintf(stderr, "%s\n", log);
00962 }
00963 
00964 GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, /*GPUShader *lib,*/ const char *libcode)
00965 {
00966         GLint status;
00967         GLcharARB log[5000];
00968         const char *fragsource[2];
00969         GLsizei length = 0;
00970         GLint count;
00971         GPUShader *shader;
00972 
00973         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
00974                 return NULL;
00975 
00976         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
00977 
00978         if(vertexcode)
00979                 shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
00980         if(fragcode)
00981                 shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
00982         shader->object = glCreateProgramObjectARB();
00983 
00984         if (!shader->object ||
00985                 (vertexcode && !shader->vertex) ||
00986                 (fragcode && !shader->fragment)) {
00987                 fprintf(stderr, "GPUShader, object creation failed.\n");
00988                 GPU_shader_free(shader);
00989                 return NULL;
00990         }
00991 
00992         if(vertexcode) {
00993                 glAttachObjectARB(shader->object, shader->vertex);
00994                 glShaderSourceARB(shader->vertex, 1, (const char**)&vertexcode, NULL);
00995 
00996                 glCompileShaderARB(shader->vertex);
00997                 glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status);
00998 
00999                 if (!status) {
01000                         glGetInfoLogARB(shader->vertex, sizeof(log), &length, log);
01001                         shader_print_errors("compile", log, vertexcode);
01002 
01003                         GPU_shader_free(shader);
01004                         return NULL;
01005                 }
01006         }
01007 
01008         if(fragcode) {
01009                 count = 0;
01010                 if(libcode) fragsource[count++] = libcode;
01011                 if(fragcode) fragsource[count++] = fragcode;
01012 
01013                 glAttachObjectARB(shader->object, shader->fragment);
01014                 glShaderSourceARB(shader->fragment, count, fragsource, NULL);
01015 
01016                 glCompileShaderARB(shader->fragment);
01017                 glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status);
01018 
01019                 if (!status) {
01020                         glGetInfoLogARB(shader->fragment, sizeof(log), &length, log);
01021                         shader_print_errors("compile", log, fragcode);
01022 
01023                         GPU_shader_free(shader);
01024                         return NULL;
01025                 }
01026         }
01027 
01028         /*if(lib && lib->lib)
01029                 glAttachObjectARB(shader->object, lib->lib);*/
01030 
01031         glLinkProgramARB(shader->object);
01032         glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status);
01033         if (!status) {
01034                 glGetInfoLogARB(shader->object, sizeof(log), &length, log);
01035                 if (fragcode) shader_print_errors("linking", log, fragcode);
01036                 else if (vertexcode) shader_print_errors("linking", log, vertexcode);
01037                 else if (libcode) shader_print_errors("linking", log, libcode);
01038 
01039                 GPU_shader_free(shader);
01040                 return NULL;
01041         }
01042 
01043         return shader;
01044 }
01045 
01046 #if 0
01047 GPUShader *GPU_shader_create_lib(const char *code)
01048 {
01049         GLint status;
01050         GLcharARB log[5000];
01051         GLsizei length = 0;
01052         GPUShader *shader;
01053 
01054         if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
01055                 return NULL;
01056 
01057         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
01058 
01059         shader->lib = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
01060 
01061         if (!shader->lib) {
01062                 fprintf(stderr, "GPUShader, object creation failed.\n");
01063                 GPU_shader_free(shader);
01064                 return NULL;
01065         }
01066 
01067         glShaderSourceARB(shader->lib, 1, (const char**)&code, NULL);
01068 
01069         glCompileShaderARB(shader->lib);
01070         glGetObjectParameterivARB(shader->lib, GL_OBJECT_COMPILE_STATUS_ARB, &status);
01071 
01072         if (!status) {
01073                 glGetInfoLogARB(shader->lib, sizeof(log), &length, log);
01074                 shader_print_errors("compile", log, code);
01075 
01076                 GPU_shader_free(shader);
01077                 return NULL;
01078         }
01079 
01080         return shader;
01081 }
01082 #endif
01083 
01084 void GPU_shader_bind(GPUShader *shader)
01085 {
01086         GPU_print_error("Pre Shader Bind");
01087         glUseProgramObjectARB(shader->object);
01088         GPU_print_error("Post Shader Bind");
01089 }
01090 
01091 void GPU_shader_unbind(GPUShader *UNUSED(shader))
01092 {
01093         GPU_print_error("Pre Shader Unbind");
01094         glUseProgramObjectARB(0);
01095         GPU_print_error("Post Shader Unbind");
01096 }
01097 
01098 void GPU_shader_free(GPUShader *shader)
01099 {
01100         if (shader->lib)
01101                 glDeleteObjectARB(shader->lib);
01102         if (shader->vertex)
01103                 glDeleteObjectARB(shader->vertex);
01104         if (shader->fragment)
01105                 glDeleteObjectARB(shader->fragment);
01106         if (shader->object)
01107                 glDeleteObjectARB(shader->object);
01108         MEM_freeN(shader);
01109 }
01110 
01111 int GPU_shader_get_uniform(GPUShader *shader, const char *name)
01112 {
01113         return glGetUniformLocationARB(shader->object, name);
01114 }
01115 
01116 void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, float *value)
01117 {
01118         if(location == -1)
01119                 return;
01120 
01121         GPU_print_error("Pre Uniform Vector");
01122 
01123         if (length == 1) glUniform1fvARB(location, arraysize, value);
01124         else if (length == 2) glUniform2fvARB(location, arraysize, value);
01125         else if (length == 3) glUniform3fvARB(location, arraysize, value);
01126         else if (length == 4) glUniform4fvARB(location, arraysize, value);
01127         else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value);
01128         else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value);
01129 
01130         GPU_print_error("Post Uniform Vector");
01131 }
01132 
01133 void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
01134 {
01135         GLenum arbnumber;
01136 
01137         if (tex->number >= GG.maxtextures) {
01138                 GPU_print_error("Not enough texture slots.");
01139                 return;
01140         }
01141                 
01142         if(tex->number == -1)
01143                 return;
01144 
01145         if(location == -1)
01146                 return;
01147 
01148         GPU_print_error("Pre Uniform Texture");
01149 
01150         arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
01151 
01152         if (tex->number != 0) glActiveTextureARB(arbnumber);
01153         glBindTexture(tex->target, tex->bindcode);
01154         glUniform1iARB(location, tex->number);
01155         glEnable(tex->target);
01156         if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
01157 
01158         GPU_print_error("Post Uniform Texture");
01159 }
01160 
01161 int GPU_shader_get_attribute(GPUShader *shader, char *name)
01162 {
01163         int index;
01164         
01165         GPU_print_error("Pre Get Attribute");
01166 
01167         index = glGetAttribLocationARB(shader->object, name);
01168 
01169         GPU_print_error("Post Get Attribute");
01170 
01171         return index;
01172 }
01173 
01174 #if 0
01175 /* GPUPixelBuffer */
01176 
01177 typedef struct GPUPixelBuffer {
01178         GLuint bindcode[2];
01179         GLuint current;
01180         int datasize;
01181         int numbuffers;
01182         int halffloat;
01183 } GPUPixelBuffer;
01184 
01185 void GPU_pixelbuffer_free(GPUPixelBuffer *pb)
01186 {
01187         if (pb->bindcode[0])
01188                 glDeleteBuffersARB(pb->numbuffers, pb->bindcode);
01189         MEM_freeN(pb);
01190 }
01191 
01192 GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers)
01193 {
01194         GPUPixelBuffer *pb;
01195 
01196         if (!GLEW_ARB_multitexture || !GLEW_EXT_pixel_buffer_object)
01197                 return NULL;
01198         
01199         pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
01200         pb->datasize = x*y*4*((halffloat)? 16: 8);
01201         pb->numbuffers = numbuffers;
01202         pb->halffloat = halffloat;
01203 
01204            glGenBuffersARB(pb->numbuffers, pb->bindcode);
01205 
01206         if (!pb->bindcode[0]) {
01207                 fprintf(stderr, "GPUPixelBuffer allocation failed\n");
01208                 GPU_pixelbuffer_free(pb);
01209                 return NULL;
01210         }
01211 
01212         return pb;
01213 }
01214 
01215 void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
01216 {
01217         void *pixels;
01218         int i;
01219 
01220         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
01221 
01222         for (i = 0; i < pb->numbuffers; i++) {
01223                 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->bindcode[pb->current]);
01224                 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->datasize, NULL,
01225                 GL_STREAM_DRAW_ARB);
01226 
01227                 pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
01228                 /*memcpy(pixels, _oImage.data(), pb->datasize);*/
01229 
01230                 if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
01231                         fprintf(stderr, "Could not unmap opengl PBO\n");
01232                         break;
01233                 }
01234         }
01235 
01236         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
01237 }
01238 
01239 static int pixelbuffer_map_into_gpu(GLuint bindcode)
01240 {
01241         void *pixels;
01242 
01243         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
01244         pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
01245 
01246         /* do stuff in pixels */
01247 
01248         if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
01249                 fprintf(stderr, "Could not unmap opengl PBO\n");
01250                 return 0;
01251         }
01252         
01253         return 1;
01254 }
01255 
01256 static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode)
01257 {
01258         GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE;
01259         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
01260         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
01261 
01262         glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h,
01263                                         GL_RGBA, type, NULL);
01264 
01265         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
01266         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
01267 }
01268 
01269 void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
01270 {
01271         int newbuffer;
01272 
01273         if (pb->numbuffers == 1) {
01274                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]);
01275                 pixelbuffer_map_into_gpu(pb->bindcode[0]);
01276         }
01277         else {
01278                 pb->current = (pb->current+1)%pb->numbuffers;
01279                 newbuffer = (pb->current+1)%pb->numbuffers;
01280 
01281                 pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
01282                 pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
01283         }
01284 }
01285 #endif
01286