/*-------------------------------------------------------------------------
 * OpenGL Conformance Test Suite
 * -----------------------------
 *
 * Copyright (c) 2020 Valve Coporation.
 * Copyright (c) 2020 The Khronos Group Inc.
 *
 * 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  glcNearestEdgeTests.cpp
 * \brief
 */ /*-------------------------------------------------------------------*/

#include "glcNearestEdgeTests.hpp"

#include "gluDefs.hpp"
#include "gluTextureUtil.hpp"
#include "gluDrawUtil.hpp"
#include "gluShaderProgram.hpp"

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

#include "tcuTestLog.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuTextureUtil.hpp"

#include <utility>
#include <map>
#include <algorithm>
#include <memory>
#include <cmath>

namespace glcts
{

namespace
{

enum class OffsetDirection
{
	LEFT	= 0,
	RIGHT	= 1,
};

// Test sampling at the edge of texels. This test is equivalent to:
//  1) Creating a texture using the same format and size as the frame buffer.
//  2) Drawing a full screen quad with GL_NEAREST using the texture.
//  3) Verifying the frame buffer image and the texture match pixel-by-pixel.
//
// However, texture coodinates are not located in the exact frame buffer corners. A small offset is applied instead so sampling
// happens near a texel border instead of in the middle of the texel.
class NearestEdgeTestCase : public deqp::TestCase
{
public:
	NearestEdgeTestCase(deqp::Context& context, OffsetDirection direction);

	void							deinit();
	void							init();
	tcu::TestNode::IterateResult	iterate();

	static std::string				getName			(OffsetDirection direction);
	static std::string				getDesc			(OffsetDirection direction);
	static tcu::TextureFormat		toTextureFormat	(deqp::Context& context, const tcu::PixelFormat& pixelFmt);

private:
	static const glw::GLenum kTextureType	= GL_TEXTURE_2D;

	void createTexture	();
	void deleteTexture	();
	void fillTexture	();
	void renderQuad		();
	bool verifyResults	();

	const float						m_offsetSign;
	const int						m_width;
	const int						m_height;
	const tcu::PixelFormat&			m_format;
	const tcu::TextureFormat		m_texFormat;
	const tcu::TextureFormatInfo	m_texFormatInfo;
	const glu::TransferFormat		m_transFormat;
	std::string						m_vertShaderText;
	std::string						m_fragShaderText;
	glw::GLuint						m_texture;
	std::vector<deUint8>			m_texData;
};

std::string NearestEdgeTestCase::getName (OffsetDirection direction)
{
	switch (direction)
	{
	case OffsetDirection::LEFT:		return "offset_left";
	case OffsetDirection::RIGHT:	return "offset_right";
	default: DE_ASSERT(false); break;
	}
	// Unreachable.
	return "";
}

std::string NearestEdgeTestCase::getDesc (OffsetDirection direction)
{
	switch (direction)
	{
	case OffsetDirection::LEFT:		return "Sampling point near the left edge";
	case OffsetDirection::RIGHT:	return "Sampling point near the right edge";
	default: DE_ASSERT(false); break;
	}
	// Unreachable.
	return "";
}

// Translate pixel format in the frame buffer to texture format.
// Copied from sglrReferenceContext.cpp.
tcu::TextureFormat NearestEdgeTestCase::toTextureFormat (deqp::Context& context, const tcu::PixelFormat& pixelFmt)
{
	static const struct
	{
		tcu::PixelFormat	pixelFmt;
		tcu::TextureFormat	texFmt;
	} pixelFormatMap[] =
	{
		{ tcu::PixelFormat(8,8,8,8),	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_INT8)				},
		{ tcu::PixelFormat(8,8,8,0),	tcu::TextureFormat(tcu::TextureFormat::RGB,		tcu::TextureFormat::UNORM_INT8)				},
		{ tcu::PixelFormat(4,4,4,4),	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_SHORT_4444)		},
		{ tcu::PixelFormat(5,5,5,1),	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_SHORT_5551)		},
		{ tcu::PixelFormat(5,6,5,0),	tcu::TextureFormat(tcu::TextureFormat::RGB,		tcu::TextureFormat::UNORM_SHORT_565)		},
		{ tcu::PixelFormat(10,10,10,2), tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_INT_1010102_REV)	},
		{ tcu::PixelFormat(16,16,16,16), tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::HALF_FLOAT)				},
	};

	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pixelFormatMap); ndx++)
	{
		if (pixelFormatMap[ndx].pixelFmt == pixelFmt)
		{
			// Some implementations treat GL_RGB8 as GL_RGBA8888,so the test should pass implementation format to ReadPixels.
			if (pixelFmt == tcu::PixelFormat(8, 8, 8, 0))
			{
				const auto& gl = context.getRenderContext().getFunctions();

				glw::GLint implFormat = GL_NONE;
				glw::GLint implType	  = GL_NONE;
				gl.getIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &implFormat);
				gl.getIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &implType);
				if (implFormat == GL_RGBA && implType == GL_UNSIGNED_BYTE)
					return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
			}

			return pixelFormatMap[ndx].texFmt;
		}
	}

	TCU_FAIL("Unable to map pixel format to texture format");
}

