Last changed:  31 Mar 1995

Random notes....

In this file we explain how and why certain things are done, and point
out where work remains...



Rasterization
-------------

There are two schemes used for rasterization:  pixel spans and pixel arrays.

Pixel Spans are horizontal runs of pixels generated by polygon rasterization
and glDrawPixel operations.  As seen in span.c, horizontal runs of pixels are
passed to each enabled raster operation (blending, depth-buffering, stencil,
etc).  At many of these stages, pixels may be discarded due to failing the
depth test, stippling, etc.  The boolean mask array indicates which pixels to
draw and which to discard.

Spans are good because many pixels can be processed per function call.  Also,
we're taking advantage of spatial coherence.

Pixel arrays are used in the rasterization of points, lines, and bitmaps.
The pixel array (or pixel buffer) scheme is very similar to the pixel span
method.  The only difference is that the pixels can be at random locations.

Despite the care I've put into rasterization, it's still the bottleneck in
Mesa.  The OpenGL rasterization pipeline imposes a certain structure which
is difficult to implement at maximum speed.  I'm still working on it though...


Polygons
--------
The vertices of a polygons (and triangles and quads, etc) are stored in
VB.Eye[], etc.  The vlist[] array is an list of indexes into the vertex
arrays, defining the vertices of the polygon.  This scheme is was prompted
by how clipping is done.  Remember that clipping a polygon may result in an
unchanged polygon or a radically different one.  In the former case, we don't
want to copy vertex data from an input list to a clipped list.  In the later
case, we don't want to shift vertex data to insert new vertices.  The solution
was to use a level of indirection (the vlist array).  This also worked
out well for the TRIANGLE_STRIP, TRIANGLE_FAN, QUAD_STRIP, etc. primitives.

The only disadvantage is the extra cycles needed to lookup indexes via
vlist when doing vertex transformations.  Maybe copying and shifting
data in the clippers is OK if you don't mind a big speed hit for clipping.

The polygon rasterizing functions in polygons.c will handle any n-sided
simple polygon.  Would it have been better to break down n-sided poly-
gons into triangles and do triangle rasterization only (which we could
optimize?)  Maybe, but interpolation of colors across quadrilaterals
looks better when they're treated as 4-sided polygons instead of 2 tri-
angles.


Clipping
--------
Clipping points is trivial.

Line clipping is done with the usual bit-mask line clipping algorithm.

Polygon clipping is based on the edge-by-edge method of Sutherland-Hodgman.

Yes, I went crazy with macros!  It was a good way to avoid writing nearly
the same code over and over and is faster than a bunch of function calls.
Be ready for a debugging nightmare if you want to change this code!  This
code is pretty fast as is.


Transformations
---------------
The functions in xform.c for rotate, scale, translate all construct 4x4
matrices then do matrix multiplies.  This should be optimized!  However,
always making a 4x4 matrix is simple for display lists.  Also, some of
the functions (gl_transform_point,etc) should be rewritten as macros
and put in xform.h.


Point, line, polygon rendering
------------------------------
In points.c, lines.c and polygons.c there are a number of rasterization
functions for each primitive.  The one to use is determined by looking
at the current context.  If you have a special combination of rendering
operations which isn't as fast as it could be, it should be easy to add
it in like the others.


Dithering
---------
The spec says dithering should initially be enabled.  Testing this using
SGI's library and demo programs, glIsEnabled says dithering is enabled
yet there is no visual evidence of dithering.  It seems to me that dithering
should initially be off especially for CI visuals.  Suppose you're drawing
a flat-shaded polygon with index 5 which is mapped to red.  You don't
want dithering to produce pixels with value 4 because who knows what
color is loaded at position 4 in the colormap.  Currently, dithering
is initially disabled in this implementation.


GLU library
-----------
The GLU library is very much incomplete.  Only the most frequently used
functions are done.  Others are half-hearted attempts.  Someone who
knows splines has to write the NURBS code.

All the GLU functions should be written in terms of GL calls.  The GLU
library could be written by someone entirely independent of the main
library.


Tk and aux libraries
--------------------
These libraries are based on SGI code.  They shouldn't be used for real
applications.  Go directly to the X/Mesa interface, use the pseudo-GLX
functions, or use GLUT instead.


Demo programs
-------------
Look at the source for the demo programs to learn what keyboard functions
are available.  New demos should be written since these are mostly SGI's.


glDrawPixels, glReadPixels, glBitmap
------------------------------------
These functions are complicated because of the vast number of options
possible.  I haven't put much effort into speeding them up.  The glPixelZoom
operation isn't supported yet.  I'm not sure of the best way to integrate it.


