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

#include "glsFboCompletenessTests.hpp"

#include "gluStrUtil.hpp"
#include "gluObjectWrapper.hpp"
#include "deStringUtil.hpp"

#include <cctype>
#include <iterator>
#include <algorithm>

using namespace glw;
using glu::RenderContext;
using glu::getFramebufferStatusName;
using glu::getTextureFormatName;
using glu::getTypeName;
using glu::getErrorName;
using glu::Framebuffer;
using tcu::TestCase;
using tcu::TestCaseGroup;
using tcu::TestLog;
using tcu::MessageBuilder;
using tcu::TestNode;
using std::string;
using de::toString;
using de::toLower;
using namespace deqp::gls::FboUtil;
using namespace deqp::gls::FboUtil::config;
typedef TestCase::IterateResult IterateResult;

namespace deqp
{
namespace gls
{
namespace fboc
{

namespace details
{

// The following extensions are applicable both to ES2 and ES3.

// GL_OES_depth_texture
static const FormatKey s_oesDepthTextureFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_DEPTH_COMPONENT,	GL_UNSIGNED_SHORT),
	GLS_UNSIZED_FORMATKEY(GL_DEPTH_COMPONENT,	GL_UNSIGNED_INT),
};

// GL_OES_packed_depth_stencil
static const FormatKey s_oesPackedDepthStencilSizedFormats[] =
{
	GL_DEPTH24_STENCIL8,
};

static const FormatKey s_oesPackedDepthStencilTexFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8),
};

// GL_OES_required_internalformat
static const FormatKey s_oesRequiredInternalFormatColorFormats[] =
{
	// Same as ES2 RBO formats, plus RGBA8 (even without OES_rgb8_rgba8)
	GL_RGB5_A1, GL_RGBA8, GL_RGBA4, GL_RGB565
};

static const FormatKey s_oesRequiredInternalFormatDepthFormats[] =
{
	GL_DEPTH_COMPONENT16,
};

// GL_EXT_color_buffer_half_float
static const FormatKey s_extColorBufferHalfFloatFormats[] =
{
	GL_RGBA16F, GL_RGB16F, GL_RG16F, GL_R16F,
};

static const FormatKey s_oesDepth24SizedFormats[] =
{
	GL_DEPTH_COMPONENT24
};

static const FormatKey s_oesDepth32SizedFormats[] =
{
	GL_DEPTH_COMPONENT32
};

static const FormatKey s_oesRgb8Rgba8RboFormats[] =
{
	GL_RGB8,
	GL_RGBA8,
};

static const FormatKey s_oesRequiredInternalFormatRgb8ColorFormat[] =
{
	GL_RGB8,
};

static const FormatKey s_extTextureType2101010RevFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_RGBA,	GL_UNSIGNED_INT_2_10_10_10_REV),
	GLS_UNSIZED_FORMATKEY(GL_RGB,	GL_UNSIGNED_INT_2_10_10_10_REV),
};

static const FormatKey s_oesRequiredInternalFormat10bitColorFormats[] =
{
	GL_RGB10_A2, GL_RGB10,
};

static const FormatKey s_extTextureRgRboFormats[] =
{
	GL_R8, GL_RG8,
};

static const FormatKey s_extTextureRgTexFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_RED,	GL_UNSIGNED_BYTE),
	GLS_UNSIZED_FORMATKEY(GL_RG,	GL_UNSIGNED_BYTE),
};

static const FormatKey s_extTextureRgFloatTexFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_RED,	GL_FLOAT),
	GLS_UNSIZED_FORMATKEY(GL_RG,	GL_FLOAT),
};

static const FormatKey s_extTextureRgHalfFloatTexFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_RED,	GL_HALF_FLOAT_OES),
	GLS_UNSIZED_FORMATKEY(GL_RG,	GL_HALF_FLOAT_OES),
};

static const FormatKey s_nvPackedFloatRboFormats[] =
{
	GL_R11F_G11F_B10F,
};

static const FormatKey s_nvPackedFloatTexFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_RGB,	GL_UNSIGNED_INT_10F_11F_11F_REV),
};

static const FormatKey s_extSrgbRboFormats[] =
{
	GL_SRGB8_ALPHA8,
};

static const FormatKey s_extSrgbRenderableTexFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_SRGB_ALPHA,	GL_UNSIGNED_BYTE),
};

