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>
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
2003-01-23 07:34:18 +08:00
// static cache of deleted display lists which can only
// by completely deleted once the appropriate OpenGL context
// is set.
typedef std : : vector < GLuint > TextureObjectVector ;
2003-02-13 03:20:47 +08:00
typedef std : : map < unsigned int , TextureObjectVector > DeletedTextureObjectCache ;
2003-01-23 07:34:18 +08:00
static DeletedTextureObjectCache s_deletedTextureObjectCache ;
2003-02-14 19:41:52 +08:00
void Texture : : deleteTextureObject ( unsigned int contextID , GLuint handle )
2003-01-23 07:34:18 +08:00
{
if ( handle ! = 0 )
{
// insert the handle into the cache for the appropriate context.
s_deletedTextureObjectCache [ contextID ] . push_back ( handle ) ;
}
}
2003-02-14 19:41:52 +08:00
void Texture : : flushDeletedTextureObjects ( unsigned int contextID )
2003-01-23 07:34:18 +08:00
{
DeletedTextureObjectCache : : iterator citr = s_deletedTextureObjectCache . find ( contextID ) ;
if ( citr ! = s_deletedTextureObjectCache . end ( ) )
{
TextureObjectVector textureObjectSet ;
// this swap will transfer the content of and empty citr->second
// in one quick pointer change.
textureObjectSet . swap ( citr - > second ) ;
for ( TextureObjectVector : : iterator titr = textureObjectSet . begin ( ) ;
titr ! = textureObjectSet . end ( ) ;
+ + titr )
{
glDeleteTextures ( 1L , & ( * titr ) ) ;
}
}
}
2002-07-21 09:29:11 +08:00
Texture : : Texture ( ) :
2002-08-28 23:28:11 +08:00
_wrap_s ( CLAMP ) ,
_wrap_t ( CLAMP ) ,
_wrap_r ( CLAMP ) ,
_min_filter ( LINEAR_MIPMAP_LINEAR ) , // trilinear
_mag_filter ( LINEAR ) ,
_maxAnisotropy ( 1.0f ) ,
2003-04-01 05:41:17 +08:00
_useHardwareMipMapGeneration ( false ) ,
2002-08-28 23:28:11 +08:00
_borderColor ( 0.0 , 0.0 , 0.0 , 0.0 ) ,
_internalFormatMode ( USE_IMAGE_DATA_FORMAT ) ,
_internalFormat ( 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 ) ,
2002-08-28 23:28:11 +08:00
_borderColor ( text . _borderColor ) ,
_internalFormatMode ( text . _internalFormatMode ) ,
_internalFormat ( text . _internalFormat )
{
}
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 )
COMPARE_StateAttribute_Parameter ( _internalFormat )
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-02-14 19:41:52 +08:00
for ( unsigned int i = 0 ; i < _handleList . size ( ) ; + + i )
2002-08-28 23:28:11 +08:00
{
if ( _handleList [ i ] ! = 0 )
2001-09-20 05:08:56 +08:00
{
2002-08-28 23:28:11 +08:00
Texture : : deleteTextureObject ( i , _handleList [ i ] ) ;
_handleList [ i ] = 0 ;
2001-09-20 05:08:56 +08:00
}
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
{
2003-02-14 19:41:52 +08:00
const unsigned int contextID = 0 ; // state.getContextID(); // set to 0 right now, assume same paramters for each graphics context...
2002-09-17 04:58:05 +08:00
const Extensions * extensions = getExtensions ( contextID , true ) ;
// static bool s_ARB_Compression = isGLExtensionSupported("GL_ARB_texture_compression");
// static bool s_S3TC_Compression = isGLExtensionSupported("GL_EXT_texture_compression_s3tc");
2001-01-11 00:32:10 +08:00
2002-08-28 23:28:11 +08:00
GLint internalFormat = image . getInternalTextureFormat ( ) ;
switch ( _internalFormatMode )
2001-01-11 00:32:10 +08:00
{
2002-08-28 23:28:11 +08:00
case ( USE_IMAGE_DATA_FORMAT ) :
internalFormat = image . getInternalTextureFormat ( ) ;
break ;
2002-07-21 02:27:40 +08:00
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 ;
case ( USE_USER_DEFINED_FORMAT ) :
internalFormat = _internalFormat ;
break ;
2001-01-11 00:32:10 +08:00
}
2002-08-28 23:28:11 +08:00
_internalFormat = internalFormat ;
}
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 ) ;
glTexParameteri ( target , GL_TEXTURE_WRAP_T , wt ) ;
2003-01-09 19:48:49 +08:00
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
}
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-04-01 19:49:09 +08:00
void Texture : : applyTexImage2D_load ( GLenum target , const Image * image , State & state , GLsizei & inwidth , GLsizei & inheight , GLsizei & numMimpmapLevels ) 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 ( ) ;
2001-09-20 05:08:56 +08:00
2002-08-28 23:28:11 +08:00
// update the modified tag to show that it is upto date.
getModifiedTag ( contextID ) = image - > getModifiedTag ( ) ;
2001-09-20 05:08:56 +08:00
2002-08-28 23:28:11 +08:00
// compute the internal texture format, this set the _internalFormat to an appropriate value.
computeInternalFormat ( ) ;
// select the internalFormat required for the texture.
2003-03-31 20:48:33 +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
unsigned char * data = ( unsigned char * ) image - > data ( ) ;
int s_powerOfTwo = Image : : computeNearestPowerOfTwo ( image - > s ( ) ) ;
int t_powerOfTwo = Image : : computeNearestPowerOfTwo ( image - > t ( ) ) ;
2002-08-28 23:28:11 +08:00
2003-04-01 19:49:09 +08:00
// cap the size to what the graphics hardware can handle.
if ( s_powerOfTwo > extensions - > maxTextureSize ( ) ) s_powerOfTwo = extensions - > maxTextureSize ( ) ;
if ( t_powerOfTwo > extensions - > maxTextureSize ( ) ) t_powerOfTwo = extensions - > maxTextureSize ( ) ;
bool needImageRescale = s_powerOfTwo ! = image - > s ( ) | | t_powerOfTwo ! = image - > t ( ) ;
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 ;
}
unsigned int newTotalSize = osg : : Image : : computeRowWidthInBytes ( s_powerOfTwo , image - > getPixelFormat ( ) , image - > getDataType ( ) , image - > getPacking ( ) ) * t_powerOfTwo ;
data = new unsigned char [ newTotalSize ] ;
if ( ! data )
{
notify ( WARN ) < < " Warning:: Not enough memory to resize image, cannot apply to texture. " < < std : : endl ;
return ;
}
if ( ! image - > getFileName ( ) . empty ( ) ) notify ( NOTICE ) < < " Scaling image ' " < < image - > getFileName ( ) < < " ' from ( " < < image - > s ( ) < < " , " < < image - > t ( ) < < " ) to ( " < < s_powerOfTwo < < " , " < < t_powerOfTwo < < " ) " < < std : : endl ;
else notify ( NOTICE ) < < " Scaling image from ( " < < image - > s ( ) < < " , " < < image - > t ( ) < < " ) to ( " < < s_powerOfTwo < < " , " < < t_powerOfTwo < < " ) " < < std : : endl ;
// rescale the image to the correct size.
glPixelStorei ( GL_PACK_ALIGNMENT , image - > getPacking ( ) ) ;
gluScaleImage ( image - > getPixelFormat ( ) ,
image - > s ( ) , image - > t ( ) , image - > getDataType ( ) , image - > data ( ) ,
s_powerOfTwo , t_powerOfTwo , image - > getDataType ( ) , data ) ;
}
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
{
2002-08-28 23:28:11 +08:00
numMimpmapLevels = 1 ;
2003-04-01 05:41:17 +08:00
2002-08-28 23:28:11 +08:00
glTexImage2D ( target , 0 , _internalFormat ,
2003-04-01 19:49:09 +08:00
s_powerOfTwo , t_powerOfTwo , 0 ,
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-04-01 05:41:17 +08:00
numMimpmapLevels = 1 ;
GLint blockSize = ( _internalFormat = = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 ) ;
2003-04-01 19:49:09 +08:00
GLint size = ( ( s_powerOfTwo + 3 ) / 4 ) * ( ( t_powerOfTwo + 3 ) / 4 ) * blockSize ;
2003-04-01 05:41:17 +08:00
extensions - > glCompressedTexImage2D ( target , 0 , _internalFormat ,
2003-04-01 19:49:09 +08:00
s_powerOfTwo , t_powerOfTwo , 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
{
2003-04-01 19:49:09 +08:00
// image is mip mapped so we take the mip map levels from the image.
2002-08-28 23:28:11 +08:00
numMimpmapLevels = image - > getNumMipmapLevels ( ) ;
2001-09-20 05:08:56 +08:00
2003-04-01 19:49:09 +08:00
int width = s_powerOfTwo ;
int height = t_powerOfTwo ;
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
{
for ( GLsizei k = 0 ; k < numMimpmapLevels & & ( width | | height ) ; k + + )
{
if ( width = = 0 )
width = 1 ;
if ( height = = 0 )
height = 1 ;
glTexImage2D ( target , k , _internalFormat ,
width , height , 0 ,
( 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 ;
for ( GLsizei k = 0 ; k < numMimpmapLevels & & ( 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 ,
width , height , 0 ,
size , image - > getMipmapData ( k ) ) ;
width > > = 1 ;
height > > = 1 ;
}
}
}
2003-04-01 19:49:09 +08:00
else
{
if ( ! compressed_image )
{
numMimpmapLevels = 0 ;
gluBuild2DMipmaps ( target , _internalFormat ,
s_powerOfTwo , t_powerOfTwo ,
( GLenum ) image - > getPixelFormat ( ) , ( GLenum ) image - > getDataType ( ) ,
data ) ;
int width = image - > s ( ) ;
int height = image - > t ( ) ;
for ( numMimpmapLevels = 0 ; ( width | | height ) ; + + numMimpmapLevels )
{
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
inwidth = s_powerOfTwo ;
inheight = t_powerOfTwo ;
if ( needImageRescale )
{
// clean up the resized image.
delete [ ] data ;
}
2003-04-01 05:41:17 +08:00
}
2003-04-01 19:49:09 +08:00
void Texture : : applyTexImage2D_subload ( GLenum target , const Image * image , State & state , GLsizei & inwidth , GLsizei & inheight , GLsizei & numMimpmapLevels ) 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.
if ( image - > s ( ) ! = inwidth | | image - > t ( ) ! = inheight )
{
2003-04-02 04:32:57 +08:00
applyTexImage2D_load ( target , image , state , inwidth , inheight , numMimpmapLevels ) ;
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 ( ) ;
// update the modified tag to show that it is upto date.
getModifiedTag ( contextID ) = image - > getModifiedTag ( ) ;
// compute the internal texture format, this set the _internalFormat to an appropriate value.
computeInternalFormat ( ) ;
// 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 ( ) ;
int s_powerOfTwo = Image : : computeNearestPowerOfTwo ( image - > s ( ) ) ;
int t_powerOfTwo = Image : : computeNearestPowerOfTwo ( image - > t ( ) ) ;
// cap the size to what the graphics hardware can handle.
if ( s_powerOfTwo > extensions - > maxTextureSize ( ) ) s_powerOfTwo = extensions - > maxTextureSize ( ) ;
if ( t_powerOfTwo > extensions - > maxTextureSize ( ) ) t_powerOfTwo = extensions - > maxTextureSize ( ) ;
bool needImageRescale = s_powerOfTwo ! = image - > s ( ) | | t_powerOfTwo ! = image - > t ( ) ;
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 ;
}
unsigned int newTotalSize = osg : : Image : : computeRowWidthInBytes ( s_powerOfTwo , image - > getPixelFormat ( ) , image - > getDataType ( ) , image - > getPacking ( ) ) * t_powerOfTwo ;
data = new unsigned char [ newTotalSize ] ;
if ( ! data )
{
notify ( WARN ) < < " Warning:: Not enough memory to resize image, cannot apply to texture. " < < std : : endl ;
return ;
}
if ( ! image - > getFileName ( ) . empty ( ) ) notify ( NOTICE ) < < " Scaling image ' " < < image - > getFileName ( ) < < " ' from ( " < < image - > s ( ) < < " , " < < image - > t ( ) < < " ) to ( " < < s_powerOfTwo < < " , " < < t_powerOfTwo < < " ) " < < std : : endl ;
else notify ( NOTICE ) < < " Scaling image from ( " < < image - > s ( ) < < " , " < < image - > t ( ) < < " ) to ( " < < s_powerOfTwo < < " , " < < t_powerOfTwo < < " ) " < < 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 ( ) ,
s_powerOfTwo , t_powerOfTwo , image - > getDataType ( ) , data ) ;
}
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-04-01 19:49:09 +08:00
s_powerOfTwo , t_powerOfTwo ,
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 ( ) )
{
extensions - > glCompressedTexSubImage2D ( target , 0 ,
0 , 0 ,
2003-04-01 19:49:09 +08:00
s_powerOfTwo , t_powerOfTwo ,
2003-04-01 05:41:17 +08:00
( GLenum ) image - > getPixelFormat ( ) ,
( GLenum ) image - > getDataType ( ) ,
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-04-01 19:49:09 +08:00
numMimpmapLevels = image - > getNumMipmapLevels ( ) ;
int width = s_powerOfTwo ;
int height = t_powerOfTwo ;
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-04-01 19:49:09 +08:00
for ( GLsizei k = 0 ; k < numMimpmapLevels & & ( width | | height ) ; k + + )
{
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 ;
for ( GLsizei k = 0 ; k < numMimpmapLevels & & ( width | | height ) ; k + + )
{
if ( width = = 0 )
width = 1 ;
if ( height = = 0 )
height = 1 ;
size = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 ) * blockSize ;
extensions - > glCompressedTexSubImage2D ( target , k ,
0 , 0 ,
width , height ,
( GLenum ) image - > getPixelFormat ( ) ,
( GLenum ) image - > getDataType ( ) ,
image - > getMipmapData ( k ) ) ;
2003-04-01 05:41:17 +08:00
2003-04-01 19:49:09 +08:00
width > > = 1 ;
height > > = 1 ;
}
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
numMimpmapLevels = 0 ;
2003-04-01 05:41:17 +08:00
2003-04-01 19:49:09 +08:00
int width = s_powerOfTwo ;
int height = t_powerOfTwo ;
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
2002-09-17 04:58:05 +08:00
void Texture : : compile ( State & state ) const
{
apply ( state ) ;
}
typedef buffered_value < ref_ptr < Texture : : Extensions > > BufferedExtensions ;
static BufferedExtensions s_extensions ;
2001-09-20 05:08:56 +08:00
2003-02-14 19:41:52 +08:00
const 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 ( )
{
setupGLExtenions ( ) ;
}
Texture : : Extensions : : Extensions ( const Extensions & rhs ) :
Referenced ( )
{
_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 ;
}
void Texture : : Extensions : : lowestCommonDenominator ( const Extensions & rhs )
{
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 ;
if ( ! rhs . _glCompressedTexImage2D ) _glCompressedTexImage2D = 0 ;
}
void Texture : : Extensions : : setupGLExtenions ( )
{
_isTextureFilterAnisotropicSupported = isGLExtensionSupported ( " GL_EXT_texture_filter_anisotropic " ) ;
2003-03-04 23:47:28 +08:00
_isTextureCompressionARBSupported = isGLExtensionSupported ( " GL_ARB_texture_compression " ) ;
_isTextureCompressionS3TCSupported = isGLExtensionSupported ( " GL_EXT_texture_compression_s3tc " ) ;
2002-09-17 04:58:05 +08:00
_isTextureMirroredRepeatSupported = isGLExtensionSupported ( " GL_IBM_texture_mirrored_repeat " ) ;
_isTextureEdgeClampSupported = isGLExtensionSupported ( " GL_EXT_texture_edge_clamp " ) ;
_isTextureBorderClampSupported = 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 " ) ;
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 ;
}
}
2003-04-01 05:41:17 +08:00
_glCompressedTexImage2D = getGLExtensionFuncPtr ( " glCompressedTexImage2D " , " glCompressedTexImage2DARB " ) ;
_glCompressedTexSubImage2D = getGLExtensionFuncPtr ( " glCompressedTexSubImage2D " , " glCompressedTexSubImage2DARB " ) ; ;
2002-09-17 04:58:05 +08:00
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
void Texture : : Extensions : : glCompressedTexSubImage2D ( GLenum target , GLint level , GLint xoffset , GLint yoffset , GLsizei width , GLsizei height , GLenum format , GLsizei type , const GLvoid * data ) const
{
if ( _glCompressedTexImage2D )
{
typedef void ( APIENTRY * CompressedTexSubImage2DArbProc ) ( GLenum target , GLint level , GLint xoffset , GLint yoffset , GLsizei width , GLsizei height , GLenum format , GLsizei type , const GLvoid * data ) ;
( ( CompressedTexSubImage2DArbProc ) _glCompressedTexSubImage2D ) ( target , level , xoffset , yoffset , width , height , format , type , data ) ;
}
else
{
notify ( WARN ) < < " Error: glCompressedTexImage2D not supported by OpenGL driver " < < std : : endl ;
}
}