/*-------------------------------------------------------------------------
 * 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 Utilities for framebuffer objects.
 *//*--------------------------------------------------------------------*/

#include "glsFboUtil.hpp"

#include "glwEnums.hpp"
#include "deUniquePtr.hpp"
#include "gluTextureUtil.hpp"
#include "gluStrUtil.hpp"
#include "deStringUtil.hpp"
#include "deSTLUtil.hpp"
#include <sstream>

using namespace glw;
using tcu::TestLog;
using tcu::TextureFormat;
using tcu::NotSupportedError;
using glu::TransferFormat;
using glu::mapGLInternalFormat;
using glu::mapGLTransferFormat;
using glu::getPixelFormatName;
using glu::getTypeName;
using glu::getFramebufferTargetName;
using glu::getFramebufferAttachmentName;
using glu::getFramebufferAttachmentTypeName;
using glu::getTextureTargetName;
using glu::getTransferFormat;
using glu::ContextInfo;
using glu::ContextType;
using glu::RenderContext;
using de::UniquePtr;
using de::toString;
using std::set;
using std::vector;
using std::string;
using std::istringstream;
using std::istream_iterator;

namespace deqp
{
namespace gls
{

namespace FboUtil
{

#if defined(DE_DEBUG)
static bool isFramebufferStatus (glw::GLenum fboStatus)
{
	return glu::getFramebufferStatusName(fboStatus) != DE_NULL;
}

static bool isErrorCode (glw::GLenum errorCode)
{
	return glu::getErrorName(errorCode) != DE_NULL;
}
#endif

std::ostream& operator<< (std::ostream& stream, const ImageFormat& format)
{
	if (format.unsizedType == GL_NONE)
	{
		// sized format
		return stream << glu::getPixelFormatStr(format.format);
	}
	else
	{
		// unsized format
		return stream << "(format = " << glu::getPixelFormatStr(format.format) << ", type = " << glu::getTypeStr(format.unsizedType) << ")";
	}
}

void FormatDB::addCoreFormat (ImageFormat format, FormatFlags newFlags)
{
	FormatFlags& flags = m_formatFlags[format];
	flags = FormatFlags(flags | newFlags);
}

void FormatDB::addExtensionFormat (ImageFormat format, FormatFlags newFlags, const std::set<std::string>& requiredExtensions)
{
	DE_ASSERT(!requiredExtensions.empty());

	{
		FormatFlags& flags = m_formatFlags[format];
		flags = FormatFlags(flags | newFlags);
	}

	{
		std::set<ExtensionInfo>&	extensionInfo	= m_formatExtensions[format];
		ExtensionInfo				extensionRecord;

		extensionRecord.flags				= newFlags;
		extensionRecord.requiredExtensions	= requiredExtensions;

		DE_ASSERT(!de::contains(extensionInfo, extensionRecord)); // extensions specified only once
		extensionInfo.insert(extensionRecord);
	}
}

// Not too fast at the moment, might consider indexing?
Formats FormatDB::getFormats (FormatFlags requirements) const
{
	Formats ret;
	for (FormatMap::const_iterator it = m_formatFlags.begin(); it != m_formatFlags.end(); it++)
	{
		if ((it->second & requirements) == requirements)
			ret.insert(it->first);
	}
	return ret;
}

bool FormatDB::isKnownFormat (ImageFormat format) const
{
	return de::contains(m_formatFlags, format);
}

FormatFlags FormatDB::getFormatInfo (ImageFormat format) const
{
	DE_ASSERT(de::contains(m_formatFlags, format));
	return de::lookup(m_formatFlags, format);
}

std::set<std::set<std::string> > FormatDB::getFormatFeatureExtensions (ImageFormat format, FormatFlags requirements) const
{
	DE_ASSERT(de::contains(m_formatExtensions, format));

	const std::set<ExtensionInfo>&		extensionInfo	= de::lookup(m_formatExtensions, format);
	std::set<std::set<std::string> >	ret;

	for (std::set<ExtensionInfo>::const_iterator it = extensionInfo.begin(); it != extensionInfo.end(); ++it)
	{
		if ((it->flags & requirements) == requirements)
			ret.insert(it->requiredExtensions);
	}

	return ret;
}

bool FormatDB::ExtensionInfo::operator< (const ExtensionInfo& other) const
{
	return (requiredExtensions < other.requiredExtensions) ||
		   ((requiredExtensions == other.requiredExtensions) && (flags < other.flags));
}

static bool detectGLESCompatibleContext (const RenderContext& ctx, int requiredMajor, int requiredMinor)
{
	const glw::Functions&	gl				= ctx.getFunctions();
	glw::GLint				majorVersion	= 0;
	glw::GLint				minorVersion	= 0;

	// Detect compatible GLES context by querying GL_MAJOR_VERSION.
	// This query does not exist on GLES2 so a failing query implies
	// GLES2 context.

	gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
	if (gl.getError() != GL_NO_ERROR)
		majorVersion = 2;

	gl.getIntegerv(GL_MINOR_VERSION, &minorVersion);
	if (gl.getError() != GL_NO_ERROR)
		minorVersion = 0;

	return (majorVersion > requiredMajor) || (majorVersion == requiredMajor && minorVersion >= requiredMinor);
}

static bool checkExtensionSupport (const ContextInfo& ctxInfo, const RenderContext& ctx, const std::string& extension)
{
	if (de::beginsWith(extension, "GL_"))
		return ctxInfo.isExtensionSupported(extension.c_str());
	else if (extension == "DEQP_gles3_core_compatible")
		return detectGLESCompatibleContext(ctx, 3, 0);
	else if (extension == "DEQP_gles31_core_compatible")
		return detectGLESCompatibleContext(ctx, 3, 1);
	else
	{
		DE_ASSERT(false);
		return false;
	}
}

bool checkExtensionSupport (const RenderContext& ctx, const std::string& extension)
{
	const de::UniquePtr<ContextInfo> info(ContextInfo::create(ctx));
	return checkExtensionSupport(*info, ctx, extension);
}

std::string getExtensionDescription (const std::string& extension)
{
	if (de::beginsWith(extension, "GL_"))
		return extension;
	else if (extension == "DEQP_gles3_core_compatible")
		return "GLES3 compatible context";
	else if (extension == "DEQP_gles31_core_compatible")
		return "GLES3.1 compatible context";
	else
	{
		DE_ASSERT(false);
		return "";
	}
}

void addFormats (FormatDB& db, FormatEntries stdFmts)
{
	for (const FormatEntry* it = stdFmts.begin(); it != stdFmts.end(); it++)
	{
		for (const FormatKey* it2 = it->second.begin(); it2 != it->second.end(); it2++)
			db.addCoreFormat(formatKeyInfo(*it2), it->first);
	}
}

void addExtFormats (FormatDB& db, FormatExtEntries extFmts, const RenderContext* ctx)
{
	const UniquePtr<ContextInfo> ctxInfo(ctx != DE_NULL ? ContextInfo::create(*ctx) : DE_NULL);
	for (const FormatExtEntry* entryIt = extFmts.begin(); entryIt != extFmts.end(); entryIt++)
	{
		bool					supported			= true;
		std::set<std::string>	requiredExtensions;

		// parse required extensions
		{
			istringstream tokenStream(string(entryIt->extensions));
			istream_iterator<string> tokens((tokenStream)), end;

			while (tokens != end)
			{
				requiredExtensions.insert(*tokens);
				++tokens;
			}
		}

		// check support
		if (ctxInfo)
		{
			for (std::set<std::string>::const_iterator extIt = requiredExtensions.begin(); extIt != requiredExtensions.end(); ++extIt)
			{
				if (!checkExtensionSupport(*ctxInfo, *ctx, *extIt))
				{
					supported = false;
					break;
				}
			}
		}

		if (supported)
			for (const FormatKey* i2 = entryIt->formats.begin(); i2 != entryIt->formats.end(); i2++)
				db.addExtensionFormat(formatKeyInfo(*i2), FormatFlags(entryIt->flags), requiredExtensions);
	}
}

FormatFlags formatFlag (GLenum context)
{
	switch (context)
	{
		case GL_NONE:
			return FormatFlags(0);
		case GL_RENDERBUFFER:
			return RENDERBUFFER_VALID;
		case GL_TEXTURE:
			return TEXTURE_VALID;
		case GL_STENCIL_ATTACHMENT:
			return STENCIL_RENDERABLE;
		case GL_DEPTH_ATTACHMENT:
			return DEPTH_RENDERABLE;
		default:
			DE_ASSERT(context >= GL_COLOR_ATTACHMENT0 && context <= GL_COLOR_ATTACHMENT15);
			return COLOR_RENDERABLE;
	}
}

static FormatFlags getAttachmentRenderabilityFlag (GLenum attachment)
{
	switch (attachment)
	{
		case GL_STENCIL_ATTACHMENT:			return STENCIL_RENDERABLE;
		case GL_DEPTH_ATTACHMENT:			return DEPTH_RENDERABLE;

		default:
			DE_ASSERT(attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15);
			return COLOR_RENDERABLE;
	}
}

namespace config {

GLsizei	imageNumSamples	(const Image& img)
{
	if (const Renderbuffer* rbo = dynamic_cast<const Renderbuffer*>(&img))
		return rbo->numSamples;
	return 0;
}

static GLenum glTarget (const Image& img)
{
	if (dynamic_cast<const Renderbuffer*>(&img) != DE_NULL)
		return GL_RENDERBUFFER;
	if (dynamic_cast<const Texture2D*>(&img) != DE_NULL)
		return GL_TEXTURE_2D;
	if (dynamic_cast<const TextureCubeMap*>(&img) != DE_NULL)
		return GL_TEXTURE_CUBE_MAP;
	if (dynamic_cast<const Texture3D*>(&img) != DE_NULL)
		return GL_TEXTURE_3D;
	if (dynamic_cast<const Texture2DArray*>(&img) != DE_NULL)
		return GL_TEXTURE_2D_ARRAY;

	DE_ASSERT(!"Impossible image type");
	return GL_NONE;
}

static void glInitFlat (const TextureFlat& cfg, GLenum target, const glw::Functions& gl)
{
	const TransferFormat format = transferImageFormat(cfg.internalFormat);
	GLint w = cfg.width;
	GLint h = cfg.height;
	for (GLint level = 0; level < cfg.numLevels; level++)
	{
		gl.texImage2D(target, level, cfg.internalFormat.format, w, h, 0,
					  format.format, format.dataType, DE_NULL);
		w = de::max(1, w / 2);
		h = de::max(1, h / 2);
	}
}

static void glInitLayered (const TextureLayered& cfg,
						   GLint depth_divider, const glw::Functions& gl)
{
	const TransferFormat format = transferImageFormat(cfg.internalFormat);
	GLint w = cfg.width;
	GLint h = cfg.height;
	GLint depth = cfg.numLayers;
	for (GLint level = 0; level < cfg.numLevels; level++)
	{
		gl.texImage3D(glTarget(cfg), level, cfg.internalFormat.format, w, h, depth, 0,
					  format.format, format.dataType, DE_NULL);
		w = de::max(1, w / 2);
		h = de::max(1, h / 2);
		depth = de::max(1, depth / depth_divider);
	}
}

static void glInit (const Texture& cfg, const glw::Functions& gl)
{
	if (const Texture2D* t2d = dynamic_cast<const Texture2D*>(&cfg))
		glInitFlat(*t2d, glTarget(*t2d), gl);
	else if (const TextureCubeMap* tcm = dynamic_cast<const TextureCubeMap*>(&cfg))
	{
		// \todo [2013-12-05 lauri]
		// move this to glu or someplace sensible (this array is already
		// present in duplicates)
		static const GLenum s_cubeMapFaces[] =
			{
				GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
				GL_TEXTURE_CUBE_MAP_POSITIVE_X,
				GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
				GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
				GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
				GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
			};
		const Range<GLenum> range = GLS_ARRAY_RANGE(s_cubeMapFaces);
		for (const GLenum* it = range.begin(); it != range.end(); it++)
			glInitFlat(*tcm, *it, gl);
	}
	else if (const Texture3D* t3d = dynamic_cast<const Texture3D*>(&cfg))
		glInitLayered(*t3d, 2, gl);
	else if (const Texture2DArray* t2a = dynamic_cast<const Texture2DArray*>(&cfg))
		glInitLayered(*t2a, 1, gl);
}

static GLuint glCreate (const Image& cfg, const glw::Functions& gl)
{
	GLuint ret = 0;
	if (const Renderbuffer* const rbo = dynamic_cast<const Renderbuffer*>(&cfg))
	{
		gl.genRenderbuffers(1, &ret);
		gl.bindRenderbuffer(GL_RENDERBUFFER, ret);

		if (rbo->numSamples == 0)
			gl.renderbufferStorage(GL_RENDERBUFFER, rbo->internalFormat.format,
								   rbo->width, rbo->height);
		else
			gl.renderbufferStorageMultisample(
				GL_RENDERBUFFER, rbo->numSamples, rbo->internalFormat.format,
				rbo->width, rbo->height);

		gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
	}
	else if (const Texture* const tex = dynamic_cast<const Texture*>(&cfg))
	{
		gl.genTextures(1, &ret);
		gl.bindTexture(glTarget(*tex), ret);
		glInit(*tex, gl);
		gl.bindTexture(glTarget(*tex), 0);
	}
	else
		DE_ASSERT(!"Impossible image type");
	return ret;
}

static void glDelete (const Image& cfg, GLuint img, const glw::Functions& gl)
{
	if (dynamic_cast<const Renderbuffer*>(&cfg) != DE_NULL)
		gl.deleteRenderbuffers(1, &img);
	else if (dynamic_cast<const Texture*>(&cfg) != DE_NULL)
		gl.deleteTextures(1, &img);
	else
		DE_ASSERT(!"Impossible image type");
}

static void attachAttachment (const Attachment& att, GLenum attPoint,
							  const glw::Functions& gl)
{
	if (const RenderbufferAttachment* const rAtt =
		dynamic_cast<const RenderbufferAttachment*>(&att))
		gl.framebufferRenderbuffer(rAtt->target, attPoint,
								   rAtt->renderbufferTarget, rAtt->imageName);
	else if (const TextureFlatAttachment* const fAtt =
			 dynamic_cast<const TextureFlatAttachment*>(&att))
		gl.framebufferTexture2D(fAtt->target, attPoint,
								fAtt->texTarget, fAtt->imageName, fAtt->level);
	else if (const TextureLayerAttachment* const lAtt =
			 dynamic_cast<const TextureLayerAttachment*>(&att))
		gl.framebufferTextureLayer(lAtt->target, attPoint,
								   lAtt->imageName, lAtt->level, lAtt->layer);
	else
		DE_ASSERT(!"Impossible attachment type");
}

GLenum attachmentType (const Attachment& att)
{
	if (dynamic_cast<const RenderbufferAttachment*>(&att) != DE_NULL)
		return GL_RENDERBUFFER;
	else if (dynamic_cast<const TextureAttachment*>(&att) != DE_NULL)
		return GL_TEXTURE;

	DE_ASSERT(!"Impossible attachment type");
	return GL_NONE;
}

static GLsizei textureLayer (const TextureAttachment& tAtt)
{
	if (dynamic_cast<const TextureFlatAttachment*>(&tAtt) != DE_NULL)
		return 0;
	else if (const TextureLayerAttachment* const lAtt =
			 dynamic_cast<const TextureLayerAttachment*>(&tAtt))
		return lAtt->layer;

	DE_ASSERT(!"Impossible attachment type");
	return 0;
}

static void checkAttachmentCompleteness (Checker& cctx, const Attachment& attachment,
										 GLenum attPoint, const Image* image,
										 const FormatDB& db)
{
	// GLES2 4.4.5 / GLES3 4.4.4, "Framebuffer attachment completeness"

	if (const TextureAttachment* const texAtt =
		dynamic_cast<const TextureAttachment*>(&attachment))
		if (const TextureLayered* const ltex = dynamic_cast<const TextureLayered*>(image))
		{
			// GLES3: "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is
			// TEXTURE and the value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names a
			// three-dimensional texture, then the value of
			// FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER must be smaller than the depth
			// of the texture.
			//
			// GLES3: "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is
			// TEXTURE and the value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names a
			// two-dimensional array texture, then the value of
			// FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER must be smaller than the
			// number of layers in the texture.

			if (textureLayer(*texAtt) >= ltex->numLayers)
				cctx.addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, "Attached layer index is larger than present");
		}

