How to use SDL_GL_LoadLibrary/SDL_GL_GetProcAddress in a sensible way?

hi

i’ve written a small opengl benchmark prog.
so far, it works fine, but i want to give the user the possibility to choose
a nondefault opengl lib.
i can use the SDL_GL_LoadLibrary(userDefinedGlLib) function to load the lib.
but after that, i have to use SDL_GL_GetProcAddress to retrieve function
pointers to GL functions. and that’s my problem.
i know this could be done in the way:
myglBegin = (glBegin_t) SDL_GL_GetProcAddress(“glBegin”);

but i have to do this for all gl* functions.
is there a sensible way to write a function like “leloadAllGlProcs()” that
updates all gl* functions (and extensions).
has someone an idea how this could be done?—
klaus gieb

There is a sensible way to do it - SDL uses a similar (less advanced)
method, but it works out the same way (and is infinitely cleaner than the
way Quake 2 and 3 do it!)

Create a file dopengl.h, transfer all of the constants and stuff from your
existing gl.h into it, along with the copyright notice of course. Hint,
use Mesa’s headers so you don’t have evil "unpublished proprietary source"
messages like SDL does - SDL needs to do the same thing as someone else
pointed out.

Now here comes the fun part:

// If you need to define this, do it in config.h
#ifndef DOPENGLENTRY
#define DOPENGLENTRY
#endif

