/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 2.0 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 Framebuffer Object Tests.
 *
 * Notes:
 *   + Like in API tests, tcu::sgl2s::Context class is used.
 *   + ReferenceContext is used to generate reference images.
 *   + API calls can be logged \todo [pyry] Implement.
 *//*--------------------------------------------------------------------*/

#include "es2fFboRenderTest.hpp"
#include "sglrContextUtil.hpp"
#include "sglrGLContext.hpp"
#include "sglrReferenceContext.hpp"
#include "tcuSurface.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTextureUtil.hpp"
#include "gluStrUtil.hpp"
#include "deRandom.hpp"
#include "deString.h"

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

using std::vector;
using std::string;
using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::RGBA;
using tcu::Surface;
using namespace glw; // GL types

namespace deqp
{
namespace gles2
{
namespace Functional
{

// Shaders.

class FlatColorShader : public sglr::ShaderProgram
{
public:
	FlatColorShader (void)
		: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
								<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
								<< sglr::pdec::VertexSource(
										"attribute highp vec4 a_position;\n"
										"void main (void)\n"
										"{\n"
										"	gl_Position = a_position;\n"
										"}\n")
								<< sglr::pdec::FragmentSource(
										"uniform mediump vec4 u_color;\n"
										"void main (void)\n"
										"{\n"
										"	gl_FragColor = u_color;\n"
										"}\n"))
	{
	}

	void setColor (sglr::Context& gl, deUint32 program, const tcu::Vec4& color)
	{
		gl.useProgram(program);
		gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, color.getPtr());
	}

	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
	{
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
			packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
	}

	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
	{
		const tcu::Vec4 color(m_uniforms[0].value.f4);

		DE_UNREF(packets);

		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
	}
};

class SingleTex2DShader : public sglr::ShaderProgram
{
public:
	SingleTex2DShader (void)
		: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
								<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
								<< sglr::pdec::VertexSource(
										"attribute highp vec4 a_position;\n"
										"attribute mediump vec2 a_coord;\n"
										"varying mediump vec2 v_coord;\n"
										"void main (void)\n"
										"{\n"
										"	gl_Position = a_position;\n"
										"	v_coord = a_coord;\n"
										"}\n")
								<< sglr::pdec::FragmentSource(
										"uniform sampler2D u_sampler0;\n"
										"varying mediump vec2 v_coord;\n"
										"void main (void)\n"
										"{\n"
										"	gl_FragColor = texture2D(u_sampler0, v_coord);\n"
										"}\n"))
	{
	}

	void setUnit (sglr::Context& gl, deUint32 program, int unitNdx)
	{
		gl.useProgram(program);
		gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unitNdx);
	}

	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
	{
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		{
			rr::VertexPacket& packet = *packets[packetNdx];

			packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
			packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
		}
	}

	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
	{
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
		{
			const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
			const float		lod		= 0.0f;

			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod));
		}
	}

};

class MixTexturesShader : public sglr::ShaderProgram
{
public:
	MixTexturesShader (void)
		: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
								<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
								<< sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
								<< sglr::pdec::Uniform("u_sampler1", glu::TYPE_SAMPLER_2D)
								<< sglr::pdec::VertexSource(
										"attribute highp vec4 a_position;\n"
										"attribute mediump vec2 a_coord;\n"
										"varying mediump vec2 v_coord;\n"
										"void main (void)\n"
										"{\n"
										"	gl_Position = a_position;\n"
										"	v_coord = a_coord;\n"
										"}\n")
								<< sglr::pdec::FragmentSource(
										"uniform sampler2D u_sampler0;\n"
										"uniform sampler2D u_sampler1;\n"
										"varying mediump vec2 v_coord;\n"
										"void main (void)\n"
										"{\n"
										"	gl_FragColor = texture2D(u_sampler0, v_coord)*0.5 + texture2D(u_sampler1, v_coord)*0.5;\n"
										"}\n"))
	{
	}

	void setUnits (sglr::Context& gl, deUint32 program, int unit0, int unit1)
	{
		gl.useProgram(program);
		gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unit0);
		gl.uniform1i(gl.getUniformLocation(program, "u_sampler1"), unit1);
	}

	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
	{
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		{
			rr::VertexPacket& packet = *packets[packetNdx];

			packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
			packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
		}
	}

	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
	{
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
		{
			const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
			const float		lod		= 0.0f;

			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0,   this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f
			                                                        + this->m_uniforms[1].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f);
		}
	}
};

// Framebuffer config.

class FboConfig
{
public:
	FboConfig (void)
		: colorbufferType		(GL_NONE)
		, colorbufferFormat		(GL_NONE)
		, depthbufferType		(GL_NONE)
		, depthbufferFormat		(GL_NONE)
		, stencilbufferType		(GL_NONE)
		, stencilbufferFormat	(GL_NONE)
	{
	}

	std::string				getName			(void) const;

	GLenum					colorbufferType;		//!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER
	GLenum					colorbufferFormat;		//!< Internal format for color buffer texture or renderbuffer

	GLenum					depthbufferType;		//!< GL_RENDERBUFFER
	GLenum					depthbufferFormat;

	GLenum					stencilbufferType;		//!< GL_RENDERBUFFER
	GLenum					stencilbufferFormat;

private:
	static const char*		getFormatName	(GLenum format);
};

const char* FboConfig::getFormatName (GLenum format)
{
	switch (format)
	{
		case GL_RGB:				return "rgb";
		case GL_RGBA:				return "rgba";
		case GL_ALPHA:				return "alpha";
		case GL_LUMINANCE:			return "luminance";
		case GL_LUMINANCE_ALPHA:	return "luminance_alpha";
		case GL_RGB565:				return "rgb565";
		case GL_RGB5_A1:			return "rgb5_a1";
		case GL_RGBA4:				return "rgba4";
		case GL_RGBA16F:			return "rgba16f";
		case GL_RGB16F:				return "rgb16f";
		case GL_DEPTH_COMPONENT16:	return "depth_component16";
		case GL_STENCIL_INDEX8:		return "stencil_index8";
		default:					DE_ASSERT(false); return DE_NULL;
	}
}

std::string FboConfig::getName (void) const
{
	std::string name = "";

	if (colorbufferType != GL_NONE)
	{
		switch (colorbufferType)
		{
			case GL_TEXTURE_2D:			name += "tex2d_";	break;
			case GL_TEXTURE_CUBE_MAP:	name += "texcube_";	break;
			case GL_RENDERBUFFER:		name += "rbo_";		break;
			default:					DE_ASSERT(false);	break;
		}
		name += getFormatName(colorbufferFormat);
	}

	if (depthbufferType != GL_NONE)
	{
		DE_ASSERT(depthbufferType == GL_RENDERBUFFER);
		if (name.length() > 0)
			name += "_";
		name += getFormatName(depthbufferFormat);
	}

	if (stencilbufferType != GL_NONE)
	{
		DE_ASSERT(stencilbufferType == GL_RENDERBUFFER);
		if (name.length() > 0)
			name += "_";
		name += getFormatName(stencilbufferFormat);
	}

	return name;
}

class FboIncompleteException : public tcu::TestError
{
public:
						FboIncompleteException		(const FboConfig& config, GLenum reason, const char* file, int line);
	virtual				~FboIncompleteException		(void) throw() {}

	const FboConfig&	getConfig					(void) const { return m_config; }
	GLenum				getReason					(void) const { return m_reason; }

private:
	FboConfig			m_config;
	GLenum				m_reason;
};