C notes
-------
When writing new code, use the strictest compiler flags available.  This
helps to catch subtle bugs and increases portability.  Also, use lint
once in a while.  There shouldn't be any compilation warnings, except
when the compiler is at fault.

Look at assembly language output when not sure how to efficiently
write something.

Use the right data types.  Use unsigned types instead of signed types
when possible since some compilers can generate better code with them.
Be aware of how type conversions are done.  On SGI systems for example,
float/int conversion is much more efficient than float/unsigned int
conversion.

Write straightforward code:  compilers often can do better optimizations
on simple code than complicated code.  It's also easier for others to
understand.

USE COMMENTS!


Compiler problems
-----------------
The DEC ultrix C compiler doesn't recognize the 'const' qualifier!  OSF/1
hasn't been tested.

The Sun ANSI C compiler doesn't have correct prototypes for memcpy(), etc
in its header files.  Also, it complains about mixed-type expressions
much more than other compilers.

The Amiga DCC compiler, at least the version I have, can't compile Mesa
because it's just too big.  Also it doesn't like the F floating point
constant suffix.

SGI's IRIX 4.0.5 C compiler produces *many* warnings when -fullwarn is
specified, unlike IRIX 5.2 C compiler.

SGI's IRIX 6.0.1 C compiler produces many detailed warnings, use the -woff
option to control them.

There appear to be some fatal bugs in Mesa when compiled on IRIX 6.0 systems.
Try the demos/wave program for example...


Known Bugs
----------
Under IRIX 6.0 in 64-bit mode, cones are drawn incorrectly.  Namely, depth
buffering is incorrect for quadrilateral which share a common vertex.  The
problem is either in the computation of the equation of the quad's plane
or in the computation/interpolation of Z values.

Under IRIX 6.0 in 64-bit mode, the wave demo doesn't work.  dbx reports the
crash inside an Xlib call...

Linux systems are more sensitive to floating point exceptions.  At the time
of writing this, all known FP exceptions have been fixed.


Summary of the source code in src/
----------------------------------
Here is a summary of the source files which implement the core library.
See the top of each file for details.

accum.[ch]	- accumulation buffer

alpha.[ch]	- alpha test

amesa.[ch]	- Amiga interface

attrib.[ch]	- attribute stack

bitmap.[ch]	- glBitmap

blend.[ch]	- pixel blending

bresenham.[ch]	- implementation of Bresenham's line algorithm

clip.[ch]	- functions for clipping points, lines, and polygons
		  against the view volume and user-defined clipping planes
		  Check out this code!  It makes liberal use of the cpp!

config.h	- tunable configuration parameters

context.[ch]	- definition of the library context and functions for creating,
		  setting, deleting contexts.

copypixels.[ch]	- glCopyPixels

dd.h		- device driver function prototypes.  These functions must
		  must be implemented by xmesa.c, amesa.c, etc. to perform
		  low-level rendering.

depth.[ch]	- depth buffer functions

dither.[ch]	- dithering functions

draw.[ch]	- point, line, and polygon rendering

drawpixels.[ch]	- glDrawPixels

enable.c	- the glEnable and glDisable functions

eval.[ch]	- evaluators

feedback.[ch]	- feedback and selection facilities

fog.c		- fog functions

get.c		- glGet* functions

glx.c		- pseudo-GLX functions

interp.[ch]	- interpolation functions

light.[ch]	- lighting, material, and shading functions

lines.[ch]	- line segment rendering

list.[ch]	- display lists

logic.[ch]	- pixel logic ops

macros.h	- useful macros used in many files

misc.c		- simple, miscellaneous functions

pb.c		- pixel buffer (pixel array) functions

pixel.[ch]	- glPixelStore, glPixelTransfer, etc.

points.[ch]	- point rendering

polygons.[ch]	- polygon rendering

quickpoly.[ch]	- quick and dirty polygon rendering

readpixels.c	- glReadPixels

scissor.[ch]	- scissor box

span.[ch]	- pixel span processing

stencil.[ch]	- stencil operations

texture.[ch]	- texture mapping

vb.[ch]		- vertex buffer data structure

vertex.c	- the glVertex*, glNormal*, glIndex* and glColor* functions

xform.[ch]	- matrix transformation functions

xmesa.c		- the X/Mesa interface



If you want to familiarize yourself with the source code, the place to
start is in context.h.  This file defines the structures which make up
the global rendering context.