	// "The width and height of image are non-zero."
	if (image->width == 0 || image->height == 0)
		cctx.addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, "Width and height of an image are not non-zero");

	// Check for renderability
	if (db.isKnownFormat(image->internalFormat))
	{
		const FormatFlags flags = db.getFormatInfo(image->internalFormat);

		// If the format does not have the proper renderability flag, the
		// completeness check _must_ fail.
		if ((flags & getAttachmentRenderabilityFlag(attPoint)) == 0)
			cctx.addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, "Attachment format is not renderable in this attachment");
		// If the format is only optionally renderable, the completeness check _can_ fail.
		else if ((flags & REQUIRED_RENDERABLE) == 0)
			cctx.addPotentialFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, "Attachment format is not required renderable");
	}
	else
		cctx.addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, "Attachment format is not legal");
}

} // namespace config

using namespace config;

Checker::Checker (const glu::RenderContext& ctx)
	: m_renderCtx(ctx)
{
	m_statusCodes.setAllowComplete(true);
}

void Checker::addGLError (glw::GLenum error, const char* description)
{
	m_statusCodes.addErrorCode(error, description);
	m_statusCodes.setAllowComplete(false);
}

void Checker::addPotentialGLError (glw::GLenum error, const char* description)
{
	m_statusCodes.addErrorCode(error, description);
}

