/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2017 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 EXT Shader Framebuffer Fetch Tests.
 *//*--------------------------------------------------------------------*/

#include "es31fShaderFramebufferFetchTests.hpp"
#include "es31fFboTestUtil.hpp"

#include "tcuTestLog.hpp"
#include "tcuSurface.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuVectorUtil.hpp"

#include "gluShaderProgram.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTextureUtil.hpp"
#include "gluContextInfo.hpp"
#include "gluObjectWrapper.hpp"

#include "glwFunctions.hpp"
#include "glwEnums.hpp"

#include "deStringUtil.hpp"

#include <vector>

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace
{

using std::vector;
using std::string;
using tcu::TestLog;

using namespace glw;
using namespace FboTestUtil;

static void checkExtensionSupport (Context& context, const char* extName)
{
	if (!context.getContextInfo().isExtensionSupported(extName))
		throw tcu::NotSupportedError(string(extName) + " not supported");
}

static void checkFramebufferFetchSupport (Context& context)
{
	checkExtensionSupport(context, "GL_EXT_shader_framebuffer_fetch");
}

static bool isRequiredFormat (deUint32 format, glu::RenderContext& renderContext)
{
	const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
	switch (format)
	{
		// Color-renderable formats
		case GL_RGBA32I:
		case GL_RGBA32UI:
		case GL_RGBA16I:
		case GL_RGBA16UI:
		case GL_RGBA8:
		case GL_RGBA8I:
		case GL_RGBA8UI:
		case GL_SRGB8_ALPHA8:
		case GL_RGB10_A2:
		case GL_RGB10_A2UI:
		case GL_RGBA4:
		case GL_RGB5_A1:
		case GL_RGB8:
		case GL_RGB565:
		case GL_RG32I:
		case GL_RG32UI:
		case GL_RG16I:
		case GL_RG16UI:
		case GL_RG8:
		case GL_RG8I:
		case GL_RG8UI:
		case GL_R32I:
		case GL_R32UI:
		case GL_R16I:
		case GL_R16UI:
		case GL_R8:
		case GL_R8I:
		case GL_R8UI:
			return true;

		// Float format
		case GL_RGBA32F:
		case GL_RGB32F:
		case GL_R11F_G11F_B10F:
		case GL_RG32F:
		case GL_R32F:
			return isES32;

		default:
			return false;
	}
}

tcu::TextureFormat getReadPixelFormat (const tcu::TextureFormat& format)
{
	switch (tcu::getTextureChannelClass(format.type))
	{
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);

		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);

		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);

		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);

		default:
			DE_ASSERT(false);
			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
	}
}

tcu::Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
{
	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);

	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);

	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);

	const tcu::IVec4	srcBits		= tcu::getTextureFormatBitDepth(sourceFormat);
	const tcu::IVec4	readBits	= tcu::getTextureFormatBitDepth(readPixelsFormat);

	return tcu::Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>();
}

tcu::UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
{
	const tcu::IVec4	srcMantissaBits		= tcu::getTextureFormatMantissaBitDepth(sourceFormat);
	const tcu::IVec4	readMantissaBits	= tcu::getTextureFormatMantissaBitDepth(readPixelsFormat);
	tcu::IVec4			ULPDiff(0);

	for (int i = 0; i < 4; i++)
		if (readMantissaBits[i] >= srcMantissaBits[i])
			ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i];

	return tcu::UVec4(4) * (tcu::UVec4(1) << (ULPDiff.cast<deUint32>()));
}

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

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

	return false;
}

static std::string getColorOutputType(tcu::TextureFormat format)
{
	switch (tcu::getTextureChannelClass(format.type))
	{
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:		return "uvec4";
		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:		return "ivec4";
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:		return "vec4";
		default:
			DE_FATAL("Unsupported TEXTURECHANNELCLASS");
			return "";
	}
}

static std::vector<std::string> getEnablingExtensions (deUint32 format, glu::RenderContext& renderContext)
{
	const bool					isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
	std::vector<std::string>	out;

	DE_ASSERT(!isRequiredFormat(format, renderContext));

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

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

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

		default:
			break;
	}

	return out;
}

void checkFormatSupport (Context& context, deUint32 sizedFormat)
{
	const bool						isCoreFormat	= isRequiredFormat(sizedFormat, context.getRenderContext());
	const std::vector<std::string>	requiredExts	= (!isCoreFormat) ? getEnablingExtensions(sizedFormat, context.getRenderContext()) : std::vector<std::string>();

	// Check that we don't try to use invalid formats.
	DE_ASSERT(isCoreFormat || !requiredExts.empty());

	if (!requiredExts.empty() && !isAnyExtensionSupported(context, requiredExts))
		throw tcu::NotSupportedError("Format not supported");
}

tcu::Vec4 scaleColorValue (tcu::TextureFormat format, const tcu::Vec4& color)
{
	const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(format);
	const tcu::Vec4					cScale			= fmtInfo.valueMax-fmtInfo.valueMin;
	const tcu::Vec4					cBias			= fmtInfo.valueMin;

	return tcu::RGBA(color).toVec() * cScale + cBias;
}

// Base class for framebuffer fetch test cases

class FramebufferFetchTestCase : public TestCase
{
public:
									FramebufferFetchTestCase		(Context& context, const char* name, const char* desc, deUint32 format);
									~FramebufferFetchTestCase		(void);

	void							init							(void);
	void							deinit							(void);

protected:
	string							genPassThroughVertSource		(void);
	virtual glu::ProgramSources		genShaderSources				(void);

