/*-------------------------------------------------------------------------
 * OpenGL Conformance Test Suite
 * -----------------------------
 *
 * Copyright (c) 2014-2019 The Khronos Group Inc.
 *
 * 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
 */ /*-------------------------------------------------------------------*/

/**
 * \file  gl2fClipControlTests.cpp
 * \brief Implements conformance tests for "EXT_clip_control" functionality.
 */ /*-------------------------------------------------------------------*/

#include "es2fClipControlTests.hpp"

#include "deSharedPtr.hpp"

#include "gluContextInfo.hpp"
#include "gluDrawUtil.hpp"
#include "gluDefs.hpp"
#include "gluPixelTransfer.hpp"
#include "gluShaderProgram.hpp"

#include "tcuFuzzyImageCompare.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuSurface.hpp"
#include "tcuTestLog.hpp"

#include "glw.h"
#include "glwFunctions.hpp"

#include <cmath>

namespace deqp
{
namespace gles2
{
namespace Functional
{

class ClipControlApi
{
public:
	ClipControlApi(Context& context) : m_context(context)
	{
		if (!Supported(m_context))
		{
			throw tcu::NotSupportedError("Required extension EXT_clip_control is not supported");
		}
		clipControl = context.getRenderContext().getFunctions().clipControl;
	}

	static bool Supported(Context& context)
	{
		return context.getContextInfo().isExtensionSupported("GL_EXT_clip_control");
	}

	glw::glClipControlFunc clipControl;

private:
	Context& m_context;
};

class ClipControlBaseTest : public TestCase
{
protected:
	ClipControlBaseTest(Context& context, const char* name, const char* description)
		: TestCase(context, name, description)
	{
	}

	void init() override
	{
		ClipControlApi api(m_context);
	}

	bool verifyState(glw::GLenum origin, glw::GLenum depth)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();

		bool ret = true;

		glw::GLint retI;
		gl.getIntegerv(GL_CLIP_ORIGIN, &retI);
		GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_CLIP_ORIGIN");

		ret &= (static_cast<glw::GLenum>(retI) == origin);

		gl.getIntegerv(GL_CLIP_DEPTH_MODE, &retI);
		GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_CLIP_DEPTH_MODE");

		ret &= (static_cast<glw::GLenum>(retI) == depth);

		return ret;
	}
};

class ClipControlRenderBaseTest : public ClipControlBaseTest
{
protected:
	ClipControlRenderBaseTest(Context& context, const char* name, const char* description)
		: ClipControlBaseTest(context, name, description), m_fbo(0), m_rboC(0), m_depthTexure(0)
	{
	}

	const char* fsh()
	{
		return "void main() {"
			   "\n"
			   "    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);"
			   "\n"
			   "}";
	}

	bool fuzzyDepthCompare(tcu::TestLog& log, const char* imageSetName, const char* imageSetDesc,
						   const tcu::TextureLevel& reference, const tcu::TextureLevel& result, float threshold,
						   const tcu::TextureLevel* importanceMask = NULL)
	{
		(void)imageSetName;
		(void)imageSetDesc;
		bool  depthOk	= true;
		float difference = 0.0f;

		for (int y = 0; y < result.getHeight() && depthOk; y++)
		{
			for (int x = 0; x < result.getWidth() && depthOk; x++)
			{
				float ref  = reference.getAccess().getPixDepth(x, y);
				float res  = result.getAccess().getPixel(x,y).x();
				difference = std::abs(ref - res);
				if (importanceMask)
				{
					difference *= importanceMask->getAccess().getPixDepth(x, y);
				}
				depthOk &= (difference < threshold);
			}
		}

		if (!depthOk)
			log << tcu::TestLog::Message << "Image comparison failed: difference = " << difference
				<< ", threshold = " << threshold << tcu::TestLog::EndMessage;
		tcu::Vec4 pixelBias(0.0f, 0.0f, 0.0f, 0.0f);
		tcu::Vec4 pixelScale(1.0f, 1.0f, 1.0f, 1.0f);
		log << tcu::TestLog::ImageSet("Result", "Depth image comparison result")
			<< tcu::TestLog::Image("Result", "Result", result.getAccess(), pixelScale, pixelBias)
			<< tcu::TestLog::Image("Reference", "Reference", reference.getAccess(), pixelScale, pixelBias);
		if (importanceMask)
		{
			log << tcu::TestLog::Image("Importance mask", "mask", importanceMask->getAccess(), pixelScale, pixelBias);
		}
		log << tcu::TestLog::EndImageSet;

		return depthOk;
	}

	virtual void init(void)
	{
		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
		glw::GLuint				 viewportW	= renderTarget.getWidth();
		glw::GLuint				 viewportH	= renderTarget.getHeight();
		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();

		gl.genFramebuffers(1, &m_fbo);
		gl.genRenderbuffers(1, &m_rboC);
		gl.genTextures(1, &m_depthTexure);

		gl.bindRenderbuffer(GL_RENDERBUFFER, m_rboC);
		gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, viewportW, viewportH);

		gl.bindTexture(GL_TEXTURE_2D, m_depthTexure);
		gl.texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportW, viewportH, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, DE_NULL);

		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rboC);
		gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexure, 0);
	}

	virtual void deinit(void)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.deleteFramebuffers(1, &m_fbo);
		gl.deleteRenderbuffers(1, &m_rboC);
		gl.deleteTextures(1, &m_depthTexure);
		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
	}

	GLuint getDepthTexture()
	{
		return m_depthTexure;
	}

private:
	GLuint m_fbo, m_rboC, m_depthTexure;
};

/*
 Verify the following state values are implemented and return a valid
 initial value by calling GetIntegerv:

 Get Value                                 Initial Value
 -------------------------------------------------------
 CLIP_ORIGIN                                  LOWER_LEFT
 CLIP_DEPTH_MODE                     NEGATIVE_ONE_TO_ONE

 Verify no GL error is generated.
 */
