
/*
Tested with LINT
*/

/**************
TEXTURE.C
Ver 1.0
***************/
#include "GLD.h"
#include "GEO.h"
#include "TEX.h"
#include "gli_st.h"
#include "textu_st.h"
#include "texture.h"
#include <string.h>
#ifdef SGL2
#include <SGL2.h>
#endif
#include "GLI_interface.h"


unsigned long ulTotalUsedMemory;
unsigned long ulAgpUsedMemory;

static long GLI_gs_lMaxTmuAvailable; 

extern unsigned long GLI_gsCurrentMemoryChannel;
extern unsigned long gs_lRGBBitCount;
extern long gs_lTreeOfNamesNumberOfLastLetter;
extern long gs_lNumberOfTextureToCreate;
extern long gs_lLastIdxInDEFTableOfTextures;
extern long lNbTextureFormat;
extern long lCurrentTextureFormat;

//extern long gs_aDEFTableOfTextureMemoryChannels[ C_lMaxNumberOfTexture ];
extern unsigned char *gs_aCurrentTextures;
//extern GLI_tdstTexture *gs_aDEFTableOfTextureAlreadyRead [ C_lMaxNumberOfTexture ];
extern unsigned char g_ucGliModuleId;
//extern void *GLI_gs_p_ConvertBufferMipMapping;

short TEXTURETWIDDLED[1024L*1024L];

static unsigned long GLI_a256FastTwiddledTable[256];

long GLI_fnLinear2CasseTete(unsigned long lLinear , long lPitch)
{
    unsigned long lreturnvalue = 0;
    unsigned long CMPX = 1;
    while  (lLinear != 0)
    {
        if (lLinear & 128) lreturnvalue += CMPX<<3;
        if (lLinear & 64) lreturnvalue += lPitch<<3;
        if (lLinear & 32) lreturnvalue += CMPX<<2;
        if (lLinear & 16) lreturnvalue += lPitch<<2;
        if (lLinear & 8) lreturnvalue += CMPX<<1;
        if (lLinear & 4) lreturnvalue += lPitch<<1;
        if (lLinear & 2) lreturnvalue += CMPX;
        if (lLinear & 1) lreturnvalue += lPitch;
        CMPX<<=4;
        lPitch<<=4;
        lLinear >>= 8;
    }
    return lreturnvalue;
}

void GLI_InitTwiddlingTable(long largeur)
{
    long i;
    for (i = 0 ; i < 256 ; i++ )
        GLI_a256FastTwiddledTable[i] = GLI_fnLinear2CasseTete(i, largeur);
}

void GLI_fnSwitchTwiddled(short *p_Texture , long size )
{
    unsigned long xcounter, SizeXSize , SizeXSizeD8;
    short *Pdest ;
    unsigned long *GLI_a256FastTwiddledTableLocal;
    static long largeur = 0;
    short *p_TextureLocal,*p_DestLast;
    Pdest = TEXTURETWIDDLED;
    if (size != largeur)
    {
        GLI_InitTwiddlingTable(size);
        largeur = size;
    }
    SizeXSize = size * size;
    if (!(SizeXSize & 0xFF))
    {
        SizeXSizeD8 = SizeXSize >> 8;
        for (xcounter = 0 ; xcounter < SizeXSizeD8 ; xcounter ++ )
        {
            p_TextureLocal = p_Texture + (GLI_a256FastTwiddledTable[xcounter & 0xFF]<<4);
            p_TextureLocal += GLI_a256FastTwiddledTable[(xcounter>>8) & 0xFF]<<8;
            p_DestLast = Pdest + 256;
            GLI_a256FastTwiddledTableLocal = GLI_a256FastTwiddledTable;    
            while (Pdest < p_DestLast)
                *(Pdest++)= *(p_TextureLocal + *(GLI_a256FastTwiddledTableLocal++));
        }
    }
    else
    {
        xcounter = SizeXSize ;
        for ( xcounter = 0 ; xcounter < SizeXSize ; xcounter++ )
            *(Pdest++)= *(p_Texture + 
            GLI_a256FastTwiddledTable[xcounter & 0xFF] + 
            (GLI_a256FastTwiddledTable[(xcounter>>8) & 0xFF]<<4) +
            (GLI_a256FastTwiddledTable[(xcounter>>16) & 0xFF]<<8));
    }
    memcpy( p_Texture,  TEXTURETWIDDLED , SizeXSize<<1);
}

#ifdef SGL2
sgl_map_sizes GLI_GetSGL2EnumSize(unsigned long lSize)
{
    switch (lSize)
    {
    case 8:return (sgl_map_8x8);
    case 16:return (sgl_map_16x16);
    case 32:return (sgl_map_32x32);
    case 64:return (sgl_map_64x64);
    case 128:return (sgl_map_128x128);
    case 256:return (sgl_map_256x256);
    case 512:return (sgl_map_512x512);
    case 1024:return (sgl_map_1024x1024);
    }
    
}
#endif

