Brian Paul
Second Edition, April 1997
In the spirit of free software, Mesa is distributed under the terms of the GNU library copyright.
The Mesa distribution includes implementations of the core OpenGL library functions, the GLU utility functions, the aux and tk toolkits, Xt/Motif widgets, drivers for X11, Microsoft Windows '95/NT and DOS, NeXTStep, and many demonstration programs. Macintosh and Amiga drivers are available separately.
Mesa compiles easily, requiring only an ANSI C compiler and standard development headers and libraries.
From the application programmer's point of view, Mesa is a nearly seemless replacement for OpenGL. The Mesa header files are named the same as OpenGL's (GL/gl.h, GL/glu.h, GL/glx.h, etc) and contain equivalent datatypes, constants and function prototypes. The Mesa library files may be renamed to match the typical OpenGL library names and locations. On some operating systems Mesa may be built as a shared library.
After Mesa has been installed most OpenGL applications should compile and execute without modification.
Since version 2.0 of Mesa the OpenGL 1.1 API is implemented.
At first, Mesa may seem to be a competitor to official OpenGL products. Actually, Mesa has helped to promote the OpenGL API by expanding the range of computers which may execute OpenGL programs. There are many systems which are not supported by OpenGL vendors but can run Mesa instead. People who are curious about OpenGL may try Mesa at no cost and later purchase an OpenGL implementation which perhaps utilizes 3-D graphics hardware. Mesa has been very popular in computer graphics courses. Many students and colleges without the resources to obtain commercial OpenGL implementations successfully use Mesa instead.
Mesa does not implement the full OpenGL specification. For example, antialiasing, trimmed NURBS, and a few glGet* functions are not yet implemented. The GLX interface is only an emulation; it does not generate GLX protocol. It is expected that these features will eventually be implemented.
Mesa doesn't typically perform as well as commercial OpenGL implementations for several reasons. First, portability to a wide range of computers is considered more important than optimizing for a particular architecture. Second, the features of the underlying hardware can't be directly accessed since Mesa exists as a software library above the operating system and window system programming interfaces. And finally, Mesa's development is not supported by any sort of development team. Only so much can be accomplished by people working in their spare time.
In other respects Mesa has some advantages over OpenGL.
Many API functions simply modify state values and produce no output. Before rendering functions are invoked it is often necessary to evaluate the current state to compute derived state values and setup pointers to specific instances of rendering functions. Lazy evaluation is used to updated the state.
For example, Mesa has many instances of specialized polygon drawing functions.
The function to use depends on the state of smooth vs flat shading,
dithering, depth testing, texturing, etc.
When any of these state values are changed
the new state flag is set. When glBegin is called
the new state flag is tested and if set, the state is evaluated
to select the specialized polygon function and the flag is cleared.
Vertices specified between glBegin and glEnd
are accumulated in a vertex buffer. When the buffer is full or
glEnd is called the buffer is processed.
Processing the vertex buffer includes transforming vertices from
object coordinates to eye coordinates, lighting, transforming
eye coordinates to clip coordinates, clip testing, and mapping clip
coordinates to window coordinates.
Each transformation and clip test stage is implemented in a tight loop which compilers can unroll for efficient executution. The size of the vertex buffer was chosen so that all vertex data touched in the transformation loops will fit in a 16KB CPU data cache.
Several optimization are used during transformation. The modelview and projection matrices often have particular elements with values of zero or one. These elements are tested to determine if simplified vector/matrix multiplications can be used. Depending on the current lighting parameters, either a full-featured or specialized, optimized lighting function is used. Lookup tables are used to compute the exponential spotlight and material shininess functions.
After a vertex buffer has been processed it is rendered as a set of
points, lines or polygons as specified by glBegin.
Arrays of points are rendered by either calling a specialized device driver function or by falling back to a core Mesa drawing function. Points whose clip flag is set are discarded.
Line segments are clipped if either endpoint's clip flag is set. Then, the line is rasterized by calling either a specialized device driver function or a fallback Mesa line drawing function. Different line drawing functions are called for flat or smooth shading, RGB or color index mode, texturing, etc.
Polygons are clipped with the Sutherland-Hodgman algorithm if any of the vertex clip flags are set. Next, the equation of the plane containing the polygon is computed. The coefficients of the plane equation ax+by+cz=d are used for determining front/back orientation and implementing the polygon offset feature.
Polygons with more than three vertices are decomposed into triangles. Then, as with line segments, the triangle is rasterized either by a specialized device driver function or by a core fall-back function.
The specialized device driver functions for point, line and triangle
rendering take vertices as input and directly modify the frame buffer.
Alternatively, the fallback rendering functions in Mesa handle rendering
of primitives with arbitrary raster operations.
Point, line and bitmap functions generate fragments which are stored in a
pixel buffer.
The triangle rasterizers and glDrawPixels generate horizontal
runs of pixels called spans.
The pixel buffer and spans are subjected to fragment processing before
being written to the frame buffer.
Pixel buffer and span-based fragment processing are very similar, the only difference is that the pixel buffer stores fragments with arbitrary window coordinates while spans are continuous horizontal runs of fragments.
Since fragments may be culled during processing, each fragment has a write flag associated with it. Initially, all fragments have their write flags set to true. Clipping, scissoring, alpha testing, stenciling, and depth testing may set a flag to false to indicate that it should not be considered in further stages. In the end, only those fragments with their flags set are written to the color buffer.
Each stage of fragment processing is implemented in succession with code similar to:
if (stage is enabled) {
for (each fragment in the buffer or span) {
apply the fragment operation,
possibly setting some write flags to false
}
}
Finally, fragments are written to the color buffer by device driver functions
similar to:
for (each fragment) {
if (fragment flag is true) {
write fragment color to color buffer
}
}
The special cases of all write flags set to true or false are handled
appropriately.
Also, optimized code is used when all fragments have the same color.
The only fragment operation which must be handled below the device driver level is dithering. Depth testing, bitwise logic operators and masking may optionally be implemented by the device driver.
The device driver interface is a set of function pointers which point to implementations specific to the window system. It includes functions for:
glClear color or index
glDrawPixels for specific situations
glFlush and glFinish
The next section explains this in more detail for the X device driver.
Mesa only emulates the GLX interface since a true implementation requires hooks into the X server. Mesa and its GLX can be though of as a translator which converts OpenGL API functions to Xlib commands. The nice side-effect of this is that Mesa can remotely render to any X server, even if the X server does not have the GLX server extension. Operating systems which support shared libraries can substitute Mesa for OpenGL at runtime, allowing OpenGL applications to be displayed on non-GLX capable X servers without recompiling.
Since it's an emulation, Mesa's GLX is not 100% compatible with OpenGL's GLX. In several ways is actually superior. For example, while OpenGL only supports RGB rendering into TrueColor or DirectColor X visuals, Mesa allows RGB rendering into virtually any type and depth of X visual. This is an important feature since many X servers don't offer TrueColor or DirectColor visuals. Other visuals are supported by dithering or converting RGB values to gray levels.
This introduces two potential incompatibilities with OpenGL's GLX.
glXChooseVisual function.
When operating in single buffered mode, rendering is directed into an X window. When operating in double buffered mode, rendering is directed into either a Pixmap or XImage. A Pixmap can be accessed in the same way as a window (both are considered to be drawables). Whether a Pixmap or XImage gives best performance depends on a number of factors.
Using a Pixmap can be quite efficient for rendering plain, flat-shaded
points, lines and polygons since the intrinsic X point, line and polygon
drawing functions can be used.
Performance is relatively good whether displaying locally or remotely.
However, when using smooth shading or per-pixel fragment operations
pixels must be drawn individually with XSetForeground
and XDrawPoint calls.
The amount of data transferred from the client to X server is directly
proportional to the number of X calls made.
For XSetForeground/XDrawPoint rendering
this is usually unacceptably slow.
In most cases using an XImage yields best performance in double buffer mode. The reason is individual pixels can be directly "poked" into the image since it resides in the client's address space. Front/back buffer swapping is implemented by copying the XImage to the X window. The X Shared Memory extension is used when displaying on the local host to accelerate this operation. In the case of remote display, the amount of data transferred from the client to the X server is directly proportional to the window size and not the number of pixels generated during rendering.
Programmers should note that double buffering using an XImage can be faster than single buffering.
The code for writing RGB pixels to the color buffer could be expressed as:
for (each pixel i) {
pixel_value = convert_rgb_to_pixel( red[i], green[i], blue[i] );
put_pixel( x[i], y[i], pixel_value );
}
However, this would be very inefficient since the convert_rgb_to_pixel
and put_pixel functions must cope with many types of X visuals and depths.
The best method to convert RGB values to pixel values depends on the X visual.
The best method to write pixels to the color buffer depends on whether the
buffer is implemented as an X Pixmap or XImage.
Therefore, almost all inner-loops in the X device driver are optimized
for special pixel formats.
For example, there are specialized span and pixel-array writing functions for 24-bit TrueColor, 16-bit TrueColor, 8-bit PseudoColor, N-bit GrayScale, etc. Furthermore, there are many line and triangle rasterizer functions optimized for these pixels formats with popular combination of flat/smooth shading, depth-tested/non-depth-tested rasterization modes.
When the device driver's UpdateState state function is
called the driver's pointers for span, line and triangle functions are
updated to point to the appropriate optimized function.
If no optimized function satisfies the current library state then a core
Mesa fall-back function is used instead.
The device driver's point, line and triangle functions are also used for hardware acceleration. In this case the driver function will simply set hardware registers and trigger an interupt or DMA to make the hardware render the primitive.
glWindowPos*MESA functions.
These functions are convenient alternatives to glRasterPos*
because they set the current raster position to a specific window coordinate,
bypassing the usual modelview, projection and viewport transformations.
This is especially useful for setting the position for
glDrawPixels or glBitmap to a desired window
coordinate.
For glWindowPosMESA4f(x,y,z,w) the
x, y, z, and w parameters
directly set the current raster position except that z is
clamped to the range [0,1].
The current raster position valid flag is always set to true.
The current raster distance is set to zero.
The current raster color and texture coordinate are updated in the
same manner as for glRasterPos.
In selection mode a hit record is always generated.
Programs using OpenGL, not Mesa, may also use the glWindowPos*MESA
functions since an implementation of it in terms of standard OpenGL
functions is included with Mesa.
Perhaps the GL_MESA_window_pos extension may be incorporated into a future version of OpenGL since it is so convenient.
GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual,
Pixmap pixmap, Colormap cmap )
It is an alternative to the standard glXCreateGLXPixmap
function.
Since Mesa supports RGB rendering into any X visual, not just TrueColor
or DirectColor, Mesa needs colormap information to convert RGB
values into pixel values. An X window carries this information but a
pixmap does not. This function associates a colormap to a GLX pixmap.
An application using GLX pixmaps should use the following code to associate a colormap with the GLX pixmap when using Mesa.
#ifdef GLX_MESA_pixmap_colormap
glxpixmap = glXCreateGLXPixmapMESA( display, xvisualinfo,
xpixmap, colormap );
#else
glxpixmap = glXCreateGLXPixmap( display, xvisualinfo, xpixmap );
#endif
If the GLX X server has 3-D acceleration hardware the Mesa-linked application would use it.
The first was a driver for the GLint chipset written by Ken Adams while at Clemson University. Development is now maintained by others at the university. Dr. Robert Geist (rmg@cs.clemson.edu) is the current contact.
The second was a driver for the Cirrus Logic CL5464 chipset written by Peter McDermott while at the University of Texas at Austin. Again, development continues at the university. Contact Adam Seligman (adams@cs.utexas.edu).
The most recent hardware support is for the 3Dfx VooDoo chipset written by David Bucciarelli (tech.hmw@plus.it). This driver is implemented on the 3Dfx GLide rasterization library.
More hardware acceleration projects will probably follow when Mesa has been integrated with XFree86.
Mesa has a bright future with many new features planned. No doubt, much of this work will be done by volunteers who share an enthusiasm for computer graphics and free software.
http://www.ssec.wisc.edu/~brianp/Mesa.html.