/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL (ES) Module
 * -----------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief GLES Scissor tests
 *//*--------------------------------------------------------------------*/

#include "glsScissorTests.hpp"
#include "glsTextureTestUtil.hpp"

#include "deMath.h"
#include "deRandom.hpp"
#include "deUniquePtr.hpp"

#include "tcuTestCase.hpp"
#include "tcuImageCompare.hpp"
#include "tcuVector.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuTexture.hpp"
#include "tcuStringTemplate.hpp"

#include "gluStrUtil.hpp"
#include "gluDrawUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "gluObjectWrapper.hpp"

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

#include <map>

namespace deqp
{
namespace gls
{
namespace Functional
{
namespace
{

using namespace ScissorTestInternal;
using namespace glw; // GL types

using tcu::ConstPixelBufferAccess;
using tcu::PixelBufferAccess;
using tcu::TestLog;

using std::vector;
using std::string;
using std::map;
using tcu::Vec3;
using tcu::Vec4;
using tcu::IVec4;
using tcu::UVec4;

void drawQuad (const glw::Functions& gl, deUint32 program, const Vec3& p0, const Vec3& p1)
{
	// Vertex data.
	const float hz = (p0.z() + p1.z()) * 0.5f;
	const float position[] =
	{
		p0.x(), p0.y(), p0.z(),	1.0f,
		p0.x(), p1.y(), hz,		1.0f,
		p1.x(), p0.y(), hz,		1.0f,
		p1.x(), p1.y(), p1.z(),	1.0f
	};

	const deUint16	indices[]	= { 0, 1, 2, 2, 1, 3 };

	const deInt32	posLoc		= gl.getAttribLocation(program, "a_position");

	gl.useProgram(program);
	gl.enableVertexAttribArray(posLoc);
	gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);

	gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0]);

	gl.disableVertexAttribArray(posLoc);

}

void drawPrimitives (const glw::Functions& gl, deUint32 program, const deUint32 type, const vector<float>& vertices, const vector<deUint16>& indices)
{
	const deInt32 posLoc = gl.getAttribLocation(program, "a_position");

	TCU_CHECK(posLoc >= 0);

	gl.useProgram(program);
	gl.enableVertexAttribArray(posLoc);
	gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &vertices[0]);

	gl.drawElements(type, GLsizei(indices.size()), GL_UNSIGNED_SHORT, &indices[0]);

	gl.disableVertexAttribArray(posLoc);
}

template<typename T>
void clearEdges (const tcu::PixelBufferAccess& access, const T& color, const IVec4& scissorArea)
{
	for (int y = 0; y < access.getHeight(); y++)
	for (int x = 0; x < access.getWidth(); x++)
	{
		if (y < scissorArea.y() ||
			y >= scissorArea.y() + scissorArea.w() ||
			x < scissorArea.x() ||
			x >= scissorArea.x()+ scissorArea.z())
			access.setPixel(color, x, y);
	}
}

glu::ProgramSources genShaders(glu::GLSLVersion version)
{
	const string vtxSource = "${VERSION}\n"
							 "${IN} highp vec4 a_position;\n"
							 "void main(){\n"
							 "	gl_Position = a_position;\n"
							 "}\n";

	const string frgSource = "${VERSION}\n"
							 "${OUT_DECL}"
							 "uniform highp vec4 u_color;\n"
							 "void main(){\n"
							 "	${OUTPUT} = u_color;\n"
							 "}\n";

	map<string, string>	params;

	switch(version)
	{
		case glu::GLSL_VERSION_100_ES:
			params["VERSION"] = "#version 100";
			params["IN"] = "attribute";
			params["OUT_DECL"] = "";
			params["OUTPUT"] = "gl_FragColor";
			break;

		case glu::GLSL_VERSION_300_ES:
		case glu::GLSL_VERSION_310_ES: // Assumed to support 3.0
			params["VERSION"] = "#version 300 es";
			params["IN"] = "in";
			params["OUT_DECL"] = "out mediump vec4 f_color;\n";
			params["OUTPUT"] = "f_color";
			break;

		default:
			DE_ASSERT(!"Unsupported version");
	}

	return glu::makeVtxFragSources(tcu::StringTemplate(vtxSource).specialize(params), tcu::StringTemplate(frgSource).specialize(params));
}

