/*
 * Copyright 1995, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED
 *
 * UNPUBLISHED -- Rights reserved under the copyright laws of the United
 * States.   Use of a copyright notice is precautionary only and does not
 * imply publication or disclosure.
 *
 * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to restrictions
 * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
 * in similar or successor clauses in the FAR, or the DOD or NASA FAR
 * Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
 * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
 *
 * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
 * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
 * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
 * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
 * GRAPHICS, INC.
 *
 */

/*
 * File:	gt.h
 * Creator:	hsa@sgi.com
 * Create Date:	Thu Oct 12 15:48:14 PDT 1995
 *
 * This file defines the GBI for the TURBO 3D graphics microcode.
 * The turbo microcode is a special FEATURE-LIMITED microcode designed
 * for specific applications. It is not for general use.
 *
 * (see XXX for more information)
 *
 */

/**************************************************************************
 *
 *  $Revision: 1.16 $
 *  $Date: 1998/05/28 00:14:50 $
 *  $Source: /hosts/gate3/exdisk2/cvs/N64OS/Master/cvsmdev2/PR/include/gt.h,v $
 *
 **************************************************************************/

#ifndef _GT_H_
#define	_GT_H_

/* this file should be #included AFTER gbi.h */

#include "sptask.h"

#ifdef	_LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif	/* _LANGUAGE_C_PLUS_PLUS */

#include <PR/ultratypes.h>

/* the following #defines seem out of order, but we need them
 * for the microcode.
 */

/* 
 * object state field: rendState
 *
 * This flag word is built up out of the bits from a
 * subset of the G_SETGEOMETRYMODE flags from gbi.h.
 * 
 * When each of these bits is '1', the comments below explain
 * the effect on the triangles.
 */
#define GT_ZBUFFER		G_ZBUFFER
#define GT_TEXTURE		G_TEXTURE_ENABLE	/* texture ON */
#define GT_CULL_BACK		G_CULL_BACK		/* reject backfaces */
#define GT_SHADING_SMOOTH	G_SHADING_SMOOTH	/* smooth shade ON */

/*
 * object state field: textureState
 *
 * The lower 3 bits of this flag word contain the texture tile number
 * to be used. All triangles of an object are rendered with the same
 * texture tile.
 */

/* 
 * object state field: flag
 *
 * This is a group of what would be pad bits. We use them for some
 * flag bits.
 */
#define GT_FLAG_NOMTX		0x01	/* don't load the matrix */
#define GT_FLAG_NO_XFM		0x02	/* load vtx, use verbatim */
#define GT_FLAG_XFM_ONLY	0x04	/* xform vtx, write to *TriN */


#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)

/* turbo 3D ucode: */
extern long long int	gspTurbo3DTextStart[], gspTurbo3DTextEnd[];
extern long long int	gspTurbo3DDataStart[], gspTurbo3DDataEnd[];
extern long long int	gspTurbo3D_dramTextStart[], gspTurbo3D_dramTextEnd[];
extern long long int	gspTurbo3D_dramDataStart[], gspTurbo3D_dramDataEnd[];
extern long long int	gspTurbo3D_fifoTextStart[], gspTurbo3D_fifoTextEnd[];
extern long long int	gspTurbo3D_fifoDataStart[], gspTurbo3D_fifoDataEnd[];

/*
 * This is the global state structure. It's definition carefully 
 * matches the ucode, so if this structure changes, you must also change
 * the ucode.
 */
typedef struct {
    u16		perspNorm;	/* persp normalization */
    u16		pad0;
    u32		flag;
    Gfx		rdpOthermode;
    u32		segBases[16];	/* table of segment base addrs (SEE NOTE!) */
    Vp		viewport;	/* the viewport to use */
    Gfx		*rdpCmds;	/* block of RDP data, process if !NULL
				 * block terminated by gDPEndDisplayList()
				 * (This is a segment address)
				 */
} gtGlobState_t;