static const char* getFboIncompleteReasonName (GLenum reason)
{
	switch (reason)
	{
		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:			return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:	return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:			return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
		case GL_FRAMEBUFFER_UNSUPPORTED:					return "GL_FRAMEBUFFER_UNSUPPORTED";
		case GL_FRAMEBUFFER_COMPLETE:						return "GL_FRAMEBUFFER_COMPLETE";
		default:											return "UNKNOWN";
	}
}

FboIncompleteException::FboIncompleteException (const FboConfig& config, GLenum reason, const char* file, int line)
	: TestError("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
	, m_config(config)
	, m_reason(reason)
{
}

class Framebuffer
{
public:
						Framebuffer			(sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorbuffer = 0, deUint32 depthbuffer = 0, deUint32 stencilbuffer = 0);
						~Framebuffer		(void);

	const FboConfig&	getConfig			(void) const { return m_config; }
	deUint32			getFramebuffer		(void) const { return m_framebuffer; }
	deUint32			getColorbuffer		(void) const { return m_colorbuffer; }
	deUint32			getDepthbuffer		(void) const { return m_depthbuffer; }
	deUint32			getStencilbuffer	(void) const { return m_stencilbuffer; }

	void				checkCompleteness	(void);

private:
	void				createRbo			(deUint32& name, GLenum format, int width, int height);
	void				destroyBuffer		(deUint32 name, GLenum type);

	FboConfig			m_config;
	sglr::Context&		m_context;
	deUint32			m_framebuffer;
	deUint32			m_colorbuffer;
	deUint32			m_depthbuffer;
	deUint32			m_stencilbuffer;
};

static bool isExtensionSupported (sglr::Context& context, const char* name)
{
	std::istringstream extensions(context.getString(GL_EXTENSIONS));
	std::string extension;

	while (std::getline(extensions, extension, ' '))
	{
		if (extension == name)
			return true;
	}

	return false;
}

static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat)
{
	switch (sizedFormat)
	{
		case GL_RGBA16F:
		case GL_RGB16F:
		case GL_RG16F:
		case GL_R16F:
			if (!isExtensionSupported(context, "GL_EXT_color_buffer_half_float"))
				throw tcu::NotSupportedError("GL_EXT_color_buffer_half_float is not supported");

		default:
			break;
	}
}

Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorbuffer, deUint32 depthbuffer, deUint32 stencilbuffer)
	: m_config			(config)
	, m_context			(context)
	, m_framebuffer		(fbo)
	, m_colorbuffer		(colorbuffer)
	, m_depthbuffer		(depthbuffer)
	, m_stencilbuffer	(stencilbuffer)
{
	// Verify that color format is supported
	checkColorFormatSupport(context, config.colorbufferFormat);

	if (m_framebuffer == 0)
		context.genFramebuffers(1, &m_framebuffer);
	context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);

	switch (m_config.colorbufferType)
	{
		case GL_TEXTURE_2D:
			if (m_colorbuffer == 0)
				context.genTextures(1, &m_colorbuffer);
			context.bindTexture(GL_TEXTURE_2D, m_colorbuffer);
			context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorbufferFormat, width, height);
			context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

			if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height))
			{
				// Set wrap mode to clamp for NPOT FBOs
				context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
				context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
			}

			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorbuffer, 0);
			break;

		case GL_TEXTURE_CUBE_MAP:
			DE_FATAL("TODO");
			break;

		case GL_RENDERBUFFER:
			createRbo(m_colorbuffer, m_config.colorbufferFormat, width, height);
			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorbuffer);
			break;

		default:
			DE_ASSERT(m_config.colorbufferType == GL_NONE);
			break;
	}

	if (m_config.depthbufferType == GL_RENDERBUFFER)
	{
		createRbo(m_depthbuffer, m_config.depthbufferFormat, width, height);
		context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer);
	}
	else
		DE_ASSERT(m_config.depthbufferType == GL_NONE);

	if (m_config.stencilbufferType == GL_RENDERBUFFER)
	{
		createRbo(m_stencilbuffer, m_config.stencilbufferFormat, width, height);
		context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilbuffer);
	}
	else
		DE_ASSERT(m_config.stencilbufferType == GL_NONE);

	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
}

Framebuffer::~Framebuffer (void)
{
	m_context.deleteFramebuffers(1, &m_framebuffer);
	destroyBuffer(m_colorbuffer, m_config.colorbufferType);
	destroyBuffer(m_depthbuffer, m_config.depthbufferType);
	destroyBuffer(m_stencilbuffer, m_config.stencilbufferType);
}

void Framebuffer::checkCompleteness (void)
{
	m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
	GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER);
	m_context.bindFramebuffer(GL_FRAMEBUFFER, 0);
	if (status != GL_FRAMEBUFFER_COMPLETE)
		throw FboIncompleteException(m_config, status, __FILE__, __LINE__);
}

void Framebuffer::createRbo (deUint32& name, GLenum format, int width, int height)
{
	if (name == 0)
		m_context.genRenderbuffers(1, &name);
	m_context.bindRenderbuffer(GL_RENDERBUFFER, name);
	m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
}

void Framebuffer::destroyBuffer (deUint32 name, GLenum type)
{
	if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP)
		m_context.deleteTextures(1, &name);
	else if (type == GL_RENDERBUFFER)
		m_context.deleteRenderbuffers(1, &name);
	else
		DE_ASSERT(type == GL_NONE);
}

static void createMetaballsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
{
	tcu::TextureFormat	texFormat	= glu::mapGLTransferFormat(format, dataType);
	tcu::TextureLevel	level		(texFormat, width, height);

	tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height);

	context.bindTexture(GL_TEXTURE_2D, name);
	context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}

static void createQuadsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
{
	tcu::TextureFormat	texFormat	= glu::mapGLTransferFormat(format, dataType);
	tcu::TextureLevel	level		(texFormat, width, height);

	tcu::fillWithRGBAQuads(level.getAccess());

	context.bindTexture(GL_TEXTURE_2D, name);
	context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}

class FboRenderCase : public TestCase
{
public:
								FboRenderCase			(Context& context, const char* name, const char* description, const FboConfig& config);
	virtual						~FboRenderCase			(void) {}

	virtual IterateResult		iterate					(void);
	virtual void				render					(sglr::Context& fboContext, Surface& dst) = DE_NULL;

	const FboConfig&			getConfig				(void) const { return m_config; }

	static bool					isConfigSupported		(const FboConfig& config) { DE_UNREF(config); return true; }

private:
	FboConfig					m_config;
};

FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config)
	: TestCase(context, name, description)
	, m_config(config)
{
}

TestCase::IterateResult FboRenderCase::iterate (void)
{
	Vec4						clearColor				(0.125f, 0.25f, 0.5f, 1.0f);
	glu::RenderContext&			renderCtx				= m_context.getRenderContext();
	const tcu::RenderTarget&	renderTarget			= m_context.getRenderTarget();
	tcu::TestLog&				log						= m_testCtx.getLog();
	const char*					failReason				= DE_NULL;

	// Position & size for context
	deRandom rnd;
	deRandom_init(&rnd, deStringHash(getName()));

	int		width	= deMin32(renderTarget.getWidth(), 128);
	int		height	= deMin32(renderTarget.getHeight(), 128);
	int		xMax	= renderTarget.getWidth()-width+1;
	int		yMax	= renderTarget.getHeight()-height+1;
	int		x		= deRandom_getUint32(&rnd) % xMax;
	int		y		= deRandom_getUint32(&rnd) % yMax;

	tcu::Surface	gles2Frame	(width, height);
	tcu::Surface	refFrame	(width, height);
	GLenum			gles2Error;
	GLenum			refError;

	// Render using GLES2
	try
	{
		sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));

		context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
		context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		render(context, gles2Frame); // Call actual render func
		gles2Error = context.getError();
	}
	catch (const FboIncompleteException& e)
	{
		if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
		{
			// Mark test case as unsupported
			log << e;
			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
			return STOP;
		}
		else
			throw; // Propagate error
	}

	// Render reference image
	{
		sglr::ReferenceContextBuffers	buffers	(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height);
		sglr::ReferenceContext			context	(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());

		context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
		context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		render(context, refFrame);
		refError = context.getError();
	}

	// Compare error codes
	bool errorCodesOk = (gles2Error == refError);

	if (!errorCodesOk)
	{
		log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles2Error) << ", expected " << glu::getErrorStr(refError) << tcu::TestLog::EndMessage;
		failReason = "Got unexpected error";
	}

	// Compare images
	const float		threshold	= 0.03f;
	bool			imagesOk	= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles2Frame, threshold, tcu::COMPARE_LOG_RESULT);

	if (!imagesOk && !failReason)
		failReason = "Image comparison failed";

	// Store test result
	bool isOk = errorCodesOk && imagesOk;
	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
							isOk ? "Pass"				: failReason);

	return STOP;
}