class ClipControlInitialState : public ClipControlBaseTest
{
public:
	ClipControlInitialState(Context& context, const char* name)
		: ClipControlBaseTest(context, name, "Verify initial state")
	{
	}

	IterateResult iterate() override
	{
		if (!verifyState(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE))
		{
			TCU_FAIL("Wrong intitial state: GL_CLIP_ORIGIN should be GL_LOWER_LEFT,"
					 " GL_CLIP_ORIGIN should be NEGATIVE_ONE_TO_ONE");
		}

		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, qpGetTestResultName(QP_TEST_RESULT_PASS));
		return STOP;
	}
};

/*
 Modify the state to each of the following combinations and after each
 state change verify the state values:

 ClipControl(UPPER_LEFT, ZERO_TO_ONE)
 ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
 ClipControl(LOWER_LEFT, ZERO_TO_ONE)
 ClipControl(LOWER_LEFT, NEGATIVE_ONE_TO_ONE)

 Verify no GL error is generated.

 */
class ClipControlModifyGetState : public ClipControlBaseTest
{
public:
	ClipControlModifyGetState(Context& context, const char* name)
		: ClipControlBaseTest(context,  name, "Verify initial state")
	{
	}

	void deinit() override
	{
		if (ClipControlApi::Supported(m_context))
		{
			ClipControlApi cc(m_context);
			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
		}
	}

	IterateResult iterate() override
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		ClipControlApi		  cc(m_context);

		GLenum cases[4][2] = {
			{ GL_UPPER_LEFT, GL_ZERO_TO_ONE },
			{ GL_UPPER_LEFT, GL_NEGATIVE_ONE_TO_ONE },
			{ GL_LOWER_LEFT, GL_ZERO_TO_ONE },
			{ GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE },
		};

		for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cases); i++)
		{
			cc.clipControl(cases[i][0], cases[i][1]);
			GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");
			if (!verifyState(cases[i][0], cases[i][1]))
			{
				TCU_FAIL("Wrong ClipControl state after ClipControl() call");
			}
		}

		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, qpGetTestResultName(QP_TEST_RESULT_PASS));
		return STOP;
	}
};

/*
 Check that ClipControl generate an GL_INVALID_ENUM error if origin is
 not GL_LOWER_LEFT or GL_UPPER_LEFT.

 Check that ClipControl generate an GL_INVALID_ENUM error if depth is
 not GL_NEGATIVE_ONE_TO_ONE or GL_ZERO_TO_ONE.

 Test is based on OpenGL 4.5 Core Profile Specification May 28th Section
 13.5 Primitive Clipping:
 "An INVALID_ENUM error is generated if origin is not LOWER_LEFT or
 UPPER_LEFT.
 An INVALID_ENUM error is generated if depth is not NEGATIVE_ONE_-
 TO_ONE or ZERO_TO_ONE."
 */
class ClipControlErrors : public ClipControlBaseTest
{
public:
	ClipControlErrors(Context& context, const char* name)
		: ClipControlBaseTest(context, name, "Verify that proper errors are generated when using ClipControl.")
	{
	}

	void deinit() override
	{
		if (ClipControlApi::Supported(m_context))
		{
			ClipControlApi cc(m_context);
			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
		}
	}

	IterateResult iterate() override
	{
		/* API query */
		tcu::TestLog&		  log = m_testCtx.getLog();
		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
		ClipControlApi		  cc(m_context);

		/* Finding improper value. */
		GLenum improper_value = GL_NONE;

		while ((GL_UPPER_LEFT == improper_value) || (GL_LOWER_LEFT == improper_value) ||
			   (GL_ZERO_TO_ONE == improper_value) || (GL_NEGATIVE_ONE_TO_ONE == improper_value))
		{
			++improper_value;
		}

		/* Test setup. */
		GLenum cases[5][2] = { { GL_UPPER_LEFT, improper_value },
							   { GL_LOWER_LEFT, improper_value },
							   { improper_value, GL_ZERO_TO_ONE },
							   { improper_value, GL_NEGATIVE_ONE_TO_ONE },
							   { improper_value, improper_value } };

		/* Test iterations. */
		for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cases); i++)
		{
			cc.clipControl(cases[i][0], cases[i][1]);

			if (GL_INVALID_ENUM != gl.getError())
			{
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));

				log << tcu::TestLog::Message
					<< "ClipControl have not generated GL_INVALID_ENUM error when called with invalid value ("
					<< cases[i][0] << ", " << cases[i][1] << ")." << tcu::TestLog::EndMessage;
			}
		}

		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, qpGetTestResultName(QP_TEST_RESULT_PASS));
		return STOP;
	}
};

/*
 Clip Control Origin Test

 * Basic <origin> behavior can be tested by rendering to a viewport with
 clip coordinates where -1.0 <= x_c <= 0.0 and -1.0 <= y_c <= 0.0.
 When <origin> is LOWER_LEFT the "bottom left" portion of the window
 is rendered and when UPPER_LEFT is used the "top left" portion of the
 window is rendered. The default framebuffer should be bound. Here is the
 basic outline of the test:

 - Clear the default framebuffer to red (1,0,0).
 - Set ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
 - Render a triangle fan covering (-1.0, -1.0) to (0.0, 0.0) and
 write a pixel value of green (0,1,0).
 - Read back the default framebuffer with ReadPixels
 - Verify the green pixels at the top and red at the bottom.

 Repeat the above test with LOWER_LEFT and verify green at the bottom
 and red at the top.
 */
class ClipControlOriginTest : public ClipControlRenderBaseTest
{
public:
	ClipControlOriginTest(Context& context, const char* name)
		: ClipControlRenderBaseTest(context,  name, "Clip Control Origin Test"), m_vao(0), m_vbo(0)
	{
	}

