Croquet & OpenGL extensions (was: RE: Croquet ARB_imaging)
andreas.raab at gmx.de
Sat Jan 4 00:13:04 UTC 2003
I finally got around to implement the "correct" solution for your
problem. I'm attaching a version which should work well with the base
Croquet version (if not, then check the iVars in GLX which is the only
problematic place). To use it, check out class GLExtManager and in
particular its *CLASS* side, for reasons following.
GLExtManager handles OpenGL extension functions for GLX. Since
extensions are specific for particular renderer/drivers all extensions
must be looked up dynamically. I provide the technical means to handle
extensions transparently for any number of contexts.
Extension functions (and constants) have to be specifically declared. To
declare functions and constants for an extension you need to do the
#1: Go to the CLASS side of GLExtManager and add a category that has the
same name as listed in glGet(GL_EXTENSIONS). For example, to use the ARB
imaging extension this category must be named GL_ARB_imaging (even
though the extension is referred to as 'ARB imaging' glGet will tell us
that the name GL_ARB_imaging so that is what you need to use).
WARNING: The name must match EXACTLY, no extra spaces, watch for small
and capital letters etc.
#2: Add a method which initializes the constants in this extension. The
method itself MUST follow the convention to begin with 'initialize' and
should then use the extension name. E.g., for initializing the constants
in the ARB_imaging it should be called 'initializeArbImaging'.
The constants itself can be initialized by just copying them from the
spec describing them and use the provided utility methods for
initialization (just look over a few existing extensions). I am trying
to make it easy for you to just copy those constants.
Note that all constants appear ONLY in the GLExtConstants -
OpenGLConstants is exclusively used for standard OpenGL constants.
#3: Add the functions the extension defines. Generally, these should
just be plain ffi call methods but there are three important issues:
a) NEVER provide a 'module' for these functions. Since they are
looked up by opengl specific means other ways are used and you MUST NOT
provide a module. The extension this particular function is contained in
is defined by the category and not by the module (this is to prevent
confusion about 'I have no GL_ARB_imaging.dll' or even worse the
possibility that on some system any such thing even exists (!)).
b) NEVER do anything but just the plain FFI call (optionally
followed by a plain return or call to #externalCallFailed). The method
you are writing will actually be run in an entirely different place -
you are only providing a template for the sake of your convenience (and
speed). If you need more sophisticated error handling do this in the
place where you call the method or provide a helper in GLX or something
similar, but NEVER EVER DO THIS HERE.
c) The calling convention is effectively ignored. Since it is
platform specific it will in fact be replaced by the appropriate OS
calling convention when used.
#4: Evaluate 'GLExtManager initialize' which will add the constants to
Once you declared the extension, using it is simple. Since the constants
defined by the extension are accessible through the GLExtConstants pool,
you can just refer to them by name.
To invoke an extension method you need to query for the GLX' extension
manager called 'glExt'. The extension manager is the guy who can
understand the extension functions you declared. To give an example, in
order to invoke the 'glUnlockArraysEXT' function you would use something
glx glExt glUnlockArraysEXT
IMPORTANT: You must NEVER, EVER keep a reference to the extension
manager. All invokations have to be done transparently through glx.
In case you wonder why you cannot use glx directly, read the
implementation details (the short answer is that there are Good Reasons
(tm) not to do it).
In order to implement the dynamic lookup mechanism in the most
convenient way, the GLExtManager is always created as a 'unique
subclass' of GLExtManager. That is when you ask for a new extension
manager using 'GLExtManager new' you actually get a subclass of
GLExtManager which is denoted by an asterisk in front of it so it looks
The *GLExtManager does not understand any of the function you have
provided. When it runs into a message which it doesn't understand it
performs the following functions:
1: First it looks if that method is in fact an extension method you
2: If it is, it looks if the extension this method belongs to is present
in the renderer it is bound to (e.g., the GLExtManager's glx inst var)
3: If the extension is present it looks at the functions you declared
for this extension, and for each function
- it copies the template method
- it looks up calling convention / address of the function
- it installs a new ffi call spec for that method
- it adds this method to *GLExtManager
4: Once all the function for the extension have been loaded it reinvokes
the message which failed.
As you can see from the implementation details, there is a certain
overhead involved in handling extensions. In particular, there can be a
noticable speed impact when an extension is loaded 'on demand' (e.g.,
when a message is not understood). To compensate for this, extensions
can be loaded explicitly, by using, e.g.,
glx glExt loadExtension: #'GL_ARB_imaging'.
BTW, if anyone needs particular extensions it would be nice if you'd add
them "to the pool" so that we can all easily use them (I hate typing all
-------------- next part --------------
A non-text attachment was scrubbed...
Size: 5113 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20030104/cbbb1a43/GLExt-ar.cs.bin
More information about the Squeak-dev