	void							genFramebufferWithTexture		(const tcu::Vec4& color);
	void							genAttachementTexture			(const tcu::Vec4& color);
	void							genUniformColor					(const tcu::Vec4& color);

	void							render							(void);
	void							verifyRenderbuffer				(TestLog& log, const tcu::TextureFormat& format, const tcu::TextureLevel& reference, const tcu::TextureLevel& result);

	const glw::Functions&			m_gl;
	const deUint32					m_format;

	glu::ShaderProgram*				m_program;
	GLuint							m_framebuffer;
	GLuint							m_texColorBuffer;

	tcu::TextureFormat				m_texFmt;
	glu::TransferFormat				m_transferFmt;
	bool							m_isFilterable;

	enum
	{
		VIEWPORT_WIDTH	= 64,
		VIEWPORT_HEIGHT = 64,
	};
};

FramebufferFetchTestCase::FramebufferFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format)
	: TestCase (context, name, desc)
	, m_gl					(m_context.getRenderContext().getFunctions())
	, m_format				(format)
	, m_program				(DE_NULL)
	, m_framebuffer			(0)
	, m_texColorBuffer		(0)
	, m_texFmt				(glu::mapGLInternalFormat(m_format))
	, m_transferFmt			(glu::getTransferFormat(m_texFmt))
	, m_isFilterable		(glu::isGLInternalColorFormatFilterable(m_format))
{
}

FramebufferFetchTestCase::~FramebufferFetchTestCase (void)
{
	FramebufferFetchTestCase::deinit();
}

void FramebufferFetchTestCase::init (void)
{
	checkFramebufferFetchSupport (m_context);
	checkFormatSupport(m_context, m_format);

	DE_ASSERT(!m_program);
	m_program = new glu::ShaderProgram(m_context.getRenderContext(), genShaderSources());

	m_testCtx.getLog() << *m_program;

	if (!m_program->isOk())
	{
		delete m_program;
		m_program = DE_NULL;
		TCU_FAIL("Failed to compile shader program");
	}

	m_gl.useProgram(m_program->getProgram());
}

void FramebufferFetchTestCase::deinit (void)
{
	delete m_program;
	m_program = DE_NULL;

	if (m_framebuffer)
	{
		m_gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
		m_gl.deleteFramebuffers(1, &m_framebuffer);
		m_framebuffer = 0;
	}

	if (m_texColorBuffer)
	{
		m_gl.deleteTextures(1, &m_texColorBuffer);
		m_texColorBuffer = 0;
	}
}

string FramebufferFetchTestCase::genPassThroughVertSource (void)
{
	std::ostringstream vertShaderSource;

	vertShaderSource	<< "#version 310 es\n"
						<< "in highp vec4 a_position;\n"
						<< "\n"
						<< "void main (void)\n"
						<< "{\n"
						<< "	gl_Position = a_position;\n"
						<< "}\n";

	return vertShaderSource.str();
}

glu::ProgramSources FramebufferFetchTestCase::genShaderSources (void)
{
	const string		vecType	= getColorOutputType(m_texFmt);
	std::ostringstream	fragShaderSource;

	fragShaderSource	<< "#version 310 es\n"
						<< "#extension GL_EXT_shader_framebuffer_fetch : require\n"
						<< "layout(location = 0) inout highp " << vecType << " o_color;\n"
						<< "uniform highp " << vecType << " u_color;\n"
						<< "\n"
						<< "void main (void)\n"
						<< "{\n"
						<< "	o_color += u_color;\n"
						<< "}\n";

	return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
}

void FramebufferFetchTestCase::genFramebufferWithTexture (const tcu::Vec4& color)
{
	m_gl.genFramebuffers(1, &m_framebuffer);
	m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);

	genAttachementTexture(color);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "genAttachementTexture()");

	m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texColorBuffer, 0);
	TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
}

void FramebufferFetchTestCase::genAttachementTexture (const tcu::Vec4& color)
{
	tcu::TextureLevel			data					(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
	tcu::TextureChannelClass	textureChannelClass =	tcu::getTextureChannelClass(m_texFmt.type);

	m_gl.genTextures(1, &m_texColorBuffer);
	m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer);

	m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
	m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
	m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
	m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	m_isFilterable ? GL_LINEAR : GL_NEAREST);
	m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	m_isFilterable ? GL_LINEAR : GL_NEAREST);

	if (textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
		tcu::clear(data.getAccess(), color.asUint());
	else if (textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
		tcu::clear(data.getAccess(), color.asInt());
	else
		tcu::clear(data.getAccess(), color);

	m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
	m_gl.bindTexture(GL_TEXTURE_2D, 0);
}

void FramebufferFetchTestCase::verifyRenderbuffer (TestLog&	log, const tcu::TextureFormat& format, const tcu::TextureLevel&	reference, const tcu::TextureLevel&	result)
{
	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");

	switch (tcu::getTextureChannelClass(format.type))
	{
		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
		{
			const string		name		= "Renderbuffer";
			const string		desc		= "Compare renderbuffer (floating_point)";
			const tcu::UVec4	threshold	= getFloatULPThreshold(format, result.getFormat());

			if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT))
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");

			break;
		}

		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
		{
			const string		name		= "Renderbuffer";
			const string		desc		= "Compare renderbuffer (integer)";
			const tcu::UVec4	threshold	(1, 1, 1, 1);

			if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT))
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");

			break;
		}

		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
		{
			const string		name		= "Renderbuffer";
			const string		desc		= "Compare renderbuffer (fixed point)";
			const tcu::Vec4		threshold	= getFixedPointFormatThreshold(format, result.getFormat());

			if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT))
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");

			break;
		}

		default:
		{
			DE_ASSERT(DE_FALSE);
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
		}
	}
}