	void deinit() override
	{
		ClipControlRenderBaseTest::deinit();

		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		if (ClipControlApi::Supported(m_context))
		{
			ClipControlApi cc(m_context);
			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
		}

		gl.clearColor(0.0, 0.0, 0.0, 0.0);
		if (m_vao)
		{
			gl.deleteVertexArrays(1, &m_vao);
		}
		if (m_vbo)
		{
			gl.deleteBuffers(1, &m_vbo);
		}
	}

	IterateResult iterate() override
	{

		tcu::TestLog&		  log = m_testCtx.getLog();
		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
		ClipControlApi		  cc(m_context);

		//Render a triangle fan covering(-1.0, -1.0) to(1.0, 0.0) and
		//write a pixel value of green(0, 1, 0).

		de::SharedPtr<glu::ShaderProgram> program(
					new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));

		log << (*program);
		if (!program->isOk())
		{
			TCU_FAIL("Program compilation failed");
		}

		gl.genVertexArrays(1, &m_vao);
		gl.bindVertexArray(m_vao);

		gl.genBuffers(1, &m_vbo);

		const float vertex_data0[] = { -1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0 };

		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);

		gl.vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
		gl.enableVertexAttribArray(0);

		gl.useProgram(program->getProgram());

		glw::GLenum origins[] = { GL_UPPER_LEFT, GL_LOWER_LEFT };

		qpTestResult result = QP_TEST_RESULT_PASS;

		for (size_t orig = 0; orig < DE_LENGTH_OF_ARRAY(origins); orig++)
		{
			//Clear the default framebuffer to red(1, 0, 0).
			gl.clearColor(1.0, 0.0, 0.0, 1.0);
			gl.clear(GL_COLOR_BUFFER_BIT);

			//Set ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
			cc.clipControl(origins[orig], GL_NEGATIVE_ONE_TO_ONE);
			GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");

			//test method modification: use GL_TRIANGLE_STRIP, not FAN.
			gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);

			//Read back the default framebuffer with ReadPixels
			//Verify the green pixels at the top and red at the bottom.
			qpTestResult loopResult = ValidateFramebuffer(m_context, origins[orig]);
			if (loopResult != QP_TEST_RESULT_PASS)
			{
				result = loopResult;
			}
		}

		m_testCtx.setTestResult(result, qpGetTestResultName(result));

		return STOP;
	}

	const char* vsh()
	{
		return "attribute highp vec2 Position;"
			   "\n"
			   "void main() {"
			   "\n"
			   "    gl_Position = vec4(Position, 0.0, 1.0);"
			   "\n"
			   "}";
	}

	qpTestResult ValidateFramebuffer(Context& context, glw::GLenum origin)
	{
		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
		glw::GLsizei			 viewportW	= renderTarget.getWidth();
		glw::GLsizei			 viewportH	= renderTarget.getHeight();
		tcu::Surface			 renderedFrame(viewportW, viewportH);
		tcu::Surface			 referenceFrame(viewportW, viewportH);

		tcu::TestLog& log = context.getTestContext().getLog();

		for (int y = 0; y < renderedFrame.getHeight(); y++)
		{
			float yCoord = (float)(y) / (float)renderedFrame.getHeight();

			for (int x = 0; x < renderedFrame.getWidth(); x++)
			{

				float xCoord = (float)(x) / (float)renderedFrame.getWidth();

				bool greenQuadrant;

				if (origin == GL_UPPER_LEFT)
				{
					greenQuadrant = (yCoord > 0.5 && xCoord <= 0.5);
				}
				else
				{
					greenQuadrant = (yCoord <= 0.5 && xCoord <= 0.5);
				}

				if (greenQuadrant)
				{
					referenceFrame.setPixel(x, y, tcu::RGBA::green());
				}
				else
				{
					referenceFrame.setPixel(x, y, tcu::RGBA::red());
				}
			}
		}

		glu::readPixels(context.getRenderContext(), 0, 0, renderedFrame.getAccess());

		if (tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f,
							  tcu::COMPARE_LOG_RESULT))
		{
			return QP_TEST_RESULT_PASS;
		}
		else
		{
			return QP_TEST_RESULT_FAIL;
		}
	}

	glw::GLuint m_vao, m_vbo;
};



/*
 Clip Control Origin With Face Culling Test

 * Face culling should be tested with both <origin> settings.
 The reason for that is, when doing Y-inversion, implementation
 should not flip the calculated area sign for the triangle.
 In other words, culling of CCW and CW triangles should
 be orthogonal to used <origin> mode. Both triangle windings
 and both <origin> modes should be tested. Here is the basic
 outline of the test:

 - Clear the framebuffer to red (1,0,0).
 - Enable GL_CULL_FACE, leave default front face & cull face (CCW, BACK)
 - Set ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
 - Render a counter-clockwise triangles covering
 (-1.0, -1.0) to (0.0, 1.0) and write a pixel value of green (0,1,0).
 - Render a clockwise triangles covering
 (0.0, -1.0) to (1.0, 1.0) and write a pixel value of green (0,1,0).
 - Read back the framebuffer with ReadPixels
 - Verify the green pixels at the left and red at the right.

 Repeat above test for ClipControl(LOWER_LEFT, NEGATIVE_ONE_TO_ONE)
 */
class ClipControlFaceCulling : public ClipControlRenderBaseTest
{
public:
	ClipControlFaceCulling(Context& context, const char* name)
		: ClipControlRenderBaseTest(context,  name, "Face culling test, both origins"), m_vao(0), m_vbo(0)
	{
	}

	void deinit()
	{
		ClipControlRenderBaseTest::deinit();

		const glw::Functions& gl = m_context.getRenderContext().getFunctions();

		if (ClipControlApi::Supported(m_context))
		{
			ClipControlApi cc(m_context);
			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
		}

		gl.disable(GL_CULL_FACE);

		gl.clearColor(0.0, 0.0, 0.0, 0.0);

		gl.disable(GL_DEPTH_TEST);
		gl.depthFunc(GL_LESS);

		if (m_vao)
		{
			gl.deleteVertexArrays(1, &m_vao);
		}
		if (m_vbo)
		{
			gl.deleteBuffers(1, &m_vbo);
		}
	}