There's only 3 global variables in the whole library: CC, PB and VB.  CC
(Current Context) and is a structure which contains the entire current
rendering context.  With the functions in context.c we can setup multiple
contexts and switch between them to support rendering in multiple windows
(almost) simultaneously.  PB is the pixel buffer structure.  VB is the
vertex buffer structure.

Why isn't CC a pointer to a context structure?  CC is referenced a *lot*
and we don't want to dereference a pointer every time we access it.  As a
trade-off, I deemed it acceptable to do memcpy's of the structure when
switching current contexts.

Probably the second thing to look at is draw.c which implements the
glBegin/glVertex/glEnd stuff.  The VB variable is a structure which holds
arrays of vertices, colors, texture coordinates, etc.  A polygon is defined
by an array of indexes into the VB arrays.  This was needed because clipping
can delete and add vertices to a polygon.  Maintaining a list of indexes is
faster than doing memcpy's to shift vertex data when vertices are added and
deleted.  Also, this system works well for primitives which share vertices
(triangle and quad strips).  Line segment vertices are indexed similarly.

Beyond that, the source code is divided up into relatively independent
modules with simple names.  It should be easy to find all the code
related to any particular library feature.

On naming conventions:  functions which are defined in one file and used
from other files have the suffix gl_.  Also, such functions are proto-
typed in the corresponding .h file.  Functions which are only called in
the file in which they are defined are declared as static without the
gl_ prefix.  I always like the Modula-2 way of doing things!

As long as the application writer doesn't name his/her functions with a
leading gl_ and doesn't use a variable named CC, there should be no
symbol conflicts.  Perhaps CC should be renamed...



Organization
------------

    +-----------------------------------------------------+
    |                                                     |
    |                 Client Programs                     |
    |                                                     |
    +-----------------------------------------------------+

    +-----------+  +------------+------------+  +---------+
    |           |  |    aux     |            |  |         |
    |    GLU    |  +------------+    tk      |  |  GLUT   |
    |           |  |                         |  |         |
    +-----------+  +-------------------------+  +---------+

    +----------------------------+------------------------+
    |                            |                        |
    |          Mesa              |                        |
    |                            |                        |
    +----------------------------+  xmesa/amesa/glx, etc  |
    |          dd.h              |                        |
    +----------------------------+                        |
    |                                                     |
    |                                                     |
    +-----------------------------------------------------+
    |           Hardware/OS/Window System                 |
    +-----------------------------------------------------+

Key:

Hardware/OS/Window System - Putting images onto the display screen is done
	by calling whatever graphics rendering functions are made available
	by the system's hardware, operating system or window system.  For
	example:
		Unix/X		Xlib calls
		Amiga		Intuition/graphics library calls
		PC		Windows calls or direct writing to hardware

xmesa, amesa, etc - Each computer system will probably require a different
	'interface library' to provide the connection between the core
	library and the underlying hardware/os/window system.  Typically,
	there will, be functions to create rendering contexts, attach them
	to windows or screens, etc.  Also, the functions described in dd.h
	must be implemented as the core library uses these functions to
	produce output.

dd.h - device driver function prototypes.  These functions must be imple-
	mented in order to produce output.  Examples are functions to
	set the current color, draw pixels, lines, polygons, write spans
	of pixels, and swap buffers.

Mesa - this is the core library.  It should be completely portable as
	all system-dependent features are accessed through the device driver
	functions.

GLU - This utility library is completely implemented in terms of GL calls.

tk  - A simple window system independent toolkit.

aux - A simple library build on tk.

Client Programs - Graphics programs will use the core functions and either
	the aux/tk library or a xmesa, amesa, etc. interface program.



More on the device drivers
==========================

See the file src/dd.h for the list of functions which compose a device
driver.  Each of the functions must be implemented on your system/hardware
for the library to function.  Additionally, you must provide some
functions for establishing rendering contexts, swapping buffers, etc.
in a manner similar to the GLX library.

There are basically three catagories of functions in the device driver:

	1. simple primitive functions
	2. span-based functions
	3. miscellaneous functions

Simple primitive functions are used to write individual pixels, line
segments, or polygons to the output device.  These functions are used
when advanced features such as depth-buffering, stenciling, and smooth
shading are disabled.  If your system supports line or polygons rendering
in hardware or in the OS, you should use those facilities.

Span-based functions are used to render primitives which require depth-
buffering, smooth shading, etc.  The span functions write a horizontal
sequence of pixels to the frame buffer with a per-pixel binary mask.
Pixels may be masked from writing when they fail the depth test, stencil
test, stippling, etc.

Among the miscellaneous functions are functions for clearing the output
buffer, specifying the reading and drawing buffers



The X/Mesa device driver
------------------------