void FramebufferFetchTestCase::genUniformColor (const tcu::Vec4& color)
{
	const GLuint colorLocation	= m_gl.getUniformLocation(m_program->getProgram(), "u_color");

	switch (tcu::getTextureChannelClass(m_texFmt.type))
	{
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
		{
			m_gl.uniform4uiv(colorLocation, 1, color.asUint().getPtr());
			break;
		}

		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
		{
			m_gl.uniform4iv(colorLocation, 1, color.asInt().getPtr());
			break;
		}
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
		{
			m_gl.uniform4fv(colorLocation, 1, color.asFloat().getPtr());
			break;
		}
		default:
			DE_ASSERT(DE_FALSE);
	}

	GLU_EXPECT_NO_ERROR(m_gl.getError(), "genUniformColor()");
}

void FramebufferFetchTestCase::render (void)
{
	const GLfloat coords[] =
	{
		-1.0f, -1.0f,
		+1.0f, -1.0f,
		+1.0f, +1.0f,
		-1.0f, +1.0f,
	};

	const GLushort indices[] =
	{
		0, 1, 2, 2, 3, 0,
	};

	const GLuint	coordLocation	= m_gl.getAttribLocation(m_program->getProgram(), "a_position");

	m_gl.viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

	glu::Buffer coordinatesBuffer(m_context.getRenderContext());
	glu::Buffer elementsBuffer(m_context.getRenderContext());

	m_gl.bindBuffer(GL_ARRAY_BUFFER, *coordinatesBuffer);
	m_gl.bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW);
	m_gl.enableVertexAttribArray(coordLocation);
	m_gl.vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL);

	m_gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *elementsBuffer);
	m_gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW);

	m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "render()");
}

// Test description:
// - Attach texture containing solid color to framebuffer.
// - Draw full quad covering the entire viewport.
// - Sum framebuffer read color with passed in uniform color.
// - Compare resulting surface with reference.

class TextureFormatTestCase : public FramebufferFetchTestCase
{
public:
						TextureFormatTestCase		(Context& context, const char* name, const char* desc, deUint32 format);
						~TextureFormatTestCase		(void) {};

	IterateResult		iterate						(void);

private:
	tcu::TextureLevel	genReferenceTexture			(const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
};

TextureFormatTestCase::TextureFormatTestCase (Context& context, const char* name, const char* desc, deUint32 format)
	: FramebufferFetchTestCase(context, name, desc, format)
{
}

tcu::TextureLevel TextureFormatTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
{
	tcu::TextureLevel			reference			(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
	tcu::TextureChannelClass	textureChannelClass = tcu::getTextureChannelClass(m_texFmt.type);

	if (textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
	{
		tcu::clear(reference.getAccess(), fbColor.asUint() + uniformColor.asUint());
	}
	else if (textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
	{
		tcu::clear(reference.getAccess(), fbColor.asInt() + uniformColor.asInt());
	}
	else
	{
		if (tcu::isSRGB(m_texFmt))
		{
			const tcu::Vec4	fragmentColor = tcu::sRGBToLinear(fbColor) + uniformColor;
			tcu::clear(reference.getAccess(), tcu::linearToSRGB(fragmentColor));
		}
		else
		{
			tcu::clear(reference.getAccess(), fbColor + uniformColor);
		}
	}

	return reference;
}

TextureFormatTestCase::IterateResult TextureFormatTestCase::iterate (void)
{
	const tcu::Vec4		uniformColor	= scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
	const tcu::Vec4		fbColor			= scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));

	tcu::TextureLevel	reference		= genReferenceTexture(fbColor, uniformColor);
	tcu::TextureLevel	result			(getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

	genFramebufferWithTexture(fbColor);
	genUniformColor(uniformColor);
	render();

	glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
	verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);

	return STOP;
}

// Test description:
// - Attach multiple textures containing solid colors to framebuffer.
// - Draw full quad covering the entire viewport.
// - For each render target sum framebuffer read color with passed in uniform color.
// - Compare resulting surfaces with references.

class MultipleRenderTargetsTestCase : public FramebufferFetchTestCase
{
public:
						MultipleRenderTargetsTestCase		(Context& context, const char* name, const char* desc, deUint32 format);
						~MultipleRenderTargetsTestCase		(void);

	IterateResult		iterate								(void);
	void				deinit								(void);

private:
	void				genFramebufferWithTextures			(const vector<tcu::Vec4>& colors);
	void				genAttachmentTextures				(const vector<tcu::Vec4>& colors);
	tcu::TextureLevel	genReferenceTexture					(const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
	glu::ProgramSources genShaderSources					(void);

	enum
	{
		MAX_COLOR_BUFFERS = 4
	};

	GLuint				m_texColorBuffers					[MAX_COLOR_BUFFERS];
	GLenum				m_colorBuffers						[MAX_COLOR_BUFFERS];
};

MultipleRenderTargetsTestCase::MultipleRenderTargetsTestCase (Context& context, const char* name, const char* desc, deUint32 format)
	: FramebufferFetchTestCase(context, name, desc, format)
	, m_texColorBuffers ()
{
	m_colorBuffers[0] = GL_COLOR_ATTACHMENT0;
	m_colorBuffers[1] = GL_COLOR_ATTACHMENT1;
	m_colorBuffers[2] = GL_COLOR_ATTACHMENT2;
	m_colorBuffers[3] = GL_COLOR_ATTACHMENT3;
}

MultipleRenderTargetsTestCase::~MultipleRenderTargetsTestCase (void)
{
	MultipleRenderTargetsTestCase::deinit();
}

void MultipleRenderTargetsTestCase::deinit (void)
{
	// Clean up texture data
	for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i)
	{
		if (m_texColorBuffers[i])
			m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texColorBuffers[i]);
	}

	FramebufferFetchTestCase::deinit();
}

void MultipleRenderTargetsTestCase::genFramebufferWithTextures (const vector<tcu::Vec4>& colors)
{
	m_gl.genFramebuffers(1, &m_framebuffer);
	m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);

