Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/Texture.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.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 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:42.
Permission is granted to use this page to write and publish articles regarding Visualization Library.