// Wrapper class, provides iterator & reporting logic
class ScissorCase : public tcu::TestCase
{
public:
							ScissorCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char *name, const char* desc, const Vec4& scissorArea);
	virtual					~ScissorCase	(void) {}

	virtual IterateResult	iterate			(void);

protected:
	virtual void			render			(GLuint program, const IVec4& viewport) const = 0;

	glu::RenderContext&		m_renderCtx;
	const Vec4				m_scissorArea;
};

ScissorCase::ScissorCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char *name, const char* desc, const Vec4& scissorArea)
	: TestCase		(testCtx, name, desc)
	, m_renderCtx	(renderCtx)
	, m_scissorArea	(scissorArea)
{
}

ScissorCase::IterateResult ScissorCase::iterate (void)
{
	using TextureTestUtil::RandomViewport;

	const glw::Functions&		gl				= m_renderCtx.getFunctions();
	TestLog&					log				= m_testCtx.getLog();
	const tcu::PixelFormat		renderFormat	= m_renderCtx.getRenderTarget().getPixelFormat();
	const tcu::Vec4				threshold		= 0.02f * UVec4(1u << de::max(0, 8 - renderFormat.redBits),
																1u << de::max(0, 8 - renderFormat.greenBits),
																1u << de::max(0, 8 - renderFormat.blueBits),
																1u << de::max(0, 8 - renderFormat.alphaBits)).asFloat();
	const glu::ShaderProgram	shader			(m_renderCtx, genShaders(glu::getContextTypeGLSLVersion(m_renderCtx.getType())));

	const RandomViewport		viewport		(m_renderCtx.getRenderTarget(), 256, 256, deStringHash(getName()));
	const IVec4					relScissorArea	(int(m_scissorArea.x()*viewport.width),
												 int(m_scissorArea.y()*viewport.height),
												 int(m_scissorArea.z()*viewport.width),
												 int(m_scissorArea.w()*viewport.height));
	const IVec4					absScissorArea	(relScissorArea.x() + viewport.x,
												 relScissorArea.y() + viewport.y,
												 relScissorArea.z(),
												 relScissorArea.w());

	tcu::Surface				refImage		(viewport.width, viewport.height);
	tcu::Surface				resImage		(viewport.width, viewport.height);

	if (!shader.isOk())
	{
		log << shader;
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader compile/link failed");
		return STOP;
	}

	log << TestLog::Message << "Viewport area is " << IVec4(viewport.x, viewport.y, viewport.width, viewport.height) << TestLog::EndMessage;
	log << TestLog::Message << "Scissor area is " << absScissorArea << TestLog::EndMessage;

	// Render reference (no scissors)
	{
		log << TestLog::Message << "Rendering reference (scissors disabled)" << TestLog::EndMessage;

		gl.useProgram(shader.getProgram());
		gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

		gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
		gl.clearDepthf(1.0f);
		gl.clearStencil(0);
		gl.disable(GL_DEPTH_TEST);
		gl.disable(GL_STENCIL_TEST);
		gl.disable(GL_SCISSOR_TEST);
		gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

		render(shader.getProgram(), IVec4(viewport.x, viewport.y, viewport.width, viewport.height));

		glu::readPixels(m_renderCtx, viewport.x, viewport.y, refImage.getAccess());
		GLU_CHECK_ERROR(gl.getError());
	}

	// Render result (scissors)
	{
		log << TestLog::Message << "Rendering result (scissors enabled)" << TestLog::EndMessage;

		gl.useProgram(shader.getProgram());
		gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

		gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
		gl.clearDepthf(1.0f);
		gl.clearStencil(0);
		gl.disable(GL_DEPTH_TEST);
		gl.disable(GL_STENCIL_TEST);
		gl.disable(GL_SCISSOR_TEST);
		gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

		gl.scissor(absScissorArea.x(), absScissorArea.y(), absScissorArea.z(), absScissorArea.w());
		gl.enable(GL_SCISSOR_TEST);

		render(shader.getProgram(), IVec4(viewport.x, viewport.y, viewport.width, viewport.height));

		glu::readPixels(m_renderCtx, viewport.x, viewport.y, resImage.getAccess());
		GLU_CHECK_ERROR(gl.getError());
	}

	// Manual 'scissors' for reference image
	log << TestLog::Message << "Clearing area outside scissor area from reference" << TestLog::EndMessage;
	clearEdges(refImage.getAccess(), IVec4(32, 64, 128, 255), relScissorArea);

	if (tcu::floatThresholdCompare(log, "ComparisonResult", "Image comparison result", refImage.getAccess(), resImage.getAccess(), threshold, tcu::COMPARE_LOG_RESULT))
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	else
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");

	return STOP;
}