void Checker::addFBOStatus (GLenum status, const char* description)
{
	m_statusCodes.addFBOErrorStatus(status, description);
	m_statusCodes.setAllowComplete(false);
}

void Checker::addPotentialFBOStatus (GLenum status, const char* description)
{
	m_statusCodes.addFBOErrorStatus(status, description);
}

FboVerifier::FboVerifier (const FormatDB& formats, CheckerFactory& factory, const glu::RenderContext& renderCtx)
	: m_formats		(formats)
	, m_factory		(factory)
	, m_renderCtx	(renderCtx)
{
}

/*--------------------------------------------------------------------*//*!
 * \brief Return acceptable framebuffer status codes.
 *
 * This function examines the framebuffer configuration descriptor `fboConfig`
 * and returns the set of status codes that `glCheckFramebufferStatus` is
 * allowed to return on a conforming implementation when given a framebuffer
 * whose configuration adheres to `fboConfig`.
 *
 * The returned set is guaranteed to be non-empty, but it may contain multiple
 * INCOMPLETE statuses (if there are multiple errors in the spec), or or a mix
 * of COMPLETE and INCOMPLETE statuses (if supporting a FBO with this spec is
 * optional). Furthermore, the statuses may contain GL error codes, which
 * indicate that trying to create a framebuffer configuration like this could
 * have failed with an error (if one was checked for) even before
 * `glCheckFramebufferStatus` was ever called.
 *
 *//*--------------------------------------------------------------------*/
