#pragma ident "@(#)api.txt 1.12 98/03/20 SMI"


Copyright (c) 1997 by Sun Microsystems, Inc.
All Rights Reserved



The following is a breif description of the geometry compression
utility API.  The definition of the compressed geometry buffer is
subject to change in future revisions.


Compression Utility API:

cgGetError()
	Returns current error.  Operates just like glGetError().
	The following are the valid error codes:

	CG_NO_ERROR
		No error has occurred.  This value is guaranteed
		to be zero.

	CG_DATA_INCONSISTENT
		Inconsistent data between cgBegin - cgEnd pairs.
		All vertices must be the same or a subset of the first
		vertex.  For instance the following would generate a
		CG_DATA_INCONSISTENT error:
			cgBegin(CG_TRIANGLE)
				cgVertex(..)
				cgVertex(..)
				cgNormal(..)
				cgVertex(..)
			cgEnd() 

		An attempt was made to mix different primitive classes
		(see cgBegin) within the same compressed geometry buffer.
		Mixing cgColor3 and cgColor4 within a cgBegin/cgEnd pair
		will also result in a CG_DATA_INCONSISTENT error.

	CG_INVALID_ENUM
		An unacceptable value has been specified for an enumerated
		argument.

	CG_OUT_OF_MEMORY
		Ran out of memory.  The state of the compression library
		is undefined after this error occurs.

	CG_INVALID_OPERATION
		Invalid operation performed during a cgBegin - cgEnd pair.

		cgEnd called before the corresponding cgBegin is called.

		Any cg command called outside a cgBeginCompressedGeometryStream


cgBeginCompressedGeometryStream(CGint geomQuant, CGint normalquant,
				CGint colorQuant, 
				CGenum quantEnforcement)

	geomquant, colorQuant - number of bits to compress geometry/color.
		16 bits maximum.
	normalQuant - number of bits to compress normals. 18 bits maximum.

	quantEnforcement - is the compression routine allowed to increase
		quantization to reduce quantization errors?  Applies
		to position quantization only.

	Initiates the building of a compressed geometry buffer.


cgEndCompressedGeometryStream(CGubyte** data, CGint size, CGviewport *viewport)

	CGubyte**    data     - will point to the compressed geometry buffer
        CGint        size     - size (in bytes) of entire buffer
        CGviewport*  viewport - viewport needed to reposition data to
				original location

	Terminates the building of the compressed geometry buffer.  If
	there were no errors while entering in the points, the compressed
        geometry buffer will be allocated (using malloc) by the compression
        routine.  The caller is responsible for freeing this memory.

	All compressed data must be in the range of -1.0 to 1.0.  If data
	is not in this range, the compression routine will perform the
	necessary steps to place it within the -1.0 to 1.0 range. The
	viewport parameter is filled in with the necessary scale and offset
	values to return the data to it's original position.

	typedef struct {
		float scale;
		float ox, oy, oz;
	} CGviewport

	See the description of glDrawCompressedGeometrySUN for details on
	how to use this for proper rendering.

cgBegin, cgEnd
	Delimit the vertices that define a primitive or a group of like
	primitives.  cgBegin accepts a single argument that specifies which
	way the vertices are interpreted, as follows:

		CG_POINTS
			a.g.a GL_POINTS

		CG_LINES
			a.k.a GL_LINES

		CG_LINE_STRIP
			a.k.a GL_LINE_STRIP

		CG_LINE_LOOP
			a.k.a GL_LINE_LOOP

		CG_TRIANGLES
			a.k.a GL_TRIANGLES

		CG_TRIANGLE_STRIP
			a.k.a GL_TRIANGLE_STRIP

		CG_TRIANGLE_FAN
			a.k.a GL_TRIANGLE_FAN

		CG_QUADS
			a.k.a GL_QUADS

		CG_QUAD_STRIP
			a.k.a GL_QUAD_STRIP

		CG_POLYGON
			a.k.a GL_POLYGON

	A compressed geometry buffer must consist of only one "class" of
	primitive.  The primitives are divided up into 3 classes:
		Point Class - CG_POINTS
 		Line Class  - CG_LINES, CG_LINE_STRIP, CG_LINE_LOOP
		Fill Class  - CG_TRIANGLES, CG_TRIANGLE_STRIP,
  				CG_TRIANGLE_FAN, CG_QUADS, CG_QUAD_STRIP,
				CG_POLYGON
	An attempt to put primitives of different classes into the same
	compressed geometry buffer is an error (CG_DATA_INCONSISTENT).

	The following are the commands which are valid between
	a cgBegin - cgEnd pair: cgVertex, cgColor and cgNormal.
	Functions as glBegin and glEnd, respectively with the following
	restriction: all data between a cgBegin - cgEnd pair must be
	subset of the data type of the first vertex.  For instance,
	if the first vertex is:
		cgNormal()
		cgVertex()
	then all subsequent vertices must be either:
		cgVertex()
	or:
		cgNormal()
		cgVertex()
	a point with color information:
		cgColor()
		cgVertex()
	would be an error and the CG_DATA_INCONSISTENT error would
	be set.  The inconsistent data would be ignored but processing
	would continue.  If a vertex is encountered that is a subset of
	the first vertex then any color or normal information needed will
	be copied from the last color or normal value set.