The X/Mesa driver is the interface between GL and the X11 window system.
All GL rendering is performed by making X11 library calls.  This isn't
the fastest method, but it's the most portable and 'networkable'.  The X/Mesa
interface was loosely modeled on the GLX interface.  See the file
include/GL/xmesa.h for the programmer's view.  The file src/xmesa.c
is the implementation of the xmesa and device driver functions.

Of interest is the implementation of the back buffer used when double
buffering is enabled.  The last argument to XMesaCreateContext() is
a flag which specifies whether an off-screen pixmap (on the server) or
an Ximage (on the host) is used as the back buffer.  It's probably best
to use a pixmap when your rendering low-complexity scenes and to use an
Ximage when rendering high-complexity scenes or displaying remotely.  Try
both to determine which is faster for your application.

There is support for the X Shared Memory extension.  To enable it, add the
flag -DSHM to the src/Makefile CFLAGS line and be sure to link your applica-
tion with -lXext.  When enabled, the Shared Memory extension will be utilized
when using an XImage for the back buffer in double buffer mode.  The net
result is the "swap" operation will be faster (especially for larger windows).

Also, note that alpha blending usually only works when rendering into
an Ximage.  This is because the X server usually discards extra bits in
the argument passed to XSetForeground while XPutPixel will not discard
the extra alpha bits.

While a 24-bit (or 12-bit) TrueColor or DirectColor visual is recommended
for rendering in RGB mode, 8-bit (or 1-bit!) PseudoColor or StaticColor
visuals are supported.  When simulating RGB mode on an 8-bit or 1-bit
display, dithering is used to increase the number of perceived colors.
Thanks to Bob Mercier for the wonderful new 8-bit dithering code.


GLX
---

Real OpenGL uses the GLX X extension to tie into the X window system.
Mesa's GLX is _not_ an implementation of the real GLX protocol.  It only
tries to act like it.  If you're going to use the GLX functions you
should scan src/glx.c to see its deficiencies.



Porting to new systems
======================

Porting Mesa to new systems should require very few changes to the core
code in src/.  The most effort will be in implementing the device driver
functions described in "dd.h".  Those functions, plus more system-specific
functions such as those in xmesa.c and amesa.c are the interface between the
Mesa library and the OS/hardware.

Ideas for porting to MS Windows:
	1. Call the interface "wmesa" (Windows/Mesa interface)
	2. Design a "wmesa.h" file which describes how users must setup/
	   destory a Windows/Mesa context, etc.
	3. Implement the functions in "dd.h" and "wmesa.h" in terms of
	   MS Windows functions in "wmesa.c"
	4. Create a makefile which compiles all the core files and wmesa.c
	   and makes a library in lib/.
	5. Update the top-level Makefile.
	6. Implement the tk libarary in terms of the core and wmesa.c
	   functions.

<One may also want to write a VGA driver and bypass windows for better
performance...>

Ideas for porting to Apple MacIntosh:
	1. Call the interface "mmesa" (Mac/Mesa interface)
	2. Design a "mmesa.h" file which describes how users must setup/
	   destroy a Mac/Mesa context, etc.
	3. Implement the functions in "dd.h" and "mmesa.h" in terms of
	   Mac OS/QuickDraw functions in "mmesa.c"
	4. Create a makefile which compiles all the Mesa core files and
	   mmesa.c and makes a library in lib/.
	5. Update the top-level Makefile.
	6. Implement the tk libarary in terms of the core and mmesa.c
	   functions.

Ideas for porting to more Unix/X workstations.
	1. Edit the Make-config to add appropriate entries for your system.
	2. If your compiler detects errors or warnings, try to correct them
	   in a portable fashion.

Also:
	1. You may want to adjust some of the parameters in config.h
	2. If the GL datatypes in GL/gl.h need to be defined in terms
	   of some C types other than what's currently seen, you may
	   have to insert some #ifdef <arch> directives.



Mesa programming notes
----------------------

Per-vertex fog is used by default when possible, use glHint( GL_FOG_HINT,
GL_NICEST ) to enable per-pixel fog.

Linear texture coordinate interpolation is used by default.  To enable
perspective-corrected interpolation use glHint( GL_PERSPECTIVE_CORRECTION_HINT,
GL_NICEST ).




Coordinate transformation order:
--------------------------------
glVertex()
    object coords
xform by ModelView matrix
    eye coords
clip to user clip planes
    eye coords
xform by Projection matrix
    clip coords
clip to view volume
    clip coords
divide by W
    ndc coords
map to window by viewport
    window coords



Checklist of library status
---------------------------

