/*
	ZOpenGLSampler.hpp
	Author: James Russell <jcrussell@762studios.com>,
			Chris Ertel <crertel@762studios.com>
	Created: 7/1/2012

	Purpose: 

	OpenGL implementation of the ZSampler interface class.

	License:

	TODO

*/

#pragma once

#ifndef _ZOPENGLSAMPLER_HPP
#define _ZOPENGLSAMPLER_HPP

#include <ZUtil/ZUtil.hpp>

#include <ZRenderer/ZSamplerBase.hpp>

#include <SST/SST_GLAPI.h>

//Forward Declarations
class ZOpenGLRenderer;

struct ZOpenGLSamplerState
{
	GLenum SWrapMode;			//Wrapping mode for S
	GLenum TWrapMode;			//Wrapping mode for T (unused for 1D)
	GLenum RWrapMode;			//Wrapping mode for R (unused for 1D, 2D)

	GLenum MinFilter;			//Minification Filter (including mip filter)
	GLenum MagFilter;			//Magnification Filter

	float MaxAnisotropy;		//Maximum Anisotropy (< 2.0 has no effect)
	float MinLOD;				//Minimum LOD
	float MaxLOD;				//Maximum LOD
	float LODBias;				//LOD Bias

	float BorderColor[4];		//RGBA Border Color

	GLenum CompareMode;			//Sampler Comparison Mode
	GLenum CompareFunc;			//Sampler Comparison Function
};

//OpenGL implementation of the ZSampler interface class
class ZOpenGLSampler : public ZSamplerBase
{
private:
	DISABLE_COPY_AND_ASSIGN(ZOpenGLSampler);

protected:
	//The current renderer
	ZOpenGLRenderer* Renderer;
	
	//Sampler State
	ZOpenGLSamplerState OpenGLSamplerState;

public:
	//OpenGL Handle for the Sampler object
	GLuint GLHandle;