ValidStatusCodes FboVerifier::validStatusCodes (const Framebuffer& fboConfig) const
{
	const AttachmentMap& atts = fboConfig.attachments;
	const UniquePtr<Checker> cctx(m_factory.createChecker(m_renderCtx));

	for (TextureMap::const_iterator it = fboConfig.textures.begin();
		 it != fboConfig.textures.end(); it++)
	{
		std::string errorDescription;

		if (m_formats.isKnownFormat(it->second->internalFormat))
		{
			const FormatFlags flags = m_formats.getFormatInfo(it->second->internalFormat);

			if ((flags & TEXTURE_VALID) == 0)
				errorDescription = "Format " + de::toString(it->second->internalFormat) + " is not a valid format for a texture";
		}
		else if (it->second->internalFormat.unsizedType == GL_NONE)
		{
			// sized format
			errorDescription = "Format " + de::toString(it->second->internalFormat) + " does not exist";
		}
		else
		{
			// unsized type-format pair
			errorDescription = "Format " + de::toString(it->second->internalFormat) + " is not a legal format";
		}

		if (!errorDescription.empty())
		{
			cctx->addGLError(GL_INVALID_ENUM,		errorDescription.c_str());
			cctx->addGLError(GL_INVALID_OPERATION,	errorDescription.c_str());
			cctx->addGLError(GL_INVALID_VALUE,		errorDescription.c_str());
		}
	}

	for (RboMap::const_iterator it = fboConfig.rbos.begin(); it != fboConfig.rbos.end(); it++)
	{
		if (m_formats.isKnownFormat(it->second->internalFormat))
		{
			const FormatFlags flags = m_formats.getFormatInfo(it->second->internalFormat);
			if ((flags & RENDERBUFFER_VALID) == 0)
			{
				const std::string reason = "Format " + de::toString(it->second->internalFormat) + " is not a valid format for a renderbuffer";
				cctx->addGLError(GL_INVALID_ENUM, reason.c_str());
			}
		}
		else
		{
			const std::string reason = "Internal format " + de::toString(it->second->internalFormat) + " does not exist";
			cctx->addGLError(GL_INVALID_ENUM, reason.c_str());
		}
	}

	// "There is at least one image attached to the framebuffer."
	// \todo support XXX_framebuffer_no_attachments
	if (atts.empty())
		cctx->addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT, "No images attached to the framebuffer");

	for (AttachmentMap::const_iterator it = atts.begin(); it != atts.end(); it++)
	{
		const GLenum attPoint = it->first;
		const Attachment& att = *it->second;
		const Image* const image = fboConfig.getImage(attachmentType(att), att.imageName);

		checkAttachmentCompleteness(*cctx, att, attPoint, image, m_formats);
		cctx->check(it->first, *it->second, image);
	}

	return cctx->getStatusCodes();
}


