/*-------------------------------------------------------------------------
 * 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.05f;
	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