	//Gets the OpenGL Sampler State
	const ZOpenGLSamplerState& GetGLSamplerState()
	{
		switch (State.SWrapMode)
		{
		case ZSWM_CLAMP_EDGE:				OpenGLSamplerState.SWrapMode = GL_CLAMP_TO_EDGE;			break;
		case ZSWM_CLAMP_BORDER:				OpenGLSamplerState.SWrapMode = GL_CLAMP_TO_BORDER;			break;
		case ZSWM_MIRROR_REPEAT:			OpenGLSamplerState.SWrapMode = GL_MIRRORED_REPEAT;			break;
		case ZSWM_REPEAT:					OpenGLSamplerState.SWrapMode = GL_REPEAT;					break;
		default:							OpenGLSamplerState.SWrapMode = GL_INVALID_ENUM;				break;
		}

		switch (State.TWrapMode)
		{
		case ZSWM_CLAMP_EDGE:				OpenGLSamplerState.TWrapMode = GL_CLAMP_TO_EDGE;			break;
		case ZSWM_CLAMP_BORDER:				OpenGLSamplerState.TWrapMode = GL_CLAMP_TO_BORDER;			break;
		case ZSWM_MIRROR_REPEAT:			OpenGLSamplerState.TWrapMode = GL_MIRRORED_REPEAT;			break;
		case ZSWM_REPEAT:					OpenGLSamplerState.TWrapMode = GL_REPEAT;					break;
		default:							OpenGLSamplerState.TWrapMode = GL_INVALID_ENUM;				break;
		}

		switch (State.RWrapMode)
		{
		case ZSWM_CLAMP_EDGE:				OpenGLSamplerState.RWrapMode = GL_CLAMP_TO_EDGE;			break;
		case ZSWM_CLAMP_BORDER:				OpenGLSamplerState.RWrapMode = GL_CLAMP_TO_BORDER;			break;
		case ZSWM_MIRROR_REPEAT:			OpenGLSamplerState.RWrapMode = GL_MIRRORED_REPEAT;			break;
		case ZSWM_REPEAT:					OpenGLSamplerState.RWrapMode = GL_REPEAT;					break;
		default:							OpenGLSamplerState.RWrapMode = GL_INVALID_ENUM;				break;
		}

		switch(State.MagFilter)
		{
		case ZSMAGF_NEAREST:				OpenGLSamplerState.MagFilter = GL_NEAREST;					break;
		case ZSMAGF_LINEAR:					OpenGLSamplerState.MagFilter = GL_LINEAR;					break;
		default:							OpenGLSamplerState.MagFilter = GL_INVALID_ENUM;				break;
		}

		switch(State.MinFilter)
		{
		case ZSMINF_NEAREST:				OpenGLSamplerState.MinFilter = GL_NEAREST;					break;
		case ZSMINF_NEAREST_MIP_NEAREST:	OpenGLSamplerState.MinFilter = GL_NEAREST_MIPMAP_NEAREST;	break;
		case ZSMINF_NEAREST_MIP_LINEAR:		OpenGLSamplerState.MinFilter = GL_NEAREST_MIPMAP_LINEAR;	break;
		case ZSMINF_LINEAR:					OpenGLSamplerState.MinFilter = GL_LINEAR;					break;
		case ZSMINF_LINEAR_MIP_NEAREST:		OpenGLSamplerState.MinFilter = GL_LINEAR_MIPMAP_NEAREST;	break;
		case ZSMINF_LINEAR_MIP_LINEAR:		OpenGLSamplerState.MinFilter = GL_LINEAR_MIPMAP_LINEAR;		break;
		default:							OpenGLSamplerState.MinFilter = GL_INVALID_ENUM;				break;
		}

		OpenGLSamplerState.MaxAnisotropy =	State.MaxAnisotropy;
		OpenGLSamplerState.MinLOD =			State.MinLOD;
		OpenGLSamplerState.MaxLOD =			State.MaxLOD;
		OpenGLSamplerState.LODBias =		State.LODBias;

		OpenGLSamplerState.BorderColor[0] = State.BorderColor[0];
		OpenGLSamplerState.BorderColor[1] = State.BorderColor[1];
		OpenGLSamplerState.BorderColor[2] = State.BorderColor[2];
		OpenGLSamplerState.BorderColor[3] = State.BorderColor[3];

		switch(State.CompareMode)
		{
		case ZSCM_NONE:						OpenGLSamplerState.CompareMode = GL_NONE;					break;
		case ZSCM_COMPARE_REF_TO_TEXTURE:	OpenGLSamplerState.CompareMode = GL_COMPARE_REF_TO_TEXTURE;	break;
		default:							OpenGLSamplerState.CompareMode = GL_INVALID_ENUM;			break;
		}

		switch(State.CompareFunc)
		{
		case ZSCF_NEVER:					OpenGLSamplerState.CompareFunc = GL_NEVER;					break;
		case ZSCF_ALWAYS:					OpenGLSamplerState.CompareFunc = GL_ALWAYS;					break;
		case ZSCF_EQUAL:					OpenGLSamplerState.CompareFunc = GL_EQUAL;					break;
		case ZSCF_NOT_EQUAL:				OpenGLSamplerState.CompareFunc = GL_NOTEQUAL;				break;
		case ZSCF_LESS:						OpenGLSamplerState.CompareFunc = GL_LESS;					break;
		case ZSCF_LESS_EQUAL:				OpenGLSamplerState.CompareFunc = GL_LEQUAL;					break;
		case ZSCF_GREATER:					OpenGLSamplerState.CompareFunc = GL_GREATER;				break;
		case ZSCF_GREATER_EQUAL:			OpenGLSamplerState.CompareFunc = GL_GEQUAL;					break;
		default:							OpenGLSamplerState.CompareFunc = GL_INVALID_ENUM;			break;
		}

		return OpenGLSamplerState;
	}

	/*
	Default Constructor.
	*/
	ZOpenGLSampler(ZOpenGLRenderer* _renderer);

	/*
	Destructor.
	*/
	~ZOpenGLSampler();
};


#endif
 
