Import dEQP.

Import drawElements Quality Program from an internal repository.

Bug: 17388917
Change-Id: Ic109fe4a57e31b2a816113d90fbdf51a43e7abeb
diff --git a/framework/randomshaders/rsgBuiltinFunctions.hpp b/framework/randomshaders/rsgBuiltinFunctions.hpp
new file mode 100644
index 0000000..1a6be3c
--- /dev/null
+++ b/framework/randomshaders/rsgBuiltinFunctions.hpp
@@ -0,0 +1,619 @@
+#ifndef _RSGBUILTINFUNCTIONS_HPP
+#define _RSGBUILTINFUNCTIONS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Random Shader Generator
+ * ----------------------------------------------------
+ *
+ * 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 Built-in Functions.
+ *//*--------------------------------------------------------------------*/
+
+#include "rsgDefs.hpp"
+#include "rsgExpression.hpp"
+#include "rsgUtils.hpp"
+#include "deMath.h"
+
+namespace rsg
+{
+
+// Template for built-in functions with form "GenType func(GenType val)".
+template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
+class UnaryBuiltinVecFunc : public Expression
+{
+public:
+								UnaryBuiltinVecFunc		(GeneratorState& state, const char* function, ConstValueRangeAccess valueRange);
+	virtual						~UnaryBuiltinVecFunc	(void);
+
+	Expression*					createNextChild			(GeneratorState& state);
+	void						tokenize				(GeneratorState& state, TokenStream& str) const;
+
+	void						evaluate				(ExecutionContext& execCtx);
+	ExecConstValueAccess		getValue				(void) const { return m_value.getValue(m_inValueRange.getType()); }
+
+	static float				getWeight				(const GeneratorState& state, ConstValueRangeAccess valueRange);
+
+private:
+	std::string					m_function;
+	ValueRange					m_inValueRange;
+	ExecValueStorage			m_value;
+	Expression*					m_child;
+};
+
+template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
+UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::UnaryBuiltinVecFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
+	: m_function		(function)
+	, m_inValueRange	(valueRange.getType())
+	, m_child			(DE_NULL)
+{
+	DE_UNREF(state);
+	DE_ASSERT(valueRange.getType().isFloatOrVec());
+
+	m_value.setStorage(valueRange.getType());
+
+	// Compute input value range
+	for (int ndx = 0; ndx < m_inValueRange.getType().getNumElements(); ndx++)
+	{
+		ConstValueRangeAccess	outRange	= valueRange.component(ndx);
+		ValueRangeAccess		inRange		= m_inValueRange.asAccess().component(ndx);
+
+		ComputeValueRange()(outRange.getMin().asFloat(), outRange.getMax().asFloat(), inRange.getMin().asFloat(), inRange.getMax().asFloat());
+	}
+}
+
+template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
+UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::~UnaryBuiltinVecFunc (void)
+{
+	delete m_child;
+}
+
+template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
+Expression* UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::createNextChild (GeneratorState& state)
+{
+	if (m_child)
+		return DE_NULL;
+
+	m_child = Expression::createRandom(state, m_inValueRange);
+	return m_child;
+}
+
+template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
+void UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::tokenize (GeneratorState& state, TokenStream& str) const
+{
+	str << Token(m_function.c_str()) << Token::LEFT_PAREN;
+	m_child->tokenize(state, str);
+	str << Token::RIGHT_PAREN;
+}
+
+template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
+void UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::evaluate (ExecutionContext& execCtx)
+{
+	m_child->evaluate(execCtx);
+
+	ExecConstValueAccess	srcValue	= m_child->getValue();
+	ExecValueAccess			dstValue	= m_value.getValue(m_inValueRange.getType());
+
+	for (int elemNdx = 0; elemNdx < m_inValueRange.getType().getNumElements(); elemNdx++)
+	{
+		ExecConstValueAccess	srcComp		= srcValue.component(elemNdx);
+		ExecValueAccess			dstComp		= dstValue.component(elemNdx);
+
+		for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
+			dstComp.asFloat(compNdx) = Evaluate()(srcComp.asFloat(compNdx));
+	}
+}
+
+template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
+float UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
+{
+	// \todo [2011-06-14 pyry] Void support?
+	if (!valueRange.getType().isFloatOrVec())
+		return 0.0f;
+
+	int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();
+
+	if (availableLevels < getConservativeValueExprDepth(state, valueRange) + 1)
+		return 0.0f;
+
+	// Compute value range weight
+	float combinedWeight = 1.0f;
+	for (int elemNdx = 0; elemNdx < valueRange.getType().getNumElements(); elemNdx++)
+	{
+		float elemWeight = GetValueRangeWeight()(valueRange.component(elemNdx).getMin().asFloat(), valueRange.component(elemNdx).getMax().asFloat());
+		combinedWeight *= elemWeight;
+	}
+
+	return combinedWeight;
+}
+
+// Proxy template.
+template <class C>
+struct GetUnaryBuiltinVecWeight
+{
+	inline float operator() (float outMin, float outMax) const { return C::getCompWeight(outMin, outMax); }
+};
+
+template <class C>
+struct ComputeUnaryBuiltinVecRange
+{
+	inline void operator() (float outMin, float outMax, float& inMin, float& inMax) const { C::computeValueRange(outMin, outMax, inMin, inMax); }
+};
+
+template <class C>
+struct EvaluateUnaryBuiltinVec
+{
+	inline float operator() (float inVal) const { return C::evaluateComp(inVal); }
+};
+
+template <class C>
+class UnaryBuiltinVecTemplateProxy : public UnaryBuiltinVecFunc<GetUnaryBuiltinVecWeight<C>, ComputeUnaryBuiltinVecRange<C>, EvaluateUnaryBuiltinVec<C> >
+{
+public:
+	UnaryBuiltinVecTemplateProxy (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
+		: UnaryBuiltinVecFunc<GetUnaryBuiltinVecWeight<C>, ComputeUnaryBuiltinVecRange<C>, EvaluateUnaryBuiltinVec<C> >(state, function, valueRange)
+	{
+	}
+};
+
+// Template for trigonometric function group.
+template <class C>
+class UnaryTrigonometricFunc : public UnaryBuiltinVecTemplateProxy<C>
+{
+public:
+	UnaryTrigonometricFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
+		: UnaryBuiltinVecTemplateProxy<C>(state, function, valueRange)
+	{
+	}
+
+	static inline float getCompWeight (float outMin, float outMax)
+	{
+		if (Scalar::min<float>() == outMin || Scalar::max<float>() == outMax)
+			return 1.0f; // Infinite value range, anything goes
+
+		// Transform range
+		float inMin, inMax;
+		if (!C::transformValueRange(outMin, outMax, inMin, inMax))
+			return 0.0f; // Not possible to transform value range (out of range perhaps)
+
+		// Quantize
+		if (!quantizeFloatRange(inMin, inMax))
+			return 0.0f; // Not possible to quantize - would cause accuracy issues
+
+		if (outMin == outMax)
+			return 1.0f; // Constant value and passed quantization
+
+		// Evaluate new intersection
+		float intersectionLen	= C::evaluateComp(inMax) - C::evaluateComp(inMin);
+		float valRangeLen		= outMax - outMin;
+
+		return deFloatMax(0.1f, intersectionLen/valRangeLen);
+	}
+
+	static inline void computeValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		DE_VERIFY(C::transformValueRange(outMin, outMax, inMin, inMax));
+		DE_VERIFY(quantizeFloatRange(inMin, inMax));
+		DE_ASSERT(inMin <= inMax);
+	}
+
+	static float getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
+	{
+		if (state.getProgramParameters().trigonometricBaseWeight <= 0.0f)
+			return 0.0f;
+
+		return UnaryBuiltinVecTemplateProxy<C>::getWeight(state, valueRange) * state.getProgramParameters().trigonometricBaseWeight;
+	}
+};
+
+class SinOp : public UnaryTrigonometricFunc<SinOp>
+{
+public:
+	SinOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryTrigonometricFunc<SinOp>(state, "sin", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		if (outMax < -1.0f || outMin > 1.0f)
+			return false;
+
+		inMin = (outMin >= -1.0f) ? deFloatAsin(outMin) : -0.5f*DE_PI;
+		inMax = (outMax <= +1.0f) ? deFloatAsin(outMax) : +0.5f*DE_PI;
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatSin(inVal);
+	}
+};
+
+class CosOp : public UnaryTrigonometricFunc<CosOp>
+{
+public:
+	CosOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryTrigonometricFunc<CosOp>(state, "cos", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		if (outMax < -1.0f || outMin > 1.0f)
+			return false;
+
+		inMax = (outMin >= -1.0f) ? deFloatAcos(outMin) : +DE_PI;
+		inMin = (outMax <= +1.0f) ? deFloatAcos(outMax) : -DE_PI;
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatCos(inVal);
+	}
+};
+
+class TanOp : public UnaryTrigonometricFunc<TanOp>
+{
+public:
+	TanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryTrigonometricFunc<TanOp>(state, "tan", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		// \note Currently tan() is limited to -4..4 range. Otherwise we will run into accuracy issues
+		const float rangeMin = -4.0f;
+		const float rangeMax = +4.0f;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false;
+
+		inMin = deFloatAtanOver(deFloatMax(outMin, rangeMin));
+		inMax = deFloatAtanOver(deFloatMin(outMax, rangeMax));
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatTan(inVal);
+	}
+};
+
+class AsinOp : public UnaryTrigonometricFunc<AsinOp>
+{
+public:
+	AsinOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryTrigonometricFunc<AsinOp>(state, "asin", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		const float rangeMin = -DE_PI/2.0f;
+		const float rangeMax = +DE_PI/2.0f;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false; // Out of range
+
+		inMin = deFloatSin(deFloatMax(outMin, rangeMin));
+		inMax = deFloatSin(deFloatMin(outMax, rangeMax));
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatAsin(inVal);
+	}
+};
+
+class AcosOp : public UnaryTrigonometricFunc<AcosOp>
+{
+public:
+	AcosOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryTrigonometricFunc<AcosOp>(state, "acos", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		const float rangeMin = 0.0f;
+		const float rangeMax = DE_PI;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false; // Out of range
+
+		inMax = deFloatCos(deFloatMax(outMin, rangeMin));
+		inMin = deFloatCos(deFloatMin(outMax, rangeMax));
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatAcos(inVal);
+	}
+};
+
+class AtanOp : public UnaryTrigonometricFunc<AtanOp>
+{
+public:
+	AtanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryTrigonometricFunc<AtanOp>(state, "atan", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		// \note For accuracy reasons output range is limited to -1..1
+		const float rangeMin = -1.0f;
+		const float rangeMax = +1.0f;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false; // Out of range
+
+		inMin = deFloatTan(deFloatMax(outMin, rangeMin));
+		inMax = deFloatTan(deFloatMin(outMax, rangeMax));
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatAtanOver(inVal);
+	}
+};
+
+// Template for exponential function group.
+// \todo [2011-07-07 pyry] Shares most of the code with Trigonometric variant..
+template <class C>
+class UnaryExponentialFunc : public UnaryBuiltinVecTemplateProxy<C>
+{
+public:
+	UnaryExponentialFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
+		: UnaryBuiltinVecTemplateProxy<C>(state, function, valueRange)
+	{
+	}
+
+	static inline float getCompWeight (float outMin, float outMax)
+	{
+		if (Scalar::min<float>() == outMin || Scalar::max<float>() == outMax)
+			return 1.0f; // Infinite value range, anything goes
+
+		// Transform range
+		float inMin, inMax;
+		if (!C::transformValueRange(outMin, outMax, inMin, inMax))
+			return 0.0f; // Not possible to transform value range (out of range perhaps)
+
+		// Quantize
+		if (!quantizeFloatRange(inMin, inMax))
+			return 0.0f; // Not possible to quantize - would cause accuracy issues
+
+		if (outMin == outMax)
+			return 1.0f; // Constant value and passed quantization
+
+		// Evaluate new intersection
+		float intersectionLen	= C::evaluateComp(inMax) - C::evaluateComp(inMin);
+		float valRangeLen		= outMax - outMin;
+
+		return deFloatMax(0.1f, intersectionLen/valRangeLen);
+	}
+
+	static inline void computeValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		DE_VERIFY(C::transformValueRange(outMin, outMax, inMin, inMax));
+		DE_VERIFY(quantizeFloatRange(inMin, inMax));
+		DE_ASSERT(inMin <= inMax);
+	}
+
+	static float getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
+	{
+		if (state.getProgramParameters().exponentialBaseWeight <= 0.0f)
+			return 0.0f;
+
+		return UnaryBuiltinVecTemplateProxy<C>::getWeight(state, valueRange) * state.getProgramParameters().exponentialBaseWeight;
+	}
+};
+
+class ExpOp : public UnaryExponentialFunc<ExpOp>
+{
+public:
+	ExpOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryExponentialFunc<ExpOp>(state, "exp", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		// Limited due to accuracy reasons, should be 0..+inf
+		const float rangeMin = 0.1f;
+		const float rangeMax = 10.0f;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false; // Out of range
+
+		inMin = deFloatLog(deFloatMax(outMin, rangeMin));
+		inMax = deFloatLog(deFloatMin(outMax, rangeMax));
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatExp(inVal);
+	}
+};
+
+class LogOp : public UnaryExponentialFunc<LogOp>
+{
+public:
+	LogOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryExponentialFunc<LogOp>(state, "log", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		// Limited due to accuracy reasons, should be -inf..+inf
+		const float rangeMin = 0.1f;
+		const float rangeMax = 6.0f;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false; // Out of range
+
+		inMin = deFloatExp(deFloatMax(outMin, rangeMin));
+		inMax = deFloatExp(deFloatMin(outMax, rangeMax));
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatLog(inVal);
+	}
+};
+
+class Exp2Op : public UnaryExponentialFunc<Exp2Op>
+{
+public:
+	Exp2Op (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryExponentialFunc<Exp2Op>(state, "exp2", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		// Limited due to accuracy reasons, should be 0..+inf
+		const float rangeMin = 0.1f;
+		const float rangeMax = 10.0f;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false; // Out of range
+
+		inMin = deFloatLog2(deFloatMax(outMin, rangeMin));
+		inMax = deFloatLog2(deFloatMin(outMax, rangeMax));
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatExp2(inVal);
+	}
+};
+
+class Log2Op : public UnaryExponentialFunc<Log2Op>
+{
+public:
+	Log2Op (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryExponentialFunc<Log2Op>(state, "log2", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		// Limited due to accuracy reasons, should be -inf..+inf
+		const float rangeMin = 0.1f;
+		const float rangeMax = 6.0f;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false; // Out of range
+
+		inMin = deFloatExp2(deFloatMax(outMin, rangeMin));
+		inMax = deFloatExp2(deFloatMin(outMax, rangeMax));
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatLog2(inVal);
+	}
+};
+
+class SqrtOp : public UnaryExponentialFunc<SqrtOp>
+{
+public:
+	SqrtOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryExponentialFunc<SqrtOp>(state, "sqrt", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		// Limited due to accuracy reasons, should be 0..+inf
+		const float rangeMin = 0.0f;
+		const float rangeMax = 4.0f;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false; // Out of range
+
+		inMin = deFloatMax(outMin, rangeMin);
+		inMax = deFloatMin(outMax, rangeMax);
+
+		inMin *= inMin;
+		inMax *= inMax;
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return deFloatSqrt(inVal);
+	}
+};
+
+class InvSqrtOp : public UnaryExponentialFunc<InvSqrtOp>
+{
+public:
+	InvSqrtOp (GeneratorState& state, ConstValueRangeAccess valueRange)
+		: UnaryExponentialFunc<InvSqrtOp>(state, "inversesqrt", valueRange)
+	{
+	}
+
+	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
+	{
+		// Limited due to accuracy reasons
+		const float rangeMin = 0.4f;
+		const float rangeMax = 3.0f;
+
+		if (outMax < rangeMin || outMin > rangeMax)
+			return false; // Out of range
+
+		inMax = 1.0f/deFloatMax(outMin, rangeMin);
+		inMin = 1.0f/deFloatMin(outMax, rangeMax);
+
+		inMin *= inMin;
+		inMax *= inMax;
+
+		return true;
+	}
+
+	static inline float evaluateComp (float inVal)
+	{
+		return 1.0f/deFloatSqrt(inVal);
+	}
+};
+
+} // rsg
+
+#endif // _RSGBUILTINFUNCTIONS_HPP