/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.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.
 *//*--------------------------------------------------------------------*/

#include "es3fFboRenderTest.hpp"
#include "sglrContextUtil.hpp"
#include "sglrGLContext.hpp"
#include "sglrReferenceContext.hpp"
#include "es3fFboTestUtil.hpp"
#include "tcuSurface.hpp"
#include "tcuImageCompare.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuRenderTarget.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTextureUtil.hpp"
#include "gluStrUtil.hpp"
#include "deRandom.h"
#include "deString.h"
#include "glwDefs.hpp"
#include "glwEnums.hpp"

#include <sstream>

using std::vector;
using std::string;
using tcu::TestLog;
using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::IVec2;
using tcu::IVec3;
using tcu::IVec4;
using tcu::RGBA;
using tcu::Surface;

namespace deqp
{
namespace gles3
{
namespace Functional
{

using glw::GLenum;
using namespace FboTestUtil;

class FboConfig
{
public:
	FboConfig (deUint32 buffers_, deUint32 colorType_, deUint32 colorFormat_, deUint32 depthStencilType_, deUint32 depthStencilFormat_, int width_ = 0, int height_ = 0, int samples_ = 0)
		: buffers				(buffers_)
		, colorType				(colorType_)
		, colorFormat			(colorFormat_)
		, depthStencilType		(depthStencilType_)
		, depthStencilFormat	(depthStencilFormat_)
		, width					(width_)
		, height				(height_)
		, samples				(samples_)
	{
	}

	FboConfig (void)
		: buffers				(0)
		, colorType				(GL_NONE)
		, colorFormat			(GL_NONE)
		, depthStencilType		(GL_NONE)
		, depthStencilFormat	(GL_NONE)
		, width					(0)
		, height				(0)
		, samples				(0)
	{
	}

	std::string				getName			(void) const;

	deUint32				buffers;		//!< Buffer bit mask (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|...)

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

	GLenum					depthStencilType;
	GLenum					depthStencilFormat;

	int						width;
	int						height;
	int						samples;
};

static const char* getTypeName (GLenum type)
{
	switch (type)
	{
		case GL_TEXTURE_2D:		return "tex2d";
		case GL_RENDERBUFFER:	return "rbo";
		default:
			TCU_FAIL("Unknown type");
	}
}

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

	DE_ASSERT(buffers & GL_COLOR_BUFFER_BIT);
	name << getTypeName(colorType) << "_" << getFormatName(colorFormat);

	if (buffers & GL_DEPTH_BUFFER_BIT)
		name << "_depth";
	if (buffers & GL_STENCIL_BUFFER_BIT)
		name << "_stencil";

	if (buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))
		name << "_" << getTypeName(depthStencilType) << "_" << getFormatName(depthStencilFormat);