namespace FboCases
{

class ColorClearsTest : public FboRenderCase
{
public:
						ColorClearsTest				(Context& context, const FboConfig& config);
						~ColorClearsTest			(void) {}

	void				render						(sglr::Context& context, Surface& dst);
};

ColorClearsTest::ColorClearsTest (Context& context, const FboConfig& config)
	: FboRenderCase(context, config.getName().c_str(), "Color buffer clears", config)
{
}

void ColorClearsTest::render (sglr::Context& context, Surface& dst)
{
	int			width	= 128;
	int			height	= 128;
	deRandom	rnd;

	deRandom_init(&rnd, 0);

	// Create framebuffer
	Framebuffer fbo(context, getConfig(), width, height);
	fbo.checkCompleteness();

	// Clear fbo
	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	context.viewport(0, 0, width, height);
	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	// Enable scissor test.
	context.enable(GL_SCISSOR_TEST);

	// Do 10 random color clears
	for (int i = 0; i < 15; i++)
	{
		int		cX		= (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % width;
		int		cY		= (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % height;
		int		cWidth	= (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (width-cX);
		int		cHeight	= (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (height-cY);
		Vec4	color	= RGBA(deRandom_getUint32(&rnd)).toVec();

		context.scissor(cX, cY, cWidth, cHeight);
		context.clearColor(color.x(), color.y(), color.z(), color.w());
		context.clear(GL_COLOR_BUFFER_BIT);
	}

	// Disable scissor.
	context.disable(GL_SCISSOR_TEST);

	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		// Unbind fbo
		context.bindFramebuffer(GL_FRAMEBUFFER, 0);

		// Draw to screen
		SingleTex2DShader	shader;
		deUint32			shaderID = context.createProgram(&shader);

		shader.setUnit(context, shaderID, 0);

		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
		context.viewport(0, 0, context.getWidth(), context.getHeight());
		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		// Read from screen
		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
	{
		// clear alpha channel for GL_RGB5_A1 format because test
		// thresholds for the alpha channel do not account for dithering
		if(getConfig().colorbufferFormat == GL_RGB5_A1)
		{
			context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
			context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
			context.clear(GL_COLOR_BUFFER_BIT);
			context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
		}

		// Read from fbo
		context.readPixels(dst, 0, 0, width, height);
	}
}

class IntersectingQuadsTest : public FboRenderCase
{
public:
					IntersectingQuadsTest			(Context& context, const FboConfig& config, bool npot = false);
	virtual			~IntersectingQuadsTest			(void) {}

	virtual void	render							(sglr::Context& context, Surface& dst);

	static bool		isConfigSupported				(const FboConfig& config);

private:
	int				m_fboWidth;
	int				m_fboHeight;
};

class IntersectingQuadsNpotTest : public IntersectingQuadsTest
{
public:
	IntersectingQuadsNpotTest (Context& context, const FboConfig& config)
		: IntersectingQuadsTest(context, config, true)
	{
	}
};

IntersectingQuadsTest::IntersectingQuadsTest (Context& context, const FboConfig& config, bool npot)
	: FboRenderCase	(context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Intersecting textured quads", config)
	, m_fboWidth	(npot ? 127 : 128)
	, m_fboHeight	(npot ?  95 : 128)
{
}

bool IntersectingQuadsTest::isConfigSupported (const FboConfig& config)
{
	// \note Disabled for stencil configurations since doesn't exercise stencil buffer
	return config.depthbufferType	!= GL_NONE &&
		   config.stencilbufferType	== GL_NONE;
}

void IntersectingQuadsTest::render (sglr::Context& ctx, Surface& dst)
{
	SingleTex2DShader	texShader;
	deUint32			texShaderID = ctx.createProgram(&texShader);

	deUint32 metaballsTex	= 1;
	deUint32 quadsTex		= 2;

	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);

	int width	= m_fboWidth;
	int height	= m_fboHeight;
	Framebuffer fbo(ctx, getConfig(), width, height);
	fbo.checkCompleteness();

	// Setup shaders
	texShader.setUnit(ctx, texShaderID, 0);

	// Draw scene
	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	ctx.viewport(0, 0, width, height);
	ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
	ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	ctx.enable(GL_DEPTH_TEST);

	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));

	ctx.disable(GL_DEPTH_TEST);

	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		// Unbind fbo
		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);

		// Draw to screen
		ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
		ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
		sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		// Read from screen
		ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
	}
	else
	{
		// Read from fbo
		ctx.readPixels(dst, 0, 0, width, height);
	}
}

class MixTest : public FboRenderCase
{
public:
						MixTest				(Context& context, const FboConfig& config, bool npot = false);
	virtual				~MixTest			(void) {}

	void				render				(sglr::Context& context, Surface& dst);

	static bool			isConfigSupported	(const FboConfig& config);

private:
	int					m_fboAWidth;
	int					m_fboAHeight;
	int					m_fboBWidth;
	int					m_fboBHeight;
};

class MixNpotTest : public MixTest
{
public:
	MixNpotTest (Context& context, const FboConfig& config)
		: MixTest(context, config, true)
	{
	}
};

MixTest::MixTest (Context& context, const FboConfig& config, bool npot)
	: FboRenderCase	(context, (string(npot ? "mix_npot_" : "mix_") + config.getName()).c_str(), "Use two fbos as sources in draw operation", config)
	, m_fboAWidth	(npot ? 127 : 128)
	, m_fboAHeight	(npot ?  95 : 128)
	, m_fboBWidth	(npot ?  55 :  64)
	, m_fboBHeight	(npot ?  63 :  64)
{
}

bool MixTest::isConfigSupported (const FboConfig& config)
{
	// \note Disabled for stencil configurations since doesn't exercise stencil buffer
	return config.colorbufferType	== GL_TEXTURE_2D &&
		   config.stencilbufferType	== GL_NONE;
}

void MixTest::render (sglr::Context& context, Surface& dst)
{
	SingleTex2DShader	singleTexShader;
	MixTexturesShader	mixShader;

	deUint32			singleTexShaderID	= context.createProgram(&singleTexShader);
	deUint32			mixShaderID			= context.createProgram(&mixShader);

	// Texture with metaballs
	deUint32 metaballsTex = 1;
	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);

	// Setup shaders
	singleTexShader.setUnit(context, singleTexShaderID, 0);
	mixShader.setUnits(context, mixShaderID, 0, 1);

