/*-------------------------------------------------------------------------
 * 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)}
{
}

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 */
