/******************************************************************************************
FILE : DoMat Glide2
 
  Do render parameters settings for texture/material/fog
  Dispay black triangles for window smaller than screen
      
*******************************************************************************************/
 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include "Gli_st.h"
#include "GLI_Defn.h"
#include "polygon.h"
#include "mater_st.h"
#include "light_st.h"
#include "PvObj_st.h"
#include "Liste.h"
#include "watrplan.h"
#include "proj.h"
#include "vpt3D.h"
#include "camera.h"
#include "material.h"
#include "texture.h"
#include "TEX.h"
#include "light.h"
#include "GliBench.h"
#define __MSC__
#include <GLIDE.H>
#include "TextuDFX.h"
 
#include "DLLCom.h"
#include "PRF.h"
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
#ifdef __cplusplus
extern "C" 
{
#endif
 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
/*
 =======================================================================================
    Globals 
 =======================================================================================
 */
 
/*
 * render parameters
 */
static long             bIsWriteEnable = 1;
static ACP_tdxIndex     xSaveFogIsOn = 0;
static GrChipID_t       xSaveTmuNumber = -1;
static unsigned char    ucSaveCyclingMode[2] = {-1, -1};
static unsigned char    ucSaveFunction = -1;
static unsigned long    gs_ulDepthBufferTestEnabled = 0;
 
/*
 *  Fog table
 */
GrFog_t                 Gli_C_xFogTable[ GR_FOG_TABLE_SIZE ];
float                   GLI_ga_fFogDist[ GR_FOG_TABLE_SIZE ];
 
/*
 * Black triangles
 */
GrVertex                g_stBlackTriangle[16];
long                    g_lNumberOfBlackTriangles = 0;
 
/*
 =======================================================================================
    Special function for displaying black polygon
        it's for cinematic scene to hide non black for color
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : reinit list of black triangles
 ----------------------------------------------------------------------------------------
 */
void GLI_DRV_vNoBlackPolygon()
{
    g_lNumberOfBlackTriangles = 0;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Add a black triangles to list
  Assume that list is large enough (no test)
 ----------------------------------------------------------------------------------------
 */
void GLI_DRV_vAddBlackPolygon( long _lLeft, long _lTop, long _lRight, long _lBottom )
{
    GrVertex *p_stVertex;
 
    p_stVertex = g_stBlackTriangle + g_lNumberOfBlackTriangles;
    memset( p_stVertex, 0, 4 * sizeof( GrVertex ) );
    g_lNumberOfBlackTriangles += 4;
 
    p_stVertex->x   = (float) _lLeft;
    p_stVertex->y   = (float) _lBottom;
    p_stVertex->oow = .8f;
 
    p_stVertex++;
    p_stVertex->x   = (float) _lLeft;
    p_stVertex->y   = (float) _lTop;
    p_stVertex->oow = .8f;
 
    p_stVertex++;
    p_stVertex->x   = (float) _lRight;
    p_stVertex->y   = (float) _lTop;
    p_stVertex->oow = .8f;
 
    p_stVertex++;
    p_stVertex->x   = (float) _lRight;
    p_stVertex->y   = (float) _lBottom;
    p_stVertex->oow = .8f;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Draw black triangles
 ----------------------------------------------------------------------------------------
 */
void GLI_vSendBlackPolygon()
{
    GrVertex *p_stVertex, *p_stLastVertex;
 
    if (g_lNumberOfBlackTriangles == 0)
        return;
 
    p_stVertex = g_stBlackTriangle;
    p_stLastVertex = p_stVertex + g_lNumberOfBlackTriangles;
 
    grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_ONE,GR_COMBINE_LOCAL_ITERATED,GR_COMBINE_OTHER_ITERATED,FXFALSE);/*  */
    grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
    guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
    grFogMode( GR_FOG_DISABLE);
    xSaveFogIsOn = 0;

 
    for ( ; p_stVertex < p_stLastVertex; p_stVertex += 4)
    {
        grDrawTriangle( p_stVertex, p_stVertex + 1, p_stVertex + 2 );
        grDrawTriangle( p_stVertex + 2, p_stVertex + 3, p_stVertex );
    }
}
 
/*
 =======================================================================================
    Function for Fog
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Set render parameter for given fog parameters
 ----------------------------------------------------------------------------------------
 */
void GLI_vSetFogParams( tdstFogParams *_p_stFogParams )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    float           *p_fFogDist, *p_fLast;
    long	        GlideColor;
    float	        xCoefOfCalculation;
    GrFog_t         *p_xFog;
    unsigned char   ucFogDensityStart, ucFogDensityEnd;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    xCoefOfCalculation = _p_stFogParams->xDepthEnd - _p_stFogParams->xDepthStart;
    if ( xCoefOfCalculation )
        xCoefOfCalculation = ( _p_stFogParams->xBlendEnd - _p_stFogParams->xBlendStart) / xCoefOfCalculation;
 
    p_fFogDist  = GLI_ga_fFogDist;
    p_fLast     = p_fFogDist + GR_FOG_TABLE_SIZE;
    p_xFog      = Gli_C_xFogTable;
 
 
    ucFogDensityStart   = (unsigned char) MTH_M_xRealToLong(_p_stFogParams->xBlendStart);
    ucFogDensityEnd     = (unsigned char) MTH_M_xRealToLong(_p_stFogParams->xBlendEnd);
        
    while ( (p_fFogDist < p_fLast) && (*p_fFogDist < _p_stFogParams->xDepthStart) )
    {
        *p_xFog++ = ucFogDensityStart;
        p_fFogDist++;
    }
 
    while ( (p_fFogDist < p_fLast) && (*p_fFogDist < _p_stFogParams->xDepthEnd) )
    {
        *p_xFog++ = (unsigned char)MTH_M_xRealToLong((xCoefOfCalculation * (*p_fFogDist++ - _p_stFogParams->xDepthStart)) + _p_stFogParams->xBlendStart);
    }
 
    while ( (p_fFogDist < p_fLast) && (*p_fFogDist < _p_stFogParams->xInfinite) )
    {
        *p_xFog++ = ucFogDensityEnd;
        p_fFogDist++;
    }
 
    while ( p_fFogDist < p_fLast ) 
    {
        *p_xFog++ = 255;
        p_fFogDist++;
    }
 
    grFogTable( Gli_C_xFogTable );
    GlideColor = (long)(_p_stFogParams->stColor.xR * 255.f) +((long)(_p_stFogParams->stColor.xG * 255.f)<<8) +((long)(_p_stFogParams->stColor.xB * 255.f)<<16) ;
    grFogColorValue(GlideColor);
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : compute fog effect on vertex color (nothing to do for Glide2)
 ----------------------------------------------------------------------------------------
 */
void GLI_DRV_vComputeFogEffect(GLI_tdstInternalGlobalValuesFor3dEngine *p_stBG )
{
}
 
/*
 =======================================================================================
    ZBuffer function
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : To enable write to ZBuffer
 ----------------------------------------------------------------------------------------
 */
static void GLI_fn_vEnableWriteToZBuffer()
{
    if (bIsWriteEnable) 
        return;
    grDepthMask(FXTRUE);
    bIsWriteEnable = 1;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : To disable write to ZBuffer
 ----------------------------------------------------------------------------------------
 */
static void GLI_fn_vDisableWriteToZBuffer()
{
    if (!bIsWriteEnable) 
        return;
    grDepthMask(FXFALSE);
    bIsWriteEnable = 0;
}


/*
 ----------------------------------------------------------------------------------------
  Description   : To manage use of ZBuffer
 ----------------------------------------------------------------------------------------
 */

void GLI_DRV_vEnableDepthTest()
{
    if( gs_ulDepthBufferTestEnabled )
        return;

    grDepthBufferFunction( GR_CMP_LESS );
    gs_ulDepthBufferTestEnabled = 1;
}

void GLI_DRV_vDisableDepthTest()
{
    if( ! gs_ulDepthBufferTestEnabled )
        return;

    grDepthBufferFunction( GR_CMP_ALWAYS );
    gs_ulDepthBufferTestEnabled = 0;
}
 
/*
 =======================================================================================
    Main render parameter setting functions
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Macro to set chromakey
         CB : La valeur de chromakey doit etre égale à : 5 bits de poids fort, plus les 3 bits de poids fort copiés dans les bits de poids faible.... !!!
         VL : sauf pour la composante G : 6 bit de poids fort + 2 bit de poids fort copiés dans les bits de poids faible !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 ----------------------------------------------------------------------------------------
 */
#define M_vChromakey()\
    if (p_stGlobaleMT -> p_stCurrentTexture -> lTextureCaps & GLI_C_lNZTexture)\
    {\
        unsigned long ulChromakey;\
		grChromakeyMode( GR_CHROMAKEY_ENABLE );\
        ulChromakey = (p_stGlobaleMT->p_stCurrentTexture->lChromakeyColorRGBA & 0x00F800F8) | ((p_stGlobaleMT->p_stCurrentTexture->lChromakeyColorRGBA & 0x00E000E0) >> 5);\
        ulChromakey|= (p_stGlobaleMT->p_stCurrentTexture->lChromakeyColorRGBA & 0x0000FC00) | ((p_stGlobaleMT->p_stCurrentTexture->lChromakeyColorRGBA & 0x0000C000) >> 6);\
        grChromakeyValue( ulChromakey );\
    }\
    else\
    {\
        grChromakeyMode( GR_CHROMAKEY_DISABLE );\
    }
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Macro to change fog rendering
 ----------------------------------------------------------------------------------------
 */
#define M_vFog()\
    if (GLI_BIG_GLOBALS->xFogIsOn == 1)\
    {\
        if ( GLI_BIG_GLOBALS->p_stLastComputedFog != GLI_BIG_GLOBALS->p_stActiveFog )\
        {\
            GLI_vSetFogParams( GLI_BIG_GLOBALS->p_stActiveFog );\
            GLI_BIG_GLOBALS->p_stLastComputedFog = GLI_BIG_GLOBALS->p_stActiveFog;\
        }\
        if (xSaveFogIsOn != 1)\
        {\
            grFogMode( GR_FOG_WITH_TABLE);\
            xSaveFogIsOn = 1;\
        }\
    }\
    else if (GLI_BIG_GLOBALS->xFogIsOn == 2)\
    {\
        if( xSaveFogIsOn != 2 ) \
        { \
            grFogMode( GR_FOG_WITH_ITERATED_ALPHA ); \
			xSaveFogIsOn = 2; \
        } \
    }\
    else if (xSaveFogIsOn)\
    {\
        grFogMode( GR_FOG_DISABLE);\
        xSaveFogIsOn = 0;\
    }
 
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Set init parameter as none set
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_vInitRenderParameters( void )
{
    bIsWriteEnable = 1;
    xSaveFogIsOn = 0;
    xSaveTmuNumber = -1;
    ucSaveCyclingMode[0] = ucSaveCyclingMode[1] = -1;
    ucSaveFunction = -1;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : set render parameters that will work for all faces which are not 
                  transparent
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_vSetRenderParametersBeforeOpaqueFace( void ) {
  grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
  grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_ONE,GR_COMBINE_LOCAL_NONE,GR_COMBINE_OTHER_TEXTURE,FXFALSE);
  guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
  grAlphaTestFunction( GR_CMP_ALWAYS );
  grAlphaTestReferenceValue( 0xC0 );
  ucSaveFunction = 4;
    
  GLI_fn_vEnableWriteToZBuffer();
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : called before the rendering of any triangle
 ----------------------------------------------------------------------------------------
 */
BOOL GLI_DRV_bBeginScene()
{
    GLI_BIG_GLOBALS->GLD_RenderingCounter = *GLD_p_lRenderingCounter;
    GLI_vSendBlackPolygon();
 
    grAlphaTestFunction( GR_CMP_LESS );
    grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
    grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_ONE,GR_COMBINE_LOCAL_NONE,GR_COMBINE_OTHER_TEXTURE,FXFALSE);
    guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
    grAlphaTestFunction( GR_CMP_ALWAYS );
    grAlphaTestReferenceValue( 0xC0 );
 
    ucSaveFunction = 4;
 
    return TRUE;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : called after the rendering of all triangles
 ----------------------------------------------------------------------------------------
 */
BOOL GLI_DRV_bEndScene()
{
    return TRUE;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Called for all object before drawn. 
                  Set some general parameters and set render parameter for opaque texture only
 ----------------------------------------------------------------------------------------
 */
void GLI_DRV_vDoOpaqueTextureSelection(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    GLI_tdstTextureDFX      *p_stSpecParam;
    BOOL                    bTexture;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 /*
    if (*GLD_p_lRenderingCounter != p_stGlobaleMT->GLD_RenderingCounter)
    {
        p_stGlobaleMT->GLD_RenderingCounter = *GLD_p_lRenderingCounter;
        GLI_vSendBlackPolygon();
        
        grAlphaTestFunction( GR_CMP_LESS );
        grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
        grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_ONE,GR_COMBINE_LOCAL_NONE,GR_COMBINE_OTHER_TEXTURE,FXFALSE);
        guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
        grAlphaTestFunction( GR_CMP_ALWAYS );
        grAlphaTestReferenceValue( 0xC0 );
        ucSaveFunction = 4;
    }
 */
	if (p_stGlobaleMT -> lCurrentDrawMask & GLI_C_lIsWriteZBuffer)
        GLI_fn_vEnableWriteToZBuffer();
    else
        GLI_fn_vDisableWriteToZBuffer();
//	GLI_fn_vEnableWriteToZBuffer();

    if ( p_stGlobaleMT->lCurrentDrawMask & GLI_C_lIsEnableZSorting )
        GLI_DRV_vEnableDepthTest();
    else
        GLI_DRV_vDisableDepthTest();

 
    bTexture = (p_stGlobaleMT->p_stCurrentTexture != NULL) && (p_stGlobaleMT->p_stCurrentTexture->bIsAvailable);
 
    if (bTexture)
    {
        p_stSpecParam = p_stGlobaleMT -> p_stCurrentTexture -> p_stSpecParam;
		GLI_GLIDE1_xTmuNumber = p_stSpecParam->xTmuNumber;
        /*
         * UV multiplier
         */
        p_stGlobaleMT -> fMulU = p_stSpecParam -> lMultiplyHeight;
        p_stGlobaleMT -> fMulV = p_stSpecParam -> lMultiplyWidth;
    }
 
    /*
     * test if triangle will be transparent if so do not set render parameters
     */
	if (GLI_BIG_GLOBALS->lAMirrorIsDetected)
		GLI_BIG_GLOBALS->lAMirrorIsDetected = 3;
 
 
    if ( 
            ( !(GLI_BIG_GLOBALS->lAMirrorIsDetected) && bTexture && (p_stGlobaleMT -> p_stCurrentTexture -> lTextureCaps & (GLI_C_lAlphaTexture | GLI_C_lNZFilteredTexture | GLI_C_lAddTransparencyTexture) ) )
         || (!(p_stGlobaleMT -> lCurrentDrawMask & GLI_C_lIsNotGrided) && (p_stGlobaleMT->xGlobalAlpha < 0.98f))
       )
    {
        p_stGlobaleMT -> lClippingModeMask |= GLI_C_TrianglesMustBeSorted;
        return;
    }
 
    p_stGlobaleMT -> lClippingModeMask &= 0xffffffff - GLI_C_TrianglesMustBeSorted;
 
    /*
     * fog
     */
    M_vFog();
    
    {
        if ( bTexture )
        {
            if (p_stGlobaleMT -> p_stCurrentTexture -> lTextureCaps & GLI_C_lAlphaTest)
            {
                if (ucSaveFunction != 5)
                {
					if ( ucSaveFunction == 2 )
						GLI_fn_vSetRenderParametersBeforeOpaqueFace() ;				
                    grAlphaTestFunction( GR_CMP_GEQUAL );
                    guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
                    ucSaveFunction = 5;
                }
            }
            else if (GLI_BIG_GLOBALS->lAMirrorIsDetected & 2)
			{
				grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,GR_BLEND_ONE_MINUS_SRC_ALPHA,GR_BLEND_ONE ,GR_BLEND_ZERO );
				guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
				grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_LOCAL,GR_COMBINE_LOCAL_ITERATED,GR_COMBINE_OTHER_TEXTURE,FXFALSE);
				ucSaveFunction = 2;
			}
			else 
            {
			    if (ucSaveFunction != 4)
                {
					if ( ucSaveFunction == 2 )
						GLI_fn_vSetRenderParametersBeforeOpaqueFace() ;				
                    grAlphaTestFunction( GR_CMP_ALWAYS );
                    guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
                    ucSaveFunction = 4;
                }
            }
 
            /*
             * Chromakey
             */
            M_vChromakey();
            
            /*
             * uv cycling mode
             */
            if ( p_stGlobaleMT -> p_stCurrentTexture -> ucCylingMode != ucSaveCyclingMode[ GLI_GLIDE1_xTmuNumber ] )
            {
                switch ( ucSaveCyclingMode[ GLI_GLIDE1_xTmuNumber ] = p_stGlobaleMT -> p_stCurrentTexture -> ucCylingMode )
                {
                    case 0:
                        /*NO CYCLING*/
                        grTexClampMode(GLI_GLIDE1_xTmuNumber, GR_TEXTURECLAMP_CLAMP,GR_TEXTURECLAMP_CLAMP);
                        break;
                    case GLI_C_lCylingUV:
                        /*CYCLING*/
                        grTexClampMode(GLI_GLIDE1_xTmuNumber, GR_TEXTURECLAMP_WRAP,GR_TEXTURECLAMP_WRAP);
                        break;
                    case GLI_C_lCylingU:
                        /*CYCLING V*/
                        grTexClampMode(GLI_GLIDE1_xTmuNumber, GR_TEXTURECLAMP_CLAMP,GR_TEXTURECLAMP_WRAP);
                        break;
                    case GLI_C_lCylingV:
                        /*CYCLING U*/
                        grTexClampMode(GLI_GLIDE1_xTmuNumber, GR_TEXTURECLAMP_WRAP , GR_TEXTURECLAMP_CLAMP);
                        break;
                }
            }
                              
            /*
             * texture Tmu 
             */
            if (GLI_GLIDE1_xTmuNumber != xSaveTmuNumber)
            {
                grTexCombineFunction((GLI_GLIDE1_xTmuNumber+1) & 0x1, GR_TEXTURECOMBINE_OTHER);
                grTexCombineFunction(GLI_GLIDE1_xTmuNumber, GR_TEXTURECOMBINE_DECAL);
                xSaveTmuNumber = GLI_GLIDE1_xTmuNumber;
            }
 
            grTexSource( GLI_GLIDE1_xTmuNumber, p_stSpecParam -> xStartAddress, p_stSpecParam -> xEvenOdd, &p_stSpecParam -> stInfoBitmapGlide);
 
            if (p_stGlobaleMT->p_stCurrentTexture->lTextureCaps  & GLI_C_lPaletteTexture)
            {
                grTexDownloadTable( GLI_GLIDE1_xTmuNumber, GR_TEXTABLE_PALETTE, p_stGlobaleMT->p_stCurrentTexture->p_vColorTable );
            }
        } 
		else /* gouraud */
        {
            if (ucSaveFunction != 0)
            {
                grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
                grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_ONE,GR_COMBINE_LOCAL_NONE,GR_COMBINE_OTHER_TEXTURE,FXFALSE);
                grAlphaTestFunction( GR_CMP_ALWAYS );
                guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
                ucSaveFunction = 0;
            }
        }
    }
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : set render parameters that will work for all transparency faces
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_vSetRenderParametersBeforeTransparencyFace( void )
{
	grAlphaTestFunction( GR_CMP_ALWAYS );
	GLI_fn_vDisableWriteToZBuffer();
}
 
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : set render parameters for transparent triangles
 ----------------------------------------------------------------------------------------
 */
void GLI_vDoTransparentTextureSelection(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT)
{
    GLI_tdstTextureDFX      *p_stSpecParam;
 
    /*grAlphaTestFunction( GR_CMP_ALWAYS );*/
 
    /*
     * write to Z buffer ?
     */
    /*
	if (p_stGlobaleMT -> lCurrentDrawMask & GLI_C_lIsWriteZBuffer)
        GLI_fn_vEnableWriteToZBuffer();
    else
        GLI_fn_vDisableWriteToZBuffer();
		*/

    /* Test Z-Buffer ? */
    if ( p_stGlobaleMT->lCurrentDrawMask & GLI_C_lIsEnableZSorting )
        GLI_DRV_vEnableDepthTest();
    else
        GLI_DRV_vDisableDepthTest();

    /*
     * fog
     */
    M_vFog();
    
    /*
     * mirror
     */
    if (p_stGlobaleMT->lAMirrorIsDetected & 2)
    {
        if ((!(p_stGlobaleMT -> lCurrentDrawMask & GLI_C_lIsNotGrided)) && (p_stGlobaleMT->xGlobalAlpha < 0.98f))
        {
        } 
        else 
        {
        }
    }
    /*
     * not a mirror
     */
    else
    {
        if ((p_stGlobaleMT -> p_stCurrentTexture != NULL) && (p_stGlobaleMT -> p_stCurrentTexture ->  bIsAvailable))
        {
            p_stSpecParam = p_stGlobaleMT -> p_stCurrentTexture -> p_stSpecParam;
			GLI_GLIDE1_xTmuNumber = p_stSpecParam->xTmuNumber;
 
 
            if (p_stGlobaleMT -> p_stCurrentTexture -> lTextureCaps & (GLI_C_lAlphaTest | GLI_C_lAlphaTexture | GLI_C_lNZFilteredTexture | GLI_C_lAddTransparencyTexture) )
            {
                if (p_stGlobaleMT -> p_stCurrentTexture -> lTextureCaps & GLI_C_lAddTransparencyTexture)
                {
                    /* Trans ADD*/
                    if (ucSaveFunction != 1)
                    {
                        grAlphaBlendFunction( GR_BLEND_ONE,GR_BLEND_ONE,GR_BLEND_ZERO ,GR_BLEND_ZERO );
                        guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ALPHA);
                        grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_LOCAL,GR_COMBINE_LOCAL_ITERATED,GR_COMBINE_OTHER_TEXTURE,FXFALSE);
                        ucSaveFunction = 1;
                    }
 
                    /* No fog With This;*/
                    if (xSaveFogIsOn)
                    {
                        grFogMode( GR_FOG_DISABLE);
                        xSaveFogIsOn = 0;
                    }
                } 
				/*VL AAA texture*/
				/*
				else if (p_stGlobaleMT->p_stCurrentTexture->lTextureCaps & GLI_C_lAAATexture )
				{
					if (ucSaveFunction != 6)
					{
						grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,GR_BLEND_ONE_MINUS_SRC_ALPHA,GR_BLEND_ONE ,GR_BLEND_ZERO );
					    grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE );
						grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT, FXFALSE );
						
						ucSaveFunction = 6;
					}
					//test
					{ 
						unsigned long ulColor;
 
						ulColor  = (long) (p_stGlobaleMT->hCurrentMaterial->stAmbient.xR * 255) & 0xFF;
						ulColor |= ((long) (p_stGlobaleMT->hCurrentMaterial->stAmbient.xG * 255) & 0xFF) << 8;
						ulColor |= ((long) (p_stGlobaleMT->hCurrentMaterial->stAmbient.xB * 255) & 0xFF) << 16;
						grConstantColorValue( ulColor );
					}
				}
				*/
				else if (ucSaveFunction != 2)
				{
                    /* Trans ALPHA*/
                    grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,GR_BLEND_ONE_MINUS_SRC_ALPHA,GR_BLEND_ONE ,GR_BLEND_ZERO );
					guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
                    grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_LOCAL,GR_COMBINE_LOCAL_ITERATED,GR_COMBINE_OTHER_TEXTURE,FXFALSE);
 
                    ucSaveFunction = 2;
                } 
            } 
            else /*if ((!(p_stGlobaleMT -> lCurrentDrawMask & GLI_C_lIsNotGrided)) && (xGlobaLAlpha < 0.98f))*/
            {
                /* Trans ALPHA ITERATED*/
                if (ucSaveFunction != 3)
                {
                    grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,GR_BLEND_ONE_MINUS_SRC_ALPHA,GR_BLEND_ONE,GR_BLEND_ZERO );
                    grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_ONE,GR_COMBINE_LOCAL_ITERATED,GR_COMBINE_OTHER_ITERATED,FXFALSE);/*  */
                    guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
 
                    ucSaveFunction = 3;
                }
            } 
 
            /*
             * Chromakey
             */
            M_vChromakey();
            
            /*
             * uv cycling mode
             */
            if ( p_stGlobaleMT -> p_stCurrentTexture -> ucCylingMode != ucSaveCyclingMode[ GLI_GLIDE1_xTmuNumber ] )
            {
                switch ( ucSaveCyclingMode[ GLI_GLIDE1_xTmuNumber ] = p_stGlobaleMT -> p_stCurrentTexture -> ucCylingMode )
                {
                    case 0:
                        /*NO CYCLING*/
                        grTexClampMode(GLI_GLIDE1_xTmuNumber, GR_TEXTURECLAMP_CLAMP,GR_TEXTURECLAMP_CLAMP);
                        break;
                    case GLI_C_lCylingUV:
                        /*CYCLING*/
                        grTexClampMode(GLI_GLIDE1_xTmuNumber, GR_TEXTURECLAMP_WRAP,GR_TEXTURECLAMP_WRAP);
                        break;
                    case GLI_C_lCylingU:
                        /*CYCLING V*/
                        grTexClampMode(GLI_GLIDE1_xTmuNumber, GR_TEXTURECLAMP_CLAMP,GR_TEXTURECLAMP_WRAP);
                        break;
                    case GLI_C_lCylingV:
                        /*CYCLING U*/
                        grTexClampMode(GLI_GLIDE1_xTmuNumber, GR_TEXTURECLAMP_WRAP , GR_TEXTURECLAMP_CLAMP);
                        break;
                }
            }
                              
            /*
             * texture Tmu 
             */
            if (GLI_GLIDE1_xTmuNumber != xSaveTmuNumber)
            {
                grTexCombineFunction((GLI_GLIDE1_xTmuNumber + 1) & 0x1, GR_TEXTURECOMBINE_OTHER);
                grTexCombineFunction(GLI_GLIDE1_xTmuNumber, GR_TEXTURECOMBINE_DECAL);
                xSaveTmuNumber = GLI_GLIDE1_xTmuNumber;
            }
 
            grTexSource( GLI_GLIDE1_xTmuNumber, p_stSpecParam -> xStartAddress, p_stSpecParam -> xEvenOdd, &p_stSpecParam -> stInfoBitmapGlide);
        } 
		else
        {
            /* GOURAUD*/
            if (((p_stGlobaleMT -> lCurrentDrawMask & GLI_C_lIsNotGrided) == 0) && (p_stGlobaleMT->xGlobalAlpha < 0.98f) )
            {
                /* alpha iterated transparency*/
                grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,GR_BLEND_ONE_MINUS_SRC_ALPHA,GR_BLEND_ONE,GR_BLEND_ZERO );
                grAlphaCombine(GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA,GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE,FXFALSE);/*  */
                guAlphaSource(GR_ALPHASOURCE_ITERATED_ALPHA);
                p_stGlobaleMT -> lClippingModeMask |= GLI_C_TrianglesMustBeSorted;
            }
            else 
            {
                grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_ONE,GR_COMBINE_LOCAL_ITERATED,GR_COMBINE_OTHER_ITERATED,FXFALSE);/*  */
                grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
            }
            guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
 
            ucSaveFunction = 0;
        }
    }
}
 