	return name.str();
}

class Framebuffer
{
public:
						Framebuffer				(sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorBuffer = 0, deUint32 depthStencilBuffer = 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			getDepthStencilBuffer	(void) const { return m_depthStencilBuffer;	}

	void				checkCompleteness		(void);

private:
	deUint32			createTex2D				(deUint32 name, GLenum format, int width, int height);
	deUint32			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_depthStencilBuffer;
};

static std::vector<std::string> getEnablingExtensions (deUint32 format)
{
	std::vector<std::string> out;

	switch (format)
	{
		case GL_RGB16F:
			out.push_back("GL_EXT_color_buffer_half_float");
			break;

		case GL_RGBA16F:
		case GL_RG16F:
		case GL_R16F:
			out.push_back("GL_EXT_color_buffer_half_float");
		// Fallthrough

		case GL_RGBA32F:
		case GL_RGB32F:
		case GL_R11F_G11F_B10F:
		case GL_RG32F:
		case GL_R32F:
			out.push_back("GL_EXT_color_buffer_float");
			break;

		default:
			break;
	}

	return out;
}

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 bool isAnyExtensionSupported (sglr::Context& context, const std::vector<std::string>& requiredExts)
{
	if (requiredExts.empty())
		return true;

	for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
	{
		const std::string& extension = *iter;

		if (isExtensionSupported(context, extension.c_str()))
			return true;
	}

	return false;
}

template<typename T>
static std::string join (const std::vector<T>& list, const std::string& sep)
{
	std::ostringstream	out;

	for (typename std::vector<T>::const_iterator iter = list.begin(); iter != list.end(); iter++)
	{
		if (iter != list.begin())
			out << sep;
		out << *iter;
	}

	return out.str();
}

static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat)
{
	const std::vector<std::string> requiredExts = getEnablingExtensions(sizedFormat);

	if (!isAnyExtensionSupported(context, requiredExts))
	{
		std::string	errMsg	= "Format not supported, requires "
							+ ((requiredExts.size() == 1) ? requiredExts[0] : " one of the following: " + join(requiredExts, ", "));

		throw tcu::NotSupportedError(errMsg);
	}
}

Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorBufferName, deUint32 depthStencilBufferName)
	: m_config				(config)
	, m_context				(context)
	, m_framebuffer			(fbo)
	, m_colorBuffer			(0)
	, m_depthStencilBuffer	(0)
{
	// Verify that color format is supported
	checkColorFormatSupport(context, config.colorFormat);

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

	if (m_config.buffers & (GL_COLOR_BUFFER_BIT))
	{
		switch (m_config.colorType)
		{
			case GL_TEXTURE_2D:
				m_colorBuffer = createTex2D(colorBufferName, m_config.colorFormat, width, height);
				context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
				break;

			case GL_RENDERBUFFER:
				m_colorBuffer = createRbo(colorBufferName, m_config.colorFormat, width, height);
				context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
				break;

			default:
				TCU_FAIL("Unsupported type");
		}
	}

	if (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))
	{
		switch (m_config.depthStencilType)
		{
			case GL_TEXTURE_2D:		m_depthStencilBuffer = createTex2D(depthStencilBufferName, m_config.depthStencilFormat, width, height);		break;
			case GL_RENDERBUFFER:	m_depthStencilBuffer = createRbo(depthStencilBufferName, m_config.depthStencilFormat, width, height);		break;
			default:
				TCU_FAIL("Unsupported type");
		}
	}

	for (int ndx = 0; ndx < 2; ndx++)
	{
		deUint32	bit		= ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
		deUint32	point	= ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;

		if ((m_config.buffers & bit) == 0)
			continue; /* Not used. */

		switch (m_config.depthStencilType)
		{
			case GL_TEXTURE_2D:		context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, m_depthStencilBuffer, 0);	break;
			case GL_RENDERBUFFER:	context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, m_depthStencilBuffer);	break;
			default:
				DE_ASSERT(false);
		}
	}

	GLenum err = m_context.getError();
	if (err != GL_NO_ERROR)
		throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), "", __FILE__, __LINE__);

	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
}

Framebuffer::~Framebuffer (void)
{
	m_context.deleteFramebuffers(1, &m_framebuffer);
	destroyBuffer(m_colorBuffer, m_config.colorType);
	destroyBuffer(m_depthStencilBuffer, m_config.depthStencilType);
}

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(status, __FILE__, __LINE__);
}

deUint32 Framebuffer::createTex2D (deUint32 name, GLenum format, int width, int height)
{
	if (name == 0)
		m_context.genTextures(1, &name);

	m_context.bindTexture(GL_TEXTURE_2D, name);
	m_context.texImage2D(GL_TEXTURE_2D, 0, format, width, height);

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

	m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	return name;
}

deUint32 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);

	return name;
}

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;

	bool						compare					(const tcu::Surface& reference, const tcu::Surface& result);

protected:
	const 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)
{
	tcu::Vec4					clearColor				= tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
	glu::RenderContext&			renderCtx				= m_context.getRenderContext();
	const tcu::RenderTarget&	renderTarget			= renderCtx.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	gles3Frame	(width, height);
	tcu::Surface	refFrame	(width, height);
	GLenum			gles3Error;
	GLenum			refError;

	// Render using GLES3
	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, gles3Frame); // Call actual render func
		gles3Error = 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 = (gles3Error == refError);

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

	// Compare images
	bool imagesOk = compare(refFrame, gles3Frame);

	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;
}

bool FboRenderCase::compare (const tcu::Surface& reference, const tcu::Surface& result)
{
	const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_config.colorFormat), tcu::RGBA(12, 12, 12, 12)));

	return tcu::bilinearCompare(m_testCtx.getLog(), "ComparisonResult", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
}