static const FormatKey s_extSrgbNonRenderableTexFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_SRGB,			GL_UNSIGNED_BYTE),
};

static const FormatKey s_nvSrgbFormatsRboFormats[] =
{
	GL_SRGB8,
};

static const FormatKey s_nvSrgbFormatsTextureFormats[] =
{
	GL_SRGB8,

	// The extension does not actually require any unsized format
	// to be renderable. However, the renderablility of unsized
	// SRGB,UBYTE internalformat-type pair is implied.
	GLS_UNSIZED_FORMATKEY(GL_SRGB,			GL_UNSIGNED_BYTE),
};

static const FormatKey s_oesRgb8Rgba8TexFormats[] =
{
	GLS_UNSIZED_FORMATKEY(GL_RGB,		GL_UNSIGNED_BYTE),
	GLS_UNSIZED_FORMATKEY(GL_RGBA,		GL_UNSIGNED_BYTE),
};

static const FormatKey s_extTextureSRGBR8Formats[] =
{
	GL_SR8_EXT,
};

static const FormatKey s_extTextureSRGBRG8Formats[] =
{
	GL_SRG8_EXT,
};

static const FormatExtEntry s_esExtFormats[] =
{
	{
		"GL_OES_depth_texture",
		(deUint32)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_oesDepthTextureFormats),
	},
	{
		"GL_OES_packed_depth_stencil",
		(deUint32)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID),
		GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats)
	},
	{
		"GL_OES_packed_depth_stencil GL_OES_required_internalformat",
		(deUint32)TEXTURE_VALID,
		GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats)
	},
	{
		"GL_OES_packed_depth_stencil GL_OES_depth_texture",
		(deUint32)(DEPTH_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_oesPackedDepthStencilTexFormats)
	},
	// The ANGLE extension incorporates GL_OES_depth_texture/GL_OES_packed_depth_stencil.
	{
		"GL_ANGLE_depth_texture",
		(deUint32)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_oesDepthTextureFormats),
	},
	{
		"GL_OES_packed_depth_stencil GL_ANGLE_depth_texture",
		(deUint32)(DEPTH_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_oesPackedDepthStencilTexFormats),
	},
	// \todo [2013-12-10 lauri] Find out if OES_texture_half_float is really a
	// requirement on ES3 also. Or is color_buffer_half_float applicatble at
	// all on ES3, since there's also EXT_color_buffer_float?
	{
		"GL_OES_texture_half_float GL_EXT_color_buffer_half_float",
		(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
		GLS_ARRAY_RANGE(s_extColorBufferHalfFloatFormats)
	},

	// OES_required_internalformat doesn't actually specify that these are renderable,
	// since it was written against ES 1.1.
	{
		"GL_OES_required_internalformat",
		 // Allow but don't require RGBA8 to be color-renderable if
		 // OES_rgb8_rgba8 is not present.
		(deUint32)(COLOR_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_oesRequiredInternalFormatColorFormats)
	},
	{
		"GL_OES_required_internalformat",
		(deUint32)(DEPTH_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_oesRequiredInternalFormatDepthFormats)
	},
	{
		"GL_EXT_texture_rg",
		(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
		GLS_ARRAY_RANGE(s_extTextureRgRboFormats)
	},
	// These are not specified to be color-renderable, but the wording is
	// exactly as ambiguous as the wording in the ES2 spec.
	{
		"GL_EXT_texture_rg",
		(deUint32)(COLOR_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_extTextureRgTexFormats)
	},
	{
		"GL_EXT_texture_rg GL_OES_texture_float",
		(deUint32)(COLOR_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_extTextureRgFloatTexFormats)
	},
	{
		"GL_EXT_texture_rg GL_OES_texture_half_float",
		(deUint32)(COLOR_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_extTextureRgHalfFloatTexFormats)
	},

	{
		"GL_NV_packed_float",
		(deUint32)(COLOR_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_nvPackedFloatTexFormats)
	},
	{
		"GL_NV_packed_float GL_EXT_color_buffer_half_float",
		(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
		GLS_ARRAY_RANGE(s_nvPackedFloatRboFormats)
	},

	{
		"GL_EXT_sRGB",
		(deUint32)(COLOR_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_extSrgbRenderableTexFormats)
	},
	{
		"GL_EXT_sRGB",
		(deUint32)TEXTURE_VALID,
		GLS_ARRAY_RANGE(s_extSrgbNonRenderableTexFormats)
	},
	{
		"GL_EXT_sRGB",
		(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
		GLS_ARRAY_RANGE(s_extSrgbRboFormats)
	},
	{
		"GL_NV_sRGB_formats",
		(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
		GLS_ARRAY_RANGE(s_nvSrgbFormatsRboFormats)
	},
	{
		"GL_NV_sRGB_formats",
		(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_nvSrgbFormatsTextureFormats)
	},

	 // In Khronos bug 7333 discussion, the consensus is that these texture
	 // formats, at least, should be color-renderable. Still, that cannot be
	 // found in any extension specs, so only allow it, not require it.
	{
		"GL_OES_rgb8_rgba8",
		(deUint32)(COLOR_RENDERABLE | TEXTURE_VALID),
		GLS_ARRAY_RANGE(s_oesRgb8Rgba8TexFormats)
	},
	{
		"GL_OES_rgb8_rgba8",
		(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
		GLS_ARRAY_RANGE(s_oesRgb8Rgba8RboFormats)
	},
	{
		"GL_OES_rgb8_rgba8 GL_OES_required_internalformat",
		(deUint32)TEXTURE_VALID,
		GLS_ARRAY_RANGE(s_oesRequiredInternalFormatRgb8ColorFormat)
	},

	// The depth-renderability of the depth RBO formats is not explicitly
	// spelled out, but all renderbuffer formats are meant to be renderable.
	{
		"GL_OES_depth24",
		(deUint32)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID),
		GLS_ARRAY_RANGE(s_oesDepth24SizedFormats)
	},
	{
		"GL_OES_depth24 GL_OES_required_internalformat GL_OES_depth_texture",
		(deUint32)TEXTURE_VALID,
		GLS_ARRAY_RANGE(s_oesDepth24SizedFormats)
	},

	{
		"GL_OES_depth32",
		(deUint32)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID),
		GLS_ARRAY_RANGE(s_oesDepth32SizedFormats)
	},
	{
		"GL_OES_depth32 GL_OES_required_internalformat GL_OES_depth_texture",
		(deUint32)TEXTURE_VALID,
		GLS_ARRAY_RANGE(s_oesDepth32SizedFormats)
	},

	{
		"GL_EXT_texture_type_2_10_10_10_REV",
		(deUint32)TEXTURE_VALID, // explicitly unrenderable
		GLS_ARRAY_RANGE(s_extTextureType2101010RevFormats)
	},
	{
		"GL_EXT_texture_type_2_10_10_10_REV GL_OES_required_internalformat",
		(deUint32)TEXTURE_VALID, // explicitly unrenderable
		GLS_ARRAY_RANGE(s_oesRequiredInternalFormat10bitColorFormats)
	},

	{
		"GL_EXT_texture_sRGB_R8",
		(deUint32)TEXTURE_VALID,
		GLS_ARRAY_RANGE(s_extTextureSRGBR8Formats)
	},
	{
		"GL_EXT_texture_sRGB_RG8",
		(deUint32)TEXTURE_VALID,
		GLS_ARRAY_RANGE(s_extTextureSRGBRG8Formats)
	},
};

Context::Context (TestContext& testCtx,
				  RenderContext& renderCtx,
				  CheckerFactory& factory)
	: m_testCtx				(testCtx)
	, m_renderCtx			(renderCtx)
	, m_verifier			(m_ctxFormats, factory, renderCtx)
	, m_haveMultiColorAtts	(false)
{
	FormatExtEntries extRange = GLS_ARRAY_RANGE(s_esExtFormats);
	addExtFormats(extRange);
}

void Context::addFormats (FormatEntries fmtRange)
{
	FboUtil::addFormats(m_coreFormats, fmtRange);
	FboUtil::addFormats(m_ctxFormats, fmtRange);
	FboUtil::addFormats(m_allFormats, fmtRange);
}

void Context::addExtFormats (FormatExtEntries extRange)
{
	FboUtil::addExtFormats(m_ctxFormats, extRange, &m_renderCtx);
	FboUtil::addExtFormats(m_allFormats, extRange, DE_NULL);
}

void TestBase::pass (void)
{
	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}

void TestBase::qualityWarning (const char* msg)
{
	m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, msg);
}

void TestBase::fail (const char* msg)
{
	m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, msg);
}

const glw::Functions& gl (const TestBase& test)
{
	return test.getContext().getRenderContext().getFunctions();
}

static bool isFormatFeatureSupported (const FormatDB& db, const ImageFormat& format, FormatFlags feature)
{
	return db.isKnownFormat(format) && ((db.getFormatInfo(format) & feature) == feature);
}

static void logAffectingExtensions (const char* prefix, const FormatDB& db, const ImageFormat& format, FormatFlags feature, tcu::MessageBuilder& msg)
{
	const std::set<std::set<std::string> > rows = db.getFormatFeatureExtensions(format, feature);

	for (std::set<std::set<std::string> >::const_iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt)
	{
		const std::set<std::string>&			requiredExtensions	= *rowIt;
		std::set<std::string>::const_iterator	it					= requiredExtensions.begin();
		std::string								extName;

		msg << prefix;

		extName = *it++;
		while (it != requiredExtensions.end())
		{
			msg << getExtensionDescription(extName);
			extName = *it++;
			msg << (it == requiredExtensions.end() ? " and " : ", ");
		}

		msg << getExtensionDescription(extName) << '\n';
	}
}

static void logFormatInfo (const config::Framebuffer& fbo, const FormatDB& ctxFormats, const FormatDB& coreFormats, const FormatDB& allFormats, tcu::TestLog& log)
{
	static const struct
	{
		const char*			name;
		const FormatFlags	flag;
	} s_renderability[] =
	{
		{ "color-renderable",	COLOR_RENDERABLE	},
		{ "depth-renderable",	DEPTH_RENDERABLE	},
		{ "stencil-renderable",	STENCIL_RENDERABLE	},
	};

	std::set<ImageFormat> formats;

	for (config::TextureMap::const_iterator it = fbo.textures.begin(); it != fbo.textures.end(); ++it)
		formats.insert(it->second->internalFormat);
	for (config::RboMap::const_iterator it = fbo.rbos.begin(); it != fbo.rbos.end(); ++it)
		formats.insert(it->second->internalFormat);

	if (!formats.empty())
	{
		const tcu::ScopedLogSection supersection(log, "Format", "Format info");

		for (std::set<ImageFormat>::const_iterator it = formats.begin(); it != formats.end(); ++it)
		{
			const tcu::ScopedLogSection section(log, "FormatInfo", de::toString(*it));

			// texture validity
			if (isFormatFeatureSupported(ctxFormats, *it, TEXTURE_VALID))
			{
				tcu::MessageBuilder msg(&log);
				msg << "* Valid texture format\n";

				if (isFormatFeatureSupported(coreFormats, *it, TEXTURE_VALID))
					msg << "\t* core feature";
				else
				{
					msg << "\t* defined in supported extension(s):\n";
					logAffectingExtensions("\t\t- ", ctxFormats, *it, TEXTURE_VALID, msg);
				}

				msg << tcu::TestLog::EndMessage;
			}
			else
			{
				tcu::MessageBuilder msg(&log);
				msg << "* Unsupported texture format\n";

				if (isFormatFeatureSupported(allFormats, *it, TEXTURE_VALID))
				{
					msg << "\t* requires any of the extensions or combinations:\n";
					logAffectingExtensions("\t\t- ", allFormats, *it, TEXTURE_VALID, msg);
				}
				else
					msg << "\t* no extension can make this format valid";

				msg << tcu::TestLog::EndMessage;
			}

			// RBO validity
			if (isFormatFeatureSupported(ctxFormats, *it, RENDERBUFFER_VALID))
			{
				tcu::MessageBuilder msg(&log);
				msg << "* Valid renderbuffer format\n";

				if (isFormatFeatureSupported(coreFormats, *it, RENDERBUFFER_VALID))
					msg << "\t* core feature";
				else
				{
					msg << "\t* defined in supported extension(s):\n";
					logAffectingExtensions("\t\t- ", ctxFormats, *it, RENDERBUFFER_VALID, msg);
				}

				msg << tcu::TestLog::EndMessage;
			}
			else
			{
				tcu::MessageBuilder msg(&log);
				msg << "* Unsupported renderbuffer format\n";

				if (isFormatFeatureSupported(allFormats, *it, RENDERBUFFER_VALID))
				{
					msg << "\t* requires any of the extensions or combinations:\n";
					logAffectingExtensions("\t\t- ", allFormats, *it, RENDERBUFFER_VALID, msg);
				}
				else
					msg << "\t* no extension can make this format valid";

				msg << tcu::TestLog::EndMessage;
			}

			// renderability
			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_renderability); ++ndx)
			{
				if (isFormatFeatureSupported(ctxFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE))
				{
					tcu::MessageBuilder msg(&log);
					msg << "* Format is " << s_renderability[ndx].name << "\n";

					if (isFormatFeatureSupported(coreFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE))
						msg << "\t* core feature";
					else
					{
						msg << "\t* defined in supported extension(s):\n";
						logAffectingExtensions("\t\t- ", ctxFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE, msg);
					}

					msg << tcu::TestLog::EndMessage;
				}
				else if (isFormatFeatureSupported(ctxFormats, *it, s_renderability[ndx].flag))
				{
					tcu::MessageBuilder msg(&log);
					msg << "* Format is allowed to be " << s_renderability[ndx].name << " but not required\n";

					if (isFormatFeatureSupported(coreFormats, *it, s_renderability[ndx].flag))
						msg << "\t* core feature";
					else if (isFormatFeatureSupported(allFormats, *it, s_renderability[ndx].flag))
					{
						msg << "\t* extensions that would make format " << s_renderability[ndx].name << ":\n";
						logAffectingExtensions("\t\t- ", allFormats, *it, s_renderability[ndx].flag, msg);
					}
					else
						msg << "\t* no extension can make this format " << s_renderability[ndx].name;

					msg << tcu::TestLog::EndMessage;
				}
				else
				{
					tcu::MessageBuilder msg(&log);
					msg << "* Format is NOT " << s_renderability[ndx].name << "\n";

					if (isFormatFeatureSupported(allFormats, *it, s_renderability[ndx].flag))
					{
						if (isFormatFeatureSupported(allFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE))
						{
							msg << "\t* extensions that would make format " << s_renderability[ndx].name << ":\n";
							logAffectingExtensions("\t\t- ", allFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE, msg);
						}
						else
						{
							msg << "\t* extensions that are allowed to make format " << s_renderability[ndx].name << ":\n";
							logAffectingExtensions("\t\t- ", allFormats, *it, s_renderability[ndx].flag, msg);
						}
					}
					else
						msg << "\t* no extension can make this format " << s_renderability[ndx].name;

					msg << tcu::TestLog::EndMessage;
				}
			}
		}
	}
}

