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