/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 2.0 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 Shader built-in variable tests.
 *//*--------------------------------------------------------------------*/

#include "es2fShaderBuiltinVarTests.hpp"
#include "glsShaderRenderCase.hpp"
#include "deRandom.hpp"
#include "deString.h"
#include "deMath.h"
#include "deStringUtil.hpp"
#include "tcuTestLog.hpp"
#include "tcuTestCase.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuImageCompare.hpp"
#include "gluPixelTransfer.hpp"
#include "gluDrawUtil.hpp"

#include "glwEnums.hpp"
#include "glwFunctions.hpp"

using std::string;
using std::vector;
using tcu::TestLog;

namespace deqp
{
namespace gles2
{
namespace Functional
{

const float builtinConstScale = 4.0f;

void evalBuiltinConstant (gls::ShaderEvalContext& c)
{
	bool isOk = 0 == (int)(deFloatFloor(c.coords.x() * builtinConstScale) + 0.05f);
	c.color = isOk ? tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f) : tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
}

class ShaderBuiltinConstantCase : public gls::ShaderRenderCase
{
public:
						ShaderBuiltinConstantCase				(Context& context, const char* name, const char* desc, const char* varName, deUint32 paramName, bool isVertexCase);
						~ShaderBuiltinConstantCase				(void);

	int					getRefValue								(void);
	void				init									(void);

private:
	const std::string	m_varName;
	const deUint32		m_paramName;
};

ShaderBuiltinConstantCase::ShaderBuiltinConstantCase (Context& context, const char* name, const char* desc, const char* varName, deUint32 paramName, bool isVertexCase)
	: ShaderRenderCase	(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, evalBuiltinConstant)
	, m_varName			(varName)
	, m_paramName		(paramName)
{
}

ShaderBuiltinConstantCase::~ShaderBuiltinConstantCase (void)
{
}

int ShaderBuiltinConstantCase::getRefValue (void)
{
	if (m_varName == "gl_MaxDrawBuffers")
	{
		if (m_ctxInfo.isExtensionSupported("GL_EXT_draw_buffers") ||
			m_ctxInfo.isExtensionSupported("GL_NV_draw_buffers") ||
			m_ctxInfo.isES3Compatible())
			return m_ctxInfo.getInt(GL_MAX_DRAW_BUFFERS);
		else
			return 1;
	}
	else
	{
		DE_ASSERT(m_paramName != GL_NONE);
		return m_ctxInfo.getInt(m_paramName);
	}
}

void ShaderBuiltinConstantCase::init (void)
{
	const int refValue = getRefValue();
	m_testCtx.getLog() << tcu::TestLog::Message << m_varName << " = " << refValue << tcu::TestLog::EndMessage;

	static const char* defaultVertSrc =
		"attribute highp vec4 a_position;\n"
		"attribute highp vec4 a_coords;\n"
		"varying mediump vec4 v_coords;\n\n"
		"void main (void)\n"
		"{\n"
		"	v_coords = a_coords;\n"
		"	gl_Position = a_position;\n"
		"}\n";
	static const char* defaultFragSrc =
		"varying mediump vec4 v_color;\n\n"
		"void main (void)\n"
		"{\n"
		"	gl_FragColor = v_color;\n"
		"}\n";

	// Construct shader.
	std::ostringstream src;
	if (m_isVertexCase)
	{
		src << "attribute highp vec4 a_position;\n"
			<< "attribute highp vec4 a_coords;\n"
			<< "varying mediump vec4 v_color;\n";
	}
	else
		src << "varying mediump vec4 v_coords;\n";

	src << "void main (void)\n{\n";

	src << "\tbool isOk = " << m_varName << " == (" << refValue << " + int(floor(" << (m_isVertexCase ? "a_coords" : "v_coords") << ".x * " << de::floatToString(builtinConstScale, 1) << ") + 0.05));\n";
	src << "\t" << (m_isVertexCase ? "v_color" : "gl_FragColor") << " = isOk ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n";

	if (m_isVertexCase)
		src << "\tgl_Position = a_position;\n";

	src << "}\n";

	m_vertShaderSource		= m_isVertexCase ? src.str()		: defaultVertSrc;
	m_fragShaderSource		= m_isVertexCase ? defaultFragSrc	: src.str();

	gls::ShaderRenderCase::init();
}

namespace
{

struct DepthRangeParams
{
	DepthRangeParams (void)
		: zNear	(0.0f)
		, zFar	(1.0f)
	{
	}