/*
 =======================================================================================
    Write bitmap into backbuffer 
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : write bitmap part into backbuffer
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_vWriteRegion3DFX(long X, long Y, long l, long h, unsigned char *p_ucSrc, long SrcPitch , GrLfbInfo_t *p_info)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    long lPitch;  
    long *p_sourceptr , *p_sourceptrLast , *p_destptr ,lYCounterLocal;
    short *p_Src;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    
    p_Src = (unsigned short *)p_ucSrc;
    lPitch = p_info->strideInBytes/4;
    
    for (lYCounterLocal = 0; lYCounterLocal < h ; lYCounterLocal++)
    {
        p_destptr = ((unsigned long *)p_info->lfbPtr) + (X>>1) + lPitch * (Y + lYCounterLocal);
        p_sourceptr  = ((unsigned long *)p_Src + lYCounterLocal * (SrcPitch >>2)) ;
        p_sourceptrLast = p_sourceptr  + (l>>1);
        for (;p_sourceptr < p_sourceptrLast ;p_sourceptr ++,p_destptr ++)
            *p_destptr = *p_sourceptr ;
    }
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Write a 16 bit bitmap in the back buffer
  _p_vSourceBuffer    -> bitmap
  _lWidth, _lHeight   -> dimension of bitmap
  _lDestX, _lDestY    -> where the bitmap have to be copied in the backbuffer
 ----------------------------------------------------------------------------------------
 */
void GLI_DRV_vWrite16bBitmapToBackBuffer( void *_p_vSourceBuffer, long _lWidth, long _lHeight, long _lDestLeft, long _lDestTop, long _lDestRight, long _lDestBottom )
{
    GrLfbInfo_t     info;
    unsigned short  *puw_Tgt, *puw_Src;
 
    info.size = sizeof( GrLfbInfo_t );
    if ( !grLfbLock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER, GR_LFBWRITEMODE_565 , GR_ORIGIN_UPPER_LEFT, FXFALSE , &info) )
      return;
 
    puw_Tgt = (unsigned short *) info.lfbPtr;
    puw_Tgt += (info.strideInBytes>> 1) * _lDestTop + _lDestLeft;
    puw_Src = (unsigned short *) _p_vSourceBuffer;

    GLD_MDRV_vBlitStretched16b( _lDestRight - _lDestLeft + 1, _lDestBottom - _lDestTop + 1, puw_Tgt, info.strideInBytes >> 1, _lWidth, _lHeight, puw_Src );
 
    grLfbUnlock( GR_LFB_WRITE_ONLY , GR_BUFFER_BACKBUFFER);
}
 
 
#ifdef __cplusplus
} /*extern "C"*/
#endif
