/***************************************************************************
 *                                                                         *
 * Module  : baimmedi.h                                                    *
 *                                                                         *
 * Purpose : 2D immediate mode interface                                   *
 *                                                                         *
 **************************************************************************/

#ifndef RWIMMEDI_H
#define RWIMMEDI_H

/****************************************************************************
 Includes
 */

#include "batypes.h"
#include "drvmodel.h"

/* RWPUBLIC */

/****************************************************************************
 Defines
 */


/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

                        Immediate mode interface V2.0

 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

/**
 * \ingroup datatypes
 * RwRenderState
 *     This type represents the various render states that
 * can be set using the API function \ref RwRenderStateSet. This function also
 * takes a render state value or pointer to an object depending on the type.
 * For render states that are toggles, the value should be TRUE to switch the
 * state on and FALSE to turn it off.
 *
 * Note that many of these render states may not be supported on certain
 * platforms. The \ref RwRenderStateSet functions will return FALSE in such cases.
 */
enum RwRenderState
{
    rwRENDERSTATENARENDERSTATE = 0,
    rwRENDERSTATETEXTURERASTER,             /**<Raster to texture with. \ref RwRenderStateSet
                                             *  takes a pointer to an \ref RwRaster */
    rwRENDERSTATETEXTUREADDRESS,            /**<\ref RwTextureAddressMode: wrap, clamp, mirror or border */
    rwRENDERSTATETEXTUREADDRESSU,           /**<\ref RwTextureAddressMode in u only */
    rwRENDERSTATETEXTUREADDRESSV,           /**<\ref RwTextureAddressMode in v only */
    rwRENDERSTATETEXTUREPERSPECTIVE,        /**<Perspective correction on/off */
    rwRENDERSTATEZTESTENABLE,               /**<Z-buffer test on/off */
    rwRENDERSTATESHADEMODE,                 /**<\ref RwShadeMode: flat or gouraud shading */
    rwRENDERSTATEZWRITEENABLE,              /**<Z-buffer write on/off */
    rwRENDERSTATETEXTUREFILTER,             /**<\ref RwTextureFilterMode: point sample, bilinear, trilinear, etc */
    rwRENDERSTATESRCBLEND,                  /**<Source alpha \ref RwBlendFunction: src alpha, 1-src alpha, etc */
    rwRENDERSTATEDESTBLEND,                 /**<Destination alpha \ref RwBlendFunction */
    rwRENDERSTATEVERTEXALPHAENABLE,         /**<Vertex alpha transparency on/off */
    rwRENDERSTATEBORDERCOLOR,               /**<Border color for \ref RwTextureAddressMode rwTEXTUREADDRESSBORDER.
                                             *  The value should be a packed RwUInt32 in ARGB form. The macro
                                             *  RWRGBALONG(r, g, b, a) may be used to construct this using 8-bit
                                             *  color components. */
    rwRENDERSTATEFOGENABLE,                 /**<Fogging on/off (all polygons will be fogged) */
    rwRENDERSTATEFOGCOLOR,                  /**<Color used for fogging. The value should be a packed RwUInt32
                                             *  in ARGB form. The macro RWRGBALONG(r, g, b, a) may be used to
                                             *  construct this using 8-bit color components */
    rwRENDERSTATEFOGTYPE,                   /**<Sets \ref RwFogType, the type of fogging to use */
    rwRENDERSTATEFOGDENSITY,                /**<Select the fog density for \ref RwFogType of rwFOGTYPEEXPONENTIAL
                                             *  or rwFOGTYPEEXPONENTIAL2. The value should be a pointer to
                                             *  an RwReal in the range 0 to 1. */
    rwRENDERSTATEFOGTABLE,                  /**<Install a 256 entry fog table placed between fog distance and far
                                             *  clip plane */
    rwRENDERSTATEALPHAPRIMITIVEBUFFER,      /**<Render transparent alpha polygons last - on/off */
    rwRENDERSTATECULLMODE,                  /**<Sets \ref RwCullMode, for selecting face culling. */
    rwRENDERSTATESTENCILENABLE,             /**< \if xbox
                                             *      TRUE to enable stenciling, or FALSE to disable stenciling
                                             *   \endif
                                             *   \if d3d8
                                             *      TRUE to enable stenciling, or FALSE to disable stenciling
                                             *   \endif
                                             */
    rwRENDERSTATESTENCILFAIL,               /**< \if xbox
                                             *      Stencil test operator for the fail case
                                             *   \endif
                                             *   \if d3d8
                                             *      Stencil test operator for the fail case
                                             *   \endif
                                             */
    rwRENDERSTATESTENCILZFAIL,              /**< \if xbox
                                             *      Stencil operation to perform if the stencil test passes
                                             *      and the depth test (z-test) fails
                                             *   \endif
                                             *   \if d3d8
                                             *      Stencil operation to perform if the stencil test passes
                                             *      and the depth test (z-test) fails
                                             *   \endif
                                             */
    rwRENDERSTATESTENCILPASS,               /**< \if xbox
                                             *      Stencil operation to perform if both the stencil and the 
                                             *      depth (z) tests pass
                                             *   \endif
                                             *   \if d3d8
                                             *      Stencil operation to perform if both the stencil and the 
                                             *      depth (z) tests pass
                                             *   \endif
                                             */
    rwRENDERSTATESTENCILFUNCTION,           /**< \if xbox
                                             *      Comparison function for the stencil test
                                             *   \endif
                                             *   \if d3d8
                                             *      Comparison function for the stencil test
                                             *   \endif
                                             */
    rwRENDERSTATESTENCILFUNCTIONREF,        /**< \if xbox
                                             *      Integer reference value for the stencil test
                                             *   \endif
                                             *   \if d3d8
                                             *      Integer reference value for the stencil test
                                             *   \endif
                                             */
    rwRENDERSTATESTENCILFUNCTIONMASK,       /**< \if xbox
                                             *      Mask applied to the reference value and each stencil buffer 
                                             *      entry to determine the significant bits for the stencil test
                                             *   \endif
                                             *   \if d3d8
                                             *      Mask applied to the reference value and each stencil buffer 
                                             *      entry to determine the significant bits for the stencil test
                                             *   \endif
                                             */
    rwRENDERSTATESTENCILFUNCTIONWRITEMASK,  /**< \if xbox
                                             *      Write mask applied to values written into the stencil buffer
                                             *   \endif
                                             *   \if d3d8
                                             *      Write mask applied to values written into the stencil buffer
                                             *   \endif
                                             */

/* RWPUBLICEND */
#ifdef RW4
/* If this is defined, an alternate renderer table is used */
    rwRENDERSTATEUSERSHADERS,               /* Use the RenderWare 4.0 user shaders */
#endif /* RW4 */