	DepthRangeParams (float zNear_, float zFar_)
		: zNear	(zNear_)
		, zFar	(zFar_)
	{
	}

	float	zNear;
	float	zFar;
};

class DepthRangeEvaluator : public gls::ShaderEvaluator
{
public:
	DepthRangeEvaluator (const DepthRangeParams& params)
		: m_params(params)
	{
	}

	void evaluate (gls::ShaderEvalContext& c)
	{
		float zNear	= deFloatClamp(m_params.zNear, 0.0f, 1.0f);
		float zFar	= deFloatClamp(m_params.zFar, 0.0f, 1.0f);
		float diff	= zFar - zNear;
		c.color.xyz() = tcu::Vec3(zNear, zFar, diff*0.5f + 0.5f);
	}

private:
	const DepthRangeParams& m_params;
};

} // anonymous

class ShaderDepthRangeTest : public gls::ShaderRenderCase
{
public:
	ShaderDepthRangeTest (Context& context, const char* name, const char* desc, bool isVertexCase)
		: ShaderRenderCase	(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_evaluator)
		, m_evaluator		(m_depthRange)
		, m_iterNdx			(0)
	{
	}

	void init (void)
	{
		static const char* defaultVertSrc =
			"attribute highp vec4 a_position;\n"
			"void main (void)\n"
			"{\n"
			"	gl_Position = a_position;\n"
			"}\n";
		static const char* defaultFragSrc =
			"varying mediump vec4 v_color;\n\n"
			"void main (void)\n"
			"{\n"
			"	gl_FragColor = v_color;\n"
			"}\n";

		// Construct shader.
		std::ostringstream src;
		if (m_isVertexCase)
			src << "attribute highp vec4 a_position;\n"
				<< "varying mediump vec4 v_color;\n";

		src << "void main (void)\n{\n";
		src << "\t" << (m_isVertexCase ? "v_color" : "gl_FragColor") << " = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff*0.5 + 0.5, 1.0);\n";

		if (m_isVertexCase)
			src << "\tgl_Position = a_position;\n";

		src << "}\n";

		m_vertShaderSource		= m_isVertexCase ? src.str()		: defaultVertSrc;
		m_fragShaderSource		= m_isVertexCase ? defaultFragSrc	: src.str();

		gls::ShaderRenderCase::init();
	}

	IterateResult iterate (void)
	{
		const glw::Functions& gl = m_renderCtx.getFunctions();

		const DepthRangeParams cases[] =
		{
			DepthRangeParams(0.0f,  1.0f),
			DepthRangeParams(1.5f, -1.0f),
			DepthRangeParams(0.7f,  0.3f)
		};

		m_depthRange = cases[m_iterNdx];
		m_testCtx.getLog() << tcu::TestLog::Message << "glDepthRangef(" << m_depthRange.zNear << ", " << m_depthRange.zFar << ")" << tcu::TestLog::EndMessage;
		gl.depthRangef(m_depthRange.zNear, m_depthRange.zFar);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthRangef()");

		gls::ShaderRenderCase::iterate();
		m_iterNdx += 1;

		if (m_iterNdx == DE_LENGTH_OF_ARRAY(cases) || m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
			return STOP;
		else
			return CONTINUE;
	}

private:
	DepthRangeParams		m_depthRange;
	DepthRangeEvaluator		m_evaluator;
	int						m_iterNdx;
};

class FragCoordXYZCase : public TestCase
{
public:
	FragCoordXYZCase (Context& context)
		: TestCase(context, "fragcoord_xyz", "gl_FragCoord.xyz Test")
	{
	}