cgColor
	cgColor3[b,d,f,i,s,ub,ui,us][v]
	cgColor4[b,d,f,i,s,ub,ui,us][v]

	Changes current color as glColor.  Can be called  at anytime after
	cgBeginCompressedGeometryStream() is called.  The color is clamped
	to the range [0.0..1.0] before being compressed.  The default color
	is: (1.0, 1.0, 1.0, 1.0) (r,g,b,a).

        Index colors are not supported.

cgNormal
	cgNormal3[b,d,f,i,s][v]

	Changes current normal as glNormal - all normals must be
	normalized.  Can be called  at anytime after
	cgBeginCompressedGeometryStream() is called.  The default
	normal is (0.0, 0.0, 1.0).

cgVertex
	cgVertex3[d,f,i,s][v]

	Specifies polygon vertices as glVertex

cgGeomFrontFace
	CG_CW, CG_CCW, the default is CG_CCW

	Specifies the orientation of front-facing polygons.  During
        decompression, this attribute is xor'd with glFrontFace to come up
	with the proper winding value.

Vertex Arrays

	For this release there will be no vertex array equivalent for the
	cg routines.



Decompression Utility API:

        cgDecompressGeometryStream(cgData, ugData, ugSize)

        CGubyte** cgData   - pointer to the compressed geometry buffer
        CGuint*  ugData   - pointer to the uncompressed data buffer.
                            This buffer is created (via malloc) and it is the
                            user's responsibility to free it.

        CGuint* ugSize   - will hold the size of the uncompressed buffer
                                        in 32-bit words.

       Takes the compressed geometry buffer, and decompresses
        it into a buffer with the format:

        CGuint type   /* data type */
        variable length data

        type is one of:
                CG_LINE_STRIP
                CG_POINTS
                CG_SET_COLOR3
                CG_SET_COLOR4
                CG_SET_FRONTFACE
                CG_SET_NORMAL
                CG_TRIANGLE_FAN
                CG_TRIANGLE_STRIP

        The following are the formats for all of the various objects:

        CG_LINE_STRIP
                CGuint  type;   /* CG_LINE_STRIP */
                CGuint  ptType; /* CG_COLOR | CG_ALPHA | CG_NORMAL */
                CGuint  numPts;

                /* followed by numPts vertices of type ptType */

        CG_POINTS
                CGuint  type;   /* CG_POINTS */
                CGuint  ptType; /* CG_COLOR | CG_ALPHA | CG_NORMAL */
                CGuint  numPts;

                /* followed by numPts vertices of type ptType */

        CG_SET_COLOR3
                CGuint  type;   /* CG_SET_COLOR3 */
                CGfloat red;
                CGfloat green;
                CGfloat blue;

        CG_SET_COLOR4
                CGuint  type;   /* CG_SET_COLOR4 */
                CGfloat red;
                CGfloat green;
                CGfloat blue;
                CGfloat alpha;

        CG_SET_FRONTFACE
                CGuint  type;   /* CG_SET_FRONTFACE */
                CGuint  val;    /* stick with CG_CW/CCW */

        CG_SET_NORMAL
                CGuint  type;   /* CG_SET_NORMAL*/
                CGfloat nx;
                CGfloat ny;
                CGfloat nz;

        CG_TRIANGLE_FAN
                CGuint  type;   /* CG_TRIANGLE_FAN */
                CGuint  ptType; /* CG_COLOR | CG_ALPHA | CG_NORMAL */
                CGuint  numPts;

                /* followed by numPts vertices of type ptType */

        CG_TRIANGLE_STRIP
                CGuint  type;   /* CG_TRIANGLE_STRIP */
                CGuint  ptType; /* CG_COLOR | CG_ALPHA | CG_NORMAL */
                CGuint  numPts;

                /* followed by numPts vertices of type ptType */


        Point formats

        Vertex3d
                CGfloat x;
                CGfloat y;
                CGfloat z;

        Normal Vertex3d
                CGfloat nx;
                CGfloat ny;
                CGfloat nz;
                CGfloat x;
                CGfloat y;
                CGfloat z;

        Color Vertex3d
                CGfloat r;
                CGfloat g;
                CGfloat b;
                CGfloat x;
                CGfloat y;
                CGfloat z;

        ColorAlpha Vertex3d
                CGfloat r;
                CGfloat g;
                CGfloat b;
                CGfloat alpha;
                CGfloat x;
                CGfloat y;
                CGfloat z;

        Color Normal Vertex3d
                CGfloat r;
                CGfloat g;
                CGfloat b;
                CGfloat nx;
                CGfloat ny;
                CGfloat nz;
                CGfloat x;
                CGfloat y;
                CGfloat z;

        ColorAlpha Normal Vertex3d
                CGfloat r;
                CGfloat g;
                CGfloat b;
                CGfloat alpha;
                CGfloat nx;
                CGfloat ny;
                CGfloat nz;
                CGfloat x;
                CGfloat y;
                CGfloat z;