// Tests scissoring with multiple primitive types
class ScissorPrimitiveCase : public ScissorCase
{
public:
								ScissorPrimitiveCase	(tcu::TestContext&		testCtx,
														 glu::RenderContext&	renderCtx,
														 const char*			name,
														 const char*			desc,
														 const Vec4&			scissorArea,
														 const Vec4&			renderArea,
														 PrimitiveType			type,
														 int					primitiveCount);
	virtual						~ScissorPrimitiveCase	(void){}

protected:
	virtual void				render					(GLuint program, const IVec4& viewport) const;

private:
	const Vec4					m_renderArea;
	const PrimitiveType			m_primitiveType;
	const int					m_primitiveCount;
};

ScissorPrimitiveCase::ScissorPrimitiveCase	(tcu::TestContext&		testCtx,
											 glu::RenderContext&	renderCtx,
											 const char*			name,
											 const char*			desc,
											 const Vec4&			scissorArea,
											 const Vec4&			renderArea,
											 PrimitiveType			type,
											 int					primitiveCount)
	: ScissorCase		(testCtx, renderCtx, name, desc, scissorArea)
	, m_renderArea		(renderArea)
	, m_primitiveType	(type)
	, m_primitiveCount	(primitiveCount)
{
}

void ScissorPrimitiveCase::render (GLuint program, const IVec4&) const
{
	const glw::Functions&		gl				= m_renderCtx.getFunctions();
	const Vec4					white			(1.0f, 1.0f, 1.0f, 1.0);
	const Vec4					primitiveArea	(m_renderArea.x()*2.0f-1.0f,
												 m_renderArea.x()*2.0f-1.0f,
												 m_renderArea.z()*2.0f,
												 m_renderArea.w()*2.0f);

	static const float quadPositions[] =
	{
		 0.0f,  1.0f,
		 0.0f,  0.0f,
		 1.0f,  1.0f,
		 1.0f,  0.0f
	};
	static const float triPositions[] =
	{
		 0.0f,  0.0f,
		 1.0f,  0.0f,
		 0.5f,  1.0f,
	};
	static const float linePositions[] =
	{
		 0.0f,  0.0f,
		 1.0f,  1.0f
	};
	static const float pointPosition[] =
	{
		 0.5f,  0.5f
	};

	const float*		positionSet[]	= { pointPosition, linePositions, triPositions, quadPositions };
	const int			vertexCountSet[]= { 1, 2, 3, 4 };
	const int			indexCountSet[]	= { 1, 2, 3, 6 };

	const deUint16		baseIndices[]	= { 0, 1, 2, 2, 1, 3 };
	const float*		basePositions	= positionSet[m_primitiveType];
	const int			vertexCount		= vertexCountSet[m_primitiveType];
	const int			indexCount		= indexCountSet[m_primitiveType];

	const float			scale			= 1.44f/deFloatSqrt(float(m_primitiveCount)*2.0f); // Magic value to roughly fill the render area with primitives at a readable density
	vector<float>		positions		(4*vertexCount*m_primitiveCount);
	vector<deUint16>	indices			(indexCount*m_primitiveCount);
	de::Random			rng				(1234);

	for (int primNdx = 0; primNdx < m_primitiveCount; primNdx++)
	{
		const float dx = m_primitiveCount>1 ? rng.getFloat() : 0.0f;
		const float dy = m_primitiveCount>1 ? rng.getFloat() : 0.0f;

		for (int vertNdx = 0; vertNdx < vertexCount; vertNdx++)
		{
			const int ndx = primNdx*4*vertexCount + vertNdx*4;
			positions[ndx+0] = (basePositions[vertNdx*2 + 0]*scale + dx)*primitiveArea.z() + primitiveArea.x();
			positions[ndx+1] = (basePositions[vertNdx*2 + 1]*scale + dy)*primitiveArea.w() + primitiveArea.y();
			positions[ndx+2] = 0.2f;
			positions[ndx+3] = 1.0f;
		}

		for (int ndx = 0; ndx < indexCount; ndx++)
			indices[primNdx*indexCount + ndx] = baseIndices[ndx] + primNdx*vertexCount;
	}

	gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, white.m_data);

	switch (m_primitiveType)
	{
		case TRIANGLE:	drawPrimitives(gl, program, GL_TRIANGLES,	positions, indices);	break;
		case LINE:		drawPrimitives(gl, program, GL_LINES,		positions, indices);	break;
		case POINT:		drawPrimitives(gl, program, GL_POINTS,		positions, indices);	break;
		default:		DE_ASSERT(false);													break;
	}
}

