/*
 =======================================================================================
  Name        : TexBench.c
  Author      : vincent lhullier            Date :25/11/98
  Description : Bench function for texture
 =======================================================================================
 */
 
#include "texbench.h"
 
#ifdef BENCH_TEXTURE
 
#include "gli_st.h"
#include "GLI_Defn.h"
#include "light_st.h"
#include "PvObj_st.h"
#include "texture.h"
#include "TEX.h"
#include "texbench.h"
#include "texarray.h"

/*
 =======================================================================================
    Structure and timer functions
 =======================================================================================
 */
typedef struct TEXBENCH_st_Timer_
{
	u_long		ulLow;
	u_long		ulHigh;
} TEXBENCH_st_Timer;

#define RDTSC   __asm _emit 0x0F  __asm _emit 0x31
 
void TEXBENCH_fnv_ReadPentiumCounter( TEXBENCH_st_Timer *p_stTimerCount)
{
    __asm
    {
        RDTSC
        mov  ebx,dword ptr p_stTimerCount
        mov  [ebx],eax
        mov  [ebx+4],edx
    }
}


/*
 ----------------------------------------------------------------------------------------
  Description   : substract two timer
  tr                  -> result = t1 - t2 (t1 > t2)
 ----------------------------------------------------------------------------------------
 */
void TEXBENCH_fnv_Diff( TEXBENCH_st_Timer *tr, TEXBENCH_st_Timer *t1, TEXBENCH_st_Timer *t2 )
{
    tr->ulHigh = t1->ulHigh - t2->ulHigh;
    if (t1->ulLow >= t2->ulLow )
    {
        tr->ulLow = t1->ulLow - t2->ulLow;
    }
    else
    {
        tr->ulHigh--;
        tr->ulLow = 0xFFFFFFFF - (t2->ulLow - t1->ulLow - 1);
    }
}

/*
 =======================================================================================
    Globals
 =======================================================================================
 */
 
#define TEXBENCH_C_cComputedSize		0
#define TEXBENCH_C_cRealSize			1
 
#define TEXBENCH_C_cSizeLogFileName		"TextureSize"			
/*
 * array of texture size
 */
long	g_a_lTextureSize[2][ GLI_C_lNBMaxOfTextures ];

/*
 * Timer
 */
TEXBENCH_st_Timer   TEXBENCH_gast_Timer[ 16 ];
TEXBENCH_st_Timer   TEXBENCH_gaast_TextureTimer[ 8 ][ GLI_C_lNBMaxOfTextures ];
 
/*
 =======================================================================================
    Functions
 =======================================================================================
 */

/*
 ----------------------------------------------------------------------------------------
  Description   : Init
 ----------------------------------------------------------------------------------------
 */
void TEXBENCH_fn_vSetTime( char _cFor )
{
    TEXBENCH_fnv_ReadPentiumCounter( &TEXBENCH_gast_Timer[ _cFor ] );
}

/*
 ----------------------------------------------------------------------------------------
  Description   : Init
 ----------------------------------------------------------------------------------------
 */
