#include <windows.h>
#include <gl/gl.h>

#include "GLD.h"
#include "GEO.h"
#include "TEX.h"
#include "gli_st.h"
#include "textu_st.h"
#include "texture.h"
#include "FIL.h"

#include "DLLCom.h"

#include "OGL_Options.h"
#include "OGL_Errors.h"
#include "OGL_Thread.h"

static long GLI_gs_lMaxTmuAvailable; 

//GLI_tdstTexture     *g_p_stTexture;

#if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
	short TEXTURETWIDDLED[1024L*1024L];
#else 
	long TEXTURETWIDDLED[1024L*1024L];
#endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)

/*
 ----------------------------------------------------------------------------------------
  Description   : get total memory size available for texture
 ----------------------------------------------------------------------------------------
 */
long GLI_fn_lGetTotalTextureMemorySize( void )
{
/*
    long i,lSize;
    GLI_gs_lMaxTmuAvailable = 2 ;
    lSize = 0;
    for (i = 0 ; i < GLI_gs_lMaxTmuAvailable ; i++)
        lSize += grTexMaxAddress( i ) - grTexMinAddress( i );
    return (lSize);
    */
	return -1;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : get video memory size taken by a given texture
 ----------------------------------------------------------------------------------------
 */
long GLI_DRV_lGetSizeOfTexture( GLI_tdstTexture *p_stTexture )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	long lTextureSize;
	long lRef, lSize;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

    lTextureSize = p_stTexture->lHeight * p_stTexture->lWidth;

    /*
     * 8 bits
     */
    if (!(p_stTexture->lTextureCaps & GLI_C_lPaletteTexture))
        lTextureSize <<= 1;

    /*
     * mipmap
     */
    if (p_stTexture ->lNumberOfLod)
	{
        lRef = (p_stTexture->lWidth > p_stTexture->lHeight) ? p_stTexture->lHeight : p_stTexture->lWidth;
        lSize   = lTextureSize;

        while ( lRef )
        {
            lSize >>= 2;
            lRef  >>= 1;
            lTextureSize += lSize;
        }
	}

    /*
     * alignment
     */
    if ( lTextureSize & 0x7 )
    {
        lTextureSize += 8 - (lTextureSize & 0x7);
    }

	GLI_MDRV_TEXBENCH_vSetTextureSize( p_stTexture, TEXBENCH_C_cComputedSize, lTextureSize );

    return lTextureSize;
}



/*
 ----------------------------------------------------------------------------------------
  Description   : Compress texture and compute mip map levels
 ----------------------------------------------------------------------------------------
 */
static void GLI_vCompressTex ( GLI_tdstTexture *p_stTexture, BOOL bReloading)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    long                lCurrentDecalTextureForMipMapping, Verify;
    
 #if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
	unsigned short      *p_Destination;
 #else 
	unsigned long       *p_Destination;
 #endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)

    //unsigned char       *p_ucDest;
    //unsigned long       *p_ulPalette;
    long                lNbLod;
    unsigned short      lWidth, lHeight;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    if (p_stTexture == NULL ) 
        return;
 
    lCurrentDecalTextureForMipMapping   = 0;
    p_Destination                       = TEXTURETWIDDLED;
    p_stTexture->p_vBitMap              = GLI_gs_p_ConvertBufferMipMapping;
       
    /*
     * load texture
     */
    GLI_MDRV_xLoadTextureInTexelField(p_stTexture, GLI_gs_p_ConvertBufferMipMapping, bReloading/*TRUE*/);
    
    /*
     * check for alpha texture
     */
    if ((p_stTexture -> lTextureCaps & GLI_C_lAlphaTexture) || (p_stTexture -> lTextureCaps & GLI_C_lNZFilteredTexture))
    {
        Verify = GLI_MDRV_vVerifyTextureIsRealyAlpha(p_stTexture);
        if ((Verify & 0xE0000000) == 0xE0000000)
            p_stTexture -> lTextureCaps &= 0xffffffff - GLI_C_lAlphaTexture;
        if ((Verify & 0x80000000) == 0x80000000)
            p_stTexture -> lTextureCaps &= 0xffffffff - GLI_C_lNZFilteredTexture;
    }

