/*
 =======================================================================================
  Name        : OGL_Func.c
  Author      : Bart     
  Description : included in OGL_Thread.c
 =======================================================================================
 */

#include "textu_st.h"
#include "texture.h"
#include "DLLCom.h"
#include "TEX.h" // for def of GLI_C_lCyling..

extern HWND                     gs_hWnd;
HGLRC                    gs_hRC;

extern HDC                      gs_hDC;


/* from OGL_Acces.c */
extern GLI_tdScreenVertx ga_stVertexBuffer[ 3000 ];


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


/* from OGL_Init.c */
extern RECT g_rcViewportRect;
extern RECT g_rcScreenRect;

/* from OGL_Domat.c */
extern GLI_tdScreenVertx g_stBlackTriangle[ 16 ];
extern long  g_lNumberOfBlackTriangles;
extern tdstFogParams* g_p_stFogParams;


/************************************ divers ************************************/

void fn_OGLThread_vCreate()
{
	M_ASSERT( (gs_hRC = wglCreateContext(gs_hDC)) )
    M_ASSERT( wglMakeCurrent(gs_hDC, gs_hRC) )
}

void fn_OGLThread_vResume()
{
	M_ASSERT( wglMakeCurrent(gs_hDC, NULL) )		/* make our context 'un-'current */
	M_ASSERT( ReleaseDC(gs_hWnd, gs_hDC) )		/* release handle to DC - already done by wglMakeCurrent(..., NULL) ! */
    M_ASSERT( wglDeleteContext(gs_hRC) )		/* delete the rendering context */
	gs_hRC = NULL;

	gs_hDC = NULL;
}

void fn_OGLThread_vSwap()
{
    SwapBuffers( gs_hDC );
    //glFinish();
    //SwapBuffers(wglGetCurrentDC());
}



/************************************ OGL_Acces.c ************************************/

void fn_OGLThread_vRender(GLI_tdScreenVertx* _p_CurrentDestXYZ)
{
    GLI_tdScreenVertx *p_stEnumerate;
	GLubyte* pBGRA;

    M_OGL_ASSERT_FAKE(glBegin(GL_TRIANGLES);)

    p_stEnumerate = ga_stVertexBuffer;
    while (p_stEnumerate < _p_CurrentDestXYZ)
    {
        //glColor4ubv( (GLubyte *) &p_stEnumerate->color );
		pBGRA = (GLubyte *) &p_stEnumerate->color;
		M_OGL_ASSERT_FAKE( glColor4ub( pBGRA[2], pBGRA[1], pBGRA[0], pBGRA[3]); )
		
        M_OGL_ASSERT_FAKE( glTexCoord2f( GetU((*p_stEnumerate)), GetV((*p_stEnumerate)) ); )

		M_OGL_ASSERT_FAKE( M_glVertex( GetX((*p_stEnumerate)), GetY((*p_stEnumerate)), GetZ((*p_stEnumerate)) ); )

        p_stEnumerate++;
    }
    M_OGL_ASSERT( glEnd(); )
}

/******************************** fin OGL_Acces.c ************************************/



/************************************ OGL_HdwTx.c ************************************/


void fn_OGLThread_vLoadTextures(GLI_tdstTexture* _p_stTexture)
{
	unsigned int		*p_uiTextureId;
    long                lNbLod;
    unsigned short      lWidth, lHeight;
	long                lCurrentDecalTextureForMipMapping;
	GLint               nInternalFormats;
	GLenum              PixelDataType;

	p_uiTextureId = (unsigned int *) &_p_stTexture->p_stSpecParam;

	M_OGL_ASSERT( glGenTextures(1, p_uiTextureId ); )

	M_OGL_ASSERT( glBindTexture(GL_TEXTURE_2D, *p_uiTextureId);  )/*texture is bound*/

#if !defined(IGNORE_TEXTUREWRAP)
	/*
	* uv cycling mode
	*/
	switch ( _p_stTexture -> ucCylingMode )
	{
		case 0:
			/*NO CYCLING*/
			M_OGL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); )
			M_OGL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); )
			break;
		case GLI_C_lCylingUV:
			/*CYCLING*/
			M_OGL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); )
			M_OGL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); )
			break;
		case GLI_C_lCylingU:
			/*CYCLING V*/
			M_OGL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); )
			M_OGL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); )
			break;
		case GLI_C_lCylingV:
			/*CYCLING U*/
			M_OGL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); )
			M_OGL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); )
			break;
	}