	IterateResult iterate (void)
	{
		TestLog&				log			= m_testCtx.getLog();
		const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
		const int				width		= m_context.getRenderTarget().getWidth();
		const int				height		= m_context.getRenderTarget().getHeight();
		const tcu::RGBA			threshold	= tcu::RGBA(1,1,1,1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
		const tcu::Vec3			scale		(1.f / float(width), 1.f / float(height), 1.0f);

		tcu::Surface			testImg		(width, height);
		tcu::Surface			refImg		(width, height);

		const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
			"attribute highp vec4 a_position;\n"
			"void main (void)\n"
			"{\n"
			"	gl_Position = a_position;\n"
			"}\n",

			"uniform mediump vec3 u_scale;\n"
			"void main (void)\n"
			"{\n"
			"	gl_FragColor = vec4(gl_FragCoord.xyz*u_scale, 1.0);\n"
			"}\n"));

		log << program;

		if (!program.isOk())
			throw tcu::TestError("Compile failed");

		// Draw with GL.
		{
			const float positions[] =
			{
				-1.0f,  1.0f, -1.0f, 1.0f,
				-1.0f, -1.0f,  0.0f, 1.0f,
				 1.0f,  1.0f,  0.0f, 1.0f,
				 1.0f, -1.0f,  1.0f, 1.0f
			};
			const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };

			const int				scaleLoc	= gl.getUniformLocation(program.getProgram(), "u_scale");
			glu::VertexArrayBinding	posBinding	= glu::va::Float("a_position", 4, 4, 0, &positions[0]);

			gl.useProgram(program.getProgram());
			gl.uniform3fv(scaleLoc, 1, scale.getPtr());

			glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
					  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));

			glu::readPixels(m_context.getRenderContext(), 0, 0, testImg.getAccess());
			GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
		}

		// Draw reference
		for (int y = 0; y < refImg.getHeight(); y++)
		{
			for (int x = 0; x < refImg.getWidth(); x++)
			{
				const float			xf			= (float(x)+.5f) / float(refImg.getWidth());
				const float			yf			= (float(refImg.getHeight()-y-1)+.5f) / float(refImg.getHeight());
				const float			z			= (xf + yf) / 2.0f;
				const tcu::Vec3		fragCoord	(float(x)+.5f, float(y)+.5f, z);
				const tcu::Vec3		scaledFC	= fragCoord*scale;
				const tcu::Vec4		color		(scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);

				refImg.setPixel(x, y, tcu::RGBA(color));
			}
		}

		// Compare
		{
			bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image comparison failed");
		}

		return STOP;
	}
};

static inline float projectedTriInterpolate (const tcu::Vec3& s, const tcu::Vec3& w, float nx, float ny)
{
	return (s[0]*(1.0f-nx-ny)/w[0] + s[1]*ny/w[1] + s[2]*nx/w[2]) / ((1.0f-nx-ny)/w[0] + ny/w[1] + nx/w[2]);
}

class FragCoordWCase : public TestCase
{
public:
	FragCoordWCase (Context& context)
		: TestCase(context, "fragcoord_w", "gl_FragCoord.w Test")
	{
	}

	IterateResult iterate (void)
	{
		TestLog&				log			= m_testCtx.getLog();
		const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
		const int				width		= m_context.getRenderTarget().getWidth();
		const int				height		= m_context.getRenderTarget().getHeight();
		const tcu::RGBA			threshold	= tcu::RGBA(1,1,1,1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();

		tcu::Surface			testImg		(width, height);
		tcu::Surface			refImg		(width, height);

		const float				w[4]		= { 1.7f, 2.0f, 1.2f, 1.0f };

		const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
			"attribute highp vec4 a_position;\n"
			"void main (void)\n"
			"{\n"
			"	gl_Position = a_position;\n"
			"}\n",

			"void main (void)\n"
			"{\n"
			"	gl_FragColor = vec4(0.0, 1.0/gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
			"}\n"));

		log << program;

		if (!program.isOk())
			throw tcu::TestError("Compile failed");