// Test effect of scissor on default framebuffer clears
class ScissorClearCase : public ScissorCase
{
public:
					ScissorClearCase	(tcu::TestContext&		testCtx,
										 glu::RenderContext&	renderCtx,
										 const char*			name,
										 const char*			desc,
										 const Vec4&			scissorArea,
										 deUint32				clearMode);
	virtual			~ScissorClearCase	(void) {}

	virtual void	init				(void);

protected:
	virtual void	render				(GLuint program, const IVec4& viewport) const;

private:
	const deUint32	m_clearMode; //!< Combination of the flags accepted by glClear
};

ScissorClearCase::ScissorClearCase	(tcu::TestContext&		testCtx,
									 glu::RenderContext&	renderCtx,
									 const char*			name,
									 const char*			desc,
									 const Vec4&			scissorArea,
									 deUint32				clearMode)
	: ScissorCase	(testCtx, renderCtx, name, desc, scissorArea)
	, m_clearMode	(clearMode)
{
}

void ScissorClearCase::init (void)
{
	if ((m_clearMode & GL_DEPTH_BUFFER_BIT) && m_renderCtx.getRenderTarget().getDepthBits() == 0)
		throw tcu::NotSupportedError("Cannot clear depth; no depth buffer present", "", __FILE__, __LINE__);
	else if ((m_clearMode & GL_STENCIL_BUFFER_BIT) && m_renderCtx.getRenderTarget().getStencilBits() == 0)
		throw tcu::NotSupportedError("Cannot clear stencil; no stencil buffer present", "", __FILE__, __LINE__);
}

void ScissorClearCase::render (GLuint program, const IVec4&) const
{
	const glw::Functions&	gl		= m_renderCtx.getFunctions();
	const Vec4				white	(1.0f, 1.0f, 1.0f, 1.0);

	gl.clearColor(0.6f, 0.1f, 0.1f, 1.0);
	gl.clearDepthf(0.0f);

	if (m_clearMode & GL_DEPTH_BUFFER_BIT)
	{
		gl.enable(GL_DEPTH_TEST);
		gl.depthFunc(GL_GREATER);
	}

	if (m_clearMode & GL_STENCIL_BUFFER_BIT)
	{
		gl.clearStencil(123);
		gl.enable(GL_STENCIL_TEST);
		gl.stencilFunc(GL_EQUAL, 123, ~0u);
	}

	if (m_clearMode & GL_COLOR_BUFFER_BIT)
		gl.clearColor(0.1f, 0.6f, 0.1f, 1.0);

	gl.clear(m_clearMode);
	gl.disable(GL_SCISSOR_TEST);

	gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, white.getPtr());

	if (!(m_clearMode & GL_COLOR_BUFFER_BIT))
		drawQuad(gl, program, Vec3(-1.0f, -1.0f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));

	gl.disable(GL_DEPTH_TEST);
	gl.disable(GL_STENCIL_TEST);
}

