I've encountered a bug in osg's OpenGL texture object management. The
problem appears to be that osg texture objects aren't being cleaned when
a context ID in which they are used is subsequently reused. I know this
problem has come up on the list before, and various workarounds
suggested, but it appears to me that this is a bug within osg and needs
to be fixed in the library.
The sequence of events is as follows:
1. Create context C1 with contextID 0.
2. Render a scene into context C1 using Texture T.
- T now has allocated an OpenGL texture ID for context ID 0.
3. Remove texture from scene. (Depending on how the scene was rendered,
this step may not be necessary.)
4. Destroy context C1.
5. Create context C2, reusing contextID 0.
6. Render a scene into context C2 using same Texture T.
7. Texture T believes it is still initialized for contextID 0 so does
not reload its image data.
Here is sample code to illustrate the problem. Only the first viewer
created correctly displays the red texture.
#include <osg/Texture2D>
#include <osg/ShapeDrawable>
#include <osgViewer/Viewer>
int main(int, char **)
{
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
osg::Image* image = new osg::Image;
static unsigned char bytes[] = { 0xff, 0x00, 0x00, 0xff };
image->setImage(1, 1, 1, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE,
&bytes[0], osg::Image::NO_DELETE, 1);
texture->setImage(image);
for( int i = 0; i < 2; ++i )
{
osgViewer::Viewer viewer;
osg::Geode* geode = new osg::Geode();
geode->addDrawable(new osg::ShapeDrawable(new
osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),1)));
viewer.setSceneData( geode );
osg::StateSet* stateset = new osg::StateSet();
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateset->setTextureAttributeAndModes(0, texture.get(),
osg::StateAttribute::ON);
geode->setStateSet( stateset );
viewer.run();
// If texture is removed from scene before viewer is destroyed,
// it does not get reinitialized when used in a different scene.
stateset->removeTextureAttribute(0, texture.get());
}
return 0;
}
One work around is simply not to reuse context IDs. This is unacceptable
for programs that don't create a limited number of windows during their
course of execution.
Another work around is to keep track of all textures created and
manually call releaseGLObjects when a context is destroyed. This becomes
more difficult when using plugins such as freetype that create their own
textures.
I think the best solution is to modify core osg to maintain a list much
like the _textureObjectListMap in TextureObjectManager, but have it
store all TextureObjects initialized, not just those that are no longer
used by an osg texture.
I suspect there may be similar problems with management of other OpenGL
resources such as shaders and buffer objects.
Mark
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org