//-----------------------------------------------------------------------------------------------
// Renderer_OpenGL3.hpp
//
#pragma once
#ifndef INCLUDED_RENDERER_OPENGL3
#define INCLUDED_RENDERER_OPENGL3
#include "Core/PlatformDefines.hpp"
#if defined( GYPSY_ENABLE_RENDERER )

//-----------------------------------------------------------------------------------------------
#include "Renderer/Renderer.hpp"

#if defined( PLATFORM_WINDOWS )
#include "Core/PlatformSpecificHeaders.hpp" // FIXME: This is necessary under Win32 as their GL.h depends on Windows.h, even though this isn't OpenGL3_Win32.  Is there a cleaner way?
#include "Renderer/OpenGLExtensions.hpp" // FIXME: Can't call advanced OpenGL functions in Windows without this, but it'd be even worse if we move extensions into Renderer_OpenGL3_Win32!
#endif

#include <gl/GL.h>


/////////////////////////////////////////////////////////////////////////////////////////////////
class Texture_OpenGL3 : public Texture
{
protected:
	Texture_OpenGL3();
	virtual void PopulateFromFile( const char* imageFilePath, TextureFilterMode minFilter, TextureFilterMode magFilter, TextureEdgeMode edgeMode );
	virtual void PopulateFromData( unsigned char* imageData, const IntVector2& dimensions, int numChannels, TextureFilterMode minFilter, TextureFilterMode magFilter, TextureEdgeMode edgeMode );

protected:
public: // TEMP HACK FOR JAMS!
	GLuint			m_openglTextureID;

	friend class Renderer_OpenGL3;
};


/////////////////////////////////////////////////////////////////////////////////////////////////
class Renderer_OpenGL3 : public Renderer
{
public:
	friend class Texture_OpenGL3;

	virtual Texture* CreateTextureFromData( const char* internalTextureName, unsigned char* imageData, const IntVector2& dimensions, int numChannels, TextureFilterMode minFilter=TEXTURE_FILTER_LINEAR, TextureFilterMode magFilter=TEXTURE_FILTER_NEAREST, TextureEdgeMode edgeMode=TEXTURE_EDGE_REPEAT );
	virtual FramebufferObject* CreateFramebufferObject( const IntVector2& renderTargetTexelSize, TextureFilterMode minFilter = TEXTURE_FILTER_LINEAR, TextureFilterMode magFilter = TEXTURE_FILTER_LINEAR );
	virtual const char* GetAPIDescription() const;
	virtual void FlushAndFinish();

	virtual void ClearScreen( const Rgba& clearColor ) const;
	virtual void ClearDepth( float clearDepth ) const;
	virtual void ClearScreenAndDepth( const Rgba& clearColor, float clearDepth ) const;
	virtual void SetScreenVirtualOrtho( const Vector2& virtualScreenCoordsBottomLeft, const Vector2& virtualScreenCoordsTopRight );
	virtual void PushMatrix();
	virtual void PopMatrix();
	virtual void UseShaderProgram( const ShaderProgram* shaderProgram );
	virtual void UseFramebuffer( const FramebufferObject* framebufferObject );
	virtual void SetLineThickness( float lineThickness );
	virtual void BindTextureToSampler( const Texture* texture, int samplerIndex );

	virtual void Draw2dLineSegment( const Vector2& startPos, const Vector2& endPos, const Rgba& startColor, const Rgba& endColor );
	virtual void Draw2dDisc( const Vector2& center, float radius, float numSides, const Rgba& color );
	virtual void Draw2dDiscOutline( const Vector2& center, float radius, float numSides, const Rgba& color );
	virtual void Draw2dAABB( const Vector2& mins, const Vector2& maxs, const Rgba& color );
	virtual void Draw2dAABB( const AABB2& bounds, const Rgba& color );
	virtual void Draw2dTexturedAABB( const AABB2& bounds, const Vector2& texCoordsAtMins, const Vector2& texCoordsAtMaxs, const Rgba& tint, const Texture& texture );
	virtual void Draw2dConvexPoly( const Vector2& anchorPos, const Vector2* ccwVertexesRelativeToAnchor, int numVertexes, const Rgba& color );
	virtual void Draw2dTextStringAtPosition( const char* latinChars, const Vector2& textMins, float cellHeight, const Rgba& tint, BitmapFont* font );

protected:
	Renderer_OpenGL3();
	virtual ~Renderer_OpenGL3();
	virtual void DetermineCapabilityLevel();
	virtual bool DoesShaderUseGenericVertexAttribs( const char* shaderSource );
	virtual void CreateBuiltInShaders( RendererCapabilityLevel renderingCapabilityLevel );
	virtual const char* GetShaderFileExtension() const { return "glsl"; }
	virtual void GetLegalShaderVersionStringList( std::vector< std::string >& out_legalShaderVersionStrings );
	virtual Shader* CompileShader( const char* shaderSource, ShaderType shaderType, const std::string& shaderName, const std::string& shaderRelativePath, const std::string& shaderVersionString );
	virtual ShaderProgram* LinkShaderProgram( const Shader& vertexShader, const Shader& fragmentShader );
	virtual void __declspec( noreturn ) ReportShaderError( ShaderID shaderID, const char* shaderSource, ShaderType shaderType, const std::string& shaderName, const std::string& shaderFileName, const std::string& shaderRelativePath );
	virtual void __declspec( noreturn ) ReportShaderProgramError( ShaderProgramID programID, const Shader& vertexShader, const Shader& fragmentShader );
	GLenum GetOpenGLShaderTypeEnumForShaderType( ShaderType shaderType ) const;
	GLint GetOpenGLFilterEnumForFilterMode( TextureFilterMode filterMode ) const;
	GLint GetOpenGLEdgeEnumForEdgeMode( TextureEdgeMode edgeMode ) const;

protected:
	static const char* s_builtInShader_UnlitVertexGLSL110;
	static const char* s_builtInShader_UnlitVertexGLSL130;
	static const char* s_builtInShader_UnlitFragmentGLSL110;
	static const char* s_builtInShader_UnlitFragmentGLSL130;
};


#endif // GYPSY_ENABLE_RENDERER
#endif // INCLUDED_RENDERER_OPENGL3