class FramebufferBlitCase : public ScissorCase
{
public:
					FramebufferBlitCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, const Vec4& scissorArea);
	virtual			~FramebufferBlitCase	(void) {}

	virtual void	init					(void);
	virtual void	deinit					(void);

protected:
	typedef de::MovePtr<glu::Framebuffer> FramebufferP;

	enum {SIZE = 64};

	virtual void	render					(GLuint program, const IVec4& viewport) const;

	FramebufferP	m_fbo;
};

FramebufferBlitCase::FramebufferBlitCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, const Vec4& scissorArea)
	: ScissorCase(testCtx, renderCtx, name, desc, scissorArea)
{
}

void FramebufferBlitCase::init (void)
{
	if (m_renderCtx.getRenderTarget().getNumSamples())
		throw tcu::NotSupportedError("Cannot blit to multisampled framebuffer", "", __FILE__, __LINE__);

	const glw::Functions&	gl			= m_renderCtx.getFunctions();
	const glu::Renderbuffer	colorbuf	(gl);
	const tcu::Vec4			clearColor	(1.0f, 0.5, 0.125f, 1.0f);

	m_fbo = FramebufferP(new glu::Framebuffer(gl));

	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, **m_fbo);

	gl.bindRenderbuffer(GL_RENDERBUFFER, *colorbuf);
	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SIZE, SIZE);
	gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorbuf);

	gl.clearBufferfv(GL_COLOR, 0, clearColor.getPtr());
	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_renderCtx.getDefaultFramebuffer());
}

void FramebufferBlitCase::deinit (void)
{
	m_fbo.clear();
}

void FramebufferBlitCase::render(GLuint program, const IVec4& viewport) const
{
	const glw::Functions&	gl					= m_renderCtx.getFunctions();

	const int				width				= viewport.z();
	const int				height				= viewport.w();
	const deInt32			defaultFramebuffer	= m_renderCtx.getDefaultFramebuffer();

	DE_UNREF(program);

	// blit to default framebuffer
	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, **m_fbo);
	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebuffer);

	gl.blitFramebuffer(0, 0, SIZE, SIZE, viewport.x(), viewport.y(), viewport.x() + width, viewport.y() + height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, defaultFramebuffer);
}

struct BufferFmtDesc
{
	tcu::TextureFormat	texFmt;
	GLenum				colorFmt;
};

struct Color
{
	enum Type {FLOAT, INT, UINT};

	Type type;

	union
	{
		float		f[4];
		deInt32		i[4];
		deUint32	u[4];
	};

	Color(const float f_[4])    : type(FLOAT) { f[0] = f_[0]; f[1] = f_[1]; f[2] = f_[2]; f[3] = f_[3]; }
	Color(const deInt32 i_[4])  : type(INT)   { i[0] = i_[0]; i[1] = i_[1]; i[2] = i_[2]; i[3] = i_[3]; }
	Color(const deUint32 u_[4]) : type(UINT)  { u[0] = u_[0]; u[1] = u_[1]; u[2] = u_[2]; u[3] = u_[3]; }
};

class FramebufferClearCase : public tcu::TestCase
{
public:
							FramebufferClearCase	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, ClearType clearType);
	virtual					~FramebufferClearCase	(void) {}

	virtual IterateResult	iterate					(void);

