/*-------------------------------------------------------------------------
 * 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_FATAL("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() * (float)viewport.width),
												 int(m_scissorArea.y() * (float)viewport.height),
												 int(m_scissorArea.z() * (float)viewport.width),
												 int(m_scissorArea.w() * (float)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] = (deUint16)(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_FATAL("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
