/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/include/drivers/common/opengl/oglgraphics.hpp

*/

#ifndef SGX_OPENGL_GRAPHICS_H
#define SGX_OPENGL_GRAPHICS_H

#include "sgx/graphics/graphics.hpp"

// NOTE: You must include <GL/glut.h> before this file
#include "oglstates.hpp"

typedef tBOOL (cb_pOpenGLIdleFunction)(tREAL32, tMEM_SIZE);

class COpenGLEngine : public CSGXGraphicsEngine
{
public:
	static sgxTexEnvState			m_StateTexEnv;
	static sgxBindTexState			m_StateBindTex;
	static sgxBlendFuncState		m_StateBlendFunc;

	static CSGXGraphicsEngine *create(const sgxString &appname, const tUINT32 width, const tUINT32 height);
	static COpenGLEngine *getOpenGL();

	virtual void	initialize();

	virtual void	showSystemCursor(const tBOOL show);
	virtual void	hideSystemCursor();

	virtual void	refresh();
	virtual void	idleScene();
	virtual void	runEngine(cb_pOpenGLIdleFunction *pFN, const tMEM_SIZE param);
	virtual void	stopEngine();

	virtual tUINT32	getMaxLights() const;
	
	virtual void	setClipRect(const tPOINT x1, const tPOINT y1, const tPOINT x2, const tPOINT y2);

protected:
	COpenGLEngine::COpenGLEngine(const sgxString &appname, const tUINT32 width, const tUINT32 height);
	COpenGLEngine::COpenGLEngine() : CSGXGraphicsEngine() {}

	virtual void set2DMode();
	virtual void set3DMode();

	virtual void doBeginScene();
	virtual void preDrawScene();
	virtual void doDrawScene();
	virtual void blit();

	virtual void setRenderBuffer(tUINT32 id);

	virtual void postUpdateScene(const tREAL32 telaps);

	virtual void flushClearBuffer();

	virtual CSGXTexture *grabFrame(const tBOOL resizeToSquarePowerOf2=FALSE);

	virtual void updateViewTransform();
	virtual void updateProjectionTransform();


	// Primitives
//	virtual void drawPolygon(const sgxPolygonPrimitive &poly, const sgxMatrix43 &transform);
	//	virtual void drawMesh(const CStaticMesh &mesh, const sgxMatrix43 &transform);
	
	virtual void updateAnimatedMesh(CAnimatedMesh &animmesh, const tREAL32 telaps);
	virtual void drawAnimatedMesh(const CAnimatedMesh &animmesh, const sgxMatrix43 &transform);

	virtual void drawPrimitiveCuboidImpl(const sgxGfxCuboid &cuboid, const sgxMatrix43 &transform);
	virtual void drawPrimitiveCuboid(const CSGXTexture **pTextures, const sgxMatrix43 &transform, const sgxVector3 &minpos, const sgxVector3 &maxpos);
	virtual void drawPrimitiveSphereImpl(const sgxGfxSphere &sphere, const sgxMatrix43 &transform);
	virtual void drawLine3D(const sgxVector3 &from, const sgxVector3 &to);

	virtual void drawTriStrip(const CSGXTexture	*pTexture, const sgxVector<sgxPolyVtx> &vtx);
	virtual void drawQuadStrip(const CSGXTexture *pTexture, const sgxVector<sgxPolyVtx> &vtx);

	virtual void drawLine2D(const tINT32 fromX, const tINT32 fromY, const tINT32 toX, const tINT32 toY);
	virtual void drawLine2D(const sgxPoint2i &from, const sgxPoint2i &to);
	virtual void drawRect2D(const sgxPoint2i &from, const sgxPoint2i &to);

	virtual void drawRect2D(const tREAL32 x1, const tREAL32 y1, const tREAL32 x2, const tREAL32 y2, const tREAL32 x3, const tREAL32 y3, const tREAL32 x4, const tREAL32 y4);
	virtual void drawRect2D(const tPOINT x1, const tPOINT y1, const tPOINT x2, const tPOINT y2, const tPOINT x3, const tPOINT y3, const tPOINT x4, const tPOINT y4);

	virtual void drawPolygon2D(const sgxVector<sgxPoint2i> &ptList);

	virtual void drawSkyBox(const CSGXTexture **pTextures,const sgxMatrix43 &transform, const sgxVector3 &minpos, const sgxVector3 &maxpos);
	virtual void drawAlphaFaces();

	virtual void drawPolygonImpl(const sgxGfxPolygon &poly, const sgxMatrix43 &transform);
	virtual void drawAlphaPolygonImpl(const sgxGfxPolygon &poly, const sgxMatrix43 &transform);

	// Conversion
	virtual void convertPolygon(sgxGfxPolygon &mesh);
	virtual void convertAnimatedMesh(CAnimatedMesh &animmesh);

private:
	cb_pOpenGLIdleFunction	*m_pIdleCallback;
	tMEM_SIZE				m_iIdleParameter;
	sgxMatrixState			m_MatrixModeState;
	
	GLfloat					m_GLViewMatrix[16];
	GLfloat					m_GLProjectionMatrix[16];

	CSGXCamera				m_CurrentCamera;
	tBOOL					m_bPostIdleRender;

	//
	// OpenGL utility functions
	//
	GLenum	getOGLMode();
	void	prepareCallbacks();
	void	applyLighting();
};

#endif /* SGX_OPENGL_GRAPHICS_H */