	genAttachmentTextures(colors);

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i)
		m_gl.framebufferTexture2D(GL_FRAMEBUFFER, m_colorBuffers[i], GL_TEXTURE_2D, m_texColorBuffers[i], 0);

	TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

	m_gl.drawBuffers((glw::GLsizei)MAX_COLOR_BUFFERS, &m_colorBuffers[0]);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "genFramebufferWithTextures()");
}

void MultipleRenderTargetsTestCase::genAttachmentTextures (const vector<tcu::Vec4>& colors)
{
	tcu::TextureLevel	data	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);

	m_gl.genTextures(MAX_COLOR_BUFFERS, m_texColorBuffers);

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i)
	{
		m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffers[i]);

		m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
		m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
		m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
		m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	m_isFilterable ? GL_LINEAR : GL_NEAREST);
		m_gl.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	m_isFilterable ? GL_LINEAR : GL_NEAREST);

		clear(data.getAccess(), colors[i]);
		m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
	}

	m_gl.bindTexture(GL_TEXTURE_2D, 0);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "genAttachmentTextures()");
}

tcu::TextureLevel MultipleRenderTargetsTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
{
	tcu::TextureLevel	reference	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
	tcu::clear(reference.getAccess(), fbColor + uniformColor);

	return reference;
}

glu::ProgramSources MultipleRenderTargetsTestCase::genShaderSources (void)
{
	const string		vecType	= getColorOutputType(m_texFmt);
	std::ostringstream	fragShaderSource;

	fragShaderSource	<< "#version 310 es\n"
						<< "#extension GL_EXT_shader_framebuffer_fetch : require\n"
						<< "layout(location = 0) inout highp " << vecType << " o_color0;\n"
						<< "layout(location = 1) inout highp " << vecType << " o_color1;\n"
						<< "layout(location = 2) inout highp " << vecType << " o_color2;\n"
						<< "layout(location = 3) inout highp " << vecType << " o_color3;\n"
						<< "uniform highp " << vecType << " u_color;\n"
						<< "\n"
						<< "void main (void)\n"
						<< "{\n"
						<< "	o_color0 += u_color;\n"
						<< "	o_color1 += u_color;\n"
						<< "	o_color2 += u_color;\n"
						<< "	o_color3 += u_color;\n"
						<< "}\n";

	return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
}

MultipleRenderTargetsTestCase::IterateResult MultipleRenderTargetsTestCase::iterate (void)
{
	const tcu::Vec4		uniformColor	= scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
	tcu::TextureLevel	result			(getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

	vector<tcu::Vec4> colors;
	colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.9f, 0.0f, 0.0f, 1.0f)));
	colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.9f, 0.0f, 1.0f)));
	colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.9f, 1.0f)));
	colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.9f, 0.9f, 1.0f)));

	genFramebufferWithTextures(colors);
	genUniformColor(uniformColor);
	render();

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_colorBuffers); ++i)
	{
		tcu::TextureLevel	reference		= genReferenceTexture(colors[i], uniformColor);

		m_gl.readBuffer(m_colorBuffers[i]);
		glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
		verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
	}

	return STOP;
}

// Test description:
// - Same as TextureFormatTestCase except uses built-in fragment output of ES 2.0

class LastFragDataTestCase : public FramebufferFetchTestCase
{
public:
						LastFragDataTestCase			(Context& context, const char* name, const char* desc, deUint32 format);
						~LastFragDataTestCase			(void) {};

	IterateResult		iterate							(void);

private:
	glu::ProgramSources genShaderSources				(void);
	tcu::TextureLevel	genReferenceTexture				(const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
};

LastFragDataTestCase::LastFragDataTestCase (Context& context, const char* name, const char* desc, deUint32 format)
	: FramebufferFetchTestCase(context, name, desc, format)
{
}

glu::ProgramSources LastFragDataTestCase::genShaderSources (void)
{
	const string		vecType	= getColorOutputType(m_texFmt);
	std::ostringstream	vertShaderSource;
	std::ostringstream	fragShaderSource;

	vertShaderSource	<< "#version 100\n"
						<< "attribute vec4 a_position;\n"
						<< "\n"
						<< "void main (void)\n"
						<< "{\n"
						<< "	gl_Position = a_position;\n"
						<< "}\n";

	fragShaderSource	<< "#version 100\n"
						<< "#extension GL_EXT_shader_framebuffer_fetch : require\n"
						<< "uniform highp " << vecType << " u_color;\n"
						<< "\n"
						<< "void main (void)\n"
						<< "{\n"
						<< "	gl_FragColor = u_color + gl_LastFragData[0];\n"
						<< "}\n";

	return glu::makeVtxFragSources(vertShaderSource.str(), fragShaderSource.str());
}

tcu::TextureLevel LastFragDataTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
{
	tcu::TextureLevel	reference	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
	tcu::clear(reference.getAccess(), fbColor + uniformColor);

	return reference;
}

LastFragDataTestCase::IterateResult LastFragDataTestCase::iterate (void)
{
	const tcu::Vec4		uniformColor	= scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
	const tcu::Vec4		fbColor			= scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));

	tcu::TextureLevel	reference		= genReferenceTexture(fbColor, uniformColor);
	tcu::TextureLevel	result			(getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

	genFramebufferWithTexture(fbColor);
	genUniformColor(uniformColor);
	render();

	glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
	verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);

	return STOP;
}