IterateResult TestBase::iterate (void)
{
	glu::Framebuffer		fbo			(m_ctx.getRenderContext());
	FboBuilder				builder		(*fbo, GL_FRAMEBUFFER, gl(*this));
	const IterateResult		ret			= build(builder);
	const ValidStatusCodes	reference	= m_ctx.getVerifier().validStatusCodes(builder);
	const GLenum			errorCode	= builder.getError();

	logFramebufferConfig(builder, m_testCtx.getLog());
	logFormatInfo(builder, m_ctx.getCtxFormats(), m_ctx.getCoreFormats(), m_ctx.getAllFormats(), m_testCtx.getLog());
	reference.logRules(m_testCtx.getLog());
	reference.logLegalResults(m_testCtx.getLog());

	// \todo [2013-12-04 lauri] Check if drawing operations succeed.

	if (errorCode != GL_NO_ERROR)
	{
		m_testCtx.getLog()
			<< TestLog::Message
			<< "Received " << glu::getErrorStr(errorCode) << " (during FBO initialization)."
			<< TestLog::EndMessage;

		if (reference.isErrorCodeValid(errorCode))
			pass();
		else if (reference.isErrorCodeRequired(GL_NO_ERROR))
			fail(("Expected no error but got " + de::toString(glu::getErrorStr(errorCode))).c_str());
		else
			fail("Got wrong error code");
	}
	else
	{
		const GLenum	fboStatus	= gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER);
		const bool		validStatus	= reference.isFBOStatusValid(fboStatus);

		m_testCtx.getLog()
			<< TestLog::Message
			<< "Received " << glu::getFramebufferStatusStr(fboStatus) << "."
			<< TestLog::EndMessage;

		if (!validStatus)
		{
			if (fboStatus == GL_FRAMEBUFFER_COMPLETE)
				fail("Framebuffer checked as complete, expected incomplete");
			else if (reference.isFBOStatusRequired(GL_FRAMEBUFFER_COMPLETE))
				fail("Framebuffer checked is incomplete, expected complete");
			else
				// An incomplete status is allowed, but not _this_ incomplete status.
				fail("Framebuffer checked as incomplete, but with wrong status");
		}
		else if (fboStatus != GL_FRAMEBUFFER_COMPLETE && reference.isFBOStatusValid(GL_FRAMEBUFFER_COMPLETE))
			qualityWarning("Framebuffer object could have checked as complete but did not.");
		else
			pass();
	}

	return ret;
}