function			status & notes
------------			--------------------------------
glAccum				Done
glAlphaFunc			Done
glBegin				Done
glBitmap			Done, but not thoroughly tested
glBlendFunc			Done
glCallList			Done
glCallLists			Done
glClear				done	(except for scissor box)
glClearAccum			Done
glClearColor			Done
glClearDepth			Done
glClearIndex			done?
glClearStencil			done?
glClipPlane			done?
glColor*			Done
glColorMask			done, but no effect in drivers
glColorMaterial			done?
glCopyPixels
glCullFace			Done
glDeleteLists			Done
glDepthFunc			Done
glDepthMask			Done
glDepthRange			Done
glDisable			Done
glDrawBuffer			Done, but behavior depends on the Mesa driver
glDrawPixels			Done, but not thoroughly tested
glEdgeFlag			Done
glEdgeFlagv			Done
glEnable			Done
glEnd				Done
glEndList			Done
glEvalCoord1*			done
glEvalCoord2*			done
glEvalMesh1			done
glEvalMesh2			done
glEvalPoint1			done
glEvalPoint2			done
glFeedbackBuffer		done?
glFinish			done
glFlush				done
glFog*				done
glFrontFace			done
glFrustum			done
glGenLists			done
glGetBooleanv			mostly done
glGetClipPlane			done
glGetDoublev			mostly done
glGetError			done
glGetFloatv			mostly done
glGetIntegerv			mostly done
glGetLightfv			done
glGetLightiv			
glGetMapdv			done
glGetMapfv			done
glGetMapiv			done
glGetMaterialfv
glGetMaterialiv
glGetPixelMapfv
glGetPixelMapuiv
glGetPixelMapusv
glGetPolygonStipple		mostly done
glGetString			done
glGetTexEnvfv
glGetTexEnviv
glGetTexGendv
glGetTexGenfv
glGetTexGeniv
glGetTexImage
glGetTexLevelParameterfv
glGetTexLevelParameteriv
glGetTexParameterfv
glGetTexParameteriv
glHint				done, but no effect in some cases
glIndexMask			done, no effect in drivers?
glIndex*			done
glInitNames			done?
glIsEnabled			done
glIsList			done
glLightModel*			done
glLight*			done
glLineStipple			done
glLineWidth			done
glListBase			done
glLoadIdentity			done
glLoadMatrixd			done
glLoadMatrixf			done
glLoadName			done
glLogicOp			done
glMap[12]*			done
glMapGrid[12]*			done
glMaterial*			done
glMatrixMode			done
glMultMatrixd			done
glMultMatrixf			done
glNewList			done
glNormal*			done
glOrtho				done
glPassThrough			done
glPixelMap*			done except for display list compile
glPixelStore*			done
glPixelTransfer*		done
glPixelZoom			not even started!
glPointSize			done
glPolygonMode			done
glPolygonStipple		almost done
glPopAttrib			done
glPopMatrix			done
glPopName			done
glPushAttrib			done
glPushMatrix			done
glPushName			done
glRasterPos*			done
glReadBuffer			done
glReadPixels			Done, but not thoroughly tested
glRect*				done
glRenderMode			done
glRotated			done
glRotatef			done
glScaled			done
glScalef			done
glScissor			done
glSelectBuffer			done
glShadeModel			done
glStencilFunc			done
glStencilMask			done
glStencilOp			done
glTexCoord*			done
glTexEnvf
glTexEnvfv
glTexEnvi
glTexEnviv
glTexGend
glTexGendv
glTexGenf
glTexGenfv
glTexGeni
glTexGeniv
glTexImage1D
glTexImage2D			partially works
glTexParameterf
glTexParameterfv
glTexParameteri
glTexParameteriv
glTranslated			done
glTranslatef			done
glVertex*			done
glViewport			done



To Do
-----

(grep for TODO in *.[ch] for details)

make sure all argument checking is delayed until display list execution time.

a few functions still don't get compiled into display lists

many GLU functions need to be written, including NURBS

glPixelZoom

many texture mapping functions

texture mapped lines, points

glGetTex* calls



Recent changes
--------------

11 Feb 95	Better makefile support for Suns
11 Feb 95	Changed NDC coordinate scheme (no more Vndc array)
12 Feb 95	Perspective-corrected texture coordinate interpolated added.
12 Feb 95	Per-pixel fog implemented
13 Feb 95	Added X Shared Memory support
...
23 Mar 95	Introduced vertex buffer (VB) stuff
27 Mar 95	Reimplemented xmesa.c using function pointers to the
		  pixel writing functions

