
                             AmigaMesaRTL 3.0
                      A run-time library of Mesa 3.0

                         by Jarno van der Linden
                            jarno@kcbbs.gen.nz

            http://www.kcbbs.gen.nz/~jarno/AmigaMesaRTL.html

             Mesa 3.0 is Copyright (C) 1995-1998  Brian Paul



INTRODUCTION
============

Once upon a time there was an Amiga port of Mesa by Stefan Zivkovic.
However, just as this port became interesting, Stefan could no longer
support it.

Then came CyberGL. A run-time library, which ran reasonably comfortably
even on lower-end machines with AGA. Unfortunately, it only implemented a
subset of OpenGL. Furthermore, the output even on a 256 colour AGA screen
was far from impressive. At present, development seems to have stalled
(possibly pending the release of the 3D drivers for the CV-PPC and BVision
cards).

Back to Mesa, through H&P we've seen the release of StormMesa.
Unfortunately this too comes in the form of a link library. (Although that
is soon to change I gather).

So I set out to create my own driver with the following objectives:

    - Based on the latest release of Mesa
    - Should come in the form of a run-time library
    - Reasonable speed on an 50MHz '030/'881 system
    - Good quality output on AGA

With AmigaMesaRTL, I think I have achieved these goals. Of course, don't
expect miracles. Framerates are still better counted in seconds-per-frame
rather than frames-per-second on my machine (A1200, Blizzard1230IV, 50MHz
'030/'881, 32MB fast). But it is still faster than CyberGL and the output
is a significantly better.



THEORY OF OPERATION
===================

The main Mesa functions (such as glBegin(), glFlush(), etc. etc. etc.) are
in mesamain.library. These functions do all sorts of things, and
eventually call some driver functions to handle the platform-specific
output.

The driver (amigamesertl.c) does all reading from and writing to a simple
memory buffer. This buffer is made up out of single bytes in the case of
colour index mode, and 4 bytes in the case RGB or RGBA mode.

When glFlush() is called, the buffer is processed by an Output Handler.
The traditional thing for an output handler to do is to quantize the
buffer to a displayable number of colours, and C2P the buffer to a window.
Output handlers can however do many other things, such as send the buffer
directly to an image editing program (e.g. ImageFX using the
magic.library).

What output handler to use depends on the output type specified by the
application. For example, if the output type is "Window", the output
handler specified by the environment variable "AmigaMesaRTL/Window" is
used.

The default output handler is a slightly modified version of DL1 from a
package by Dennis Lee (denlee@ecf.utoronto.ca). I've included the original
documentation in the amiga/outputhandlers/dl1 directory.

Because of the various buffers involved, AmigaMesaRTL does use a fair bit
of memory.



COMPILING THE LIBRARY
=====================

The AmigaMesaRTL distribution only contains the changed and new files of
Mesa. You will need the Mesa 3.0 distribution. Once you have obtained the
Mesa 3.0 distribution and unpacked it to somewhere, copy the amiga
directory of AmigaMesaRTL to the Mesa directory. Go to the amiga/src
directory, change the SCOPTIONS file to suit your system (mainly the MATH
and CPU settings), and run SMake. Sit back, relax, enjoy life. This is
going to take a while.

Note that there are still a few references to __XCEXIT(). Just ignore it
and let the linker replace it with __stub().

Once this is done, you should end up with a file called mesamain.library
in the amiga/library directory.

Go to the amiga/drivers/amigamesartl directory, edit SCOPTIONS, run SMake.
Out pops amiga/mesadrivers/amigamesartl (no ".library").

Some output handlers can be found in amiga/outputhandlers. Go to one of
them (e.g. dl1), edit SCOPTIONS, run SMake, and you should now have a
library called amiga/library/outputhandlers/dl1.

The GLUT library is made by going to amiga/src-glut, edit SCOPTIONS,
SMake, and you have amiga/library/glut.library.

Finally, go to the amiga/lib directory, edit the SCOPTIONS file if you
want to, run SMake. Out should come Mesa.LIB and GLUT.LIB.