private:
	static void				clearBuffers			(const glw::Functions& gl, Color color, float depth, int stencil);
	static Color			getBaseColor			(const BufferFmtDesc& bufferFmt);
	static Color			getMainColor			(const BufferFmtDesc& bufferFmt);
	static BufferFmtDesc	getBufferFormat			(ClearType type);

	virtual void			render					(GLuint program) const;

	glu::RenderContext&		m_renderCtx;
	const ClearType			m_clearType;
};

FramebufferClearCase::FramebufferClearCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, ClearType clearType)
	: tcu::TestCase	(testCtx, name, desc)
	, m_renderCtx	(renderCtx)
	, m_clearType	(clearType)
{
}

void FramebufferClearCase::clearBuffers (const glw::Functions& gl, Color color, float depth, int stencil)
{
	switch(color.type)
	{
		case Color::FLOAT:	gl.clearBufferfv (GL_COLOR, 0, color.f); break;
		case Color::INT:	gl.clearBufferiv (GL_COLOR, 0, color.i); break;
		case Color::UINT:	gl.clearBufferuiv(GL_COLOR, 0, color.u); break;
		default:
			DE_ASSERT(false);
	}

	gl.clearBufferfv(GL_DEPTH, 0, &depth);
	gl.clearBufferiv(GL_STENCIL, 0, &stencil);
}

FramebufferClearCase::IterateResult FramebufferClearCase::iterate (void)
{
	TestLog&					log				= m_testCtx.getLog();
	const glw::Functions&		gl				= m_renderCtx.getFunctions();
	const glu::ShaderProgram	shader			(m_renderCtx, genShaders(glu::getContextTypeGLSLVersion(m_renderCtx.getType())));

	const glu::Framebuffer		fbo				(gl);
	const glu::Renderbuffer		colorbuf		(gl);
	const glu::Renderbuffer		depthbuf		(gl);

	const BufferFmtDesc			bufferFmt		= getBufferFormat(m_clearType);
	const Color					baseColor		= getBaseColor(bufferFmt);

	const int					width			= 64;
	const int					height			= 64;

	const IVec4					scissorArea		(8, 8, 48, 48);

	vector<deUint8>				refData			(width*height*bufferFmt.texFmt.getPixelSize());
	vector<deUint8>				resData			(width*height*bufferFmt.texFmt.getPixelSize());

	tcu::PixelBufferAccess		refAccess		(bufferFmt.texFmt, width, height, 1, &refData[0]);
	tcu::PixelBufferAccess		resAccess		(bufferFmt.texFmt, width, height, 1, &resData[0]);

	if (!shader.isOk())
	{
		log << shader;
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader compile/link failed");
		return STOP;
	}

	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo);
	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *fbo);

	// Color
	gl.bindRenderbuffer(GL_RENDERBUFFER, *colorbuf);
	gl.renderbufferStorage(GL_RENDERBUFFER, bufferFmt.colorFmt, width, height);
	gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorbuf);

	// Depth/stencil
	gl.bindRenderbuffer(GL_RENDERBUFFER, *depthbuf);
	gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
	gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *depthbuf);

	log << TestLog::Message << "Scissor area is " << scissorArea << TestLog::EndMessage;

	// Render reference
	{
		log << TestLog::Message << "Rendering reference (scissors disabled)" << TestLog::EndMessage;

		gl.useProgram(shader.getProgram());
		gl.viewport(0, 0, width, height);

		gl.disable(GL_DEPTH_TEST);
		gl.disable(GL_STENCIL_TEST);
		gl.disable(GL_SCISSOR_TEST);

		clearBuffers(gl, baseColor, 1.0f, 0);

		render(shader.getProgram());

		glu::readPixels(m_renderCtx, 0, 0, refAccess);
		GLU_CHECK_ERROR(gl.getError());
	}

	// Render result
	{
		log << TestLog::Message << "Rendering result (scissors enabled)" << TestLog::EndMessage;

		gl.useProgram(shader.getProgram());
		gl.viewport(0, 0, width, height);

		gl.disable(GL_DEPTH_TEST);
		gl.disable(GL_STENCIL_TEST);
		gl.disable(GL_SCISSOR_TEST);

		clearBuffers(gl, baseColor, 1.0f, 0);

		gl.enable(GL_SCISSOR_TEST);
		gl.scissor(scissorArea.x(), scissorArea.y(), scissorArea.z(), scissorArea.w());

		render(shader.getProgram());

		glu::readPixels(m_renderCtx, 0, 0, resAccess);
		GLU_CHECK_ERROR(gl.getError());
	}

	{
		bool resultOk = false;

		switch (baseColor.type)
		{
			case Color::FLOAT:
				clearEdges(refAccess, Vec4(baseColor.f[0], baseColor.f[1], baseColor.f[2], baseColor.f[3]), scissorArea);
				resultOk = tcu::floatThresholdCompare(log, "ComparisonResult", "Image comparison result", refAccess, resAccess, Vec4(0.02f, 0.02f, 0.02f, 0.02f), tcu::COMPARE_LOG_RESULT);
				break;

			case Color::INT:
				clearEdges(refAccess, IVec4(baseColor.i[0], baseColor.i[1], baseColor.i[2], baseColor.i[3]), scissorArea);
				resultOk = tcu::intThresholdCompare(log, "ComparisonResult", "Image comparison result", refAccess, resAccess, UVec4(2, 2, 2, 2), tcu::COMPARE_LOG_RESULT);
				break;

			case Color::UINT:
				clearEdges(refAccess, UVec4(baseColor.u[0], baseColor.u[1], baseColor.u[2], baseColor.u[3]), scissorArea);
				resultOk = tcu::intThresholdCompare(log, "ComparisonResult", "Image comparison result", refAccess, resAccess, UVec4(2, 2, 2, 2), tcu::COMPARE_LOG_RESULT);
				break;
		}

		if (resultOk)
			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
		else
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
	}

	return STOP;
}