IterateResult TestBase::build (FboBuilder& builder)
{
	DE_UNREF(builder);
	return STOP;
}

ImageFormat TestBase::getDefaultFormat (GLenum attPoint, GLenum bufType) const
{
	if (bufType == GL_NONE)
	{
		return ImageFormat::none();
	}

	// Prefer a standard format, if there is one, but if not, use a format
	// provided by an extension.
	Formats formats = m_ctx.getCoreFormats().getFormats(formatFlag(attPoint) |
														 formatFlag(bufType));
	Formats::const_iterator it = formats.begin();
	if (it == formats.end())
	{
		formats = m_ctx.getCtxFormats().getFormats(formatFlag(attPoint) |
													 formatFlag(bufType));
		it = formats.begin();
	}
	if (it == formats.end())
		throw tcu::NotSupportedError("Unsupported attachment kind for attachment point",
									 "", __FILE__, __LINE__);
	return *it;
};

Image* makeImage (GLenum bufType, ImageFormat format,
				  GLsizei width, GLsizei height, FboBuilder& builder)
{
	Image* image = DE_NULL;
	switch (bufType)
	{
		case GL_NONE:
			return DE_NULL;
		case GL_RENDERBUFFER:
			image = &builder.makeConfig<Renderbuffer>();
			break;
		case GL_TEXTURE:
			image = &builder.makeConfig<Texture2D>();
			break;
		default:
			DE_FATAL("Impossible case");
	}
	image->internalFormat = format;
	image->width = width;
	image->height = height;
	return image;
}