	// Fbo, quad with metaballs texture
	Framebuffer fboA(context, getConfig(), m_fboAWidth, m_fboAHeight);
	fboA.checkCompleteness();
	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
	context.viewport(0, 0, m_fboAWidth, m_fboAHeight);
	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
	sglr::drawQuad(context, singleTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	// Fbo, color clears
	Framebuffer fboB(context, getConfig(), m_fboBWidth, m_fboBHeight);
	fboB.checkCompleteness();
	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
	context.viewport(0, 0, m_fboBWidth, m_fboBHeight);
	context.enable(GL_SCISSOR_TEST);
	context.scissor(0, 0, 32, 64);
	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT);
	context.scissor(32, 0, 32, 64);
	context.clearColor(0.0f, 1.0f, 0.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT);
	context.disable(GL_SCISSOR_TEST);

	// Final mix op
	context.activeTexture(GL_TEXTURE0);
	context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
	context.activeTexture(GL_TEXTURE1);
	context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
	context.viewport(0, 0, context.getWidth(), context.getHeight());
	sglr::drawQuad(context, mixShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
}

class BlendTest : public FboRenderCase
{
public:
						BlendTest			(Context& context, const FboConfig& config, bool npot = false);
	virtual				~BlendTest			(void) {}

	void				render				(sglr::Context& context, Surface& dst);

	static bool			isConfigSupported	(const FboConfig& config);

private:
	int					m_fboWidth;
	int					m_fboHeight;
};

class BlendNpotTest : public BlendTest
{
public:
	BlendNpotTest (Context& context, const FboConfig& config)
		: BlendTest(context, config, true)
	{
	}
};

BlendTest::BlendTest (Context& context, const FboConfig& config, bool npot)
	: FboRenderCase	(context, (string(npot ? "blend_npot_" : "blend_") + config.getName()).c_str(), "Blend to fbo", config)
	, m_fboWidth	(npot ? 111 : 128)
	, m_fboHeight	(npot ? 122 : 128)
{
}

bool BlendTest::isConfigSupported (const FboConfig& config)
{
	// \note Disabled for stencil configurations since doesn't exercise stencil buffer
	return config.stencilbufferType	== GL_NONE;
}

void BlendTest::render (sglr::Context& context, Surface& dst)
{
	SingleTex2DShader	shader;
	deUint32			shaderID		= context.createProgram(&shader);
	int					width			= m_fboWidth;
	int					height			= m_fboHeight;
	deUint32			metaballsTex	= 1;

	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);

	Framebuffer fbo(context, getConfig(), width, height);
	fbo.checkCompleteness();

	shader.setUnit(context, shaderID, 0);

	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	context.viewport(0, 0, width, height);
	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
	context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	context.enable(GL_BLEND);
	context.blendEquation(GL_FUNC_ADD);
	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
	context.disable(GL_BLEND);

	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
		context.viewport(0, 0, context.getWidth(), context.getHeight());
		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
		context.readPixels(dst, 0, 0, width, height);
}

class StencilClearsTest : public FboRenderCase
{
public:
						StencilClearsTest		(Context& context, const FboConfig& config);
	virtual				~StencilClearsTest		(void) {};

	void				render					(sglr::Context& context, Surface& dst);

	static bool			isConfigSupported		(const FboConfig& config);
};

StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
	: FboRenderCase(context, config.getName().c_str(), "Stencil clears", config)
{
}

void StencilClearsTest::render (sglr::Context& context, Surface& dst)
{
	SingleTex2DShader	shader;
	deUint32			shaderID		= context.createProgram(&shader);
	int					width			= 128;
	int					height			= 128;
	deUint32			quadsTex		= 1;
	deUint32			metaballsTex	= 2;

	createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);

	Framebuffer fbo(context, getConfig(), width, height);
	fbo.checkCompleteness();

	// Bind framebuffer and clear
	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	context.viewport(0, 0, width, height);
	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	// Do stencil clears
	context.enable(GL_SCISSOR_TEST);
	context.scissor(10, 16, 32, 120);
	context.clearStencil(1);
	context.clear(GL_STENCIL_BUFFER_BIT);
	context.scissor(16, 32, 100, 64);
	context.clearStencil(2);
	context.clear(GL_STENCIL_BUFFER_BIT);
	context.disable(GL_SCISSOR_TEST);

	// Draw 2 textures with stecil tests
	context.activeTexture(GL_TEXTURE0);
	context.bindTexture(GL_TEXTURE_2D, quadsTex);
	context.activeTexture(GL_TEXTURE1);
	context.bindTexture(GL_TEXTURE_2D, metaballsTex);

	context.enable(GL_STENCIL_TEST);
	context.stencilFunc(GL_EQUAL, 1, 0xffffffffu);
	shader.setUnit(context, shaderID, 0);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	context.stencilFunc(GL_EQUAL, 2, 0xffffffffu);
	shader.setUnit(context, shaderID, 1);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	context.disable(GL_STENCIL_TEST);

	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
		context.activeTexture(GL_TEXTURE0);
		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
		context.viewport(0, 0, context.getWidth(), context.getHeight());
		shader.setUnit(context, shaderID, 0);
		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
	{
		// clear alpha channel for GL_RGB5_A1 format because test
		// thresholds for the alpha channel do not account for dithering
		if(getConfig().colorbufferFormat == GL_RGB5_A1)
		{
			context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
			context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
			context.clear(GL_COLOR_BUFFER_BIT);
			context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
		}

		context.readPixels(dst, 0, 0, width, height);
	}
}

bool StencilClearsTest::isConfigSupported (const FboConfig& config)
{
	return config.stencilbufferType != GL_NONE;
}

class StencilTest : public FboRenderCase
{
public:
						StencilTest				(Context& context, const FboConfig& config, bool npot = false);
	virtual				~StencilTest			(void) {};

	void				render					(sglr::Context& context, Surface& dst);

	static bool			isConfigSupported		(const FboConfig& config);

private:
	int					m_fboWidth;
	int					m_fboHeight;
};

class StencilNpotTest : public StencilTest
{
public:
	StencilNpotTest (Context& context, const FboConfig& config)
		: StencilTest(context, config, true)
	{
	}
};

StencilTest::StencilTest (Context& context, const FboConfig& config, bool npot)
	: FboRenderCase	(context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Stencil ops", config)
	, m_fboWidth	(npot ?  99 : 128)
	, m_fboHeight	(npot ? 110 : 128)
{
}

bool StencilTest::isConfigSupported (const FboConfig& config)
{
	return config.stencilbufferType != GL_NONE;
}

void StencilTest::render (sglr::Context& ctx, Surface& dst)
{
	FlatColorShader		colorShader;
	SingleTex2DShader	texShader;
	deUint32			colorShaderID	= ctx.createProgram(&colorShader);
	deUint32			texShaderID		= ctx.createProgram(&texShader);
	int					width			= m_fboWidth;
	int					height			= m_fboHeight;
	int					texWidth		= 64;
	int					texHeight		= 64;
	deUint32			quadsTex		= 1;
	deUint32			metaballsTex	= 2;
	bool				depth			= getConfig().depthbufferType != GL_NONE;

	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);

	Framebuffer fbo(ctx, getConfig(), width, height);
	fbo.checkCompleteness();

	// Bind framebuffer and clear
	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	ctx.viewport(0, 0, width, height);
	ctx.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	// Render intersecting quads - increment stencil on depth pass
	ctx.enable(GL_DEPTH_TEST);
	ctx.enable(GL_STENCIL_TEST);
	ctx.stencilFunc(GL_ALWAYS, 0, 0xffu);
	ctx.stencilOp(GL_KEEP, GL_KEEP, GL_INCR);

	colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
	sglr::drawQuad(ctx, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));

	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
	texShader.setUnit(ctx, texShaderID, 0);
	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));

	// Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
	ctx.disable(GL_DEPTH_TEST);
	ctx.stencilFunc(GL_EQUAL, depth ? 2 : 1, 0xffu);
	ctx.stencilOp(GL_DECR, GL_KEEP, GL_KEEP);
	colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
	sglr::drawQuad(ctx, colorShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));

	// Draw metaballs with stencil test where stencil > 1 or 2 depending on depth buffer
	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
	ctx.stencilFunc(GL_GREATER, depth ? 1 : 2, 0xffu);
	ctx.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));

	ctx.disable(GL_STENCIL_TEST);

	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
		ctx.activeTexture(GL_TEXTURE0);
		ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
		ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
		sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
	}
	else
		ctx.readPixels(dst, 0, 0, width, height);
}