void Framebuffer::attach (glw::GLenum attPoint, const Attachment* att)
{
	if (att == DE_NULL)
		attachments.erase(attPoint);
	else
		attachments[attPoint] = att;
}

const Image* Framebuffer::getImage (GLenum type, glw::GLuint imgName) const
{
	switch (type)
	{
		case GL_TEXTURE:
			return de::lookupDefault(textures, imgName, DE_NULL);
		case GL_RENDERBUFFER:
			return de::lookupDefault(rbos, imgName, DE_NULL);
		default:
			DE_ASSERT(!"Bad image type");
	}
	return DE_NULL; // shut up compiler warning
}

void Framebuffer::setTexture (glw::GLuint texName, const Texture& texCfg)
{
	textures[texName] = &texCfg;
}

void Framebuffer::setRbo (glw::GLuint rbName, const Renderbuffer& rbCfg)
{
	rbos[rbName] = &rbCfg;
}

static void logField (TestLog& log, const string& field, const string& value)
{
	log << TestLog::Message << field << ": " << value << TestLog::EndMessage;
}

static void logImage (const Image& img, TestLog& log, bool useType)
{
	const GLenum type = img.internalFormat.unsizedType;
	logField(log, "Internal format",	getPixelFormatName(img.internalFormat.format));
	if (useType && type != GL_NONE)
		logField(log, "Format type",	getTypeName(type));
	logField(log, "Width",				toString(img.width));
	logField(log, "Height",				toString(img.height));
}

