OglDump
An OpenGL Analysis Tool
Authored by Don Burns
OglDump is intended for use by programmers that are familiar with a development environment, the C/C++ programming language and OpenGL. Current functionality has been tested with :
Applications may then link dynamically to this libGL.so (rather than system libGL.so), trap and view commands, by either using the built in functionality via environmental variables, or altered _gl.c code.
Makefile |
Builds parser, libGL.so or both. |
Parser |
Contains source code for the parser |
doc |
A directory containing documentation |
include |
Some include directories used by the parser |
srcfiles |
Source files for building final ogldump code. |
vectors.h |
Used for internal parsing of OpenGL vector arguments |
Typing 'make' in this directory attempts to build the parser, generate code for libGL.so and compile libGL.so. You may build just the parser by typing 'make parser' or changing to the Parser directory and typing 'make'.
A 'make' session on an Irix 6.5/OpenGL 1.2 follows:
don_burns@peru 49% makeAt this point the parser is made and resides in the OglDump root directory. The historical C preprocessor is then invoked to produce "pure" C code as input to the parser's stdin.
cd Parser; make
CC -g -c parser.C
yacc -d parse.y
1 rules never reducedconflicts: 4 reduce/reduce
cc -O -c y.tab.c
rm -f y.tab.c
mv -f y.tab.o parse.o
lex lex.l
cc -O -c lex.yy.c
rm -f lex.yy.c; mv -f lex.yy.o lex.o
CC -g parser.o parse.o lex.o -ll -o ../parser(Possible C++ prelinker info here)
At this point, _gl.c, _gl.h, ogldump.c and ogldump.h have been generated from source files in the srcfiles directory and definitions in the system glx.h header file. Note that glx.h is used but not gl.h, since glx.h normally includes gl.h. Also note that if you want to make code changes to the generated files that persist beyond future parsing of the system glx.h, then you must make this changes either in the corresponding file in srcfiles/ file or in Parser/parser.C.
/lib/cpp -D_MIPS_SZINT=32 -D_LANGUAGE_C -P \ -I./include \ /usr/include/GL/glx.h | parser
Note that -I./include is passed to the preprocessor. This directory contains some lightweight versions of X11 header files, containing only the needed definitions for the purpose of OglDump. Using the standard system X11 files would result in a need for an unecessarily complex parser due to the large scope.
cc -g -c _gl.c
cc -g -c ogldump.c
cc -g -g -shared _gl.o ogldump.o -o libGL.so
Due to the light weight parsing approach of the parser, and differences
in systems, it is likely that there will be problems at this point.
If you are able to ascertain these problems and fix them, please send the
author
an update and an email regarding your fixes.
setenv LD_PRELOAD `pwd`/libGL.so.1
setenv LD_LIBRARY_PATH `pwd`It is entirely probable that your application is not linked directly to libGL.so, but rather to something like libGL.so.1. Assuming your executable is named myexecutable, test this with ldd. For example
don_burns@peru 60% pwdIn the above case, myexecutable is, indeed linked to the libGL.so in the current directory. If however, the ldd command had output :
/DonsDisk/OglDump
don_burns@peru 61% ldd myexecutable
libGLU.so => /usr/lib32/libGLU.so
libGL.so => /DonsDisk/OglDump/libGL.so
libX11.so.1 => /usr/lib32/libX11.so.1
libm.so => /usr/lib32/libm.so
libimage.so => /usr/lib32/libimage.so
libCsup.so => /usr/lib32/libCsup.so
libC.so.2 => /usr/lib32/libC.so.2
libc.so.1 => /usr/lib32/libc.so.1
libGL.so.1 => /usr/lib32/libGL.so.1
then, link libGL.so with libGL.so.1
ln -s libGL.so libGL.so.1All of this assumes that LD_LIBRARY_PATH is set to the current directory.
don_burns@peru 62% myexecutableThis is there to remind you (who the author is and) that your are linked to the analysis library. There is a performance penalty for running with the analysis library and it is best that it not be silent. Other than the message printed to the shell, the program should run normally.
**************************************************
WARNING
USING Ogldump libGL.so libraryDon Burns
(Some Date)
**************************************************
Two environmental variables invoke built in functionality:
OGLDUMP_ENABLETurns on printing of all OpenGL calls, with their arguments and values (where possible). However, this is still not very useful since it is difficult to read all commands as they fly by, even if you are a speed reader. It is more interesting to take the output of a single frame. The assumption is made here that the OpenGL application is double buffered, such that a frame boundary is defined by glXSwapBuffers(). Use, then,
OGLDUMP_FRAME=nwhere n is the number of the frame you want to dump to the stdout. n may not be less than 1, and n=1 is the first frame of execution. Alternately,you may specify a range of frames, as in:
OGLDUMP_FRAME=30,80
A simple example follows:
don_burns@peru 63% setenv OGLDUMP_FRAME 60
don_burns@peru 64% ./myexecutable
**************************************************
WARNING
USING Ogldump libGL.so libraryDon Burns
Mar 8, 2002
**************************************************
-------------- OGLDUMP Frame 60 ----------------
glViewport( x = 0, y = 0, width = 640, height = 480 )
glClearColor( red = 0.0000, green = 0.0000, blue = 0.0000, alpha = 1.0000 )
glClear( mask = GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT )
glMatrixMode( mode = GL_PROJECTION )
glLoadIdentity()
glMultMatrixd({
{ 1.2990 0.0000 0.0000 0.0000 }
{ 0.0000 1.7321 0.0000 0.0000 }
{ 0.0000 0.0000 -1.0020 -1.0000 }
{ 0.0000 0.0000 -2.0020 0.0000 }
)
glMatrixMode( mode = GL_MODELVIEW )
glLoadIdentity()
glMultMatrixf({
{ 1.0000 0.0000 0.0000 0.0000 }
{ 0.0000 1.0000 0.0000 0.0000 }
{ 0.0000 0.0000 1.0000 0.0000 }
{ 0.0000 0.0000 0.0000 1.0000 }
)
glTranslated( x = 0.0000, y = 0.0000, z = -7.0000 )
glMultMatrixf({
{ 1.0000 0.0000 0.0000 0.0000 }
{ 0.0000 1.0000 0.0000 0.0000 }
{ 0.0000 0.0000 1.0000 0.0000 }
{ 0.0000 0.0000 0.0000 1.0000 }
)
glCallList( list = 1 )
glXSwapBuffers( dpy = 0x1001a128, drawable = 0x6400004 )
This example displays the output of a program that draws a simple,
display listed cube and the frame ends at glXSwapBuffers. Complex
and larger output can be redirected to a file, then browsed for interesting
information.
To enable the caliper:
% setenv OGLDUMP_CALIPERLaunch your app as in a typical ogldump invocation. Then, to start tracing:
% kill -USR1 <pid>where <pid> is the process id of your running executable. To stop tracing:
% kill -USR2 <pid>The caliper can be started and stopped as many times as necessary. Caliper readings automatically sync to the next swapbuffers, and begin and end on frame boundaries.
For example, you may want to test to see how many tex binds occur during run time. Declare the following variables at the top of the file:
static int frame = 0;
static int ntexbinds = 0;
Alter glBindTexture() and glBindTextureEXT():
void glBindTexture( GLenum target, GLuint texture)Then, monitor in glXSwapBuffers() :
{
inited || init();ntexbinds++;
....
}void glBindTextureEXT( GLenum target, GLuint texture)
{
inited || init();ntexbinds++;
....
}
void glXSwapBuffers( Display * dpy, GLXDrawable drawable)
{
inited || init();++nframe;
printf( "\033[0;0H\n" );
printf( " Frame number : %4d\n", frame );
printf( "Number of Tex Binds : %4d\n", ntexbinds );ntexbinds = 0;
...
}
OglDump is open-sourced in hopes that it can receive contributions from its users. Please email the author with your comments, questions, enhancements or problems.
GLAPI void GLAPIENTRY glGetPointerv( GLenum pname, void **params );These functions declare the params variable to be void ** instead of GLvoid **. This is a small anomaly that trips up the parser. Rather than tweaking the parser to handle an otherwise trivial case, a bug has been opened with the Mesa folks and I'm asking users of Mesa3.4 to change the declaration of these functions to :
GLAPI void GLAPIENTRY glGetPointervEXT( GLenum pname, void **params );
GLAPI void GLAPIENTRY glGetPointerv( GLenum pname, GLvoid **params );
GLAPI void GLAPIENTRY glGetPointervEXT( GLenum pname, GLvoid **params );