	IterateResult iterate()
	{

		tcu::TestLog&		  log = m_testCtx.getLog();
		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
		ClipControlApi		  cc(m_context);

		//Enable GL_CULL_FACE, leave default front face & cull face(CCW, BACK)
		gl.enable(GL_CULL_FACE);

		//Render a counter-clockwise triangles covering
		//(-1.0, -1.0) to(0.0, 1.0) and write a pixel value of green(0, 1, 0).
		//Render a clockwise triangles covering
		//(0.0, -1.0) to(1.0, 1.0) and write a pixel value of green(0, 1, 0).
		de::SharedPtr<glu::ShaderProgram> program(
					new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));

		log << (*program);
		if (!program->isOk())
		{
			TCU_FAIL("Program compilation failed");
		}

		gl.genVertexArrays(1, &m_vao);
		gl.bindVertexArray(m_vao);

		gl.genBuffers(1, &m_vbo);

		const float vertex_data0[] = {
			//CCW
			-1.0, -1.0, 0.0, -1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 1.0, -1.0, 1.0,
			//CW
			0.0, -1.0, 0.0, 1.0, 1.0, -1.0, 1.0, -1.0, 0.0, 1.0, 1.0, 1.0,
		};

		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);

		gl.vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
		gl.enableVertexAttribArray(0);

		gl.useProgram(program->getProgram());

		glw::GLenum origins[] = { GL_UPPER_LEFT, GL_LOWER_LEFT };

		qpTestResult result = QP_TEST_RESULT_PASS;

		for (size_t orig = 0; orig < DE_LENGTH_OF_ARRAY(origins); orig++)
		{
			//Clear the framebuffer to red (1,0,0).
			gl.clearColor(1.0, 0.0, 0.0, 1.0);
			gl.clear(GL_COLOR_BUFFER_BIT);

			gl.drawArrays(GL_TRIANGLES, 0, 12);

			//Set ClipControl(<origin>, NEGATIVE_ONE_TO_ONE)
			cc.clipControl(origins[orig], GL_NEGATIVE_ONE_TO_ONE);
			GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");

			//Read back the framebuffer with ReadPixels
			//Verify the green pixels at the left and red at the right.
			qpTestResult loopResult = ValidateFramebuffer(m_context);
			if (loopResult != QP_TEST_RESULT_PASS)
			{
				result = loopResult;
			}
		}
		m_testCtx.setTestResult(result, qpGetTestResultName(result));

		return STOP;
	}

	const char* vsh()
	{
		return "attribute  highp vec3 Position;"
			   "\n"
			   "void main() {"
			   "\n"
			   "    gl_Position = vec4(Position, 1.0);"
			   "\n"
			   "}";
	}

	qpTestResult ValidateFramebuffer(Context& context)
	{
		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
		glw::GLsizei			 viewportW	= renderTarget.getWidth();
		glw::GLsizei			 viewportH	= renderTarget.getHeight();
		tcu::Surface			 renderedColorFrame(viewportW, viewportH);
		tcu::Surface			 referenceColorFrame(viewportW, viewportH);
		tcu::TestLog&			 log = context.getTestContext().getLog();

		for (int y = 0; y < renderedColorFrame.getHeight(); y++)
		{
			for (int x = 0; x < renderedColorFrame.getWidth(); x++)
			{
				float xCoord = (float)(x) / (float)renderedColorFrame.getWidth();

				if (xCoord < 0.5f)
				{
					referenceColorFrame.setPixel(x, y, tcu::RGBA::green());
				}
				else
				{
					referenceColorFrame.setPixel(x, y, tcu::RGBA::red());
				}
			}
		}

		glu::readPixels(context.getRenderContext(), 0, 0, renderedColorFrame.getAccess());
		if (!tcu::fuzzyCompare(log, "Result", "Color image comparison result", referenceColorFrame, renderedColorFrame,
							   0.05f, tcu::COMPARE_LOG_RESULT))
		{

			return QP_TEST_RESULT_FAIL;
		}
		return QP_TEST_RESULT_PASS;
	}

	glw::GLuint m_vao, m_vbo;
};

/*
 Viewport Bounds Test

 * Viewport bounds should be tested, to ensure that rendering with flipped
 origin affects only viewport area.

 This can be done by clearing the window to blue, making viewport
 a non-symmetric-in-any-way subset of the window, than rendering
 full-viewport multiple color quad. The (-1.0, -1.0)..(0.0, 0.0) quadrant
 of a quad is red, the rest is green.
 Whatever the origin is, the area outside of the viewport should stay blue.
 If origin is LOWER_LEFT the "lower left" portion of the viewport is red,
 if origin is UPPER_LEFT the "top left" portion of the viewport is red
 (and in both cases the rest of viewport is green).

 Here is the basic outline of the test:

 - Clear the default framebuffer to blue (0,0,1).
 - Set viewport to A = (x, y, w, h) = (1/8, 1/4, 1/2, 1/4)  in terms of proportional window size
 - Set ClipControl(UPPER_LEFT, NEGATIVE_ONE_TO_ONE)
 - Render a triangle strip covering (-1.0, -1.0) to (1.0, 1.0).
 Write a pixel value of red (0,1,0) to (-1.0, -1.0)..(0.0, 0.0), other parts are green
 - Reset viewport to defaults
 - Read back the default framebuffer with ReadPixels
 - Verify:
 - regions outside A viewport are green
 - Inside A viewport upper upper left portion is red, rest is green.

 Repeat the above test with LOWER_LEFT origin and lower left portion of A is red,
 rest is green.
 */
class ClipControlViewportBounds : public ClipControlRenderBaseTest
{
public:
	ClipControlViewportBounds(Context& context, const char* name)
		: ClipControlRenderBaseTest(context,  name, "Clip Control Origin Test"), m_vao(0), m_vbo(0)
	{
	}

