2003-01-22 00:45:36 +08:00
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
*
* This library is open source and may be redistributed and / or modified under
* the terms of the OpenSceneGraph Public License ( OSGPL ) version 0.0 or
* ( at your option ) any later version . The full license is in LICENSE file
* included with this distribution , and on the openscenegraph . org website .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* OpenSceneGraph Public License for more details .
*/
2002-08-25 03:39:39 +08:00
# include <osg/GLExtensions>
2001-09-20 05:08:56 +08:00
# include <osg/Image>
2002-08-28 23:28:11 +08:00
# include <osg/Texture>
2001-09-20 05:08:56 +08:00
# include <osg/State>
# include <osg/Notify>
2001-10-04 05:44:07 +08:00
# include <osg/GLU>
2003-07-16 17:52:43 +08:00
# include <osg/Timer>
2001-01-11 00:32:10 +08:00
using namespace osg ;
2003-01-10 02:41:01 +08:00
# ifndef GL_TEXTURE_WRAP_R
2003-01-10 00:13:30 +08:00
# define GL_TEXTURE_WRAP_R 0x8072
# endif
2002-08-28 23:28:11 +08:00
2004-03-09 01:09:58 +08:00
# ifndef GL_UNPACK_CLIENT_STORAGE_APPLE
# define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
# endif
# ifndef GL_APPLE_vertex_array_range
# define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
# define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
# define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
# define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
# define GL_STORAGE_CACHED_APPLE 0x85BE
# define GL_STORAGE_SHARED_APPLE 0x85BF
# endif
2003-01-23 07:34:18 +08:00
2003-07-14 22:42:10 +08:00
Texture : : TextureObject * Texture : : TextureObjectManager : : generateTextureObject ( unsigned int /*contextID*/ , GLenum target )
{
GLuint id ;
glGenTextures ( 1L , & id ) ;
return new Texture : : TextureObject ( id , target ) ;
}
Texture : : TextureObject * Texture : : TextureObjectManager : : generateTextureObject ( unsigned int /*contextID*/ ,
GLenum target ,
GLint numMipmapLevels ,
GLenum internalFormat ,
GLsizei width ,
GLsizei height ,
GLsizei depth ,
GLint border )
{
// no useable texture object found so return 0
GLuint id ;
glGenTextures ( 1L , & id ) ;
2003-01-23 07:34:18 +08:00
2003-07-14 22:42:10 +08:00
return new Texture : : TextureObject ( id , target , numMipmapLevels , internalFormat , width , height , depth , border ) ;
}
Texture : : TextureObject * Texture : : TextureObjectManager : : reuseTextureObject ( unsigned int contextID ,
GLenum target ,
GLint numMipmapLevels ,
GLenum internalFormat ,
GLsizei width ,
GLsizei height ,
GLsizei depth ,
GLint border )
2003-01-23 07:34:18 +08:00
{
2004-07-22 03:16:49 +08:00
# ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
# endif
2003-07-14 22:42:10 +08:00
TextureObjectList & tol = _textureObjectListMap [ contextID ] ;
for ( TextureObjectList : : iterator itr = tol . begin ( ) ;
itr ! = tol . end ( ) ;
+ + itr )
2003-01-23 07:34:18 +08:00
{
2003-07-14 22:42:10 +08:00
if ( ( * itr ) - > match ( target , numMipmapLevels , internalFormat , width , height , depth , border ) )
{
// found usable texture object.
Texture : : TextureObject * textureObject = ( * itr ) . release ( ) ;
tol . erase ( itr ) ;
2003-08-15 17:38:36 +08:00
//notify(INFO)<<"reusing texture object "<<textureObject<<std::endl;
2003-07-14 22:42:10 +08:00
return textureObject ;
}
2003-01-23 07:34:18 +08:00
}
2003-07-14 22:42:10 +08:00
return 0 ;
2003-01-23 07:34:18 +08:00
}
2003-07-14 22:42:10 +08:00
2003-01-23 07:34:18 +08:00
2003-07-14 22:42:10 +08:00
void Texture : : TextureObjectManager : : addTextureObjects ( Texture : : TextureObjectListMap & toblm )
2003-01-23 07:34:18 +08:00
{
2004-07-22 03:16:49 +08:00
# ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
# endif
2003-07-14 22:42:10 +08:00
for ( TextureObjectListMap : : iterator itr = toblm . begin ( ) ;
itr ! = toblm . end ( ) ;
+ + itr )
2003-01-23 07:34:18 +08:00
{
2003-07-14 22:42:10 +08:00
TextureObjectList & tol = _textureObjectListMap [ itr - > first ] ;
tol . insert ( tol . end ( ) , itr - > second . begin ( ) , itr - > second . end ( ) ) ;
}
}
void Texture : : TextureObjectManager : : addTextureObjectsFrom ( Texture & texture )
{
2004-07-22 03:16:49 +08:00
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
2003-07-14 22:42:10 +08:00
texture . takeTextureObjects ( _textureObjectListMap ) ;
}
2003-07-16 17:52:43 +08:00
void Texture : : TextureObjectManager : : flushTextureObjects ( unsigned int contextID , double currentTime , double & availableTime )
2003-07-14 22:42:10 +08:00
{
2003-07-16 17:52:43 +08:00
// if no time available don't try to flush objects.
if ( availableTime < = 0.0 ) return ;
2003-07-14 22:42:10 +08:00
2004-07-22 03:16:49 +08:00
2003-07-16 17:52:43 +08:00
const osg : : Timer & timer = * osg : : Timer : : instance ( ) ;
osg : : Timer_t start_tick = timer . tick ( ) ;
double elapsedTime = 0.0 ;
2004-07-22 03:16:49 +08:00
{
# ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
# endif
2003-07-16 17:52:43 +08:00
2004-07-22 03:16:49 +08:00
TextureObjectListMap : : iterator tmitr = _textureObjectListMap . find ( contextID ) ;
if ( tmitr ! = _textureObjectListMap . end ( ) )
2003-07-14 22:42:10 +08:00
{
2004-07-22 03:16:49 +08:00
TextureObjectList & tol = tmitr - > second ;
// reset the time of any uninitialized objects.
TextureObjectList : : iterator itr ;
for ( itr = tol . begin ( ) ;
itr ! = tol . end ( ) ;
+ + itr )
2003-07-16 17:52:43 +08:00
{
2004-07-22 03:16:49 +08:00
if ( ( * itr ) - > _timeStamp = = 0.0 ) ( * itr ) - > _timeStamp = currentTime ;
2003-07-16 17:52:43 +08:00
}
2004-07-22 03:16:49 +08:00
double expiryTime = currentTime - _expiryDelay ;
unsigned int numTexturesDeleted = 0 ;
for ( itr = tol . begin ( ) ;
itr ! = tol . end ( ) & & elapsedTime < availableTime ;
)
2003-07-16 17:52:43 +08:00
{
2004-07-22 03:16:49 +08:00
if ( ( * itr ) - > _timeStamp < expiryTime )
{
glDeleteTextures ( 1L , & ( ( * itr ) - > _id ) ) ;
itr = tol . erase ( itr ) ;
+ + numTexturesDeleted ;
}
else
{
+ + itr ;
}
elapsedTime = timer . delta_s ( start_tick , timer . tick ( ) ) ;
2003-07-16 17:52:43 +08:00
}
2004-07-22 03:16:49 +08:00
if ( numTexturesDeleted ) notify ( osg : : INFO ) < < " Number of Texture's deleted = " < < numTexturesDeleted < < std : : endl ;
}
2003-01-23 07:34:18 +08:00
}
2004-07-22 03:16:49 +08:00
2003-07-16 17:52:43 +08:00
availableTime - = elapsedTime ;
2003-07-14 22:42:10 +08:00
}
static ref_ptr < Texture : : TextureObjectManager > s_textureObjectManager ;
void Texture : : setTextureObjectManager ( Texture : : TextureObjectManager * tom )
{
s_textureObjectManager = tom ;
}
Texture : : TextureObjectManager * Texture : : getTextureObjectManager ( )
{
if ( ! s_textureObjectManager ) s_textureObjectManager = new Texture : : TextureObjectManager ;
return s_textureObjectManager . get ( ) ;
2003-01-23 07:34:18 +08:00
}
2003-07-16 05:19:03 +08:00
void Texture : : flushTextureObjects ( unsigned int contextID , double currentTime , double & availbleTime )
{
getTextureObjectManager ( ) - > flushTextureObjects ( contextID , currentTime , availbleTime ) ;
}
2003-01-23 07:34:18 +08:00
2002-07-21 09:29:11 +08:00
Texture : : Texture ( ) :
2003-12-16 07:22:35 +08:00
_wrap_s ( CLAMP ) ,
_wrap_t ( CLAMP ) ,
_wrap_r ( CLAMP ) ,
2002-08-28 23:28:11 +08:00
_min_filter ( LINEAR_MIPMAP_LINEAR ) , // trilinear
_mag_filter ( LINEAR ) ,
_maxAnisotropy ( 1.0f ) ,
2003-04-07 20:51:00 +08:00
_useHardwareMipMapGeneration ( true ) ,
_unrefImageDataAfterApply ( false ) ,
2004-03-09 01:09:58 +08:00
_clientStorageHint ( false ) ,
2002-08-28 23:28:11 +08:00
_borderColor ( 0.0 , 0.0 , 0.0 , 0.0 ) ,
2004-01-28 05:29:58 +08:00
_borderWidth ( 0 ) ,
2002-08-28 23:28:11 +08:00
_internalFormatMode ( USE_IMAGE_DATA_FORMAT ) ,
2003-12-18 03:26:16 +08:00
_internalFormat ( 0 ) ,
_use_shadow_comparison ( false ) ,
_shadow_compare_func ( LEQUAL ) ,
2004-01-29 19:16:49 +08:00
_shadow_texture_mode ( LUMINANCE ) ,
_shadow_ambient ( 0 )
2001-01-11 00:32:10 +08:00
{
}
2002-07-29 19:02:14 +08:00
Texture : : Texture ( const Texture & text , const CopyOp & copyop ) :
2002-08-28 23:28:11 +08:00
StateAttribute ( text , copyop ) ,
_wrap_s ( text . _wrap_s ) ,
_wrap_t ( text . _wrap_t ) ,
_wrap_r ( text . _wrap_r ) ,
_min_filter ( text . _min_filter ) ,
_mag_filter ( text . _mag_filter ) ,
_maxAnisotropy ( text . _maxAnisotropy ) ,
2003-04-01 05:41:17 +08:00
_useHardwareMipMapGeneration ( text . _useHardwareMipMapGeneration ) ,
2003-04-07 20:51:00 +08:00
_unrefImageDataAfterApply ( text . _unrefImageDataAfterApply ) ,
2004-03-09 01:09:58 +08:00
_clientStorageHint ( text . _clientStorageHint ) ,
2002-08-28 23:28:11 +08:00
_borderColor ( text . _borderColor ) ,
2004-01-28 05:29:58 +08:00
_borderWidth ( text . _borderWidth ) ,
2002-08-28 23:28:11 +08:00
_internalFormatMode ( text . _internalFormatMode ) ,
2003-12-18 03:26:16 +08:00
_internalFormat ( text . _internalFormat ) ,
_use_shadow_comparison ( text . _use_shadow_comparison ) ,
_shadow_compare_func ( text . _shadow_compare_func ) ,
2004-01-29 19:16:49 +08:00
_shadow_texture_mode ( text . _shadow_texture_mode ) ,
_shadow_ambient ( text . _shadow_ambient )
2002-08-28 23:28:11 +08:00
{
}
2001-01-11 00:32:10 +08:00
2001-09-20 05:08:56 +08:00
Texture : : ~ Texture ( )
2001-01-11 00:32:10 +08:00
{
2002-08-28 23:28:11 +08:00
// delete old texture objects.
dirtyTextureObject ( ) ;
2001-01-11 00:32:10 +08:00
}
2002-08-28 23:28:11 +08:00
int Texture : : compareTexture ( const Texture & rhs ) const
2001-09-22 10:42:08 +08:00
{
2002-08-28 23:28:11 +08:00
COMPARE_StateAttribute_Parameter ( _wrap_s )
COMPARE_StateAttribute_Parameter ( _wrap_t )
COMPARE_StateAttribute_Parameter ( _wrap_r )
COMPARE_StateAttribute_Parameter ( _min_filter )
COMPARE_StateAttribute_Parameter ( _mag_filter )
COMPARE_StateAttribute_Parameter ( _maxAnisotropy )
2003-04-01 05:41:17 +08:00
COMPARE_StateAttribute_Parameter ( _useHardwareMipMapGeneration )
2002-08-28 23:28:11 +08:00
COMPARE_StateAttribute_Parameter ( _internalFormatMode )
2004-01-11 01:13:20 +08:00
# if 1
2002-08-28 23:28:11 +08:00
COMPARE_StateAttribute_Parameter ( _internalFormat )
2004-01-11 01:13:20 +08:00
# endif
2003-12-18 03:26:16 +08:00
COMPARE_StateAttribute_Parameter ( _use_shadow_comparison )
COMPARE_StateAttribute_Parameter ( _shadow_compare_func )
COMPARE_StateAttribute_Parameter ( _shadow_texture_mode )
2004-01-29 19:16:49 +08:00
COMPARE_StateAttribute_Parameter ( _shadow_ambient )
2004-03-09 01:09:58 +08:00
COMPARE_StateAttribute_Parameter ( _unrefImageDataAfterApply )
COMPARE_StateAttribute_Parameter ( _clientStorageHint )
2002-08-28 23:28:11 +08:00
return 0 ;
}
2001-09-22 10:42:08 +08:00
2002-08-28 23:28:11 +08:00
2002-09-02 20:31:35 +08:00
void Texture : : setWrap ( WrapParameter which , WrapMode wrap )
2002-08-28 23:28:11 +08:00
{
switch ( which )
2001-09-22 10:42:08 +08:00
{
2002-09-04 16:14:04 +08:00
case WRAP_S : _wrap_s = wrap ; dirtyTextureParameters ( ) ; break ;
case WRAP_T : _wrap_t = wrap ; dirtyTextureParameters ( ) ; break ;
case WRAP_R : _wrap_r = wrap ; dirtyTextureParameters ( ) ; break ;
2002-08-28 23:28:11 +08:00
default : notify ( WARN ) < < " Error: invalid 'which' passed Texture::setWrap( " < < ( unsigned int ) which < < " , " < < ( unsigned int ) wrap < < " ) " < < std : : endl ; break ;
2001-09-22 10:42:08 +08:00
}
2002-08-28 23:28:11 +08:00
}
2001-09-22 10:42:08 +08:00
2002-09-02 20:31:35 +08:00
Texture : : WrapMode Texture : : getWrap ( WrapParameter which ) const
2002-08-28 23:28:11 +08:00
{
switch ( which )
{
case WRAP_S : return _wrap_s ;
case WRAP_T : return _wrap_t ;
case WRAP_R : return _wrap_r ;
default : notify ( WARN ) < < " Error: invalid 'which' passed Texture::getWrap(which) " < < std : : endl ; return _wrap_s ;
}
}
2002-08-25 03:39:39 +08:00
2002-09-02 20:31:35 +08:00
void Texture : : setFilter ( FilterParameter which , FilterMode filter )
2002-08-28 23:28:11 +08:00
{
switch ( which )
{
2002-09-04 16:14:04 +08:00
case MIN_FILTER : _min_filter = filter ; dirtyTextureParameters ( ) ; break ;
case MAG_FILTER : _mag_filter = filter ; dirtyTextureParameters ( ) ; break ;
2002-08-28 23:28:11 +08:00
default : notify ( WARN ) < < " Error: invalid 'which' passed Texture::setFilter( " < < ( unsigned int ) which < < " , " < < ( unsigned int ) filter < < " ) " < < std : : endl ; break ;
}
}
2002-08-25 03:39:39 +08:00
2001-09-22 10:42:08 +08:00
2002-09-02 20:31:35 +08:00
Texture : : FilterMode Texture : : getFilter ( FilterParameter which ) const
2002-08-28 23:28:11 +08:00
{
switch ( which )
{
case MIN_FILTER : return _min_filter ;
case MAG_FILTER : return _mag_filter ;
default : notify ( WARN ) < < " Error: invalid 'which' passed Texture::getFilter(which) " < < std : : endl ; return _min_filter ;
}
2001-09-22 10:42:08 +08:00
}
2002-08-28 23:28:11 +08:00
void Texture : : setMaxAnisotropy ( float anis )
2001-01-11 00:32:10 +08:00
{
2002-08-28 23:28:11 +08:00
if ( _maxAnisotropy ! = anis )
2001-01-11 00:32:10 +08:00
{
2002-08-28 23:28:11 +08:00
_maxAnisotropy = anis ;
2002-09-04 16:14:04 +08:00
dirtyTextureParameters ( ) ;
2002-08-28 23:28:11 +08:00
}
}
/** Force a recompile on next apply() of associated OpenGL texture objects.*/
void Texture : : dirtyTextureObject ( )
{
2003-07-14 22:42:10 +08:00
getTextureObjectManager ( ) - > addTextureObjectsFrom ( * this ) ;
}
void Texture : : takeTextureObjects ( Texture : : TextureObjectListMap & toblm )
{
for ( unsigned int i = 0 ; i < _textureObjectBuffer . size ( ) ; + + i )
2002-08-28 23:28:11 +08:00
{
2003-07-14 22:42:10 +08:00
if ( _textureObjectBuffer [ i ] . valid ( ) )
2001-09-20 05:08:56 +08:00
{
2003-08-15 17:38:36 +08:00
//notify(INFO) << "releasing texure "<<toblm[i].size()<<std::endl;
2003-07-14 22:42:10 +08:00
toblm [ i ] . push_back ( _textureObjectBuffer [ i ] ) ;
2001-09-20 05:08:56 +08:00
}
2001-01-11 00:32:10 +08:00
}
2003-07-14 22:42:10 +08:00
_textureObjectBuffer . setAllElementsTo ( 0 ) ;
2001-01-11 00:32:10 +08:00
}
2002-09-04 16:14:04 +08:00
void Texture : : dirtyTextureParameters ( )
{
2003-02-14 19:41:52 +08:00
for ( unsigned int i = 0 ; i < _texParametersDirtyList . size ( ) ; + + i )
2002-09-04 16:14:04 +08:00
{
2002-11-19 18:56:59 +08:00
_texParametersDirtyList [ i ] = 1 ;
2002-09-04 16:14:04 +08:00
}
}
2003-04-01 19:49:09 +08:00
void Texture : : computeInternalFormatWithImage ( const osg : : Image & image ) const
2001-01-11 00:32:10 +08:00
{
2002-08-28 23:28:11 +08:00
GLint internalFormat = image . getInternalTextureFormat ( ) ;
2004-06-29 06:09:52 +08:00
if ( _internalFormatMode = = USE_IMAGE_DATA_FORMAT )
2001-01-11 00:32:10 +08:00
{
2004-06-29 06:09:52 +08:00
internalFormat = image . getInternalTextureFormat ( ) ;
}
else if ( _internalFormatMode = = USE_USER_DEFINED_FORMAT )
{
internalFormat = _internalFormat ;
}
else
{
const unsigned int contextID = 0 ; // state.getContextID(); // set to 0 right now, assume same paramters for each graphics context...
const Extensions * extensions = getExtensions ( contextID , true ) ;
2002-07-21 02:27:40 +08:00
2004-06-29 06:09:52 +08:00
switch ( _internalFormatMode )
{
2002-08-28 23:28:11 +08:00
case ( USE_ARB_COMPRESSION ) :
2002-09-17 04:58:05 +08:00
if ( extensions - > isTextureCompressionARBSupported ( ) )
2001-09-20 05:08:56 +08:00
{
2002-08-28 23:28:11 +08:00
switch ( image . getPixelFormat ( ) )
{
case ( 1 ) : internalFormat = GL_COMPRESSED_ALPHA_ARB ; break ;
case ( 2 ) : internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_ARB ; break ;
case ( 3 ) : internalFormat = GL_COMPRESSED_RGB_ARB ; break ;
case ( 4 ) : internalFormat = GL_COMPRESSED_RGBA_ARB ; break ;
case ( GL_RGB ) : internalFormat = GL_COMPRESSED_RGB_ARB ; break ;
case ( GL_RGBA ) : internalFormat = GL_COMPRESSED_RGBA_ARB ; break ;
case ( GL_ALPHA ) : internalFormat = GL_COMPRESSED_ALPHA_ARB ; break ;
case ( GL_LUMINANCE ) : internalFormat = GL_COMPRESSED_LUMINANCE_ARB ; break ;
case ( GL_LUMINANCE_ALPHA ) : internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_ARB ; break ;
case ( GL_INTENSITY ) : internalFormat = GL_COMPRESSED_INTENSITY_ARB ; break ;
}
}
else internalFormat = image . getInternalTextureFormat ( ) ;
break ;
2002-07-29 07:28:27 +08:00
2002-08-28 23:28:11 +08:00
case ( USE_S3TC_DXT1_COMPRESSION ) :
2002-09-17 04:58:05 +08:00
if ( extensions - > isTextureCompressionS3TCSupported ( ) )
2002-08-28 23:28:11 +08:00
{
switch ( image . getPixelFormat ( ) )
{
case ( 3 ) : internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ; break ;
case ( 4 ) : internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ; break ;
case ( GL_RGB ) : internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ; break ;
case ( GL_RGBA ) : internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ; break ;
default : internalFormat = image . getInternalTextureFormat ( ) ; break ;
}
}
else internalFormat = image . getInternalTextureFormat ( ) ;
break ;
2002-07-29 07:28:27 +08:00
2002-08-28 23:28:11 +08:00
case ( USE_S3TC_DXT3_COMPRESSION ) :
2002-09-17 04:58:05 +08:00
if ( extensions - > isTextureCompressionS3TCSupported ( ) )
2002-08-28 23:28:11 +08:00
{
switch ( image . getPixelFormat ( ) )
{
case ( 3 ) :
case ( GL_RGB ) : internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ; break ;
case ( 4 ) :
case ( GL_RGBA ) : internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ; break ;
default : internalFormat = image . getInternalTextureFormat ( ) ; break ;
}
2001-09-20 05:08:56 +08:00
}
2002-08-28 23:28:11 +08:00
else internalFormat = image . getInternalTextureFormat ( ) ;
break ;
case ( USE_S3TC_DXT5_COMPRESSION ) :
2002-09-17 04:58:05 +08:00
if ( extensions - > isTextureCompressionS3TCSupported ( ) )
2002-08-16 21:33:32 +08:00
{
2002-08-28 23:28:11 +08:00
switch ( image . getPixelFormat ( ) )
{
case ( 3 ) :
case ( GL_RGB ) : internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ; break ;
case ( 4 ) :
case ( GL_RGBA ) : internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ; break ;
default : internalFormat = image . getInternalTextureFormat ( ) ; break ;
}
2002-08-16 21:33:32 +08:00
}
2002-08-28 23:28:11 +08:00
else internalFormat = image . getInternalTextureFormat ( ) ;
break ;
2004-07-06 20:15:03 +08:00
default :
break ;
2004-06-29 06:09:52 +08:00
}
2001-01-11 00:32:10 +08:00
}
2002-08-28 23:28:11 +08:00
_internalFormat = internalFormat ;
2004-07-12 21:13:58 +08:00
//osg::notify(osg::NOTICE)<<"Internal format="<<std::hex<<internalFormat<<std::dec<<std::endl;
2002-08-28 23:28:11 +08:00
}
2002-09-19 00:05:26 +08:00
bool Texture : : isCompressedInternalFormat ( ) const
{
return isCompressedInternalFormat ( getInternalFormat ( ) ) ;
}
2002-08-28 23:28:11 +08:00
bool Texture : : isCompressedInternalFormat ( GLint internalFormat ) const
{
switch ( internalFormat )
2001-01-11 00:32:10 +08:00
{
2002-08-28 23:28:11 +08:00
case ( GL_COMPRESSED_ALPHA_ARB ) :
case ( GL_COMPRESSED_INTENSITY_ARB ) :
case ( GL_COMPRESSED_LUMINANCE_ALPHA_ARB ) :
case ( GL_COMPRESSED_LUMINANCE_ARB ) :
case ( GL_COMPRESSED_RGBA_ARB ) :
case ( GL_COMPRESSED_RGB_ARB ) :
case ( GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ) :
case ( GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ) :
case ( GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ) :
case ( GL_COMPRESSED_RGB_S3TC_DXT1_EXT ) :
return true ;
default :
return false ;
}
}
2001-01-11 00:32:10 +08:00
2002-09-04 16:14:04 +08:00
void Texture : : applyTexParameters ( GLenum target , State & state ) const
2002-08-28 23:28:11 +08:00
{
2002-09-17 04:58:05 +08:00
// get the contextID (user defined ID of 0 upwards) for the
// current OpenGL context.
2003-02-14 19:41:52 +08:00
const unsigned int contextID = state . getContextID ( ) ;
2002-09-17 04:58:05 +08:00
const Extensions * extensions = getExtensions ( contextID , true ) ;
2003-01-09 18:06:44 +08:00
WrapMode ws = _wrap_s , wt = _wrap_t , wr = _wrap_r ;
2001-09-20 05:08:56 +08:00
2002-08-28 23:28:11 +08:00
// GL_IBM_texture_mirrored_repeat, fall-back REPEAT
2002-09-17 04:58:05 +08:00
if ( ! extensions - > isTextureMirroredRepeatSupported ( ) )
2002-08-28 23:28:11 +08:00
{
if ( ws = = MIRROR )
ws = REPEAT ;
if ( wt = = MIRROR )
wt = REPEAT ;
2003-01-09 18:06:44 +08:00
if ( wr = = MIRROR )
wr = REPEAT ;
2002-08-28 23:28:11 +08:00
}
2001-09-20 05:08:56 +08:00
2002-08-28 23:28:11 +08:00
// GL_EXT_texture_edge_clamp, fall-back CLAMP
2002-09-17 04:58:05 +08:00
if ( ! extensions - > isTextureEdgeClampSupported ( ) )
2002-08-28 23:28:11 +08:00
{
if ( ws = = CLAMP_TO_EDGE )
ws = CLAMP ;
if ( wt = = CLAMP_TO_EDGE )
wt = CLAMP ;
2003-01-09 18:06:44 +08:00
if ( wr = = CLAMP_TO_EDGE )
wr = CLAMP ;
2002-08-28 23:28:11 +08:00
}
2001-12-04 20:31:10 +08:00
2002-09-17 04:58:05 +08:00
if ( ! extensions - > isTextureBorderClampSupported ( ) )
2002-08-28 23:28:11 +08:00
{
if ( ws = = CLAMP_TO_BORDER )
ws = CLAMP ;
if ( wt = = CLAMP_TO_BORDER )
wt = CLAMP ;
2003-01-09 18:06:44 +08:00
if ( wr = = CLAMP_TO_BORDER )
wr = CLAMP ;
2002-08-16 21:33:32 +08:00
}
2002-08-28 23:28:11 +08:00
glTexParameteri ( target , GL_TEXTURE_WRAP_S , ws ) ;
2003-08-19 03:51:27 +08:00
if ( target ! = GL_TEXTURE_1D ) glTexParameteri ( target , GL_TEXTURE_WRAP_T , wt ) ;
if ( target = = GL_TEXTURE_3D ) glTexParameteri ( target , GL_TEXTURE_WRAP_R , wr ) ;
2002-08-28 23:28:11 +08:00
glTexParameteri ( target , GL_TEXTURE_MIN_FILTER , _min_filter ) ;
glTexParameteri ( target , GL_TEXTURE_MAG_FILTER , _mag_filter ) ;
2003-04-02 04:32:57 +08:00
if ( extensions - > isTextureFilterAnisotropicSupported ( ) )
2002-08-28 23:28:11 +08:00
{
2002-09-17 04:58:05 +08:00
// note, GL_TEXTURE_MAX_ANISOTROPY_EXT will either be defined
// by gl.h (or via glext.h) or by include/osg/Texture.
glTexParameterf ( target , GL_TEXTURE_MAX_ANISOTROPY_EXT , _maxAnisotropy ) ;
2002-08-28 23:28:11 +08:00
}
2002-09-17 04:58:05 +08:00
if ( extensions - > isTextureBorderClampSupported ( ) )
2001-09-20 05:08:56 +08:00
{
2002-08-28 23:28:11 +08:00
glTexParameterfv ( target , GL_TEXTURE_BORDER_COLOR , _borderColor . ptr ( ) ) ;
2001-09-20 05:08:56 +08:00
}
2003-12-18 03:26:16 +08:00
if ( extensions - > isShadowSupported ( ) & & target = = GL_TEXTURE_2D )
{
if ( _use_shadow_comparison )
{
2003-12-19 18:52:17 +08:00
glTexParameteri ( target , GL_TEXTURE_COMPARE_MODE_ARB , GL_COMPARE_R_TO_TEXTURE_ARB ) ;
2003-12-18 03:26:16 +08:00
glTexParameteri ( target , GL_TEXTURE_COMPARE_FUNC_ARB , _shadow_compare_func ) ;
glTexParameteri ( target , GL_DEPTH_TEXTURE_MODE_ARB , _shadow_texture_mode ) ;
2004-01-29 19:16:49 +08:00
// if ambient value is 0 - it is default behaviour of GL_ARB_shadow
// no need for GL_ARB_shadow_ambient in this case
if ( extensions - > isShadowAmbientSupported ( ) & & _shadow_ambient > 0 )
{
glTexParameterf ( target , TEXTURE_COMPARE_FAIL_VALUE_ARB , _shadow_ambient ) ;
}
2003-12-18 03:26:16 +08:00
}
else
{
glTexParameteri ( target , GL_TEXTURE_COMPARE_MODE_ARB , GL_NONE ) ;
}
}
2002-11-12 00:11:48 +08:00
getTextureParameterDirty ( state . getContextID ( ) ) = false ;
2002-08-28 23:28:11 +08:00
}
2001-09-20 05:08:56 +08:00
2003-07-14 22:42:10 +08:00
void Texture : : computeRequiredTextureDimensions ( State & state , const osg : : Image & image , GLsizei & inwidth , GLsizei & inheight , GLsizei & numMipmapLevels ) const
{
const unsigned int contextID = state . getContextID ( ) ;
const Extensions * extensions = getExtensions ( contextID , true ) ;
2004-01-28 05:29:58 +08:00
int width = Image : : computeNearestPowerOfTwo ( image . s ( ) - 2 * _borderWidth ) + 2 * _borderWidth ;
int height = Image : : computeNearestPowerOfTwo ( image . t ( ) - 2 * _borderWidth ) + 2 * _borderWidth ;
2003-07-14 22:42:10 +08:00
// cap the size to what the graphics hardware can handle.
if ( width > extensions - > maxTextureSize ( ) ) width = extensions - > maxTextureSize ( ) ;
if ( height > extensions - > maxTextureSize ( ) ) height = extensions - > maxTextureSize ( ) ;
inwidth = width ;
inheight = height ;
2003-12-27 19:30:41 +08:00
bool useHardwareMipMapGeneration = ! image . isMipmap ( ) & & _useHardwareMipMapGeneration & & extensions - > isGenerateMipMapSupported ( ) ;
2003-07-14 22:42:10 +08:00
2003-12-27 19:30:41 +08:00
if ( _min_filter = = LINEAR | | _min_filter = = NEAREST | | useHardwareMipMapGeneration )
{
numMipmapLevels = 1 ;
}
else if ( image . isMipmap ( ) )
{
numMipmapLevels = image . getNumMipmapLevels ( ) ;
}
else
{
numMipmapLevels = 0 ;
for ( ; ( width | | height ) ; + + numMipmapLevels )
{
2003-07-14 22:42:10 +08:00
2003-12-27 19:30:41 +08:00
if ( width = = 0 )
width = 1 ;
if ( height = = 0 )
height = 1 ;
2003-07-14 22:42:10 +08:00
2003-12-27 19:30:41 +08:00
width > > = 1 ;
height > > = 1 ;
}
}
2003-07-14 22:42:10 +08:00
}
bool Texture : : areAllTextureObjectsLoaded ( ) const
{
for ( unsigned int i = 0 ; i < DisplaySettings : : instance ( ) - > getMaxNumberOfGraphicsContexts ( ) ; + + i )
{
2004-01-19 19:01:45 +08:00
if ( _textureObjectBuffer [ i ] = = 0 ) return false ;
2003-07-14 22:42:10 +08:00
}
2004-01-19 19:01:45 +08:00
return true ;
2003-07-14 22:42:10 +08:00
}
void Texture : : applyTexImage2D_load ( State & state , GLenum target , const Image * image , GLsizei inwidth , GLsizei inheight , GLsizei numMipmapLevels ) const
2001-09-20 05:08:56 +08:00
{
2002-08-28 23:28:11 +08:00
// if we don't have a valid image we can't create a texture!
if ( ! image | | ! image - > data ( ) )
return ;
// get the contextID (user defined ID of 0 upwards) for the
// current OpenGL context.
2003-02-14 19:41:52 +08:00
const unsigned int contextID = state . getContextID ( ) ;
2002-09-17 04:58:05 +08:00
const Extensions * extensions = getExtensions ( contextID , true ) ;
2003-04-01 05:41:17 +08:00
bool generateMipMapSupported = extensions - > isGenerateMipMapSupported ( ) ;
2002-08-28 23:28:11 +08:00
// select the internalFormat required for the texture.
2003-07-14 22:42:10 +08:00
bool compressed_image = isCompressedInternalFormat ( ( GLenum ) image - > getPixelFormat ( ) ) ;
2002-08-28 23:28:11 +08:00
glPixelStorei ( GL_UNPACK_ALIGNMENT , image - > getPacking ( ) ) ;
2003-04-01 19:49:09 +08:00
2004-03-09 01:09:58 +08:00
bool useClientStorage = extensions - > isClientStorageSupported ( ) & & getClientStorageHint ( ) ;
if ( useClientStorage )
{
glPixelStorei ( GL_UNPACK_CLIENT_STORAGE_APPLE , GL_TRUE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_PRIORITY , 0.0f ) ;
# ifdef GL_TEXTURE_STORAGE_HINT_APPLE
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE ) ;
# endif
}
2003-04-01 19:49:09 +08:00
unsigned char * data = ( unsigned char * ) image - > data ( ) ;
2002-08-28 23:28:11 +08:00
2003-07-14 22:42:10 +08:00
bool needImageRescale = inwidth ! = image - > s ( ) | | inheight ! = image - > t ( ) ;
2003-04-01 19:49:09 +08:00
if ( needImageRescale )
2001-09-20 05:08:56 +08:00
{
2003-04-01 19:49:09 +08:00
// resize the image to power of two.
if ( image - > isMipmap ( ) )
{
notify ( WARN ) < < " Warning:: Mipmapped osg::Image not a power of two, cannot apply to texture. " < < std : : endl ;
return ;
}
else if ( compressed_image )
{
notify ( WARN ) < < " Warning:: Compressed osg::Image not a power of two, cannot apply to texture. " < < std : : endl ;
return ;
}
2003-07-14 22:42:10 +08:00
unsigned int newTotalSize = osg : : Image : : computeRowWidthInBytes ( inwidth , image - > getPixelFormat ( ) , image - > getDataType ( ) , image - > getPacking ( ) ) * inheight ;
2003-04-01 19:49:09 +08:00
data = new unsigned char [ newTotalSize ] ;
if ( ! data )
{
notify ( WARN ) < < " Warning:: Not enough memory to resize image, cannot apply to texture. " < < std : : endl ;
return ;
}
2003-07-14 22:42:10 +08:00
if ( ! image - > getFileName ( ) . empty ( ) ) notify ( NOTICE ) < < " Scaling image ' " < < image - > getFileName ( ) < < " ' from ( " < < image - > s ( ) < < " , " < < image - > t ( ) < < " ) to ( " < < inwidth < < " , " < < inheight < < " ) " < < std : : endl ;
else notify ( NOTICE ) < < " Scaling image from ( " < < image - > s ( ) < < " , " < < image - > t ( ) < < " ) to ( " < < inwidth < < " , " < < inheight < < " ) " < < std : : endl ;
2003-04-01 19:49:09 +08:00
// rescale the image to the correct size.
glPixelStorei ( GL_PACK_ALIGNMENT , image - > getPacking ( ) ) ;
gluScaleImage ( image - > getPixelFormat ( ) ,
image - > s ( ) , image - > t ( ) , image - > getDataType ( ) , image - > data ( ) ,
2003-07-14 22:42:10 +08:00
inwidth , inheight , image - > getDataType ( ) , data ) ;
2003-04-01 19:49:09 +08:00
}
bool useHardwareMipMapGeneration = ! image - > isMipmap ( ) & & _useHardwareMipMapGeneration & & generateMipMapSupported ;
if ( _min_filter = = LINEAR | | _min_filter = = NEAREST | | useHardwareMipMapGeneration )
{
2003-04-02 04:32:57 +08:00
bool hardwareMipMapOn = false ;
if ( _min_filter ! = LINEAR & & _min_filter ! = NEAREST )
{
if ( useHardwareMipMapGeneration ) glTexParameteri ( GL_TEXTURE_2D , GL_GENERATE_MIPMAP_SGIS , GL_TRUE ) ;
hardwareMipMapOn = true ;
}
2003-04-01 19:49:09 +08:00
2003-04-01 05:41:17 +08:00
if ( ! compressed_image )
2001-09-20 05:08:56 +08:00
{
2003-07-14 22:42:10 +08:00
numMipmapLevels = 1 ;
2003-04-01 05:41:17 +08:00
2002-08-28 23:28:11 +08:00
glTexImage2D ( target , 0 , _internalFormat ,
2004-01-28 05:29:58 +08:00
inwidth , inheight , _borderWidth ,
2002-08-28 23:28:11 +08:00
( GLenum ) image - > getPixelFormat ( ) ,
( GLenum ) image - > getDataType ( ) ,
2003-04-01 19:49:09 +08:00
data ) ;
2002-08-28 23:28:11 +08:00
}
2002-09-17 04:58:05 +08:00
else if ( extensions - > isCompressedTexImage2DSupported ( ) )
2002-08-28 23:28:11 +08:00
{
2003-07-14 22:42:10 +08:00
numMipmapLevels = 1 ;
2003-04-01 05:41:17 +08:00
GLint blockSize = ( _internalFormat = = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 ) ;
2003-07-14 22:42:10 +08:00
GLint size = ( ( inwidth + 3 ) / 4 ) * ( ( inheight + 3 ) / 4 ) * blockSize ;
2003-04-01 05:41:17 +08:00
extensions - > glCompressedTexImage2D ( target , 0 , _internalFormat ,
2003-07-14 22:42:10 +08:00
inwidth , inheight , 0 ,
2003-04-01 05:41:17 +08:00
size ,
2003-04-01 19:49:09 +08:00
data ) ;
2003-04-01 05:41:17 +08:00
}
2003-04-02 04:32:57 +08:00
if ( hardwareMipMapOn ) glTexParameteri ( GL_TEXTURE_2D , GL_GENERATE_MIPMAP_SGIS , GL_FALSE ) ;
2003-04-01 05:41:17 +08:00
}
else
{
2003-04-01 19:49:09 +08:00
// we require mip mapping.
if ( image - > isMipmap ( ) )
2002-08-28 23:28:11 +08:00
{
2004-07-06 20:15:03 +08:00
2003-04-01 19:49:09 +08:00
// image is mip mapped so we take the mip map levels from the image.
2003-07-14 22:42:10 +08:00
numMipmapLevels = image - > getNumMipmapLevels ( ) ;
2001-09-20 05:08:56 +08:00
2003-07-14 22:42:10 +08:00
int width = inwidth ;
int height = inheight ;
2001-09-20 05:08:56 +08:00
2003-04-01 05:41:17 +08:00
if ( ! compressed_image )
2002-08-28 23:28:11 +08:00
{
2003-07-14 22:42:10 +08:00
for ( GLsizei k = 0 ; k < numMipmapLevels & & ( width | | height ) ; k + + )
2002-08-28 23:28:11 +08:00
{
if ( width = = 0 )
width = 1 ;
if ( height = = 0 )
height = 1 ;
glTexImage2D ( target , k , _internalFormat ,
2004-01-28 05:29:58 +08:00
width , height , _borderWidth ,
2002-08-28 23:28:11 +08:00
( GLenum ) image - > getPixelFormat ( ) ,
( GLenum ) image - > getDataType ( ) ,
image - > getMipmapData ( k ) ) ;
width > > = 1 ;
height > > = 1 ;
}
}
2002-09-17 04:58:05 +08:00
else if ( extensions - > isCompressedTexImage2DSupported ( ) )
2002-08-28 23:28:11 +08:00
{
2003-04-01 05:41:17 +08:00
GLint blockSize = ( _internalFormat = = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 ) ;
GLint size = 0 ;
2003-07-14 22:42:10 +08:00
for ( GLsizei k = 0 ; k < numMipmapLevels & & ( width | | height ) ; k + + )
2002-08-28 23:28:11 +08:00
{
2003-04-01 05:41:17 +08:00
if ( width = = 0 )
width = 1 ;
if ( height = = 0 )
height = 1 ;
2002-08-28 23:28:11 +08:00
2003-04-01 05:41:17 +08:00
size = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 ) * blockSize ;
extensions - > glCompressedTexImage2D ( target , k , _internalFormat ,
2004-01-28 05:29:58 +08:00
width , height , _borderWidth ,
2003-04-01 05:41:17 +08:00
size , image - > getMipmapData ( k ) ) ;
width > > = 1 ;
height > > = 1 ;
}
}
}
2003-04-01 19:49:09 +08:00
else
{
if ( ! compressed_image )
{
2003-07-14 22:42:10 +08:00
numMipmapLevels = 0 ;
2003-04-01 19:49:09 +08:00
gluBuild2DMipmaps ( target , _internalFormat ,
2003-07-14 22:42:10 +08:00
inwidth , inheight ,
2003-04-01 19:49:09 +08:00
( GLenum ) image - > getPixelFormat ( ) , ( GLenum ) image - > getDataType ( ) ,
data ) ;
int width = image - > s ( ) ;
int height = image - > t ( ) ;
2003-07-14 22:42:10 +08:00
for ( numMipmapLevels = 0 ; ( width | | height ) ; + + numMipmapLevels )
2003-04-01 19:49:09 +08:00
{
width > > = 1 ;
height > > = 1 ;
}
}
else
{
notify ( WARN ) < < " Warning:: Compressed image cannot be mip mapped " < < std : : endl ;
}
}
2003-04-01 05:41:17 +08:00
}
2003-04-01 19:49:09 +08:00
if ( needImageRescale )
{
// clean up the resized image.
delete [ ] data ;
}
2003-04-01 05:41:17 +08:00
2004-03-09 01:09:58 +08:00
if ( useClientStorage )
{
glPixelStorei ( GL_UNPACK_CLIENT_STORAGE_APPLE , GL_FALSE ) ;
}
2003-04-01 05:41:17 +08:00
}
2003-07-14 22:42:10 +08:00
2004-01-23 21:25:45 +08:00
void Texture : : applyTexImage2D_subload ( State & state , GLenum target , const Image * image , GLsizei inwidth , GLsizei inheight , GLint inInternalFormat , GLint numMipmapLevels ) const
2003-04-01 05:41:17 +08:00
{
// if we don't have a valid image we can't create a texture!
if ( ! image | | ! image - > data ( ) )
return ;
// image size has changed so we have to re-load the image from scratch.
2004-01-23 21:25:45 +08:00
if ( image - > s ( ) ! = inwidth | | image - > t ( ) ! = inheight | | image - > getInternalTextureFormat ( ) ! = inInternalFormat )
2003-04-01 05:41:17 +08:00
{
2003-07-14 22:42:10 +08:00
applyTexImage2D_load ( state , target , image , inwidth , inheight , numMipmapLevels ) ;
2003-04-01 05:41:17 +08:00
return ;
}
// else image size the same as when loaded so we can go ahead and subload
2003-04-02 04:32:57 +08:00
2003-04-01 05:41:17 +08:00
// get the contextID (user defined ID of 0 upwards) for the
// current OpenGL context.
const unsigned int contextID = state . getContextID ( ) ;
const Extensions * extensions = getExtensions ( contextID , true ) ;
bool generateMipMapSupported = extensions - > isGenerateMipMapSupported ( ) ;
// select the internalFormat required for the texture.
bool compressed_image = isCompressedInternalFormat ( ( GLenum ) image - > getPixelFormat ( ) ) ;
glPixelStorei ( GL_UNPACK_ALIGNMENT , image - > getPacking ( ) ) ;
2003-04-01 19:49:09 +08:00
unsigned char * data = ( unsigned char * ) image - > data ( ) ;
2003-07-14 22:42:10 +08:00
bool needImageRescale = inwidth ! = image - > s ( ) | | inheight ! = image - > t ( ) ;
2003-04-01 19:49:09 +08:00
if ( needImageRescale )
{
// resize the image to power of two.
if ( image - > isMipmap ( ) )
{
notify ( WARN ) < < " Warning:: Mipmapped osg::Image not a power of two, cannot apply to texture. " < < std : : endl ;
return ;
}
else if ( compressed_image )
{
notify ( WARN ) < < " Warning:: Compressed osg::Image not a power of two, cannot apply to texture. " < < std : : endl ;
return ;
}
2003-07-14 22:42:10 +08:00
unsigned int newTotalSize = osg : : Image : : computeRowWidthInBytes ( inwidth , image - > getPixelFormat ( ) , image - > getDataType ( ) , image - > getPacking ( ) ) * inheight ;
2003-04-01 19:49:09 +08:00
data = new unsigned char [ newTotalSize ] ;
if ( ! data )
{
notify ( WARN ) < < " Warning:: Not enough memory to resize image, cannot apply to texture. " < < std : : endl ;
return ;
}
2003-07-14 22:42:10 +08:00
if ( ! image - > getFileName ( ) . empty ( ) ) notify ( NOTICE ) < < " Scaling image ' " < < image - > getFileName ( ) < < " ' from ( " < < image - > s ( ) < < " , " < < image - > t ( ) < < " ) to ( " < < inwidth < < " , " < < inheight < < " ) " < < std : : endl ;
else notify ( NOTICE ) < < " Scaling image from ( " < < image - > s ( ) < < " , " < < image - > t ( ) < < " ) to ( " < < inwidth < < " , " < < inheight < < " ) " < < std : : endl ;
2003-04-01 05:41:17 +08:00
2003-04-01 19:49:09 +08:00
// rescale the image to the correct size.
glPixelStorei ( GL_PACK_ALIGNMENT , image - > getPacking ( ) ) ;
gluScaleImage ( image - > getPixelFormat ( ) ,
image - > s ( ) , image - > t ( ) , image - > getDataType ( ) , image - > data ( ) ,
2003-07-14 22:42:10 +08:00
inwidth , inheight , image - > getDataType ( ) , data ) ;
2003-04-01 19:49:09 +08:00
}
bool useHardwareMipMapGeneration = ! image - > isMipmap ( ) & & _useHardwareMipMapGeneration & & generateMipMapSupported ;
if ( _min_filter = = LINEAR | | _min_filter = = NEAREST | | useHardwareMipMapGeneration )
2003-04-01 05:41:17 +08:00
{
2003-04-02 04:32:57 +08:00
bool hardwareMipMapOn = false ;
if ( _min_filter ! = LINEAR & & _min_filter ! = NEAREST )
{
if ( useHardwareMipMapGeneration ) glTexParameteri ( GL_TEXTURE_2D , GL_GENERATE_MIPMAP_SGIS , GL_TRUE ) ;
hardwareMipMapOn = true ;
}
2003-04-01 19:49:09 +08:00
2003-04-01 05:41:17 +08:00
if ( ! compressed_image )
{
glTexSubImage2D ( target , 0 ,
0 , 0 ,
2003-07-14 22:42:10 +08:00
inwidth , inheight ,
2003-04-01 05:41:17 +08:00
( GLenum ) image - > getPixelFormat ( ) ,
( GLenum ) image - > getDataType ( ) ,
2003-04-01 19:49:09 +08:00
data ) ;
2003-03-31 20:48:33 +08:00
2003-04-01 05:41:17 +08:00
}
else if ( extensions - > isCompressedTexImage2DSupported ( ) )
{
2003-07-14 22:42:10 +08:00
GLint blockSize = ( _internalFormat = = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 ) ;
GLint size = ( ( inwidth + 3 ) / 4 ) * ( ( inheight + 3 ) / 4 ) * blockSize ;
2003-04-01 05:41:17 +08:00
extensions - > glCompressedTexSubImage2D ( target , 0 ,
0 , 0 ,
2003-07-14 22:42:10 +08:00
inwidth , inheight ,
2003-04-01 05:41:17 +08:00
( GLenum ) image - > getPixelFormat ( ) ,
2003-07-14 22:42:10 +08:00
size ,
2003-04-01 19:49:09 +08:00
data ) ;
2003-04-01 05:41:17 +08:00
}
2003-03-31 20:48:33 +08:00
2003-04-02 04:32:57 +08:00
if ( hardwareMipMapOn ) glTexParameteri ( GL_TEXTURE_2D , GL_GENERATE_MIPMAP_SGIS , GL_FALSE ) ;
2003-04-01 05:41:17 +08:00
}
else
{
2003-04-01 19:49:09 +08:00
if ( image - > isMipmap ( ) )
2003-04-01 05:41:17 +08:00
{
2003-07-14 22:42:10 +08:00
numMipmapLevels = image - > getNumMipmapLevels ( ) ;
2003-04-01 19:49:09 +08:00
2003-07-14 22:42:10 +08:00
int width = inwidth ;
int height = inheight ;
2003-04-01 05:41:17 +08:00
2003-04-01 19:49:09 +08:00
if ( ! compressed_image )
2003-04-01 05:41:17 +08:00
{
2003-07-14 22:42:10 +08:00
for ( GLsizei k = 0 ; k < numMipmapLevels & & ( width | | height ) ; k + + )
2003-04-01 19:49:09 +08:00
{
2003-04-01 05:41:17 +08:00
2003-04-01 19:49:09 +08:00
if ( width = = 0 )
width = 1 ;
if ( height = = 0 )
height = 1 ;
2003-04-01 05:41:17 +08:00
2003-04-01 19:49:09 +08:00
glTexSubImage2D ( target , k ,
0 , 0 ,
width , height ,
( GLenum ) image - > getPixelFormat ( ) ,
( GLenum ) image - > getDataType ( ) ,
image - > getMipmapData ( k ) ) ;
width > > = 1 ;
height > > = 1 ;
}
}
else if ( extensions - > isCompressedTexImage2DSupported ( ) )
{
GLint blockSize = ( _internalFormat = = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 ) ;
GLint size = 0 ;
2003-07-14 22:42:10 +08:00
for ( GLsizei k = 0 ; k < numMipmapLevels & & ( width | | height ) ; k + + )
2003-04-01 19:49:09 +08:00
{
if ( width = = 0 )
width = 1 ;
if ( height = = 0 )
height = 1 ;
size = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 ) * blockSize ;
2003-07-16 05:19:03 +08:00
//state.checkGLErrors("before extensions->glCompressedTexSubImage2D(");
2003-07-14 22:42:10 +08:00
2003-04-01 19:49:09 +08:00
extensions - > glCompressedTexSubImage2D ( target , k ,
0 , 0 ,
width , height ,
( GLenum ) image - > getPixelFormat ( ) ,
2003-07-14 22:42:10 +08:00
size ,
2003-04-01 19:49:09 +08:00
image - > getMipmapData ( k ) ) ;
2003-04-01 05:41:17 +08:00
2003-07-16 05:19:03 +08:00
//state.checkGLErrors("after extensions->glCompressedTexSubImage2D(");
2003-07-14 22:42:10 +08:00
2003-04-01 19:49:09 +08:00
width > > = 1 ;
height > > = 1 ;
}
2003-07-14 22:42:10 +08:00
2003-04-01 05:41:17 +08:00
}
2003-04-01 19:49:09 +08:00
}
else
{
if ( ! compressed_image )
2003-04-01 05:41:17 +08:00
{
2003-04-02 04:32:57 +08:00
2003-07-14 22:42:10 +08:00
numMipmapLevels = 0 ;
2003-04-01 05:41:17 +08:00
2003-07-14 22:42:10 +08:00
int width = inwidth ;
int height = inheight ;
2003-04-01 05:41:17 +08:00
glPixelStorei ( GL_PACK_ALIGNMENT , image - > getPacking ( ) ) ;
unsigned int newTotalSize = osg : : Image : : computeRowWidthInBytes ( width , image - > getPixelFormat ( ) , image - > getDataType ( ) , image - > getPacking ( ) ) * height ;
unsigned char * copyData1 = new unsigned char [ newTotalSize ] ;
unsigned char * copyData2 = new unsigned char [ newTotalSize ] ;
2003-04-01 19:49:09 +08:00
unsigned char * tmpdata = data ;
2003-04-01 05:41:17 +08:00
int previous_width = width ;
int previous_height = height ;
for ( GLsizei k = 0 ; ( width | | height ) ; + + k )
{
if ( width = = 0 )
width = 1 ;
if ( height = = 0 )
height = 1 ;
if ( k > 0 )
{
if ( data ! = copyData1 )
{
gluScaleImage ( image - > getPixelFormat ( ) ,
previous_width , previous_height , image - > getDataType ( ) , data ,
width , height , image - > getDataType ( ) , copyData1 ) ;
data = copyData1 ;
}
else
{
gluScaleImage ( image - > getPixelFormat ( ) ,
previous_width , previous_height , image - > getDataType ( ) , data ,
width , height , image - > getDataType ( ) , copyData2 ) ;
data = copyData2 ;
}
2003-03-31 20:48:33 +08:00
}
2003-04-01 05:41:17 +08:00
2003-04-01 19:49:09 +08:00
glTexSubImage2D ( target , k ,
0 , 0 ,
width , height ,
( GLenum ) image - > getPixelFormat ( ) ,
( GLenum ) image - > getDataType ( ) ,
data ) ;
2003-04-01 05:41:17 +08:00
previous_width = width ;
previous_height = height ;
width > > = 1 ;
height > > = 1 ;
}
delete [ ] copyData1 ;
delete [ ] copyData2 ;
2003-04-01 19:49:09 +08:00
// restore the data paramters so it can be deleted if it was allocated locally via needImageRescale
data = tmpdata ;
2003-04-01 05:41:17 +08:00
}
2003-04-01 19:49:09 +08:00
else
2003-04-01 05:41:17 +08:00
{
2003-04-01 19:49:09 +08:00
notify ( WARN ) < < " Warning:: Compressed image cannot be mip mapped " < < std : : endl ;
2002-08-28 23:28:11 +08:00
}
}
}
2003-04-01 19:49:09 +08:00
if ( needImageRescale )
{
// clean up the resized image.
delete [ ] data ;
}
2001-09-20 05:08:56 +08:00
}
2002-09-05 19:42:55 +08:00
///////////////////////////////////////////////////////////////////////////////////////////////
// Static map to manage the deletion of texture objects are the right time.
//////////////////////////////////////////////////////////////////////////////////////////////
# include <map>
# include <set>
2001-09-20 05:08:56 +08:00
2004-07-20 13:37:59 +08:00
void Texture : : compileGLObjects ( State & state ) const
2002-09-17 04:58:05 +08:00
{
apply ( state ) ;
}
2004-07-20 13:37:59 +08:00
void Texture : : releaseGLObjects ( State * state ) const
{
const_cast < Texture * > ( this ) - > dirtyTextureObject ( ) ;
}
2002-09-17 04:58:05 +08:00
typedef buffered_value < ref_ptr < Texture : : Extensions > > BufferedExtensions ;
static BufferedExtensions s_extensions ;
2001-09-20 05:08:56 +08:00
2003-04-10 21:41:45 +08:00
Texture : : Extensions * Texture : : getExtensions ( unsigned int contextID , bool createIfNotInitalized )
2002-08-28 23:28:11 +08:00
{
2002-09-17 04:58:05 +08:00
if ( ! s_extensions [ contextID ] & & createIfNotInitalized ) s_extensions [ contextID ] = new Extensions ;
return s_extensions [ contextID ] . get ( ) ;
}
2003-02-14 19:41:52 +08:00
void Texture : : setExtensions ( unsigned int contextID , Extensions * extensions )
2002-09-17 04:58:05 +08:00
{
s_extensions [ contextID ] = extensions ;
}
Texture : : Extensions : : Extensions ( )
{
2004-04-17 06:50:41 +08:00
setupGLExtensions ( ) ;
2002-09-17 04:58:05 +08:00
}
Texture : : Extensions : : Extensions ( const Extensions & rhs ) :
Referenced ( )
{
2003-04-11 03:32:32 +08:00
_isMultiTexturingSupported = rhs . _isMultiTexturingSupported ;
2002-09-17 04:58:05 +08:00
_isTextureFilterAnisotropicSupported = rhs . _isTextureFilterAnisotropicSupported ;
2003-03-04 23:47:28 +08:00
_isTextureCompressionARBSupported = rhs . _isTextureCompressionARBSupported ;
_isTextureCompressionS3TCSupported = rhs . _isTextureCompressionS3TCSupported ;
2002-09-17 04:58:05 +08:00
_isTextureMirroredRepeatSupported = rhs . _isTextureMirroredRepeatSupported ;
_isTextureEdgeClampSupported = rhs . _isTextureEdgeClampSupported ;
_isTextureBorderClampSupported = rhs . _isTextureBorderClampSupported ;
2003-03-04 23:47:28 +08:00
_isGenerateMipMapSupported = rhs . _isGenerateMipMapSupported ;
2002-09-17 04:58:05 +08:00
_maxTextureSize = rhs . _maxTextureSize ;
_glCompressedTexImage2D = rhs . _glCompressedTexImage2D ;
2004-01-29 19:16:49 +08:00
_isShadowSupported = rhs . _isShadowSupported ;
_isShadowAmbientSupported = rhs . _isShadowAmbientSupported ;
2004-03-09 01:09:58 +08:00
_isClientStorageSupported = rhs . _isClientStorageSupported ;
2002-09-17 04:58:05 +08:00
}
void Texture : : Extensions : : lowestCommonDenominator ( const Extensions & rhs )
{
2003-04-11 03:32:32 +08:00
if ( ! rhs . _isMultiTexturingSupported ) _isMultiTexturingSupported = false ;
2002-09-17 04:58:05 +08:00
if ( ! rhs . _isTextureFilterAnisotropicSupported ) _isTextureFilterAnisotropicSupported = false ;
if ( ! rhs . _isTextureMirroredRepeatSupported ) _isTextureMirroredRepeatSupported = false ;
if ( ! rhs . _isTextureEdgeClampSupported ) _isTextureEdgeClampSupported = false ;
if ( ! rhs . _isTextureBorderClampSupported ) _isTextureBorderClampSupported = false ;
2002-08-28 23:28:11 +08:00
2002-09-17 04:58:05 +08:00
if ( ! rhs . _isTextureCompressionARBSupported ) _isTextureCompressionARBSupported = false ;
if ( ! rhs . _isTextureCompressionS3TCSupported ) _isTextureCompressionS3TCSupported = false ;
2003-03-04 23:47:28 +08:00
if ( ! rhs . _isGenerateMipMapSupported ) _isGenerateMipMapSupported = false ;
2002-09-17 04:58:05 +08:00
if ( rhs . _maxTextureSize < _maxTextureSize ) _maxTextureSize = rhs . _maxTextureSize ;
2004-05-07 19:28:55 +08:00
if ( rhs . _numTextureUnits < _numTextureUnits ) _numTextureUnits = rhs . _numTextureUnits ;
2002-09-17 04:58:05 +08:00
if ( ! rhs . _glCompressedTexImage2D ) _glCompressedTexImage2D = 0 ;
2003-04-11 03:32:32 +08:00
if ( ! rhs . _glCompressedTexSubImage2D ) _glCompressedTexSubImage2D = 0 ;
if ( ! rhs . _glGetCompressedTexImage ) _glGetCompressedTexImage = 0 ;
2004-01-29 19:16:49 +08:00
2004-03-09 01:09:58 +08:00
if ( ! rhs . _isShadowSupported ) _isShadowSupported = false ;
if ( ! rhs . _isShadowAmbientSupported ) _isShadowAmbientSupported = false ;
if ( ! rhs . _isClientStorageSupported ) _isClientStorageSupported = false ;
2002-09-17 04:58:05 +08:00
}
2004-04-17 06:50:41 +08:00
void Texture : : Extensions : : setupGLExtensions ( )
2002-09-17 04:58:05 +08:00
{
2004-04-16 18:05:57 +08:00
float glVersion = atof ( ( const char * ) glGetString ( GL_VERSION ) ) ;
_isMultiTexturingSupported = ( glVersion > = 1.3 ) | |
2003-04-11 03:32:32 +08:00
isGLExtensionSupported ( " GL_ARB_multitexture " ) | |
isGLExtensionSupported ( " GL_EXT_multitexture " ) ;
2002-09-17 04:58:05 +08:00
_isTextureFilterAnisotropicSupported = isGLExtensionSupported ( " GL_EXT_texture_filter_anisotropic " ) ;
2004-05-17 21:20:41 +08:00
_isTextureCompressionARBSupported = ( glVersion > = 1.3 ) | |
isGLExtensionSupported ( " GL_ARB_texture_compression " ) ;
2003-03-04 23:47:28 +08:00
_isTextureCompressionS3TCSupported = isGLExtensionSupported ( " GL_EXT_texture_compression_s3tc " ) ;
2004-05-17 21:20:41 +08:00
_isTextureMirroredRepeatSupported = ( glVersion > = 1.4 ) | |
isGLExtensionSupported ( " GL_IBM_texture_mirrored_repeat " ) | |
isGLExtensionSupported ( " GL_ARB_texture_mirrored_repeat " ) ;
2004-04-16 18:05:57 +08:00
_isTextureEdgeClampSupported = ( glVersion > = 1.2 ) | |
isGLExtensionSupported ( " GL_EXT_texture_edge_clamp " ) | |
isGLExtensionSupported ( " GL_SGIS_texture_edge_clamp " ) ;
2004-05-17 21:20:41 +08:00
_isTextureBorderClampSupported = ( glVersion > = 1.3 ) | |
isGLExtensionSupported ( " GL_ARB_texture_border_clamp " ) ;
2003-03-04 23:47:28 +08:00
_isGenerateMipMapSupported = ( strncmp ( ( const char * ) glGetString ( GL_VERSION ) , " 1.4 " , 3 ) > = 0 ) | |
isGLExtensionSupported ( " GL_SGIS_generate_mipmap " ) ;
2003-12-18 03:26:16 +08:00
_isShadowSupported = isGLExtensionSupported ( " GL_ARB_shadow " ) ;
2004-01-29 19:16:49 +08:00
_isShadowAmbientSupported = isGLExtensionSupported ( " GL_ARB_shadow_ambient " ) ;
2002-09-17 04:58:05 +08:00
2004-03-09 01:09:58 +08:00
_isClientStorageSupported = isGLExtensionSupported ( " GL_APPLE_client_storage " ) ;
2002-09-17 04:58:05 +08:00
glGetIntegerv ( GL_MAX_TEXTURE_SIZE , & _maxTextureSize ) ;
char * ptr ;
if ( ( ptr = getenv ( " OSG_MAX_TEXTURE_SIZE " ) ) ! = 0 )
{
GLint osg_max_size = atoi ( ptr ) ;
if ( osg_max_size < _maxTextureSize )
2002-08-28 23:28:11 +08:00
{
2002-09-17 04:58:05 +08:00
_maxTextureSize = osg_max_size ;
}
2004-05-07 19:28:55 +08:00
}
2002-09-17 04:58:05 +08:00
2004-05-07 19:28:55 +08:00
glGetIntegerv ( GL_MAX_TEXTURE_UNITS , & _numTextureUnits ) ;
2002-09-17 04:58:05 +08:00
2003-04-01 05:41:17 +08:00
_glCompressedTexImage2D = getGLExtensionFuncPtr ( " glCompressedTexImage2D " , " glCompressedTexImage2DARB " ) ;
2003-07-14 22:42:10 +08:00
_glCompressedTexSubImage2D = getGLExtensionFuncPtr ( " glCompressedTexSubImage2D " , " glCompressedTexSubImage2DARB " ) ;
2003-04-03 02:26:34 +08:00
_glGetCompressedTexImage = getGLExtensionFuncPtr ( " glGetCompressedTexImage " , " glGetCompressedTexImageARB " ) ; ;
2001-01-11 00:32:10 +08:00
}
2002-08-16 21:33:32 +08:00
2002-09-17 04:58:05 +08:00
void Texture : : Extensions : : glCompressedTexImage2D ( GLenum target , GLint level , GLenum internalformat , GLsizei width , GLsizei height , GLint border , GLsizei imageSize , const GLvoid * data ) const
2002-08-28 23:28:11 +08:00
{
2002-09-17 04:58:05 +08:00
if ( _glCompressedTexImage2D )
{
typedef void ( APIENTRY * CompressedTexImage2DArbProc ) ( GLenum target , GLint level , GLenum internalformat , GLsizei width , GLsizei height , GLint border , GLsizei imageSize , const GLvoid * data ) ;
2002-09-20 22:51:59 +08:00
( ( CompressedTexImage2DArbProc ) _glCompressedTexImage2D ) ( target , level , internalformat , width , height , border , imageSize , data ) ;
2002-09-17 04:58:05 +08:00
}
else
{
notify ( WARN ) < < " Error: glCompressedTexImage2D not supported by OpenGL driver " < < std : : endl ;
}
2002-08-28 23:28:11 +08:00
}
2003-04-01 05:41:17 +08:00
2003-07-14 22:42:10 +08:00
void Texture : : Extensions : : glCompressedTexSubImage2D ( GLenum target , GLint level , GLint xoffset , GLint yoffset , GLsizei width , GLsizei height , GLenum format , GLsizei imageSize , const GLvoid * data ) const
2003-04-01 05:41:17 +08:00
{
if ( _glCompressedTexImage2D )
{
2003-07-14 22:42:10 +08:00
typedef void ( APIENTRY * CompressedTexSubImage2DArbProc ) ( GLenum target , GLint level , GLint xoffset , GLint yoffset , GLsizei width , GLsizei height , GLenum format , GLsizei imageSize , const GLvoid * data ) ;
( ( CompressedTexSubImage2DArbProc ) _glCompressedTexSubImage2D ) ( target , level , xoffset , yoffset , width , height , format , imageSize , data ) ;
2003-04-01 05:41:17 +08:00
}
else
{
notify ( WARN ) < < " Error: glCompressedTexImage2D not supported by OpenGL driver " < < std : : endl ;
}
}
2003-04-03 02:26:34 +08:00
void Texture : : Extensions : : glGetCompressedTexImage ( GLenum target , GLint level , GLvoid * data ) const
{
if ( _glGetCompressedTexImage )
{
typedef void ( APIENTRY * GetCompressedTexImageArbProc ) ( GLenum target , GLint level , GLvoid * data ) ;
( ( GetCompressedTexImageArbProc ) _glGetCompressedTexImage ) ( target , level , data ) ;
}
else
{
notify ( WARN ) < < " Error: glGetCompressedTexImage not supported by OpenGL driver " < < std : : endl ;
}
}