static void logRenderbuffer (const Renderbuffer& rbo, TestLog& log)
{
	logImage(rbo, log, false);
	logField(log, "Samples",			toString(rbo.numSamples));
}

static void logTexture (const Texture& tex, TestLog& log)
{
	logField(log, "Type",				glu::getTextureTargetName(glTarget(tex)));
	logImage(tex, log, true);
	logField(log, "Levels",				toString(tex.numLevels));
	if (const TextureLayered* const lTex = dynamic_cast<const TextureLayered*>(&tex))
		logField(log, "Layers",				toString(lTex->numLayers));
}

static void logAttachment (const Attachment& att, TestLog& log)
{
	logField(log, "Target",				getFramebufferTargetName(att.target));
	logField(log, "Type",				getFramebufferAttachmentTypeName(attachmentType(att)));
	logField(log, "Image Name",			toString(att.imageName));
	if (const RenderbufferAttachment* const rAtt
		= dynamic_cast<const RenderbufferAttachment*>(&att))
	{
		DE_UNREF(rAtt); // To shut up compiler during optimized builds.
		DE_ASSERT(rAtt->renderbufferTarget == GL_RENDERBUFFER);
		logField(log, "Renderbuffer Target",	"GL_RENDERBUFFER");
	}
	else if (const TextureAttachment* const tAtt = dynamic_cast<const TextureAttachment*>(&att))
	{
		logField(log, "Mipmap Level",		toString(tAtt->level));
		if (const TextureFlatAttachment* const fAtt =
			dynamic_cast<const TextureFlatAttachment*>(tAtt))
			logField(log, "Texture Target",		getTextureTargetName(fAtt->texTarget));
		else if (const TextureLayerAttachment* const lAtt =
			dynamic_cast<const TextureLayerAttachment*>(tAtt))
			logField(log, "Layer",				toString(lAtt->level));
	}
}

