/*-------------------------------------------------------------------------
 * drawElements Internal Test Module
 * ---------------------------------
 *
 * Copyright 2016 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 ASTC tests.
 *//*--------------------------------------------------------------------*/

#include "ditAstcTests.hpp"

#include "tcuCompressedTexture.hpp"
#include "tcuAstcUtil.hpp"

#include "deUniquePtr.hpp"
#include "deStringUtil.hpp"

namespace dit
{

using std::string;
using std::vector;
using namespace tcu;

namespace
{

class AstcCase : public tcu::TestCase
{
public:
								AstcCase		(tcu::TestContext& testCtx, CompressedTexFormat format);

	IterateResult				iterate			(void);

private:
	const CompressedTexFormat	m_format;
};

static const string getASTCFormatShortName (CompressedTexFormat format)
{
	DE_ASSERT(isAstcFormat(format));
	const IVec3 blockSize = getBlockPixelSize(format);
	DE_ASSERT(blockSize.z() == 1);

	return de::toString(blockSize.x()) + "x" + de::toString(blockSize.y()) + (tcu::isAstcSRGBFormat(format) ? "_srgb" : "");
}

AstcCase::AstcCase (tcu::TestContext& testCtx, CompressedTexFormat format)
	: tcu::TestCase	(testCtx, getASTCFormatShortName(format).c_str(), "")
	, m_format		(format)
{
}

void testDecompress (CompressedTexFormat format, TexDecompressionParams::AstcMode mode, size_t numBlocks, const deUint8* data)
{
	const IVec3						blockPixelSize			= getBlockPixelSize(format);
	const TexDecompressionParams	decompressionParams		(mode);
	const TextureFormat				uncompressedFormat		= getUncompressedFormat(format);
	TextureLevel					texture					(uncompressedFormat, blockPixelSize.x()*(int)numBlocks, blockPixelSize.y());

	decompress(texture.getAccess(), format, data, decompressionParams);
}

void testDecompress (CompressedTexFormat format, size_t numBlocks, const deUint8* data)
{
	testDecompress(format, TexDecompressionParams::ASTCMODE_LDR, numBlocks, data);

	if (!isAstcSRGBFormat(format))
		testDecompress(format, TexDecompressionParams::ASTCMODE_HDR, numBlocks, data);
}

void verifyBlocksValid (CompressedTexFormat format, TexDecompressionParams::AstcMode mode, size_t numBlocks, const deUint8* data)
{
	for (size_t blockNdx = 0; blockNdx < numBlocks; blockNdx++)
	{
		if (!astc::isValidBlock(data + blockNdx*astc::BLOCK_SIZE_BYTES, format, mode))
			TCU_FAIL("Invalid ASTC block was generated");
	}
}

inline size_t getNumBlocksFromBytes (size_t numBytes)
{
	TCU_CHECK(numBytes % astc::BLOCK_SIZE_BYTES == 0);
	return (numBytes / astc::BLOCK_SIZE_BYTES);
}

AstcCase::IterateResult AstcCase::iterate (void)
{
	vector<deUint8> generatedData;

	// Verify that can generate & decode data with all BlockTestType's
	for (int blockTestTypeNdx = 0; blockTestTypeNdx < astc::BLOCK_TEST_TYPE_LAST; blockTestTypeNdx++)
	{
		const astc::BlockTestType	blockTestType	= (astc::BlockTestType)blockTestTypeNdx;

		if (astc::isBlockTestTypeHDROnly(blockTestType) && isAstcSRGBFormat(m_format))
			continue;

		generatedData.clear();
		astc::generateBlockCaseTestData(generatedData, m_format, blockTestType);

		testDecompress(m_format, getNumBlocksFromBytes(generatedData.size()), &generatedData[0]);

		// All but random case should generate only valid blocks
		if (blockTestType != astc::BLOCK_TEST_TYPE_RANDOM)
		{
			// \note CEMS generates HDR blocks as well
			if (!astc::isBlockTestTypeHDROnly(blockTestType) &&
				(blockTestType != astc::BLOCK_TEST_TYPE_CEMS))
				verifyBlocksValid(m_format, TexDecompressionParams::ASTCMODE_LDR, getNumBlocksFromBytes(generatedData.size()), &generatedData[0]);

			if (!isAstcSRGBFormat(m_format))
				verifyBlocksValid(m_format, TexDecompressionParams::ASTCMODE_HDR, getNumBlocksFromBytes(generatedData.size()), &generatedData[0]);
		}
	}

	// Verify generating void extent blocks (format-independent)
	{
		const size_t		numBlocks		= 1024;

		generatedData.resize(numBlocks*astc::BLOCK_SIZE_BYTES);
		astc::generateDefaultVoidExtentBlocks(&generatedData[0], numBlocks);

		testDecompress(m_format, numBlocks, &generatedData[0]);

		verifyBlocksValid(m_format, TexDecompressionParams::ASTCMODE_LDR, numBlocks, &generatedData[0]);

		if (!isAstcSRGBFormat(m_format))
			verifyBlocksValid(m_format, TexDecompressionParams::ASTCMODE_HDR, numBlocks, &generatedData[0]);
	}

	// Verify generating unused normal blocks
	{
		const size_t		numBlocks			= 1024;
		const IVec3			blockPixelSize		= getBlockPixelSize(m_format);

		generatedData.resize(numBlocks*astc::BLOCK_SIZE_BYTES);
		astc::generateDefaultNormalBlocks(&generatedData[0], numBlocks, blockPixelSize.x(), blockPixelSize.y());

		testDecompress(m_format, numBlocks, &generatedData[0]);

		verifyBlocksValid(m_format, TexDecompressionParams::ASTCMODE_LDR, numBlocks, &generatedData[0]);

		if (!isAstcSRGBFormat(m_format))
			verifyBlocksValid(m_format, TexDecompressionParams::ASTCMODE_HDR, numBlocks, &generatedData[0]);
	}

	// Verify generating random valid blocks
	for (int astcModeNdx = 0; astcModeNdx < TexDecompressionParams::ASTCMODE_LAST; astcModeNdx++)
	{
		const TexDecompressionParams::AstcMode	mode		= (TexDecompressionParams::AstcMode)astcModeNdx;
		const size_t							numBlocks	= 1024;

		if (mode == tcu::TexDecompressionParams::ASTCMODE_HDR && isAstcFormat(m_format))
			continue; // sRGB is not supported in HDR mode

		generatedData.resize(numBlocks*astc::BLOCK_SIZE_BYTES);
		astc::generateRandomValidBlocks(&generatedData[0], numBlocks, m_format, mode, deInt32Hash(m_format) ^ deInt32Hash(mode));

		testDecompress(m_format, numBlocks, &generatedData[0]);

		verifyBlocksValid(m_format, mode, numBlocks, &generatedData[0]);
	}

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "All checks passed");
	return STOP;
}

} // anonymous

tcu::TestCaseGroup* createAstcTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup>	astcTests	(new tcu::TestCaseGroup(testCtx, "astc", "Tests for ASTC Utilities"));

	for (int formatNdx = 0; formatNdx < COMPRESSEDTEXFORMAT_LAST; formatNdx++)
	{
		const CompressedTexFormat	format	= (CompressedTexFormat)formatNdx;

		if (isAstcFormat(format))
			astcTests->addChild(new AstcCase(testCtx, format));
	}

	return astcTests.release();
}

} // dit