// Test description:
// - Attach texture containing solid color to framebuffer.
// - Create one 2D texture for sampler with a grid pattern
// - Draw full screen quad covering the entire viewport.
// - Sum color values taken from framebuffer texture and sampled texture
// - Compare resulting surface with reference.

class TexelFetchTestCase : public FramebufferFetchTestCase
{
public:
						TexelFetchTestCase		(Context& context, const char* name, const char* desc, deUint32 format);
						~TexelFetchTestCase		(void) {}

	IterateResult		iterate					(void);

private:
	glu::ProgramSources genShaderSources		(void);
	tcu::TextureLevel	genReferenceTexture		(const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd, const tcu::Vec4& fbColor);
	void				genSamplerTexture		(const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd);

	GLuint				m_samplerTexture;
};

TexelFetchTestCase::TexelFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format)
	: FramebufferFetchTestCase(context, name, desc, format)
	, m_samplerTexture(0)
{
}

void TexelFetchTestCase::genSamplerTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd)
{
	tcu::TextureLevel	data	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);

	m_gl.activeTexture(GL_TEXTURE1);

	m_gl.genTextures(1, &m_samplerTexture);
	m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer);
	m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	tcu::fillWithGrid(data.getAccess(), 8, colorEven, colorOdd);

	m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
	m_gl.bindTexture(GL_TEXTURE_2D, 0);

	const GLuint samplerLocation = m_gl.getUniformLocation(m_program->getProgram(), "u_sampler");
	m_gl.uniform1i(samplerLocation, 1);

	GLU_EXPECT_NO_ERROR(m_gl.getError(), "genSamplerTexture()");
}

glu::ProgramSources TexelFetchTestCase::genShaderSources (void)
{
	const string		vecType	= getColorOutputType(m_texFmt);
	std::ostringstream	fragShaderSource;

	fragShaderSource	<< "#version 310 es\n"
						<< "#extension GL_EXT_shader_framebuffer_fetch : require\n"
						<< "layout(location = 0) inout highp " << vecType << " o_color;\n"
						<< "\n"
						<< "uniform sampler2D u_sampler;\n"
						<< "void main (void)\n"
						<< "{\n"
						<< "	o_color += texelFetch(u_sampler, ivec2(gl_FragCoord), 0);\n"
						<< "}\n";

	return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
}

tcu::TextureLevel TexelFetchTestCase::genReferenceTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd, const tcu::Vec4& fbColor)
{
	tcu::TextureLevel	reference	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
	tcu::fillWithGrid(reference.getAccess(), 8, colorEven + fbColor, colorOdd + fbColor);

	return reference;
}

TexelFetchTestCase::IterateResult TexelFetchTestCase::iterate (void)
{
	const tcu::Vec4		fbColor			= scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f));
	const tcu::Vec4		colorEven		= scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f));
	const tcu::Vec4		colorOdd		= scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f));

	genSamplerTexture(colorEven, colorOdd);
	tcu::TextureLevel	reference		= genReferenceTexture(colorEven, colorOdd, fbColor);
	tcu::TextureLevel	result			(getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

	genFramebufferWithTexture(fbColor);
	render();

	glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
	verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);

	// cleanup
	m_gl.deleteTextures(1, &m_samplerTexture);

	return STOP;
}

// Test description:
// - Attach texture containing solid color to framebuffer.
// - Draw full screen quad covering the entire viewport.
// - Multiple assignments are made to the output color for fragments on the right vertical half of the screen.
// - A single assignment is made to the output color for fragments on the left vertical centre of the screen.
// - Values are calculated using the sum of the passed in uniform color and the previous framebuffer color.
// - Compare resulting surface with reference.

class MultipleAssignmentTestCase : public FramebufferFetchTestCase
{
public:
						MultipleAssignmentTestCase		(Context& context, const char* name, const char* desc, deUint32 format);
						~MultipleAssignmentTestCase		(void) {}

