/*-------------------------------------------------------------------------
 * 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.deleteRenderbuffers(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"));
}
}
}
}

