2006-07-18 23:21:48 +08:00
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2003-01-22 00:45:36 +08:00
*
* 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>
2005-11-03 18:59:22 +08:00
# include <osg/ApplicationUsage>
2001-01-11 00:32:10 +08:00
2004-09-22 05:33:52 +08:00
# include <OpenThreads/ScopedLock>
# include <OpenThreads/Mutex>
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
2005-02-22 21:34:24 +08:00
// #define DO_TIMING
2005-11-03 18:59:22 +08:00
ApplicationUsageProxy Texture_e0 ( ApplicationUsage : : ENVIRONMENTAL_VARIABLE , " OSG_MAX_TEXTURE_SIZE " , " Set the maximum size of textures. " ) ;
2004-09-22 01:26:08 +08:00
unsigned int Texture : : s_numberTextureReusedLastInLastFrame = 0 ;
unsigned int Texture : : s_numberNewTextureInLastFrame = 0 ;
unsigned int Texture : : s_numberDeletedTextureInLastFrame = 0 ;
2004-09-22 05:33:52 +08:00
unsigned int s_minimumNumberOfTextureObjectsToRetainInCache = 0 ;
void Texture : : setMinimumNumberOfTextureObjectsToRetainInCache ( unsigned int minimum )
{
s_minimumNumberOfTextureObjectsToRetainInCache = minimum ;
}
unsigned int Texture : : getMinimumNumberOfTextureObjectsToRetainInCache ( )
{
return s_minimumNumberOfTextureObjectsToRetainInCache ;
}
2005-04-12 01:14:17 +08:00
class TextureObjectManager : public osg : : Referenced
2004-09-22 05:33:52 +08:00
{
public :
TextureObjectManager ( ) :
2006-08-02 23:41:47 +08:00
_expiryDelay ( 0.0 )
{
// printf("Constructing TextureObjectManager\n");
}
~ TextureObjectManager ( )
{
// printf("Destructing TextureObjectManager\n");
}
2004-09-22 05:33:52 +08:00
virtual Texture : : TextureObject * generateTextureObject ( unsigned int contextID , GLenum target ) ;
virtual Texture : : TextureObject * generateTextureObject ( unsigned int contextID ,
GLenum target ,
GLint numMipmapLevels ,
GLenum internalFormat ,
GLsizei width ,
GLsizei height ,
GLsizei depth ,
GLint border ) ;
virtual Texture : : TextureObject * reuseTextureObject ( unsigned int contextID ,
GLenum target ,
GLint numMipmapLevels ,
GLenum internalFormat ,
GLsizei width ,
GLsizei height ,
GLsizei depth ,
GLint border ) ;
inline Texture : : TextureObject * reuseOrGenerateTextureObject ( unsigned int contextID ,
GLenum target ,
GLint numMipmapLevels ,
GLenum internalFormat ,
GLsizei width ,
GLsizei height ,
GLsizei depth ,
GLint border )
{
Texture : : TextureObject * to = reuseTextureObject ( contextID , target , numMipmapLevels , internalFormat , width , height , depth , border ) ;
if ( to ) return to ;
else return generateTextureObject ( contextID , target , numMipmapLevels , internalFormat , width , height , depth , border ) ;
}
void addTextureObjects ( Texture : : TextureObjectListMap & toblm ) ;
void addTextureObjectsFrom ( Texture & texture ) ;
void flushAllTextureObjects ( unsigned int contextID ) ;
void flushTextureObjects ( unsigned int contextID , double currentTime , double & availableTime ) ;
void setExpiryDelay ( double expiryDelay ) { _expiryDelay = expiryDelay ; }
double getExpiryDelay ( ) const { return _expiryDelay ; }
/** How long to keep unused texture objects before deletion. */
double _expiryDelay ;
Texture : : TextureObjectListMap _textureObjectListMap ;
// mutex to keep access serialized.
OpenThreads : : Mutex _mutex ;
} ;
Texture : : TextureObject * TextureObjectManager : : generateTextureObject ( unsigned int /*contextID*/ , GLenum target )
2003-07-14 22:42:10 +08:00
{
GLuint id ;
glGenTextures ( 1L , & id ) ;
return new Texture : : TextureObject ( id , target ) ;
}
2004-09-22 01:26:08 +08:00
static int s_number = 0 ;
2004-09-22 05:33:52 +08:00
Texture : : TextureObject * TextureObjectManager : : generateTextureObject ( unsigned int /*contextID*/ ,
2003-07-14 22:42:10 +08:00
GLenum target ,
GLint numMipmapLevels ,
GLenum internalFormat ,
GLsizei width ,
GLsizei height ,
GLsizei depth ,
GLint border )
{
2004-09-22 01:26:08 +08:00
+ + s_number ;
2004-09-22 05:33:52 +08:00
+ + Texture : : s_numberNewTextureInLastFrame ;
2004-09-22 01:26:08 +08:00
// notify(NOTICE)<<"creating new texture object "<<s_number<<std::endl;
2003-07-14 22:42:10 +08:00
// 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 ) ;
}
2004-09-22 05:33:52 +08:00
Texture : : TextureObject * TextureObjectManager : : reuseTextureObject ( unsigned int contextID ,
2003-07-14 22:42:10 +08:00
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
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
2004-09-22 05:33:52 +08:00
Texture : : TextureObjectList & tol = _textureObjectListMap [ contextID ] ;
for ( Texture : : TextureObjectList : : iterator itr = tol . begin ( ) ;
2003-07-14 22:42:10 +08:00
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 ) ;
2004-09-22 01:26:08 +08:00
// notify(NOTICE)<<"reusing texture object "<<std::endl;
2003-07-14 22:42:10 +08:00
2004-09-22 05:33:52 +08:00
+ + Texture : : s_numberTextureReusedLastInLastFrame ;
2004-09-22 01:26:08 +08:00
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
2004-09-22 05:33:52 +08:00
void TextureObjectManager : : addTextureObjects ( Texture : : TextureObjectListMap & toblm )
2003-01-23 07:34:18 +08:00
{
2004-07-22 03:16:49 +08:00
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
2006-07-26 23:29:26 +08:00
for ( unsigned int i = 0 ; i < toblm . size ( ) ; + + i )
2003-01-23 07:34:18 +08:00
{
2006-07-26 23:29:26 +08:00
Texture : : TextureObjectList & tol = _textureObjectListMap [ i ] ;
tol . insert ( tol . end ( ) , toblm [ i ] . begin ( ) , toblm [ i ] . end ( ) ) ;
2003-07-14 22:42:10 +08:00
}
}
2004-09-22 05:33:52 +08:00
void TextureObjectManager : : addTextureObjectsFrom ( Texture & texture )
2003-07-14 22:42:10 +08:00
{
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 ) ;
}
2004-09-22 05:33:52 +08:00
void TextureObjectManager : : flushAllTextureObjects ( unsigned int contextID )
{
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
2006-07-26 23:29:26 +08:00
Texture : : TextureObjectList & tol = _textureObjectListMap [ contextID ] ;
2004-09-22 05:33:52 +08:00
2006-07-26 23:29:26 +08:00
for ( Texture : : TextureObjectList : : iterator itr = tol . begin ( ) ;
itr ! = tol . end ( ) ;
+ + itr )
{
glDeleteTextures ( 1L , & ( ( * itr ) - > _id ) ) ;
2004-09-22 05:33:52 +08:00
}
2006-07-26 23:29:26 +08:00
tol . clear ( ) ;
2004-09-22 05:33:52 +08:00
}
void 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-09-22 01:26:08 +08:00
unsigned int numObjectsDeleted = 0 ;
unsigned int maxNumObjectsToDelete = 4 ;
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-09-22 01:26:08 +08:00
unsigned int numTexturesDeleted = 0 ;
2004-07-22 03:16:49 +08:00
{
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
2003-07-16 17:52:43 +08:00
2006-07-26 23:29:26 +08:00
Texture : : TextureObjectList & tol = _textureObjectListMap [ contextID ] ;
// reset the time of any uninitialized objects.
Texture : : TextureObjectList : : iterator itr ;
for ( itr = tol . begin ( ) ;
itr ! = tol . end ( ) ;
+ + itr )
2003-07-14 22:42:10 +08:00
{
2006-07-26 23:29:26 +08:00
if ( ( * itr ) - > _timeStamp = = 0.0 ) ( * itr ) - > _timeStamp = currentTime ;
}
2004-07-22 03:16:49 +08:00
2006-07-26 23:29:26 +08:00
double expiryTime = currentTime - _expiryDelay ;
2004-07-22 03:16:49 +08:00
2006-07-26 23:29:26 +08:00
for ( itr = tol . begin ( ) ;
itr ! = tol . end ( ) & & elapsedTime < availableTime & & tol . size ( ) > s_minimumNumberOfTextureObjectsToRetainInCache & & numObjectsDeleted < maxNumObjectsToDelete ;
)
{
if ( ( * itr ) - > _timeStamp < = expiryTime )
{
- - s_number ;
+ + Texture : : s_numberDeletedTextureInLastFrame ;
2004-07-22 03:16:49 +08:00
2006-07-26 23:29:26 +08:00
glDeleteTextures ( 1L , & ( ( * itr ) - > _id ) ) ;
itr = tol . erase ( itr ) ;
+ + numTexturesDeleted ;
+ + numObjectsDeleted ;
}
else
2003-07-16 17:52:43 +08:00
{
2006-07-26 23:29:26 +08:00
+ + itr ;
2003-07-16 17:52:43 +08:00
}
2006-07-26 23:29:26 +08:00
elapsedTime = timer . delta_s ( start_tick , timer . tick ( ) ) ;
2004-07-22 03:16:49 +08:00
}
2003-01-23 07:34:18 +08:00
}
2004-09-22 01:26:08 +08:00
elapsedTime = timer . delta_s ( start_tick , timer . tick ( ) ) ;
// if (numTexturesDeleted) notify(osg::NOTICE)<<"Number of Texture's deleted = "<<numTexturesDeleted<<" new total "<<s_number<<" elapsed time"<<elapsedTime<<std::endl;
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
}
2004-09-22 05:33:52 +08:00
static TextureObjectManager * getTextureObjectManager ( )
2003-07-14 22:42:10 +08:00
{
2006-08-02 23:41:47 +08:00
static ref_ptr < TextureObjectManager > s_textureObjectManager = new TextureObjectManager ;
2004-09-22 05:33:52 +08:00
return s_textureObjectManager . get ( ) ;
2003-07-14 22:42:10 +08:00
}
2004-09-22 05:33:52 +08:00
Texture : : TextureObject * Texture : : generateTextureObject ( unsigned int contextID , GLenum target )
2003-07-14 22:42:10 +08:00
{
2006-08-02 23:41:47 +08:00
if ( getTextureObjectManager ( ) ) return getTextureObjectManager ( ) - > generateTextureObject ( contextID , target ) ;
else return 0 ;
2003-01-23 07:34:18 +08:00
}
2004-09-22 05:33:52 +08:00
Texture : : TextureObject * Texture : : generateTextureObject ( unsigned int contextID ,
GLenum target ,
GLint numMipmapLevels ,
GLenum internalFormat ,
GLsizei width ,
GLsizei height ,
GLsizei depth ,
GLint border )
{
2006-08-02 23:41:47 +08:00
if ( getTextureObjectManager ( ) )
return getTextureObjectManager ( ) - > reuseOrGenerateTextureObject ( contextID ,
2004-09-22 05:33:52 +08:00
target ,
numMipmapLevels ,
internalFormat ,
width ,
height ,
depth ,
border ) ;
2006-08-02 23:41:47 +08:00
else
return 0 ;
2004-09-22 05:33:52 +08:00
}
void Texture : : flushAllDeletedTextureObjects ( unsigned int contextID )
{
2006-08-02 23:41:47 +08:00
if ( getTextureObjectManager ( ) ) getTextureObjectManager ( ) - > flushAllTextureObjects ( contextID ) ;
2004-09-22 05:33:52 +08:00
}
void Texture : : flushDeletedTextureObjects ( unsigned int contextID , double currentTime , double & availbleTime )
2003-07-16 05:19:03 +08:00
{
2006-08-02 23:41:47 +08:00
if ( getTextureObjectManager ( ) ) getTextureObjectManager ( ) - > flushTextureObjects ( contextID , currentTime , availbleTime ) ;
2003-07-16 05:19:03 +08:00
}
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 ) ,
2005-11-24 18:28:09 +08:00
_resizeNonPowerOfTwoHint ( true ) ,
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 ) ,
2005-11-08 23:52:21 +08:00
_sourceFormat ( 0 ) ,
2005-11-09 18:41:52 +08:00
_sourceType ( 0 ) ,
2003-12-18 03:26:16 +08:00
_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 ) ,
2005-05-06 17:04:41 +08:00
_resizeNonPowerOfTwoHint ( text . _resizeNonPowerOfTwoHint ) ,
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 ) ,
2005-11-08 23:52:21 +08:00
_sourceFormat ( text . _sourceFormat ) ,
_sourceType ( text . _sourceType ) ,
2003-12-18 03:26:16 +08:00
_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-11-09 00:39:10 +08:00
// only compare _internalFomat is it has alrady been set in both lhs, and rhs
if ( _internalFormat ! = 0 & & rhs . _internalFormat ! = 0 )
{
COMPARE_StateAttribute_Parameter ( _internalFormat )
}
2005-11-08 23:52:21 +08:00
COMPARE_StateAttribute_Parameter ( _sourceFormat )
COMPARE_StateAttribute_Parameter ( _sourceType )
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 )
2005-05-06 17:04:41 +08:00
COMPARE_StateAttribute_Parameter ( _resizeNonPowerOfTwoHint )
2002-08-28 23:28:11 +08:00
return 0 ;
}
2001-09-22 10:42:08 +08:00
2006-08-15 03:42:22 +08:00
int Texture : : compareTextureObjects ( const Texture & rhs ) const
{
if ( _textureObjectBuffer . size ( ) < rhs . _textureObjectBuffer . size ( ) ) return - 1 ;
if ( rhs . _textureObjectBuffer . size ( ) < _textureObjectBuffer . size ( ) ) return 1 ;
for ( unsigned int i = 0 ; i < _textureObjectBuffer . size ( ) ; + + i )
{
if ( _textureObjectBuffer [ i ] < rhs . _textureObjectBuffer [ i ] ) return - 1 ;
else if ( rhs . _textureObjectBuffer [ i ] < _textureObjectBuffer [ i ] ) return 1 ;
}
return 0 ;
}
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 ( )
{
2006-08-02 23:41:47 +08:00
if ( getTextureObjectManager ( ) ) getTextureObjectManager ( ) - > addTextureObjectsFrom ( * this ) ;
2003-07-14 22:42:10 +08:00
}
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 ( ) ) ;
}
2006-06-30 21:47:12 +08:00
bool Texture : : isCompressedInternalFormat ( GLint internalFormat )
2002-08-28 23:28:11 +08:00
{
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 ) :
2004-09-30 20:10:45 +08:00
case ( GL_COMPRESSED_RGB_S3TC_DXT1_EXT ) :
2002-08-28 23:28:11 +08:00
case ( GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ) :
case ( GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ) :
case ( GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ) :
return true ;
default :
return false ;
}
}
2001-01-11 00:32:10 +08:00
2006-06-30 21:47:12 +08:00
void Texture : : getCompressedSize ( GLenum internalFormat , GLint width , GLint height , GLint depth , GLint & blockSize , GLint & size )
2004-09-30 17:10:29 +08:00
{
2004-11-14 05:42:45 +08:00
if ( internalFormat = = GL_COMPRESSED_RGB_S3TC_DXT1_EXT | | internalFormat = = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
2004-09-30 17:10:29 +08:00
blockSize = 8 ;
2006-07-05 21:44:07 +08:00
else if ( internalFormat = = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT | | internalFormat = = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT )
2004-09-30 17:10:29 +08:00
blockSize = 16 ;
2006-07-05 21:44:07 +08:00
else
{
notify ( WARN ) < < " Texture::getCompressedSize(...) : cannot compute correct size of compressed format ( " < < internalFormat < < " ) returning 0. " < < std : : endl ;
blockSize = 0 ;
}
2004-09-30 17:10:29 +08:00
size = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 ) * depth * blockSize ;
}
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 )
2005-08-09 18:47:21 +08:00
{
2003-12-18 03:26:16 +08:00
if ( _use_shadow_comparison )
2005-08-09 18:47:21 +08:00
{
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 )
2005-08-09 18:47:21 +08:00
{
2004-01-29 19:16:49 +08:00
glTexParameterf ( target , TEXTURE_COMPARE_FAIL_VALUE_ARB , _shadow_ambient ) ;
2005-08-09 18:47:21 +08:00
}
}
2003-12-18 03:26:16 +08:00
else
2005-08-09 18:47:21 +08:00
{
2003-12-18 03:26:16 +08:00
glTexParameteri ( target , GL_TEXTURE_COMPARE_MODE_ARB , GL_NONE ) ;
2005-08-09 18:47:21 +08:00
}
}
2003-12-18 03:26:16 +08:00
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 ) ;
2005-05-06 17:04:41 +08:00
int width , height ;
2005-05-17 19:00:13 +08:00
if ( ! _resizeNonPowerOfTwoHint & & extensions - > isNonPowerOfTwoTextureSupported ( _min_filter ) )
2005-05-06 17:04:41 +08:00
{
width = image . s ( ) ;
height = image . t ( ) ;
}
else
{
width = Image : : computeNearestPowerOfTwo ( image . s ( ) - 2 * _borderWidth ) + 2 * _borderWidth ;
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 ( ) ;
2005-05-06 17:04:41 +08:00
2003-07-14 22:42:10 +08:00
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
}
2004-09-30 17:10:29 +08:00
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 ;
2005-02-22 21:34:24 +08:00
# ifdef DO_TIMING
osg : : Timer_t start_tick = osg : : Timer : : instance ( ) - > tick ( ) ;
osg : : notify ( osg : : NOTICE ) < < " glTexImage2D pixelFormat = " < < std : : hex < < image - > getPixelFormat ( ) < < std : : dec < < std : : endl ;
# endif
2002-08-28 23:28:11 +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-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 ( ) ) ;
2006-07-06 22:14:19 +08:00
// If the texture's internal format is a compressed type, then the
// user is requesting that the graphics card compress the image if it's
// not already compressed. However, if the image is not a multiple of
// four in each dimension the subsequent calls to glTexSubImage* will
// fail. Revert to uncompressed format in this case.
if ( isCompressedInternalFormat ( _internalFormat ) & &
( ( ( inwidth > > 2 ) < < 2 ) ! = inwidth | |
( ( inheight > > 2 ) < < 2 ) ! = inheight ) )
{
osg : : notify ( osg : : NOTICE ) < < " Received a request to compress an image, but image size is not a multiple of four ( " < < inwidth < < " x " < < inheight < < " ). Reverting to uncompressed. \n " ;
switch ( _internalFormat )
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT :
case GL_COMPRESSED_RGB : _internalFormat = GL_RGB ; break ;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT :
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT :
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT :
case GL_COMPRESSED_RGBA : _internalFormat = GL_RGBA ; break ;
case GL_COMPRESSED_ALPHA : _internalFormat = GL_ALPHA ; break ;
case GL_COMPRESSED_LUMINANCE : _internalFormat = GL_LUMINANCE ; break ;
case GL_COMPRESSED_LUMINANCE_ALPHA : _internalFormat = GL_LUMINANCE_ALPHA ; break ;
case GL_COMPRESSED_INTENSITY : _internalFormat = GL_INTENSITY ; break ;
}
}
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
}
2005-05-25 17:50:11 +08:00
unsigned char * dataMinusOffset = 0 ;
unsigned char * dataPlusOffset = 0 ;
2003-04-01 19:49:09 +08:00
2005-02-22 21:34:24 +08:00
const PixelBufferObject * pbo = image - > getPixelBufferObject ( ) ;
2006-08-25 16:48:16 +08:00
if ( pbo & & pbo - > isPBOSupported ( contextID ) & & ! needImageRescale )
2005-02-22 21:34:24 +08:00
{
pbo - > compileBuffer ( state ) ;
pbo - > bindBuffer ( contextID ) ;
2005-05-25 17:50:11 +08:00
dataMinusOffset = data ;
dataPlusOffset = reinterpret_cast < unsigned char * > ( pbo - > offset ( ) ) ;
2005-02-22 21:34:24 +08:00
# ifdef DO_TIMING
osg : : notify ( osg : : NOTICE ) < < " after PBO " < < osg : : Timer : : instance ( ) - > delta_m ( start_tick , osg : : Timer : : instance ( ) - > tick ( ) ) < < " ms " < < std : : endl ;
# endif
}
else
{
pbo = 0 ;
}
bool useHardwareMipMapGeneration = ! image - > isMipmap ( ) & & _useHardwareMipMapGeneration & & generateMipMapSupported ;
2003-04-01 19:49:09 +08:00
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 ( ) ,
2005-02-22 21:34:24 +08:00
data - dataMinusOffset + dataPlusOffset ) ;
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
2004-09-30 17:10:29 +08:00
GLint blockSize , size ;
getCompressedSize ( _internalFormat , inwidth , inheight , 1 , blockSize , size ) ;
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 ,
2005-02-22 21:34:24 +08:00
data - dataMinusOffset + dataPlusOffset ) ;
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 ( ) ,
2005-02-22 21:34:24 +08:00
image - > getMipmapData ( k ) - dataMinusOffset + dataPlusOffset ) ;
2002-08-28 23:28:11 +08:00
width > > = 1 ;
height > > = 1 ;
}
}
2002-09-17 04:58:05 +08:00
else if ( extensions - > isCompressedTexImage2DSupported ( ) )
2002-08-28 23:28:11 +08:00
{
2004-09-30 17:10:29 +08:00
GLint blockSize , size ;
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
2004-09-30 17:10:29 +08:00
getCompressedSize ( _internalFormat , width , height , 1 , blockSize , size ) ;
2004-09-30 20:10:45 +08:00
2003-04-01 05:41:17 +08:00
extensions - > glCompressedTexImage2D ( target , k , _internalFormat ,
2004-01-28 05:29:58 +08:00
width , height , _borderWidth ,
2005-02-22 21:34:24 +08:00
size , image - > getMipmapData ( k ) - dataMinusOffset + dataPlusOffset ) ;
2003-04-01 05:41:17 +08:00
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 ( ) ,
2005-02-22 21:34:24 +08:00
data - dataMinusOffset + dataPlusOffset ) ;
2003-04-01 19:49:09 +08:00
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
}
2005-02-22 21:34:24 +08:00
if ( pbo )
{
pbo - > unbindBuffer ( contextID ) ;
}
# ifdef DO_TIMING
static double s_total_time = 0.0 ;
double delta_time = osg : : Timer : : instance ( ) - > delta_m ( start_tick , osg : : Timer : : instance ( ) - > tick ( ) ) ;
s_total_time + = delta_time ;
osg : : notify ( osg : : NOTICE ) < < " glTexImage2D " < < delta_time < < " ms total " < < s_total_time < < " ms " < < std : : endl ;
# endif
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
2006-07-06 22:14:19 +08:00
// If the texture's internal format is a compressed type, then the
// user is requesting that the graphics card compress the image if it's
// not already compressed. However, if the image is not a multiple of
// four in each dimension the subsequent calls to glTexSubImage* will
// fail. Revert to uncompressed format in this case.
if ( isCompressedInternalFormat ( _internalFormat ) & &
( ( ( inwidth > > 2 ) < < 2 ) ! = inwidth | |
( ( inheight > > 2 ) < < 2 ) ! = inheight ) )
{
applyTexImage2D_load ( state , target , image , inwidth , inheight , numMipmapLevels ) ;
return ;
}
2005-02-22 21:34:24 +08:00
# ifdef DO_TIMING
osg : : Timer_t start_tick = osg : : Timer : : instance ( ) - > tick ( ) ;
osg : : notify ( osg : : NOTICE ) < < " glTexSubImage2D pixelFormat = " < < std : : hex < < image - > getPixelFormat ( ) < < std : : dec < < std : : endl ;
# endif
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 ;
2005-02-09 18:39:45 +08:00
2005-05-25 17:50:11 +08:00
unsigned char * dataMinusOffset = 0 ;
unsigned char * dataPlusOffset = 0 ;
2005-02-09 18:39:45 +08:00
const PixelBufferObject * pbo = image - > getPixelBufferObject ( ) ;
2006-08-25 16:48:16 +08:00
if ( pbo & & pbo - > isPBOSupported ( contextID ) & & ! needImageRescale )
2005-02-09 18:39:45 +08:00
{
pbo - > compileBuffer ( state ) ;
pbo - > bindBuffer ( contextID ) ;
2005-05-25 17:50:11 +08:00
dataMinusOffset = data ;
dataPlusOffset = reinterpret_cast < unsigned char * > ( pbo - > offset ( ) ) ;
2005-02-22 21:34:24 +08:00
# ifdef DO_TIMING
osg : : notify ( osg : : NOTICE ) < < " after PBO " < < osg : : Timer : : instance ( ) - > delta_m ( start_tick , osg : : Timer : : instance ( ) - > tick ( ) ) < < " ms " < < std : : endl ;
# endif
2005-02-09 18:39:45 +08:00
}
else
{
pbo = 0 ;
}
2003-04-01 19:49:09 +08:00
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 ( ) ,
2005-02-22 21:34:24 +08:00
data - dataMinusOffset + dataPlusOffset ) ;
2003-03-31 20:48:33 +08:00
2003-04-01 05:41:17 +08:00
}
else if ( extensions - > isCompressedTexImage2DSupported ( ) )
{
2004-09-30 17:10:29 +08:00
GLint blockSize , size ;
2006-07-06 05:52:36 +08:00
getCompressedSize ( image - > getInternalTextureFormat ( ) , inwidth , inheight , 1 , blockSize , size ) ;
2003-07-14 22:42:10 +08:00
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 ,
2005-02-22 21:34:24 +08:00
data - dataMinusOffset + dataPlusOffset ) ;
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 ( ) ,
2005-02-22 21:34:24 +08:00
image - > getMipmapData ( k ) - dataMinusOffset + dataPlusOffset ) ;
2003-04-01 19:49:09 +08:00
width > > = 1 ;
height > > = 1 ;
}
}
else if ( extensions - > isCompressedTexImage2DSupported ( ) )
{
2004-09-30 17:10:29 +08:00
GLint blockSize , size ;
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 ;
2006-07-06 05:52:36 +08:00
getCompressedSize ( image - > getInternalTextureFormat ( ) , width , height , 1 , blockSize , size ) ;
2003-04-01 19:49:09 +08:00
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 ,
2005-02-22 21:34:24 +08:00
image - > getMipmapData ( k ) - dataMinusOffset + dataPlusOffset ) ;
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
{
2005-09-29 17:49:20 +08:00
//notify(WARN)<<"Warning:: cannot subload mip mapped texture from non mipmapped image."<<std::endl;
applyTexImage2D_load ( state , target , image , inwidth , inheight , numMipmapLevels ) ;
return ;
2002-08-28 23:28:11 +08:00
}
}
2005-02-09 18:39:45 +08:00
if ( pbo )
{
pbo - > unbindBuffer ( contextID ) ;
}
2005-02-22 21:34:24 +08:00
# ifdef DO_TIMING
osg : : notify ( osg : : NOTICE ) < < " glTexSubImage2D " < < osg : : Timer : : instance ( ) - > delta_m ( start_tick , osg : : Timer : : instance ( ) - > tick ( ) ) < < " ms " < < std : : endl ;
# endif
2005-02-09 18:39:45 +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
{
2004-08-02 21:57:47 +08:00
if ( ! state ) const_cast < Texture * > ( this ) - > dirtyTextureObject ( ) ;
else
{
unsigned int contextID = state - > getContextID ( ) ;
2006-08-02 23:41:47 +08:00
if ( _textureObjectBuffer [ contextID ] . valid ( ) & & getTextureObjectManager ( ) )
2004-08-02 21:57:47 +08:00
{
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( getTextureObjectManager ( ) - > _mutex ) ;
getTextureObjectManager ( ) - > _textureObjectListMap [ contextID ] . push_back ( _textureObjectBuffer [ contextID ] ) ;
_textureObjectBuffer [ contextID ] = 0 ;
}
}
2004-07-20 13:37:59 +08:00
}
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
{
2005-04-26 21:15:27 +08:00
if ( ! s_extensions [ contextID ] & & createIfNotInitalized ) s_extensions [ contextID ] = new Extensions ( contextID ) ;
2002-09-17 04:58:05 +08:00
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 ;
}
2005-04-26 21:15:27 +08:00
Texture : : Extensions : : Extensions ( unsigned int contextID )
2002-09-17 04:58:05 +08:00
{
2005-04-26 21:15:27 +08:00
setupGLExtensions ( contextID ) ;
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 ;
2005-05-05 17:18:03 +08:00
2005-05-17 19:00:13 +08:00
_isNonPowerOfTwoTextureMipMappedSupported = rhs . _isNonPowerOfTwoTextureMipMappedSupported ;
_isNonPowerOfTwoTextureNonMipMappedSupported = rhs . _isNonPowerOfTwoTextureNonMipMappedSupported ;
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 ;
2005-05-05 17:18:03 +08:00
2005-05-17 19:00:13 +08:00
if ( ! rhs . _isNonPowerOfTwoTextureMipMappedSupported ) _isNonPowerOfTwoTextureMipMappedSupported = false ;
if ( ! rhs . _isNonPowerOfTwoTextureNonMipMappedSupported ) _isNonPowerOfTwoTextureNonMipMappedSupported = false ;
2002-09-17 04:58:05 +08:00
}
2005-04-26 21:15:27 +08:00
void Texture : : Extensions : : setupGLExtensions ( unsigned int contextID )
2002-09-17 04:58:05 +08:00
{
2005-10-29 18:04:35 +08:00
const char * version = ( const char * ) glGetString ( GL_VERSION ) ;
if ( ! version )
{
osg : : notify ( osg : : FATAL ) < < " Error: In Texture::Extensions::setupGLExtensions(..) OpenGL version test failed, requires valid graphics context. " < < std : : endl ;
return ;
}
float glVersion = atof ( ( const char * ) version ) ;
2005-05-17 19:00:13 +08:00
const char * renderer = ( const char * ) glGetString ( GL_RENDERER ) ;
std : : string rendererString ( renderer ? renderer : " " ) ;
2004-04-16 18:05:57 +08:00
_isMultiTexturingSupported = ( glVersion > = 1.3 ) | |
2005-04-26 21:15:27 +08:00
isGLExtensionSupported ( contextID , " GL_ARB_multitexture " ) | |
isGLExtensionSupported ( contextID , " GL_EXT_multitexture " ) ;
_isTextureFilterAnisotropicSupported = isGLExtensionSupported ( contextID , " GL_EXT_texture_filter_anisotropic " ) ;
2004-05-17 21:20:41 +08:00
_isTextureCompressionARBSupported = ( glVersion > = 1.3 ) | |
2005-04-26 21:15:27 +08:00
isGLExtensionSupported ( contextID , " GL_ARB_texture_compression " ) ;
_isTextureCompressionS3TCSupported = isGLExtensionSupported ( contextID , " GL_EXT_texture_compression_s3tc " ) ;
2004-05-17 21:20:41 +08:00
_isTextureMirroredRepeatSupported = ( glVersion > = 1.4 ) | |
2005-04-26 21:15:27 +08:00
isGLExtensionSupported ( contextID , " GL_IBM_texture_mirrored_repeat " ) | |
isGLExtensionSupported ( contextID , " GL_ARB_texture_mirrored_repeat " ) ;
2004-04-16 18:05:57 +08:00
_isTextureEdgeClampSupported = ( glVersion > = 1.2 ) | |
2005-04-26 21:15:27 +08:00
isGLExtensionSupported ( contextID , " GL_EXT_texture_edge_clamp " ) | |
isGLExtensionSupported ( contextID , " GL_SGIS_texture_edge_clamp " ) ;
2004-05-17 21:20:41 +08:00
_isTextureBorderClampSupported = ( glVersion > = 1.3 ) | |
2005-04-26 21:15:27 +08:00
isGLExtensionSupported ( contextID , " GL_ARB_texture_border_clamp " ) ;
2003-03-04 23:47:28 +08:00
_isGenerateMipMapSupported = ( strncmp ( ( const char * ) glGetString ( GL_VERSION ) , " 1.4 " , 3 ) > = 0 ) | |
2005-04-26 21:15:27 +08:00
isGLExtensionSupported ( contextID , " GL_SGIS_generate_mipmap " ) ;
_isShadowSupported = isGLExtensionSupported ( contextID , " GL_ARB_shadow " ) ;
_isShadowAmbientSupported = isGLExtensionSupported ( contextID , " GL_ARB_shadow_ambient " ) ;
2002-09-17 04:58:05 +08:00
2005-04-26 21:15:27 +08:00
_isClientStorageSupported = isGLExtensionSupported ( contextID , " GL_APPLE_client_storage " ) ;
2004-03-09 01:09:58 +08:00
2005-05-17 19:00:13 +08:00
_isNonPowerOfTwoTextureNonMipMappedSupported = ( glVersion > = 2.0 ) | |
2005-05-05 17:18:03 +08:00
isGLExtensionSupported ( contextID , " GL_ARB_texture_non_power_of_two " ) ;
2005-05-17 19:00:13 +08:00
_isNonPowerOfTwoTextureMipMappedSupported = _isNonPowerOfTwoTextureNonMipMappedSupported ;
2005-05-18 04:12:13 +08:00
if ( rendererString . find ( " Radeon " ) ! = std : : string : : npos | | rendererString . find ( " RADEON " ) ! = std : : string : : npos )
2005-05-17 19:00:13 +08:00
{
_isNonPowerOfTwoTextureMipMappedSupported = false ;
osg : : notify ( osg : : INFO ) < < " Disabling _isNonPowerOfTwoTextureMipMappedSupported for ATI hardware. " < < std : : endl ;
}
2005-06-22 19:02:37 +08:00
if ( rendererString . find ( " GeForce FX " ) ! = std : : string : : npos )
{
_isNonPowerOfTwoTextureMipMappedSupported = false ;
osg : : notify ( osg : : INFO ) < < " Disabling _isNonPowerOfTwoTextureMipMappedSupported for GeForce FX hardware. " < < std : : endl ;
}
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-09-01 18:41:50 +08:00
if ( _isMultiTexturingSupported )
{
glGetIntegerv ( GL_MAX_TEXTURE_UNITS , & _numTextureUnits ) ;
}
else
{
_numTextureUnits = 1 ;
}
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
{
2004-09-29 18:01:46 +08:00
if ( _glCompressedTexSubImage2D )
2003-04-01 05:41:17 +08:00
{
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 ;
}
}
2005-09-29 17:49:20 +08:00