/*-------------------------------------------------------------------------
 * 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)),
						static_cast<glw::GLint>(0.25f * static_cast<float>(windowH)),
						static_cast<glw::GLsizei>(0.5f * static_cast<float>(windowW)),
						static_cast<glw::GLsizei>(0.25f * static_cast<float>(windowH)));

			//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"));
}
}
}
}