		// Draw with GL.
		{
			const float positions[] =
			{
				-w[0],  w[0], 0.0f, w[0],
				-w[1], -w[1], 0.0f, w[1],
				 w[2],  w[2], 0.0f, w[2],
				 w[3], -w[3], 0.0f, w[3]
			};
			const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };

			glu::VertexArrayBinding	posBinding	= glu::va::Float("a_position", 4, 4, 0, &positions[0]);

			gl.useProgram(program.getProgram());

			glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
					  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));

			glu::readPixels(m_context.getRenderContext(), 0, 0, testImg.getAccess());
			GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
		}

		// Draw reference
		for (int y = 0; y < refImg.getHeight(); y++)
		{
			for (int x = 0; x < refImg.getWidth(); x++)
			{
				const float			xf			= (float(x)+.5f) / float(refImg.getWidth());
				const float			yf			= (float(refImg.getHeight()-y-1)+.5f) / float(refImg.getHeight());
				const float			oow			= ((xf + yf) < 1.0f)
												? projectedTriInterpolate(tcu::Vec3(w[0], w[1], w[2]), tcu::Vec3(w[0], w[1], w[2]), xf, yf)
												: projectedTriInterpolate(tcu::Vec3(w[3], w[2], w[1]), tcu::Vec3(w[3], w[2], w[1]), 1.0f-xf, 1.0f-yf);
				const tcu::Vec4		color		(0.0f, oow - 1.0f, 0.0f, 1.0f);

				refImg.setPixel(x, y, tcu::RGBA(color));
			}
		}

		// Compare
		{
			bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image comparison failed");
		}

		return STOP;
	}
};

class PointCoordCase : public TestCase
{
public:
	PointCoordCase (Context& context)
		: TestCase(context, "pointcoord", "gl_PointCoord Test")
	{
	}

	IterateResult iterate (void)
	{
		TestLog&				log			= m_testCtx.getLog();
		const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
		const int				width		= de::min(256, m_context.getRenderTarget().getWidth());
		const int				height		= de::min(256, m_context.getRenderTarget().getHeight());
		const float				threshold	= 0.02f;

		const int				numPoints	= 8;

		vector<tcu::Vec3>		coords		(numPoints);
		float					pointSizeRange[2]	= { 0.0f, 0.0f };

		de::Random				rnd			(0x145fa);
		tcu::Surface			testImg		(width, height);
		tcu::Surface			refImg		(width, height);

		gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, &pointSizeRange[0]);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE)");

		if (pointSizeRange[0] <= 0.0f || pointSizeRange[1] <= 0.0f || pointSizeRange[1] < pointSizeRange[0])
			throw tcu::TestError("Invalid GL_ALIASED_POINT_SIZE_RANGE");

		// Compute coordinates.
		{

			for (vector<tcu::Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
			{
				coord->x() = rnd.getFloat(-0.9f, 0.9f);
				coord->y() = rnd.getFloat(-0.9f, 0.9f);
				coord->z() = rnd.getFloat(pointSizeRange[0], pointSizeRange[1]);
			}
		}

		const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
			"attribute highp vec3 a_positionSize;\n"
			"void main (void)\n"
			"{\n"
			"	gl_Position = vec4(a_positionSize.xy, 0.0, 1.0);\n"
			"	gl_PointSize = a_positionSize.z;\n"
			"}\n",

			"void main (void)\n"
			"{\n"
			"	gl_FragColor = vec4(gl_PointCoord, 0.0, 1.0);\n"
			"}\n"));

		log << program;

		if (!program.isOk())
			throw tcu::TestError("Compile failed");

		// Draw with GL.
		{
			glu::VertexArrayBinding	posBinding	= glu::va::Float("a_positionSize", 3, (int)coords.size(), 0, (const float*)&coords[0]);
			const int				viewportX	= rnd.getInt(0, m_context.getRenderTarget().getWidth()-width);
			const int				viewportY	= rnd.getInt(0, m_context.getRenderTarget().getHeight()-height);

			gl.viewport(viewportX, viewportY, width, height);
			gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
			gl.clear(GL_COLOR_BUFFER_BIT);

			gl.useProgram(program.getProgram());

			glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
					  glu::pr::Points((int)coords.size()));

			glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
			GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
		}

		// Draw reference
		tcu::clear(refImg.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
		for (vector<tcu::Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
		{
			const int	x0		= deRoundFloatToInt32(float(width) *(pointIter->x()*0.5f + 0.5f) - pointIter->z()*0.5f);
			const int	y0		= deRoundFloatToInt32(float(height)*(pointIter->y()*0.5f + 0.5f) - pointIter->z()*0.5f);
			const int	x1		= deRoundFloatToInt32(float(width) *(pointIter->x()*0.5f + 0.5f) + pointIter->z()*0.5f);
			const int	y1		= deRoundFloatToInt32(float(height)*(pointIter->y()*0.5f + 0.5f) + pointIter->z()*0.5f);
			const int	w		= x1-x0;
			const int	h		= y1-y0;

			for (int yo = 0; yo < h; yo++)
			{
				for (int xo = 0; xo < w; xo++)
				{
					const float			xf		= (float(xo)+0.5f) / float(w);
					const float			yf		= (float(h-yo-1)+0.5f) / float(h);
					const tcu::Vec4		color	(xf, yf, 0.0f, 1.0f);
					const int			dx		= x0+xo;
					const int			dy		= y0+yo;

					if (de::inBounds(dx, 0, refImg.getWidth()) && de::inBounds(dy, 0, refImg.getHeight()))
						refImg.setPixel(dx, dy, tcu::RGBA(color));
				}
			}
		}

		// Compare
		{
			bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image comparison failed");
		}

		return STOP;
	}
};

