Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #include <vlGraphics/Texture.hpp> 00033 #include <vlCore/checks.hpp> 00034 #include <vlCore/Image.hpp> 00035 #include <vlCore/math_utils.hpp> 00036 #include <vlCore/Say.hpp> 00037 #include <vlCore/Log.hpp> 00038 00039 using namespace vl; 00040 00041 namespace 00042 { 00043 // if you think your application has a bug that depends on this function you are wrong 00044 int getDefaultFormat(ETextureFormat internal_format) 00045 { 00046 // OpenGL ES requires the internal format to be equal to the source image format when creating textures 00047 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2) 00048 return internal_format; 00049 #else 00050 switch(internal_format) 00051 { 00052 case TF_ALPHA: 00053 case TF_ALPHA4: 00054 case TF_ALPHA8: 00055 case TF_ALPHA12: 00056 case TF_ALPHA16: 00057 return GL_ALPHA; 00058 00059 case TF_LUMINANCE: 00060 case TF_LUMINANCE4: 00061 case TF_LUMINANCE8: 00062 case TF_LUMINANCE12: 00063 case TF_LUMINANCE16: 00064 case TF_SLUMINANCE: 00065 case TF_SLUMINANCE8: 00066 return GL_LUMINANCE; 00067 00068 case TF_LUMINANCE_ALPHA: 00069 case TF_LUMINANCE4_ALPHA4: 00070 case TF_LUMINANCE6_ALPHA2: 00071 case TF_LUMINANCE8_ALPHA8: 00072 case TF_LUMINANCE12_ALPHA4: 00073 case TF_LUMINANCE12_ALPHA12: 00074 case TF_LUMINANCE16_ALPHA16: 00075 case TF_SLUMINANCE_ALPHA: 00076 case TF_SLUMINANCE8_ALPHA8: 00077 return GL_LUMINANCE_ALPHA; 00078 00079 case TF_INTENSITY: 00080 case TF_INTENSITY4: 00081 case TF_INTENSITY8: 00082 case TF_INTENSITY12: 00083 case TF_INTENSITY16: 00084 return GL_INTENSITY; 00085 00086 case TF_RED: 00087 case TF_R8: 00088 case TF_R8_SNORM: 00089 case TF_R16: 00090 case TF_R16_SNORM: 00091 case TF_R16F: 00092 case TF_R32F: 00093 return GL_RED; 00094 00095 case TF_RG: 00096 case TF_RG8: 00097 case TF_RG8_SNORM: 00098 case TF_RG16: 00099 case TF_RG16_SNORM: 00100 case TF_RG16F: 00101 case TF_RG32F: 00102 return GL_RG; 00103 00104 case TF_RGB: 00105 case TF_RGB4: 00106 case TF_RGB5: 00107 case TF_RGB8: 00108 case TF_RGB8_SNORM: 00109 case TF_RGB10: 00110 case TF_RGB12: 00111 case TF_RGB16: 00112 // case TF_RGB16_SNORM: 00113 case TF_RGB16F: 00114 case TF_RGB32F: 00115 case TF_R3_G3_B2: 00116 case TF_R11F_G11F_B10F: 00117 // case TF_RGB9_A5: 00118 case TF_SRGB8: 00119 return GL_RGB; 00120 00121 case TF_RGBA: 00122 case TF_RGBA2: 00123 case TF_RGBA4: 00124 case TF_RGBA8: 00125 case TF_RGBA8_SNORM: 00126 case TF_RGBA12: 00127 case TF_RGBA16: 00128 case TF_RGBA16_SNORM: 00129 case TF_RGBA16F: 00130 case TF_RGBA32F: 00131 case TF_RGB5_A1: 00132 case TF_RGB10_A2: 00133 case TF_SRGB8_ALPHA8: 00134 return GL_RGBA; 00135 00136 case TF_R8I: 00137 case TF_R8UI: 00138 case TF_R16I: 00139 case TF_R16UI: 00140 case TF_R32I: 00141 case TF_R32UI: 00142 return GL_RED_INTEGER; 00143 00144 case TF_RG8I: 00145 case TF_RG8UI: 00146 case TF_RG16I: 00147 case TF_RG16UI: 00148 case TF_RG32I: 00149 case TF_RG32UI: 00150 return GL_RG_INTEGER; 00151 00152 case TF_RGB8I: 00153 // case TF_RGB8I_EXT: // Has the same value has above 00154 case TF_RGB8UI: 00155 // case TF_RGB8UI_EXT: // Has the same value has above 00156 case TF_RGB16I: 00157 // case TF_RGB16I_EXT: // Has the same value has above 00158 case TF_RGB16UI: 00159 // case TF_RGB16UI_EXT: // Has the same value has above 00160 case TF_RGB32I: 00161 // case TF_RGB32I_EXT: // Has the same value has above 00162 case TF_RGB32UI: 00163 // case TF_RGB32UI_EXT: // Has the same value has above 00164 return GL_RGB_INTEGER; 00165 00166 case TF_RGBA8I: 00167 // case TF_RGBAI_EXT: // Has the same value has above 00168 case TF_RGBA8UI: 00169 // case TF_RGBA8UI_EXT: // Has the same value has above 00170 case TF_RGBA16I: 00171 // case TF_RGBA16I_EXT: // Has the same value has above 00172 case TF_RGBA16UI: 00173 // case TF_RGBA16UI_EXT: // Has the same value has above 00174 case TF_RGBA32I: 00175 // case TF_RGBA32I_EXT: // Has the same value has above 00176 case TF_RGBA32UI: 00177 // case TF_RGBA32UI_EXT: // Has the same value has above 00178 case TF_RGB10_A2UI: 00179 return GL_RGBA_INTEGER; 00180 00181 case TF_DEPTH_STENCIL: 00182 case TF_DEPTH24_STENCIL8: 00183 case TF_DEPTH32F_STENCIL8: 00184 return GL_DEPTH_STENCIL; 00185 00186 case TF_DEPTH_COMPONENT: 00187 case TF_DEPTH_COMPONENT16: 00188 case TF_DEPTH_COMPONENT24: 00189 case TF_DEPTH_COMPONENT32: 00190 case TF_DEPTH_COMPONENT32F: 00191 return GL_DEPTH_COMPONENT; 00192 00193 // GL_EXT_texture_integer 00194 case TF_ALPHA8I_EXT: 00195 case TF_ALPHA8UI_EXT: 00196 case TF_ALPHA16I_EXT: 00197 case TF_ALPHA16UI_EXT: 00198 case TF_ALPHA32I_EXT: 00199 case TF_ALPHA32UI_EXT: 00200 return GL_ALPHA_INTEGER; 00201 00202 case TF_INTENSITY8I_EXT: 00203 case TF_INTENSITY8UI_EXT: 00204 case TF_INTENSITY16I_EXT: 00205 case TF_INTENSITY16UI_EXT: 00206 case TF_INTENSITY32I_EXT: 00207 case TF_INTENSITY32UI_EXT: 00208 return GL_RED_INTEGER; // Nothing associated with intensity in GL_EXT_texture_integer 00209 00210 case TF_LUMINANCE8I_EXT: 00211 case TF_LUMINANCE8UI_EXT: 00212 case TF_LUMINANCE16UI_EXT: 00213 case TF_LUMINANCE16I_EXT: 00214 case TF_LUMINANCE32I_EXT: 00215 case TF_LUMINANCE32UI_EXT: 00216 return GL_LUMINANCE_INTEGER_EXT; 00217 00218 case TF_LUMINANCE_ALPHA8I_EXT: 00219 case TF_LUMINANCE_ALPHA8UI_EXT: 00220 case TF_LUMINANCE_ALPHA16I_EXT: 00221 case TF_LUMINANCE_ALPHA16UI_EXT: 00222 case TF_LUMINANCE_ALPHA32I_EXT: 00223 case TF_LUMINANCE_ALPHA32UI_EXT: 00224 return GL_LUMINANCE_ALPHA_INTEGER_EXT; 00225 00226 default: 00227 return GL_RED; 00228 } 00229 #endif 00230 } 00231 00232 // if you think your application has a bug that depends on this function you are wrong 00233 int getDefaultType(ETextureFormat internal_format) 00234 { 00235 switch( internal_format ) 00236 { 00237 case TF_ALPHA4: 00238 case TF_ALPHA8: 00239 case TF_ALPHA8UI_EXT: 00240 case TF_INTENSITY4: 00241 case TF_INTENSITY8: 00242 case TF_INTENSITY8UI_EXT: 00243 case TF_LUMINANCE4: 00244 case TF_LUMINANCE8: 00245 case TF_LUMINANCE8UI_EXT: 00246 case TF_LUMINANCE8_ALPHA8: 00247 case TF_LUMINANCE_ALPHA8UI_EXT: 00248 case TF_R8: 00249 case TF_R8UI: 00250 case TF_RG8: 00251 case TF_RG8UI: 00252 case TF_RGB8: 00253 case TF_RGB8UI: 00254 case TF_RGBA8: 00255 case TF_RGBA8UI: 00256 return GL_UNSIGNED_BYTE; 00257 00258 case TF_ALPHA8I_EXT: 00259 case TF_INTENSITY8I_EXT: 00260 case TF_LUMINANCE8I_EXT: 00261 case TF_LUMINANCE_ALPHA8I_EXT: 00262 case TF_R8I: 00263 case TF_RG8I: 00264 case TF_RGB8I: 00265 case TF_RGBA8I: 00266 return GL_BYTE; 00267 00268 case TF_ALPHA12: 00269 case TF_ALPHA16: 00270 case TF_ALPHA16UI_EXT: 00271 case TF_INTENSITY12: 00272 case TF_INTENSITY16: 00273 case TF_INTENSITY16UI_EXT: 00274 case TF_LUMINANCE12: 00275 case TF_LUMINANCE16: 00276 case TF_LUMINANCE16UI_EXT: 00277 case TF_LUMINANCE16_ALPHA16: 00278 case TF_LUMINANCE_ALPHA16UI_EXT: 00279 case TF_R16: 00280 case TF_R16UI: 00281 case TF_RG16: 00282 case TF_RG16UI: 00283 case TF_RGB10: 00284 case TF_RGB12: 00285 case TF_RGB16: 00286 case TF_RGB16UI: 00287 case TF_RGBA12: 00288 case TF_RGBA16: 00289 case TF_RGBA16UI: 00290 case TF_DEPTH_COMPONENT16: 00291 return GL_UNSIGNED_SHORT; 00292 00293 case TF_ALPHA16I_EXT: 00294 case TF_INTENSITY16I_EXT: 00295 case TF_LUMINANCE16I_EXT: 00296 case TF_LUMINANCE_ALPHA16I_EXT: 00297 case TF_R16I: 00298 case TF_RG16I: 00299 case TF_RGB16I: 00300 case TF_RGBA16I: 00301 return GL_SHORT; 00302 00303 case TF_ALPHA32UI_EXT: 00304 case TF_INTENSITY32UI_EXT: 00305 case TF_LUMINANCE32UI_EXT: 00306 case TF_LUMINANCE_ALPHA32UI_EXT: 00307 case TF_R32UI: 00308 case TF_RG32UI: 00309 case TF_RGB32UI: 00310 case TF_RGBA32UI: 00311 case TF_DEPTH_COMPONENT24: 00312 case TF_DEPTH_COMPONENT32: 00313 return GL_UNSIGNED_INT; 00314 00315 case TF_ALPHA32I_EXT: 00316 case TF_INTENSITY32I_EXT: 00317 case TF_LUMINANCE32I_EXT: 00318 case TF_LUMINANCE_ALPHA32I_EXT: 00319 case TF_R32I: 00320 case TF_RG32I: 00321 case TF_RGB32I: 00322 case TF_RGBA32I: 00323 return GL_INT; 00324 00325 case TF_DEPTH24_STENCIL8: 00326 return GL_UNSIGNED_INT_24_8; 00327 00328 case TF_R16F: 00329 case TF_R32F: 00330 case TF_RG16F: 00331 case TF_RG32F: 00332 case TF_RGB16F: 00333 case TF_RGB32F: 00334 case TF_RGBA16F: 00335 case TF_RGBA32F: 00336 case TF_R11F_G11F_B10F: 00337 case TF_ALPHA16F: 00338 case TF_ALPHA32F: 00339 case TF_INTENSITY16F: 00340 case TF_INTENSITY32F: 00341 case TF_LUMINANCE16F: 00342 case TF_LUMINANCE32F: 00343 case TF_LUMINANCE_ALPHA16F: 00344 case TF_LUMINANCE_ALPHA32F: 00345 case TF_DEPTH_COMPONENT32F: 00346 return GL_FLOAT; 00347 00348 case TF_DEPTH32F_STENCIL8: 00349 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV; 00350 00351 default: 00352 return GL_UNSIGNED_BYTE; 00353 } 00354 } 00355 } 00356 //----------------------------------------------------------------------------- 00357 // Texture 00358 //----------------------------------------------------------------------------- 00359 void Texture::destroyTexture() 00360 { 00361 if (mHandle) 00362 glDeleteTextures(1, &mHandle); 00363 reset(); 00364 // getTexParameter()->mDirty = true; 00365 } 00366 //----------------------------------------------------------------------------- 00367 Texture::~Texture() 00368 { 00369 destroyTexture(); 00370 } 00371 //----------------------------------------------------------------------------- 00372 void Texture::reset() 00373 { 00374 setDimension(TD_TEXTURE_UNKNOWN); 00375 setInternalFormat(TF_UNKNOWN); 00376 setBorder(0); 00377 setWidth(0); 00378 setHeight(0); 00379 setDepth(0); 00380 mHandle = 0; 00381 mSetupParams = NULL; 00382 mBufferObject = NULL; 00383 mSamples = 0; 00384 mFixedSamplesLocation = true; 00385 } 00386 //----------------------------------------------------------------------------- 00387 Texture::Texture(int width, ETextureFormat format, bool border) 00388 { 00389 VL_DEBUG_SET_OBJECT_NAME() 00390 mTexParameter = new TexParameter; 00391 reset(); 00392 if (!createTexture(vl::TD_TEXTURE_1D, format, width, 0, 0, border, NULL, 0, 0)) 00393 { 00394 Log::error("1D texture creation failed!\n"); 00395 } 00396 } 00397 //----------------------------------------------------------------------------- 00398 Texture::Texture(int width, int height, ETextureFormat format, bool border) 00399 { 00400 VL_DEBUG_SET_OBJECT_NAME() 00401 mTexParameter = new TexParameter; 00402 reset(); 00403 if (!createTexture(vl::TD_TEXTURE_2D, format, width, height, 0, border, NULL, 0, 0)) 00404 { 00405 Log::error("2D texture constructor failed!\n"); 00406 } 00407 } 00408 //----------------------------------------------------------------------------- 00409 Texture::Texture(int width, int height, int depth, ETextureFormat format, bool border) 00410 { 00411 VL_DEBUG_SET_OBJECT_NAME() 00412 mTexParameter = new TexParameter; 00413 reset(); 00414 if (!createTexture(vl::TD_TEXTURE_3D, format, width, height, depth, border, NULL, 0, 0)) 00415 { 00416 Log::error("3D texture constructor failed!\n"); 00417 } 00418 } 00419 //----------------------------------------------------------------------------- 00420 Texture::Texture(const Image* image, ETextureFormat format, bool mipmaps , bool border) 00421 { 00422 VL_DEBUG_SET_OBJECT_NAME() 00423 mTexParameter = new TexParameter; 00424 reset(); 00425 00426 if (image && image->isValid()) 00427 { 00428 switch(image->dimension()) 00429 { 00430 #if defined(VL_OPENGL) 00431 case ID_1D: prepareTexture1D(image, format, mipmaps, border); break; 00432 #else 00433 case ID_1D: prepareTexture2D(image, format, mipmaps, border); break; 00434 #endif 00435 case ID_2D: prepareTexture2D(image, format, mipmaps, border); break; 00436 case ID_3D: prepareTexture3D(image, format, mipmaps, border); break; 00437 case ID_Cubemap: prepareTextureCubemap(image, format, mipmaps, border); break; 00438 default: 00439 break; 00440 } 00441 if( !createTexture() ) 00442 Log::error("Texture constructor failed!\n"); 00443 } 00444 else 00445 Log::bug("Texture constructor called with an invalid Image!\n"); 00446 } 00447 //----------------------------------------------------------------------------- 00448 Texture::Texture(const String& image_path, ETextureFormat format, bool mipmaps , bool border) 00449 { 00450 VL_DEBUG_SET_OBJECT_NAME() 00451 mTexParameter = new TexParameter; 00452 reset(); 00453 00454 ref<Image> image = vl::loadImage(image_path); 00455 00456 if (image && image->isValid()) 00457 { 00458 switch(image->dimension()) 00459 { 00460 #if defined(VL_OPENGL) 00461 case ID_1D: prepareTexture1D(image.get(), format, mipmaps, border); break; 00462 #else 00463 case ID_1D: prepareTexture2D(image.get(), format, mipmaps, border); break; 00464 #endif 00465 case ID_2D: prepareTexture2D(image.get(), format, mipmaps, border); break; 00466 case ID_3D: prepareTexture3D(image.get(), format, mipmaps, border); break; 00467 case ID_Cubemap: prepareTextureCubemap(image.get(), format, mipmaps, border); break; 00468 default: 00469 break; 00470 } 00471 if( !createTexture() ) 00472 Log::error("Texture constructor failed!\n"); 00473 } 00474 else 00475 Log::bug("Texture constructor called with an invalid Image!\n"); 00476 } 00477 //----------------------------------------------------------------------------- 00478 Texture::Texture() 00479 { 00480 VL_DEBUG_SET_OBJECT_NAME() 00481 mTexParameter = new TexParameter; 00482 reset(); 00483 } 00484 //----------------------------------------------------------------------------- 00485 bool Texture::isValid() const 00486 { 00487 bool a = mWidth != 0 && mHeight == 0 && mDepth == 0; 00488 bool b = mWidth != 0 && mHeight != 0 && mDepth == 0; 00489 bool c = mWidth != 0 && mHeight != 0 && mDepth != 0; 00490 return handle() != 0 && (a|b|c); 00491 } 00492 //----------------------------------------------------------------------------- 00493 bool Texture::supports(ETextureDimension tex_dimension, ETextureFormat tex_format, int mip_level, EImageDimension img_dimension, int w, int h, int d, bool border, int samples, bool fixedsamplelocations, bool verbose) 00494 { 00495 VL_CHECK_OGL(); 00496 00497 // clear errors 00498 00499 glGetError(); 00500 00501 // texture buffer 00502 00503 if ( tex_dimension == TD_TEXTURE_2D_MULTISAMPLE || tex_dimension == TD_TEXTURE_2D_MULTISAMPLE_ARRAY ) 00504 { 00505 if (!Has_Texture_Multisample) 00506 { 00507 if (verbose) Log::error("Texture::supports(): multisample textures not supported by the current hardware.\n"); 00508 return false; 00509 } 00510 00511 if (border) 00512 { 00513 if (verbose) Log::error("Texture::supports(): multisample textures cannot have borders.\n"); 00514 return false; 00515 } 00516 00517 if (mip_level) 00518 { 00519 if (verbose) Log::error("Texture::supports(): multisample textures cannot have mip levels other than 0.\n"); 00520 return false; 00521 } 00522 00523 // these should be non zero 00524 VL_CHECK( w && h ); 00525 } 00526 00527 if ( tex_dimension == TD_TEXTURE_BUFFER ) 00528 { 00529 if (!Has_Texture_Buffer) 00530 { 00531 if (verbose) Log::error("Texture::supports(): texture buffer not supported by the current hardware.\n"); 00532 return false; 00533 } 00534 00535 if (border) 00536 { 00537 if (verbose) Log::error("Texture::supports(): a texture buffer cannot have borders.\n"); 00538 return false; 00539 } 00540 00541 if (mip_level) 00542 { 00543 if (verbose) Log::error("Texture::supports(): a texture buffer cannot have mip levels other than 0.\n"); 00544 return false; 00545 } 00546 00547 // these should be zero 00548 VL_CHECK( !(w||h||d) ); 00549 } 00550 00551 // cubemaps 00552 00553 if ( tex_dimension == TD_TEXTURE_CUBE_MAP ) 00554 { 00555 if (!Has_Cubemap_Textures) 00556 { 00557 if (verbose) Log::error("Texture::supports(): texture cubemap not supported by the current hardware.\n"); 00558 return false; 00559 } 00560 00561 if ( w != h ) 00562 { 00563 if (verbose) Log::error("Texture::supports(): cubemaps must have square faces.\n"); 00564 return false; 00565 } 00566 } 00567 00568 // texture arrays 00569 00570 if ( tex_dimension == TD_TEXTURE_1D_ARRAY || tex_dimension == TD_TEXTURE_2D_ARRAY ) 00571 { 00572 if (border) 00573 { 00574 if (verbose) Log::error("Texture::supports(): you cannot create a texture array with borders.\n"); 00575 return false; 00576 } 00577 00578 if(!Has_Texture_Array) 00579 { 00580 if (verbose) Log::error("Texture::supports(): texture array not supported by the current hardware.\n"); 00581 return false; 00582 } 00583 00584 if ( img_dimension ) 00585 { 00586 if ( (img_dimension != ID_2D && tex_dimension == TD_TEXTURE_1D_ARRAY) || ( img_dimension != ID_3D && tex_dimension == TD_TEXTURE_2D_ARRAY ) ) 00587 { 00588 if (verbose) Log::error("Texture::supports(): the image dimensions are not suitable to create a texture array." 00589 "To create a 1D texture array you need a 2D image and to create a 2D texture array you need a 3D image.\n"); 00590 return false; 00591 } 00592 } 00593 } 00594 00595 // texture rectangle 00596 00597 if (tex_dimension == TD_TEXTURE_RECTANGLE) 00598 { 00599 if (!Has_Texture_Rectangle) 00600 { 00601 if (verbose) Log::error("Texture::supports(): texture rectangle not supported by the current hardware.\n"); 00602 return false; 00603 } 00604 00605 if ( mip_level != 0 ) 00606 { 00607 if (verbose) Log::error("Texture::supports(): TD_TEXTURE_RECTANGLE textures do not support mipmapping level other than zero.\n"); 00608 return false; 00609 } 00610 00611 if (border) 00612 { 00613 if (verbose) Log::error("Texture::supports(): TD_TEXTURE_RECTANGLE textures do not allow textures borders\n"); 00614 return false; 00615 } 00616 } 00617 00618 // OpenGL ES does not support proxy textures and glGetTexLevelParameter* 00619 #if defined(VL_OPENGL) 00620 int width = 0; 00621 00622 int default_format = getDefaultFormat(tex_format); 00623 int default_type = getDefaultType(tex_format); 00624 00625 if (tex_dimension == TD_TEXTURE_BUFFER) 00626 { 00627 width = 1; // pass the test 00628 } 00629 else 00630 if (tex_dimension == TD_TEXTURE_2D_MULTISAMPLE) 00631 { 00632 glTexImage2DMultisample(GL_PROXY_TEXTURE_2D_MULTISAMPLE, samples, tex_format, w, h, fixedsamplelocations ); 00633 if ( glGetError() ) 00634 { 00635 if (verbose) Log::error( Say("Texture::supports(): 2d multisample texture requested with too many samples for the current hardware! (%n)\n") << samples ); 00636 return false; 00637 } 00638 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_WIDTH, &width); VL_CHECK_OGL(); 00639 } 00640 else 00641 if (tex_dimension == TD_TEXTURE_2D_MULTISAMPLE_ARRAY) 00642 { 00643 glTexImage3DMultisample(GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY, samples, tex_format, w, h, d, fixedsamplelocations ); VL_CHECK_OGL(); 00644 if ( glGetError() ) 00645 { 00646 if (verbose) Log::error( Say("Texture::supports(): multisample texture array requested with too many samples for the current hardware! (%n)\n") << samples ); 00647 return false; 00648 } 00649 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY, 0, GL_TEXTURE_WIDTH, &width); VL_CHECK_OGL(); 00650 } 00651 else 00652 if (tex_dimension == TD_TEXTURE_CUBE_MAP) 00653 { 00654 glTexImage2D(GL_PROXY_TEXTURE_CUBE_MAP, mip_level, tex_format, w + (border?2:0), h + (border?2:0), border?1:0, default_format, default_type, NULL); 00655 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_CUBE_MAP, mip_level, GL_TEXTURE_WIDTH, &width); 00656 } 00657 else 00658 if (tex_dimension == TD_TEXTURE_2D_ARRAY) 00659 { 00660 glTexImage3D(GL_PROXY_TEXTURE_2D_ARRAY, mip_level, tex_format, w + (border?2:0), h + (border?2:0), d + (border?2:0), border?1:0, default_format, default_type, NULL); 00661 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D_ARRAY, mip_level, GL_TEXTURE_WIDTH, &width); 00662 } 00663 else 00664 if (tex_dimension == TD_TEXTURE_3D) 00665 { 00666 glTexImage3D(GL_PROXY_TEXTURE_3D, mip_level, tex_format, w + (border?2:0), h + (border?2:0), d + (border?2:0), border?1:0, default_format, default_type, NULL); 00667 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, mip_level, GL_TEXTURE_WIDTH, &width); 00668 } 00669 else 00670 if (tex_dimension == TD_TEXTURE_RECTANGLE) 00671 { 00672 glTexImage2D(GL_PROXY_TEXTURE_RECTANGLE, mip_level, tex_format, w, h, 0, default_format, default_type, NULL); 00673 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_RECTANGLE, mip_level, GL_TEXTURE_WIDTH, &width); 00674 } 00675 else 00676 if (tex_dimension == TD_TEXTURE_1D_ARRAY) 00677 { 00678 glTexImage2D(GL_PROXY_TEXTURE_1D_ARRAY, mip_level, tex_format, w, h, 0, default_format, default_type, NULL); 00679 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_1D_ARRAY, mip_level, GL_TEXTURE_WIDTH, &width); 00680 } 00681 else 00682 if (tex_dimension == TD_TEXTURE_2D) 00683 { 00684 glTexImage2D(GL_PROXY_TEXTURE_2D, mip_level, tex_format, w + (border?2:0), h + (border?2:0), border?1:0, default_format, default_type, NULL); 00685 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, mip_level, GL_TEXTURE_WIDTH, &width); 00686 } 00687 else 00688 if (tex_dimension == TD_TEXTURE_1D) 00689 { 00690 glTexImage1D(GL_PROXY_TEXTURE_1D, mip_level, tex_format, w + (border?2:0), border?1:0, default_format, default_type, NULL); 00691 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_1D, mip_level, GL_TEXTURE_WIDTH, &width); 00692 } 00693 00694 GLenum err = glGetError(); 00695 return err == 0 && width != 0; 00696 #else 00697 return true; 00698 #endif 00699 } 00700 //----------------------------------------------------------------------------- 00701 bool Texture::createTexture(ETextureDimension tex_dimension, ETextureFormat tex_format, int w, int h, int d, bool border, BufferObject* buffer_object, int samples, bool fixedsamplelocations) 00702 { 00703 VL_CHECK_OGL() 00704 00705 if ( tex_dimension == TD_TEXTURE_BUFFER ) 00706 { 00707 if( !buffer_object || !buffer_object->handle() || !glIsBuffer(buffer_object->handle()) ) 00708 { 00709 Log::bug( "Texture::createTexture() requires a non NULL valid buffer object in order to create a texture buffer!\n" ); 00710 VL_CHECK(buffer_object); 00711 VL_CHECK(buffer_object->handle()); 00712 VL_CHECK(glIsBuffer(buffer_object->handle())); 00713 return false; 00714 } 00715 else 00716 { 00717 // the buffer object must not be empty! 00718 GLint buffer_size = 0; 00719 glBindBuffer(GL_TEXTURE_BUFFER, buffer_object->handle()); 00720 glGetBufferParameteriv(GL_TEXTURE_BUFFER, GL_BUFFER_SIZE, &buffer_size); 00721 glBindBuffer(GL_TEXTURE_BUFFER, 0); 00722 if ( buffer_size == 0 ) 00723 { 00724 Log::bug("Texture::createTexture(): cannot create a texture buffer with an empty buffer object!\n"); VL_TRAP(); 00725 return false; 00726 } 00727 } 00728 } 00729 00730 if (mHandle) 00731 { 00732 Log::bug("Texture::createTexture(): a texture can be created only once!\n"); 00733 return false; 00734 } 00735 else 00736 { 00737 if ( !supports(tex_dimension , tex_format, 0, ID_None, w, h, d, border, samples, fixedsamplelocations, true) ) 00738 { 00739 VL_CHECK_OGL() 00740 Log::bug("Texture::createTexture(): the format/size combination requested is not supported!\n"); VL_TRAP(); 00741 return false; 00742 } 00743 00744 reset(); 00745 00746 glGenTextures( 1, &mHandle ); VL_CHECK_OGL(); 00747 00748 if (!mHandle) 00749 { 00750 Log::bug("Texture::createTexture(): texture creation failed!\n"); 00751 VL_TRAP(); 00752 return false; 00753 } 00754 00755 setDimension(tex_dimension); 00756 setInternalFormat(tex_format); 00757 setWidth(w); 00758 setHeight(h); 00759 setDepth(d); 00760 setBorder(border); 00761 mBufferObject = buffer_object; // the user cannot change this 00762 mSamples = samples; 00763 mFixedSamplesLocation = fixedsamplelocations; 00764 glBindTexture(tex_dimension, mHandle); VL_CHECK_OGL(); 00765 00766 int default_format = getDefaultFormat(tex_format); 00767 int default_type = getDefaultType(tex_format); 00768 00769 if (tex_dimension == TD_TEXTURE_2D_MULTISAMPLE) 00770 { 00771 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, tex_format, w, h, fixedsamplelocations ); VL_CHECK_OGL(); 00772 } 00773 else 00774 if (tex_dimension == TD_TEXTURE_2D_MULTISAMPLE_ARRAY) 00775 { 00776 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, samples, tex_format, w, h, d, fixedsamplelocations ); VL_CHECK_OGL(); 00777 } 00778 else 00779 if (tex_dimension == TD_TEXTURE_BUFFER) 00780 { 00781 VL_CHECK(buffer_object) 00782 VL_CHECK(buffer_object->handle()) 00783 glTexBuffer(GL_TEXTURE_BUFFER, tex_format, buffer_object->handle()); 00784 unsigned int glerr = glGetError(); 00785 if (glerr != GL_NO_ERROR) 00786 { 00787 String msg( (const char*)getGLErrorString(glerr) ); 00788 Log::bug( "Texture::createTexture(): glTexBuffer() failed with error: '" + msg + "'.\n" ); 00789 Log::error("Probably you supplied a non supported texture format! Review the glTexBuffer() man page for a complete list of supported texture formats.\n"); 00790 VL_TRAP(); 00791 } 00792 } 00793 else 00794 if (tex_dimension == TD_TEXTURE_CUBE_MAP) 00795 { 00796 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, tex_format, w + (border?2:0), h + (border?2:0), border?1:0, default_format, default_type, NULL); 00797 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, tex_format, w + (border?2:0), h + (border?2:0), border?1:0, default_format, default_type, NULL); 00798 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, tex_format, w + (border?2:0), h + (border?2:0), border?1:0, default_format, default_type, NULL); 00799 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, tex_format, w + (border?2:0), h + (border?2:0), border?1:0, default_format, default_type, NULL); 00800 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, tex_format, w + (border?2:0), h + (border?2:0), border?1:0, default_format, default_type, NULL); 00801 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, tex_format, w + (border?2:0), h + (border?2:0), border?1:0, default_format, default_type, NULL); 00802 VL_CHECK_OGL(); 00803 } 00804 else 00805 if (tex_dimension == TD_TEXTURE_2D_ARRAY) 00806 { 00807 VL_glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, tex_format, w + (border?2:0), h + (border?2:0), d + (border?2:0), border?1:0, default_format, default_type, NULL); 00808 VL_CHECK_OGL(); 00809 } 00810 else 00811 if (tex_dimension == TD_TEXTURE_3D) 00812 { 00813 VL_glTexImage3D(GL_TEXTURE_3D, 0, tex_format, w + (border?2:0), h + (border?2:0), d + (border?2:0), border?1:0, default_format, default_type, NULL); 00814 VL_CHECK_OGL(); 00815 } 00816 else 00817 if (tex_dimension == TD_TEXTURE_RECTANGLE) 00818 { 00819 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, tex_format, w, h, 0, default_format, default_type, NULL); 00820 VL_CHECK_OGL(); 00821 } 00822 else 00823 if (tex_dimension == TD_TEXTURE_1D_ARRAY) 00824 { 00825 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, tex_format, w, h, 0, default_format, default_type, NULL); 00826 VL_CHECK_OGL(); 00827 } 00828 else 00829 if (tex_dimension == TD_TEXTURE_2D) 00830 { 00831 glTexImage2D(GL_TEXTURE_2D, 0, tex_format, w + (border?2:0), h + (border?2:0), border?1:0, default_format, default_type, NULL); 00832 VL_CHECK_OGL(); 00833 } 00834 else 00835 if (tex_dimension == TD_TEXTURE_1D) 00836 { 00837 glTexImage1D(GL_TEXTURE_1D, 0, tex_format, w + (border?2:0), border?1:0, default_format, default_type, NULL); 00838 VL_CHECK_OGL(); 00839 } 00840 00841 glBindTexture(tex_dimension, 0); VL_CHECK_OGL(); 00842 return true; 00843 } 00844 } 00845 //----------------------------------------------------------------------------- 00846 bool Texture::setMipLevel(int mip_level, const Image* img, bool gen_mipmaps) 00847 { 00848 VL_CHECK_OGL() 00849 00850 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2) 00851 if (internalFormat() != img->format()) 00852 { 00853 Log::bug("Texture::setMipLevel(): under OpenGL ES the texture internal format must match the source image format!\n"); 00854 return false; 00855 } 00856 #endif 00857 00858 if ( dimension() == TD_TEXTURE_BUFFER || dimension() == TD_TEXTURE_2D_MULTISAMPLE || dimension() == TD_TEXTURE_2D_MULTISAMPLE_ARRAY ) 00859 { 00860 Log::bug("You cannot call Texture::setMipLevel() on a texture buffer or on a multisample texture!\n"); 00861 return false; 00862 } 00863 00864 if (!mHandle) 00865 { 00866 Log::error("Texture::setMipLevel(): texture hasn't been created yet, please call createTexture() first!\n"); 00867 VL_TRAP(); 00868 return false; 00869 } 00870 00871 if ( !supports(dimension(), internalFormat(), mip_level, img->dimension(), img->width(), img->height(), img->depth(), border(), 0, 0, true) ) 00872 { 00873 VL_CHECK_OGL() 00874 Log::error("Texture::setMipLevel(): the format/size combination requested is not supported.\n"); 00875 return false; 00876 } 00877 00878 glPixelStorei( GL_UNPACK_ALIGNMENT, img->byteAlignment() ); VL_CHECK_OGL() 00879 00880 glBindTexture( dimension(), mHandle ); VL_CHECK_OGL() 00881 00882 int w = width() + (border()?2:0); 00883 int h = height() + (border()?2:0); 00884 int d = depth() + (border()?2:0); 00885 int is_compressed = (int)img->format() == (int)internalFormat() && isCompressedFormat( internalFormat() ); 00886 00887 bool use_glu = false; 00888 GLint generate_mipmap_orig = GL_FALSE; 00889 if ( gen_mipmaps ) 00890 { 00891 if ( Has_glGenerateMipmaps ) 00892 { 00893 // do nothing, we will use glGenerateMipmaps later 00894 } 00895 else 00896 if( Has_GL_GENERATE_MIPMAP ) 00897 { 00898 glGetTexParameteriv( dimension(), GL_GENERATE_MIPMAP, &generate_mipmap_orig ); VL_CHECK_OGL() 00899 glTexParameteri(dimension(), GL_GENERATE_MIPMAP, GL_TRUE); VL_CHECK_OGL() 00900 } 00901 else 00902 { 00903 if (mip_level > 0) // because GLU regenerates the whole mip-mapping chain 00904 Log::error("Texture::setMipLevel(): automatic mipmaps generation for levels below 0 requires OpenGL 1.4 minimum.\n"); 00905 else 00906 use_glu = true; 00907 00908 #define VL_IS_POW_2(x) ((x != 0) && ((x & (x - 1)) == 0)) 00909 if ( !VL_IS_POW_2(w) || !VL_IS_POW_2(h) ) 00910 Log::warning("Texture::setMipLevel(): the image will be rescaled to the nearest upper power of 2.\n"); 00911 } 00912 } 00913 00914 if ( use_glu && is_compressed ) 00915 { 00916 Log::error("Texture::setMipLevel(): could not generate compressed mipmaps, OpenGL 1.4 required.\n"); 00917 use_glu = false; 00918 } 00919 00920 if ( use_glu && dimension() == TD_TEXTURE_3D ) 00921 { 00922 Log::error("Texture::setMipLevel(): could not generate 3D mipmaps, OpenGL 1.4 required.\n"); 00923 use_glu = false; 00924 } 00925 00926 if (dimension() == TD_TEXTURE_CUBE_MAP) 00927 { 00928 if (is_compressed) 00929 { 00930 VL_CHECK( img->requiredMemory() % 6 == 0 ); 00931 int bytes = img->requiredMemory() / 6; 00932 glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, mip_level, internalFormat(), w, h, border()?1:0, bytes, img->pixelsXP()); 00933 glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, mip_level, internalFormat(), w, h, border()?1:0, bytes, img->pixelsXN()); 00934 glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mip_level, internalFormat(), w, h, border()?1:0, bytes, img->pixelsYP()); 00935 glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mip_level, internalFormat(), w, h, border()?1:0, bytes, img->pixelsYN()); 00936 glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, mip_level, internalFormat(), w, h, border()?1:0, bytes, img->pixelsZP()); 00937 glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, mip_level, internalFormat(), w, h, border()?1:0, bytes, img->pixelsZN()); 00938 VL_CHECK_OGL() 00939 } 00940 else 00941 { 00942 if (use_glu) 00943 { 00944 gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_X, internalFormat(), w, h, img->format(), img->type(), img->pixelsXP()); 00945 gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, internalFormat(), w, h, img->format(), img->type(), img->pixelsXN()); 00946 gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, internalFormat(), w, h, img->format(), img->type(), img->pixelsYP()); 00947 gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, internalFormat(), w, h, img->format(), img->type(), img->pixelsYN()); 00948 gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, internalFormat(), w, h, img->format(), img->type(), img->pixelsZP()); 00949 gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, internalFormat(), w, h, img->format(), img->type(), img->pixelsZN()); 00950 VL_CHECK_OGL() 00951 } 00952 else 00953 { 00954 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, mip_level, internalFormat(), w, h, border()?1:0, img->format(), img->type(), img->pixelsXP()); 00955 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, mip_level, internalFormat(), w, h, border()?1:0, img->format(), img->type(), img->pixelsXN()); 00956 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mip_level, internalFormat(), w, h, border()?1:0, img->format(), img->type(), img->pixelsYP()); 00957 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mip_level, internalFormat(), w, h, border()?1:0, img->format(), img->type(), img->pixelsYN()); 00958 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, mip_level, internalFormat(), w, h, border()?1:0, img->format(), img->type(), img->pixelsZP()); 00959 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, mip_level, internalFormat(), w, h, border()?1:0, img->format(), img->type(), img->pixelsZN()); 00960 VL_CHECK_OGL() 00961 } 00962 } 00963 } 00964 else 00965 if (dimension() == TD_TEXTURE_2D_ARRAY) 00966 { 00967 if (is_compressed) 00968 { 00969 VL_glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, mip_level, internalFormat(), w, h, d, border()?1:0, img->requiredMemory(), img->pixels()); 00970 VL_CHECK_OGL() 00971 } 00972 else 00973 { 00974 VL_glTexImage3D(GL_TEXTURE_2D_ARRAY, mip_level, internalFormat(), w, h, d, border()?1:0, img->format(), img->type(), img->pixels()); 00975 VL_CHECK_OGL() 00976 } 00977 } 00978 else 00979 if (dimension() == TD_TEXTURE_3D) 00980 { 00981 if (is_compressed) 00982 { 00983 VL_glCompressedTexImage3D(GL_TEXTURE_3D, mip_level, internalFormat(), w, h, d, border()?1:0, img->requiredMemory(), img->pixels()); 00984 VL_CHECK_OGL() 00985 } 00986 else 00987 { 00988 VL_glTexImage3D(GL_TEXTURE_3D, mip_level, internalFormat(), w, h, d, border()?1:0, img->format(), img->type(), img->pixels()); 00989 VL_CHECK_OGL() 00990 } 00991 } 00992 else 00993 if (dimension() == TD_TEXTURE_RECTANGLE) 00994 { 00995 if (is_compressed) 00996 { 00997 glCompressedTexImage2D(GL_TEXTURE_RECTANGLE, mip_level, internalFormat(), width(), height(), 0, img->requiredMemory(), img->pixels()); 00998 VL_CHECK_OGL() 00999 } 01000 else 01001 { 01002 glTexImage2D(GL_TEXTURE_RECTANGLE, mip_level, internalFormat(), width(), height(), 0, img->format(), img->type(), img->pixels()); 01003 VL_CHECK_OGL() 01004 } 01005 } 01006 else 01007 if (dimension() == TD_TEXTURE_1D_ARRAY) 01008 { 01009 if (is_compressed) 01010 { 01011 glCompressedTexImage2D(GL_TEXTURE_1D_ARRAY, mip_level, internalFormat(), width(), height(), 0, img->requiredMemory(), img->pixels()); 01012 VL_CHECK_OGL() 01013 } 01014 else 01015 { 01016 glTexImage2D(GL_TEXTURE_1D_ARRAY, mip_level, internalFormat(), width(), height(), 0, img->format(), img->type(), img->pixels()); 01017 VL_CHECK_OGL() 01018 } 01019 } 01020 else 01021 if (dimension() == TD_TEXTURE_2D) 01022 { 01023 if (is_compressed) 01024 { 01025 glCompressedTexImage2D(GL_TEXTURE_2D, mip_level, internalFormat(), w, h, border()?1:0, img->requiredMemory(), img->pixels()); 01026 VL_CHECK_OGL() 01027 } 01028 else 01029 { 01030 if (use_glu) 01031 { 01032 gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat(), w, h, img->format(), img->type(), img->pixels()); 01033 VL_CHECK_OGL() 01034 } 01035 else 01036 { 01037 glTexImage2D(GL_TEXTURE_2D, mip_level, internalFormat(), w, h, border()?1:0, img->format(), img->type(), img->pixels()); 01038 VL_CHECK_OGL() 01039 } 01040 } 01041 } 01042 else 01043 if (dimension() == TD_TEXTURE_1D) 01044 { 01045 if (is_compressed) 01046 { 01047 glCompressedTexImage1D(GL_TEXTURE_1D, mip_level, internalFormat(), w, border()?1:0, img->requiredMemory(), img->pixels()); 01048 VL_CHECK_OGL() 01049 } 01050 else 01051 { 01052 if (use_glu) 01053 { 01054 gluBuild1DMipmaps(GL_TEXTURE_1D, internalFormat(), w, img->format(), img->type(), img->pixels()); 01055 VL_CHECK_OGL() 01056 } 01057 else 01058 { 01059 glTexImage1D(GL_TEXTURE_1D, mip_level, internalFormat(), w, border()?1:0, img->format(), img->type(), img->pixels()); 01060 VL_CHECK_OGL() 01061 } 01062 } 01063 } 01064 01065 if ( gen_mipmaps ) 01066 { 01067 if ( Has_glGenerateMipmaps ) 01068 { 01069 glGenerateMipmap( dimension() ); 01070 } 01071 else 01072 if ( Has_GL_GENERATE_MIPMAP ) 01073 { 01074 glTexParameteri(dimension(), GL_GENERATE_MIPMAP, generate_mipmap_orig); VL_CHECK_OGL() 01075 } 01076 } 01077 01078 glBindTexture( dimension(), 0 ); VL_CHECK_OGL() 01079 01080 glPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); 01081 01082 return true; 01083 } 01084 //----------------------------------------------------------------------------- 01085 bool Texture::createTexture() 01086 { 01087 VL_CHECK_OGL() 01088 01089 if (!setupParams()) 01090 return false; 01091 01092 class InOutCondition 01093 { 01094 Texture* mTex; 01095 public: 01096 InOutCondition(Texture* tex): mTex(tex) {} 01097 ~InOutCondition() 01098 { 01099 // make sure no errors were generated 01100 VL_CHECK_OGL() 01101 01102 // release Image and BufferObject from SetupParams 01103 if (mTex->mSetupParams) 01104 { 01105 if (mTex->mSetupParams->imagePath().empty() && mTex->mSetupParams->image()) 01106 mTex->mSetupParams->setImagePath( mTex->mSetupParams->image()->filePath() ); 01107 mTex->mSetupParams->setImage(NULL); 01108 mTex->mSetupParams->setBufferObject(NULL); 01109 } 01110 } 01111 }; 01112 01113 InOutCondition in_out_condition(this); 01114 01115 ETextureFormat tex_format = setupParams()->format(); 01116 ETextureDimension tex_dimension = setupParams()->dimension(); 01117 bool gen_mipmaps = setupParams()->genMipmaps(); 01118 bool border = setupParams()->border(); 01119 if ( !setupParams()->image() && !setupParams()->imagePath().empty() ) 01120 { 01121 setupParams()->setImage( loadImage( setupParams()->imagePath() ).get() ); 01122 if (!setupParams()->image()) 01123 { 01124 vl::Log::error( Say("Texture::createTexture(): could not load image file '%s'\n") << setupParams()->imagePath() ); 01125 return false; 01126 } 01127 } 01128 01129 ref<Image> img = const_cast<Image*>(setupParams()->image()); 01130 01131 int w = setupParams()->width(); 01132 int h = setupParams()->height(); 01133 int d = setupParams()->depth(); 01134 if (img) 01135 { 01136 setObjectName( img->objectName().c_str() ); 01137 w = img->width(); 01138 h = img->height(); 01139 d = img->depth(); 01140 // guess from image format 01141 if (tex_format == TF_UNKNOWN) 01142 tex_format = (ETextureFormat)img->format(); 01143 } 01144 //w = w > 0 ? w : 1; 01145 //h = h > 0 ? h : 1; 01146 //d = d > 0 ? d : 1; 01147 01148 if ( !createTexture( tex_dimension, tex_format, w, h, d, border, setupParams()->bufferObject(), setupParams()->samples(), setupParams()->fixedSamplesLocations() ) ) 01149 return false; 01150 01151 VL_CHECK_OGL() 01152 01153 if (img) 01154 { 01155 // compile mipmapping levels 01156 std::vector<const vl::Image*> mipmaps; 01157 mipmaps.push_back(img.get()); 01158 for(int i=0; i<(int)img->mipmaps().size(); ++i) 01159 mipmaps.push_back( img->mipmaps()[i].get() ); 01160 01161 bool ok = false; 01162 01163 if (!gen_mipmaps) // no mipmaps 01164 { 01165 ok = setMipLevel(0, img.get(), false); 01166 } 01167 else 01168 { 01169 if (mipmaps.size() > 1) // explicit mipmaps 01170 { 01171 for(int i=0; i<(int)mipmaps.size(); ++i) 01172 ok = setMipLevel(i, mipmaps[i], false); 01173 } 01174 else // automatic mipmaps generation 01175 if (mipmaps.size() == 1) 01176 { 01177 ok = setMipLevel(0, img.get(), true); 01178 } 01179 } 01180 return ok; 01181 } 01182 else 01183 return true; 01184 } 01185 //----------------------------------------------------------------------------- 01186 void Texture::clone(const Texture& other) 01187 { 01188 // keep its own copyof SetupParams 01189 if (other.mSetupParams) 01190 mSetupParams = new SetupParams(*other.mSetupParams); 01191 else 01192 mSetupParams = NULL; 01193 mHandle = other.mHandle; 01194 mTexParameter = other.mTexParameter; 01195 mBufferObject = other.mBufferObject; 01196 mFormat = other.mFormat; 01197 mDimension = other.mDimension; 01198 mWidth = other.mWidth; 01199 mHeight = other.mHeight; 01200 mDepth = other.mDepth; 01201 mSamples = other.mSamples; 01202 mBorder = other.mBorder; 01203 mFixedSamplesLocation = other.mFixedSamplesLocation; 01204 } 01205 //----------------------------------------------------------------------------- 01206 bool Texture::isDepthTexture() const 01207 { 01208 switch(internalFormat()) 01209 { 01210 case TF_DEPTH_STENCIL: 01211 case TF_DEPTH24_STENCIL8: 01212 01213 case TF_DEPTH_COMPONENT32F: 01214 case TF_DEPTH32F_STENCIL8: 01215 01216 case TF_DEPTH_COMPONENT: 01217 case TF_DEPTH_COMPONENT16: 01218 case TF_DEPTH_COMPONENT24: 01219 case TF_DEPTH_COMPONENT32: 01220 return true; 01221 01222 default: 01223 return false; 01224 } 01225 } 01226 //----------------------------------------------------------------------------- 01227 bool Texture::isCompressedFormat(int format) 01228 { 01229 int comp[] = 01230 { 01231 TF_COMPRESSED_ALPHA, 01232 TF_COMPRESSED_INTENSITY, 01233 TF_COMPRESSED_LUMINANCE, 01234 TF_COMPRESSED_LUMINANCE_ALPHA, 01235 TF_COMPRESSED_RGB, 01236 TF_COMPRESSED_RGBA, 01237 01238 // 3DFX_texture_compression_FXT1 01239 TF_COMPRESSED_RGB_FXT1_3DFX, 01240 TF_COMPRESSED_RGBA_FXT1_3DFX, 01241 01242 // EXT_texture_compression_s3tc 01243 TF_COMPRESSED_RGB_S3TC_DXT1_EXT, 01244 TF_COMPRESSED_RGBA_S3TC_DXT1_EXT, 01245 TF_COMPRESSED_RGBA_S3TC_DXT3_EXT, 01246 TF_COMPRESSED_RGBA_S3TC_DXT5_EXT, 01247 01248 // GL_EXT_texture_compression_latc 01249 TF_COMPRESSED_LUMINANCE_LATC1_EXT, 01250 TF_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT, 01251 TF_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, 01252 TF_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT, 01253 01254 // EXT_texture_compression_rgtc 01255 TF_COMPRESSED_RED_RGTC1_EXT, 01256 TF_COMPRESSED_SIGNED_RED_RGTC1_EXT, 01257 TF_COMPRESSED_RED_GREEN_RGTC2_EXT, 01258 TF_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 01259 01260 0 01261 }; 01262 01263 for(int i=0; comp[i]; ++i) 01264 { 01265 if(comp[i] == format) 01266 return true; 01267 } 01268 01269 return false; 01270 } 01271 //-----------------------------------------------------------------------------