Color FramebufferClearCase::getBaseColor (const BufferFmtDesc& bufferFmt)
{
	const float		f[4] = {0.125f, 0.25f, 0.5f, 1.0f};
	const deInt32	i[4] = {0, 0, 0, 0};
	const deUint32	u[4] = {0, 0, 0, 0};

	switch(bufferFmt.colorFmt)
	{
		case GL_RGBA8:		return Color(f);
		case GL_RGBA8I:		return Color(i);
		case GL_RGBA8UI:	return Color(u);
		default:
			DE_ASSERT(false);
	}

	return Color(f);
}

Color FramebufferClearCase::getMainColor (const BufferFmtDesc& bufferFmt)
{
	const float		f[4] = {1.0f, 1.0f, 0.5f, 1.0f};
	const deInt32	i[4] = {127, -127, 0, 127};
	const deUint32	u[4] = {255, 255, 0, 255};

	switch(bufferFmt.colorFmt)
	{
		case GL_RGBA8:		return Color(f);
		case GL_RGBA8I:		return Color(i);
		case GL_RGBA8UI:	return Color(u);
		default:
			DE_ASSERT(false);
	}

	return Color(f);
}

BufferFmtDesc FramebufferClearCase::getBufferFormat (ClearType type)
{
	BufferFmtDesc retval;

	switch (type)
	{
		case CLEAR_COLOR_FLOAT:
			retval.colorFmt	= GL_RGBA16F;
			retval.texFmt	= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::HALF_FLOAT);
			DE_ASSERT(!"Floating point clear not implemented");// \todo [2014-1-23 otto] pixel read format & type, nothing guaranteed, need extension...
			break;

		case CLEAR_COLOR_INT:
			retval.colorFmt	= GL_RGBA8I;
			retval.texFmt	= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
			break;

		case CLEAR_COLOR_UINT:
			retval.colorFmt	= GL_RGBA8UI;
			retval.texFmt	= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
			break;

		default:
			retval.colorFmt = GL_RGBA8;
			retval.texFmt	= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
			break;
	}

	return retval;
}