	void deinit() override
	{
		ClipControlRenderBaseTest::deinit();

		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
		glw::GLsizei				 windowW	  = renderTarget.getWidth();
		glw::GLsizei				 windowH	  = renderTarget.getHeight();
		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();

		if (ClipControlApi::Supported(m_context))
		{
			ClipControlApi cc(m_context);
			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
		}

		gl.clearColor(0.0, 0.0, 0.0, 0.0);
		gl.viewport(0, 0, windowW, windowH);

		if (m_vao)
		{
			gl.deleteVertexArrays(1, &m_vao);
		}
		if (m_vbo)
		{
			gl.deleteBuffers(1, &m_vbo);
		}
	}

	IterateResult iterate() override
	{
		tcu::TestLog&			 log		  = m_testCtx.getLog();
		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();
		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
		glw::GLsizei			 windowW	  = renderTarget.getWidth();
		glw::GLsizei			 windowH	  = renderTarget.getHeight();
		ClipControlApi			 cc(m_context);

		//Clear the default framebuffer to blue (0,0,1).
		gl.clearColor(0.0, 0.0, 1.0, 1.0);
		gl.clear(GL_COLOR_BUFFER_BIT);

		de::SharedPtr<glu::ShaderProgram> program(
					new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));

		log << (*program);
		if (!program->isOk())
		{
			TCU_FAIL("Program compilation failed");
		}
		gl.genVertexArrays(1, &m_vao);
		gl.bindVertexArray(m_vao);

		gl.genBuffers(1, &m_vbo);

		const float vertex_data0[] = { -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0 };

		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);

		gl.vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
		gl.enableVertexAttribArray(0);

		gl.useProgram(program->getProgram());

		glw::GLenum origins[] = { GL_UPPER_LEFT, GL_LOWER_LEFT };

		qpTestResult result = QP_TEST_RESULT_PASS;

		for (size_t orig = 0; orig < DE_LENGTH_OF_ARRAY(origins); orig++)
		{
			//Set viewport to A = (x, y, w, h) = (1/8, 1/4, 1/2, 1/4) in terms of proportional window size
			gl.viewport(static_cast<glw::GLint>((0.125f * static_cast<float>(windowW))+0.5f),
						static_cast<glw::GLint>((0.25f * static_cast<float>(windowH))+0.5f),
						static_cast<glw::GLsizei>((0.5f * static_cast<float>(windowW))+0.5f),
						static_cast<glw::GLsizei>((0.25f * static_cast<float>(windowH))+0.5f));

			//Set ClipControl(<origin>, NEGATIVE_ONE_TO_ONE)
			cc.clipControl(origins[orig], GL_NEGATIVE_ONE_TO_ONE);
			GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");

			//Render a triangle strip covering (-1.0, -1.0) to (1.0, 1.0).
			//Write a pixel value of red (0,1,0) to (-1.0, -1.0)..(0.0, 0.0), other parts are green
			gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);

			gl.viewport(0, 0, windowW, windowH);

			//Read back the default framebuffer with ReadPixels
			//Verify the green pixels at the top and red at the bottom.
			qpTestResult loopResult = ValidateFramebuffer(m_context, origins[orig]);
			if (loopResult != QP_TEST_RESULT_PASS)
			{
				result = loopResult;
			}
		}
		m_testCtx.setTestResult(result, qpGetTestResultName(result));
		return STOP;
	}

	const char* vsh()
	{
		return "attribute highp vec2 Position;"
			   "\n"
			   "varying highp vec2 PositionOut;"
			   "\n"
			   "void main() {"
			   "\n"
			   "    gl_Position = vec4(Position, 0.0, 1.0);"
			   "\n"
			   "    PositionOut = Position;"
			   "\n"
			   "}";
	}

	const char* fsh()
	{
		return "varying highp vec2 PositionOut;"
			   "\n"
			   "void main() {"
			   "\n"
			   "    if (PositionOut.x < 0.0 && PositionOut.y < 0.0)"
			   "\n"
			   "       gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);"
			   "\n"
			   "    else"
			   "\n"
			   "       gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);"
			   "\n"
			   "}";
	}

	qpTestResult ValidateFramebuffer(Context& context, glw::GLenum origin)
	{
		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
		glw::GLsizei				 windowW	  = renderTarget.getWidth();
		glw::GLsizei				 windowH	  = renderTarget.getHeight();
		tcu::Surface			 renderedFrame(windowW, windowH);
		tcu::Surface			 referenceFrame(windowW, windowH);

		tcu::TestLog& log = context.getTestContext().getLog();

		for (int y = 0; y < renderedFrame.getHeight(); y++)
		{
			float yCoord   = static_cast<float>(y) / static_cast<float>(renderedFrame.getHeight());
			float yVPCoord = (yCoord - 0.25f) * 4.0f;

			for (int x = 0; x < renderedFrame.getWidth(); x++)
			{
				float xCoord   = static_cast<float>(x) / static_cast<float>(renderedFrame.getWidth());
				float xVPCoord = (xCoord - 0.125f) * 2.0f;

				if (xVPCoord > 0.0f && xVPCoord < 1.0f && yVPCoord > 0.0f && yVPCoord < 1.0f)
				{

					bool greenQuadrant;

					//inside viewport
					if (origin == GL_UPPER_LEFT)
					{
						greenQuadrant = (yVPCoord > 0.5f && xVPCoord <= 0.5f);
					}
					else
					{
						greenQuadrant = (yVPCoord <= 0.5f && xVPCoord <= 0.5f);
					}

					if (greenQuadrant)
					{
						referenceFrame.setPixel(x, y, tcu::RGBA::green());
					}
					else
					{
						referenceFrame.setPixel(x, y, tcu::RGBA::red());
					}
				}
				else
				{
					//outside viewport
					referenceFrame.setPixel(x, y, tcu::RGBA::blue());
				}
			}
		}

		glu::readPixels(context.getRenderContext(), 0, 0, renderedFrame.getAccess());

		if (tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f,
							  tcu::COMPARE_LOG_RESULT))
		{
			return QP_TEST_RESULT_PASS;
		}
		else
		{
			return QP_TEST_RESULT_FAIL;
		}
	}

	glw::GLuint m_vao, m_vbo;
};