That is all that is needed to get a working mesa library. Whew!
Alternatively, edit all the SCOPTIONS files you can find to suit your
system and execute mklib.amiga.



USING THE LIBRARY
=================

To compile a program using AmigaMesaRTL, make sure the compiler can see
the files in amiga/include and the link libraries in amiga/lib (by e.g.
adding them to your INCLUDE: tree).

Mesa.LIB contains autoopen code for the mesamain.library, so you shouldn't
have to worry about opening and closing it. Just don't forget to link with
Mesa.LIB. It will also cause a driver library to open.

If you want to open the libraries yourself, I recommend opening
mesamain.library, and then getting a driver library base from it by
calling mesaGetAttr(MESA_DriverBase,&mesadriverBase). It is also possible
to open a specific driver, see the mesadriver and mesamain docs.

In typical use, you probably want to output the result to a window. After
setting up your Intuition window as per usual, create a context for it by
calling AmigaMesaRTLCreateContext(). Pass a pointer to the window to the
output handler with OH_Output, and tell it is a window by setting
OH_OutputType to "Window". Make sure the context is current by calling
AmigaMesaRTLMakeCurrent().

Do lots of interesting graphics stuff. Don't forget that glFlush() has to
be called (directly or indirectly) for the result to be send to an output
handler.

Before closing the window, you should destroy the context with
AmigaMesaRTLDestroyContext().

For example (without error checking):

  my_window = OpenWindowTags(...);
  my_context = AmigaMesaRTLCreateContext(
                     OH_OutputType,  "Window,    /* Output is a window */
                     OH_Output,      my_window,  /* Use my window */
                     AMRTL_RGBAMode, TRUE,       /* RGBA drawing mode */
                     TAG_END);
  AmigaMesaRTLMakeCurrent(my_context);

  /* ...Do OpenGL stuff... */

  AmigaMesaRTLDestroyContext(my_context);
  CloseWindow(my_window);

See the included examples and src-glut/glutCreateWindow.c for inspiration,
and the mesadriver and outputhandler docs.



GLUT
====

Having a Mesa library is all fine and dandy, but most Mesa and OpenGL
examples use the GL Utility Toolkit (GLUT) by Mark Kilgard. So the obvious
answer is: we need a port of GLUT.

Having looked at the GLUT source code, this is easier said than done. It
is highly X11-centric, with a Windows port mixed in. I thought about it,
but in the end I decided to do a from-scratch GLUT look-alike
implementation. It can be found in amiga/src-glut.

At present, most of the most-commonly used functions are implemented. No
guarantee that they behave identically to the official GLUT distribution,
but most of the redbook examples seem to work OK.


Using GLUT
----------

when compiling a GLUT program, make sure you link with GLUT.LIB and
Mesa.LIB. These will open the libraries for you. If you want to open the
GLUT library yourself, you must remember to tell GLUT which mesamain base
and mesadriver base to use by calling glutAssociateGL(). These bases
should be the same ones the application is using.

When run, a glut program will by default let the output handler open a
window. If told top open a window itself, GLUT will try to open a window
on a public screen named Mesa, or the one specified by the pubscreen
argument. Use one of the zillion pubscreen managers available on AmiNet to
set up a public screen.

GLUT Menus
..........
The GLUT menus use the usual Amiga menu system. Instead of having a menu
associated with a mouse button, there is a "Left Menu", "Middle Menu", and
"Right Menu" menu.
As the Amiga menu system only supports up to one level of sub-menus, any
sub-sub-menus (and sub-sub-sub-menus and sub-sub-sub-sub-menus and ...)
will be changed to a sub-menu after the parent.

GLUT mouse buttons
..................
As the right mouse button is tied up with menus, middle and right mouse
button presses can be done by qualifying the left mouse button press with
the Right-Amiga and Right-Alt keys respectively. For those of you with
three-button mice, the middle button should also be recognised.