#if defined (NO_MIPMAP_FOR_TRANSPARENT_TEX)
	if (p_stTexture -> lTextureCaps & (/*GLI_C_lAlphaTest |*/ GLI_C_lAlphaTexture /*| GLI_C_lNZFilteredTexture */ /*| GLI_C_lAddTransparencyTexture*/) )
		p_stTexture->lNumberOfLod = 0;
#endif //defined (NO_MIPMAP_FOR_TRANSPARENT_TEX)

#if defined (MIPMAP_DOWN_TO_1x1)
	if ( (p_stTexture->lNumberOfLod >0) && (p_stTexture->lWidth != p_stTexture->lHeight) )
	{
		//recalc lNumberOfLod
		lWidth  = p_stTexture->lWidth;
		lHeight = p_stTexture->lHeight;
		while ( (lWidth>1) && (lHeight>1) )	{
			lHeight >>= 1;
			lWidth  >>= 1;
		}
		while ( (lWidth>1) || (lHeight>1) )	{
			p_stTexture->lNumberOfLod++;
			lHeight >>= 1;
			lWidth  >>= 1;
		}
	}
#endif //defined MIPMAP_DOWN_TO_1x1
 
    p_stTexture->p_vBitMap = GLI_gs_p_ConvertBufferMipMapping;
    lNbLod  = p_stTexture->lNumberOfLod;
    lWidth  = p_stTexture->lWidth;
    lHeight = p_stTexture->lHeight;

    
    /*if ( p_stTexture->lTextureCaps & GLI_C_lPaletteTexture )
    {
        p_ucDest    = (char *) p_Destination;
        p_ulPalette = (unsigned long *) p_stTexture->p_vColorTable;
        
        //((GLI_tdstTextureDFX  *) p_stTexture->p_stSpecParam)->stInfoBitmapGlide.format = GR_TEXFMT_P_8;
        memcpy( p_ucDest, GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth );
        lCurrentDecalTextureForMipMapping = p_stTexture->lHeight * p_stTexture->lWidth ;
    
        while( lNbLod-- )
        {
            GLI_MDRV_vDivideBitmapSurfaceBy2Palette( (unsigned long *)GLI_gs_p_ConvertBufferMipMapping , p_ulPalette, p_stTexture->lHeight, p_stTexture->lWidth );
            p_stTexture->lHeight >>= 1;
            p_stTexture->lWidth  >>= 1;
            memcpy( p_ucDest + lCurrentDecalTextureForMipMapping, GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth );
            lCurrentDecalTextureForMipMapping += p_stTexture->lHeight * p_stTexture->lWidth;
        }
    }
    else */ 
    // TEST sur nouveau traitement sur texture NZ : marche pas bien pour l'instant
	if ( p_stTexture->lTextureCaps & GLI_C_lAlphaTest )
    {
        //((GLI_tdstTextureDFX  *) p_stTexture->p_stSpecParam)->stInfoBitmapGlide.format = GR_TEXFMT_ARGB_1555;

 #if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
        GLI_MDRV_vCompressTex1555( p_stTexture  ,(void *)(p_Destination)) ;
 #else
		memcpy( p_Destination, GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth * sizeof(unsigned long) );
 #endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
        lCurrentDecalTextureForMipMapping = p_stTexture->lHeight * p_stTexture->lWidth ;

        while( lNbLod-- )
        {
            GLI_MDRV_vDivideBitmapSurfaceBy2NonZero((unsigned long *)GLI_gs_p_ConvertBufferMipMapping , (unsigned long *)GLI_gs_p_ConvertBufferMipMapping , p_stTexture->lHeight, p_stTexture->lWidth, p_stTexture->lChromakeyColorRGBA); /* G.CLEMENT 04/08/1999 : added chromakey */
            p_stTexture->lHeight >>= 1;
            p_stTexture->lWidth  >>= 1;
 #if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
            GLI_MDRV_vCompressTex1555( p_stTexture  ,(void *)(p_Destination + lCurrentDecalTextureForMipMapping)) ;
 #else
			memcpy( p_Destination + lCurrentDecalTextureForMipMapping, GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth * sizeof(unsigned long) );
 #endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
            lCurrentDecalTextureForMipMapping += p_stTexture->lHeight * p_stTexture->lWidth;
        }
    }
    else if ((!(p_stTexture -> lTextureCaps & GLI_C_lAlphaTexture)) && (p_stTexture -> lTextureCaps & GLI_C_lNZFilteredTexture))
    {
        //((GLI_tdstTextureDFX  *) p_stTexture->p_stSpecParam)->stInfoBitmapGlide.format = GR_TEXFMT_ARGB_1555;

 #if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
        GLI_MDRV_vCompressTex1555( p_stTexture  ,(void *)(p_Destination)) ;
 #else
		memcpy( p_Destination , GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth * sizeof(unsigned long) );
 #endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
        lCurrentDecalTextureForMipMapping = p_stTexture->lHeight * p_stTexture->lWidth ;

        while( lNbLod-- )
        {
            if (p_stTexture -> lTextureCaps & GLI_C_lNZTexture)
                GLI_MDRV_vDivideBitmapSurfaceBy2NonZero((unsigned long *)GLI_gs_p_ConvertBufferMipMapping , (unsigned long *)GLI_gs_p_ConvertBufferMipMapping , p_stTexture -> lHeight, p_stTexture -> lWidth, p_stTexture->lChromakeyColorRGBA); /* G.CLEMENT 04/08/1999 : added chromakey */
            else
                GLI_MDRV_vDivideBitmapSurfaceBy2((unsigned long *)GLI_gs_p_ConvertBufferMipMapping , (unsigned long *)GLI_gs_p_ConvertBufferMipMapping , p_stTexture -> lHeight, p_stTexture -> lWidth);
            p_stTexture->lHeight >>= 1;
            p_stTexture->lWidth  >>= 1;
 #if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
            GLI_MDRV_vCompressTex1555( p_stTexture  ,(void *)(p_Destination + lCurrentDecalTextureForMipMapping)) ;
 #else
			memcpy( p_Destination + lCurrentDecalTextureForMipMapping, GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth * sizeof(unsigned long) );
 #endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
            lCurrentDecalTextureForMipMapping += p_stTexture->lHeight * p_stTexture->lWidth;
        }
    }
    else if (p_stTexture -> lTextureCaps & GLI_C_lAlphaTexture)
    {
        //((GLI_tdstTextureDFX  *) p_stTexture->p_stSpecParam)->stInfoBitmapGlide.format = GR_TEXFMT_ARGB_4444;

 #if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
        GLI_MDRV_vCompressTex4444( p_stTexture , (void *)(p_Destination)) ;
 #else
		memcpy( p_Destination, GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth * sizeof(unsigned long) );
 #endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
        lCurrentDecalTextureForMipMapping = p_stTexture->lHeight * p_stTexture->lWidth ;

        while( lNbLod-- )
        {
            if (p_stTexture -> lTextureCaps & GLI_C_lNZTexture)
                GLI_MDRV_vDivideBitmapSurfaceBy2NonZero((unsigned long *)GLI_gs_p_ConvertBufferMipMapping , (unsigned long *)GLI_gs_p_ConvertBufferMipMapping , p_stTexture -> lHeight , p_stTexture -> lWidth, p_stTexture->lChromakeyColorRGBA); /* G.CLEMENT 04/08/1999 : added chromakey */
            else
                GLI_MDRV_vDivideBitmapSurfaceBy2((unsigned long *)GLI_gs_p_ConvertBufferMipMapping , (unsigned long *)GLI_gs_p_ConvertBufferMipMapping , p_stTexture -> lHeight , p_stTexture -> lWidth );
            p_stTexture->lHeight >>= 1;
            p_stTexture->lWidth  >>= 1;
 #if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
            GLI_MDRV_vCompressTex4444( p_stTexture , (void *)(p_Destination + lCurrentDecalTextureForMipMapping)) ;
 #else
			memcpy( p_Destination + lCurrentDecalTextureForMipMapping, GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth * sizeof(unsigned long) );
 #endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
            lCurrentDecalTextureForMipMapping += p_stTexture->lHeight * p_stTexture->lWidth;
        }
    }
    else
    {
        //((GLI_tdstTextureDFX  *) p_stTexture->p_stSpecParam)->stInfoBitmapGlide.format = GR_TEXFMT_RGB_565;

 #if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
		GLI_MDRV_vCompressTex565( p_stTexture , (void *)(p_Destination)) ;
 #else
        memcpy( p_Destination, GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth * sizeof(unsigned long) );
 #endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
		lCurrentDecalTextureForMipMapping = p_stTexture->lHeight * p_stTexture->lWidth ;

        while( lNbLod-- )
        {
            if (p_stTexture -> lTextureCaps & GLI_C_lNZTexture)
                GLI_MDRV_vDivideBitmapSurfaceBy2NonZero((unsigned long *)GLI_gs_p_ConvertBufferMipMapping , (unsigned long *)GLI_gs_p_ConvertBufferMipMapping , p_stTexture -> lHeight, p_stTexture -> lWidth, p_stTexture->lChromakeyColorRGBA); /* G.CLEMENT 04/08/1999 : added chromakey */
            else
                GLI_MDRV_vDivideBitmapSurfaceBy2((unsigned long *)GLI_gs_p_ConvertBufferMipMapping , (unsigned long *)GLI_gs_p_ConvertBufferMipMapping , p_stTexture -> lHeight, p_stTexture -> lWidth);
            p_stTexture->lHeight >>= 1;
            p_stTexture->lWidth  >>= 1;
 #if defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
            GLI_MDRV_vCompressTex565 ( p_stTexture , (void *)(p_Destination + lCurrentDecalTextureForMipMapping)) ;
 #else
			memcpy( p_Destination + lCurrentDecalTextureForMipMapping, GLI_gs_p_ConvertBufferMipMapping, p_stTexture->lHeight * p_stTexture->lWidth * sizeof(unsigned long) );
 #endif //defined (OGL_VER2_2) || defined (GL_EXT_packed_pixels)
            lCurrentDecalTextureForMipMapping += p_stTexture->lHeight * p_stTexture->lWidth;
		}
    }

    p_stTexture->lWidth = lWidth;
    p_stTexture->lHeight = lHeight;
}