/*   Depth Mode Test

 * Basic <depth> behavior can be tested by writing specific z_c (z
 clip coordinates) and observing its clipping and transformation.
 Create and bind a framebuffer object with a floating-point depth
 buffer attachment. Make sure depth clamping is disabled. The best
 steps for verifying the correct depth mode:

 - Clear the depth buffer to 0.5.
 - Set ClipControl(LOWER_LEFT, ZERO_TO_ONE)
 - Enable(DEPTH_TEST) with DepthFunc(ALWAYS)
 - Render a triangle fan coverage (-1.0,-1.0,-1.0) to (1.0,1.0,1.0).
 - Read back the floating-point depth buffer with ReadPixels
 - Verify that the pixels with a Z clip coordinate less than 0.0 are
 clipped and those coordinates from 0.0 to 1.0 update the depth
 buffer with values 0.0 to 1.0.
 */

class ClipControlDepthModeTest : public ClipControlRenderBaseTest
{
public:
	ClipControlDepthModeTest(Context& context, const char* name, const char* subname)
		: ClipControlRenderBaseTest(context, name, subname)
	{

	}

	void init() override
	{
		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();
		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
		glw::GLuint				 viewportW	= renderTarget.getWidth();
		glw::GLuint				 viewportH	= renderTarget.getHeight();

		ClipControlRenderBaseTest::init();

		gl.genFramebuffers(1, &m_fboD);

		gl.genTextures(1, &m_texDepthResolve);
		gl.bindTexture(GL_TEXTURE_2D, m_texDepthResolve);
		setupTexture();
		gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, viewportW, viewportH, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
	}

	void deinit() override
	{
		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();

		gl.deleteTextures(1, &m_texDepthResolve);
		gl.deleteFramebuffers(1, &m_fboD);

		ClipControlRenderBaseTest::deinit();
	}

	void setupTexture()
	{
		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();
		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	}

	void readDepthPixels(const tcu::PixelBufferAccess& pixelBuf)
	{

		const char* vs = "\n"
						 "attribute vec4 pos;\n"
						 "attribute vec2 UV;\n"
						 "varying highp vec2 vUV;\n"
						 "void main() {\n"
						 "  gl_Position = pos;\n"
						 "  vUV = UV;\n"
						 "}\n";

		const char* fs = "\n"
						 "precision mediump float;\n"
						 "varying vec2 vUV;\n"
						 "uniform sampler2D tex;\n"
						 "void main() {\n"
						 "  gl_FragColor = texture2D(tex, vUV).rrrr;\n"
						 "}\n";

		const glu::RenderContext&	renderContext	= m_context.getRenderContext();
		const glw::Functions&		gl				= renderContext.getFunctions();
		const tcu::RenderTarget&	renderTarget	= renderContext.getRenderTarget();
		glw::GLsizei				windowW			= renderTarget.getWidth();
		glw::GLsizei				windowH			= renderTarget.getHeight();

		glu::ShaderProgram program(renderContext,  glu::makeVtxFragSources(vs, fs));

		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboD);
		gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texDepthResolve, 0);

		gl.disable(GL_DEPTH_TEST);
		gl.depthMask(GL_FALSE);
		gl.disable(GL_STENCIL_TEST);
		gl.viewport(0, 0, windowW, windowH);
		gl.clearColor(0.0f, 0.2f, 1.0f, 1.0f);
		gl.clear(GL_COLOR_BUFFER_BIT);

		const int	texLoc	= gl.getUniformLocation(program.getProgram(), "tex");

		gl.bindVertexArray(0);
		gl.bindBuffer(GL_ARRAY_BUFFER, 0);

		gl.bindTexture(GL_TEXTURE_2D, getDepthTexture());
		setupTexture();

		gl.useProgram(program.getProgram());
		gl.uniform1i(texLoc, 0);

		{
			const GLfloat vertices[] = {
				-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 GLfloat texCoords[] = {
				0.0f, 0.0f,
				1.0f, 0.0f,
				0.0f, 1.0f,
				1.0f, 1.0f,
			};
			const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };

			const glu::VertexArrayBinding	vertexArray[]	= { glu::va::Float("pos", 4, 4, 0, vertices),
																glu::va::Float("UV", 2, 4, 0, texCoords) };

			glu::draw(renderContext, program.getProgram(), 2, vertexArray,
					  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), indices));
		}
		glu::readPixels(renderContext, 0, 0, pixelBuf);
	}

	GLuint m_fboD;
	GLuint m_texDepthResolve;

};

class ClipControlDepthModeZeroToOneTest : public ClipControlDepthModeTest
{
public:
	ClipControlDepthModeZeroToOneTest(Context& context, const char* name)
		: ClipControlDepthModeTest(context, name, "Depth Mode Test, ZERO_TO_ONE"), m_vao(0), m_vbo(0)
	{

	}

	void deinit() override
	{
		ClipControlDepthModeTest::deinit();

		const glw::Functions& gl = m_context.getRenderContext().getFunctions();

		if (ClipControlApi::Supported(m_context))
		{
			ClipControlApi cc(m_context);
			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
		}

		gl.clearDepthf(0.0f);
		gl.clearColor(0.0, 0.0, 0.0, 0.0);

		gl.disable(GL_DEPTH_TEST);
		gl.depthFunc(GL_LESS);

		if (m_vao)
		{
			gl.deleteVertexArrays(1, &m_vao);
		}
		if (m_vbo)
		{
			gl.deleteBuffers(1, &m_vbo);
		}
	}