void logFramebufferConfig (const Framebuffer& cfg, TestLog& log)
{
	log << TestLog::Section("Framebuffer", "Framebuffer configuration");

	for (RboMap::const_iterator it = cfg.rbos.begin(); it != cfg.rbos.end(); ++it)
	{
		const string				num			= toString(it->first);
		const tcu::ScopedLogSection	subsection	(log, num, "Renderbuffer " + num);

		logRenderbuffer(*it->second, log);
	}

	for (TextureMap::const_iterator it = cfg.textures.begin();
		it != cfg.textures.end(); ++it)
	{
		const string				num			= toString(it->first);
		const tcu::ScopedLogSection	subsection	(log, num, "Texture " + num);

		logTexture(*it->second, log);
	}

	const string attDesc = cfg.attachments.empty()
		? "Framebuffer has no attachments"
		: "Framebuffer attachments";
	log << TestLog::Section("Attachments", attDesc);
	for (AttachmentMap::const_iterator it = cfg.attachments.begin();
		 it != cfg.attachments.end(); it++)
	{
		const string attPointName = getFramebufferAttachmentName(it->first);
		log << TestLog::Section(attPointName, "Attachment point " + attPointName);
		logAttachment(*it->second, log);
		log << TestLog::EndSection;
	}
	log << TestLog::EndSection; // Attachments

	log << TestLog::EndSection; // Framebuffer
}

ValidStatusCodes::ValidStatusCodes (void)
	: m_allowComplete(false)
{
}

bool ValidStatusCodes::isFBOStatusValid (glw::GLenum fboStatus) const
{
	if (fboStatus == GL_FRAMEBUFFER_COMPLETE)
		return m_allowComplete;
	else
	{
		// rule violation exists?
		for (int ndx = 0; ndx < (int)m_errorStatuses.size(); ++ndx)
		{
			if (m_errorStatuses[ndx].errorCode == fboStatus)
				return true;
		}
		return false;
	}
}

bool ValidStatusCodes::isFBOStatusRequired (glw::GLenum fboStatus) const
{
	if (fboStatus == GL_FRAMEBUFFER_COMPLETE)
		return m_allowComplete && m_errorStatuses.empty();
	else
		// fboStatus is the only allowed error status and succeeding is forbidden
		return !m_allowComplete && m_errorStatuses.size() == 1 && m_errorStatuses.front().errorCode == fboStatus;
}

bool ValidStatusCodes::isErrorCodeValid (glw::GLenum errorCode) const
{
	if (errorCode == GL_NO_ERROR)
		return m_errorCodes.empty();
	else
	{
		// rule violation exists?
		for (int ndx = 0; ndx < (int)m_errorCodes.size(); ++ndx)
		{
			if (m_errorCodes[ndx].errorCode == errorCode)
				return true;
		}
		return false;
	}
}

bool ValidStatusCodes::isErrorCodeRequired (glw::GLenum errorCode) const
{
	if (m_errorCodes.empty() && errorCode == GL_NO_ERROR)
		return true;
	else
		// only this error code listed
		return m_errorCodes.size() == 1 && m_errorCodes.front().errorCode == errorCode;
}

void ValidStatusCodes::addErrorCode (glw::GLenum error, const char* description)
{
	DE_ASSERT(isErrorCode(error));
	DE_ASSERT(error != GL_NO_ERROR);
	addViolation(m_errorCodes, error, description);
}

void ValidStatusCodes::addFBOErrorStatus (glw::GLenum status, const char* description)
{
	DE_ASSERT(isFramebufferStatus(status));
	DE_ASSERT(status != GL_FRAMEBUFFER_COMPLETE);
	addViolation(m_errorStatuses, status, description);
}

void ValidStatusCodes::setAllowComplete (bool b)
{
	m_allowComplete = b;
}

void ValidStatusCodes::logLegalResults (tcu::TestLog& log) const
{
	tcu::MessageBuilder			msg				(&log);
	std::vector<std::string>	validResults;

	for (int ndx = 0; ndx < (int)m_errorCodes.size(); ++ndx)
		validResults.push_back(std::string(glu::getErrorName(m_errorCodes[ndx].errorCode)) + " (during FBO initialization)");

	for (int ndx = 0; ndx < (int)m_errorStatuses.size(); ++ndx)
		validResults.push_back(glu::getFramebufferStatusName(m_errorStatuses[ndx].errorCode));

	if (m_allowComplete)
		validResults.push_back("GL_FRAMEBUFFER_COMPLETE");

	msg << "Expected ";
	if (validResults.size() > 1)
		msg << "one of ";

	for (int ndx = 0; ndx < (int)validResults.size(); ++ndx)
	{
		const bool last			= ((ndx + 1) == (int)validResults.size());
		const bool secondToLast	= ((ndx + 2) == (int)validResults.size());

		msg << validResults[ndx];
		if (!last)
			msg << ((secondToLast) ? (" or ") : (", "));
	}

	msg << "." << TestLog::EndMessage;
}

