/*-------------------------------------------------------------------------
 * 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 uint8_t *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 uint8_t *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 uint8_t *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<uint8_t> 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::generateDummyVoidExtentBlocks(&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 dummy normal blocks
    {
        const size_t numBlocks     = 1024;
        const IVec3 blockPixelSize = getBlockPixelSize(m_format);

        generatedData.resize(numBlocks * astc::BLOCK_SIZE_BYTES);
        astc::generateDummyNormalBlocks(&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;
}

} // namespace

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();
}

} // namespace dit