NearestEdgeTestCase::NearestEdgeTestCase (deqp::Context& context, OffsetDirection direction)
	: TestCase(context, getName(direction).c_str(), getDesc(direction).c_str())
	, m_offsetSign		{(direction == OffsetDirection::LEFT) ? -1.0f : 1.0f}
	, m_width			{context.getRenderTarget().getWidth()}
	, m_height			{context.getRenderTarget().getHeight()}
	, m_format			{context.getRenderTarget().getPixelFormat()}
	, m_texFormat		{toTextureFormat(context, m_format)}
	, m_texFormatInfo	{tcu::getTextureFormatInfo(m_texFormat)}
	, m_transFormat		{glu::getTransferFormat(m_texFormat)}
	, m_texture			(0)
{
}

void NearestEdgeTestCase::deinit()
{
}

void NearestEdgeTestCase::init()
{
	if (m_width < 2 || m_height < 2)
		TCU_THROW(NotSupportedError, "Render target size too small");

	m_vertShaderText =
        "#version ${VERSION}\n"
        "\n"
        "in highp vec2 position;\n"
        "\n"
        "void main()\n"
        "{\n"
        "    gl_Position = vec4(position, 0.0, 1.0);\n"
        "}\n"
        ;
    m_fragShaderText =
        "#version ${VERSION}\n"
        "\n"
        "precision highp float;\n"
        "out highp vec4 fragColor;\n"
        "\n"
        "uniform highp sampler2D texSampler;\n"
        "uniform float texOffset;\n"
        "uniform float texWidth;\n"
        "uniform float texHeight;\n"
        "\n"
        "void main()\n"
        "{\n"
        "    float texCoordX;\n"
        "    float texCoordY;\n"
        "    texCoordX = (gl_FragCoord.x + texOffset) / texWidth;\n "
        "    texCoordY = (gl_FragCoord.y + texOffset) / texHeight;\n"
        "    vec2 sampleCoord = vec2(texCoordX, texCoordY);\n"
        "    fragColor = texture(texSampler, sampleCoord);\n"
        "}\n"
        "\n";

	tcu::StringTemplate vertShaderTemplate{m_vertShaderText};
	tcu::StringTemplate fragShaderTemplate{m_fragShaderText};
	std::map<std::string, std::string> replacements;

	if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
		replacements["VERSION"] = "130";
	else
		replacements["VERSION"] = "300 es";

	m_vertShaderText = vertShaderTemplate.specialize(replacements);
	m_fragShaderText = fragShaderTemplate.specialize(replacements);
}