namespace FboCases
{

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

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

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

void StencilClearsTest::render (sglr::Context& context, Surface& dst)
{
	tcu::TextureFormat		colorFormat			= glu::mapGLInternalFormat(m_config.colorFormat);
	glu::DataType			fboSamplerType		= glu::getSampler2DType(colorFormat);
	glu::DataType			fboOutputType		= getFragmentOutputType(colorFormat);
	tcu::TextureFormatInfo	fboRangeInfo		= tcu::getTextureFormatInfo(colorFormat);
	Vec4					fboOutScale			= fboRangeInfo.valueMax - fboRangeInfo.valueMin;
	Vec4					fboOutBias			= fboRangeInfo.valueMin;

	Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
	Texture2DShader			texFromFboShader	(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);

	deUint32				texToFboShaderID	= context.createProgram(&texToFboShader);
	deUint32				texFromFboShaderID	= context.createProgram(&texFromFboShader);

	deUint32				metaballsTex		= 1;
	deUint32				quadsTex			= 2;
	int						width				= 128;
	int						height				= 128;

	texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
	texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);

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

	Framebuffer fbo(context, m_config, 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.enable(GL_STENCIL_TEST);

	context.bindTexture(GL_TEXTURE_2D, quadsTex);
	context.stencilFunc(GL_EQUAL, 1, 0xffu);

	texToFboShader.setUniforms(context, texToFboShaderID);
	sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));

	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
	context.stencilFunc(GL_EQUAL, 2, 0xffu);

	texToFboShader.setUniforms(context, texToFboShaderID);
	sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));

	context.disable(GL_STENCIL_TEST);

	if (fbo.getConfig().colorType == GL_TEXTURE_2D)
	{
		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
		context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
		context.viewport(0, 0, context.getWidth(), context.getHeight());

		texFromFboShader.setUniforms(context, texFromFboShaderID);
		sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
		readPixels(context, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
}

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)
{
	Texture2DShader			texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
	FlatColorShader			flatShader		(glu::TYPE_FLOAT_VEC4);
	deUint32				texShaderID		= context.createProgram(&texShader);
	deUint32				flatShaderID	= context.createProgram(&flatShader);

	int						width			= 128;
	int						height			= 128;
	deUint32				quadsTex		= 1;
	deUint32				metaballsTex	= 2;
	bool					stencil			= (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;

	context.disable(GL_DITHER);

	// Textures
	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);

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

	// Fbo B - don't create colorbuffer
	FboConfig cfg = m_config;
	cfg.buffers		&= ~GL_COLOR_BUFFER_BIT;
	cfg.colorType	 = GL_NONE;
	cfg.colorFormat	 = GL_NONE;
	Framebuffer fboB(context, cfg, width, height);

	// Attach color buffer from fbo A
	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
	switch (m_config.colorType)
	{
		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(DE_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);
	}

	texShader.setUniforms(context, texShaderID);

	context.enable(GL_DEPTH_TEST);
	sglr::drawQuad(context, texShaderID, 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, texShaderID, 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, texShaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
	context.disable(GL_DEPTH_TEST);

	if (stencil)
	{
		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().colorType == GL_TEXTURE_2D)
	{
		texShader.setUniforms(context, texShaderID);

		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
		context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer());
		context.viewport(0, 0, context.getWidth(), context.getHeight());
		sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
		readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(fboA.getConfig().colorFormat), Vec4(1.0f), Vec4(0.0f));
}

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

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

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

