/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


		#include "core/texture_parm.h"
		#include "core/render_data.h"
		#include "picture/pict.h"
		#include "metafile/nml.h"
		#include "metafile/nml_object.h"
		#include "reflection/c_refl.h"
		#include "log/log.h"

		using namespace GS;
		using namespace GS::Render;
		using namespace GS::Reflection;


//------------------------------------------------------------------------------
const char			*TextureParm::GetSwizzleFlags(Swizzle swizzle)
{
	static char RGBA[4] = { 0, 1, 2, 3 };
	static char BGRA[4] = { 2, 1, 0, 3 };
	static char ARGB[4] = { 3, 0, 1, 2 };
	static char ABGR[4] = { 3, 2, 1, 0 };
	static char XYZ[4] = { 0, 1, 2, 3 };
	static char XZY[4] = { 0, 2, 1, 3 };
	static char YXZ[4] = { 1, 0, 2, 3 };
	static char YZX[4] = { 1, 2, 0, 3 };
	static char ZXY[4] = { 2, 0, 1, 3 };
	static char ZYX[4] = { 2, 1, 0, 3 };

	switch (swizzle)
	{
		default:
			break;

		case SwizzleRGBA:	return RGBA;
		case SwizzleBGRA:	return BGRA;
		case SwizzleARGB:	return ARGB;
		case SwizzleABGR:	return ABGR;
		case SwizzleXYZ:	return XYZ;
		case SwizzleXZY:	return XZY;
		case SwizzleYXZ:	return YXZ;
		case SwizzleYZX:	return YZX;
		case SwizzleZXY:	return ZXY;
		case SwizzleZYX:	return ZYX;
	}
	return RGBA;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void				TextureParm::Apply(Picture &p) const
{
	const char *f = GetSwizzleFlags(swizzle);
	p.Swizzle(f[0], f[1], f[2], f[3]);
	p.Negative(invert[0], invert[1], invert[2], invert[3]);
	p.Flip(flip[0], flip[1]);
}
void				TextureParm::Apply(Texture &t) const
{
	t.SetFiltering(filtering);
	t.SetAnisotropy(anisotropy);
	t.SetWrapping(wrap_u, wrap_v);

	// Note: LOD bias is done per texture stage.
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
Enum::Dict TextureParm::filtering_dict[] =
{
	{ TextureParm::FilterDefault, "Default" },
	{ TextureParm::FilterNearest, "Nearest" },
	{ TextureParm::FilterBilinear, "Bilinear" },
	{ TextureParm::FilterTrilinear, "Trilinear" },
	{ 0, 0 }
};
Enum::Dict TextureParm::anisotropic_dict[] =
{
	{ TextureParm::AnisotropyDefault, "Default" },
	{ TextureParm::AnisotropyNone, "None" },
	{ TextureParm::Anisotropy2x, "2x" },
	{ TextureParm::Anisotropy4x, "4x" },
	{ TextureParm::Anisotropy8x, "8x" },
	{ TextureParm::Anisotropy16x, "16x" },
	{ 0, 0 }
};
Enum::Dict TextureParm::wrap_dict[] =
{
	{ TextureParm::WrapDefault, "Default" },
	{ TextureParm::WrapRepeat, "Repeat" },
	{ TextureParm::WrapClamp, "Clamp" },
	{ 0, 0 }
};
Enum::Dict TextureParm::swizzle_dict[] =
{
	{ TextureParm::SwizzleRGBA, "RGBA" },
	{ TextureParm::SwizzleBGRA, "BGRA" },
	{ TextureParm::SwizzleARGB, "ARGB" },
	{ TextureParm::SwizzleABGR, "ABGR" },
	{ TextureParm::SwizzleXYZ, "XYZ" },
	{ TextureParm::SwizzleXZY, "XZY" },
	{ TextureParm::SwizzleYXZ, "YXZ" },
	{ TextureParm::SwizzleYZX, "YZX" },
	{ TextureParm::SwizzleZXY, "ZXY" },
	{ TextureParm::SwizzleZYX, "ZYX" },
	{ 0, 0 }
};
Property	TextureParm::serializable[] =
{
	{ Property::EnumProp, "WrapU", offsetof(TextureParm, wrap_u), wrap_dict },
	{ Property::EnumProp, "WrapV", offsetof(TextureParm, wrap_v), wrap_dict },
	{ Property::EnumProp, "Filtering", offsetof(TextureParm, filtering), filtering_dict },
	{ Property::EnumProp, "Anisotropy", offsetof(TextureParm, anisotropy), anisotropic_dict },
	{ Property::EnumProp, "Swizzle", offsetof(TextureParm, swizzle), swizzle_dict },
	{ Property::BoolProp, "InvertR", offsetof(TextureParm, invert[0]), NULL },
	{ Property::BoolProp, "InvertG", offsetof(TextureParm, invert[1]), NULL },
	{ Property::BoolProp, "InvertB", offsetof(TextureParm, invert[2]), NULL },
	{ Property::BoolProp, "InvertA", offsetof(TextureParm, invert[3]), NULL },
	{ Property::BoolProp, "FlipU", offsetof(TextureParm, flip[0]), NULL },
	{ Property::BoolProp, "FlipV", offsetof(TextureParm, flip[1]), NULL },
	{ Property::FloatProp, "LODBias", offsetof(TextureParm, lod_bias), NULL },

	{ Property::InvalidProp, 0, 0 }
};
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
String				TextureParm::GetParmFileName(const char *uri)
{	return String::Format("%s.parm", uri);	}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
bool				TextureParm::FromMetaTag(NML::Tag &t)
{	return t.name == "TextureParm" ? GenericObjectFromMetaTag(t, this, serializable) : false;	}
NML::Tag			*TextureParm::AsMetaTag() const
{	return NML::GenericObjectToMetaTag(new NML::Tag("TextureParm"), this, serializable);	}
//------------------------------------------------------------------------------