OpenGL API:

When geometry compression is present in the library the extension string
GL_SUNX_geometry_compression will be listed in the GL_EXTENSIONS string.

glDrawCompressedGeometrySUNX(data, size)

        GLubyte*   data;
        GLuint     size;  /* size of data in bytes */

	Draws compressed geometry.  When drawing with glPolygonMode
	set to GL_LINE, all edges are considered to be external. All
	current attributes are inherited (ex: glMaterial, current glColor...).
	Upon return, the current color and current normal are undefined.

	For this release, texture attributes are not allowed.

	All data in a compressed geometry stream is in the range of
	-1.0 to 1.0.  To place the compressed geometry back to its
	original position in the scene a scale and offset value may need
	to be appended to the modelview matrix.

	For example:

		glPushAttrib(GL_MATRIX_MODE);	// If modelview not current mx
		glMatrixMode(GL_MODELVIEW);	// If modelview not current mx
		glPushMatrix();			// If not a leaf matrix
		glTranslatef(xo, yo, zo);
		glScalef(scale, scale, scale);
		glDrawCompressedGeometrySUNX(data, size);
		glPopMatrix();			// If not a leaf matrix
		glPopAttrib();			// If modelview not current mx
		

	One problem - normals.

	When OpenGL computes the inverse transpose of the modelview matrix
	(needed to transform the normals), it does not rescale the normals.
	This can result in incorrect lighting.  To correct this problem
	there are three possible solutions:

		Set GL_RESCALE_NORMAL_EXT if present.

                If the above extension is not present then set
		GL_NORMALIZE.


glGetString(GL_COMPRESSED_GEOM_ACCELERATED_SUNX);

	Used to check for the presence of hardware that supports compressed
	geometry.  Returns either the highest version number supported by
	the hardware or NULL if the hardware does not support compression
	at all.  The version number is major.minor.minor-minor.

glGetString(GL_COMPRESSED_GEOM_VERSION_SUNX);

	Returns the highest version number of the compressed geometry buffer
	format supported by the software library. The version number is
	major.minor.minor-minor.
		 