/* NOTE:
 * Although there are 16 segment table entries, the first one (segment 0)
 * is reserved for physical memory mapping. You should not segment 0
 * to anything other than 0x0.
 */

typedef union {
    gtGlobState_t	sp;
    long long int	force_structure_alignment;
} gtGlobState;


/*
 * This is the 'state' structure associated with each object
 * to be rendered. It's definition carefully matches the
 * ucode, so if this structure changes, you must also change
 * the gtoff.c tool and the ucode.
 */
typedef struct {
    u32		renderState;	/* render state */
    u32		textureState;	/* texture state */
    u8		vtxCount;	/* how many verts? */
    u8		vtxV0;		/* where to load verts? */
    u8		triCount;	/* how many tris? */
    u8		flag;
    Gfx		*rdpCmds;	/* ptr (segment address) to RDP DL */
    Gfx		rdpOthermode;
    Mtx		transform;	/* the transform matrix to use */
} gtState_t;

typedef union {
    gtState_t		sp;
    long long int	force_structure_alignment;
} gtState;

/* gtStateLite : same as gtState, but no matrix (see flags below) */
/* this structure must be identical to gtState! (bad) */
typedef struct {
    u32		renderState;	/* render state */
    u32		textureState;	/* texture state */
    u8		vtxCount;	/* how many verts? */
    u8		vtxV0;		/* where to load verts? */
    u8		triCount;	/* how many tris? */
    u8		flag;
    Gfx		*rdpCmds;	/* ptr (segment address) to RDP DL */
    Gfx		rdpOthermode;
} gtStateL_t;

typedef union {
    gtStateL_t		sp;
    long long int	force_structure_alignment;
} gtStateL;

/*
 * The vertex list for the turbo display list uses the
 * Vtx struct in gbi.h
 *
 */


/*
 * This structure represents a single triangle, part of the
 * triangle list of the object to be rendered.
 *
 * NOTE: The triangle list MUST be aligned to an 8-byte boundary.
 * Since this structure is only 4 bytes, we are REQUIRING that
 * this structure only be used as an array of triangles, and we 
 * depend on the MIPS C compiler (which always aligns arrays to 
 * 8-byte boundaries). THIS IS DANGEROUS!!!!
 *
 */
typedef struct {
    u8		v0, v1, v2, flag;	/* flag is which one for flat shade */
} gtTriN;


/*
 * This structure represents the transformed points. It is the format
 * of the points written out when GT_FLAG_XFM_ONLY is set, as well as
 * the format expected when GT_FLAG_NO_XFM is used.
 *
 * NOTE: The size and layout of these points is very similar to Vtx,
 * except the screen coordinates overwrite the x,y,z,pad fields.
 * (we could consider adding to the Vtx union, but we want to keep
 * turbo stuff out of gbi.h)
 *
 * NOTE: The z is a special format. It can be used to compare vertices
 * for sorting, but it should not be used for other purposes. If modified,
 * the z-buffer hardware might not understand the data.
 *
 */
typedef struct {
    short int	xscrn;	/* x,y screen coordinates are SSSS10.2	*/
    short int	yscrn;
    int		zscrn;	/* z screen is S15.16			*/

    short int	s;	/* transformed texture coord, S10.5	*/
    short int	t;

    u8		r;	/* color (or normal)			*/
    u8		g;
    u8		b;
    u8		a;
} gtVtxOut_t;

/* see "Data Structure" comment in gbi.h for information about why
 * we use this union.
 */
typedef union {
    gtVtxOut_t		v;
    long long int	force_structure_alignment;
} gtVtxOut;



/*
 * state field: rdpOthermode
 *
 * This is one of the trickier state fields. The turbo interface
 * requires the RDP othermode command to be cached by the host,
 * therefore we provide a different interface in libultra to help cache
 * this in the gt state (this word is just bits, you could pack them
 * on your own). 
 *
 * gtStateSetOthermode() accomplishs this, taking as arguments 
 * the state, one of the following mode enums, and a piece of data 
 * (othermode parameters from gbi.h).
 *
 * By definition, the othermode word from the gt state structure is sent
 * to the RDP *before* any RDP commands from the rdpCmds[] field. The
 * othermode is *always* sent.
 *
 * Stated another way, NONE of the gbi RDP othermode commands equivalent
 * to those listed here are allowed in the rdpCmd[] field of the 
 * gt state structure.
 *
 * Notice also that many of these commands do not make sense for
 * the turbo ucode (they control features not supported, like mip-mapping). 
 * They are only included here for completeness.
 *
 */