class FrontFacingCase : public TestCase
{
public:
	FrontFacingCase (Context& context)
		: TestCase(context, "frontfacing", "gl_FrontFacing Test")
	{
	}

	IterateResult iterate (void)
	{
		// Test case renders two adjecent quads, where left is has front-facing
		// triagles and right back-facing. Color is selected based on gl_FrontFacing
		// value.

		TestLog&				log			= m_testCtx.getLog();
		const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
		de::Random				rnd			(0x89f2c);
		const int				width		= de::min(64, m_context.getRenderTarget().getWidth());
		const int				height		= de::min(64, m_context.getRenderTarget().getHeight());
		const int				viewportX	= rnd.getInt(0, m_context.getRenderTarget().getWidth()-width);
		const int				viewportY	= rnd.getInt(0, m_context.getRenderTarget().getHeight()-height);
		const tcu::RGBA			threshold	= tcu::RGBA(1,1,1,1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();

		tcu::Surface			testImg		(width, height);
		tcu::Surface			refImg		(width, height);

		const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
			"attribute highp vec4 a_position;\n"
			"void main (void)\n"
			"{\n"
			"	gl_Position = a_position;\n"
			"}\n",

			"void main (void)\n"
			"{\n"
			"	if (gl_FrontFacing)\n"
			"		gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
			"	else\n"
			"		gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
			"}\n"));

		log << program;

		if (!program.isOk())
			throw tcu::TestError("Compile failed");