#endif //!defined(IGNORE_TEXTUREWRAP)
	
	M_OGL_ASSERT( glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR /*GL_NEAREST*/); )
	if (_p_stTexture->lNumberOfLod == 0)
		M_OGL_ASSERT( glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); )
	else
		M_OGL_ASSERT( glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR /*GL_NEAREST_MIPMAP_LINEAR*/ /*GL_LINEAR_MIPMAP_NEAREST*/ /*GL_NEAREST_MIPMAP_NEAREST*/ /*GL_LINEAR*/); )

	
	lCurrentDecalTextureForMipMapping   = 0;
    lWidth  = _p_stTexture->lWidth;
    lHeight = _p_stTexture->lHeight;

	nInternalFormats = 4; // default : 8888
	PixelDataType = GL_UNSIGNED_BYTE; // default (OpenGL ver 1.1, no EXT) : 32 bits !

	if ( _p_stTexture->lTextureCaps & GLI_C_lAlphaTest )
	{
        nInternalFormats = GL_RGB5_A1; //5551
	   #if defined (OGL_VER2_2)
        PixelDataType = GL_UNSIGNED_SHORT_5_5_5_1; //5551
	   #elif defined (GL_EXT_packed_pixels)
        PixelDataType = GL_UNSIGNED_SHORT_5_5_5_1_EXT; //5551
	   #endif //defined (GL_EXT_packed_pixels)
    }
	else if ((!(_p_stTexture -> lTextureCaps & GLI_C_lAlphaTexture)) && (_p_stTexture -> lTextureCaps & GLI_C_lNZFilteredTexture)) 
	{
        nInternalFormats = GL_RGB5_A1; //5551
	   #if defined (OGL_VER2_2)
        PixelDataType = GL_UNSIGNED_SHORT_5_5_5_1; //5551
	   #elif defined (GL_EXT_packed_pixels)
        PixelDataType = GL_UNSIGNED_SHORT_5_5_5_1_EXT; //5551
	   #endif //defined (GL_EXT_packed_pixels)
	}
	else if (_p_stTexture -> lTextureCaps & GLI_C_lAlphaTexture) 
	{
        nInternalFormats = GL_RGBA4; //4444
	   #if defined (OGL_VER2_2)
        PixelDataType = GL_UNSIGNED_SHORT_4_4_4_4; //4444
	   #elif defined (GL_EXT_packed_pixels)
        PixelDataType = GL_UNSIGNED_SHORT_4_4_4_4_EXT; //4444
	   #endif //defined (GL_EXT_packed_pixels)
    }
	else 
	{
		nInternalFormats = GL_RGB5; //555 because no 565 !
	   #if defined (OGL_VER2_2)
        PixelDataType = GL_UNSIGNED_SHORT_5_6_5; // 565 only in version 2.2 !
	   #elif defined (GL_EXT_packed_pixels)
        PixelDataType = GL_UNSIGNED_SHORT_5_5_5_1_EXT; //? 5551 because no 565 !
	   #endif //defined (GL_EXT_packed_pixels)
	}

	for ( lNbLod=0 ; lNbLod <= _p_stTexture->lNumberOfLod ; lNbLod++ )
	{
		assert(lHeight>0);
		assert(lWidth>0);

		M_OGL_ASSERT( glTexImage2D(GL_TEXTURE_2D, lNbLod, nInternalFormats, lWidth, lHeight, 0, GL_RGBA, PixelDataType, TEXTURETWIDDLED+lCurrentDecalTextureForMipMapping ); )

		lCurrentDecalTextureForMipMapping += lHeight * lWidth;
		lHeight >>= 1;
		lWidth  >>= 1;
#if defined (MIPMAP_DOWN_TO_1x1)
		if (lHeight == 0) lHeight = 1;
		if (lWidth == 0) lWidth = 1;
#endif //defined (MIPMAP_DOWN_TO_1x1)
	}
}


/******************************** fin OGL_HdwTx.c ************************************/





/************************************ OGL_Init.c ************************************/
#if defined (Z_BUFFER)
	#define ZFAR 10000.0f
	#define ZNEAR 0.0f //0.1667f
	#define VIG_ZPOS 6.0f