Attachment* makeAttachment (GLenum bufType, ImageFormat format,
							GLsizei width, GLsizei height, FboBuilder& builder)
{
	Image* const imgCfg = makeImage (bufType, format, width, height, builder);
	Attachment* att = DE_NULL;
	GLuint img = 0;

	if (Renderbuffer* rboCfg = dynamic_cast<Renderbuffer*>(imgCfg))
	{
		img = builder.glCreateRbo(*rboCfg);
		att = &builder.makeConfig<RenderbufferAttachment>();
	}
	else if (Texture2D* texCfg = dynamic_cast<Texture2D*>(imgCfg))
	{
		img = builder.glCreateTexture(*texCfg);
		TextureFlatAttachment& texAtt = builder.makeConfig<TextureFlatAttachment>();
		texAtt.texTarget = GL_TEXTURE_2D;
		att = &texAtt;
	}
	else
	{
		DE_ASSERT(imgCfg == DE_NULL);
		return DE_NULL;
	}
	att->imageName = img;
	return att;
}

void TestBase::attachTargetToNew (GLenum target, GLenum bufType, ImageFormat format,
								  GLsizei width, GLsizei height, FboBuilder& builder)
{
	ImageFormat imgFmt = format;
	if (imgFmt.format == GL_NONE)
		imgFmt = getDefaultFormat(target, bufType);

	const Attachment* const att = makeAttachment(bufType, imgFmt, width, height, builder);
	builder.glAttach(target, att);
}

