Tue, 15 Oct 2002 18:14:24 +0200: 0.3.5 is just a minor bugfix release.

Wed, 25 Sep 2002 09:39:22 +0200: 0.3.3 couldn't wait to be released with working tracing and breaking!

Tue, 24 Sep 2002 16:15:25 +0200: 0.3.2 came running and making noise shortly after 0.3.1.

Mon, 23 Sep 2002 21:10:57 +0200: 0.3.1 saw the light of day (the darkness of night actually)


spyGLass is an OpenGL call tracer and debugging aid. It outputs the OpenGL function call including the values of the parameters passed to the function. Filtering is implemented externally (think grep) as I find that model more appealing and it keeps the code simple. It handles enumerations properly and input pointers are on the TODO list. With some work it could be extended to make it produce compilable code.

Besides tracing, it also does error trapping (without hiding it from the application). If you ever spent a night figuring out where your mistake was by sprinkling your code with glGetError() calls, you know this can be a really welcomed feature. DRI and Mesa 3D users know about MESA_DEBUG, but sadly not every OpenGL vendor is developer friendly.


It is implemented as a shared library to be preloaded using the dynamic linker. It contains its own version of the OpenGL library calls, which in turn call the system's OpenGL counterparts, that is the native OpenGL library does all the work, while spyGLass provides only tracing and error checking. The source for spyGLass is automatically generated using the OpenGL Sample Implementation spec files. This means the function set is not only complete but also correct. The current parser is hand-crafted Perl code. If one day I feel like it, I will change it to something using Parse::RecDescent, but the current code works for now and it isn't that ugly.


spyGLass is easy to use on the command line. Behold:

$ spyglass ./savetheints
glXChooseVisual(0x804a260, 0, attriblist);
glXCreateContext(0x804a260, 0x804be18, (nil), 1);
glXIsDirect(0x804a260, 0x804f790);
glXMakeCurrent(0x804a260, 23068673, 0x804f790);
glClearColor(0.5, 0.5, 0.5, 1);
glXMakeCurrent(0x804a260, 23068673, 0x804f790);
glViewport(0, 0, 400, 400);
glOrtho(-1, 1, -1, 1, -1, 1);
glXMakeCurrent(0x804a260, 23068673, 0x804f790);
glVertex2d(-0.5, -0.5);
glVertex2d(0.5, -0.5);
glVertex2d(0.5, 0.5);
glVertex2d(-0.5, 0.5);
glXSwapBuffers(0x804a260, 23068673);
glXMakeCurrent(0x804a260, 23068673, 0x804f790);

And there's a GUI in the works:

Where to get it?

Visit the project's page at Source Forge for more information on dowload and CVS access.

Random musings

Perhaps spyGLass is a bit overkill for what you want to do. Here's a handy macro that wraps glGetError:

#if defined(NDEBUG)
# define GL_CHECK_ERROR() 1
# if defined(__GNUC__)
#  define GL_CHECK_ERROR()                          \
    do                                              \
    {                                               \
        GLenum error = glGetError();                \
        if (error != GL_NO_ERROR)                   \
            fprintf(stderr, "E: %s(%d): %s 0x%X\n", \
                    __FILE__, __LINE__,             \
                    __PRETTY_FUNCTION__, error);    \
    } while(0)
# else
#  define GL_CHECK_ERROR()                          \
    do                                              \
    {                                               \
        GLenum error = glGetError();                \
        if (error != GL_NO_ERROR)                   \
            fprintf(stderr, "E: %s(%d): 0x%X\n",    \
                    __FILE__, __LINE__, error);     \
    } while(0)
# endif

As it stands the first definition is GCC specific, because __PRETTY_FUNCTION__ is a GCCism (as well as __FUNCTION__ AFAIR). Other than that, this should work with any ANSI C compiler. If you define NDEBUG the macro will be defined as a noop thus enabling its use in shipping code, too.

Related stuff

glxforker is nifty trick, even if a bit out of sync with the current version of the same idea. I have to clean that up. Like spyglass, this is also a library to be preloaded into your program. It will intercept a few (for now) GLX calls, open another window on another server, create a GLX context on it, direct your program to this context, read out the rendered image using glReadPixels and write that to the original window. The original purpose of this was to get VNC working with OpenGL clients, which can be trivially achieved using Mesa and its "fakeglx" implementation, but that kind of defeats having an Onyx doing the rendering work (actually you don't need VNC at all if this is what you want to do, a remote shell and glxforker are all you need). This "solution" can take advantage of hardware accelerated rendering, at the cost of needing some trickery on the server side (err... "server" in this case is the machine doing the OpenGL rendering, where the client runs -- it can get pretty confusing after five minutes of talking about it). There's much room for optimization, but it gets ugly fast. It works on PCs (under Linux) and SGIs (under IRIX). It will use PBuffers if available (the code is rough at the edges and doesn't handle cases where the pbuffers are too small) as well as the MIT-SHM extension. The README provides some porting instructions.

If you need something similar to spyGLass for the Windows platform, take a look at GLTrace from Hawk Software.


spyGLass is developed by Marcelo E. Magallón. The first GUI was developed entirely by Baris Bikmaz, Özgür Sen and Tobias Weideman.