diff --git a/include/osg/Texture b/include/osg/Texture index a8b4aec39..55c8c9ec9 100644 --- a/include/osg/Texture +++ b/include/osg/Texture @@ -159,6 +159,14 @@ class SG_EXPORT Texture : public osg::StateAttribute /** Get the hint of whether to use hardware mip map generation where available.*/ inline bool getUseHardwareMipMapGeneration() const { return _useHardwareMipMapGeneration; } + /** Set the automatic unreference of image data after the texture has been set up in apply, on (true) or off (false). + * If the image data is only referened by this Texture then the image data will be autoamtically deleted.*/ + inline void setUnRefImageDataAfterApply(bool flag) { _unrefImageDataAfterApply = flag; } + + /** Get the automatic unreference of image data after the texture has been set up in apply.*/ + inline bool getUnRefImageDataAfterApply() const { return _unrefImageDataAfterApply; } + + enum InternalFormatMode { USE_IMAGE_DATA_FORMAT, USE_USER_DEFINED_FORMAT, @@ -333,6 +341,7 @@ class SG_EXPORT Texture : public osg::StateAttribute FilterMode _mag_filter; float _maxAnisotropy; bool _useHardwareMipMapGeneration; + bool _unrefImageDataAfterApply; Vec4 _borderColor; diff --git a/include/osg/TextureCubeMap b/include/osg/TextureCubeMap index 63ea6babe..af525e8cd 100644 --- a/include/osg/TextureCubeMap +++ b/include/osg/TextureCubeMap @@ -155,7 +155,7 @@ class SG_EXPORT TextureCubeMap : public Texture virtual void computeInternalFormat() const; - mutable ref_ptr _images[6]; + ref_ptr _images[6]; // subloaded images can have different texture and image sizes. mutable GLsizei _textureWidth, _textureHeight; diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp index e4694f801..32ebd9a5b 100644 --- a/src/osg/Texture.cpp +++ b/src/osg/Texture.cpp @@ -68,7 +68,8 @@ Texture::Texture(): _min_filter(LINEAR_MIPMAP_LINEAR), // trilinear _mag_filter(LINEAR), _maxAnisotropy(1.0f), - _useHardwareMipMapGeneration(false), + _useHardwareMipMapGeneration(true), + _unrefImageDataAfterApply(false), _borderColor(0.0, 0.0, 0.0, 0.0), _internalFormatMode(USE_IMAGE_DATA_FORMAT), _internalFormat(0) @@ -84,6 +85,7 @@ Texture::Texture(const Texture& text,const CopyOp& copyop): _mag_filter(text._mag_filter), _maxAnisotropy(text._maxAnisotropy), _useHardwareMipMapGeneration(text._useHardwareMipMapGeneration), + _unrefImageDataAfterApply(text._unrefImageDataAfterApply), _borderColor(text._borderColor), _internalFormatMode(text._internalFormatMode), _internalFormat(text._internalFormat) diff --git a/src/osg/Texture1D.cpp b/src/osg/Texture1D.cpp index 4b124d96d..b335041dc 100644 --- a/src/osg/Texture1D.cpp +++ b/src/osg/Texture1D.cpp @@ -144,6 +144,20 @@ void Texture1D::apply(State& state) const // update the modified tag to show that it is upto date. getModifiedTag(contextID) = _image->getModifiedTag(); + if (_unrefImageDataAfterApply) + { + // only unref image once all the graphics contexts has been set up. + unsigned int numLeftToBind=0; + for(unsigned int i=0;igetMaxNumberOfGraphicsContexts();++i) + { + if (_handleList[i]==0) ++numLeftToBind; + } + if (numLeftToBind==0) + { + Texture1D* non_const_this = const_cast(this); + non_const_this->_image = 0; + } + } // in theory the following line is redundent, but in practice // have found that the first frame drawn doesn't apply the textures diff --git a/src/osg/Texture2D.cpp b/src/osg/Texture2D.cpp index 628291705..ecfbb5b72 100644 --- a/src/osg/Texture2D.cpp +++ b/src/osg/Texture2D.cpp @@ -147,6 +147,22 @@ void Texture2D::apply(State& state) const // update the modified tag to show that it is upto date. getModifiedTag(contextID) = _image->getModifiedTag(); + + if (_unrefImageDataAfterApply) + { + // only unref image once all the graphics contexts has been set up. + int numLeftToBind=0; + for(int i=0;igetMaxNumberOfGraphicsContexts();++i) + { + if (_handleList[i]==0) ++numLeftToBind; + } + if (numLeftToBind==0) + { + Texture2D* non_const_this = const_cast(this); + non_const_this->_image = 0; + } + } + // in theory the following line is redundent, but in practice // have found that the first frame drawn doesn't apply the textures // unless a second bind is called?!! diff --git a/src/osg/Texture3D.cpp b/src/osg/Texture3D.cpp index a65941af9..9d4c47d3f 100644 --- a/src/osg/Texture3D.cpp +++ b/src/osg/Texture3D.cpp @@ -161,6 +161,21 @@ void Texture3D::apply(State& state) const // update the modified tag to show that it is upto date. getModifiedTag(contextID) = _image->getModifiedTag(); + if (_unrefImageDataAfterApply) + { + // only unref image once all the graphics contexts has been set up. + unsigned int numLeftToBind=0; + for(unsigned int i=0;igetMaxNumberOfGraphicsContexts();++i) + { + if (_handleList[i]==0) ++numLeftToBind; + } + if (numLeftToBind==0) + { + Texture3D* non_const_this = const_cast(this); + non_const_this->_image = 0; + } + } + // in theory the following line is redundent, but in practice // have found that the first frame drawn doesn't apply the textures // unless a second bind is called?!! diff --git a/src/osg/TextureCubeMap.cpp b/src/osg/TextureCubeMap.cpp index 82baa86b0..b9d1201f5 100644 --- a/src/osg/TextureCubeMap.cpp +++ b/src/osg/TextureCubeMap.cpp @@ -221,7 +221,7 @@ void TextureCubeMap::apply(State& state) const { for (int n=0; n<6; n++) { - osg::Image* image = _images[n].get(); + const osg::Image* image = _images[n].get(); if (image && getModifiedTag((Face)n,contextID) != image->getModifiedTag()) { applyTexImage2D_subload( faceTarget[n], _images[n].get(), state, _textureWidth, _textureHeight, _numMimpmapLevels); @@ -264,14 +264,37 @@ void TextureCubeMap::apply(State& state) const for (int n=0; n<6; n++) { - osg::Image* image = _images[n].get(); + const osg::Image* image = _images[n].get(); if (image) { applyTexImage2D_load( faceTarget[n], _images[n].get(), state, _textureWidth, _textureHeight, _numMimpmapLevels); getModifiedTag((Face)n,contextID) = image->getModifiedTag(); } + + } + if (_unrefImageDataAfterApply) + { + // only unref image once all the graphics contexts has been set up. + unsigned int numLeftToBind=0; + for(unsigned int i=0;igetMaxNumberOfGraphicsContexts();++i) + { + if (_handleList[i]==0) ++numLeftToBind; + } + if (numLeftToBind==0) + { + TextureCubeMap* non_const_this = const_cast(this); + for (int n=0; n<6; n++) + { + non_const_this->_images[n] = 0; + } + } + } + + + + // in theory the following line is redundent, but in practice // have found that the first frame drawn doesn't apply the textures // unless a second bind is called?!! diff --git a/src/osgPlugins/osg/Texture.cpp b/src/osgPlugins/osg/Texture.cpp index ac4b001d5..4529c0f7e 100644 --- a/src/osgPlugins/osg/Texture.cpp +++ b/src/osgPlugins/osg/Texture.cpp @@ -91,7 +91,7 @@ bool Texture_readLocalData(Object& obj, Input& fr) fr +=2 ; iteratorAdvanced = true; } - else if (fr[1].matchWord("TRUE")) + else if (fr[1].matchWord("FALSE")) { texture.setUseHardwareMipMapGeneration(false); fr +=2 ; @@ -99,6 +99,23 @@ bool Texture_readLocalData(Object& obj, Input& fr) } } + if (fr[0].matchWord("unRefImageDataAfterApply")) + { + if (fr[1].matchWord("TRUE")) + { + texture.setUnRefImageDataAfterApply(true); + fr +=2 ; + iteratorAdvanced = true; + } + else if (fr[1].matchWord("FALSE")) + { + texture.setUnRefImageDataAfterApply(false); + fr +=2 ; + iteratorAdvanced = true; + } + } + + Texture::InternalFormatMode mode; if (fr[0].matchWord("internalFormatMode") && Texture_matchInternalFormatModeStr(fr[1].getStr(),mode)) { @@ -135,6 +152,7 @@ bool Texture_writeLocalData(const Object& obj, Output& fw) fw.indent() << "maxAnisotropy " << texture.getMaxAnisotropy() << std::endl; fw.indent() << "useHardwareMipMapGeneration "<< (texture.getUseHardwareMipMapGeneration()?"TRUE":"FALSE") << std::endl; + fw.indent() << "unRefImageDataAfterApply "<< (texture.getUnRefImageDataAfterApply()?"TRUE":"FALSE") << std::endl; fw.indent() << "internalFormatMode " << Texture_getInternalFormatModeStr(texture.getInternalFormatMode()) << std::endl;