void FramebufferClearCase::render (GLuint program) const
{
	const glw::Functions&	gl					= m_renderCtx.getFunctions();

	const BufferFmtDesc		bufferFmt			= getBufferFormat(m_clearType);
	const Color				clearColor			= getMainColor(bufferFmt);

	const int				clearStencil		= 123;
	const float				clearDepth			= 0.5f;

	switch (m_clearType)
	{
		case CLEAR_COLOR_FIXED:		gl.clearBufferfv (GL_COLOR, 0, clearColor.f);						break;
		case CLEAR_COLOR_FLOAT:		gl.clearBufferfv (GL_COLOR, 0, clearColor.f);						break;
		case CLEAR_COLOR_INT:		gl.clearBufferiv (GL_COLOR, 0, clearColor.i);						break;
		case CLEAR_COLOR_UINT:		gl.clearBufferuiv(GL_COLOR, 0, clearColor.u);						break;
		case CLEAR_DEPTH:			gl.clearBufferfv (GL_DEPTH, 0, &clearDepth);						break;
		case CLEAR_STENCIL:			gl.clearBufferiv (GL_STENCIL, 0, &clearStencil);					break;
		case CLEAR_DEPTH_STENCIL:	gl.clearBufferfi (GL_DEPTH_STENCIL, 0, clearDepth, clearStencil);	break;

		default:
			DE_ASSERT(false);
	}

	const bool useDepth		= (m_clearType == CLEAR_DEPTH   || m_clearType == CLEAR_DEPTH_STENCIL);
	const bool useStencil	= (m_clearType == CLEAR_STENCIL || m_clearType == CLEAR_DEPTH_STENCIL);

	// Render something to expose changes to depth/stencil buffer
	if (useDepth || useStencil)
	{
		if (useDepth)
			gl.enable(GL_DEPTH_TEST);

		if (useStencil)
			gl.enable(GL_STENCIL_TEST);

		gl.stencilFunc(GL_EQUAL, clearStencil, ~0u);
		gl.depthFunc(GL_GREATER);
		gl.disable(GL_SCISSOR_TEST);

		gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, clearColor.f);
		drawQuad(gl, program, tcu::Vec3(-1.0f, -1.0f, 0.6f), tcu::Vec3(1.0f, 1.0f, 0.6f));
	}
}

} // Anonymous

namespace ScissorTestInternal
{

tcu::TestNode* createPrimitiveTest (tcu::TestContext&	testCtx,
									glu::RenderContext&	renderCtx,
									const char*			name,
									const char*			desc,
									const Vec4&			scissorArea,
									const Vec4&			renderArea,
									PrimitiveType		type,
									int					primitiveCount)
{
	return new ScissorPrimitiveCase(testCtx, renderCtx, name, desc, scissorArea, renderArea, type, primitiveCount);
}

tcu::TestNode* createClearTest (tcu::TestContext&	testCtx,
								glu::RenderContext&	renderCtx,
								const char*			name,
								const char*			desc,
								const Vec4&			scissorArea,
								deUint32			clearMode)
{
	return new ScissorClearCase(testCtx, renderCtx, name, desc, scissorArea, clearMode);
}

tcu::TestNode* createFramebufferClearTest (tcu::TestContext&	testCtx,
										   glu::RenderContext&	renderCtx,
										   const char*			name,
										   const char*			desc,
										   ClearType			clearType)
{
	return new FramebufferClearCase(testCtx, renderCtx, name, desc, clearType);
}

tcu::TestNode* createFramebufferBlitTest (tcu::TestContext&		testCtx,
										  glu::RenderContext&	renderCtx,
										  const char*			name,
										  const char*			desc,
										  const Vec4&			scissorArea)
{
	return new FramebufferBlitCase(testCtx, renderCtx, name, desc, scissorArea);
}

} // ScissorTestInternal
} // Functional
} // gls
} // deqp