#else //W_BUFFER

	#define ZFAR 0.0001f
	#if defined ACCURATE_DEPTH_BUFFER
		#define ZNEAR 0.5f
	#else
		#define ZNEAR 6.0f
	#endif
	#define VIG_ZPOS ZNEAR

#endif


void fn_OGLThread_vInitOglFlags()
{
/*** GL_TEXTURE ***/
    M_OGL_ASSERT( glMatrixMode(GL_TEXTURE); )
    M_OGL_ASSERT( glLoadIdentity(); )
	//glScalef( 1.0f, -1.0f, 0.0f ); // ?

/*** GL_PROJECTION ***/
    M_OGL_ASSERT( glMatrixMode(GL_PROJECTION); )
    M_OGL_ASSERT( glLoadIdentity(); )

 
/*** GL_MODELVIEW ***/
    M_OGL_ASSERT( glMatrixMode(GL_MODELVIEW); )
    M_OGL_ASSERT( glLoadIdentity(); )

	M_OGL_ASSERT( glOrtho(0, (GLdouble)(g_rcViewportRect.right - g_rcViewportRect.left), (GLdouble)(g_rcViewportRect.bottom - g_rcViewportRect.top), 0, -ZFAR, -ZNEAR);  )

    M_OGL_ASSERT( glViewport(0, 0, g_rcScreenRect.right - g_rcScreenRect.left, g_rcScreenRect.bottom - g_rcScreenRect.top); )

{
        M_OGL_ASSERT( glDisable(GL_ALPHA_TEST); )
        //M_OGL_ASSERT( glDisable(GL_BLEND); )
        //M_OGL_ASSERT( glDisable(GL_DEPTH_TEST); )
		M_OGL_ASSERT( glDisable(GL_DITHER); )
		M_OGL_ASSERT( glDisable(GL_LIGHTING); )
        M_OGL_ASSERT( glDisable(GL_LOGIC_OP); )
		M_OGL_ASSERT( glDisable(GL_STENCIL_TEST); )
        M_OGL_ASSERT( glDisable(GL_TEXTURE_1D); )
		M_OGL_ASSERT( glDisable(GL_TEXTURE_2D); )
        M_OGL_ASSERT( glPixelTransferi(GL_MAP_COLOR, GL_FALSE); )
        M_OGL_ASSERT( glPixelTransferi(GL_RED_SCALE, 1); )
        M_OGL_ASSERT( glPixelTransferi(GL_RED_BIAS, 0); )
        M_OGL_ASSERT( glPixelTransferi(GL_GREEN_SCALE, 1); )
        M_OGL_ASSERT( glPixelTransferi(GL_GREEN_BIAS, 0); )
        M_OGL_ASSERT( glPixelTransferi(GL_BLUE_SCALE, 1); )
        M_OGL_ASSERT( glPixelTransferi(GL_BLUE_BIAS, 0); )
        M_OGL_ASSERT( glPixelTransferi(GL_ALPHA_SCALE, 1); )
        M_OGL_ASSERT( glPixelTransferi(GL_ALPHA_BIAS, 0); )
}

    M_OGL_ASSERT( glEnable(GL_DEPTH_TEST); )	// Hidden surface removal
	M_OGL_ASSERT( glDepthMask( GL_TRUE ); ) 
 

	M_OGL_ASSERT( glDisable(GL_CULL_FACE); )		// Do not calculate inside of jet
	//glEnable(GL_CULL_FACE);		// Do not calculate inside of jet

	M_OGL_ASSERT( glFrontFace(GL_CCW); )		// Counter clock-wise polygons face out

	M_OGL_ASSERT( glEnable(GL_TEXTURE_2D); )

	M_OGL_ASSERT( glEnable(GL_BLEND); )

	M_OGL_ASSERT( glClearColor (0.0, 0.0, 0.0, 0.0); )

	M_OGL_ASSERT( glClearDepth(0.0f); ) 
    M_OGL_ASSERT( glDepthFunc( GL_GREATER ); )

	//M_OGL_ASSERT( glClearDepth(1.0f); ) 
	//M_OGL_ASSERT( glDepthFunc( GL_LESS ); )
    
	//glDepthMask( GL_TRUE );

    // fog
	M_OGL_ASSERT( glDisable(GL_FOG); )
    M_OGL_ASSERT( glFogi(GL_FOG_MODE, GL_LINEAR /*GL_EXP*/); ) //grFogTable( Gli_C_xFogTable );

	// hint
    M_OGL_ASSERT( glHint (GL_FOG_HINT, /*GL_NICEST*/ GL_FASTEST); ) /*  per pixel   */
	M_OGL_ASSERT( glHint (GL_PERSPECTIVE_CORRECTION_HINT, /*GL_NICEST*/ GL_FASTEST); )
}