typedef enum {
    GT_CLEAR,		/* special gt mode, clears othermode state */
    GT_ALPHACOMPARE,
    GT_ZSRCSEL,
    GT_RENDERMODE,
    GT_ALPHADITHER,
    GT_RGBDITHER,
    GT_COMBKEY,
    GT_TEXTCONV,
    GT_TEXTFILT,
    GT_TEXTLUT,
    GT_TEXTLOD,
    GT_TEXTDETAIL,
    GT_TEXTPERSP,
    GT_CYCLETYPE,
    GT_PIPELINE
} gtStateOthermode_t;

/*
 * This call builds up an othermode command word. The 'mode' is one of
 * the above modes, the 'data' field comes from gbi.h, it is the data
 * field for the equivalent gbi setothermode macro.
 */
extern void gtStateSetOthermode(Gfx *om, gtStateOthermode_t mode, int data);

/* 
 * This call dumps a turbo display list for use with gbi2mem and RSPSIM
 */
#define GT_DUMPTURBO_HANGAFTER           64
#define GT_DUMPTURBO_NOTEXTURES          128
extern void gtDumpTurbo(OSTask *tp,u8 flags);

/*
 * Special macros to init othermode words to all 0's, a good default
 * value.
 */
#define gDPClearOtherMode(pkt)						\
{									\
	Gfx *_g = (Gfx *)(pkt);						\
									\
	_g->words.w0 = _SHIFTL(G_RDPSETOTHERMODE, 24, 8);		\
	_g->words.w1 = 0x0;						\
}

#define gsDPClearOtherMode()						\
{									\
	_SHIFTL(G_RDPSETOTHERMODE, 24, 8), 0x0				\
}

/*
 * Special macros to end DP blocks (see above). These commands
 * generate all 0's, which the turbo ucode looks for. They *aren't*
 * real DP commands!
 */
#define gDPEndDisplayList(pkt)	gSPNoOp(pkt)
#define gsDPEndDisplayList()	gsSPNoOp()

/*
 * This structure is a turbo 'object', the turbo display list is
 * simply a list of these.
 *
 * NOTE: All pointers are segment addresses
 *
 * NOTE: If (statep->flag & GT_FLAG_XFM_ONLY), the trip field is
 * interpreted as a pointer to gtVtxOut[] that can be used to store
 * the transformed points. (statep->triCount should be 0, else bad
 * things could happen...)
 *
 * NOTE: If (statep->flag & GT_FLAG_NO_XFM), the vtxp field is
 * interpreted as a pointer to gtVtxOut[] that can be used to load
 * pre-transformed points.
 *
 */
typedef struct {
    gtGlobState	*gstatep;	/* global state, usually NULL */
    gtState	*statep;	/* if this is NULL, end object processing */
    Vtx		*vtxp;		/* if this is NULL, use points in buffer */
    gtTriN	*trip;		/* if this is NULL, use tris in buffer */
} gtGfx_t;

typedef union {
    gtGfx_t		obj;
    long long int	force_structure_alignment;
} gtGfx;


#endif	/* _LANGUAGE_C */

#ifdef	_LANGUAGE_ASSEMBLY
#include <PR/gtoff.h>
#endif	/* _LANGUAGE_ASSEMBLY */

#ifdef	_LANGUAGE_C_PLUS_PLUS
}
#endif	/* _LANGUAGE_C_PLUS_PLUS */

#ifdef	_LANGUAGE_MAKEROM
#endif	/* _LANGUAGE_MAKEROM */

#endif	/* _GT_H_ */