/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 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 Texture swizzle tests.
 *//*--------------------------------------------------------------------*/

#include "es3fTextureSwizzleTests.hpp"
#include "glsTextureTestUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTexture.hpp"
#include "gluRenderContext.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuRenderTarget.hpp"
#include "deString.h"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"

namespace deqp
{
namespace gles3
{
namespace Functional
{

using std::string;
using std::vector;
using tcu::TestLog;
using namespace deqp::gls;
using namespace deqp::gls::TextureTestUtil;

static int swizzle (const tcu::RGBA& c, deUint32 swz)
{
	switch (swz)
	{
		case GL_RED:	return c.getRed();
		case GL_GREEN:	return c.getGreen();
		case GL_BLUE:	return c.getBlue();
		case GL_ALPHA:	return c.getAlpha();
		case GL_ZERO:	return 0;
		case GL_ONE:	return (1<<8)-1;
		default:
			DE_ASSERT(false);
			return 0;
	}
}

static void swizzle (tcu::Surface& surface, deUint32 swzR, deUint32 swzG, deUint32 swzB, deUint32 swzA)
{
	for (int y = 0; y < surface.getHeight(); y++)
	{
		for (int x = 0; x < surface.getWidth(); x++)
		{
			tcu::RGBA p = surface.getPixel(x, y);
			surface.setPixel(x, y, tcu::RGBA(swizzle(p, swzR), swizzle(p, swzG), swizzle(p, swzB), swizzle(p, swzA)));
		}
	}
}

class Texture2DSwizzleCase : public TestCase
{
public:
							Texture2DSwizzleCase	(Context& context, const char* name, const char* description, deUint32 internalFormat, deUint32 format, deUint32 dataType, deUint32 swizzleR, deUint32 swizzleG, deUint32 swizzleB, deUint32 swizzleA);
							~Texture2DSwizzleCase	(void);

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

private:
							Texture2DSwizzleCase	(const Texture2DSwizzleCase& other);
	Texture2DSwizzleCase&	operator=				(const Texture2DSwizzleCase& other);

	deUint32				m_internalFormat;
	deUint32				m_format;
	deUint32				m_dataType;
	deUint32				m_swizzleR;
	deUint32				m_swizzleG;
	deUint32				m_swizzleB;
	deUint32				m_swizzleA;

	glu::Texture2D*			m_texture;
	TextureRenderer			m_renderer;
};

Texture2DSwizzleCase::Texture2DSwizzleCase (Context& context, const char* name, const char* description, deUint32 internalFormat, deUint32 format, deUint32 dataType, deUint32 swizzleR, deUint32 swizzleG, deUint32 swizzleB, deUint32 swizzleA)
	: TestCase			(context, name, description)
	, m_internalFormat	(internalFormat)
	, m_format			(format)
	, m_dataType		(dataType)
	, m_swizzleR		(swizzleR)
	, m_swizzleG		(swizzleG)
	, m_swizzleB		(swizzleB)
	, m_swizzleA		(swizzleA)
	, m_texture			(DE_NULL)
	, m_renderer		(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
{
}

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

void Texture2DSwizzleCase::init (void)
{
	int	width	= de::min(128, m_context.getRenderContext().getRenderTarget().getWidth());
	int	height	= de::min(128, m_context.getRenderContext().getRenderTarget().getHeight());

	m_texture = (m_internalFormat == m_format) ? new glu::Texture2D(m_context.getRenderContext(), m_format, m_dataType, width, height)
											   : new glu::Texture2D(m_context.getRenderContext(), m_internalFormat, width, height);

	tcu::TextureFormatInfo spec = tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());

	// Fill level 0.
	m_texture->getRefTexture().allocLevel(0);
	tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), spec.valueMin, spec.valueMax);
}

void Texture2DSwizzleCase::deinit (void)
{
	delete m_texture;
	m_texture = DE_NULL;

	m_renderer.clear();
}

Texture2DSwizzleCase::IterateResult Texture2DSwizzleCase::iterate (void)
{
	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
	TestLog&				log					= m_testCtx.getLog();
	RandomViewport			viewport			(m_context.getRenderContext().getRenderTarget(), m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight(), deStringHash(getName()));
	tcu::Surface			renderedFrame		(viewport.width, viewport.height);
	tcu::Surface			referenceFrame		(viewport.width, viewport.height);
	tcu::RGBA				threshold			= m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
	vector<float>			texCoord;
	ReferenceParams			renderParams		(TEXTURETYPE_2D);
	tcu::TextureFormatInfo	spec				= tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());