	IterateResult		iterate							(void);

private:
	glu::ProgramSources genShaderSources				(void);
	tcu::TextureLevel	genReferenceTexture				(const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
};

MultipleAssignmentTestCase::MultipleAssignmentTestCase (Context& context, const char* name, const char* desc, deUint32 format)
	: FramebufferFetchTestCase(context, name, desc, format)
{
}

glu::ProgramSources MultipleAssignmentTestCase::genShaderSources (void)
{
	const string		vecType = getColorOutputType(m_texFmt);
	std::ostringstream	vertShaderSource;
	std::ostringstream	fragShaderSource;

	vertShaderSource	<< "#version 310 es\n"
						<< "in highp vec4 a_position;\n"
						<< "out highp vec4 v_position;\n"
						<< "\n"
						<< "void main (void)\n"
						<< "{\n"
						<< "	gl_Position = a_position;\n"
						<< "	v_position  = gl_Position;\n"
						<< "}\n";

	fragShaderSource	<< "#version 310 es\n"
						<< "#extension GL_EXT_shader_framebuffer_fetch : require\n"
						<< "in highp vec4 v_position;\n"
						<< "layout(location = 0) inout highp " << vecType << " o_color;\n"
						<< "uniform highp " << vecType << " u_color;\n"
						<< "\n"
						<< "void main (void)\n"
						<< "{\n"
						<< "	if (v_position.x > 0.0f)\n"
						<< "		o_color += u_color;\n"
						<< "\n"
						<< "	o_color += u_color;\n"
						<< "}\n";

	return glu::makeVtxFragSources(vertShaderSource.str(), fragShaderSource.str());
}

tcu::TextureLevel MultipleAssignmentTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
{
	tcu::TextureLevel	reference	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);

	int	width	= reference.getAccess().getWidth();
	int	height	= reference.getAccess().getHeight();
	int	left	= width /2;
	int	top		= height/2;

	tcu::Vec4 compositeColor(uniformColor * 2.0f);

	tcu::clear(getSubregion(reference.getAccess(), left,		0,		0, width-left,	top,		1),	fbColor + compositeColor);
	tcu::clear(getSubregion(reference.getAccess(), 0,			top,	0, left,		height-top,	1), fbColor + uniformColor);
	tcu::clear(getSubregion(reference.getAccess(), left,		top,	0, width-left,	height-top, 1), fbColor + compositeColor);
	tcu::clear(getSubregion(reference.getAccess(), 0,			0,		0, left,		top,		1),	fbColor + uniformColor);

	return reference;
}

MultipleAssignmentTestCase::IterateResult MultipleAssignmentTestCase::iterate (void)
{
	const tcu::Vec4		fbColor			= scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
	const tcu::Vec4		uniformColor	= scaleColorValue(m_texFmt, tcu::Vec4(0.25f, 0.0f, 0.0f, 1.0f));

	tcu::TextureLevel	reference		= genReferenceTexture(fbColor, uniformColor);
	tcu::TextureLevel	result			(getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

	genFramebufferWithTexture(fbColor);
	genUniformColor(uniformColor);
	render();

	glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
	verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);

	return STOP;
}

// Test description:
// - Attach texture containing grid pattern to framebuffer.
// - Using framebuffer reads discard odd squares in the grid.
// - The even squares framebuffer color is added to the passed in uniform color.

class FragmentDiscardTestCase : public FramebufferFetchTestCase
{
public:
						FragmentDiscardTestCase		(Context& context, const char* name, const char* desc, deUint32 format);
						~FragmentDiscardTestCase	(void) {}

	IterateResult		iterate						(void);

private:
	glu::ProgramSources genShaderSources			(void);
	void				genFramebufferWithGrid		(const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd);
	tcu::TextureLevel	genReferenceTexture			(const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd);
};

FragmentDiscardTestCase::FragmentDiscardTestCase (Context& context, const char* name, const char* desc, deUint32 format)
	: FramebufferFetchTestCase(context, name, desc, format)
{
}

glu::ProgramSources FragmentDiscardTestCase::genShaderSources (void)
{
	const string		vecType	= getColorOutputType(m_texFmt);
	std::ostringstream	fragShaderSource;

	fragShaderSource	<< "#version 310 es\n"
						<< "#extension GL_EXT_shader_framebuffer_fetch : require\n"
						<< "layout(location = 0) inout highp " << vecType << " o_color;\n"
						<< "uniform highp " << vecType << " u_color;\n"
						<< "\n"
						<< "void main (void)\n"
						<< "{\n"
						<< "	const highp float threshold = 0.0005f;\n"
						<< "	bool valuesEqual = all(lessThan(abs(o_color - u_color), vec4(threshold)));\n\n"
						<< "	if (valuesEqual)\n"
						<< "		o_color += u_color;\n"
						<< "	else\n"
						<< "		discard;\n"
						<< "}\n";

	return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
}

void FragmentDiscardTestCase::genFramebufferWithGrid (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd)
{
	tcu::TextureLevel data	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);

	m_gl.genFramebuffers(1, &m_framebuffer);
	m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);

	m_gl.genTextures(1, &m_texColorBuffer);
	m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer);

	tcu::fillWithGrid(data.getAccess(), 8, fbColorEven, fbColorOdd);

	m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
	m_gl.bindTexture(GL_TEXTURE_2D, 0);

	m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texColorBuffer, 0);
	TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
}

tcu::TextureLevel FragmentDiscardTestCase::genReferenceTexture (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd)
{
	tcu::TextureLevel	reference	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
	tcu::fillWithGrid(reference.getAccess(), 8, fbColorEven + fbColorEven, fbColorOdd);

	return reference;
}

FragmentDiscardTestCase::IterateResult FragmentDiscardTestCase::iterate (void)
{
	const tcu::Vec4		fbColorEven		= scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 1.0f, 1.0f));
	const tcu::Vec4		fbColorOdd		= scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f));

	tcu::TextureLevel	reference		= genReferenceTexture(fbColorEven, fbColorOdd);
	tcu::TextureLevel	result			(getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
	genFramebufferWithGrid(fbColorEven, fbColorOdd);

	genUniformColor(fbColorEven);
	render();

	glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
	verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);

	return STOP;
}