class SharedColorbufferTest : public FboRenderCase
{
public:
						SharedColorbufferTest			(Context& context, const FboConfig& config);
	virtual				~SharedColorbufferTest			(void) {};

	void				render							(sglr::Context& context, Surface& dst);
};

SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
	: FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config)
{
}

void SharedColorbufferTest::render (sglr::Context& context, Surface& dst)
{
	SingleTex2DShader	shader;
	deUint32			shaderID		= context.createProgram(&shader);
	int					width			= 128;
	int					height			= 128;
//	bool				depth			= getConfig().depthbufferFormat		!= GL_NONE;
	bool				stencil			= getConfig().stencilbufferFormat	!= GL_NONE;

	// Textures
	deUint32	quadsTex		= 1;
	deUint32	metaballsTex	= 2;
	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);

	context.viewport(0, 0, width, height);

	shader.setUnit(context, shaderID, 0);

	// Fbo A
	Framebuffer fboA(context, getConfig(), width, height);
	fboA.checkCompleteness();

	// Fbo B - don't create colorbuffer
	FboConfig cfg = getConfig();
	cfg.colorbufferType		= GL_NONE;
	cfg.colorbufferFormat	= GL_NONE;
	Framebuffer fboB(context, cfg, width, height);

	// Attach color buffer from fbo A
	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
	switch (getConfig().colorbufferType)
	{
		case GL_TEXTURE_2D:
			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorbuffer(), 0);
			break;

		case GL_RENDERBUFFER:
			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorbuffer());
			break;

		default:
			DE_ASSERT(false);
	}

	// Clear depth and stencil in fbo B
	context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	// Render quads to fbo 1, with depth 0.0
	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
	context.bindTexture(GL_TEXTURE_2D, quadsTex);
	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	if (stencil)
	{
		// Stencil to 1 in fbo A
		context.clearStencil(1);
		context.clear(GL_STENCIL_BUFFER_BIT);
	}

	context.enable(GL_DEPTH_TEST);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
	context.disable(GL_DEPTH_TEST);

	// Blend metaballs to fbo 2
	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
	context.enable(GL_BLEND);
	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	// Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
	context.bindTexture(GL_TEXTURE_2D, quadsTex);
	context.enable(GL_DEPTH_TEST);
	sglr::drawQuad(context, shaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
	context.disable(GL_DEPTH_TEST);

	if (stencil)
	{
		FlatColorShader flatShader;
		deUint32		flatShaderID = context.createProgram(&flatShader);

		flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));

		// Clear subset of stencil buffer to 1
		context.enable(GL_SCISSOR_TEST);
		context.scissor(10, 10, 12, 25);
		context.clearStencil(1);
		context.clear(GL_STENCIL_BUFFER_BIT);
		context.disable(GL_SCISSOR_TEST);

		// Render quad with stencil mask == 1
		context.enable(GL_STENCIL_TEST);
		context.stencilFunc(GL_EQUAL, 1, 0xffu);
		sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		context.disable(GL_STENCIL_TEST);
	}

	// Get results
	if (fboA.getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
		context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
		context.viewport(0, 0, context.getWidth(), context.getHeight());
		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
		context.readPixels(dst, 0, 0, width, height);
}

class SharedColorbufferClearsTest : public FboRenderCase
{
public:
					SharedColorbufferClearsTest		(Context& context, const FboConfig& config);
	virtual			~SharedColorbufferClearsTest	(void) {}

	static bool		isConfigSupported				(const FboConfig& config);
	void			render							(sglr::Context& context, Surface& dst);
};

SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
	: FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config)
{
}

bool SharedColorbufferClearsTest::isConfigSupported (const FboConfig& config)
{
	return config.colorbufferType	!= GL_NONE &&
		   config.depthbufferType	== GL_NONE &&
		   config.stencilbufferType	== GL_NONE;
}

void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
{
	int			width			= 128;
	int			height			= 128;
	deUint32	colorbuffer		= 1;

	checkColorFormatSupport(context, getConfig().colorbufferFormat);

	// Single colorbuffer
	if (getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		context.bindTexture(GL_TEXTURE_2D, colorbuffer);
		context.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, width, height);
		context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	}
	else
	{
		DE_ASSERT(getConfig().colorbufferType == GL_RENDERBUFFER);
		context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
		context.renderbufferStorage(GL_RENDERBUFFER, getConfig().colorbufferFormat, width, height);
	}

	// Multiple framebuffers sharing the colorbuffer
	for (int fbo = 1; fbo <= 3; fbo++)
	{
		context.bindFramebuffer(GL_FRAMEBUFFER, fbo);

		if (getConfig().colorbufferType == GL_TEXTURE_2D)
			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
		else
			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
	}

	context.bindFramebuffer(GL_FRAMEBUFFER, 1);

	// Check completeness
	{
		GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
		if (status != GL_FRAMEBUFFER_COMPLETE)
			throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
	}

	// Render to them
	context.viewport(0, 0, width, height);
	context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT);

	context.enable(GL_SCISSOR_TEST);

	context.bindFramebuffer(GL_FRAMEBUFFER, 2);
	context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
	context.scissor(10, 10, 64, 64);
	context.clear(GL_COLOR_BUFFER_BIT);
	context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
	context.scissor(60, 60, 40, 20);
	context.clear(GL_COLOR_BUFFER_BIT);

	context.bindFramebuffer(GL_FRAMEBUFFER, 3);
	context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
	context.scissor(20, 20, 100, 10);
	context.clear(GL_COLOR_BUFFER_BIT);

	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
	context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
	context.scissor(20, 20, 5, 100);
	context.clear(GL_COLOR_BUFFER_BIT);

	context.disable(GL_SCISSOR_TEST);

	if (getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		SingleTex2DShader	shader;
		deUint32			shaderID = context.createProgram(&shader);

		shader.setUnit(context, shaderID, 0);

		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
		context.viewport(0, 0, context.getWidth(), context.getHeight());
		sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
		context.readPixels(dst, 0, 0, width, height);
}

class SharedDepthbufferTest : public FboRenderCase
{
public:
					SharedDepthbufferTest		(Context& context, const FboConfig& config);
	virtual			~SharedDepthbufferTest		(void) {};

	static bool		isConfigSupported			(const FboConfig& config);
	void			render						(sglr::Context& context, Surface& dst);
};

SharedDepthbufferTest::SharedDepthbufferTest (Context& context, const FboConfig& config)
	: FboRenderCase(context, config.getName().c_str(), "Shared depthbuffer", config)
{
}

bool SharedDepthbufferTest::isConfigSupported (const FboConfig& config)
{
	return config.depthbufferType == GL_RENDERBUFFER;
}