    /* RWPUBLIC */
    rwRENDERSTATEFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwRenderState RwRenderState;


/**
 * \ingroup datatypes
 * RwShadeMode
 *  This type represents the options available for setting the
 * rwRENDERSTATESHADEMODE render state */
enum RwShadeMode
{
    rwSHADEMODENASHADEMODE = 0,     /**<Invalid shading mode */
    rwSHADEMODEFLAT,                /**<Flat shading */
    rwSHADEMODEGOURAUD,             /**<Gouraud shading */
    rwSHADEMODEFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwShadeMode RwShadeMode;


/**
 * \ingroup datatypes
 * RwTextureFilterMode
 *  This type represents the options available for texture
 * filtering (see API functions \ref RwTextureSetFilterMode and \ref RwRenderStateSet)*/
enum RwTextureFilterMode
{
    rwFILTERNAFILTERMODE = 0,       /**<Invalid filter mode */
    rwFILTERNEAREST,                /**<Point sampled */
    rwFILTERLINEAR,                 /**<Bilinear */
    rwFILTERMIPNEAREST,             /**<Point sampled per pixel mip map */
    rwFILTERMIPLINEAR,              /**<Bilinear per pixel mipmap */
    rwFILTERLINEARMIPNEAREST,       /**<MipMap interp point sampled */
    rwFILTERLINEARMIPLINEAR,        /**<Trilinear */
    rwTEXTUREFILTERMODEFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwTextureFilterMode RwTextureFilterMode;


/**
 * \ingroup datatypes
 * RwFogType
 *  This type represents the options available to the
 * rwRENDERSTATEFOGTYPE render state (see \ref RwRenderState);*/
enum RwFogType
{
    rwFOGTYPENAFOGTYPE = 0,     /**<Invalid fog type */
    rwFOGTYPELINEAR,            /**<Linear fog */
    rwFOGTYPEEXPONENTIAL,       /**<Exponential fog */
    rwFOGTYPEEXPONENTIAL2,      /**<Exponential^2 fog */
    rwFOGTYPEFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwFogType RwFogType;


/**
 * \ingroup datatypes
 * RwBlendFunction
 *  This type represents the options available
 * to the rwRENDERSTATESRCBLEND and rwRENDERSTATEDESTBLEND render states
 * (see \ref RwRenderState).  In the following description,
 * a subscript s refers to a source value while subscript d refers to a
 * destination value.*/
enum RwBlendFunction
{
    rwBLENDNABLEND = 0,     /**<Invalid blend mode */
    rwBLENDZERO,            /**<(0,    0,    0,    0   ) */
    rwBLENDONE,             /**<(1,    1,    1,    1   ) */
    rwBLENDSRCCOLOR,        /**<(Rs,   Gs,   Bs,   As  ) */
    rwBLENDINVSRCCOLOR,     /**<(1-Rs, 1-Gs, 1-Bs, 1-As) */
    rwBLENDSRCALPHA,        /**<(As,   As,   As,   As  ) */
    rwBLENDINVSRCALPHA,     /**<(1-As, 1-As, 1-As, 1-As) */
    rwBLENDDESTALPHA,       /**<(Ad,   Ad,   Ad,   Ad  ) */
    rwBLENDINVDESTALPHA,    /**<(1-Ad, 1-Ad, 1-Ad, 1-Ad) */
    rwBLENDDESTCOLOR,       /**<(Rd,   Gd,   Bd,   Ad  ) */
    rwBLENDINVDESTCOLOR,    /**<(1-Rd, 1-Gd, 1-Bd, 1-Ad) */
    rwBLENDSRCALPHASAT,     /**<(f,    f,    f,    1   )  f = min (As, 1-Ad) */
    rwBLENDFUNCTIONFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwBlendFunction RwBlendFunction;


/**
 * \ingroup datatypes
 * RwTextureAddressMode
 *  This type represents the options available for
 * applying textures to polygons (see API functions \ref RwTextureSetAddressing
 * and \ref RwRenderStateSet, and the \ref RwRenderState type) */
enum RwTextureAddressMode
{
    rwTEXTUREADDRESSNATEXTUREADDRESS = 0,   /**<Invalid addressing mode */
    rwTEXTUREADDRESSWRAP,                   /**<UV wraps (tiles) */
    rwTEXTUREADDRESSMIRROR,                 /**<Alternate UV is flipped */
    rwTEXTUREADDRESSCLAMP,                  /**<UV is clamped to 0-1 */
    rwTEXTUREADDRESSBORDER,                 /**<Border colour takes effect outside of 0-1 */
    rwTEXTUREADDRESSMODEFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwTextureAddressMode RwTextureAddressMode;

enum RwStencilOperation
{
    rwSTENCILOPERATIONNASTENCILOPERATION = 0,
    rwSTENCILOPERATIONKEEP,     /* Do not update the entry in the stencil buffer */
    rwSTENCILOPERATIONZERO,     /* Set the stencil-buffer entry to 0 */
    rwSTENCILOPERATIONREPLACE,  /* Replace the stencil-buffer entry with reference value */
    rwSTENCILOPERATIONINCRSAT,  /* Increment the stencil-buffer entry, clamping to the maximum value */
    rwSTENCILOPERATIONDECRSAT,  /* Decrement the stencil-buffer entry, clamping to zero */    
    rwSTENCILOPERATIONINVERT,   /* Invert the bits in the stencil-buffer entry */
    rwSTENCILOPERATIONINCR,     /* Increment the stencil-buffer entry, wrapping to zero if the new value exceeds the maximum value */
    rwSTENCILOPERATIONDECR,     /* Decrement the stencil-buffer entry, wrapping to the maximum value if the new value is less than zero */
    rwSTENCILOPERATIONFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwStencilOperation RwStencilOperation;

enum RwStencilFunction
{
    rwSTENCILFUNCTIONNASTENCILFUNCTION = 0,
    rwSTENCILFUNCTIONNEVER,         /* Always fail the test */
    rwSTENCILFUNCTIONLESS,          /* Accept the new pixel if its value is less than the value of the current pixel */
    rwSTENCILFUNCTIONEQUAL,         /* Accept the new pixel if its value equals the value of the current pixel */
    rwSTENCILFUNCTIONLESSEQUAL,     /* Accept the new pixel if its value is less than or equal to the value of the current pixel */
    rwSTENCILFUNCTIONGREATER,       /* Accept the new pixel if its value is greater than the value of the current pixel */
    rwSTENCILFUNCTIONNOTEQUAL,      /* Accept the new pixel if its value does not equal the value of the current pixel */
    rwSTENCILFUNCTIONGREATEREQUAL,  /* Accept the new pixel if its value is greater than or equal to the value of the current pixel */
    rwSTENCILFUNCTIONALWAYS,        /* Always pass the test */
    rwSTENCILFUNCTIONFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwStencilFunction RwStencilFunction;

/**
 * \ingroup datatypes
 * RwCullMode
 *  This type represents the options available for culling polygons during rendering.
 * and \ref RwRenderStateSet, and the \ref RwRenderState type) */
enum RwCullMode
{
    rwCULLMODENACULLMODE = 0,
    rwCULLMODECULLNONE,                /**< Both front and back-facing triangles are drawn. */
    rwCULLMODECULLBACK,                /**< Just front-facing triangles are drawn */
    rwCULLMODECULLFRONT,               /**< Just rear-facing triangles are drawn */

    rwCULLMODEFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwCullMode RwCullMode;

/**
 * \ingroup datatypes
 * RwPrimitiveType
 *  This type represents the different types of indexed
 * line and indexed triangle primitives that are available when rendering 2D
 * and 3D immediate mode objects (see API functions \ref RwIm2DRenderIndexedPrimitive,
 * \ref RwIm2DRenderPrimitive, \ref RwIm3DRenderIndexedPrimitive and \ref RwIm3DRenderPrimitive).
 * Indices are into a vertex list and must be defined in a counter-clockwise order
 * (as seen from the camera) to be visible.*/
enum RwPrimitiveType
{
    rwPRIMTYPENAPRIMTYPE = 0,   /**<Invalid primative type */
    rwPRIMTYPELINELIST = 1,     /**<Unconnected line segments, each line is specified by
                                 * both its start and end index, independently of other lines
                                 * (for example, 3 segments specified as 0-1, 2-3, 4-5) */
    rwPRIMTYPEPOLYLINE = 2,     /**<Connected line segments, each line's start index
                                 * (except the first) is specified by the index of the end of
                                 * the previous segment (for example, 3 segments specified as
                                 * 0-1, 1-2, 2-3) */
    rwPRIMTYPETRILIST = 3,      /**<Unconnected triangles: each triangle is specified by
                                 * three indices, independently of other triangles (for example,
                                 * 3 triangles specified as 0-1-2, 3-4-5, 6-7-8) */
    rwPRIMTYPETRISTRIP = 4,     /**<Connected triangles sharing an edge with, at most, one
                                 * other forming a series (for example, 3 triangles specified
                                 * as 0-2-1, 1-2-3-, 2-4-3) */
    rwPRIMTYPETRIFAN = 5 ,      /**<Connected triangles sharing an edge with, at most,
                                 * two others forming a fan (for example, 3 triangles specified
                                 * as 0-2-1, 0-3-2, 0-4-3) */
    rwPRIMTYPEPOINTLIST = 6,    /**<Points 1, 2, 3, etc. This is not
                                 * supported by the default RenderWare
                                 * immediate or retained-mode pipelines
                                 * (except on PlayStation 2), it is intended
                                 * for use by user-created pipelines */
    rwPRIMITIVETYPEFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RwPrimitiveType RwPrimitiveType;




/* RWPUBLICEND */

/****************************************************************************
 Global Types
 */

/* RWPUBLIC */
/****************************************************************************
 Function prototypes
 */

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

/* Expose Z buffer range */
extern RwReal RwIm2DGetNearScreenZ(void);
extern RwReal RwIm2DGetFarScreenZ(void);

extern RwBool RwRenderStateGet(RwRenderState state, void *value);
extern RwBool RwRenderStateSet(RwRenderState state, void *value);

extern RwBool RwIm2DRenderLine(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2);
extern RwBool RwIm2DRenderTriangle(RwIm2DVertex *vertices, RwInt32 numVertices,
                                   RwInt32 vert1, RwInt32 vert2, RwInt32 vert3 );
extern RwBool RwIm2DRenderPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices);
extern RwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices,
                                                             RwImVertexIndex *indices, RwInt32 numIndices);

#ifdef    __cplusplus
}
#endif                          /* __cplusplus */

/* RWPUBLICEND */

#endif /* RWIMMEDI_H */

