/*-------------------------------------------------------------------------
 * 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"))
			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
