/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmap.h"
#include "SkData.h"
#include "SkEndian.h"
#include "SkImageInfo.h"
#include "SkTextureCompressor.h"
#include "Test.h"

/**
 * Make sure that we properly fail when we don't have multiple of four image dimensions.
 */
DEF_TEST(CompressAlphaFailDimensions, reporter) {
    SkBitmap bitmap;
    static const int kWidth = 17;
    static const int kHeight = 17;
    SkImageInfo info = SkImageInfo::MakeA8(kWidth, kHeight);

    // R11_EAC and LATC are both dimensions of 4, so we need to make sure that we
    // are violating those assumptions. And if we are, then we're also violating the
    // assumptions of ASTC, which is 12x12 since any number not divisible by 4 is
    // also not divisible by 12. Our dimensions are prime, so any block dimension
    // larger than 1 should fail.
    REPORTER_ASSERT(reporter, kWidth % 4 != 0);
    REPORTER_ASSERT(reporter, kHeight % 4 != 0);

    bool setInfoSuccess = bitmap.setInfo(info);
    REPORTER_ASSERT(reporter, setInfoSuccess);

    bool allocPixelsSuccess = bitmap.allocPixels(info);
    REPORTER_ASSERT(reporter, allocPixelsSuccess);
    bitmap.unlockPixels();
    
    for (int i = 0; i < SkTextureCompressor::kFormatCnt; ++i) {
        const SkTextureCompressor::Format fmt = static_cast<SkTextureCompressor::Format>(i);
        SkAutoDataUnref data(SkTextureCompressor::CompressBitmapToFormat(bitmap, fmt));
        REPORTER_ASSERT(reporter, NULL == data);
    }
}

/**
 * Make sure that we properly fail when we don't have the correct bitmap type.
 * compressed textures can (currently) only be created from A8 bitmaps.
 */
DEF_TEST(CompressAlphaFailColorType, reporter) {
    SkBitmap bitmap;
    static const int kWidth = 12;
    static const int kHeight = 12;
    SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);

    // ASTC is at most 12x12, and any dimension divisible by 12 is also divisible
    // by 4, which is the dimensions of R11_EAC and LATC. In the future, we might
    // support additional variants of ASTC, such as 5x6 and 8x8, in which case this would
    // need to be updated.
    REPORTER_ASSERT(reporter, kWidth % 12 == 0);
    REPORTER_ASSERT(reporter, kHeight % 12 == 0);

    bool setInfoSuccess = bitmap.setInfo(info);
    REPORTER_ASSERT(reporter, setInfoSuccess);

    bool allocPixelsSuccess = bitmap.allocPixels(info);
    REPORTER_ASSERT(reporter, allocPixelsSuccess);
    bitmap.unlockPixels();

    for (int i = 0; i < SkTextureCompressor::kFormatCnt; ++i) {
        const SkTextureCompressor::Format fmt = static_cast<SkTextureCompressor::Format>(i);
        SkAutoDataUnref data(SkTextureCompressor::CompressBitmapToFormat(bitmap, fmt));
        REPORTER_ASSERT(reporter, NULL == data);
    }
}

/**
 * Make sure that if you compress a texture with alternating black/white pixels, and
 * then decompress it, you get what you started with.
 */
DEF_TEST(CompressCheckerboard, reporter) {
    SkBitmap bitmap;
    static const int kWidth = 48;  // We need the number to be divisible by both
    static const int kHeight = 48; // 12 (ASTC) and 16 (ARM NEON R11 EAC).
    SkImageInfo info = SkImageInfo::MakeA8(kWidth, kHeight);

    // ASTC is at most 12x12, and any dimension divisible by 12 is also divisible
    // by 4, which is the dimensions of R11_EAC and LATC. In the future, we might
    // support additional variants of ASTC, such as 5x6 and 8x8, in which case this would
    // need to be updated. Additionally, ARM NEON and SSE code paths support up to
    // four blocks of R11 EAC at once, so they operate on 16-wide blocks. Hence, the
    // valid width and height is going to be the LCM of 12 and 16 which is 4*4*3 = 48
    REPORTER_ASSERT(reporter, kWidth % 48 == 0);
    REPORTER_ASSERT(reporter, kHeight % 48 == 0);

    bool setInfoSuccess = bitmap.setInfo(info);
    REPORTER_ASSERT(reporter, setInfoSuccess);

    bool allocPixelsSuccess = bitmap.allocPixels(info);
    REPORTER_ASSERT(reporter, allocPixelsSuccess);
    bitmap.unlockPixels();

    // Populate bitmap
    {
        SkAutoLockPixels alp(bitmap);

        uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap.getPixels());
        REPORTER_ASSERT(reporter, NULL != pixels);
        if (NULL == pixels) {
            return;
        }

        for (int y = 0; y < kHeight; ++y) {
            for (int x = 0; x < kWidth; ++x) {
                if ((x ^ y) & 1) {
                    pixels[x] = 0xFF;
                } else {
                    pixels[x] = 0;
                }
            }
            pixels += bitmap.rowBytes();
        }
    }

    SkAutoMalloc decompMemory(kWidth*kHeight);
    uint8_t* decompBuffer = reinterpret_cast<uint8_t*>(decompMemory.get());
    REPORTER_ASSERT(reporter, NULL != decompBuffer);
    if (NULL == decompBuffer) {
        return;
    }

    for (int i = 0; i < SkTextureCompressor::kFormatCnt; ++i) {
        const SkTextureCompressor::Format fmt = static_cast<SkTextureCompressor::Format>(i);

        // ASTC is for RGBA data, and the decompressed buffer
        // won't match the size and contents of the original.
        // TODO: Create separate tests for RGB and RGBA data once
        // ASTC decompression is implemented.
        if (SkTextureCompressor::kASTC_12x12_Format == fmt) {
            continue;
        }

        SkAutoDataUnref data(SkTextureCompressor::CompressBitmapToFormat(bitmap, fmt));
        REPORTER_ASSERT(reporter, NULL != data);
        if (NULL == data) {
            continue;
        }

        bool decompResult =
            SkTextureCompressor::DecompressBufferFromFormat(
                decompBuffer, kWidth,
                data->bytes(),
                kWidth, kHeight, fmt);
        REPORTER_ASSERT(reporter, decompResult);

        SkAutoLockPixels alp(bitmap);
        uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap.getPixels());
        REPORTER_ASSERT(reporter, NULL != pixels);
        if (NULL == pixels) {
            continue;
        }

        for (int y = 0; y < kHeight; ++y) {
            for (int x = 0; x < kWidth; ++x) {
                bool ok = pixels[y*bitmap.rowBytes() + x] == decompBuffer[y*kWidth + x];
                REPORTER_ASSERT(reporter, ok);
            }
        }
    }
}