GLUT termination
................
The GLUT main loop is traditionally terminated by exit()'ing the program.
Amiga GLUT uses SAS/C's STI_ and STD_ mechanism to clean up on exit().
Quiting a GLUT program is usually done by pressing the ESC key. Clicking
the window close button will cause Amiga GLUT to call the context's
keyboard function with an ESC key code.
However, some example programs never exit. Instead they expect the user to
kill the program (by e.g. ^C). To handle such evil programs, Amiga GLUT
has a panic drop-through. If pressing the window close button has no
effect (i.e. the program is not listening to ESC key presses), a second
click on the window close button will cause glutMainLoop() to return. This
usually works as glutMainLoop() is often the last command in main() before
it returns. But, as this is against the documented behaviour of
glutMainLoop(), Bad Things may happen instead.
As of version 2, the GLUT library also listens for ^C. When received, this
too causes glutMainLoop() to return. This is handy in case the window
doesn't have a close gadget.

GLUT keys
.........
The GLUT special keys implemented are: the cursor keys, and functon keys
F1 to F10.

Idle
....
A single glutMainLoop() loop will handle all the messages on the queue. If
set, glutIdleFunc() will be called whenever glutMainLoop() finds no
messages to handle (other than IDCMP_INTUITICKS) in a single loop. (This
is in contrast to a macintosh implementation I know of which actually
speeds up if you e.g. press a key).


Running a GLUT program
----------------------

Any GLUT program which calls glutInit() (as all should), recognises the
following command line options:

  Option      : -pubscreen
  Values      : <any name>
  Default     : Mesa
  Description : Set the public screen to open windows on

  Option      : -outputhandler
  Values      : <any name>
  Default     : <not set>
  Description : Set value for AMRTL_OutputHandler

  Option      : -outputhandlerversion
  Values      : <any ULONG>
  Default     : <not set>
  Description : Set value for AMRTL_OutputHandlerVersion

  Option      : -nohandlerwindow
  Values      : <none>
  Default     : <not set>
  Description : When specified, don't let the output handler open a
                window. GLUT will open a window instead.

If a program doesn't appear to give any output, check to see if it calls
glFlush(), or anything that calls it (like glutSwapBuffers()). If it
doesn't, add it (typically at the end of the display() function). Also
make sure you give the program plenty of stack.


WARNING!
--------

Please beware that at present, Amiga GLUT lacks a lot of error checking.
Bad Things will very likely happen if Something Goes Wrong.



ENVIRONMENT VARIABLES
=====================

From v2, a variety of environment variables are used by AmigaMesaRTL. Here
is a summary. The effect of a variable can be limited to one program by
setting a local environment variable, or made general by setting it as a
global environment variable. The values of each of these variables can of
course be overridden by an application by setting tag values.


AmigaMesaRTL/Driver        (default: amigamesartl)
AmigaMesaRTL/DriverVersion (default: 2)
--------------------------
Name and version of driver to use. A driver with the exact name given is
expected to be found in LIBS:MesaDrivers/.


AmigaMesaRTL/OutputHandler        (default: dl1)
AmigaMesaRTL/OutputHandlerVersion (default: 2)
---------------------------------
Name and version of output handler to use. An output handler with the
exact name given is expected to be found in LIBS:OutputHandlers/.


AmigaMesaRTL/<output type> (e.g. AmigaMesaRTL/Window)
--------------------------
Name of the output handler to use for a specific output type. This
overrides the AmigaMesaRTL/OutputHandler variable. An output handler with
the exact name given is expected to be found in LIBS:OutputHandlers/.


AmigaMesaRTL/<output handler>.prefs (e.g. AmigaMesaRTL/dl1.prefs)
-----------------------------------
Each output handler can have its own preferences. These are stored in this
environment variable. The format is output handler specific, but should be
parseable by ReadArgs() using the pattern obtained by getting the value of
OH_ParameterQuery from the output handler.



MORE DOCUMENTATION
==================

Autodoc-style documentation is provided in amiga/drivers/mesadriver.doc,
amiga/outputhandlers/outputhandler.doc, and amiga/src/mesamain.doc.



FUTURE
======

I'm thinking about doing a Warp3D-based driver.