void NearestEdgeTestCase::createTexture ()
{
	const auto& gl = m_context.getRenderContext().getFunctions();

	gl.genTextures(1, &m_texture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures");
	gl.bindTexture(kTextureType, m_texture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");

	gl.texParameteri(kTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
	gl.texParameteri(kTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
	gl.texParameteri(kTextureType, GL_TEXTURE_WRAP_S, GL_REPEAT);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
	gl.texParameteri(kTextureType, GL_TEXTURE_WRAP_T, GL_REPEAT);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
	gl.texParameteri(kTextureType, GL_TEXTURE_MAX_LEVEL, 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
}

void NearestEdgeTestCase::deleteTexture ()
{
	const auto& gl = m_context.getRenderContext().getFunctions();

	gl.deleteTextures(1, &m_texture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
}

void NearestEdgeTestCase::fillTexture ()
{
	const auto& gl = m_context.getRenderContext().getFunctions();

	m_texData.resize(m_width * m_height * tcu::getPixelSize(m_texFormat));
	tcu::PixelBufferAccess texAccess{m_texFormat, m_width, m_height, 1, m_texData.data()};

	// Create gradient over the whole texture.
	DE_ASSERT(m_width > 1);
	DE_ASSERT(m_height > 1);

	const float divX = static_cast<float>(m_width - 1);
	const float divY = static_cast<float>(m_height - 1);

	for (int x = 0; x < m_width; ++x)
	for (int y = 0; y < m_height; ++y)
	{
		const float colorX = static_cast<float>(x) / divX;
		const float colorY = static_cast<float>(y) / divY;
		const float colorZ = std::min(colorX, colorY);

		tcu::Vec4 color{colorX, colorY, colorZ, 1.0f};
		tcu::Vec4 finalColor = (color - m_texFormatInfo.lookupBias) / m_texFormatInfo.lookupScale;
		texAccess.setPixel(finalColor, x, y);
	}

	const auto internalFormat = glu::getInternalFormat(m_texFormat);
	if (tcu::getPixelSize(m_texFormat) < 4)
		gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
	gl.texImage2D(kTextureType, 0, internalFormat, m_width,  m_height, 0 /* border */, m_transFormat.format, m_transFormat.dataType, m_texData.data());
	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D");
}

// Draw full screen quad with the texture and an offset of almost half a texel in one direction, so sampling happens near the texel
// border and verifies truncation is happening properly.
void NearestEdgeTestCase::renderQuad ()
{
	const auto& renderContext	= m_context.getRenderContext();
	const auto& gl				= renderContext.getFunctions();

	float minU = 0.0f;
	float maxU = 1.0f;
	float minV = 0.0f;
	float maxV = 1.0f;

	// Apply offset of almost half a texel to the texture coordinates.
	DE_ASSERT(m_offsetSign == 1.0f || m_offsetSign == -1.0f);

	const float offset			= 0.5f - pow(2.0f, -8.0f);
	const float offsetWidth		= offset / static_cast<float>(m_width);
	const float offsetHeight	= offset / static_cast<float>(m_height);

	minU += m_offsetSign * offsetWidth;
	maxU += m_offsetSign * offsetWidth;
	minV += m_offsetSign * offsetHeight;
	maxV += m_offsetSign * offsetHeight;

	const std::vector<float>	positions	= { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f };
	const std::vector<float>	texCoords	= { minU, minV, minU, maxV, maxU, minV, maxU, maxV };
	const std::vector<deUint16>	quadIndices	= { 0, 1, 2, 2, 1, 3 };

	const std::vector<glu::VertexArrayBinding> vertexArrays =
	{
		glu::va::Float("position", 2, 4, 0, positions.data())
	};

	glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(m_vertShaderText, m_fragShaderText));
	if (!program.isOk())
		TCU_FAIL("Shader compilation failed");

	gl.useProgram(program.getProgram());
	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed");

	gl.uniform1i(gl.getUniformLocation(program.getProgram(), "texSampler"), 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i failed");

	gl.uniform1f(gl.getUniformLocation(program.getProgram(), "texOffset"), m_offsetSign * offset);
	gl.uniform1f(gl.getUniformLocation(program.getProgram(), "texWidth"), float(m_width));
	gl.uniform1f(gl.getUniformLocation(program.getProgram(), "texHeight"), float(m_height));
	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i failed");

	gl.disable(GL_DITHER);
	gl.clear(GL_COLOR_BUFFER_BIT);

	glu::draw(renderContext, program.getProgram(),
			  static_cast<int>(vertexArrays.size()), vertexArrays.data(),
			  glu::pr::TriangleStrip(static_cast<int>(quadIndices.size()), quadIndices.data()));
}

bool NearestEdgeTestCase::verifyResults ()
{
	const auto& gl = m_context.getRenderContext().getFunctions();

	std::vector<deUint8> fbData(m_width * m_height * tcu::getPixelSize(m_texFormat));
	if (tcu::getPixelSize(m_texFormat) < 4)
		gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
	gl.readPixels(0, 0, m_width, m_height, m_transFormat.format, m_transFormat.dataType, fbData.data());
	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");

	tcu::ConstPixelBufferAccess texAccess	{m_texFormat, m_width, m_height, 1, m_texData.data()};
	tcu::ConstPixelBufferAccess fbAccess	{m_texFormat, m_width, m_height, 1, fbData.data()};

	// Difference image to ease spotting problems.
	const tcu::TextureFormat		diffFormat	{tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8};
	const auto						diffBytes	= tcu::getPixelSize(diffFormat) * m_width * m_height;
	std::unique_ptr<deUint8[]>		diffData	{new deUint8[diffBytes]};
	const tcu::PixelBufferAccess	diffAccess	{diffFormat, m_width, m_height, 1, diffData.get()};

	const tcu::Vec4					colorRed	{1.0f, 0.0f, 0.0f, 1.0f};
	const tcu::Vec4					colorGreen	{0.0f, 1.0f, 0.0f, 1.0f};

	bool pass = true;
	for (int x = 0; x < m_width; ++x)
	for (int y = 0; y < m_height; ++y)
	{
		const auto texPixel	= texAccess.getPixel(x, y);
		const auto fbPixel	= fbAccess.getPixel(x, y);

		// Require perfect pixel match.
		if (texPixel != fbPixel)
		{
			pass = false;
			diffAccess.setPixel(colorRed, x, y);
		}
		else
		{
			diffAccess.setPixel(colorGreen, x, y);
		}
	}

	if (!pass)
	{
		auto& log = m_testCtx.getLog();
		log
			<< tcu::TestLog::Message << "\n"
			<< "Width:       " << m_width << "\n"
			<< "Height:      " << m_height << "\n"
			<< tcu::TestLog::EndMessage;

		log << tcu::TestLog::Image("texture", "Generated Texture", texAccess);
		log << tcu::TestLog::Image("fb", "Frame Buffer Contents", fbAccess);
		log << tcu::TestLog::Image("diff", "Mismatched pixels in red", diffAccess);
	}

	return pass;
}

tcu::TestNode::IterateResult NearestEdgeTestCase::iterate ()
{
	// Populate and configure m_texture.
	createTexture();

	// Fill m_texture with data.
	fillTexture();

	// Draw full screen quad using the texture and a slight offset left or right.
	renderQuad();

	// Verify results.
	bool pass = verifyResults();

	// Destroy texture.
	deleteTexture();

	const qpTestResult	result	= (pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL);
	const char*			desc	= (pass ? "Pass" : "Pixel mismatch; check the generated images");

	m_testCtx.setTestResult(result, desc);
	return STOP;
}

} /* anonymous namespace */

NearestEdgeCases::NearestEdgeCases(deqp::Context& context)
	: TestCaseGroup(context, "nearest_edge", "GL_NEAREST edge cases")
{
}

NearestEdgeCases::~NearestEdgeCases(void)
{
}

void NearestEdgeCases::init(void)
{
	static const std::vector<OffsetDirection> kDirections = { OffsetDirection::LEFT, OffsetDirection::RIGHT };
	for (const auto direction : kDirections)
		addChild(new NearestEdgeTestCase{m_context, direction});
}

} /* glcts namespace */