static string formatName (ImageFormat format)
{
	const string s = getTextureFormatName(format.format);
	const string fmtStr = toLower(s.substr(3));

	if (format.unsizedType != GL_NONE)
	{
		const string typeStr = getTypeName(format.unsizedType);
		return fmtStr + "_" + toLower(typeStr.substr(3));
	}

	return fmtStr;
}

static string formatDesc (ImageFormat format)
{
	const string fmtStr = getTextureFormatName(format.format);

	if (format.unsizedType != GL_NONE)
	{
		const string typeStr = getTypeName(format.unsizedType);
		return fmtStr + " with type " + typeStr;
	}

	return fmtStr;
}

struct RenderableParams
{
	GLenum				attPoint;
	GLenum				bufType;
	ImageFormat			format;
	static string		getName				(const RenderableParams& params)
	{
		return formatName(params.format);
	}
	static string		getDescription		(const RenderableParams& params)
	{
		return formatDesc(params.format);
	}
};

class RenderableTest : public ParamTest<RenderableParams>
{
public:
					RenderableTest		(Context& group, const Params& params)
						: ParamTest<RenderableParams> (group, params) {}
	IterateResult	build				(FboBuilder& builder);
};

IterateResult RenderableTest::build (FboBuilder& builder)
{
	attachTargetToNew(m_params.attPoint, m_params.bufType, m_params.format, 64, 64, builder);
	return STOP;
}