/**
 * Make sure that if we pass in a solid color bitmap that we get the appropriate results
 */
DEF_TEST(CompressLATC, reporter) {

    const SkTextureCompressor::Format kLATCFormat = SkTextureCompressor::kLATC_Format;
    static const int kLATCEncodedBlockSize = 8;

    SkBitmap bitmap;
    static const int kWidth = 8;
    static const int kHeight = 8;
    SkImageInfo info = SkImageInfo::MakeA8(kWidth, kHeight);

    bool setInfoSuccess = bitmap.setInfo(info);
    REPORTER_ASSERT(reporter, setInfoSuccess);

    bool allocPixelsSuccess = bitmap.allocPixels(info);
    REPORTER_ASSERT(reporter, allocPixelsSuccess);
    bitmap.unlockPixels();

    int latcDimX, latcDimY;
    SkTextureCompressor::GetBlockDimensions(kLATCFormat, &latcDimX, &latcDimY);

    REPORTER_ASSERT(reporter, kWidth % latcDimX == 0);
    REPORTER_ASSERT(reporter, kHeight % latcDimY == 0);
    const size_t kSizeToBe =
        SkTextureCompressor::GetCompressedDataSize(kLATCFormat, kWidth, kHeight);
    REPORTER_ASSERT(reporter, kSizeToBe == ((kWidth*kHeight*kLATCEncodedBlockSize)/16));
    REPORTER_ASSERT(reporter, (kSizeToBe % kLATCEncodedBlockSize) == 0);

    for (int lum = 0; lum < 256; ++lum) {
        bitmap.lockPixels();
        uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap.getPixels());
        REPORTER_ASSERT(reporter, NULL != pixels);
        if (NULL == pixels) {
            bitmap.unlockPixels();
            continue;
        }

        for (int i = 0; i < kWidth*kHeight; ++i) {
            pixels[i] = lum;
        }
        bitmap.unlockPixels();

        SkAutoDataUnref latcData(
            SkTextureCompressor::CompressBitmapToFormat(bitmap, kLATCFormat));
        REPORTER_ASSERT(reporter, NULL != latcData);
        if (NULL == latcData) {
            continue;
        }

        REPORTER_ASSERT(reporter, kSizeToBe == latcData->size());

        // Make sure that it all matches a given block encoding. Since we have
        // COMPRESS_LATC_FAST defined in SkTextureCompressor_LATC.cpp, we are using
        // an approximation scheme that optimizes for speed against coverage maps.
        // That means that each palette in the encoded block is exactly the same,
        // and that the three bits saved per pixel are computed from the top three
        // bits of the luminance value.
        const uint64_t kIndexEncodingMap[8] = { 1, 7, 6, 5, 4, 3, 2, 0 };
        const uint64_t kIndex = kIndexEncodingMap[lum >> 5];
        const uint64_t kConstColorEncoding =
            SkEndian_SwapLE64(
                255 |
                (kIndex << 16) | (kIndex << 19) | (kIndex << 22) | (kIndex << 25) |
                (kIndex << 28) | (kIndex << 31) | (kIndex << 34) | (kIndex << 37) |
                (kIndex << 40) | (kIndex << 43) | (kIndex << 46) | (kIndex << 49) |
                (kIndex << 52) | (kIndex << 55) | (kIndex << 58) | (kIndex << 61));

        const uint64_t* blockPtr = reinterpret_cast<const uint64_t*>(latcData->data());
        for (size_t i = 0; i < (kSizeToBe/8); ++i) {
            REPORTER_ASSERT(reporter, blockPtr[i] == kConstColorEncoding);
        }
    }
}
