Remove proliferation of static containers that had previously characterised the extensions setup
All laudable goals I'm sure you'd agree, but... while I have achieved all of these goals with what I've checked into svn/trunk over the past few days there isn't something I haven't been able to avoid - changing the API's associated with set up and getting extensions.
For most users I don't expect any build issues with these API changes but for those whose application specifically get OpenGL extensions via the old Extension classes like GL2Extensions then you may see build errors that will required local changes to keep things compiling.
The new scheme is pretty straight forward so changing things to keep things compiling shouldn't be difficult, often you'll end up with the same or less code required to do the job.
The main changes are:
osg::State now has a local container that hold Extension objects,
this replaces the old static ones that used to live with StateAttribute subclasses etc.
To get the Extension objects from the osg::State object you use form:
MyExtensionObject* mso = state->get<MyExtensionObject>();
If no MyExtensionObject has been used before then osg::State will construct one for you, assign it to its local container then return it. Future calls will then return that original MyExtensionObject.
To implement a custom extension object you simply used the form:
struct MyExtensionObject : public osg::Referenced
{
MyExtensionObject(unsigned int contextID)
{
osg::setGLExtensionFuncPtr(glNewGLFunction, "glNewGLFunction");
}
void (GL_APIENTRY * glNewGLFunction)(GLsizei n, const GLenum *bufs);
};
If you then want to invoke the GL extension you'd used;
MyExtensionObject* mso = state->get<MyExtensionObject>();
if (mso->glNewGLFunction!=0) glNewGLFunction(n, bufs);
This is far far simpler than it used to, taking a quarter as much code than the old convoluted scheme ;-)
The new scheme is pretty lightweight making it easier to have lots of local Extension objects, but for performance I feel that it's better for us to group all the most commonly used OpenGL extensions into a single extensions object so that can all sit together in the cache. This new class is call GLExtensions and there is a fast track implementation for it assigned to the osg::State as soon as a GraphicsContext::makeCurrent() is called. To get this extension object you use exactly the same calling convention:
GLExtensions* ext = state->get<GLExtensions>();
Previous we had a GL2Extensions that partially had this role - originally for GL2 related extensions, however, over the years more and post GL2 functionality has been pushed into it. Often contributors don't really know where things should go, and to be honest it was no exactly clear to me either - a good marker that something was amiss with the old approach and the reason why I've undertaken this refactor.
All the old GL2Extensions functionality has now been put into the GLExtensions class, along with all the local Extension functionality that used to sit with various StateAttribute classes. With pulling all of these functionality out of the StateAttributes the individual headers get smaller and more straight forward to read/maintain. Unfortunately if your code directly got one of these local Extension classes you'll find your build broken, in which case you'll need to just use the state->get<GLExtensions>() usage mentioned above.
There are certain places in the OSG code base where extensions are needed by the appropriate osg::State for the current graphics context isn't available, for this case the old static access methods used to be used, so I've had to maintain these for GLExtensions object, so you'll now get them via static GLExtensions* GLExtensions::Get(contextID, createFlag); method in the same way that GL2Extensions::Get(..) used to be used. I'm not entirely happy with this old bit of design living on but for now haven't come up with a reason alternative that doesn't require refactoring more OSG code than I'm prepared to do right now.
Another change I have made is to move the #define that used to be in GL2Extensions header into a new GLDefines header. This GLDefines header is included by the GLExtensions header so most applications won't need to include it directly.
--
These changes are now part of OSG svn/trunk, and will be part of OSG-3.3.3 dev release that I'll tag this week. The total line count include/osg directory is now actually smaller in 3.3.3 than 3.3.2 despite introduction of several new classes and associated new OpenGL functionality. The libosg.so is also 5% smaller in 3.3.3 and 3.3.2.
Smaller, easier to use, easier to extend, easier to maintain and faster. But please be patient the build breakages :-)
If you see build/runtime errors let me know right away via this thread and I'll provide guidance on how to resolve them as they appear.
Cheers,
Robert.