void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
{
	tcu::TextureFormat		colorFormat		= glu::mapGLInternalFormat(m_config.colorFormat);
	glu::DataType			fboSamplerType	= glu::getSampler2DType(colorFormat);
	int						width			= 128;
	int						height			= 128;
	deUint32				colorbuffer		= 1;

	// Check for format support.
	checkColorFormatSupport(context, m_config.colorFormat);

	// Single colorbuffer
	if (m_config.colorType == GL_TEXTURE_2D)
	{
		context.bindTexture(GL_TEXTURE_2D, colorbuffer);
		context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorFormat, width, height);
		context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	}
	else
	{
		DE_ASSERT(m_config.colorType == GL_RENDERBUFFER);
		context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
		context.renderbufferStorage(GL_RENDERBUFFER, m_config.colorFormat, width, height);
	}

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

		if (m_config.colorType == 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(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 (m_config.colorType == GL_TEXTURE_2D)
	{
		Texture2DShader shader(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
		deUint32 shaderID = context.createProgram(&shader);

		shader.setUniforms(context, shaderID);

		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
		readPixels(context, dst, 0, 0, width, height, colorFormat, Vec4(1.0f), Vec4(0.0f));
}

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

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

SharedDepthStencilTest::SharedDepthStencilTest (Context& context, const FboConfig& config)
	: FboRenderCase	(context, config.getName().c_str(), "Shared depth/stencilbuffer", config)
{
}

bool SharedDepthStencilTest::isConfigSupported (const FboConfig& config)
{
	return (config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0;
}

void SharedDepthStencilTest::render (sglr::Context& context, Surface& dst)
{
	Texture2DShader	texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
	FlatColorShader	flatShader		(glu::TYPE_FLOAT_VEC4);
	deUint32		texShaderID		= context.createProgram(&texShader);
	deUint32		flatShaderID	= context.createProgram(&flatShader);
	int				width			= 128;
	int				height			= 128;
//	bool			depth			= (m_config.buffers & GL_DEPTH_BUFFER_BIT) != 0;
	bool			stencil			= (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;

	// 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, m_config, width, height);
	fboA.checkCompleteness();

	// Fbo B
	FboConfig cfg = m_config;
	cfg.buffers				&= ~(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	cfg.depthStencilType	 = GL_NONE;
	cfg.depthStencilFormat	 = GL_NONE;
	Framebuffer fboB(context, cfg, width, height);

	// Bind depth/stencil buffers from fbo A to fbo B
	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
	for (int ndx = 0; ndx < 2; ndx++)
	{
		deUint32	bit		= ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
		deUint32	point	= ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;

		if ((m_config.buffers & bit) == 0)
			continue;

		switch (m_config.depthStencilType)
		{
			case GL_TEXTURE_2D:		context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, fboA.getDepthStencilBuffer(), 0);	break;
			case GL_RENDERBUFFER:	context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, fboA.getDepthStencilBuffer());	break;
			default:
				TCU_FAIL("Not implemented");
		}
	}

	// Setup uniforms
	texShader.setUniforms(context, texShaderID);

	// Clear color to red and stencil to 1 in fbo B.
	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);

	context.enable(GL_DEPTH_TEST);

	// Render quad to fbo A
	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
	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 (stencil)
	{
		// Clear subset of stencil buffer to 0 in fbo A
		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 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)
	{
		// Render quad with stencil mask == 0
		context.enable(GL_STENCIL_TEST);
		context.stencilFunc(GL_EQUAL, 0, 0xffu);
		context.useProgram(flatShaderID);
		flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
		sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
		context.disable(GL_STENCIL_TEST);
	}

	if (m_config.colorType == 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
		readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(m_config.colorFormat), Vec4(1.0f), Vec4(0.0f));
	}
}

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

	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)
{
}

void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
{
	using sglr::TexturedQuadOp;

	bool isRGBA = true;

	Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
	tcu::SurfaceUtil::fillWithFourQuads(fourQuads);

	Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
	tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);

	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, fourQuads);

	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);
	context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));

	// Update texture using TexSubImage2D
	context.bindTexture(GL_TEXTURE_2D, fboTex);
	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);

	// Draw to screen
	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
	context.viewport(0, 0, context.getWidth(), context.getHeight());
	context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
}

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

	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)
{
}

