diff --git a/include/osg/Texture2D b/include/osg/Texture2D index ee954d0da..7fc528c2c 100644 --- a/include/osg/Texture2D +++ b/include/osg/Texture2D @@ -87,6 +87,12 @@ class OSG_EXPORT Texture2D : public Texture class OSG_EXPORT SubloadCallback : public Referenced { public: + + virtual bool textureObjectValid(const Texture2D& texture, State& state) const + { + return texture.textureObjectValid(state); + } + virtual TextureObject* generateTextureObject(const Texture2D& texture, State& state) const { return osg::Texture::generateTextureObject(&texture, state.getContextID(), GL_TEXTURE_2D); @@ -132,6 +138,8 @@ class OSG_EXPORT Texture2D : public Texture * compiled, create the texture mipmap levels. */ virtual void apply(State& state) const; + + protected : virtual ~Texture2D(); @@ -139,6 +147,10 @@ class OSG_EXPORT Texture2D : public Texture virtual void computeInternalFormat() const; void allocateMipmap(State& state) const; + /** Return true of the TextureObject assigned to the context associate with osg::State object is valid.*/ + bool textureObjectValid(State& state) const; + + friend class SubloadCallback; ref_ptr _image; diff --git a/src/osg/Texture2D.cpp b/src/osg/Texture2D.cpp index ab23c61b3..cbc46f2ea 100644 --- a/src/osg/Texture2D.cpp +++ b/src/osg/Texture2D.cpp @@ -125,6 +125,25 @@ void Texture2D::setImage(Image* image) } } +bool Texture2D::textureObjectValid(State& state) const +{ + TextureObject* textureObject = getTextureObject(state.getContextID()); + if (!textureObject) return false; + + // return true if image isn't assigned as we won't be override the value. + if (!_image) return true; + + // compute the internal texture format, this set the _internalFormat to an appropriate value. + computeInternalFormat(); + + GLsizei new_width, new_height, new_numMipmapLevels; + + // compute the dimensions of the texture. + computeRequiredTextureDimensions(state, *_image, new_width, new_height, new_numMipmapLevels); + + return textureObject->match(GL_TEXTURE_2D, new_numMipmapLevels, _internalFormat, new_width, new_height, 1, _borderWidth); +} + void Texture2D::apply(State& state) const { @@ -141,25 +160,24 @@ void Texture2D::apply(State& state) const // get the texture object for the current contextID. TextureObject* textureObject = getTextureObject(contextID); - - if (textureObject) + if (textureObject && !textureObjectValid(state)) { - if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount()) + bool textureObjectInvalidated = false; + if (_subloadCallback.valid()) { - // compute the internal texture format, this set the _internalFormat to an appropriate value. - computeInternalFormat(); + textureObjectInvalidated = !_subloadCallback->textureObjectValid(*this, state); + } + else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount()) + { + textureObjectInvalidated = !textureObjectValid(state); + } - GLsizei new_width, new_height, new_numMipmapLevels; - - // compute the dimensions of the texture. - computeRequiredTextureDimensions(state, *_image, new_width, new_height, new_numMipmapLevels); - - if (!textureObject->match(GL_TEXTURE_2D, new_numMipmapLevels, _internalFormat, new_width, new_height, 1, _borderWidth)) - { - Texture::releaseTextureObject(contextID, _textureObjectBuffer[contextID].get()); - _textureObjectBuffer[contextID] = 0; - textureObject = 0; - } + if (textureObjectInvalidated) + { + OSG_NOTICE<<"Discarding TextureObject"<