Overview of glean internals
Directory structure
Starting at $GLEAN_ROOT, you'll see bin,
include, and lib directories.
These are initially empty, and are filled by the Makefile in
src.
$GLEAN_ROOT also contains documentation in doc,
common Makefile templates in make, sample result files in
results, and source code in src.
The Makefile templates are particularly interesting, since they
automate nearly all of the process of defining Makefiles.
cd into src, and take a look around.
The main Makefile resides here. There are also subdirectories for
glean itself (glean), a wrapper for OpenGL header
files that covers up some Windows-specific problems (glh),
libraries that are used by multiple tools (libs), and
code for tools like showvis (tools). The Makefile
ensures that everything in the subdirectories is built in the correct
order.
Libraries
There are several libraries providing services that you may want when
you start writing tests. These particular libraries are of sufficiently
general usefulness that they're broken out into separate directories.
(As we'll see later, some other services are local to the glean
subdirectory.)
-
dsurf
This library provides a portable interface to drawing surface
configuration information (pixel format descriptors under Windows,
and extended X11 Visuals under X). It also provides the filtering
capability that's used by showvis and glean to
select configurations that match particular criteria.
-
image
The basic abstraction provided by this library is an in-memory
image structure that maps almost directly onto the image format
used by OpenGL. The library also offers utilities that read and
write TIFF files, tools to convert image data to a common format,
and convenience routines for invoking OpenGL operations like
reading and drawing images. Finally, there is a "registration"
utility that compares two images and attempts to align one on top
of the other in the position at which the images are most similar.
-
lex
This is a simple lexical analyzer. libdsurf uses it when
parsing drawing surface configuration criteria, and when constructing
a drawing surface configuration from a canonical description stored
in a results file.
-
rand
This set of classes provides uniform random values in several different
ranges and formats, in an OS-independent fashion. (This allows results
generated by glean on one OS to be compared to results on the same
hardware running under another OS.) It's based on a linear congruential
generator discussed in Knuth Vol. 2 and Numerical Recipes (2nd ed.).
-
stats
These classes generate simple statistical measures (min, max, mean,
standard deviation, etc.).
-
timer
This class provides timing services for benchmarking. It's capable of
calibrating measurement overhead, repeating benchmarks until a target
runtime is achieved, etc.
glean itself
glean consists of a relatively simple main program, a set of
classes providing commonly-needed services, and the tests themselves.
The main program essentially just parses command-line options, creates
the test environment (see below) and invokes each test in turn. The
list of tests is generated automatically by test class constructors,
so there's no need to maintain one independently. It should be fairly
straightforward to replace the current main program with a graphical
front-end, if anyone cares to do so.
The main service classes are as follows:
-
Options
This class collects all option information (the verbosity level,
names of the test results databases, etc.) in one place. Doing
so allows option setting to be separated from option interpretation.
-
Environment
This class encapsulates information about the test environment:
the options, an output stream for the test log, the window system,
etc. It is passed as an argument to each test.
-
WindowSystem
This class abstracts information about the window system, so that
most glean tests need not know the system under which they're
running. Its main task is to maintain lists of drawing surface
configurations, drawing surfaces, and OpenGL rendering contexts.
However, it does expose window-system-specific data (such as the
X11 Display pointer) so that window-system-specific tests can be
written. (Such tests must use conditional compilation to protect
references to non-portable function calls and data structures,
though.)
-
DrawingSurface and Window
A drawing surface is a canvas on which OpenGL rendering can take
place. Each drawing surface has a configuration that specifies
the buffers (color, depth, stencil, etc.) associated with the
surface.
The prototypical drawing surface is the window, which adds size
information and buffer-swap capability that's used by most tests.
Eventually we will need to add more drawing surfaces to glean,
for example, the PBuffers supported under GLX version 1.3.
-
RenderingContext
A rendering context encapsulates all OpenGL state information
(except for the contents of the drawing surface). In general,
in order to render, you must create a drawing surface, create
a rendering context, and then bind the two (using a service
provided by the WindowSystem class). Then you can use
ordinary OpenGL commands freely.
A few general utilities are also available:
-
useScreenCoords() (glutils.h)
Sets up the modelview and projection matrices so that OpenGL
object coordinates correspond directly to screen pixel
coordinates. (Note: The origin of the coordinate system is
at the lower left corner of the window.) This is convenient
for most tests of rasterization operations.
-
RandomMesh2D (geomutil.h)
Creates a 2D array of points that fit within a given bounding
rectangle, but are displaced by random amounts from the lattice
points within it. This is especially useful for benchmarking,
because it yields randomly sized and oriented triangles whose
average area is nevertheless accurately known.
To create a new test, you need do little more than create a new
.cpp file in the glean subdirectory. (The Makefile
will handle its dependencies and build it automatically.)
All tests are derived from the base class Test. For truly
new types of tests you'll need to derive a new class, but for many
common types of tests you can start by copying a test that already
exists. Here are some examples:
-
BasicTest (tbasic.cpp)
This is a good outline for any
simple test that runs in one window with one rendering context,
generating a result for each drawing surface configuration that
meets specified criteria. If your test is of this type, you may
be able to copy tbasic.cpp and modify just the functions
runOne(), compareOne(), put(), and get().
It may be instructive to compare tbasic.cpp with
tgetstr.cpp, which is derived in just that way.
-
TexBindPerf (tchgperf.cpp)
This test demonstrates how to measure performance, by benchmarking
texture binding time. It's a bit more complicated than
BasicTest, but the structure is basically the same, and
most of the work is concentrated in the four functions mentioned
above.
-
RGBTriStripTest (trgbtris.cpp)
This shows how to save and compare TIFF images. While it's not a
good idea to make too many tests dependent on image comparisons
(because they're not particularly robust), there are cases like
regression testing where image comparison may be a good approach.
That's pretty much all there is to it. The glean framework
provides most of the mechanisms needed to develop simple tests.
Now it's time to create a good set of tests and thereby make a new
tool that's valuable to the entire OpenGL community.