#include #include #include #include #include #include typedef void (APIENTRY * MyCompressedTexImage2DArbProc) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); using namespace osg; Texture::Texture(): _wrap_s(CLAMP), _wrap_t(CLAMP), _wrap_r(CLAMP), _min_filter(LINEAR_MIPMAP_LINEAR), // trilinear _mag_filter(LINEAR), _maxAnisotropy(1.0f), _borderColor(0.0, 0.0, 0.0, 0.0), _internalFormatMode(USE_IMAGE_DATA_FORMAT), _internalFormat(0) { // _handleList.resize(DisplaySettings::instance()->getMaxNumberOfGraphicsContexts(),0); // _modifiedTag.resize(DisplaySettings::instance()->getMaxNumberOfGraphicsContexts(),0); // _texParametersDirtyList.resize(DisplaySettings::instance()->getMaxNumberOfGraphicsContexts(),true); } Texture::Texture(const Texture& text,const CopyOp& copyop): 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), _borderColor(text._borderColor), _internalFormatMode(text._internalFormatMode), _internalFormat(text._internalFormat) { // _handleList.resize(DisplaySettings::instance()->getMaxNumberOfGraphicsContexts(),0); // _modifiedTag.resize(DisplaySettings::instance()->getMaxNumberOfGraphicsContexts(),0); // _texParametersDirtyList.resize(DisplaySettings::instance()->getMaxNumberOfGraphicsContexts(),true); } Texture::~Texture() { // delete old texture objects. dirtyTextureObject(); } int Texture::compareTexture(const Texture& rhs) const { 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) COMPARE_StateAttribute_Parameter(_internalFormatMode) COMPARE_StateAttribute_Parameter(_internalFormat) return 0; } void Texture::setWrap(WrapParameter which, WrapMode wrap) { switch( which ) { case WRAP_S : _wrap_s = wrap; dirtyTextureParameters(); break; case WRAP_T : _wrap_t = wrap; dirtyTextureParameters(); break; case WRAP_R : _wrap_r = wrap; dirtyTextureParameters(); break; default : notify(WARN)<<"Error: invalid 'which' passed Texture::setWrap("<<(unsigned int)which<<","<<(unsigned int)wrap<<")"<1.0f) { // check for support for anisotropic filter, // note since this is static varible it is intialised // only on the first time entering this code block, // is then never reevaluated on subsequent calls. static bool s_anisotropicSupported = isGLExtensionSupported("GL_EXT_texture_filter_anisotropic"); if (s_anisotropicSupported) { // 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); } } if (s_borderClampSupported) { glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, _borderColor.ptr()); } getTextureParameterDity(state.getContextID()) = false; } void Texture::applyTexImage2D(GLenum target, Image* image, State& state, GLsizei& inwidth, GLsizei& inheight,GLsizei& numMimpmapLevels) const { // 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. const uint contextID = state.getContextID(); // 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 = isCompressedInternalFormat(_internalFormat); image->ensureValidSizeForTexturing(); glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking()); static MyCompressedTexImage2DArbProc glCompressedTexImage2D_ptr = (MyCompressedTexImage2DArbProc)getGLExtensionFuncPtr("glCompressedTexImage2DARB"); if( _min_filter == LINEAR || _min_filter == NEAREST ) { if ( !compressed ) { numMimpmapLevels = 1; glTexImage2D( target, 0, _internalFormat, image->s(), image->t(), 0, (GLenum)image->getPixelFormat(), (GLenum)image->getDataType(), image->data() ); } else if(glCompressedTexImage2D_ptr) { numMimpmapLevels = 1; GLint blockSize = ( _internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 ); GLint size = ((image->s()+3)/4)*((image->t()+3)/4)*blockSize; glCompressedTexImage2D_ptr(target, 0, _internalFormat, image->s(), image->t(),0, size, image->data()); } } else { if(!image->isMipmap()) { numMimpmapLevels = 1; gluBuild2DMipmaps( target, _internalFormat, image->s(),image->t(), (GLenum)image->getPixelFormat(), (GLenum)image->getDataType(), image->data() ); } else { numMimpmapLevels = image->getNumMipmapLevels(); int width = image->s(); int height = image->t(); if( !compressed ) { 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; } } else if(glCompressedTexImage2D_ptr) { 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; glCompressedTexImage2D_ptr(target, k, _internalFormat, width, height, 0, size, image->getMipmapData(k)); width >>= 1; height >>= 1; } } } } inwidth = image->s(); inheight = image->t(); } /////////////////////////////////////////////////////////////////////////////////////////////// // Static map to manage the deletion of texture objects are the right time. ////////////////////////////////////////////////////////////////////////////////////////////// #include #include // static cache of deleted display lists which can only // by completely deleted once the appropriate OpenGL context // is set. typedef std::map > DeletedTextureObjectCache; static DeletedTextureObjectCache s_deletedTextureObjectCache; void Texture::deleteTextureObject(uint contextID,GLuint handle) { if (handle!=0) { // insert the handle into the cache for the appropriate context. s_deletedTextureObjectCache[contextID].insert(handle); } } void Texture::flushDeletedTextureObjects(uint contextID) { DeletedTextureObjectCache::iterator citr = s_deletedTextureObjectCache.find(contextID); if (citr!=s_deletedTextureObjectCache.end()) { std::set& textureObjectSet = citr->second; for(std::set::iterator titr=textureObjectSet.begin(); titr!=textureObjectSet.end(); ++titr) { glDeleteTextures( 1L, &(*titr )); } s_deletedTextureObjectCache.erase(citr); } } GLint Texture::getMaxTextureSize() { static GLint s_maxTextureSize = 0; if (s_maxTextureSize == 0) { glGetIntegerv(GL_MAX_TEXTURE_SIZE,&s_maxTextureSize); notify(INFO) << "GL_MAX_TEXTURE_SIZE "<