void TEXBENCH_fn_vInitTextureSize( void )
{
	memset( g_a_lTextureSize, 0, sizeof (g_a_lTextureSize) );
    memset( TEXBENCH_gast_Timer, 0, sizeof (TEXBENCH_gast_Timer) );
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Set size of a texture given by it's index
 ----------------------------------------------------------------------------------------
 */
void TEXBENCH_fn_vSetTextureSizeWithIndex( long _lTextureIndex, char _cSizeType, long _lSize )
{
	g_a_lTextureSize[ _cSizeType ][ _lTextureIndex ] = _lSize;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Set size of a texture given by data pointer
 ----------------------------------------------------------------------------------------
 */
void TEXBENCH_fn_vSetTextureSize( GLI_tdstTexture *_p_stTexture, char _cSizeType, long _lSize )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	long lTexture;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

    /*
     * special for timer set calling from DLL
     */
    if (_p_stTexture == NULL)
    {
        TEXBENCH_fnv_ReadPentiumCounter( &TEXBENCH_gaast_TextureTimer[ _cSizeType ][ _lSize ] );
        return;
    }
 
	for (lTexture = 0; lTexture < GLI_C_lNBMaxOfTextures; lTexture++)
	{
		if (_p_stTexture == gs_aDEFTableOfTextureAlreadyRead[ lTexture ] )
		{
			TEXBENCH_fn_vSetTextureSizeWithIndex( lTexture, _cSizeType, _lSize );
			return;
		}
	}
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : write info in log file
 ----------------------------------------------------------------------------------------
 */
void TEXBENCH_fn_vWriteSizeInFile( void )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char				szFileName[ _MAX_PATH ];
	long				lFileIndex = 0;
	FILE				*hpFile;
	long				lTexture;
	GLI_tdstTexture		**pp_stTexture;
	long				a_lTotal[2];
	long				lDiff, lTotalDiff;
	long				lBitmapSize, lSize, lLod;
    long                lNumberOfStructureAllocated;
    BOOL                bTwice;
    long                lStringSize = 0;
    TEXBENCH_st_Timer   stDiff;
    unsigned long       a_ulTimeTotal[ 7 ];
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	while(1)
	{
        CreateDirectory( "log", NULL );
		sprintf( szFileName, "log\\%s%03d.log", TEXBENCH_C_cSizeLogFileName, lFileIndex );
		if (_access( szFileName, 0 ) != 0)
			break;
		lFileIndex++;
		if (lFileIndex == 1000)
			return;
	}
 
	hpFile = fopen( szFileName, "wt" );
	fprintf(hpFile, "Texture size result\n\n" );
 
	pp_stTexture = gs_aDEFTableOfTextureAlreadyRead;
	lTotalDiff = a_lTotal[0] = a_lTotal[1] = 0;
 
    lNumberOfStructureAllocated = 0;
 
	for (lTexture = 0; lTexture < GLI_C_lNBMaxOfTextures; lTexture++, pp_stTexture++)
	{
		if (*pp_stTexture == NULL)
			continue;

        {
            long            lT2;
            GLI_tdstTexture	**pp_stT2;

            bTwice = 0;

            pp_stT2 = gs_aDEFTableOfTextureAlreadyRead;
            for (lT2 = 0; lT2 < GLI_C_lNBMaxOfTextures; lT2++, pp_stT2++)
	        {
                if (*pp_stT2 == NULL)
                    continue;

                if (*pp_stT2 == *pp_stTexture)
                    continue;

                if (strcmp( (*pp_stT2)->a255_cFileName, (*pp_stTexture)->a255_cFileName) == 0 )
                {
                    bTwice = 1;
                    break;
                }

            }

        }
 
		lDiff = g_a_lTextureSize[0][lTexture] - g_a_lTextureSize[1][lTexture];
		lTotalDiff += lDiff;
 
		lBitmapSize = (*pp_stTexture)->lWidth * (*pp_stTexture)->lHeight;
		if ( !( (*pp_stTexture)->lTextureCaps & GLI_C_lPaletteTexture ) )
			lBitmapSize <<= 1;
		lSize = lBitmapSize;
		for (lLod = 0; lLod < (*pp_stTexture)->lNumberOfLod; lLod++)
		{
			lBitmapSize >>= 2;
			lSize += lBitmapSize;
		}
 
		fprintf( hpFile, "%4d - %6d - %6d - %4d - %6d (%3d-%3d %8X %d) %s %s\n", 
					lTexture, g_a_lTextureSize[0][lTexture], g_a_lTextureSize[1][lTexture], lDiff, lSize, 
					(*pp_stTexture)->lWidth, (*pp_stTexture)->lHeight, (*pp_stTexture)->lTextureCaps, (*pp_stTexture)->lNumberOfLod,
                    bTwice ? "*" : " ", (*pp_stTexture)->a255_cFileName );
		a_lTotal[0] += g_a_lTextureSize[0][lTexture];
		a_lTotal[1] += g_a_lTextureSize[1][lTexture];
 
        lNumberOfStructureAllocated++;
        lStringSize += strlen((*pp_stTexture)->a255_cFileName) + 1;
        /*
        for ( pTextureLod = (*pp_stTexture)->p_NextLodOfTexture; pTextureLod != NULL; pTextureLod = pTextureLod->p_NextLodOfTexture )
            lNumberOfStructureAllocated++;
            */
	}
 
	fprintf( hpFile,"\ntotal : %d - %d - %d\n", a_lTotal[0], a_lTotal[1], lTotalDiff );
 
    fprintf( hpFile,"\nNumber of texture structure allocated : %d (size of one is %d => total size = %d)", lNumberOfStructureAllocated, sizeof( GLI_tdstTexture ), lNumberOfStructureAllocated *  sizeof( GLI_tdstTexture ) );
    fprintf( hpFile,"\nSize of memory taken by texture name  : %d", lStringSize );

    fprintf( hpFile,"\n\nTime taken (in cycles)\n" );
    TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gast_Timer[1], &TEXBENCH_gast_Timer[0] );
    fprintf( hpFile,"Unload        -> (%d,%d)\n",stDiff.ulHigh, stDiff.ulLow);
    TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gast_Timer[3], &TEXBENCH_gast_Timer[2] );
    fprintf( hpFile,"Uncompress    -> (%d,%d)\n",stDiff.ulHigh, stDiff.ulLow);
    TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gast_Timer[5], &TEXBENCH_gast_Timer[4] );
    fprintf( hpFile,"Compression   -> (%d,%d)\n",stDiff.ulHigh, stDiff.ulLow);
    TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gast_Timer[7], &TEXBENCH_gast_Timer[6] );
    fprintf( hpFile,"Compute lod   -> (%d,%d)\n",stDiff.ulHigh, stDiff.ulLow);
    TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gast_Timer[9], &TEXBENCH_gast_Timer[8] );
    fprintf( hpFile,"Download      -> (%d,%d)\n",stDiff.ulHigh, stDiff.ulLow);
    TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gast_Timer[11], &TEXBENCH_gast_Timer[10] );
    fprintf( hpFile,"  part1       -> (%d,%d)\n",stDiff.ulHigh, stDiff.ulLow);
    TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gast_Timer[13], &TEXBENCH_gast_Timer[12] );
    fprintf( hpFile,"  part2       -> (%d,%d)\n",stDiff.ulHigh, stDiff.ulLow);
    TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gast_Timer[15], &TEXBENCH_gast_Timer[14] );
    fprintf( hpFile,"  part3       -> (%d,%d)\n",stDiff.ulHigh, stDiff.ulLow);

    /*
     * time for each texture
     */
    fprintf( hpFile,"\n\nTime taken by each texture for download (in cycles)\n" );
    pp_stTexture = gs_aDEFTableOfTextureAlreadyRead;
    memset( a_ulTimeTotal, 0, sizeof(a_ulTimeTotal) );
    for (lTexture = 0; lTexture < GLI_C_lNBMaxOfTextures; lTexture++, pp_stTexture++)
	{
		if (*pp_stTexture == NULL)
			continue;

        fprintf( hpFile,"%4d ", lTexture );
        TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gaast_TextureTimer[1][lTexture], &TEXBENCH_gaast_TextureTimer[0][lTexture] );
        a_ulTimeTotal[ 0 ] += stDiff.ulLow;
        fprintf( hpFile,"%10d ", stDiff.ulLow);
        TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gaast_TextureTimer[2][lTexture], &TEXBENCH_gaast_TextureTimer[1][lTexture] );
        a_ulTimeTotal[ 1 ] += stDiff.ulLow;
        fprintf( hpFile,"%10d ", stDiff.ulLow);
        TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gaast_TextureTimer[3][lTexture], &TEXBENCH_gaast_TextureTimer[2][lTexture] );
        a_ulTimeTotal[ 2 ] += stDiff.ulLow;
        fprintf( hpFile,"%10d ", stDiff.ulLow);
        TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gaast_TextureTimer[4][lTexture], &TEXBENCH_gaast_TextureTimer[3][lTexture] );
        a_ulTimeTotal[ 3 ] += stDiff.ulLow;
        fprintf( hpFile,"%10d ", stDiff.ulLow);
        TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gaast_TextureTimer[5][lTexture], &TEXBENCH_gaast_TextureTimer[4][lTexture] );
        a_ulTimeTotal[ 4 ] += stDiff.ulLow;
        fprintf( hpFile,"%10d", stDiff.ulLow);
        TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gaast_TextureTimer[6][lTexture], &TEXBENCH_gaast_TextureTimer[5][lTexture] );
        a_ulTimeTotal[ 5 ] += stDiff.ulLow;
        fprintf( hpFile,"%10d", stDiff.ulLow);
        TEXBENCH_fnv_Diff( &stDiff, &TEXBENCH_gaast_TextureTimer[7][lTexture], &TEXBENCH_gaast_TextureTimer[6][lTexture] );
        a_ulTimeTotal[ 6 ] += stDiff.ulLow;
        fprintf( hpFile,"%10d\n", stDiff.ulLow);
	}
    fprintf( hpFile, "\nsum = %10d %10d %10d %10d %10d %10d %10d\n", a_ulTimeTotal[ 0 ], a_ulTimeTotal[ 1 ], a_ulTimeTotal[ 2 ], a_ulTimeTotal[ 3 ], a_ulTimeTotal[ 4 ], a_ulTimeTotal[ 5 ], a_ulTimeTotal[ 6 ] );
 
	fclose( hpFile );
}
 
#endif
