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