/*
 ----------------------------------------------------------------------------------------
  Description   : get total memory size available for texture
 ----------------------------------------------------------------------------------------
 */
void GLI_DRV_vDownLoadTextures(long bRestore, long _lTextureMode, BOOL bReloading )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    long                lTextureCounter;
    GLI_tdstTexture     *p_stTexture;
	/*#if defined (ERROR_TEST)
		char sz255String[255];
	#endif //defined (ERROR_TEST)*/
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/*
#if defined (ERROR_TEST)
	p_uiTextureId = NULL;
#endif //defined (ERROR_TEST)
*/

    for (lTextureCounter = 0; lTextureCounter < GLI_C_lNBMaxOfTextures ; lTextureCounter ++)
    {
        if (gs_aDEFTableOfTextureMemoryChannels[lTextureCounter] == GLI_TEXIsUnallocated )
            continue;

        p_stTexture = gs_aDEFTableOfTextureAlreadyRead[lTextureCounter];
        if (p_stTexture == NULL)
            continue;
        
        OGLThread_fn_vWaitForSynchro(); // finishing
		GLI_vCompressTex( p_stTexture, bReloading);
		//GLI_MDRV_xLoadTextureInTexelField(p_stTexture, GLI_gs_p_ConvertBufferMipMapping, bReloading); //bart990224
        
		p_stTexture -> bIsAvailable = 1;

        OGLThread_fn_vWaitForSynchro(); // for TEXTURETWIDDLED
        //grTexDownloadMipMap (p_stSpecParam -> xTmuNumber,p_stSpecParam -> xStartAddress ,p_stSpecParam -> xEvenOdd ,&p_stSpecParam -> stInfoBitmapGlide  );
		OGLThread_fn_vPostCmd_1Long(OGLT1_LOADTEXTURES, (long)p_stTexture);

    }
/*
#if defined (ERROR_TEST)
	if (p_uiTextureId == NULL) {
		M_OUTPUT("No texture loaded ! ! !\n");
	}
	else {
		sprintf(sz255String, "Last texture loaded : %d\n", *p_uiTextureId);
		M_OUTPUT(sz255String);
	}
#endif //defined (ERROR_TEST)
*/
/*#endif*/
}



/*
 ----------------------------------------------------------------------------------------
  Description   : get total memory size available for texture
 ----------------------------------------------------------------------------------------
 */
void GLI_DRV_vUnLoadTextures()
{
    long lTextureCounter;
	//unsigned int		*p_uiTextureId;
    
    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)
                {
					OGLThread_fn_vPostCmd_1Long(OGLT1_DELETETEXTURE, (long)p_stTexture->p_stSpecParam); //p_uiTextureId = (unsigned int *) &p_stTexture->p_stSpecParam;

                    p_stTexture->bIsAvailable = 0;
                }
            }
        }
    }
}


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