/*
 * 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 "SkTextureCompressor.h"
#include "SkTextureCompressor_ASTC.h"
#include "SkTextureCompressor_LATC.h"
#include "SkTextureCompressor_R11EAC.h"

#include "SkBitmap.h"
#include "SkBitmapProcShader.h"
#include "SkData.h"
#include "SkEndian.h"

#include "SkTextureCompression_opts.h"

#ifndef SK_IGNORE_ETC1_SUPPORT
#  include "etc1.h"
#endif

// Convert ETC1 functions to our function signatures
static bool compress_etc1_565(uint8_t* dst, const uint8_t* src,
                              int width, int height, size_t rowBytes) {
#ifndef SK_IGNORE_ETC1_SUPPORT
    return 0 == etc1_encode_image(src, width, height, 2, SkToInt(rowBytes), dst);
#else
    return false;
#endif
}

////////////////////////////////////////////////////////////////////////////////

namespace SkTextureCompressor {

void GetBlockDimensions(Format format, int* dimX, int* dimY, bool matchSpec) {
    if (NULL == dimX || NULL == dimY) {
        return;
    }

    if (!matchSpec && SkTextureCompressorGetPlatformDims(format, dimX, dimY)) {
        return;
    }

    // No specialized arguments, return the dimensions as they are in the spec.
    static const struct FormatDimensions {
        const int fBlockSizeX;
        const int fBlockSizeY;
    } kFormatDimensions[kFormatCnt] = {
        { 4, 4 }, // kLATC_Format
        { 4, 4 }, // kR11_EAC_Format
        { 4, 4 }, // kETC1_Format
        { 4, 4 }, // kASTC_4x4_Format
        { 5, 4 }, // kASTC_5x4_Format
        { 5, 5 }, // kASTC_5x5_Format
        { 6, 5 }, // kASTC_6x5_Format
        { 6, 6 }, // kASTC_6x6_Format
        { 8, 5 }, // kASTC_8x5_Format
        { 8, 6 }, // kASTC_8x6_Format
        { 8, 8 }, // kASTC_8x8_Format
        { 10, 5 }, // kASTC_10x5_Format
        { 10, 6 }, // kASTC_10x6_Format
        { 10, 8 }, // kASTC_10x8_Format
        { 10, 10 }, // kASTC_10x10_Format
        { 12, 10 }, // kASTC_12x10_Format
        { 12, 12 }, // kASTC_12x12_Format
    };

    *dimX = kFormatDimensions[format].fBlockSizeX;
    *dimY = kFormatDimensions[format].fBlockSizeY;
}

int GetCompressedDataSize(Format fmt, int width, int height) {
    int dimX, dimY;
    GetBlockDimensions(fmt, &dimX, &dimY, true);

    int encodedBlockSize = 0;
            
    switch (fmt) {
        // These formats are 64 bits per 4x4 block.
        case kLATC_Format:
        case kR11_EAC_Format:
        case kETC1_Format:
            encodedBlockSize = 8;
            break;

        // This format is 128 bits.
        case kASTC_4x4_Format:
        case kASTC_5x4_Format:
        case kASTC_5x5_Format:
        case kASTC_6x5_Format:
        case kASTC_6x6_Format:
        case kASTC_8x5_Format:
        case kASTC_8x6_Format:
        case kASTC_8x8_Format:
        case kASTC_10x5_Format:
        case kASTC_10x6_Format:
        case kASTC_10x8_Format:
        case kASTC_10x10_Format:
        case kASTC_12x10_Format:
        case kASTC_12x12_Format:
            encodedBlockSize = 16;
            break;

        default:
            SkFAIL("Unknown compressed format!");
            return -1;
    }

    if(((width % dimX) == 0) && ((height % dimY) == 0)) {
        const int blocksX = width / dimX;
        const int blocksY = height / dimY;

        return blocksX * blocksY * encodedBlockSize;
    }

    return -1;
}

bool CompressBufferToFormat(uint8_t* dst, const uint8_t* src, SkColorType srcColorType,
                            int width, int height, size_t rowBytes, Format format, bool opt) {
    CompressionProc proc = NULL;
    if (opt) {
        proc = SkTextureCompressorGetPlatformProc(srcColorType, format);
    }

    if (NULL == proc) {
        switch (srcColorType) {
            case kAlpha_8_SkColorType:
            {
                switch (format) {
                    case kLATC_Format:
                        proc = CompressA8ToLATC;
                        break;
                    case kR11_EAC_Format:
                        proc = CompressA8ToR11EAC;
                        break;
                    case kASTC_12x12_Format:
                        proc = CompressA8To12x12ASTC;
                        break;
                    default:
                        // Do nothing...
                        break;
                }
            }
            break;

            case kRGB_565_SkColorType:
            {
                switch (format) {
                    case kETC1_Format:
                        proc = compress_etc1_565;
                        break;
                    default:
                        // Do nothing...
                        break;
                }
            }
            break;

            default:
                // Do nothing...
                break;
        }
    }

    if (proc) {
        return proc(dst, src, width, height, rowBytes);
    }

    return false;
}

SkData* CompressBitmapToFormat(const SkBitmap &bitmap, Format format) {
    SkAutoLockPixels alp(bitmap);

    int compressedDataSize = GetCompressedDataSize(format, bitmap.width(), bitmap.height());
    if (compressedDataSize < 0) {
        return NULL;
    }

    const uint8_t* src = reinterpret_cast<const uint8_t*>(bitmap.getPixels());
    SkData* dst = SkData::NewUninitialized(compressedDataSize);

    if (!CompressBufferToFormat((uint8_t*)dst->writable_data(), src, bitmap.colorType(),
                                bitmap.width(), bitmap.height(), bitmap.rowBytes(), format)) {
        dst->unref();
        dst = NULL;
    }
    return dst;
}

SkBlitter* CreateBlitterForFormat(int width, int height, void* compressedBuffer,
                                  SkTBlitterAllocator *allocator, Format format) {
    switch(format) {
        case kLATC_Format:
            return CreateLATCBlitter(width, height, compressedBuffer, allocator);

        case kR11_EAC_Format:
            return CreateR11EACBlitter(width, height, compressedBuffer, allocator);

        case kASTC_12x12_Format:
            return CreateASTCBlitter(width, height, compressedBuffer, allocator);

        default:
            return NULL;
    }

    return NULL;
}

bool DecompressBufferFromFormat(uint8_t* dst, int dstRowBytes, const uint8_t* src,
                                int width, int height, Format format) {
    int dimX, dimY;
    GetBlockDimensions(format, &dimX, &dimY, true);

    if (width < 0 || ((width % dimX) != 0) || height < 0 || ((height % dimY) != 0)) {
        return false;
    }

    switch(format) {
        case kLATC_Format:
            DecompressLATC(dst, dstRowBytes, src, width, height);
            return true;

        case kR11_EAC_Format:
            DecompressR11EAC(dst, dstRowBytes, src, width, height);
            return true;

#ifndef SK_IGNORE_ETC1_SUPPORT
        case kETC1_Format:
            return 0 == etc1_decode_image(src, dst, width, height, 3, dstRowBytes);
#endif

        case kASTC_4x4_Format:
        case kASTC_5x4_Format:
        case kASTC_5x5_Format:
        case kASTC_6x5_Format:
        case kASTC_6x6_Format:
        case kASTC_8x5_Format:
        case kASTC_8x6_Format:
        case kASTC_8x8_Format:
        case kASTC_10x5_Format:
        case kASTC_10x6_Format:
        case kASTC_10x8_Format:
        case kASTC_10x10_Format:
        case kASTC_12x10_Format:
        case kASTC_12x12_Format:
            DecompressASTC(dst, dstRowBytes, src, width, height, dimX, dimY);
            return true;

        default:
            // Do nothing...
            break;
    }

    return false;
}

}  // namespace SkTextureCompressor