		// Draw with GL.
		{
			const float positions[] =
			{
				-1.0f,  1.0f, 0.0f, 1.0f,
				-1.0f, -1.0f, 0.0f, 1.0f,
				 1.0f,  1.0f, 0.0f, 1.0f,
				 1.0f, -1.0f, 0.0f, 1.0f
			};
			const deUint16 indicesCCW[]	= { 0, 1, 2, 2, 1, 3 };
			const deUint16 indicesCW[]	= { 2, 1, 0, 3, 1, 2 };

			glu::VertexArrayBinding	posBinding	= glu::va::Float("a_position", 4, 4, 0, &positions[0]);

			gl.useProgram(program.getProgram());

			gl.frontFace(GL_CCW);

			gl.viewport(viewportX, viewportY, width/2, height/2);
			glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
					  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCCW), &indicesCCW[0]));

			gl.viewport(viewportX + width/2, viewportY, width-width/2, height/2);
			glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
					  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCW), &indicesCW[0]));

			gl.frontFace(GL_CW);

			gl.viewport(viewportX, viewportY + height/2, width/2, height-height/2);
			glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
					  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCCW), &indicesCCW[0]));

			gl.viewport(viewportX + width/2, viewportY + height/2, width-width/2, height-height/2);
			glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
					  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCW), &indicesCW[0]));

			glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
			GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
		}

		// Draw reference
		{
			for(int y = 0; y < refImg.getHeight() / 2; y++)
				for(int x = 0; x < refImg.getWidth() / 2; x++)
					refImg.setPixel(x, y, tcu::RGBA::green());

			for(int y = 0; y < refImg.getHeight() / 2; y++)
				for(int x = refImg.getWidth() / 2; x < refImg.getWidth(); x++)
					refImg.setPixel(x, y, tcu::RGBA::blue());

			for(int y = refImg.getHeight() / 2; y < refImg.getHeight(); y++)
				for(int x = 0; x < refImg.getWidth() / 2; x++)
					refImg.setPixel(x, y, tcu::RGBA::blue());

			for(int y = refImg.getHeight() / 2; y < refImg.getHeight(); y++)
				for(int x = refImg.getWidth() / 2; x < refImg.getWidth(); x++)
					refImg.setPixel(x, y, tcu::RGBA::green());
		}

		// Compare
		{
			bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image comparison failed");
		}

		return STOP;
	}
};

ShaderBuiltinVarTests::ShaderBuiltinVarTests (Context& context)
	: TestCaseGroup(context, "builtin_variable", "Built-in Variable Tests")
{
}

ShaderBuiltinVarTests::~ShaderBuiltinVarTests (void)
{
}

void ShaderBuiltinVarTests::init (void)
{
	// Builtin constants.

	static const struct
	{
		const char*		caseName;
		const char*		varName;
		deUint32		paramName;
	} builtinConstants[] =
	{
		{ "max_vertex_attribs",					"gl_MaxVertexAttribs",				GL_MAX_VERTEX_ATTRIBS },
		{ "max_vertex_uniform_vectors",			"gl_MaxVertexUniformVectors",		GL_MAX_VERTEX_UNIFORM_VECTORS },
		{ "max_fragment_uniform_vectors",		"gl_MaxFragmentUniformVectors",		GL_MAX_FRAGMENT_UNIFORM_VECTORS },
		{ "max_varying_vectors",				"gl_MaxVaryingVectors",				GL_MAX_VARYING_VECTORS },
		{ "max_texture_image_units",			"gl_MaxTextureImageUnits",			GL_MAX_TEXTURE_IMAGE_UNITS },
		{ "max_vertex_texture_image_units",		"gl_MaxVertexTextureImageUnits",	GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS },
		{ "max_combined_texture_image_units",	"gl_MaxCombinedTextureImageUnits",	GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS },
		{ "max_draw_buffers",					"gl_MaxDrawBuffers",				GL_NONE }
	};

	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtinConstants); ndx++)
	{
		const char*		caseName	= builtinConstants[ndx].caseName;
		const char*		varName		= builtinConstants[ndx].varName;
		deUint32		paramName	= builtinConstants[ndx].paramName;

		addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_vertex").c_str(),	varName, varName, paramName, true));
		addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_fragment").c_str(),	varName, varName, paramName, false));
	}

	addChild(new ShaderDepthRangeTest(m_context, "depth_range_vertex",		"gl_DepthRange", true));
	addChild(new ShaderDepthRangeTest(m_context, "depth_range_fragment",	"gl_DepthRange", false));

	// Fragment shader builtin variables.

	addChild(new FragCoordXYZCase	(m_context));
	addChild(new FragCoordWCase		(m_context));
	addChild(new PointCoordCase		(m_context));
	addChild(new FrontFacingCase	(m_context));
}

} // Functional
} // gles2
} // deqp