void ValidStatusCodes::logRules (tcu::TestLog& log) const
{
	const tcu::ScopedLogSection section(log, "Rules", "Active rules");

	for (int ndx = 0; ndx < (int)m_errorCodes.size(); ++ndx)
		logRule(log, glu::getErrorName(m_errorCodes[ndx].errorCode), m_errorCodes[ndx].rules);

	for (int ndx = 0; ndx < (int)m_errorStatuses.size(); ++ndx)
		logRule(log, glu::getFramebufferStatusName(m_errorStatuses[ndx].errorCode), m_errorStatuses[ndx].rules);

	if (m_allowComplete)
	{
		std::set<std::string> defaultRule;
		defaultRule.insert("FBO is complete");
		logRule(log, "GL_FRAMEBUFFER_COMPLETE", defaultRule);
	}
}

void ValidStatusCodes::logRule (tcu::TestLog& log, const std::string& ruleName, const std::set<std::string>& rules) const
{
	if (!rules.empty())
	{
		const tcu::ScopedLogSection		section	(log, ruleName, ruleName);
		tcu::MessageBuilder				msg		(&log);

		msg << "Rules:\n";
		for (std::set<std::string>::const_iterator it = rules.begin(); it != rules.end(); ++it)
			msg << "\t * " << *it << "\n";
		msg << TestLog::EndMessage;
	}
}

void ValidStatusCodes::addViolation (std::vector<RuleViolation>& dst, glw::GLenum code, const char* description) const
{
	// rule violation already exists?
	for (int ndx = 0; ndx < (int)dst.size(); ++ndx)
	{
		if (dst[ndx].errorCode == code)
		{
			dst[ndx].rules.insert(std::string(description));
			return;
		}
	}

	// new violation
	{
		RuleViolation violation;

		violation.errorCode = code;
		violation.rules.insert(std::string(description));

		dst.push_back(violation);
	}
}

FboBuilder::FboBuilder (GLuint fbo, GLenum target, const glw::Functions& gl)
	: m_error	(GL_NO_ERROR)
	, m_target	(target)
	, m_gl		(gl)
{
	m_gl.bindFramebuffer(m_target, fbo);
}

FboBuilder::~FboBuilder (void)
{
	for (TextureMap::const_iterator it = textures.begin(); it != textures.end(); it++)
	{
		glDelete(*it->second, it->first, m_gl);
	}
	for (RboMap::const_iterator it = rbos.begin(); it != rbos.end(); it++)
	{
		glDelete(*it->second, it->first, m_gl);
	}
	m_gl.bindFramebuffer(m_target, 0);
	for (Configs::const_iterator it = m_configs.begin(); it != m_configs.end(); it++)
	{
		delete *it;
	}
}

void FboBuilder::checkError (void)
{
	const GLenum error = m_gl.getError();
	if (error != GL_NO_ERROR && m_error == GL_NO_ERROR)
		m_error = error;
}

void FboBuilder::glAttach (GLenum attPoint, const Attachment* att)
{
	if (att == NULL)
		m_gl.framebufferRenderbuffer(m_target, attPoint, GL_RENDERBUFFER, 0);
	else
		attachAttachment(*att, attPoint, m_gl);
	checkError();
	attach(attPoint, att);
}

GLuint FboBuilder::glCreateTexture (const Texture& texCfg)
{
	const GLuint texName = glCreate(texCfg, m_gl);
	checkError();
	setTexture(texName, texCfg);
	return texName;
}

GLuint FboBuilder::glCreateRbo (const Renderbuffer& rbCfg)
{
	const GLuint rbName = glCreate(rbCfg, m_gl);
	checkError();
	setRbo(rbName, rbCfg);
	return rbName;
}

TransferFormat transferImageFormat (const ImageFormat& imgFormat)
{
	if (imgFormat.unsizedType == GL_NONE)
		return getTransferFormat(mapGLInternalFormat(imgFormat.format));
	else
		return TransferFormat(imgFormat.format, imgFormat.unsizedType);
}

} // FboUtil
} // gls
} // deqp
