/*
	ZSampler.hpp
	Author: James Russell <jcrussell@762studios.com>
	Created: 7/1/2012

	Purpose: 

	Samplers act as a view onto a texture object, encapsulating all the filtering, mipmapping,
	and addressing settings for shaders to access a texture.

	TODO - A writeup here on the various settings and how they interact, or at least a link to
	some place that does

	License:

	TODO

*/

#pragma once

#ifndef _ZSAMPLER_HPP
#define _ZSAMPLER_HPP

#include <ZRenderer/ZRendererBuild.hpp>
#include <ZRenderer/ZRendererResource.hpp>

//This should be ~log2 of ZT_MAX_TEXTURE_DIMENSION
#ifndef ZS_DEFAULT_MAX_LOD
#define ZS_DEFAULT_MAX_LOD (13.0f)
#endif

//Enumeration of sampler wrapping modes
enum ZSamplerWrapMode
{
	ZSWM_CLAMP_EDGE,		//Sampling beyond the edge results in the last pixel value
	ZSWM_CLAMP_BORDER,		//Sampling beyond the edge results in the specified border value
	ZSWM_MIRROR_REPEAT,		//Sampling beyond the edge wraps back in on itself
	ZSWM_REPEAT,			//Sampling beyond the edge wraps around to the other side
	ZSWM_SIZE
};

//Enumeration of magnification sampler filtering modes
enum ZSamplerMagFilter
{
	ZSMAGF_NEAREST,			//Nearest mode filter
	ZSMAGF_LINEAR,			//Linear mode filter
	ZSMAGF_SIZE
};

//Enumeration of minification sampler filtering modes
enum ZSamplerMinFilter
{
	ZSMINF_NEAREST,				//Nearest-neighbor pixel, no mip levels
	ZSMINF_NEAREST_MIP_NEAREST,	//Nearest-neighbor sampling on nearest mip level
	ZSMINF_NEAREST_MIP_LINEAR,	//Nearest-neighbor sampling on lerped mip level
	ZSMINF_LINEAR,				//Linear interpolation, no mip levels
	ZSMINF_LINEAR_MIP_NEAREST,	//Lerped sampling on nearest mip level
	ZSMINF_LINEAR_MIP_LINEAR,	//Lerped sampling on lerped mip level
	ZSMINF_SIZE
};

//Enumeration of sampler comparison modes
enum ZSamplerCompareMode
{
	ZSCM_COMPARE_REF_TO_TEXTURE,	//Compares reference to texture
	ZSCM_NONE,						//No comparison
	ZSCM_SIZE
};

//Enumeration of sampler comparison functions
enum ZSamplerCompareFunc
{
	ZSCF_LESS_EQUAL,				//Less than or equal
	ZSCF_GREATER_EQUAL,				//Greater than or equal
	ZSCF_LESS,						//Less than
	ZSCF_GREATER,					//Greater than
	ZSCF_EQUAL,						//Equal
	ZSCF_NOT_EQUAL,					//Not Equal
	ZSCF_ALWAYS,					//Always
	ZSCF_NEVER,						//Never
	ZSCF_SIZE
};

//Struct that encapsulates the sampler state
struct ZSamplerState
{
	ZSamplerWrapMode SWrapMode;			//Wrapping mode for S
	ZSamplerWrapMode TWrapMode;			//Wrapping mode for T (unused for 1D)
	ZSamplerWrapMode RWrapMode;			//Wrapping mode for R (unused for 1D, 2D)
	
	ZSamplerMinFilter MinFilter;		//Minification Filter
	ZSamplerMagFilter 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

	ZSamplerCompareMode CompareMode;	//Sampler Comparison Mode
	ZSamplerCompareFunc CompareFunc;	//Sampler Comparison Function

	//Default Configuration
	ZSamplerState() 
		: SWrapMode(ZSWM_REPEAT), TWrapMode(ZSWM_REPEAT), RWrapMode(ZSWM_REPEAT),
		  MinFilter(ZSMINF_LINEAR), MagFilter(ZSMAGF_LINEAR),
		  MaxAnisotropy(1.0), MinLOD(0), MaxLOD(ZS_DEFAULT_MAX_LOD), LODBias(0),
		  CompareMode(ZSCM_NONE), CompareFunc(ZSCF_ALWAYS) 
	{ }
};

/*
Sampler interface class.
*/
class ZSampler : public ZRendererResource
{
public:
	//Virtual Destructor
	virtual ~ZSampler() { }

	/*
	ZSampler::Get*

	The following methods are getters for the various ZSampler settings 
	that can be set on a given sampler.  For a greater explanation of each
	setting and what it does, see above.
	*/

	//Getters for the S, T, and R Wrap Mode set on this sampler
	virtual ZSamplerWrapMode GetSWrapMode() = 0;	
	virtual ZSamplerWrapMode GetTWrapMode() = 0;
	virtual ZSamplerWrapMode GetRWrapMode() = 0;

	//Getters for the minification filter and magnification filter
	virtual ZSamplerMagFilter GetMagFilter() = 0;
	virtual ZSamplerMinFilter GetMinFilter() = 0;

	//Getters for the maximum anisotropy, minimum LOD, maximum LOD, and LOD bias
	virtual float GetMaxAnisotropy() = 0;
	virtual float GetMinLOD() = 0;
	virtual float GetMaxLOD() = 0;
	virtual float GetLODBias() = 0;

	//Getter for the border color setting (four-element array, RGBA)
	virtual const float* GetBorderColor() = 0;

	//Getter for the comparison mode and comparison function
	virtual ZSamplerCompareMode GetCompareMode() = 0;
	virtual ZSamplerCompareFunc GetCompareFunc() = 0;

	//Getter for the entire sampler state
	virtual const ZSamplerState& GetSamplerState() = 0;

	/*
	ZSampler::Set*

	The following methods are setters for the various ZSampler settings than
	can be set on a given sampler.  For a greater explanation of each setting and what it 
	does, see above.

	If any of the setters returns false, it is because the resource is contended.
	*/

	//Setters for the S, T, and R wrapping modes
	virtual bool SetSWrapMode(ZSamplerWrapMode _mode) = 0;
	virtual bool SetTWrapMode(ZSamplerWrapMode _mode) = 0;
	virtual bool SetRWrapMode(ZSamplerWrapMode _mode) = 0;

	//Setters for the minification and magnification filter
	virtual bool SetMagFilter(ZSamplerMagFilter _filter) = 0;
	virtual bool SetMinFilter(ZSamplerMinFilter _filter) = 0;

	//Setters for maximum anisotropy, minimum LOD, maximum LOD, and LOD bias
	virtual bool SetMaxAnisotropy(float _max) = 0;
	virtual bool SetMinLOD(float _min) = 0;
	virtual bool SetMaxLOD(float _max) = 0;
	virtual bool SetLODBias(float _bias) = 0;

	//Setter for border color 
	virtual bool SetBorderColor(float _r, float _g, float _b, float _a) = 0;

	//Setter for comparison mode and comparison function
	virtual bool SetCompareMode(ZSamplerCompareMode _mode) = 0;
	virtual bool SetCompareFunc(ZSamplerCompareFunc _func) = 0;

	//Setter for entire sampler state
	virtual bool SetSamplerState(const ZSamplerState& _state) = 0;
};

#endif 