	IterateResult iterate() override
	{

		tcu::TestLog&		  log = m_testCtx.getLog();
		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
		ClipControlApi		  cc(m_context);

		gl.clearColor(1.0, 0.0, 0.0, 1.0);
		gl.clear(GL_COLOR_BUFFER_BIT);

		//Clear the depth buffer to 0.5.
		gl.clearDepthf(0.5);
		gl.clear(GL_DEPTH_BUFFER_BIT);

		//Set ClipControl(LOWER_LEFT, ZERO_TO_ONE)
		cc.clipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
		GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");

		//Enable(DEPTH_TEST) with DepthFunc(ALWAYS)
		gl.enable(GL_DEPTH_TEST);
		gl.depthFunc(GL_ALWAYS);

		//Render a triangle fan coverage (-1.0,-1.0,-1.0) to (1.0,1.0,1.0).
		de::SharedPtr<glu::ShaderProgram> program(
					new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));

		log << (*program);
		if (!program->isOk())
		{
			TCU_FAIL("Program compilation failed");
		}

		gl.genVertexArrays(1, &m_vao);
		gl.bindVertexArray(m_vao);

		gl.genBuffers(1, &m_vbo);

		const float vertex_data0[] = {
			-1.0, -1.0, -1.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0,
		};

		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);

		gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		gl.enableVertexAttribArray(0);

		gl.useProgram(program->getProgram());

		//test method modification: use GL_TRIANGLE_STRIP, not FAN.
		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);

		//Read back the floating-point depth buffer with ReadPixels
		//Verify that the pixels with a Z clip coordinate less than 0.0 are
		//  clipped and those coordinates from 0.0 to 1.0 update the depth
		//  buffer with values 0.0 to 1.0.
		qpTestResult result = ValidateFramebuffer(m_context);
		m_testCtx.setTestResult(result, qpGetTestResultName(result));

		return STOP;
	}

	const char* vsh()
	{
		return "attribute vec3 Position;"
			   "\n"
			   "void main() {"
			   "\n"
			   "    gl_Position = vec4(Position, 1.0);"
			   "\n"
			   "}";
	}

	qpTestResult ValidateFramebuffer(Context& context)
	{
		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
		glw::GLuint				 viewportW	= renderTarget.getWidth();
		glw::GLuint				 viewportH	= renderTarget.getHeight();
		tcu::Surface			 renderedColorFrame(viewportW, viewportH);
		tcu::Surface			 referenceColorFrame(viewportW, viewportH);
		tcu::TextureFormat		 depthReadbackFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
		tcu::TextureFormat		 depthFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
		tcu::TextureLevel		 renderedDepthFrame(depthReadbackFormat, viewportW, viewportH);
		tcu::TextureLevel		 referenceDepthFrame(depthFormat, viewportW, viewportH);
		tcu::TextureLevel		 importanceMaskFrame(depthFormat, viewportW, viewportH);

		tcu::TestLog& log = context.getTestContext().getLog();

		const float rasterizationError =
				2.0f / (float)renderedColorFrame.getHeight() + 2.0f / (float)renderedColorFrame.getWidth();

		for (int y = 0; y < renderedColorFrame.getHeight(); y++)
		{
			float yCoord = ((float)(y) + 0.5f) / (float)renderedColorFrame.getHeight();

			for (int x = 0; x < renderedColorFrame.getWidth(); x++)
			{
				float xCoord = ((float)(x) + 0.5f) / (float)renderedColorFrame.getWidth();

				if (yCoord >= 1.0 - xCoord - rasterizationError && yCoord <= 1.0 - xCoord + rasterizationError)
				{
					importanceMaskFrame.getAccess().setPixDepth(0.0f, x, y);
				}
				else
				{
					importanceMaskFrame.getAccess().setPixDepth(1.0f, x, y);
				}

				if (yCoord < 1.0 - xCoord)
				{
					referenceColorFrame.setPixel(x, y, tcu::RGBA::red());
					referenceDepthFrame.getAccess().setPixDepth(0.5f, x, y);
				}
				else
				{
					referenceColorFrame.setPixel(x, y, tcu::RGBA::green());

					referenceDepthFrame.getAccess().setPixDepth(-1.0f + xCoord + yCoord, x, y);
				}
			}
		}

		glu::readPixels(context.getRenderContext(), 0, 0, renderedColorFrame.getAccess());
		if (!tcu::fuzzyCompare(log, "Result", "Color image comparison result", referenceColorFrame, renderedColorFrame,
							   0.05f, tcu::COMPARE_LOG_RESULT))
		{

			return QP_TEST_RESULT_FAIL;
		}

		readDepthPixels(renderedDepthFrame.getAccess());
		if (!fuzzyDepthCompare(log, "Result", "Depth image comparison result", referenceDepthFrame, renderedDepthFrame,
							   0.05f, &importanceMaskFrame))
		{
			return QP_TEST_RESULT_FAIL;
		}
		return QP_TEST_RESULT_PASS;
	}

	glw::GLuint m_vao, m_vbo;
};

/*
 Do the same as above, but use the default NEGATIVE_ONE_TO_ONE depth mode:

 - Clear the depth buffer to 0.5.
 - Set ClipControl(LOWER_LEFT, NEGATIVE_ONE_TO_ONE)
 - Enable(DEPTH_TEST) with DepthFunc(ALWAYS)
 - Render a triangle fan coverage (-1.0,-1.0,-1.0) to (1.0,1.0,1.0).
 - Read back the floating-point depth buffer with ReadPixels
 - Verify that no pixels are clipped and the depth buffer contains
 values from 0.0 to 1.0.
 */
class ClipControlDepthModeOneToOneTest : public ClipControlDepthModeTest
{
public:
	ClipControlDepthModeOneToOneTest(Context& context, const char* name)
		: ClipControlDepthModeTest(context, name, "Depth Mode Test, ONE_TO_ONE"), m_vao(0), m_vbo(0)
	{
	}

