Ogldebug (IRIX 6.5 version) tips

Creating simpler test cases

The first step is to modify the test case to be as simple as possible. For example, with Performer applications, three things may be done.
  1. Make sure it is single threaded. Change the parameter to pfMultiprocess() to PFMP_APPCULLDRAW so that it will run as a single process - often it is PFMP_DEFAULT which will fork run in multiprocess mode depending on the number of processors.
  2. Isolate the viewing position showing the error. This may be done by printf(3S)ing the viewing position in the main loop, and sending a SIGSTOP (usually done with ctrl-z) to the process when it is displaying the desired problem area. The viewing position that was last output by the printf(3S) function should be hard coded in the application.
  3. Only make one iteration. Usually this means removing the 'while (1)' statement (but not the block it iterates over), and adding a sleep(3C) at the end of the program.
The test case should now be simple enough to run through ogldebug.

Making test cases as simple as possible is especially important with Performer applications due to the high number of OpenGL calls that Performer generates.

We are going to use ogldebug to produce firstly a gls trace file, which is a list of OpenGL function calls encoded in ogldebug's gls language. Then we will use ogldebug to play back the gls file, and then to produce compilable C programs based on either GLUT or X. I will be using a real example, the test case of which is called simpleBug - it must be run with a file called ground.iv. The source code is simpleBug.C.

Ogldebug allows you to specify a display for the ogldebug GUI with the -display option, and a separate display for the test case to display to, with the -appdisplay option. If your test case is a full screen application, which is often the case with Performer applications, this may prove more convenient.

Run the test case in ogldebug (I need to use ogldebug32 - ogldebug will inform you if you should do so with your test case) :-

IRIS# ogldebug32 ./simpleBug ground.iv
 
 
The ogldebug window appears, and proceeds to run the test case, but blocks on the first OpenGL function call.

Hit the 'Continue' button, and wait for the test case to finish rendering. Push the test case's window to the back, so that the ogldebug window is visible.

While the test case was rendering, ogldebug was recording all the OpenGL calls made by the application. We now need to save that recording to a file.

Select 'Call History' from the 'Information' menu. A 'GL Context' window appears, listing all the OpenGL contexts the test case created.
 
 

Ogldebug records the OpenGL functions calls made within each OpenGL context separately. This makes it much easier to isolate drawing to different buffers. My Performer test case has three separate contexts.

I have found that the last context listed, in this case GL context 3, is the one which represents the main Performer window. Selecting the 'GL context 3' line will bring up a 'GL Context 3 History Panel', and a quick look over the list should confirm it is the correct context - it should be much longer than the other contexts.


 
With Performer applications which are anything more than simple, the list of OpenGL functions it calls will be extremely lengthy. When this is the case, ogldebug avoids immediately listing them, and will, instead, bring up a dialogue asking if you want to view them, or just save them.

 
If you're sure it is the correct context, then there is no need to view them - simply hit save. A file selection dialogue box will appear, allowing you to specify a file. By default it is the test case's filename with '.gls' appended, in this case simpleBug.gls After it has finished saving, quit ogldebug by hitting 'Cancel' on the two windows, and selecting 'Quit' from the file menu.

You may now use ogldebug to play back the gls file. Ogldebug seems somewhat unreliable in this function, so don't expect it to work. Different (older) versions may do a better job. For our task, it isn't important that this work, so it isn't a problem.

The next step is to use ogldebug to convert the gls file into a compilable C program (it can produce a C code snippet also for including in your own programs). It can produce code based on GLUT, or on X. It doesn't matter too much which you choose, but if you are going to submit the program as a test case for a bug, then I would recommend using X.

The following command will convert the gls file into a compilable C program based on GLUT :-

IRIS# ogldebug32 -gls2glut simpleBug.gls > simpleBug.glut.c

to compile, use the standard GLUT compile line (from the glut(3GLUT) man page) :-

IRIS# cc -o simpleBug.glut simpleBug.glut.c -lglut -lGLU -lGL -lXmu -lXi -lXext -lX11 -lm

To convert to a compilable program based on X :-

IRIS# ogldebug32 -gls2x simpleBug.gls > simpleBug.x.c

which can be compiled with :-

IRIS# cc -o simpleBug.x simpleBug.x.c -lGL -lXext -lX11

Now you have an simple version of the test case, which doesn't involve any of the complexities of a Performer application.
 

OK
Bad

Performer does tend to make _alot_ of OpenGL calls, even for simple scenes. Before submitting a program such as the above, it would be worth editing the program by hand - the OpenGL function calls are placed in a function called DrawScene()for X, and Draw() for GLUT. For example, in the simpleBug.x.c program produced above, the DrawScene() function contains a lot of glGetString() function calls, the return values of which is ignored. These can quite likely be removed without affecting the main purpose of the program. Also, Performer creates a lot of display lists for fonts, which it uses in it's GUI and stats graph. These can safely be removed. Beyond that, you may find things such as redundant state setting, such as two sequential calls to color(), for example - obviously only the latter call has any lasting effect. You should use your own judgement, and test frequently to see if removing calls affects the display of the problem. The smaller the program you can get, the less time engineers have to spend on narrowing it down, and the more time they get to spend on developing spiffing new products :-)
 

Working with IrisGL

Ogldebug also works well with IrisGL applications when those applications are run with Igloo (IrisGL On Opengl), which is always the case on machines with OpenGL hardware (anything more recent than RealityEngine). The techniques are the same as above. The only problem you will have is when attempting to use ogldebug to produce compilable programs (ie with the -gls2x or -gls2glut options). You will find the compiler complained about unresolved symbols. These symbols are #define's and would normally be in /usr/include/GL/gl.h. For now you should edit the code to also include a file called glfuture.h, after the #include <GL/gl.h> line.

Of course, with this functionality, ogldebug can be a great help when converting IrisGL code to OpenGL.

Other uses for ogldebug

Making simple programs

When writing your own test cases, it is often more convenient to work from simple example programs. There are several in the /usr/share/src heirarchy. The compilable programs produced by ogldebug have a common structure which is in the style of a GLUT program. It is good to have examples with this structure from which to work. Using ogldebug on the examples in /usr/share/src, in the same way described above, can give you such a simple example with a familar structure. Adding code to handle, for example, different key presses becomes a trivial task. The ogldebug X output has the following code to handle keys :-

  switch (keySym) {
      case XK_Escape:
          exit(EXIT_SUCCESS);
      default:
   break;
  }

Adding another case with, say XK_Down or XK_Up, is straight forward.

I used just this technique to quickly develop a gangdraw program to test the swapready functionality of an Onyx. I called the program gangrene.c.

Converting simple GLUT programs to X and vice versa

Ogldebug may be used to convert a simple GLUT program to X and vice versa.

First, run the GLUT program in ogldebug to produce a gls file and convert that gls file to X. If the GLUT example was also produced with ogldebug, this should prove sufficient. Otherwise, parts of the GLUT program will need to be copied into the relevant part of the X program. How easy this is, will depend on how similar the GLUT example was to an example output by ogldebug.

I found this method useful when an engineer, who was working on a bug I had submitted, requested a test case based on X rather than GLUT. Converting it took a matter of a minute or two, which impressed said engineer :-)