/*-------------------------------------------------------------------------
 * 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 "es3fFboCompletenessTests.hpp"

#include "glsFboCompletenessTests.hpp"
#include <sstream>

using namespace glw;
using deqp::gls::Range;
using namespace deqp::gls::FboUtil;
using namespace deqp::gls::FboUtil::config;
namespace fboc = deqp::gls::fboc;
typedef tcu::TestCase::IterateResult IterateResult;
using std::string;
using std::ostringstream;

namespace deqp
{
namespace gles3
{
namespace Functional
{

static const FormatKey s_es3ColorRenderables[] =
{
	// GLES3, 4.4.4: "An internal format is color-renderable if it is one of
	// the formats from table 3.12 noted as color-renderable..."
	GL_R8, GL_RG8, GL_RGB8, GL_RGB565, GL_RGBA4, GL_RGB5_A1, GL_RGBA8,
	GL_RGB10_A2, GL_RGB10_A2UI, GL_SRGB8_ALPHA8,
	GL_R8I, GL_R8UI, GL_R16I, GL_R16UI, GL_R32I, GL_R32UI,
	GL_RG8I, GL_RG8UI, GL_RG16I, GL_RG16UI, GL_RG32I, GL_RG32UI,
	GL_RGBA8I, GL_RGBA8UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI,
};

static const FormatKey s_es3UnsizedColorRenderables[] =
{
	// "...or if it is unsized format RGBA or RGB."
	// See Table 3.3 in GLES3.
	GLS_UNSIZED_FORMATKEY(GL_RGBA,	GL_UNSIGNED_BYTE),
	GLS_UNSIZED_FORMATKEY(GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4),
	GLS_UNSIZED_FORMATKEY(GL_RGBA,	GL_UNSIGNED_SHORT_5_5_5_1),
	GLS_UNSIZED_FORMATKEY(GL_RGB,	GL_UNSIGNED_BYTE),
	GLS_UNSIZED_FORMATKEY(GL_RGB,	GL_UNSIGNED_SHORT_5_6_5),
};

static const FormatKey s_es3DepthRenderables[] =
{
	// GLES3, 4.4.4: "An internal format is depth-renderable if it is one of
	// the formats from table 3.13."
	GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32F,
	GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8,
};

static const FormatKey s_es3StencilRboRenderables[] =
{
	// GLES3, 4.4.4: "An internal format is stencil-renderable if it is
	// STENCIL_INDEX8..."
	GL_STENCIL_INDEX8,
};

static const FormatKey s_es3StencilRenderables[] =
{
	// "...or one of the formats from table 3.13 whose base internal format is
	// DEPTH_STENCIL."
	GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8,
};

static const FormatKey s_es3TextureFloatFormats[] =
{
	GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F,
	GL_RG32F, GL_RG16F, GL_R32F, GL_R16F,
	GL_RGBA16F, GL_RGB16F, GL_RG16F, GL_R16F,
};

static const FormatKey s_es3NotRenderableTextureFormats[] =
{
	GL_R8_SNORM, GL_RG8_SNORM, GL_RGB8_SNORM, GL_RGBA8_SNORM,
	GL_RGB9_E5, GL_SRGB8,
	GL_RGB8I, GL_RGB16I, GL_RGB32I,
	GL_RGB8UI, GL_RGB16UI,GL_RGB32UI,
};

static const FormatEntry s_es3Formats[] =
{
	// Renderbuffers don't support unsized formats
	{ REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID,
	  GLS_ARRAY_RANGE(s_es3UnsizedColorRenderables) },
	{ REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID,
	  GLS_ARRAY_RANGE(s_es3ColorRenderables) },
	{ REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID,
	  GLS_ARRAY_RANGE(s_es3DepthRenderables) },
	{ REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID,
	  GLS_ARRAY_RANGE(s_es3StencilRboRenderables) },
	{ REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID,
	  GLS_ARRAY_RANGE(s_es3StencilRenderables) },
	{ TEXTURE_VALID,
	  GLS_ARRAY_RANGE(s_es3NotRenderableTextureFormats) },

	// These are not color-renderable in vanilla ES3, but we need to mark them
	// as valid for textures, since EXT_color_buffer_(half_)float brings in
	// color-renderability and only renderbuffer-validity.
	{ TEXTURE_VALID,
	  GLS_ARRAY_RANGE(s_es3TextureFloatFormats) },
};

// GL_EXT_color_buffer_float
static const FormatKey s_extColorBufferFloatFormats[] =
{
	GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F, GL_RG32F, GL_RG16F, GL_R32F, GL_R16F,
};

// GL_OES_texture_stencil8
static const FormatKey s_extOESTextureStencil8[] =
{
	GL_STENCIL_INDEX8,
};

// GL_EXT_render_snorm
static const FormatKey s_extRenderSnorm[] =
{
	GL_R8_SNORM, GL_RG8_SNORM, GL_RGBA8_SNORM,
};

static const FormatExtEntry s_es3ExtFormats[] =
{
	{
		"GL_EXT_color_buffer_float",
		// These are already texture-valid in ES3, the extension just adds RBO
		// support and makes them color-renderable.
		REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID,
		GLS_ARRAY_RANGE(s_extColorBufferFloatFormats)
	},
	{
		"GL_OES_texture_stencil8",
		// \note: es3 RBO tests actually cover the first two requirements
		// - kept here for completeness
		REQUIRED_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID,
		GLS_ARRAY_RANGE(s_extOESTextureStencil8)
	},

	// Since GLES31 is backwards compatible to GLES3, we might actually be running on a GLES31.
	// Add rule changes of GLES31 that have no corresponding GLES3 extension.
	//
	// \note Not all feature changes are listed here but only those that alter GLES3 subset of
	//       the formats
	{
		"DEQP_gles31_core_compatible GL_EXT_render_snorm",
		REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID | RENDERBUFFER_VALID,
		GLS_ARRAY_RANGE(s_extRenderSnorm)
	},
};

class ES3Checker : public Checker
{
public:
				ES3Checker	(const glu::RenderContext& ctx)
					: Checker				(ctx)
					, m_numSamples			(-1)
					, m_depthStencilImage	(0)
					, m_depthStencilType	(GL_NONE) {}
	void		check 		(GLenum attPoint, const Attachment& att, const Image* image);

private:
	//! The common number of samples of images.
	GLsizei		m_numSamples;

	//! The common image for depth and stencil attachments.
	GLuint		m_depthStencilImage;
	GLenum		m_depthStencilType;
};

void ES3Checker::check (GLenum attPoint, const Attachment& att, const Image* image)
{
	GLsizei imgSamples = imageNumSamples(*image);

	if (m_numSamples == -1)
	{
		m_numSamples = imgSamples;
	}
	else
	{
		// GLES3: "The value of RENDERBUFFER_SAMPLES is the same for all attached
		// renderbuffers and, if the attached images are a mix of renderbuffers
		// and textures, the value of RENDERBUFFER_SAMPLES is zero."
		//
		// On creating a renderbuffer: "If _samples_ is zero, then
		// RENDERBUFFER_SAMPLES is set to zero. Otherwise [...] the resulting
		// value for RENDERBUFFER_SAMPLES is guaranteed to be greater than or
		// equal to _samples_ and no more than the next larger sample count
		// supported by the implementation."

		// Either all attachments are zero-sample renderbuffers and/or
		// textures, or none of them are.
		if ((m_numSamples == 0) != (imgSamples == 0))
			addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Mixed multi- and single-sampled attachments");

		// If the attachments requested a different number of samples, the
		// implementation is allowed to report this as incomplete. However, it
		// is also possible that despite the different requests, the
		// implementation allocated the same number of samples to both. Hence
		// reporting the framebuffer as complete is also legal.
		if (m_numSamples != imgSamples)
			addPotentialFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Number of samples differ");
	}

	// "Depth and stencil attachments, if present, are the same image."
	if (attPoint == GL_DEPTH_ATTACHMENT || attPoint == GL_STENCIL_ATTACHMENT)
	{
		if (m_depthStencilImage == 0)
		{
			m_depthStencilImage = att.imageName;
			m_depthStencilType = attachmentType(att);
		}
		else
		{
			if (m_depthStencilImage != att.imageName || m_depthStencilType != attachmentType(att))
				addFBOStatus(GL_FRAMEBUFFER_UNSUPPORTED, "Depth and stencil attachments are not the same image");
		}
	}
}

struct NumLayersParams
{
	GLenum		textureKind;		//< GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY
	GLsizei		numLayers;			//< Number of layers in texture
	GLsizei		attachmentLayer;	//< Layer referenced by attachment

	static string	getName			(const NumLayersParams& params);
	static string	getDescription	(const NumLayersParams& params);
};

string NumLayersParams::getName (const NumLayersParams& params)
{
	ostringstream os;
	const string kindStr = params.textureKind == GL_TEXTURE_3D ? "3d" : "2darr";
	os << kindStr << "_" << params.numLayers << "_" << params.attachmentLayer;
	return os.str();
}

string NumLayersParams::getDescription (const NumLayersParams& params)
{
	ostringstream os;
	const string kindStr = (params.textureKind == GL_TEXTURE_3D
							? "3D Texture"
							: "2D Array Texture");
	os << kindStr + ", "
	   << params.numLayers << " layers, "
	   << "attached layer " << params.attachmentLayer << ".";
	return os.str();
}

class NumLayersTest : public fboc::ParamTest<NumLayersParams>
{
public:
					NumLayersTest		(fboc::Context& ctx, NumLayersParams param)
						: fboc::ParamTest<NumLayersParams> (ctx, param) {}

	IterateResult	build				(FboBuilder& builder);
};

IterateResult NumLayersTest::build (FboBuilder& builder)
{
	TextureLayered* texCfg = DE_NULL;
	const GLenum target = GL_COLOR_ATTACHMENT0;

	switch (m_params.textureKind)
	{
		case GL_TEXTURE_3D:
			texCfg = &builder.makeConfig<Texture3D>();
			break;
		case GL_TEXTURE_2D_ARRAY:
			texCfg = &builder.makeConfig<Texture2DArray>();
			break;
		default:
			DE_ASSERT(!"Impossible case");
	}
	texCfg->internalFormat = getDefaultFormat(target, GL_TEXTURE);
	texCfg->width = 64;
	texCfg->height = 64;
	texCfg->numLayers = m_params.numLayers;
	const GLuint tex = builder.glCreateTexture(*texCfg);

	TextureLayerAttachment* att = &builder.makeConfig<TextureLayerAttachment>();
	att->layer = m_params.attachmentLayer;
	att->imageName = tex;

	builder.glAttach(target, att);

	return STOP;
}

enum
{
	SAMPLES_NONE = -2,
	SAMPLES_TEXTURE = -1
};
struct NumSamplesParams
{
	// >= 0: renderbuffer with N samples, -1: texture, -2: no attachment
	GLsizei		numSamples[3];

	static string	getName			(const NumSamplesParams& params);
	static string	getDescription	(const NumSamplesParams& params);
};

string NumSamplesParams::getName (const NumSamplesParams& params)
{
	ostringstream os;
	bool first = true;
	for (const GLsizei* ns	=	DE_ARRAY_BEGIN(params.numSamples);
		 ns 				!=	DE_ARRAY_END(params.numSamples);
		 ns++)
	{
		if (first)
			first = false;
		else
			os << "_";

		if (*ns == SAMPLES_NONE)
			os << "none";
		else if (*ns == SAMPLES_TEXTURE)
			os << "tex";
		else
			os << "rbo" << *ns;
	}
	return os.str();
}

string NumSamplesParams::getDescription (const NumSamplesParams& params)
{
	ostringstream os;
	bool first = true;
	static const char* const s_names[] = { "color", "depth", "stencil" };
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == DE_LENGTH_OF_ARRAY(params.numSamples));

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_names); i++)
	{
		GLsizei ns = params.numSamples[i];

		if (ns == SAMPLES_NONE)
			continue;

		if (first)
			first = false;
		else
			os << ", ";

		if (ns == SAMPLES_TEXTURE)
			os << "texture " << s_names[i] << " attachment";
		else
			os << ns << "-sample renderbuffer " << s_names[i] << " attachment";
	}
	return os.str();
}

class NumSamplesTest : public fboc::ParamTest<NumSamplesParams>
{
public:
					NumSamplesTest		(fboc::Context& ctx, NumSamplesParams param)
						: fboc::ParamTest<NumSamplesParams> (ctx, param) {}

	IterateResult	build				(FboBuilder& builder);
};

IterateResult NumSamplesTest::build (FboBuilder& builder)
{
	static const GLenum s_targets[] =
		{
			GL_COLOR_ATTACHMENT0,	GL_COLOR_ATTACHMENT1,	GL_DEPTH_ATTACHMENT,
		};
	// Non-integer formats for each attachment type.
	// \todo [2013-12-17 lauri] Add fixed/floating/integer metadata for formats so
	// we can pick one smartly or maybe try several.
	static const GLenum s_formats[] =
		{
			GL_RGBA8,				GL_RGB565,				GL_DEPTH_COMPONENT24,
		};
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_targets) == DE_LENGTH_OF_ARRAY(m_params.numSamples));

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_targets); i++)
	{
		const GLenum target = s_targets[i];
		const ImageFormat fmt = { s_formats[i], GL_NONE };

		const GLsizei ns = m_params.numSamples[i];
		if (ns == -2)
			continue;

		if (ns == -1)
		{
			attachTargetToNew(target, GL_TEXTURE, fmt, 64, 64, builder);
		}
		else
		{
			Renderbuffer& rboCfg = builder.makeConfig<Renderbuffer>();
			rboCfg.internalFormat = fmt;
			rboCfg.width = rboCfg.height = 64;
			rboCfg.numSamples = ns;

			const GLuint rbo = builder.glCreateRbo(rboCfg);
			// Implementations do not necessarily support sample sizes greater than 1.
			TCU_CHECK_AND_THROW(NotSupportedError,
								builder.getError() != GL_INVALID_OPERATION,
								"Unsupported number of samples");
			RenderbufferAttachment& att = builder.makeConfig<RenderbufferAttachment>();
			att.imageName = rbo;
			builder.glAttach(target, &att);
		}
	}

	return STOP;
}

class ES3CheckerFactory : public CheckerFactory
{
public:
	Checker*			createChecker	(const glu::RenderContext& ctx) { return new ES3Checker(ctx); }
};

class TestGroup : public TestCaseGroup
{
public:
						TestGroup		(Context& context);
	void				init			(void);
private:
	ES3CheckerFactory	m_checkerFactory;
	fboc::Context		m_fboc;
};

void TestGroup::init (void)
{
	addChild(m_fboc.createRenderableTests());
	addChild(m_fboc.createAttachmentTests());
	addChild(m_fboc.createSizeTests());

	TestCaseGroup* layerTests = new TestCaseGroup(
		getContext(), "layer", "Tests for layer attachments");

	static const NumLayersParams s_layersParams[] =
		{ //  textureKind			numLayers	attachmentKind
			{ GL_TEXTURE_2D_ARRAY,	1,			0 },
			{ GL_TEXTURE_2D_ARRAY,	1,			3 },
			{ GL_TEXTURE_2D_ARRAY,	4,			3 },
			{ GL_TEXTURE_2D_ARRAY,	4,			15 },
			{ GL_TEXTURE_3D,		1,			0 },
			{ GL_TEXTURE_3D,		1,			15 },
			{ GL_TEXTURE_3D,		4,			15 },
			{ GL_TEXTURE_3D,		64,			15 },
		};

	for (const NumLayersParams* lp	=	DE_ARRAY_BEGIN(s_layersParams);
		 lp							!=  DE_ARRAY_END(s_layersParams);
		 ++lp)
		layerTests->addChild(new NumLayersTest(m_fboc, *lp));

	addChild(layerTests);

	TestCaseGroup* sampleTests = new TestCaseGroup(
		getContext(), "samples", "Tests for multisample attachments");

	static const NumSamplesParams s_samplesParams[] =
	{
		{ { 0,					SAMPLES_NONE,		SAMPLES_NONE } },
		{ { 1,					SAMPLES_NONE,		SAMPLES_NONE } },
		{ { 2,					SAMPLES_NONE,		SAMPLES_NONE } },
		{ { 0,					SAMPLES_TEXTURE,	SAMPLES_NONE } },
		{ { 1,					SAMPLES_TEXTURE,	SAMPLES_NONE } },
		{ { 2,					SAMPLES_TEXTURE,	SAMPLES_NONE } },
		{ { 2,					1,					SAMPLES_NONE } },
		{ { 2,					2,					SAMPLES_NONE } },
		{ { 0,					0,					SAMPLES_TEXTURE } },
		{ { 1,					2,					0 } },
		{ { 2,					2,					0 } },
		{ { 1,					1,					1 } },
		{ { 1,					2,					4 } },
	};

	for (const NumSamplesParams* lp	=	DE_ARRAY_BEGIN(s_samplesParams);
		 lp							!=  DE_ARRAY_END(s_samplesParams);
		 ++lp)
		sampleTests->addChild(new NumSamplesTest(m_fboc, *lp));

	addChild(sampleTests);
}

TestGroup::TestGroup (Context& ctx)
	: TestCaseGroup		(ctx, "completeness", "Completeness tests")
	, m_checkerFactory	()
	, m_fboc			(ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory)
{
	const FormatEntries stdRange = GLS_ARRAY_RANGE(s_es3Formats);
	const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es3ExtFormats);

	m_fboc.addFormats(stdRange);
	m_fboc.addExtFormats(extRange);
	m_fboc.setHaveMulticolorAtts(true); // Vanilla ES3 has multiple color attachments
}

tcu::TestCaseGroup* createFboCompletenessTests (Context& context)
{
	return new TestGroup(context);
}

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