string attTypeName (GLenum bufType)
{
	switch (bufType)
	{
		case GL_NONE:
			return "none";
		case GL_RENDERBUFFER:
			return "rbo";
		case GL_TEXTURE:
			return "tex";
		default:
			DE_FATAL("Impossible case");
	}
	return ""; // Shut up compiler
}

struct AttachmentParams
{
	GLenum						color0Kind;
	GLenum						colornKind;
	GLenum						depthKind;
	GLenum						stencilKind;

	static string		getName			(const AttachmentParams& params);
	static string		getDescription	(const AttachmentParams& params)
	{
		return getName(params);
	}
};

string AttachmentParams::getName (const AttachmentParams& params)
{
	return (attTypeName(params.color0Kind) + "_" +
			attTypeName(params.colornKind) + "_" +
			attTypeName(params.depthKind) + "_" +
			attTypeName(params.stencilKind));
}

//! Test for combinations of different kinds of attachments
class AttachmentTest : public ParamTest<AttachmentParams>
{
public:
					AttachmentTest		(Context& group, Params& params)
						: ParamTest<AttachmentParams> (group, params) {}

protected:
	IterateResult	build				(FboBuilder& builder);
	void			makeDepthAndStencil	(FboBuilder& builder);
};


void AttachmentTest::makeDepthAndStencil (FboBuilder& builder)
{
	if (m_params.stencilKind == m_params.depthKind)
	{
		// If there is a common stencil+depth -format, try to use a common
		// image for both attachments.
		const FormatFlags flags =
			DEPTH_RENDERABLE | STENCIL_RENDERABLE | formatFlag(m_params.stencilKind);
		const Formats& formats = m_ctx.getCoreFormats().getFormats(flags);
		Formats::const_iterator it = formats.begin();
		if (it != formats.end())
		{
			const ImageFormat format = *it;
			Attachment* att = makeAttachment(m_params.depthKind, format, 64, 64, builder);
			builder.glAttach(GL_DEPTH_ATTACHMENT, att);
			builder.glAttach(GL_STENCIL_ATTACHMENT, att);
			return;
		}
	}
	// Either the kinds were separate, or a suitable format was not found.
	// Create separate images.
	attachTargetToNew(GL_STENCIL_ATTACHMENT, m_params.stencilKind, ImageFormat::none(),
					  64, 64, builder);
	attachTargetToNew(GL_DEPTH_ATTACHMENT, m_params.depthKind, ImageFormat::none(),
					  64, 64, builder);
}

IterateResult AttachmentTest::build (FboBuilder& builder)
{
	attachTargetToNew(GL_COLOR_ATTACHMENT0, m_params.color0Kind, ImageFormat::none(),
					  64, 64, builder);

	if (m_params.colornKind != GL_NONE)
	{
		TCU_CHECK_AND_THROW(NotSupportedError, m_ctx.haveMultiColorAtts(),
							"Multiple attachments not supported");
		GLint maxAttachments = 1;
		gl(*this).getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxAttachments);
		GLU_EXPECT_NO_ERROR(
			gl(*this).getError(), "Couldn't read GL_MAX_COLOR_ATTACHMENTS");

		for (int i = 1; i < maxAttachments; i++)
		{
			attachTargetToNew(GL_COLOR_ATTACHMENT0 + i, m_params.colornKind,
							  ImageFormat::none(), 64, 64, builder);
		}
	}

	makeDepthAndStencil(builder);

	return STOP;
}

class EmptyImageTest : public TestBase
{
public:
					EmptyImageTest	(Context& group,
									 const char* name, const char* desc)
						: TestBase	(group, name, desc) {}

	IterateResult	build			(FboBuilder& builder);
};

IterateResult EmptyImageTest::build (FboBuilder& builder)
{
	attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(),
					  0, 0, builder);
	return STOP;
}