void fn_OGLThread_vClearDevice(BOOL ZBuffer, BOOL ColorBuffer, unsigned long Color)
{
    char cR, cG, cB, cA;
	char* pColor;

	M_OGL_ASSERT( glDepthMask( GL_TRUE ); )
	
	pColor = (char*) &Color;
	cR = *pColor++;
	cG = *pColor++;
	cB = *pColor++;
	cA = *pColor;
		
    M_OGL_ASSERT( glClearColor ((float)cR/255.0f, (float)cG/255.0f, (float)cB/255.0f, (float)cA/255.0f); )

    if ( ColorBuffer )  
        if (ZBuffer)
			M_OGL_ASSERT( {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); )}
        else
			M_OGL_ASSERT( {glClear(GL_COLOR_BUFFER_BIT ); )}
    else if (ZBuffer)
		M_OGL_ASSERT( {glClear( GL_DEPTH_BUFFER_BIT ); )}
}

/******************************** fin OGL_Init.c ************************************/


/******************************** OGL_Domat.c ************************************/

void fn_OGLThread_vSendBlackPolygon(void)
{
    GLI_tdScreenVertx *p_stVertex, *p_stLastVertex;

	M_OGL_ASSERT( glDisable(GL_TEXTURE_2D); )
	M_OGL_ASSERT( glDisable(GL_FOG); )
	M_OGL_ASSERT( glBlendFunc(GL_ONE, GL_ZERO); ) //grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
	M_OGL_ASSERT( glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE/*GL_DECAL*/ /*not yet implemented : GL_BLEND, GL_REPLACE*/ ); ) //guColorCombineFunction( GR_COLORCOMBINE_ITRGB);

	M_OGL_ASSERT( glColor4ub( 0, 0, 0, 0 ); )
	
    p_stVertex = g_stBlackTriangle;
    p_stLastVertex = p_stVertex + g_lNumberOfBlackTriangles;

	M_OGL_ASSERT_FAKE( glBegin(GL_QUADS); )

    for ( ; p_stVertex < p_stLastVertex; p_stVertex++ )
		M_OGL_ASSERT_FAKE( glVertex3f( p_stVertex->sx, p_stVertex->sy, p_stVertex->sz ); )

	M_OGL_ASSERT( glEnd(); )
}

void fn_OGLThread_vSetFogParams(void)
{
    GLfloat fogColor[4];
    GLfloat fBlendFactor;

    M_OGL_ASSERT( glFogf (GL_FOG_START, g_p_stFogParams->xDepthStart); )
    M_OGL_ASSERT( glFogf (GL_FOG_END, g_p_stFogParams->xDepthEnd); )

	//glFogf (GL_FOG_DENSITY, g_p_stFogParams->xBlendEnd); // ?

	fBlendFactor = g_p_stFogParams->xBlendEnd / 255.0f;

    fogColor[0] = (GLfloat)g_p_stFogParams->stColor.xR * fBlendFactor;
	fogColor[1] = (GLfloat)g_p_stFogParams->stColor.xG * fBlendFactor;
	fogColor[2] = (GLfloat)g_p_stFogParams->stColor.xB * fBlendFactor;
	fogColor[3] = (GLfloat)g_p_stFogParams->stColor.xA * fBlendFactor;
    M_OGL_ASSERT( glFogfv(GL_FOG_COLOR, fogColor); ) //grFogColorValue(GlideColor);

	fBlendFactor = g_p_stFogParams->xBlendStart / 255.0f;

    fogColor[0] = (GLfloat)g_p_stFogParams->stColor.xR * fBlendFactor;
	fogColor[1] = (GLfloat)g_p_stFogParams->stColor.xG * fBlendFactor;
	fogColor[2] = (GLfloat)g_p_stFogParams->stColor.xB * fBlendFactor;
	fogColor[3] = (GLfloat)g_p_stFogParams->stColor.xA * fBlendFactor;

	M_OGL_ASSERT( glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, fogColor ); )
}

/******************************** fin OGL_Domat.c ************************************/

#include "OGL_Lock.c"