// Test description:
// - Create 2D texture array containing three mipmaps.
// - Each mipmap level is assigned a different color.
// - Attach single mipmap level to framebuffer and draw full screen quad.
// - Sum framebuffer read color with passed in uniform color.
// - Compare resulting surface with reference.
// - Repeat for subsequent mipmap levels.

class TextureLevelTestCase : public FramebufferFetchTestCase
{
public:
						TextureLevelTestCase			(Context& context, const char* name, const char* desc, deUint32 format);
						~TextureLevelTestCase			(void) {}

	IterateResult		iterate							(void);

private:
	void				create2DTextureArrayMipMaps		(const vector<tcu::Vec4>& colors);
	tcu::TextureLevel	genReferenceTexture				(int level, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor);
	void				genReferenceMipmap				(const tcu::Vec4& color, tcu::TextureLevel& reference);
};

TextureLevelTestCase::TextureLevelTestCase (Context& context, const char* name, const char* desc, deUint32 format)
	: FramebufferFetchTestCase(context, name, desc, format)
{
}

void TextureLevelTestCase::create2DTextureArrayMipMaps (const vector<tcu::Vec4>& colors)
{
	int						numLevels	= (int)colors.size();
	tcu::TextureLevel		levelData	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType));

	m_gl.genTextures(1, &m_texColorBuffer);
	m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texColorBuffer);

	m_gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1, 0, m_transferFmt.format, m_transferFmt.dataType, DE_NULL);
	m_gl.generateMipmap(GL_TEXTURE_2D_ARRAY);

	for (int level = 0; level < numLevels; level++)
	{
		int		levelW		= de::max(1, VIEWPORT_WIDTH		>> level);
		int		levelH		= de::max(1, VIEWPORT_HEIGHT	>> level);

		levelData.setSize(levelW, levelH, 1);

		clear(levelData.getAccess(), colors[level]);
		m_gl.texImage3D(GL_TEXTURE_2D_ARRAY, level, m_format, levelW, levelH, 1, 0, m_transferFmt.format, m_transferFmt.dataType, levelData.getAccess().getDataPtr());
	}

	m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "create2DTextureArrayMipMaps()");
}

tcu::TextureLevel TextureLevelTestCase::genReferenceTexture (int level, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor)
{
	tcu::TextureLevel	reference	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH >> level, VIEWPORT_HEIGHT >> level, 1);

	genReferenceMipmap(colors[level] + uniformColor, reference);

	return reference;
}

void TextureLevelTestCase::genReferenceMipmap (const tcu::Vec4& color, tcu::TextureLevel& reference)
{
	const int	width	= reference.getAccess().getWidth();
	const int	height	= reference.getAccess().getHeight();
	const int	left	= width  / 2;
	const int	top		= height / 2;

	clear(getSubregion(reference.getAccess(), left,		0,		0, width-left,	top,		1),	color);
	clear(getSubregion(reference.getAccess(), 0,		top,	0, left,		height-top,	1), color);
	clear(getSubregion(reference.getAccess(), left,		top,	0, width-left,	height-top, 1), color);
	clear(getSubregion(reference.getAccess(), 0,		0,		0, left,		top,		1),	color);
}

TextureLevelTestCase::IterateResult TextureLevelTestCase::iterate (void)
{
	const tcu::Vec4		uniformColor	= scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f));
	vector<tcu::Vec4>	levelColors;

	levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f)));
	levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f)));
	levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));

	m_gl.genFramebuffers(1, &m_framebuffer);
	m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);

	create2DTextureArrayMipMaps(levelColors);

	// attach successive mipmap layers to framebuffer and render
	for (int level = 0; level < (int)levelColors.size(); ++level)
	{
		std::ostringstream name, desc;
		name << "Level "		<< level;
		desc << "Mipmap level " << level;

		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), name.str(), desc.str());
		tcu::TextureLevel			result			(getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH >> level, VIEWPORT_HEIGHT >> level);
		tcu::TextureLevel			reference		= genReferenceTexture(level, levelColors, uniformColor);

		m_gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texColorBuffer, level, 0);

		genUniformColor(uniformColor);
		render();

		glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
		verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);

		if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
			return STOP;
	}

	return STOP;
}

class TextureLayerTestCase : public FramebufferFetchTestCase
{
public:
						TextureLayerTestCase		(Context& context, const char* name, const char* desc, deUint32 format);
						~TextureLayerTestCase		(void) {}

	IterateResult		iterate						(void);

private:
	void				create2DTextureArrayLayers	(const vector<tcu::Vec4>&  colors);
	tcu::TextureLevel	genReferenceTexture			(int layer, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor);
};

TextureLayerTestCase::TextureLayerTestCase (Context& context, const char* name, const char* desc, deUint32 format)
	: FramebufferFetchTestCase(context, name, desc, format)
{
}

void TextureLayerTestCase::create2DTextureArrayLayers (const vector<tcu::Vec4>& colors)
{
	int						numLayers	= (int)colors.size();
	tcu::TextureLevel		layerData	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType));

	m_gl.genTextures(1, &m_texColorBuffer);
	m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texColorBuffer);
	m_gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, numLayers);
	m_gl.bindImageTexture(0, m_texColorBuffer, 0, GL_FALSE, 0, GL_READ_ONLY, m_format);

	layerData.setSize(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, numLayers);

	for (int layer = 0; layer < numLayers; layer++)
	{
		clear(layerData.getAccess(), colors[layer]);
		m_gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1, m_transferFmt.format, m_transferFmt.dataType, layerData.getAccess().getDataPtr());
	}

	m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "create2DTextureArrayLayers()");
}