void SharedDepthbufferTest::render (sglr::Context& context, Surface& dst)
{
	SingleTex2DShader	texShader;
	FlatColorShader		colorShader;
	deUint32			texShaderID		= context.createProgram(&texShader);
	deUint32			colorShaderID	= context.createProgram(&colorShader);
	int					width			= 128;
	int					height			= 128;
	bool				stencil			= getConfig().stencilbufferType != GL_NONE;

	// Setup shaders
	texShader.setUnit(context, texShaderID, 0);
	colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));

	// Textures
	deUint32 metaballsTex	= 5;
	deUint32 quadsTex		= 6;
	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);

	context.viewport(0, 0, width, height);

	// Fbo A
	Framebuffer fboA(context, getConfig(), width, height);
	fboA.checkCompleteness();

	// Fbo B
	FboConfig cfg = getConfig();
	cfg.depthbufferType		= GL_NONE;
	cfg.depthbufferFormat	= GL_NONE;
	Framebuffer fboB(context, cfg, width, height);

	// Bind depth buffer from fbo A to fbo B
	DE_ASSERT(fboA.getConfig().depthbufferType == GL_RENDERBUFFER);
	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboA.getDepthbuffer());

	// Clear fbo B color to red and stencil to 1
	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
	context.clearStencil(1);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	// Enable depth test.
	context.enable(GL_DEPTH_TEST);

	// Render quad to fbo A
	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
	context.bindTexture(GL_TEXTURE_2D, quadsTex);
	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	// Render metaballs to fbo B
	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

	context.disable(GL_DEPTH_TEST);

	if (stencil)
	{
		// Clear subset of stencil buffer to 0
		context.enable(GL_SCISSOR_TEST);
		context.scissor(10, 10, 12, 25);
		context.clearStencil(0);
		context.clear(GL_STENCIL_BUFFER_BIT);
		context.disable(GL_SCISSOR_TEST);

		// Render quad with stencil mask == 0
		context.enable(GL_STENCIL_TEST);
		context.stencilFunc(GL_EQUAL, 0, 0xffu);
		sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		context.disable(GL_STENCIL_TEST);
	}

	if (getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		// Render both to screen
		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
		context.viewport(0, 0, context.getWidth(), context.getHeight());
		context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
		sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
		context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
		sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
	{
		// Read results from fbo B
		context.readPixels(dst, 0, 0, width, height);
	}
}

class TexSubImageAfterRenderTest : public FboRenderCase
{
public:
					TexSubImageAfterRenderTest		(Context& context, const FboConfig& config);
	virtual			~TexSubImageAfterRenderTest		(void) {}

	static bool		isConfigSupported				(const FboConfig& config);
	void			render							(sglr::Context& context, Surface& dst);
};

TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
	: FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
{
}

bool TexSubImageAfterRenderTest::isConfigSupported (const FboConfig& config)
{
	return config.colorbufferType == GL_TEXTURE_2D &&
		   (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
		   config.depthbufferType == GL_NONE &&
		   config.stencilbufferType == GL_NONE;
}

void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
{
	SingleTex2DShader	shader;
	deUint32			shaderID	= context.createProgram(&shader);
	bool				isRGBA		= getConfig().colorbufferFormat == GL_RGBA;

	tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
	tcu::fillWithRGBAQuads(fourQuads.getAccess());

	tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
	tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);

	shader.setUnit(context, shaderID, 0);

	deUint32 fourQuadsTex = 1;
	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());

	context.bindFramebuffer(GL_FRAMEBUFFER, 1);

	deUint32 fboTex = 2;
	context.bindTexture(GL_TEXTURE_2D, fboTex);
	context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);

	// Render to fbo
	context.viewport(0, 0, 128, 128);
	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	// Update texture using TexSubImage2D
	context.bindTexture(GL_TEXTURE_2D, fboTex);
	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());

	// Draw to screen
	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
	context.viewport(0, 0, context.getWidth(), context.getHeight());
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
}

class TexSubImageBetweenRenderTest : public FboRenderCase
{
public:
					TexSubImageBetweenRenderTest		(Context& context, const FboConfig& config);
	virtual			~TexSubImageBetweenRenderTest		(void) {}

	static bool		isConfigSupported					(const FboConfig& config);
	void			render								(sglr::Context& context, Surface& dst);
};

TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
	: FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
{
}

bool TexSubImageBetweenRenderTest::isConfigSupported (const FboConfig& config)
{
	return config.colorbufferType == GL_TEXTURE_2D &&
		   (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
		   config.depthbufferType == GL_NONE &&
		   config.stencilbufferType == GL_NONE;
}

void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
{
	SingleTex2DShader	shader;
	deUint32			shaderID	= context.createProgram(&shader);
	bool				isRGBA		= getConfig().colorbufferFormat == GL_RGBA;

	tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
	tcu::fillWithRGBAQuads(fourQuads.getAccess());

	tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
	tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);

	tcu::TextureLevel metaballs2(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 64, 64);
	tcu::fillWithMetaballs(metaballs2.getAccess(), 5, 4);

	deUint32 metaballsTex = 3;
	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, metaballs2.getAccess().getDataPtr());

	deUint32 fourQuadsTex = 1;
	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());

	context.bindFramebuffer(GL_FRAMEBUFFER, 1);

	deUint32 fboTex = 2;
	context.bindTexture(GL_TEXTURE_2D, fboTex);
	context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);

	shader.setUnit(context, shaderID, 0);

	// Render to fbo
	context.viewport(0, 0, 128, 128);
	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	// Update texture using TexSubImage2D
	context.bindTexture(GL_TEXTURE_2D, fboTex);
	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());

	// Render again to fbo
	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
	context.enable(GL_BLEND);
	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
	context.disable(GL_BLEND);

	// Draw to screen
	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
	context.viewport(0, 0, context.getWidth(), context.getHeight());
	context.bindTexture(GL_TEXTURE_2D, fboTex);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
}

class ResizeTest : public FboRenderCase
{
public:
					ResizeTest				(Context& context, const FboConfig& config);
	virtual			~ResizeTest				(void) {}

	void			render					(sglr::Context& context, Surface& dst);
};

ResizeTest::ResizeTest (Context& context, const FboConfig& config)
	: FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config)
{
}