Format of compressed geometry buffer:
	The compressed geometry buffer is a byte stream of data.

	The first 48 bytes are header info:
		1 byte major number
		1 byte minor version number
		1 byte minor-minor version number
                1 byte buffer type field
		1 byte data present field
		23 bytes reserved (must be 0)
		4  byte floating point scale (big endian)
		4  byte floating point xoffset
		4  byte floating point yoffset
		4  byte floating point zoffset
		4  byte Size (in bytes) of compressed geometry (including
		    header)
			byte 1 - bits 31..24
			byte 2 - bits 23..16
			byte 3 - bits 15..8
			byte 4 - bits  7..0

	The valid values for the buffer type field are:
		0x01	Point buffer
		0x02	Line buffer
		0x04	Triangle buffer

        The valid values for the data present field are:
                0x01    normal present in buffer
                0x02    color present in buffer
		0x04    color alpha present in buffer

	The next Size - header bytes is the compressed geometry buffer.


	The valid formats for the compressed geometry are:

        (Note the first 8 bits of an instruction are called the instrucion's
	 header)

	Vertex
	
	+-------------------------------+   +---------------------------- ~ +
	|   |   |   |   |   |   |   |   |   |   |   |   |                   |
	| 0 | 1 |  Pos Bits n - (n -5)  |   |  rep  |mbp| Pos (n - 6) - 0   | 
	+-------------------------------+   +---------------------------- ~ +

	 +- - - - - - - - - - - - - - ~ -+   +- - - - - - - - - - - - - - ~ -+
	 |                               |   |                               |
	 |       Normal Bits n - 0       |   |        Color Bits n - 0       | 
	 +- - - - - - - - - - - - - - ~ -+   +- - - - - - - - - - - - - - ~ -+

		rep - vertex replacement (this field ignored for points)
		 00 - Restart clockwise (move for lines)
                 01 - Restart counter-clockwise (move for lines)
                 10 - Replace middle (draw for lines)
                 11 - Replace oldest (draw for lines)

		mbp - mesh buffer push
                  0 - No push
                  1 - Push

		The position is a variable length Huffman tag (0 - 6 bits)
		followed by three fields of variable but equal length for
                the X, Y, and Z components, which are either absolute or
                delta values.  The format for the position data is s.15 (less
                than 15 bits can be used for greater compression).

		If the bnv bit is set (via a Set State call) a normal is
		included.  The encoded normal has a Huffman tag followed by
		either two variable length data fields for delta u and
		delta v or a fixed length field consisting of 3 bits for
		the sextant and 3 bits for the octant followed by two variable
		length fields of up to 6 bits each for u and v (or delta-u and
		delta-v).  u and v are used as indices into the normal look-up
		table.

		If the bcv bit is set (via a Set State call) a color is
		included with the vertex.  A Huffman tag is followed by
		three equal but variable length fields for R, G, and B.  The
                cap bit (set via a Set State call) indicates if a field for
		Alpha is included.  The format for the color data is
		s.15 (less than 15 bits can be used for greater compression).
		

	Normal

	+-------------------------------+   +---------------------------- ~ +
	|   |   |   |   |   |   |   |   |   |                               |
	| 1 | 1 | Norm Bits n - (n - 5) |   |   Normal Bits (n - 6) - 0     | 
	+-------------------------------+   +---------------------------- ~ +


		The Set Normal instruction sets the value of the current
		normal.  The encoded normal has a Huffman tag followed by
		either two variable length data fields for delta u and
		delta v or a fixed length field consisting of 3 bits for
		the sextant and 3 bits for the octant followed by two variable
		length fields of up to 7 bits each for u and v (or delta-u and
		delta-v).  u and v are used as indices into the normal look-up
		table.  The value of u and the value of v must be less than
		or equal to 64.


	Color

	+-------------------------------+   +---------------------------- ~ +
	|   |   |   |   |   |   |   |   |   |                               |
	| 1 | 0 | Color Bits n - (n - 5)|   |    Color Bits (n - 6) - 0     | 
	+-------------------------------+   +---------------------------- ~ +

		The Set Color instruction sets the value of the current
		color.  The color data is encoded the same as the color
		data in the Vertex command. The format for the color data is
		s.15 (less than 15 bits can be used for greater compression).


	Mesh Buffer Reference

	+-------------------------------+   +---+
	|   |   |   |   |   |   |   |   |   |   |
	| 0 | 0 | 1 |     Index     |rep|   |rep| 
	+-------------------------------+   +---+

		rep - vertex replacement
		 00 - Restart clockwise
                 01 - Restart counter-clockwise
                 10 - Replace middle
                 11 - Replace oldest

		This instruction causes data from an entry in the mesh
		buffer to be used.  The index indicates the entry from
		the mesh buffer to send.  The newest entry in the mesh
		buffer has index 0, and the oldest has index 15.  If more
		than 16 entries are pushed onto the mesh buffer, the oldest
		entry is discarded.

		If the bnv (or bcv) bit is set and a Set Normal (or
		Set Color) command is issued, then the next Mesh Buffer
		Reference will use the current normal (or color) 
		and not the mesh buffer normal. If a Vertex or Set State
		instruction comes between the Set Normal or Set Color
		instruction and the Mesh Buffer Reference instruction,
		the data will come from the mesh buffer.

		Ex:
			V, N0 (mesh buffer push)
			V, N1
			Set Normal N2
			MBR 0 (uses normal N2)
			Set Normal N3
			V, N4
			MBR 0 (uses normal N0)
			


	Set State

	+-------------------------------+   +-----------+
	|   |   |   |   |   |   |   |   |   |   |   |   |
	| 0 | 0 | 0 | 1 | 1 |rsv|rsv|bnv|   |bcv|cap|rsv| 
	+-------------------------------+   +-----------+

		rsv - reserved must be set to 0
		bnv - bundle normals with vertices
		bcv - bundle colors with vertices
		cap - color alpha present

		Sets the indicated value(s).


	Set Table

	+---------------------------------------------------------------------+
	|   |   |   |   |   |   |   |   |   |   |   |   |   |   |             |
	| 0 | 0 | 0 | 1 | 0 |  tbl  |           Address         |Entry(9 bits)|
	+---------------------------------------------------------------------+

		tbl - table selection
		 00 - Position table
                 01 - Color table
                 10 - Normal table
                 11 - undefined

		Sets entries in the Huffman table.  The Huffman tables are
		used to decode the Huffman tags preceding the compressed data.
		In order to send down any data, the Huffman tables must be
		initialized to their proper values.  Not initializing the
		Huffman tables will yield unpredictable results.

                Table settings are made in aligned power of two ranges; the
		position of the first '1' bit in the address field indicates
		how many entries are to be consecutively set; the remaining
		bits after the first '1' are the upper address bits of the
		base table entries to be set.  This also sets the length of
		the "tag" that this entry defines as equal to the number of
		leading zero bits (if any) before the first '1' bit.

		Address	Semantics			Tag Length
		1xxxxxx	set table entry xxxxxx			6
		01aaaaa	set table entries xxxxx0-xxxxx1		5
		001xxxx	set table entries xxxx00-xxxx11		4
		0001xxx	set table entries xxx000-xxx111		3
		00001xx set table entries xx0000-xx1111 	2
		000001x set table entries x00000-x11111 	1
		0000001 set table entries 000000-111111 	0

		The tables entries look like:

		+-----------------------------------------------+
		|   |   |   |   |   |   |   |   |   |   |   |   |
		|  tag_len  |   data_len    |a/r|    Shift      | 
		+-----------------------------------------------+

		 tag_len  - length of the Huffman tag.  The tag_len and
				data_len field must add to a minimum of 6.
                 data_len - length of the data fields that follow the
				huffman tag.  For color and position data,
				a zero in this field means the data is 16 bits
				in length.  The data_len value for normals is
				the length of either an u/v entry or a du/dv
				entry.  For the absolute case, the
				sextant/octant bits are not counted in the
				data_len field.  This length is the length
				from the first significant bit to the end.
				The tag_len and data_len field must add to
				a minimum of 6.
		 a/r      - absolute data (1) or relative to previous value (0)
		 Shift    - quantization level (number of trailing zeroes)

		The tag_len field is derived from the address and is not sent
                down with the Set Table command.  The address
		is a variable length Huffman code.

		Note: The AFB hardware cannot process data that has a tag
		length of 0.  This means setting a huffman table using
		address 0000001 will not work.
 
	VNOP

	+-------------------------------+   +---------------------------- ~ +
	|   |   |   |   |   |   |   |   |   |   |   |   |   |   |           |
	| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |   |      Bit Count    |    0's    | 
	+-------------------------------+   +---------------------------- ~ +

		Encodes a variable number of 0 bits into the data stream.
		The bit count field specifies the number of 0 bits that follow.
		This instruction can be used to align data to 64-bit word
		boundaries.  An implicit VNOP header is always assumed to start
		a compressed geometry buffer.


        Reserved

        +-------------------+
        |   |   |   |   |   |
        | 0 | 0 | 0 | 0 | 1 |
        +-------------------+

                This op-code is reserved for future use.


Building a Compressed Geometry Buffer

	A compressed geometry buffer stream has the format of:

		header (first 8 bits) of instrucion N
		data (remaining bits after header) for instruction N - 1
		header for instruction N + 1
		data for instruction N
		...

	Further, a compressed geometry buffer is always assumed to start
	with an implicit VNOP header so the start of a compressed geometry
	buffer looks like:

		header of first user instruction
		data for implicit VNOP instruction
		  (at least the 5 bit length field set to 0)
		header of next user instruction
		data for first user instruction


	Whenever color or normal information is bundled with a vertex, the
	first 6 bits of the color/normal data are treated as the instruction
	header:

		vtx header
		data for previous instruction
		color/normal header (first 6 bits)
		vtx data
		header for next instruction
		color/normal data

	A buffer must always end on a 64 bit boundary and with a vnop
	header with no data field:

		VNOP header
		data for previous instruction
		VNOP header (the empty VNOP command)
		VNOP data (with 0's to align data to 64 bit boundary)

	The minimum value of: tag_length + (data_length - data_shift) is
	6.