#ifdef SGL2
void GLI_DRV_vDownLoadTextures(long bRestore, long _lTextureMode, BOOL bReloading )
{
    long lTextureCounter;
    GLI_tdstTexture *p_stTexture;
    sgl_mipmap_generation_options MipMapping;
    long AddValue;
    sgl_intermediate_map SGL2_IM;
    memset(&SGL2_IM , 0 , sizeof (sgl_intermediate_map));
    SGL2_IM . id[0]  = 'I';
    SGL2_IM . id[1]  = 'M';
    SGL2_IM . id[2]  = 'A';
    SGL2_IM . id[3]  = 'P';
    for (lTextureCounter = 0; lTextureCounter < GLI_C_lNBMaxOfTextures ; lTextureCounter ++)
        if (gs_aDEFTableOfTextureMemoryChannels[lTextureCounter] != GLI_TEXIsUnallocated )
        {
            p_stTexture = gs_aDEFTableOfTextureAlreadyRead[lTextureCounter];
            while (p_stTexture != NULL) 
            {
                p_stTexture -> bIsAvailable = 0;
                GLI_MDRV_xLoadTextureInTexelField(p_stTexture, GLI_gs_p_ConvertBufferMipMapping);
                AddValue = 0;
                if (p_stTexture ->lNumberOfLod)
                {
                    AddValue = sgl_map_mipmap_shift;
                    MipMapping = sgl_mipmap_generate_2x2;
                }
                else
                    MipMapping = sgl_mipmap_generate_none;
                if (p_stTexture -> lTextureCaps & GLI_C_lNZTexture)
                {
                    GLI_vInvertAlphaField(GLI_gs_p_ConvertBufferMipMapping , p_stTexture->lHeight * p_stTexture->lHeight);
                    SGL2_IM . pixels = GLI_gs_p_ConvertBufferMipMapping ;
                    SGL2_IM . y_dim = SGL2_IM . x_dim = p_stTexture->lHeight;
                    *(int *)&p_stTexture -> p_stSpecParam = 
                        sgl_create_texture( sgl_map_argb_1555 + AddValue, GLI_GetSGL2EnumSize(p_stTexture->lHeight), MipMapping, FALSE , &SGL2_IM , NULL);
                } else
                {
                    if ((p_stTexture -> lTextureCaps & GLI_C_lAlphaTexture) == 0)
                    {
                        SGL2_IM . pixels = GLI_gs_p_ConvertBufferMipMapping     ;
                        SGL2_IM . y_dim = SGL2_IM . x_dim = p_stTexture->lHeight;
                        *(int *)&p_stTexture -> p_stSpecParam= 
                            sgl_create_texture( sgl_map_rgb_565 + AddValue, GLI_GetSGL2EnumSize(p_stTexture->lHeight), MipMapping, FALSE , &SGL2_IM , NULL);
                    } else
                    {
                        GLI_vInvertAlphaField(GLI_gs_p_ConvertBufferMipMapping , p_stTexture->lHeight * p_stTexture->lHeight);
                        SGL2_IM . pixels = GLI_gs_p_ConvertBufferMipMapping ;
                        SGL2_IM . y_dim = SGL2_IM . x_dim = p_stTexture->lHeight;
                        *(int *)&p_stTexture -> p_stSpecParam= 
                            sgl_create_texture( sgl_map_argb_4444 + AddValue, GLI_GetSGL2EnumSize(p_stTexture->lHeight), MipMapping ,FALSE, &SGL2_IM , NULL);
                    } 
                }
                if (*(int *)&p_stTexture -> p_stSpecParam > 0)
                {
                    p_stTexture->bIsAvailable = 1 ;
                }
                p_stTexture = NULL;
            }
        }
}
#endif

/*
 ----------------------------------------------------------------------------------------
  Description   : get total memory size available for texture
 ----------------------------------------------------------------------------------------
 */
long GLI_DRV_lGetHardwareTotalTextureMemorySize(long _lTextureMode)
{
    return (6388608L);
}

//********************************************************************************************
// Name: GLI_DRV_lGetHardwareMaxTextureSize() 1.0
// OPTIMMIZED : No
//********************************************************************************************
long GLI_DRV_lGetHardwareMaxTextureSize(void)
{
    return (1024);
}

//********************************************************************************************
// Name: GLI_DRV_lIsHardwareAcceptNonSquaredTextures() 1.0
// OPTIMMIZED : No
//********************************************************************************************
long GLI_DRV_lIsHardwareAcceptNonSquaredTextures(void)
{
    return (0);
}

void GLI_DRV_vUnLoadTextures()
{
    long lTextureCounter;
    
    GLI_tdstTexture *p_stTexture;
    
    for ( lTextureCounter = 0 ; lTextureCounter < C_lMaxNumberOfTexture ;lTextureCounter ++)
    {
        if (gs_aDEFTableOfTextureMemoryChannels[lTextureCounter] != GLI_TEXIsUnallocated )
        {
            p_stTexture = gs_aDEFTableOfTextureAlreadyRead[lTextureCounter];
            if (p_stTexture != NULL)
            {
                if (p_stTexture->bIsAvailable)
                {
                    sgl_delete_texture(*(int *)&p_stTexture -> p_stSpecParam);
                    p_stTexture->bIsAvailable = 0;
                }
            }
        }
    }
}


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