
About the renouveau tool
-----------------------------

There are multiple ways for the CPU to send graphics commands to a video card.
* The fastest one is the use of a fifo. This fifo is nothing more than a chunk 
  of memory which contains commands in a format suitable for the video card. In
  order to control the video card, the CPU writes commands into that fifo, and 
  tells the card to execute them. In odrer to write a driver, we need to find 
  out what commands we need to write in a fifo to achieve the functionality we 
  want. The fifo area is displayed by renouveau as "=> fifo".
* Another technique is the use of memory mapped registers (MMIO). Once again, 
  these registers are just seen as a piece of memory. Each register is one word
  in that piece of memory, contains a value, and has a meaning. In order to 
  write a working driver, we also have to take care of putting the right values 
  in the right registers at the right time. The register areas are displayed 
  by renouveau as "=> registers". 

That's where renouveau comes in the mix. The code is self-contained in re.c, 
and has a very simple interface described in re.h :
* dump_before() : this is the starting point from which commands and register
  modifications will be displayed. This function doesn't output anything.
* dump_after() : this is the end of the dump. This functions outputs the 
  changes in the registers and in the fifo contents since dump_before() was
  called.

Sample usage is shown in main.c : an OpenGL display is setup through SDL, and
dump_before() is called. Some vertices are sent, and dump_after() is called. 
The changes of state are printed to screen, and some other commands are then
tested.
  
In order to figure out new functionality using renouveau, a simple scheme can
be followed : 
* call dump_before()
* call OpenGL commands that trigger the functionnality you're looking for
* call dump_after()
* look at the changes, and try to make sense out of them. Retrying multiple 
  times is almost mandatory before being able to make sense out of the data, 
  and sometimes using small variations in the OpenGL commands (for example, 
  changing a vertex color or position) can help

Although registers don't have a rigid format (it's just an array of values), 
the fifo contents has a strict packet format described as follows : 
* a 32 bit header containing the command type, the command size and the 
  channel number as follows :
  ((size) << 18) | ((channel) << 13) | (command_type))
* a number of 32 bit values which are the actual data.

For example, {0x00043808,0x00000005} can be interpreted as follows :
* The header is 0x00043808 
  0x00043808 = 0x00040000 | 0x00002000 | 0x00001808
             = (1<<18)    | (1<<13)    | 0x00001808
  So here, the packet carries 1 dword (or 4 bytes) of data, is sent to channel 1, 
  and is of type 0x1808. It turns out that 0x1808 almost means glBegin()
* The data is 0x00000005
  here the data means GL_TRIANGLES


Kernel 2.4
----------

  Currently most of the work is used with kernel 2.6.x. If you want to try renouveau
on a 2.4 kernel (for example when you test an old Nvidia driver), you need to add
'-lGL' to the LDFLAGS in the Makefile. Even if renouveau loads libGL itself, it
crashes with a 2.4 kernel without being linked to the libGL library.  


Dump tips
---------

  When you make dumps, you want them to be as small as possible for the feature
you test. There are 3 defines to uncomment in re.c file to help it:
- OUTPUT_MULTIPLE_FILES: each test will be outputted to a different file
- DONT_DUMP_CHANGED_REGS: when uploading a texture to video ram, you'll see all
the texture data uploaded in this type of section of the dump. For a 16x16 32
bits texture, this is 256 32bits values. As you're not really interested in what
the texture is like, you can avoid dumping it, especially when you test with a
2048x2048 texture (4M values).
- DONT_DUMP_ABOVE_40000: sometimes, renouveau sees changes in the fifo which are
above offset 0x40000, mainly there are leftover for some stuff, so you can safely
ignore them most of the time, except if you have a test that requires more than
0x40000 commands to be sent to gpu.

  Both test_startup() and test_default() must be left uncommented in main.c.
test_startup() will dump all commands used to setup default values for the OpenGL
context. test_default() only draws a simple triangle using this context.


Where is feature X in 3D TCL engine?
------------------------------------

  The TCL engine takes most parameters as 32bits float, so run renouveau with '-f'
parameter on the command line. It will only display unknown values as floats. The
known ones have already their format. And it's easier to see a value displayed as
'1.0' instead of '0x3f800000'.
  Luckily most features in the TCL engine use OpenGL defined constants, to set
a special mode of operation for a 3D command. Here is an example:

20c   0x00001d01   0x00001d01            NV10_TCL_PRIMITIVE_3D      [0x037c/4] =
 0.000000 | UNKNOWN = 00001d01

So we have a 3D TCL feature, using fifo command 0x37c, set to integer value
0x1d01. This does not seem to be a meaningful value? you're wrong.

$ grep -i 1d01 /path/to/GL/gl.h
#define GL_SMOOTH                         0x1D01

If it is not found in GL/gl.h, it may be in GL/glext.h if it is coming from some
extension. So now, we must check which OpenGL command setup GL_SMOOTH as default
value. Your OpenGL redbook will come handy to find that this is glShadeModel().
So now you write a small test function, like test_shade_model() in tests.c to do
some rendering using both GL_FLAT and GL_SMOOTH as parameters to glShadeModel().
In the dump for test_shade_model, you'll see this fifo command 0x37c called just
before rendering the triangle, setting it to 0x1d00 (GL_FLAT) and then 0x1d01
(GL_SMOOTH). Nice, you find how glShadeModel() is done inside gpu.