void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
{
	using sglr::TexturedQuadOp;
	using sglr::BlendTextureOp;

	bool isRGBA = true;

	Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
	tcu::SurfaceUtil::fillWithFourQuads(fourQuads);

	Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
	tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);

	Surface metaballs2(Surface::PIXELFORMAT_RGBA, 64, 64);
	tcu::SurfaceUtil::fillWithMetaballs(metaballs2, 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, metaballs2);

	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, fourQuads);

	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);
	context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));

	// Update texture using TexSubImage2D
	context.bindTexture(GL_TEXTURE_2D, fboTex);
	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);

	// Render again to fbo
	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
	context.draw(BlendTextureOp(0));

	// Draw to screen
	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
	context.viewport(0, 0, context.getWidth(), context.getHeight());
	context.bindTexture(GL_TEXTURE_2D, fboTex);
	context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));

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

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)
{
	tcu::TextureFormat		colorFormat			= glu::mapGLInternalFormat(m_config.colorFormat);
	glu::DataType			fboSamplerType		= glu::getSampler2DType(colorFormat);
	glu::DataType			fboOutputType		= getFragmentOutputType(colorFormat);
	tcu::TextureFormatInfo	fboRangeInfo		= tcu::getTextureFormatInfo(colorFormat);
	Vec4					fboOutScale			= fboRangeInfo.valueMax - fboRangeInfo.valueMin;
	Vec4					fboOutBias			= fboRangeInfo.valueMin;

	Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
	Texture2DShader			texFromFboShader	(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
	FlatColorShader			flatShader			(fboOutputType);
	deUint32				texToFboShaderID	= context.createProgram(&texToFboShader);
	deUint32				texFromFboShaderID	= context.createProgram(&texFromFboShader);
	deUint32				flatShaderID		= context.createProgram(&flatShader);

	deUint32				quadsTex			= 1;
	deUint32				metaballsTex		= 2;
	bool					depth				= (m_config.buffers & GL_DEPTH_BUFFER_BIT)		!= 0;
	bool					stencil				= (m_config.buffers & GL_STENCIL_BUFFER_BIT)	!= 0;
	int						initialWidth		= 128;
	int						initialHeight		= 128;
	int						newWidth			= 64;
	int						newHeight			= 32;

	texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
	texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);

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

	Framebuffer fbo(context, m_config, initialWidth, initialHeight);
	fbo.checkCompleteness();

	// Setup shaders
	texToFboShader.setUniforms	(context, texToFboShaderID);
	texFromFboShader.setUniforms(context, texFromFboShaderID);
	flatShader.setColor			(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f) * fboOutScale + fboOutBias);

	// Render quads
	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	context.viewport(0, 0, initialWidth, initialHeight);
	clearColorBuffer(context, colorFormat, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
	context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	context.bindTexture(GL_TEXTURE_2D, quadsTex);
	sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

	if (fbo.getConfig().colorType == 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, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

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

	// Resize buffers
	switch (fbo.getConfig().colorType)
	{
		case GL_TEXTURE_2D:
			context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
			context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorFormat, newWidth, newHeight);
			break;

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

		default:
			DE_ASSERT(DE_FALSE);
	}

	if (depth || stencil)
	{
		switch (fbo.getConfig().depthStencilType)
		{
			case GL_TEXTURE_2D:
				context.bindTexture(GL_TEXTURE_2D, fbo.getDepthStencilBuffer());
				context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().depthStencilFormat, newWidth, newHeight);
				break;

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

			default:
				DE_ASSERT(false);
		}
	}

	// Render to resized fbo
	context.viewport(0, 0, newWidth, newHeight);
	clearColorBuffer(context, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
	context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	context.enable(GL_DEPTH_TEST);

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

	context.bindTexture(GL_TEXTURE_2D, quadsTex);
	sglr::drawQuad(context, texToFboShaderID, 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.clearStencil(1);
		context.scissor(10, 10, 5, 15);
		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, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
		context.disable(GL_STENCIL_TEST);
	}

	if (m_config.colorType == 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, texFromFboShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
	}
	else
		readPixels(context, dst, 0, 0, newWidth, newHeight, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
}

class RecreateBuffersTest : public FboRenderCase
{
public:
					RecreateBuffersTest			(Context& context, const FboConfig& config, deUint32 buffers, bool rebind);
	virtual			~RecreateBuffersTest		(void) {}

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

private:
	deUint32		m_buffers;
	bool			m_rebind;
};

RecreateBuffersTest::RecreateBuffersTest (Context& context, const FboConfig& config, deUint32 buffers, bool rebind)
	: FboRenderCase		(context, (string(config.getName()) + (rebind ? "" : "_no_rebind")).c_str(), "Recreate buffers", config)
	, m_buffers			(buffers)
	, m_rebind			(rebind)
{
}

void RecreateBuffersTest::render (sglr::Context& ctx, Surface& dst)
{
	tcu::TextureFormat		colorFormat			= glu::mapGLInternalFormat(m_config.colorFormat);
	glu::DataType			fboSamplerType		= glu::getSampler2DType(colorFormat);
	glu::DataType			fboOutputType		= getFragmentOutputType(colorFormat);
	tcu::TextureFormatInfo	fboRangeInfo		= tcu::getTextureFormatInfo(colorFormat);
	Vec4					fboOutScale			= fboRangeInfo.valueMax - fboRangeInfo.valueMin;
	Vec4					fboOutBias			= fboRangeInfo.valueMin;

	Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
	Texture2DShader			texFromFboShader	(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
	FlatColorShader			flatShader			(fboOutputType);
	deUint32				texToFboShaderID	= ctx.createProgram(&texToFboShader);
	deUint32				texFromFboShaderID	= ctx.createProgram(&texFromFboShader);
	deUint32				flatShaderID		= ctx.createProgram(&flatShader);

	int						width				= 128;
	int						height				= 128;
	deUint32				metaballsTex		= 1;
	deUint32				quadsTex			= 2;
	bool					stencil				= (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;

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

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

	// Setup shaders
	texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
	texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
	texToFboShader.setUniforms	(ctx, texToFboShaderID);
	texFromFboShader.setUniforms(ctx, texFromFboShaderID);
	flatShader.setColor			(ctx, flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f) * fboOutScale + fboOutBias);

	// Draw scene
	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
	ctx.viewport(0, 0, width, height);
	clearColorBuffer(ctx, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
	ctx.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	ctx.enable(GL_DEPTH_TEST);

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

	ctx.disable(GL_DEPTH_TEST);

	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);

	DE_ASSERT((m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == 0 ||
			  (m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)));

	// Recreate.
	for (int ndx = 0; ndx < 2; ndx++)
	{
		deUint32	bit		= ndx == 0 ? GL_COLOR_BUFFER_BIT
									   : (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
		deUint32	type	= ndx == 0 ? fbo.getConfig().colorType
									   : fbo.getConfig().depthStencilType;
		deUint32	format	= ndx == 0 ? fbo.getConfig().colorFormat
									   : fbo.getConfig().depthStencilFormat;
		deUint32	buf		= ndx == 0 ? fbo.getColorBuffer()
									   : fbo.getDepthStencilBuffer();

		if ((m_buffers & bit) == 0)
			continue;

		switch (type)
		{
			case GL_TEXTURE_2D:
				ctx.deleteTextures(1, &buf);
				ctx.bindTexture(GL_TEXTURE_2D, buf);
				ctx.texImage2D(GL_TEXTURE_2D, 0, format, width, height);
				ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
				ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
				break;

			case GL_RENDERBUFFER:
				ctx.deleteRenderbuffers(1, &buf);
				ctx.bindRenderbuffer(GL_RENDERBUFFER, buf);
				ctx.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
				break;

			default:
				DE_ASSERT(false);
		}
	}

	// Rebind.
	if (m_rebind)
	{
		for (int ndx = 0; ndx < 3; ndx++)
		{
			deUint32	bit		= ndx == 0 ? GL_COLOR_BUFFER_BIT	:
								  ndx == 1 ? GL_DEPTH_BUFFER_BIT	:
								  ndx == 2 ? GL_STENCIL_BUFFER_BIT	: 0;
			deUint32	point	= ndx == 0 ? GL_COLOR_ATTACHMENT0	:
								  ndx == 1 ? GL_DEPTH_ATTACHMENT	:
								  ndx == 2 ? GL_STENCIL_ATTACHMENT	: 0;
			deUint32	type	= ndx == 0 ? fbo.getConfig().colorType
										   : fbo.getConfig().depthStencilType;
			deUint32	buf		= ndx == 0 ? fbo.getColorBuffer()
										   : fbo.getDepthStencilBuffer();

			if ((m_buffers & bit) == 0)
				continue;

			switch (type)
			{
				case GL_TEXTURE_2D:
					ctx.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, buf, 0);
					break;

				case GL_RENDERBUFFER:
					ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, buf);
					break;

				default:
					DE_ASSERT(false);
			}
		}
	}

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

	ctx.clearStencil(0);
	ctx.clear(m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); // \note Clear only buffers that were re-created
	if (m_buffers & GL_COLOR_BUFFER_BIT)
	{
		// Clearing of integer buffers is undefined so do clearing by rendering flat color.
		sglr::drawQuad(ctx, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
	}

	ctx.enable(GL_DEPTH_TEST);

	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, texToFboShaderID, 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);

	if (fbo.getConfig().colorType == 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, texFromFboShaderID, 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
		readPixels(ctx, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
	}
}

} // FboCases

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

FboRenderTestGroup::~FboRenderTestGroup (void)
{
}

void FboRenderTestGroup::init (void)
{
	static const deUint32 objectTypes[] =
	{
		GL_TEXTURE_2D,
		GL_RENDERBUFFER
	};

	enum FormatType
	{
		FORMATTYPE_FLOAT = 0,
		FORMATTYPE_FIXED,
		FORMATTYPE_INT,
		FORMATTYPE_UINT,

		FORMATTYPE_LAST
	};

	// Required by specification.
	static const struct
	{
		deUint32	format;
		FormatType	type;
	} colorFormats[] =
	{
		{ GL_RGBA32F,			FORMATTYPE_FLOAT	},
		{ GL_RGBA32I,			FORMATTYPE_INT		},
		{ GL_RGBA32UI,			FORMATTYPE_UINT		},
		{ GL_RGBA16F,			FORMATTYPE_FLOAT	},
		{ GL_RGBA16I,			FORMATTYPE_INT		},
		{ GL_RGBA16UI,			FORMATTYPE_UINT		},
		{ GL_RGB16F,			FORMATTYPE_FLOAT	},
		{ GL_RGBA8,				FORMATTYPE_FIXED	},
		{ GL_RGBA8I,			FORMATTYPE_INT		},
		{ GL_RGBA8UI,			FORMATTYPE_UINT		},
		{ GL_SRGB8_ALPHA8,		FORMATTYPE_FIXED	},
		{ GL_RGB10_A2,			FORMATTYPE_FIXED	},
		{ GL_RGB10_A2UI,		FORMATTYPE_UINT		},
		{ GL_RGBA4,				FORMATTYPE_FIXED	},
		{ GL_RGB5_A1,			FORMATTYPE_FIXED	},
		{ GL_RGB8,				FORMATTYPE_FIXED	},
		{ GL_RGB565,			FORMATTYPE_FIXED	},
		{ GL_R11F_G11F_B10F,	FORMATTYPE_FLOAT	},
		{ GL_RG32F,				FORMATTYPE_FLOAT	},
		{ GL_RG32I,				FORMATTYPE_INT		},
		{ GL_RG32UI,			FORMATTYPE_UINT		},
		{ GL_RG16F,				FORMATTYPE_FLOAT	},
		{ GL_RG16I,				FORMATTYPE_INT		},
		{ GL_RG16UI,			FORMATTYPE_UINT		},
		{ GL_RG8,				FORMATTYPE_FLOAT	},
		{ GL_RG8I,				FORMATTYPE_INT		},
		{ GL_RG8UI,				FORMATTYPE_UINT		},
		{ GL_R32F,				FORMATTYPE_FLOAT	},
		{ GL_R32I,				FORMATTYPE_INT		},
		{ GL_R32UI,				FORMATTYPE_UINT		},
		{ GL_R16F,				FORMATTYPE_FLOAT	},
		{ GL_R16I,				FORMATTYPE_INT		},
		{ GL_R16UI,				FORMATTYPE_UINT		},
		{ GL_R8,				FORMATTYPE_FLOAT	},
		{ GL_R8I,				FORMATTYPE_INT		},
		{ GL_R8UI,				FORMATTYPE_UINT		}
	};

	static const struct
	{
		deUint32	format;
		bool		depth;
		bool		stencil;
	} depthStencilFormats[] =
	{
		{ GL_DEPTH_COMPONENT32F,	true,	false	},
		{ GL_DEPTH_COMPONENT24,		true,	false	},
		{ GL_DEPTH_COMPONENT16,		true,	false	},
		{ GL_DEPTH32F_STENCIL8,		true,	true	},
		{ GL_DEPTH24_STENCIL8,		true,	true	},
		{ GL_STENCIL_INDEX8,		false,	true	}
	};

	using namespace FboCases;

	// .stencil_clear
	tcu::TestCaseGroup* stencilClearGroup = new tcu::TestCaseGroup(m_testCtx, "stencil_clear", "Stencil buffer clears");
	addChild(stencilClearGroup);
	for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
	{
		deUint32	colorType	= GL_TEXTURE_2D;
		deUint32	stencilType	= GL_RENDERBUFFER;
		deUint32	colorFmt	= GL_RGBA8;

		if (!depthStencilFormats[fmtNdx].stencil)
			continue;

		FboConfig config(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, colorType, colorFmt, stencilType, depthStencilFormats[fmtNdx].format);
		stencilClearGroup->addChild(new StencilClearsTest(m_context, config));
	}

	// .shared_colorbuffer_clear
	tcu::TestCaseGroup* sharedColorbufferClearGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer_clear", "Shader colorbuffer clears");
	addChild(sharedColorbufferClearGroup);
	for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
	{
		// Clearing of integer buffers is undefined.
		if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT || colorFormats[colorFmtNdx].type == FORMATTYPE_UINT)
			continue;

		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
		{
			FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE);
			sharedColorbufferClearGroup->addChild(new SharedColorbufferClearsTest(m_context, config));
		}
	}

	// .shared_colorbuffer
	tcu::TestCaseGroup* sharedColorbufferGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer", "Shared colorbuffer tests");
	addChild(sharedColorbufferGroup);
	for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
	{
		deUint32	depthStencilType	= GL_RENDERBUFFER;
		deUint32	depthStencilFormat	= GL_DEPTH24_STENCIL8;

		// Blending with integer buffers and fp32 targets is not supported.
		if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT	||
			colorFormats[colorFmtNdx].type == FORMATTYPE_UINT	||
			colorFormats[colorFmtNdx].format == GL_RGBA32F		||
			colorFormats[colorFmtNdx].format == GL_RGB32F		||
			colorFormats[colorFmtNdx].format == GL_RG32F		||
			colorFormats[colorFmtNdx].format == GL_R32F)
			continue;

		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
		{
			FboConfig colorOnlyConfig			(GL_COLOR_BUFFER_BIT,											objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE);
			FboConfig colorDepthConfig			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT,						objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat);
			FboConfig colorDepthStencilConfig	(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT,	objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat);

			sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorOnlyConfig));
			sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthConfig));
			sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthStencilConfig));
		}
	}

	// .shared_depth_stencil
	tcu::TestCaseGroup* sharedDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "shared_depth_stencil", "Shared depth and stencil buffers");
	addChild(sharedDepthStencilGroup);
	for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
	{
		deUint32	colorType		= GL_TEXTURE_2D;
		deUint32	colorFmt		= GL_RGBA8;
		bool		depth			= depthStencilFormats[fmtNdx].depth;
		bool		stencil			= depthStencilFormats[fmtNdx].stencil;

		if (!depth)
			continue; // Not verified.

		// Depth and stencil: both rbo and textures
		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
		{
			FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
			sharedDepthStencilGroup->addChild(new SharedDepthStencilTest(m_context, config));
		}
	}

	// .resize
	tcu::TestCaseGroup* resizeGroup = new tcu::TestCaseGroup(m_testCtx, "resize", "FBO resize tests");
	addChild(resizeGroup);
	for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
	{
		deUint32 colorFormat = colorFormats[colorFmtNdx].format;

		// Color-only.
		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
		{
			FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormat, GL_NONE, GL_NONE);
			resizeGroup->addChild(new ResizeTest(m_context, config));
		}

		// For selected color formats tests depth & stencil variants.
		if (colorFormat == GL_RGBA8 || colorFormat == GL_RGBA16F)
		{
			for (int depthStencilFmtNdx = 0; depthStencilFmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); depthStencilFmtNdx++)
			{
				deUint32	colorType		= GL_TEXTURE_2D;
				bool		depth			= depthStencilFormats[depthStencilFmtNdx].depth;
				bool		stencil			= depthStencilFormats[depthStencilFmtNdx].stencil;

				// Depth and stencil: both rbo and textures
				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
				{
					if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
						continue; // Not supported.

					FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0),
									 colorType, colorFormat,
									 objectTypes[typeNdx], depthStencilFormats[depthStencilFmtNdx].format);
					resizeGroup->addChild(new ResizeTest(m_context, config));
				}
			}
		}
	}

	// .recreate_color
	tcu::TestCaseGroup* recreateColorGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_color", "Recreate colorbuffer tests");
	addChild(recreateColorGroup);
	for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
	{
		deUint32	colorFormat			= colorFormats[colorFmtNdx].format;
		deUint32	depthStencilFormat	= GL_DEPTH24_STENCIL8;
		deUint32	depthStencilType	= GL_RENDERBUFFER;

		// Color-only.
		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
		{
			FboConfig config(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormat, depthStencilType, depthStencilFormat);
			recreateColorGroup->addChild(new RecreateBuffersTest(m_context, config, GL_COLOR_BUFFER_BIT, true /* rebind */));
		}
	}

	// .recreate_depth_stencil
	tcu::TestCaseGroup* recreateDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_depth_stencil", "Recreate depth and stencil buffers");
	addChild(recreateDepthStencilGroup);
	for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
	{
		deUint32	colorType		= GL_TEXTURE_2D;
		deUint32	colorFmt		= GL_RGBA8;
		bool		depth			= depthStencilFormats[fmtNdx].depth;
		bool		stencil			= depthStencilFormats[fmtNdx].stencil;

		// Depth and stencil: both rbo and textures
		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
		{
			if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
				continue;

			FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
			recreateDepthStencilGroup->addChild(new RecreateBuffersTest(m_context, config, (depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), true /* rebind */));
		}
	}
}

} // Functional
} // gles3
} // deqp