void ResizeTest::render (sglr::Context& context, Surface& dst)
{
	SingleTex2DShader	texShader;
	FlatColorShader		colorShader;
	deUint32			texShaderID		= context.createProgram(&texShader);
	deUint32			colorShaderID	= context.createProgram(&colorShader);
	deUint32			quadsTex		= 1;
	deUint32			metaballsTex	= 2;
	bool				depth			= getConfig().depthbufferType	 != GL_NONE;
	bool				stencil			= getConfig().stencilbufferType	 != GL_NONE;

	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);

	Framebuffer fbo(context, getConfig(), 128, 128);
	fbo.checkCompleteness();

	// Setup shaders
	texShader.setUnit(context, texShaderID, 0);
	colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));

	// Render quads
	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	context.viewport(0, 0, 128, 128);
	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	context.bindTexture(GL_TEXTURE_2D, quadsTex);
	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		// Render fbo to screen
		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
		context.viewport(0, 0, context.getWidth(), context.getHeight());
		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
		sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		// Restore binding
		context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	}

	int newWidth	= 64;
	int newHeight	= 32;

	// Resize buffers
	switch (fbo.getConfig().colorbufferType)
	{
		case GL_TEXTURE_2D:
			context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
			context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
			break;

		case GL_RENDERBUFFER:
			context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorbuffer());
			context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
			break;

		default:
			DE_ASSERT(false);
	}

	if (depth)
	{
		DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
		context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthbuffer());
		context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, newWidth, newHeight);
	}

	if (stencil)
	{
		DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
		context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getStencilbuffer());
		context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, newWidth, newHeight);
	}

	// Render to resized fbo
	context.viewport(0, 0, newWidth, newHeight);
	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	context.enable(GL_DEPTH_TEST);

	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));

	context.bindTexture(GL_TEXTURE_2D, quadsTex);
	sglr::drawQuad(context, texShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));

	context.disable(GL_DEPTH_TEST);

	if (stencil)
	{
		context.enable(GL_SCISSOR_TEST);
		context.scissor(10, 10, 5, 15);
		context.clearStencil(1);
		context.clear(GL_STENCIL_BUFFER_BIT);
		context.disable(GL_SCISSOR_TEST);

		context.enable(GL_STENCIL_TEST);
		context.stencilFunc(GL_EQUAL, 1, 0xffu);
		sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
		context.disable(GL_STENCIL_TEST);
	}

	if (getConfig().colorbufferType == GL_TEXTURE_2D)
	{
		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
		context.viewport(0, 0, context.getWidth(), context.getHeight());
		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
		sglr::drawQuad(context, texShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
		context.readPixels(dst, 0, 0, newWidth, newHeight);
}

template <GLenum Buffers>
class RecreateBuffersTest : public FboRenderCase
{
public:
					RecreateBuffersTest			(Context& context, const FboConfig& config, bool rebind);
	virtual			~RecreateBuffersTest		(void) {}

	static bool		isConfigSupported			(const FboConfig& config);
	void			render						(sglr::Context& context, Surface& dst);

private:
	bool			m_rebind;
};

template <GLenum Buffers>
class RecreateBuffersNoRebindTest : public RecreateBuffersTest<Buffers>
{
public:
	RecreateBuffersNoRebindTest (Context& context, const FboConfig& config)
		: RecreateBuffersTest<Buffers>(context, config, false)
	{
	}
};

template <GLenum Buffers>
class RecreateBuffersRebindTest : public RecreateBuffersTest<Buffers>
{
public:
	RecreateBuffersRebindTest (Context& context, const FboConfig& config)
		: RecreateBuffersTest<Buffers>(context, config, true)
	{
	}
};

template <GLenum Buffers>
RecreateBuffersTest<Buffers>::RecreateBuffersTest (Context& context, const FboConfig& config, bool rebind)
	: FboRenderCase		(context, (string(rebind ? "rebind_" : "no_rebind_") + config.getName()).c_str(), "Recreate buffers", config)
	, m_rebind			(rebind)
{
}

template <GLenum Buffers>
bool RecreateBuffersTest<Buffers>::isConfigSupported (const FboConfig& config)
{
	if ((Buffers & GL_COLOR_BUFFER_BIT) && config.colorbufferType == GL_NONE)
		return false;
	if ((Buffers & GL_DEPTH_BUFFER_BIT) && config.depthbufferType == GL_NONE)
		return false;
	if ((Buffers & GL_STENCIL_BUFFER_BIT) && config.stencilbufferType == GL_NONE)
		return false;
	return true;
}

template <GLenum Buffers>
void RecreateBuffersTest<Buffers>::render (sglr::Context& ctx, Surface& dst)
{
	SingleTex2DShader	texShader;
	deUint32			texShaderID		= ctx.createProgram(&texShader);
	int					width			= 128;
	int					height			= 128;
	deUint32			metaballsTex	= 1;
	deUint32			quadsTex		= 2;
	bool				stencil			= getConfig().stencilbufferType != GL_NONE;

	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);

	Framebuffer fbo(ctx, getConfig(), width, height);
	fbo.checkCompleteness();

	// Setup shader
	texShader.setUnit(ctx, texShaderID, 0);

	// Draw scene
	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	ctx.viewport(0, 0, width, height);
	ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
	ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	ctx.enable(GL_DEPTH_TEST);

	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	if (stencil)
	{
		ctx.enable(GL_SCISSOR_TEST);
		ctx.scissor(width/4, height/4, width/2, height/2);
		ctx.clearStencil(1);
		ctx.clear(GL_STENCIL_BUFFER_BIT);
		ctx.disable(GL_SCISSOR_TEST);
	}

	// Recreate buffers
	if (!m_rebind)
		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);

	if (Buffers & GL_COLOR_BUFFER_BIT)
	{
		deUint32 colorbuf = fbo.getColorbuffer();
		switch (fbo.getConfig().colorbufferType)
		{
			case GL_TEXTURE_2D:
				ctx.deleteTextures(1, &colorbuf);
				ctx.bindTexture(GL_TEXTURE_2D, colorbuf);
				ctx.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, width, height);
				ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

				if (m_rebind)
					ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuf, 0);
				break;

			case GL_RENDERBUFFER:
				ctx.deleteRenderbuffers(1, &colorbuf);
				ctx.bindRenderbuffer(GL_RENDERBUFFER, colorbuf);
				ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, width, height);

				if (m_rebind)
					ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf);
				break;

			default:
				DE_ASSERT(false);
		}
	}

	if (Buffers & GL_DEPTH_BUFFER_BIT)
	{
		deUint32 depthbuf = fbo.getDepthbuffer();
		DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);

		ctx.deleteRenderbuffers(1, &depthbuf);
		ctx.bindRenderbuffer(GL_RENDERBUFFER, depthbuf);
		ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, width, height);

		if (m_rebind)
			ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuf);
	}

	if (Buffers & GL_STENCIL_BUFFER_BIT)
	{
		deUint32 stencilbuf = fbo.getStencilbuffer();
		DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);

		ctx.deleteRenderbuffers(1, &stencilbuf);
		ctx.bindRenderbuffer(GL_RENDERBUFFER, stencilbuf);
		ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, width, height);

		if (m_rebind)
			ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilbuf);
	}

	if (!m_rebind)
		ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());

	ctx.clearColor(0.0f, 0.0f, 1.0f, 0.0f);
	ctx.clearStencil(0);
	ctx.clear(Buffers); // \note Clear only buffers that were re-created

	if (stencil)
	{
		// \note Stencil test enabled only if we have stencil buffer
		ctx.enable(GL_STENCIL_TEST);
		ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
	}
	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
	if (stencil)
		ctx.disable(GL_STENCIL_TEST);

	ctx.disable(GL_DEPTH_TEST);

	// Read from fbo
	ctx.readPixels(dst, 0, 0, width, height);
}

class RepeatedClearCase : public FboRenderCase
{
private:
	static FboConfig makeConfig (deUint32 format)
	{
		FboConfig cfg;
		cfg.colorbufferType		= GL_TEXTURE_2D;
		cfg.colorbufferFormat	= format;
		cfg.depthbufferType		= GL_NONE;
		cfg.stencilbufferType	= GL_NONE;
		return cfg;
	}

public:
	RepeatedClearCase (Context& context, deUint32 format)
		: FboRenderCase(context, makeConfig(format).getName().c_str(), "Repeated clears", makeConfig(format))
	{
	}

protected:
	void render (sglr::Context& ctx, Surface& dst)
	{
		const int						numRowsCols		= 4;
		const int						cellSize		= 16;
		const int						fboSizes[]		= { cellSize, cellSize*numRowsCols };

		SingleTex2DShader				fboBlitShader;
		const deUint32					fboBlitShaderID	= ctx.createProgram(&fboBlitShader);

		de::Random						rnd				(18169662);
		deUint32						fbos[]			= { 0, 0 };
		deUint32						textures[]		= { 0, 0 };

		ctx.genFramebuffers(2, &fbos[0]);
		ctx.genTextures(2, &textures[0]);

		for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
		{
			ctx.bindTexture(GL_TEXTURE_2D, textures[fboNdx]);
			ctx.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, fboSizes[fboNdx], fboSizes[fboNdx], 0,
						   getConfig().colorbufferFormat, GL_UNSIGNED_BYTE, DE_NULL);
			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);

			ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
			ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);

			{
				const GLenum status = ctx.checkFramebufferStatus(GL_FRAMEBUFFER);
				if (status != GL_FRAMEBUFFER_COMPLETE)
					throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
			}
		}

		// larger fbo bound -- clear to transparent black
		ctx.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
		ctx.clear(GL_COLOR_BUFFER_BIT);

		fboBlitShader.setUnit(ctx, fboBlitShaderID, 0);
		ctx.bindTexture(GL_TEXTURE_2D, textures[0]);

		for (int cellY = 0; cellY < numRowsCols; cellY++)
		for (int cellX = 0; cellX < numRowsCols; cellX++)
		{
			const float	r	= rnd.getFloat();
			const float	g	= rnd.getFloat();
			const float	b	= rnd.getFloat();
			const float	a	= rnd.getFloat();

			ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
			ctx.clearColor(r, g, b, a);
			ctx.clear(GL_COLOR_BUFFER_BIT);

			ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
			ctx.viewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize);
			sglr::drawQuad(ctx, fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		}

		ctx.readPixels(dst, 0, 0, fboSizes[1], fboSizes[1]);
	}
};

} // FboCases

