/*-------------------------------------------------------------------------
 * drawElements Quality Program EGL Module
 * ---------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Choose config reference implementation.
 *//*--------------------------------------------------------------------*/

#include "teglChooseConfigReference.hpp"

#include "egluUtil.hpp"
#include "egluConfigInfo.hpp"
#include "egluStrUtil.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"

#include <algorithm>
#include <vector>
#include <map>

namespace deqp
{
namespace egl
{

using namespace eglw;
using eglu::ConfigInfo;

enum Criteria
{
	CRITERIA_AT_LEAST = 0,
	CRITERIA_EXACT,
	CRITERIA_MASK,
	CRITERIA_SPECIAL,

	CRITERIA_LAST
};

enum SortOrder
{
	SORTORDER_NONE	= 0,
	SORTORDER_SMALLER,
	SORTORDER_SPECIAL,

	SORTORDER_LAST
};

struct AttribRule
{
	EGLenum		name;
	EGLint		value;
	Criteria	criteria;
	SortOrder	sortOrder;

	AttribRule (void)
		: name			(EGL_NONE)
		, value			(EGL_NONE)
		, criteria		(CRITERIA_LAST)
		, sortOrder		(SORTORDER_LAST)
	{
	}

	AttribRule (EGLenum name_, EGLint value_, Criteria criteria_, SortOrder sortOrder_)
		: name			(name_)
		, value			(value_)
		, criteria		(criteria_)
		, sortOrder		(sortOrder_)
	{
	}
};

class SurfaceConfig
{
private:
	static int getCaveatRank (EGLenum caveat)
	{
		switch (caveat)
		{
			case EGL_NONE:					return 0;
			case EGL_SLOW_CONFIG:			return 1;
			case EGL_NON_CONFORMANT_CONFIG:	return 2;
			default:
				TCU_THROW(TestError, (std::string("Unknown config caveat: ") + eglu::getConfigCaveatStr(caveat).toString()).c_str());
		}
	}

	static int getColorBufferTypeRank (EGLenum type)
	{
		switch (type)
		{
			case EGL_RGB_BUFFER:			return 0;
			case EGL_LUMINANCE_BUFFER:		return 1;
			case EGL_YUV_BUFFER_EXT:		return 2;
			default:
				TCU_THROW(TestError, (std::string("Unknown color buffer type: ") + eglu::getColorBufferTypeStr(type).toString()).c_str());
		}
	}

	typedef bool (*CompareFunc) (const SurfaceConfig& a, const SurfaceConfig& b);

	static bool compareCaveat (const SurfaceConfig& a, const SurfaceConfig& b)
	{
		return getCaveatRank((EGLenum)a.m_info.configCaveat) < getCaveatRank((EGLenum)b.m_info.configCaveat);
	}

	static bool compareColorBufferType (const SurfaceConfig& a, const SurfaceConfig& b)
	{
		return getColorBufferTypeRank((EGLenum)a.m_info.colorBufferType) < getColorBufferTypeRank((EGLenum)b.m_info.colorBufferType);
	}

	static bool compareColorBufferBits (const SurfaceConfig& a, const SurfaceConfig& b, const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors)
	{
		DE_ASSERT(a.m_info.colorBufferType == b.m_info.colorBufferType);
		switch (a.m_info.colorBufferType)
		{
			case EGL_RGB_BUFFER:
			{
				const tcu::IVec4	mask	(specifiedRGBColors.cast<deInt32>());

				return (a.m_info.redSize * mask[0] + a.m_info.greenSize * mask[1] + a.m_info.blueSize * mask[2] + a.m_info.alphaSize * mask[3])
						> (b.m_info.redSize * mask[0] + b.m_info.greenSize * mask[1] + b.m_info.blueSize * mask[2] + b.m_info.alphaSize * mask[3]);
			}

			case EGL_LUMINANCE_BUFFER:
			{
				const tcu::IVec2	mask	(specifiedLuminanceColors.cast<deInt32>());

				return (a.m_info.luminanceSize * mask[0] + a.m_info.alphaSize * mask[1]) > (b.m_info.luminanceSize * mask[0] + b.m_info.alphaSize * mask[1]);
			}

			case EGL_YUV_BUFFER_EXT:
				// \todo [mika 2015-05-05] Sort YUV configs correctly. Currently all YUV configs are non-conformant and ordering can be relaxed.
				return true;

			default:
				DE_ASSERT(DE_FALSE);
				return true;
		}
	}