	renderParams.samplerType	= getSamplerType(m_texture->getRefTexture().getFormat());
	renderParams.sampler		= tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
	renderParams.colorScale		= spec.lookupScale;
	renderParams.colorBias		= spec.lookupBias;

	computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));

	// Setup base viewport.
	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

	// Upload texture data to GL.
	m_texture->upload();

	// Bind to unit 0.
	gl.activeTexture(GL_TEXTURE0);
	gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());

	// Setup nearest neighbor filtering and clamp-to-edge.
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);

	// Setup texture swizzle.
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R,	m_swizzleR);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G,	m_swizzleG);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B,	m_swizzleB);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A,	m_swizzleA);

	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");

	// Draw.
	m_renderer.renderQuad(0, &texCoord[0], renderParams);
	glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());

	// Compute reference
	{
		const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();

		// Do initial rendering to RGBA8 in order to keep alpha
		sampleTexture(SurfaceAccess(referenceFrame, tcu::PixelFormat(8,8,8,8)), m_texture->getRefTexture(), &texCoord[0], renderParams);

		// Swizzle channels
		swizzle(referenceFrame, m_swizzleR, m_swizzleG, m_swizzleB, m_swizzleA);

		// Convert to destination format
		if (pixelFormat != tcu::PixelFormat(8,8,8,8))
		{
			for (int y = 0; y < referenceFrame.getHeight(); y++)
			{
				for (int x = 0; x < referenceFrame.getWidth(); x++)
				{
					tcu::RGBA p = referenceFrame.getPixel(x, y);
					referenceFrame.setPixel(x, y, pixelFormat.convertColor(p));
				}
			}
		}
	}

	// Compare and log.
	bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);

	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
							isOk ? "Pass"				: "Image comparison failed");

	return STOP;
}

TextureSwizzleTests::TextureSwizzleTests (Context& context)
	: TestCaseGroup(context, "swizzle", "Texture Swizzle Tests")
{
}

TextureSwizzleTests::~TextureSwizzleTests (void)
{
}