tcu::TextureLevel TextureLayerTestCase::genReferenceTexture (int layer, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor)
{
	tcu::TextureLevel	reference	(glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
	clear(reference.getAccess(), colors[layer] + uniformColor);

	return reference;
}

// Test description
// - Create 2D texture array containing three layers.
// - Each layer is assigned a different color.
// - Attach single layer to framebuffer and draw full screen quad.
// - Sum framebuffer read color with passed in uniform color.
// - Compare resulting surface with reference.
// - Repeat for subsequent texture layers.

TextureLayerTestCase::IterateResult TextureLayerTestCase::iterate (void)
{
	const tcu::Vec4		uniformColor	= scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
	tcu::TextureLevel	result			(getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
	vector<tcu::Vec4>	layerColors;

	layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f)));
	layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f)));
	layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));

	m_gl.genFramebuffers(1, &m_framebuffer);
	m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);

	create2DTextureArrayLayers(layerColors);

	for (int layer = 0; layer < (int)layerColors.size(); ++layer)
	{
		std::ostringstream name, desc;
		name << "Layer " << layer;
		desc << "Layer " << layer;

		const tcu::ScopedLogSection section		(m_testCtx.getLog(), name.str(), desc.str());
		tcu::TextureLevel			reference	= genReferenceTexture(layer, layerColors, uniformColor);

		m_gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texColorBuffer, 0, layer);

		genUniformColor(uniformColor);
		render();

		glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
		verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);

		if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
			return STOP;
	}

	return STOP;
}

} // Anonymous

ShaderFramebufferFetchTests::ShaderFramebufferFetchTests (Context& context)
	: TestCaseGroup (context, "framebuffer_fetch", "GL_EXT_shader_framebuffer_fetch tests")
{
}

ShaderFramebufferFetchTests::~ShaderFramebufferFetchTests (void)
{
}

void ShaderFramebufferFetchTests::init (void)
{
	tcu::TestCaseGroup* const basicTestGroup				= new tcu::TestCaseGroup(m_testCtx, "basic",				"Basic framebuffer shader fetch tests");
	tcu::TestCaseGroup* const framebufferFormatTestGroup	= new tcu::TestCaseGroup(m_testCtx, "framebuffer_format",	"Texture render target formats tests");

	// basic
	{
		basicTestGroup->addChild(new TexelFetchTestCase				(m_context,		"texel_fetch",					"Framebuffer fetches in conjunction with shader texel fetches",			GL_RGBA8));
		basicTestGroup->addChild(new LastFragDataTestCase			(m_context,		"last_frag_data",				"Framebuffer fetches with built-in fragment output of ES 2.0",			GL_RGBA8));
		basicTestGroup->addChild(new FragmentDiscardTestCase		(m_context,		"fragment_discard",				"Framebuffer fetches in combination with fragment discards",			GL_RGBA8));
		basicTestGroup->addChild(new MultipleAssignmentTestCase		(m_context,		"multiple_assignment",			"Multiple assignments to fragment color inout",							GL_RGBA8));
		basicTestGroup->addChild(new MultipleRenderTargetsTestCase	(m_context,		"multiple_render_targets",		"Framebuffer fetches used in combination with multiple render targets",	GL_RGBA8));
		basicTestGroup->addChild(new TextureLevelTestCase			(m_context,		"framebuffer_texture_level",	"Framebuffer fetches with individual texture render target mipmaps",	GL_RGBA8));
		basicTestGroup->addChild(new TextureLayerTestCase			(m_context,		"framebuffer_texture_layer",	"Framebuffer fetches with individual texture render target layers",		GL_RGBA8));
	}

	// framebuffer formats
	{
		static const deUint32 colorFormats[] =
		{
			// RGBA formats
			GL_RGBA32I,
			GL_RGBA32UI,
			GL_RGBA16I,
			GL_RGBA16UI,
			GL_RGBA8,
			GL_RGBA8I,
			GL_RGBA8UI,
			GL_SRGB8_ALPHA8,
			GL_RGB10_A2,
			GL_RGB10_A2UI, GL_RGBA4, GL_RGB5_A1,

			// RGB formats
			GL_RGB8,
			GL_RGB565,

			// RG formats
			GL_RG32I,
			GL_RG32UI,
			GL_RG16I,
			GL_RG16UI,
			GL_RG8,
			GL_RG8I,
			GL_RG8UI,

			// R formats
			GL_R32I,
			GL_R32UI,
			GL_R16I,
			GL_R16UI,
			GL_R8,
			GL_R8I,
			GL_R8UI,

			// GL_EXT_color_buffer_float
			GL_RGBA32F,
			GL_RGBA16F,
			GL_R11F_G11F_B10F,
			GL_RG32F,
			GL_RG16F,
			GL_R32F,
			GL_R16F,

			// GL_EXT_color_buffer_half_float
			GL_RGB16F
		};

		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
			framebufferFormatTestGroup->addChild(new TextureFormatTestCase(m_context, getFormatName(colorFormats[ndx]), "Framebuffer fetches from texture attachments with varying formats", colorFormats[ndx]));
	}

	addChild(basicTestGroup);
	addChild(framebufferFormatTestGroup);
}

} // Functional
} // gles31
} // deqp