#define DOPENGL_NEED(ret, name, args)
extern ret (DOPENGLENTRY * q##name) args
#define DOPENGL_WANT(ret, name, args, altfunc)
extern ret (DOPENGLENTRY * q##name) args
#define DOPENGL_EXT(ret, name, args, extension)
extern ret (DOPENGLENTRY * q##name) args

#include “dopengl_funcs.h”

#undef DOPENGL_NEED
#undef DOPENGL_WANT
#undef DOPENGL_EXT

Before I get much further, I should explain these defines. DOPENGL_NEED
is used for functions which must exist or the program won’t run. If we
get a NULL back from SDL_GL_GetProcAddress for one of these, the program
exits with an error.

DOPENGL_WANT is what we use for functions which should be in the lib, but
aren’t there. Several braindead OpenGL drivers exist (3dfx, PowerVR, etc)
which leave out basically any part of the OpenGL spec that Id Software is
not using. =p If we can actually live without the function, this is what
we use. Note that DOPENGL_WANT will let you supply a NULL altfunc, but if
you do that beware the consiquences.

DOPENGL_EXT functions are dependant on a named extension. The first thing
you do after processing all the DOPENGL_NEED and DOPENGL_WANT functions is
parse the extensions list into something more managable and try to get the
DOPENGL_EXT functions. Note that we only try if the extension is reported
and a needed function isn’t there (ie, the driver is lying to us), we just
report a warning and disable the extension.

Now, for dopengl_funcs.h:

#define DOPENGL_DONT_NEED(ret, func, params)
#define DOPENGL_DONT_WANT(ret, func, params, altfunc)
#define DOPENGL_DONT_EXT(ret, func, params, extension)
#ifndef DOPENGL_NEED
#error “dopengl_funcs.h included without DOPENGL_NEED”
#endif
#ifndef DOPENGL_WANT
#error “dopengl_funcs.h included without DOPENGL_WANT”
#endif
#ifndef DOPENGL_EXT
#error “dopengl_funcs.h included without DOPENGL_EXT”
#endif

DOPENGL_DONT_NEED(void, glAccum, (GLenum op, GLfloat value))
DOPENGL_EXT(void, glActiveTextureARB, (GLenum), “GL_ARB_multitexture”)
DOPENGL_NEED(void, glAlphaFunc, (GLenum func, GLclampf ref))
DOPENGL_DONT_EXT(void, glApplyTextureEXT, (GLenum), “GL_EXT_light_texture”)
:

…basically every function prototype from your header gl.h and glext.h
goes here.

              :

#undef DOPENGL_DONT_NEED
#undef DOPENGL_DONT_WANT
#undef DOPENGL_DONT_EXT

Now we go to code! Something like this should be found in dopengl.c:

#include “dopengl.h”

#define DOPENGL_NEED(ret, name, args)
ret (DOPENGLENTRY * q##name) args = NULL;
#define DOPENGL_WANT(ret, name, args, altfunc)
ret (DOPENGLENTRY * q##name) args = NULL;
#define DOPENGL_EXT(ret, name, args)
ret (DOPENGLENTRY * q##name) args = NULL;

#include “dopengl_funcs.h”
#undef DOPENGL_NEED
#undef DOPENGL_WANT
#undef DOPENGL_EXT

This gives you a set of function pointers and cleanly sets them all to
NULL for the time being. It also explains why the _DONT versions exist,
to save a little memory. Then you’re going to need this in a function
called after SDL_SetVideoMode is called:

#define DOPENGL_NEED(ret, name, args)
if (!(q##name = SDL_GL_GetProcAddress(#name))) {
YourErrorPrintf (“can’t find %s\n”, #name)
return 0;
}
#define DOPENGL_WANT(ret, name, args, altfunc)
if (!(q##name = SDL_GL_GetProcAddress(#name))) {
YourPrintf (“OpenGL is missing %s, using alternate\n”, #name);
q##name = altfunc;
}
#define DOPENGL_EXT(ret, name, args, extension)
#include “dopengl_funcs.h”

ParseExtensionsList (qglGetString (GL_EXTENSIONS));

#undef DOPENGL_NEED
#define DOPENGL_NEED(ret, name, args)
#undef DOPENGL_WANT
#define DOPENGL_WANT(ret, name, args, altfunc)
#undef DOPENGL_EXT
#define DOPENGL_EXT(ret, name, args, extension)
if (CheckExtension (extension)) {
if (!(q##name = SDL_GL_GetProcAddress(#name))) {
YourPrintf (“OpenGL lied about having %s, disabling.\n”,
#name);
RemoveExtension (extension);
}
}
#include “dopengl_funcs.h”
#undef DOPENGL_NEED
#undef DOPENGL_WANT
#undef DOPENGL_EXT

Obviously what you do with YourPrintf, YourErrorPrintf, CheckExtension,
RemoveExtension, and ParseExtensionList are totally up to you - the names
I used here are obviously not very good. Change that or be slapped around
like a redheaded stepchild when someone else looks at your code.

For the extensions list, I recommend you strtok the string into a linked
list to make removal easier. Yes I know strtok has lots of issues, but
they don’t apply here and it makes it easy to either mark an extension as
not really there (if you want your game to be able to print out an
extensions list which indicates that the driver lied to us, for example…)

This is as clean as it gets. You’ll have to maintain your own dopengl.h
and dopengl_funcs.h this way. Just remember to call SDL_GL_LoadLibrary
before you call SDL_SetVideoMode and call the above only after that.
Also, on win32, you need to set OPENGLENTRY to APIENTRY and make sure that
you include windows.h in dopengl.h - I do not know if you can define
WIN32_LEAN_AND_MEAN when you do so, you’ll have to check that if you care.On Mon, Mar 18, 2002 at 03:21:37PM +0100, Klaus Gieb wrote:

i’ve written a small opengl benchmark prog.
so far, it works fine, but i want to give the user the possibility to choose
a nondefault opengl lib.
i can use the SDL_GL_LoadLibrary(userDefinedGlLib) function to load the lib.
but after that, i have to use SDL_GL_GetProcAddress to retrieve function
pointers to GL functions. and that’s my problem.
i know this could be done in the way:
myglBegin = (glBegin_t) SDL_GL_GetProcAddress(“glBegin”);

but i have to do this for all gl* functions.
is there a sensible way to write a function like “leloadAllGlProcs()” that
updates all gl* functions (and extensions).
has someone an idea how this could be done?


Joseph Carter Do not write in this space

And don’t get me started on perl!
:>
perl is beyond evil
you don’t know perl yet?
gotta love a language with no definable syntax

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020318/a2a71ada/attachment.pgp

hi
the method described by Joseph Carter (in the
previous mail on this subject) works fine. - thanks.
i use c++, so i had to make some small changes (eg. a cast to (ret (*)args)
from void):
#define DOPENGL_NEED(ret, name, args)
if (!(q##name = (ret (
)args)SDL_GL_GetProcAddress(#name))) {
fprintf (stderr, “Error in loading OpenGL: Function %s not found.\n”,
#name);
return;
}
the main problem in this solution is, to write a sensible dopengl_funcs.h.
(currently i use only DOPENGL_NEED because this can be done very fast
with a texteditor. it works fine for mesaGL an the nvidiaGL on linux).

but there is still a (small) problem:
if i load a libGL.so.somevendor that is not suitable for my system,
SDL_GL_LoadLibrary(libFile) reports success, but after a
SDL_SetVideoMode(…) call i get a seg-fault. how could this be avoided?—
klaus

You’re saying that if you load the wrong libGL you get a segfault? Not sure there’s a way around that…

-EvilTypeGuyOn Thu, Mar 21, 2002 at 05:39:12PM +0100, Klaus Gieb wrote:

but there is still a (small) problem:
if i load a libGL.so.somevendor that is not suitable for my system,
SDL_GL_LoadLibrary(libFile) reports success, but after a
SDL_SetVideoMode(…) call i get a seg-fault. how could this be avoided?

the method described by Joseph Carter (in the
previous mail on this subject) works fine. - thanks.
i use c++, so i had to make some small changes (eg. a cast to (ret (*)args)
from void):
#define DOPENGL_NEED(ret, name, args)
if (!(q##name = (ret (
)args)SDL_GL_GetProcAddress(#name))) {
fprintf (stderr, “Error in loading OpenGL: Function %s not found.\n”,
#name);
return;
}

Yes, thanks, I forgot this. It may also require you stick DOPENGLENTRY
someplace in there too, but I forget if that is required or not.

the main problem in this solution is, to write a sensible dopengl_funcs.h.
(currently i use only DOPENGL_NEED because this can be done very fast
with a texteditor. it works fine for mesaGL an the nvidiaGL on linux).

My suggestion is that you take the Mesa headers and use those. Start with
everything as a _DONT and then as you need functions, add them. I would
like at some point to impelement a thing which is capible of telling you
if you are using functions that you haven’t got, but at the moment I don’t
have a good solution for doing this.

but there is still a (small) problem:
if i load a libGL.so.somevendor that is not suitable for my system,
SDL_GL_LoadLibrary(libFile) reports success, but after a
SDL_SetVideoMode(…) call i get a seg-fault. how could this be avoided?

This is not something that can be fixed by your code. Patching SDL is
required so that it is able to fail gracefully. I’m betting it’s not
checking the errors or something when it does a SetVideoMode. In fact I’m
guessing that it doesn’t.On Thu, Mar 21, 2002 at 05:39:12PM +0100, Klaus Gieb wrote:


Joseph Carter Intelligent backside at large

Lucas’ Law: Good will always win, because evil hires the stupid
engineers.

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020321/0295ba13/attachment.pgp

> > the main problem in this solution is, to write a sensible dopengl_funcs.h. > > (currently i use only DOPENGL_NEED because this can be done very fast > > with a texteditor. it works fine for mesaGL an the nvidiaGL on linux). > > My suggestion is that you take the Mesa headers and use those. Start with > everything as a _DONT and then as you need functions, add them. I would > like at some point to impelement a thing which is capible of telling you > if you are using functions that you haven't got, but at the moment I don't > have a good solution for doing this.

Actually for Twilight I used a simple grep to get the list of functions
being used (easy), then indent and some perl to take the list of
functions, and a mesa GL header and spit out the file with _NEED and
_DONT as was already used.

I should still have those scripts around here somewhere if someone wants
them.

Zephaniah E. Hull.
(The guy who did all this the first time.)On Thu, Mar 21, 2002 at 10:24:29AM -0800, Joseph Carter wrote:

On Thu, Mar 21, 2002 at 05:39:12PM +0100, Klaus Gieb wrote:


1024D/E65A7801 Zephaniah E. Hull <@Zephaniah_E_Hull>
92ED 94E4 B1E6 3624 226D 5727 4453 008B E65A 7801
CCs of replies from mailing lists are requested.

My kid brother tells me Visual Age for Java is the cat’s pajamas

I’m not a cat person, but I can just imagine the reaction of your
average feline to someone’s attempt to stuff it into a pair of
pajamas.

Now picture your hard disk after the thing installs.
– Berry Kercheval and Graham Reed on ASR.
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020321/74de5b42/attachment.pgp