FboRenderTestGroup::FboRenderTestGroup (Context& context)
	: TestCaseGroup(context, "render", "Rendering Tests")
{
}

FboRenderTestGroup::~FboRenderTestGroup (void)
{
}

namespace
{

struct TypeFormatPair
{
	GLenum		type;
	GLenum		format;
};

template <typename CaseType>
void addChildVariants (deqp::gles2::TestCaseGroup* group)
{
	TypeFormatPair colorbufferConfigs[] =
	{
//		{ GL_TEXTURE_2D,	GL_ALPHA },
//		{ GL_TEXTURE_2D,	GL_LUMINANCE },
//		{ GL_TEXTURE_2D,	GL_LUMINANCE_ALPHA },
		{ GL_TEXTURE_2D,	GL_RGB },
		{ GL_TEXTURE_2D,	GL_RGBA },
		{ GL_RENDERBUFFER,	GL_RGB565 },
		{ GL_RENDERBUFFER,	GL_RGB5_A1 },
		{ GL_RENDERBUFFER,	GL_RGBA4 },
//		{ GL_RENDERBUFFER,	GL_RGBA16F },
//		{ GL_RENDERBUFFER,	GL_RGB16F }
	};
	TypeFormatPair depthbufferConfigs[] =
	{
		{ GL_NONE,			GL_NONE },
		{ GL_RENDERBUFFER,	GL_DEPTH_COMPONENT16 }
	};
	TypeFormatPair stencilbufferConfigs[] =
	{
		{ GL_NONE,			GL_NONE },
		{ GL_RENDERBUFFER,	GL_STENCIL_INDEX8 }
	};

	for (int colorbufferNdx = 0; colorbufferNdx < DE_LENGTH_OF_ARRAY(colorbufferConfigs); colorbufferNdx++)
	for (int depthbufferNdx = 0; depthbufferNdx < DE_LENGTH_OF_ARRAY(depthbufferConfigs); depthbufferNdx++)
	for (int stencilbufferNdx = 0; stencilbufferNdx < DE_LENGTH_OF_ARRAY(stencilbufferConfigs); stencilbufferNdx++)
	{
		FboConfig config;
		config.colorbufferType		= colorbufferConfigs[colorbufferNdx].type;
		config.colorbufferFormat	= colorbufferConfigs[colorbufferNdx].format;
		config.depthbufferType		= depthbufferConfigs[depthbufferNdx].type;
		config.depthbufferFormat	= depthbufferConfigs[depthbufferNdx].format;
		config.stencilbufferType	= stencilbufferConfigs[stencilbufferNdx].type;
		config.stencilbufferFormat	= stencilbufferConfigs[stencilbufferNdx].format;

		if (CaseType::isConfigSupported(config))
			group->addChild(new CaseType(group->getContext(), config));
	}
}

template <typename CaseType>
void createChildGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
{
	deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
	parent->addChild(tmpGroup);
	addChildVariants<CaseType>(tmpGroup);
}

template <GLbitfield Buffers>
void createRecreateBuffersGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
{
	deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
	parent->addChild(tmpGroup);
	addChildVariants<FboCases::RecreateBuffersRebindTest<Buffers> >		(tmpGroup);
	addChildVariants<FboCases::RecreateBuffersNoRebindTest<Buffers> >	(tmpGroup);
}

} // anonymous

void FboRenderTestGroup::init (void)
{
	createChildGroup<FboCases::ColorClearsTest>					(this, "color_clear",		"Color buffer clears");
	createChildGroup<FboCases::StencilClearsTest>				(this, "stencil_clear",		"Stencil buffer clears");

	deqp::gles2::TestCaseGroup* colorGroup = new deqp::gles2::TestCaseGroup(m_context, "color", "Color buffer tests");
	addChild(colorGroup);
	addChildVariants<FboCases::MixTest>			(colorGroup);
	addChildVariants<FboCases::MixNpotTest>		(colorGroup);
	addChildVariants<FboCases::BlendTest>		(colorGroup);
	addChildVariants<FboCases::BlendNpotTest>	(colorGroup);

	deqp::gles2::TestCaseGroup* depthGroup = new deqp::gles2::TestCaseGroup(m_context, "depth", "Depth bufer tests");
	addChild(depthGroup);
	addChildVariants<FboCases::IntersectingQuadsTest>		(depthGroup);
	addChildVariants<FboCases::IntersectingQuadsNpotTest>	(depthGroup);

	deqp::gles2::TestCaseGroup* stencilGroup = new deqp::gles2::TestCaseGroup(m_context, "stencil", "Stencil buffer tests");
	addChild(stencilGroup);
	addChildVariants<FboCases::StencilTest>		(stencilGroup);
	addChildVariants<FboCases::StencilNpotTest>	(stencilGroup);

	createChildGroup<FboCases::SharedColorbufferClearsTest>		(this, "shared_colorbuffer_clear",	"Shared colorbuffer clears");
	createChildGroup<FboCases::SharedColorbufferTest>			(this, "shared_colorbuffer",		"Shared colorbuffer tests");
	createChildGroup<FboCases::SharedDepthbufferTest>			(this, "shared_depthbuffer",		"Shared depthbuffer tests");
	createChildGroup<FboCases::ResizeTest>						(this, "resize",					"FBO resize tests");

	createRecreateBuffersGroup<GL_COLOR_BUFFER_BIT>				(this, "recreate_colorbuffer",		"Recreate colorbuffer tests");
	createRecreateBuffersGroup<GL_DEPTH_BUFFER_BIT>				(this, "recreate_depthbuffer",		"Recreate depthbuffer tests");
	createRecreateBuffersGroup<GL_STENCIL_BUFFER_BIT>			(this, "recreate_stencilbuffer",	"Recreate stencilbuffer tests");

	deqp::gles2::TestCaseGroup* texSubImageGroup = new deqp::gles2::TestCaseGroup(m_context, "texsubimage", "TexSubImage interop with FBO colorbuffer texture");
	addChild(texSubImageGroup);
	addChildVariants<FboCases::TexSubImageAfterRenderTest>		(texSubImageGroup);
	addChildVariants<FboCases::TexSubImageBetweenRenderTest>	(texSubImageGroup);

	{
		tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated FBO clears");
		addChild(repeatedClearGroup);

		repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGB));
		repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGBA));
	}
}

} // Functional
} // gles2
} // deqp