void TextureSwizzleTests::init (void)
{
	static const struct
	{
		const char*		name;
		deUint32		internalFormat;
		deUint32		format;
		deUint32		dataType;
	} formats[] =
	{
		{ "alpha",				GL_ALPHA,				GL_ALPHA,			GL_UNSIGNED_BYTE },
		{ "luminance",			GL_LUMINANCE,			GL_LUMINANCE,		GL_UNSIGNED_BYTE },
		{ "luminance_alpha",	GL_LUMINANCE_ALPHA,		GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE },
		{ "red",				GL_R8,					GL_RED,				GL_UNSIGNED_BYTE },
		{ "rg",					GL_RG8,					GL_RG,				GL_UNSIGNED_BYTE },
		{ "rgb",				GL_RGB8,				GL_RGB,				GL_UNSIGNED_BYTE },
		{ "rgba",				GL_RGBA8,				GL_RGBA,			GL_UNSIGNED_BYTE }
	};

	static const struct
	{
		const char*		name;
		deUint32		channel;
	} channels[] =
	{
		{ "r",	GL_TEXTURE_SWIZZLE_R },
		{ "g",	GL_TEXTURE_SWIZZLE_G },
		{ "b",	GL_TEXTURE_SWIZZLE_B },
		{ "a",	GL_TEXTURE_SWIZZLE_A }
	};

	static const struct
	{
		const char*		name;
		deUint32		swizzle;
	} swizzles[] =
	{
		{ "red",		GL_RED		},
		{ "green",		GL_GREEN	},
		{ "blue",		GL_BLUE		},
		{ "alpha",		GL_ALPHA	},
		{ "zero",		GL_ZERO		},
		{ "one",		GL_ONE		}
	};

	static const struct
	{
		const char*		name;
		deUint32		swzR;
		deUint32		swzG;
		deUint32		swzB;
		deUint32		swzA;
	} swizzleCases[] =
	{
		{ "all_red",			GL_RED,		GL_RED,		GL_RED,		GL_RED		},
		{ "all_green",			GL_GREEN,	GL_GREEN,	GL_GREEN,	GL_GREEN	},
		{ "all_blue",			GL_BLUE,	GL_BLUE,	GL_BLUE,	GL_BLUE		},
		{ "all_alpha",			GL_ALPHA,	GL_ALPHA,	GL_ALPHA,	GL_ALPHA	},
		{ "all_zero",			GL_ZERO,	GL_ZERO,	GL_ZERO,	GL_ZERO		},
		{ "all_one",			GL_ONE,		GL_ONE,		GL_ONE,		GL_ONE		},
		{ "bgra",				GL_BLUE,	GL_GREEN,	GL_RED,		GL_ALPHA	},
		{ "abgr",				GL_ALPHA,	GL_BLUE,	GL_GREEN,	GL_RED		},
		{ "one_one_red_green",	GL_ONE,		GL_ONE,		GL_RED,		GL_GREEN	}
	};

	static const deUint32 defaultSwizzles[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };

	// All swizzles applied to each channel.
	tcu::TestCaseGroup* singleChannelGroup = new tcu::TestCaseGroup(m_testCtx, "single_channel", "Single-channel swizzle");
	addChild(singleChannelGroup);
	for (int chanNdx = 0; chanNdx < DE_LENGTH_OF_ARRAY(channels); chanNdx++)
	{
		for (int swzNdx = 0; swzNdx < DE_LENGTH_OF_ARRAY(swizzles); swzNdx++)
		{
			if (swizzles[swzNdx].swizzle == defaultSwizzles[chanNdx])
				continue; // No need to test default case.

			string		name	= string(channels[chanNdx].name) + "_" + swizzles[swzNdx].name;
			deUint32	swz		= swizzles[swzNdx].swizzle;
			deUint32	swzR	= (chanNdx == 0) ? swz : defaultSwizzles[0];
			deUint32	swzG	= (chanNdx == 1) ? swz : defaultSwizzles[1];
			deUint32	swzB	= (chanNdx == 2) ? swz : defaultSwizzles[2];
			deUint32	swzA	= (chanNdx == 3) ? swz : defaultSwizzles[3];

			singleChannelGroup->addChild(new Texture2DSwizzleCase(m_context, name.c_str(), "Single-channel swizzle", GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, swzR, swzG, swzB, swzA));
		}
	}

	// Swizzles for all formats.
	tcu::TestCaseGroup* multiChannelGroup = new tcu::TestCaseGroup(m_testCtx, "multi_channel", "Multi-channel swizzle");
	addChild(multiChannelGroup);
	for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); fmtNdx++)
	{
		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(swizzleCases); caseNdx++)
		{
			string		name		= string(formats[fmtNdx].name) + "_" + swizzleCases[caseNdx].name;
			deUint32	swzR		= swizzleCases[caseNdx].swzR;
			deUint32	swzG		= swizzleCases[caseNdx].swzG;
			deUint32	swzB		= swizzleCases[caseNdx].swzB;
			deUint32	swzA		= swizzleCases[caseNdx].swzA;
			deUint32	intFormat	= formats[fmtNdx].internalFormat;
			deUint32	format		= formats[fmtNdx].format;
			deUint32	dataType	= formats[fmtNdx].dataType;

			multiChannelGroup->addChild(new Texture2DSwizzleCase(m_context, name.c_str(), "Multi-channel swizzle", intFormat, format, dataType, swzR, swzG, swzB, swzA));
		}
	}
}

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