/*-------------------------------------------------------------------------
 * 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 | TEXTURE_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