	void deinit() override
	{
		ClipControlDepthModeTest::deinit();

		const glw::Functions& gl = m_context.getRenderContext().getFunctions();

		if (ClipControlApi::Supported(m_context))
		{
			ClipControlApi cc(m_context);
			cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
		}

		gl.clearDepthf(0.0);
		gl.clearColor(0.0, 0.0, 0.0, 0.0);

		gl.disable(GL_DEPTH_TEST);
		gl.depthFunc(GL_LESS);

		if (m_vao)
		{
			gl.deleteVertexArrays(1, &m_vao);
		}
		if (m_vbo)
		{
			gl.deleteBuffers(1, &m_vbo);
		}
	}

	IterateResult iterate() override
	{
		tcu::TestLog&		  log = m_testCtx.getLog();
		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
		ClipControlApi		  cc(m_context);

		gl.clearColor(1.0, 0.0, 0.0, 1.0);
		gl.clear(GL_COLOR_BUFFER_BIT);

		//Clear the depth buffer to 0.5.
		gl.clearDepthf(0.5f);
		gl.clear(GL_DEPTH_BUFFER_BIT);

		//Set ClipControl(LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE)
		cc.clipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
		GLU_EXPECT_NO_ERROR(gl.getError(), "ClipControl()");

		//Enable(DEPTH_TEST) with DepthFunc(ALWAYS)
		gl.enable(GL_DEPTH_TEST);
		gl.depthFunc(GL_ALWAYS);

		//Render a triangle fan coverage (-1.0,-1.0,-1.0) to (1.0,1.0,1.0).
		de::SharedPtr<glu::ShaderProgram> program(
					new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vsh(), fsh())));

		log << (*program);
		if (!program->isOk())
		{
			TCU_FAIL("Program compilation failed");
		}

		gl.genVertexArrays(1, &m_vao);
		gl.bindVertexArray(m_vao);

		gl.genBuffers(1, &m_vbo);

		const float vertex_data0[] = {
			-1.0, -1.0, -1.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0,
		};

		gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
		gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertex_data0), vertex_data0, GL_STATIC_DRAW);

		gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		gl.enableVertexAttribArray(0);

		gl.useProgram(program->getProgram());

		//test method modification: use GL_TRIANGLE_STRIP, not FAN.
		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);

		//Read back the floating-point depth buffer with ReadPixels
		//Verify that the pixels with a Z clip coordinate less than 0.0 are
		//  clipped and those coordinates from 0.0 to 1.0 update the depth
		//  buffer with values 0.0 to 1.0.
		qpTestResult result = ValidateFramebuffer(m_context);
		m_testCtx.setTestResult(result, qpGetTestResultName(result));

		return STOP;
	}

	const char* vsh()
	{
		return "attribute vec3 Position;"
			   "\n"
			   "void main() {"
			   "\n"
			   "    gl_Position = vec4(Position, 1.0);"
			   "\n"
			   "}";
	}

	qpTestResult ValidateFramebuffer(Context& context)
	{
		const tcu::RenderTarget& renderTarget = context.getRenderContext().getRenderTarget();
		glw::GLuint				 viewportW	= renderTarget.getWidth();
		glw::GLuint				 viewportH	= renderTarget.getHeight();
		tcu::Surface			 renderedColorFrame(viewportW, viewportH);
		tcu::Surface			 referenceColorFrame(viewportW, viewportH);
		tcu::TextureFormat		 depthReadbackFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
		tcu::TextureFormat		 depthFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
		tcu::TextureLevel		 renderedDepthFrame(depthReadbackFormat, viewportW, viewportH);
		tcu::TextureLevel		 referenceDepthFrame(depthFormat, viewportW, viewportH);

		tcu::TestLog& log = context.getTestContext().getLog();

		for (int y = 0; y < renderedColorFrame.getHeight(); y++)
		{
			float yCoord = (float)(y) / (float)renderedColorFrame.getHeight();
			for (int x = 0; x < renderedColorFrame.getWidth(); x++)
			{
				float xCoord = (float)(x) / (float)renderedColorFrame.getWidth();

				referenceColorFrame.setPixel(x, y, tcu::RGBA::green());
				referenceDepthFrame.getAccess().setPixDepth((xCoord + yCoord) * 0.5f, x, y);
			}
		}

		glu::readPixels(context.getRenderContext(), 0, 0, renderedColorFrame.getAccess());
		if (!tcu::fuzzyCompare(log, "Result", "Color image comparison result", referenceColorFrame, renderedColorFrame,
							   0.05f, tcu::COMPARE_LOG_RESULT))
		{
			return QP_TEST_RESULT_FAIL;
		}

		readDepthPixels(renderedDepthFrame.getAccess());
		if (!fuzzyDepthCompare(log, "Result", "Depth image comparison result", referenceDepthFrame, renderedDepthFrame,
							   0.05f))
		{
			return QP_TEST_RESULT_FAIL;
		}

		return QP_TEST_RESULT_PASS;
	}

	glw::GLuint m_vao, m_vbo;
};


/** Constructor.
 *
 *  @param context Rendering context.
 **/
ClipControlTests::ClipControlTests(Context& context)
	: TestCaseGroup(context, "clip_control", "Verifies \"clip_control\" functionality")
{
	/* Left blank on purpose */
}

/** Destructor.
 *
 **/
ClipControlTests::~ClipControlTests()
{
}

/** Initializes a texture_storage_multisample test group.
 *
 **/
void ClipControlTests::init(void)
{
	addChild(new ClipControlInitialState(m_context, "initial"));
	addChild(new ClipControlModifyGetState(m_context, "modify_get"));
	addChild(new ClipControlErrors(m_context, "errors"));
	addChild(new ClipControlOriginTest(m_context, "origin"));
	addChild(new ClipControlDepthModeZeroToOneTest(m_context, "depth_mode_zero_to_one"));
	addChild(new ClipControlDepthModeOneToOneTest(m_context, "depth_mode_one_to_one"));
	addChild(new ClipControlFaceCulling(m_context, "face_culling"));
	addChild(new ClipControlViewportBounds(m_context, "viewport_bounds"));
}
}
}
}