	template <EGLenum Attribute>
	static bool compareAttributeSmaller (const SurfaceConfig& a, const SurfaceConfig& b)
	{
		return a.getAttribute(Attribute) < b.getAttribute(Attribute);
	}
public:
	SurfaceConfig (EGLConfig config, ConfigInfo &info)
		: m_config(config)
		, m_info(info)
	{
	}

	EGLConfig getEglConfig (void) const
	{
		return m_config;
	}

	EGLint getAttribute (const EGLenum attribute) const
	{
		return m_info.getAttribute(attribute);
	}

	friend bool operator== (const SurfaceConfig& a, const SurfaceConfig& b)
	{
		for (std::map<EGLenum, AttribRule>::const_iterator iter = SurfaceConfig::defaultRules.begin(); iter != SurfaceConfig::defaultRules.end(); iter++)
		{
			const EGLenum attribute = iter->first;

			if (a.getAttribute(attribute) != b.getAttribute(attribute)) return false;
		}
		return true;
	}

	bool compareTo (const SurfaceConfig& b, const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors) const
	{
		static const SurfaceConfig::CompareFunc compareFuncs[] =
		{
			SurfaceConfig::compareCaveat,
			SurfaceConfig::compareColorBufferType,
			DE_NULL, // SurfaceConfig::compareColorBufferBits,
			SurfaceConfig::compareAttributeSmaller<EGL_BUFFER_SIZE>,
			SurfaceConfig::compareAttributeSmaller<EGL_SAMPLE_BUFFERS>,
			SurfaceConfig::compareAttributeSmaller<EGL_SAMPLES>,
			SurfaceConfig::compareAttributeSmaller<EGL_DEPTH_SIZE>,
			SurfaceConfig::compareAttributeSmaller<EGL_STENCIL_SIZE>,
			SurfaceConfig::compareAttributeSmaller<EGL_ALPHA_MASK_SIZE>,
			SurfaceConfig::compareAttributeSmaller<EGL_CONFIG_ID>
		};

		if (*this == b)
			return false; // std::sort() can compare object to itself.

		for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(compareFuncs); ndx++)
		{
			if (!compareFuncs[ndx])
			{
				if (compareColorBufferBits(*this, b, specifiedRGBColors, specifiedLuminanceColors))
					return true;
				else if (compareColorBufferBits(b, *this, specifiedRGBColors, specifiedLuminanceColors))
					return false;

				continue;
			}

			if (compareFuncs[ndx](*this, b))
				return true;
			else if (compareFuncs[ndx](b, *this))
				return false;
		}

		TCU_FAIL("Unable to compare configs - duplicate ID?");
	}

	static const std::map<EGLenum, AttribRule> defaultRules;