class DistinctSizeTest : public TestBase
{
public:
					DistinctSizeTest	(Context& group,
										 const char* name, const char* desc)
						: TestBase		(group, name, desc) {}

	IterateResult	build				(FboBuilder& builder);
};

IterateResult DistinctSizeTest::build (FboBuilder& builder)
{
	attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(),
					  64, 64, builder);
	attachTargetToNew(GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, ImageFormat::none(),
					  128, 128, builder);
	return STOP;
}

TestCaseGroup* Context::createRenderableTests (void)
{
	TestCaseGroup* const renderableTests = new TestCaseGroup(
		m_testCtx, "renderable", "Tests for support of renderable image formats");

	TestCaseGroup* const rbRenderableTests = new TestCaseGroup(
		m_testCtx, "renderbuffer", "Tests for renderbuffer formats");

	TestCaseGroup* const texRenderableTests = new TestCaseGroup(
		m_testCtx, "texture", "Tests for texture formats");

	static const struct AttPoint {
		GLenum			attPoint;
		const char*		name;
		const char*		desc;
	} attPoints[] =
	{
		{ GL_COLOR_ATTACHMENT0,		"color0",	"Tests for color attachments"	},
		{ GL_STENCIL_ATTACHMENT,	"stencil",	"Tests for stencil attachments" },
		{ GL_DEPTH_ATTACHMENT,		"depth",	"Tests for depth attachments"	},
	};

	// At each attachment point, iterate through all the possible formats to
	// detect both false positives and false negatives.
	const Formats rboFmts = m_allFormats.getFormats(ANY_FORMAT);
	const Formats texFmts = m_allFormats.getFormats(ANY_FORMAT);

	for (const AttPoint* it = DE_ARRAY_BEGIN(attPoints); it != DE_ARRAY_END(attPoints); it++)
	{
		TestCaseGroup* const rbAttTests = new TestCaseGroup(m_testCtx, it->name, it->desc);
		TestCaseGroup* const texAttTests = new TestCaseGroup(m_testCtx, it->name, it->desc);

		for (Formats::const_iterator it2 = rboFmts.begin(); it2 != rboFmts.end(); it2++)
		{
			const RenderableParams params = { it->attPoint, GL_RENDERBUFFER, *it2 };
			rbAttTests->addChild(new RenderableTest(*this, params));
		}
		rbRenderableTests->addChild(rbAttTests);

		for (Formats::const_iterator it2 = texFmts.begin(); it2 != texFmts.end(); it2++)
		{
			const RenderableParams params = { it->attPoint, GL_TEXTURE, *it2 };
			texAttTests->addChild(new RenderableTest(*this, params));
		}
		texRenderableTests->addChild(texAttTests);
	}
	renderableTests->addChild(rbRenderableTests);
	renderableTests->addChild(texRenderableTests);

	return renderableTests;
}

TestCaseGroup* Context::createAttachmentTests (void)
{
	TestCaseGroup* const attCombTests = new TestCaseGroup(
		m_testCtx, "attachment_combinations", "Tests for attachment combinations");

	static const GLenum s_bufTypes[] = { GL_NONE, GL_RENDERBUFFER, GL_TEXTURE };
	static const Range<GLenum> s_kinds = GLS_ARRAY_RANGE(s_bufTypes);

	for (const GLenum* col0 = s_kinds.begin(); col0 != s_kinds.end(); ++col0)
		for (const GLenum* coln = s_kinds.begin(); coln != s_kinds.end(); ++coln)
			for (const GLenum* dep = s_kinds.begin(); dep != s_kinds.end(); ++dep)
				for (const GLenum* stc = s_kinds.begin(); stc != s_kinds.end(); ++stc)
				{
					AttachmentParams params = { *col0, *coln, *dep, *stc };
					attCombTests->addChild(new AttachmentTest(*this, params));
				}

	return attCombTests;
}

TestCaseGroup* Context::createSizeTests (void)
{
	TestCaseGroup* const sizeTests = new TestCaseGroup(
		m_testCtx, "size", "Tests for attachment sizes");
	sizeTests->addChild(new EmptyImageTest(
							*this, "zero",
							"Test for zero-sized image attachment"));
	sizeTests->addChild(new DistinctSizeTest(
							*this, "distinct",
							"Test for attachments with different sizes"));

	return sizeTests;
}

} // details

} // fboc
} // gls
} // deqp