	static std::map<EGLenum, AttribRule> initAttribRules (void)
	{
		// \todo [2011-03-24 pyry] From EGL 1.4 spec - check that this is valid for other versions as well
		std::map<EGLenum, AttribRule> rules;

		//									Attribute									Default				Selection Criteria	Sort Order			Sort Priority
		rules[EGL_BUFFER_SIZE]				= AttribRule(EGL_BUFFER_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	4
		rules[EGL_RED_SIZE]					= AttribRule(EGL_RED_SIZE,					0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
		rules[EGL_GREEN_SIZE]				= AttribRule(EGL_GREEN_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
		rules[EGL_BLUE_SIZE]				= AttribRule(EGL_BLUE_SIZE,					0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
		rules[EGL_LUMINANCE_SIZE]			= AttribRule(EGL_LUMINANCE_SIZE,			0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
		rules[EGL_ALPHA_SIZE]				= AttribRule(EGL_ALPHA_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
		rules[EGL_ALPHA_MASK_SIZE]			= AttribRule(EGL_ALPHA_MASK_SIZE,			0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	9
		rules[EGL_BIND_TO_TEXTURE_RGB]		= AttribRule(EGL_BIND_TO_TEXTURE_RGB,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
		rules[EGL_BIND_TO_TEXTURE_RGBA]		= AttribRule(EGL_BIND_TO_TEXTURE_RGBA,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
		rules[EGL_COLOR_BUFFER_TYPE]		= AttribRule(EGL_COLOR_BUFFER_TYPE,			EGL_RGB_BUFFER,		CRITERIA_EXACT,		SORTORDER_NONE);	//	2
		rules[EGL_CONFIG_CAVEAT]			= AttribRule(EGL_CONFIG_CAVEAT,				EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_SPECIAL);	//	1
		rules[EGL_CONFIG_ID]				= AttribRule(EGL_CONFIG_ID,					EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_SMALLER);	//	11
		rules[EGL_CONFORMANT]				= AttribRule(EGL_CONFORMANT,				0,					CRITERIA_MASK,		SORTORDER_NONE);
		rules[EGL_DEPTH_SIZE]				= AttribRule(EGL_DEPTH_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	7
		rules[EGL_LEVEL]					= AttribRule(EGL_LEVEL,						0,					CRITERIA_EXACT,		SORTORDER_NONE);
		rules[EGL_MATCH_NATIVE_PIXMAP]		= AttribRule(EGL_MATCH_NATIVE_PIXMAP,		EGL_NONE,			CRITERIA_SPECIAL,	SORTORDER_NONE);
		rules[EGL_MAX_SWAP_INTERVAL]		= AttribRule(EGL_MAX_SWAP_INTERVAL,			EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
		rules[EGL_MIN_SWAP_INTERVAL]		= AttribRule(EGL_MIN_SWAP_INTERVAL,			EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
		rules[EGL_NATIVE_RENDERABLE]		= AttribRule(EGL_NATIVE_RENDERABLE,			EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
		rules[EGL_NATIVE_VISUAL_TYPE]		= AttribRule(EGL_NATIVE_VISUAL_TYPE,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_SPECIAL);	//	10
		rules[EGL_RENDERABLE_TYPE]			= AttribRule(EGL_RENDERABLE_TYPE,			EGL_OPENGL_ES_BIT,	CRITERIA_MASK,		SORTORDER_NONE);
		rules[EGL_SAMPLE_BUFFERS]			= AttribRule(EGL_SAMPLE_BUFFERS,			0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	5
		rules[EGL_SAMPLES]					= AttribRule(EGL_SAMPLES,					0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	6
		rules[EGL_STENCIL_SIZE]				= AttribRule(EGL_STENCIL_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	8
		rules[EGL_SURFACE_TYPE]				= AttribRule(EGL_SURFACE_TYPE,				EGL_WINDOW_BIT,		CRITERIA_MASK,		SORTORDER_NONE);
		rules[EGL_TRANSPARENT_TYPE]			= AttribRule(EGL_TRANSPARENT_TYPE,			EGL_NONE,			CRITERIA_EXACT,		SORTORDER_NONE);
		rules[EGL_TRANSPARENT_RED_VALUE]	= AttribRule(EGL_TRANSPARENT_RED_VALUE,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
		rules[EGL_TRANSPARENT_GREEN_VALUE]	= AttribRule(EGL_TRANSPARENT_GREEN_VALUE,	EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
		rules[EGL_TRANSPARENT_BLUE_VALUE]	= AttribRule(EGL_TRANSPARENT_BLUE_VALUE,	EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);

		return rules;
	}
private:
	EGLConfig m_config;
	ConfigInfo m_info;
};

const std::map<EGLenum, AttribRule> SurfaceConfig::defaultRules = SurfaceConfig::initAttribRules();

class CompareConfigs
{
public:
	CompareConfigs (const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors)
		: m_specifiedRGBColors			(specifiedRGBColors)
		, m_specifiedLuminanceColors	(specifiedLuminanceColors)
	{
	}

	bool operator() (const SurfaceConfig& a, const SurfaceConfig& b)
	{
		return a.compareTo(b, m_specifiedRGBColors, m_specifiedLuminanceColors);
	}

private:
	const tcu::BVec4	m_specifiedRGBColors;
	const tcu::BVec2	m_specifiedLuminanceColors;
};

class ConfigFilter
{
private:
	std::map<EGLenum, AttribRule> m_rules;
public:
	ConfigFilter ()
		: m_rules(SurfaceConfig::defaultRules)
	{
	}

	void setValue (EGLenum name, EGLint value)
	{
		DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end());
		m_rules[name].value = value;
	}

	void setValues (std::vector<std::pair<EGLenum, EGLint> > values)
	{
		for (size_t ndx = 0; ndx < values.size(); ndx++)
		{
			const EGLenum	name	= values[ndx].first;
			const EGLint	value	= values[ndx].second;

			setValue(name, value);
		}
	}

	AttribRule getAttribute (EGLenum name)
	{
		DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end());
		return m_rules[name];
	}

	bool isMatch (const SurfaceConfig& config)
	{
		for (std::map<EGLenum, AttribRule>::const_iterator iter = m_rules.begin(); iter != m_rules.end(); iter++)
		{
			const AttribRule rule = iter->second;

			if (rule.value == EGL_DONT_CARE)
				continue;
			else if (rule.name == EGL_MATCH_NATIVE_PIXMAP)
				TCU_CHECK(rule.value == EGL_NONE); // Not supported
			else if (rule.name == EGL_TRANSPARENT_RED_VALUE || rule.name == EGL_TRANSPARENT_GREEN_VALUE || rule.name == EGL_TRANSPARENT_BLUE_VALUE)
				continue;
			else
			{
				const EGLint cfgValue = config.getAttribute(rule.name);

				switch (rule.criteria)
				{
					case CRITERIA_EXACT:
						if (rule.value != cfgValue)
							return false;
						break;

					case CRITERIA_AT_LEAST:
						if (rule.value > cfgValue)
							return false;
						break;

					case CRITERIA_MASK:
						if ((rule.value & cfgValue) != rule.value)
							return false;
						break;

					default:
						TCU_FAIL("Unknown criteria");
				}
			}
		}

		return true;
	}

	tcu::BVec4 getSpecifiedRGBColors (void)
	{
		const EGLenum bitAttribs[] =
		{
			EGL_RED_SIZE,
			EGL_GREEN_SIZE,
			EGL_BLUE_SIZE,
			EGL_ALPHA_SIZE
		};

		tcu::BVec4 result;

		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bitAttribs); ndx++)
		{
			const EGLenum	attrib	= bitAttribs[ndx];
			const EGLint	value	= getAttribute(attrib).value;

			if (value != 0 && value != EGL_DONT_CARE)
				result[ndx] = true;
			else
				result[ndx] = false;
		}

		return result;
	}

	tcu::BVec2 getSpecifiedLuminanceColors (void)
	{
		const EGLenum bitAttribs[] =
		{
			EGL_LUMINANCE_SIZE,
			EGL_ALPHA_SIZE
		};

		tcu::BVec2 result;

		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bitAttribs); ndx++)
		{
			const EGLenum	attrib	= bitAttribs[ndx];
			const EGLint	value	= getAttribute(attrib).value;

			if (value != 0 && value != EGL_DONT_CARE)
				result[ndx] = true;
			else
				result[ndx] = false;
		}

		return result;
	}

	std::vector<SurfaceConfig> filter (const std::vector<SurfaceConfig>& configs)
	{
		std::vector<SurfaceConfig> out;

		for (std::vector<SurfaceConfig>::const_iterator iter = configs.begin(); iter != configs.end(); iter++)
		{
			if (isMatch(*iter)) out.push_back(*iter);
		}

		return out;
	}
};

void chooseConfigReference (const Library& egl, EGLDisplay display, std::vector<EGLConfig>& dst, const std::vector<std::pair<EGLenum, EGLint> >& attributes)
{
	// Get all configs
	std::vector<EGLConfig> eglConfigs = eglu::getConfigs(egl, display);

	// Config infos
	std::vector<ConfigInfo> configInfos;
	configInfos.resize(eglConfigs.size());
	for (size_t ndx = 0; ndx < eglConfigs.size(); ndx++)
		eglu::queryConfigInfo(egl, display, eglConfigs[ndx], &configInfos[ndx]);

	// Pair configs with info
	std::vector<SurfaceConfig> configs;
	for (size_t ndx = 0; ndx < eglConfigs.size(); ndx++)
		configs.push_back(SurfaceConfig(eglConfigs[ndx], configInfos[ndx]));

	// Filter configs
	ConfigFilter configFilter;
	configFilter.setValues(attributes);

	std::vector<SurfaceConfig> filteredConfigs = configFilter.filter(configs);

	// Sort configs
	std::sort(filteredConfigs.begin(), filteredConfigs.end(), CompareConfigs(configFilter.getSpecifiedRGBColors(), configFilter.getSpecifiedLuminanceColors()));

	// Write to dst list
	dst.resize(filteredConfigs.size());
	for (size_t ndx = 0; ndx < filteredConfigs.size(); ndx++)
		dst[ndx] = filteredConfigs[ndx].getEglConfig();
}

} // egl
} // deqp
