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

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkImage.h"
#include "include/gpu/GrContext.h"
#include "include/private/GrRecordingContext.h"
#include "src/core/SkCompressedDataUtils.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/image/SkImage_Base.h"

constexpr int kImgWidth  = 16;
constexpr int kImgHeight = 8;
constexpr int kPad       = 4;

struct BC1Block {
    uint16_t fColor0;
    uint16_t fColor1;
    uint32_t fIndices;
};

static int num_4x4_blocks(int size) {
    return ((size + 3) & ~3) >> 2;
}

static uint16_t to565(SkColor col) {
    int r5 = SkMulDiv255Round(31, SkColorGetR(col));
    int g6 = SkMulDiv255Round(63, SkColorGetG(col));
    int b5 = SkMulDiv255Round(31, SkColorGetB(col));

    return (r5 << 11) | (g6 << 5) | b5;
}

// BC1 has per-block transparency. If, taken as ints,
//    fColor0 < fColor1    -> the block has transparency (& it is in color3)
//    fColor1 > fColor0    -> the block is opaque
//
// This method can create two blocks to test out BC1's behavior. If BC1
// behaves as expected (i.e., w/ per-block transparency) then, for RGBA textures,
// the transparent block(s) should appear as:
//    opaque black, medium grey, transparent black, white.
// and the opaque block(s) should appear as:
//    opaque black, dark grey, light grey, white
//
// For RGB textures, however, the transparent block(s) should appear as:
//    opaque black, medium grey, _opaque_ black, white
// and the opaque block(s) should appear as:
//    opaque black, dark grey, light grey, white.
static void create_BC1_block(BC1Block* block, bool transparent) {
    unsigned int byte;

    if (transparent) {
        block->fColor0 = to565(SK_ColorBLACK);
        block->fColor1 = to565(SK_ColorWHITE);
        SkASSERT(block->fColor0 <= block->fColor1); // this signals a transparent block
        // opaque black (col0), medium grey (col2), transparent black (col3), white (col1).
        byte = (0x0 << 0) | (0x2 << 2) | (0x3 << 4) | (0x1 << 6);
    } else {
        block->fColor0 = to565(SK_ColorWHITE);
        block->fColor1 = to565(SK_ColorBLACK);
        SkASSERT(block->fColor0 > block->fColor1); // this signals an opaque block
        // opaque black (col1), dark grey (col3), light grey (col2), white (col0)
        byte = (0x1 << 0) | (0x3 << 2) | (0x2 << 4) | (0x0 << 6);
    }

    block->fIndices = (byte << 24) | (byte << 16) | (byte << 8) | byte;
}

// This makes a 16x8 BC1 texture which has the top 4 rows be officially transparent
// and the bottom 4 rows be officially opaque.
static sk_sp<SkData> make_compressed_data() {
    SkISize dim{ kImgWidth, kImgHeight };

    size_t totalSize = SkCompressedDataSize(SkImage::CompressionType::kBC1_RGB8_UNORM, dim,
                                            nullptr, false);

    sk_sp<SkData> tmp = SkData::MakeUninitialized(totalSize);
    BC1Block* dstBlocks = reinterpret_cast<BC1Block*>(tmp->writable_data());

    BC1Block transBlock, opaqueBlock;
    create_BC1_block(&transBlock, true);
    create_BC1_block(&opaqueBlock, false);

    int numXBlocks = num_4x4_blocks(kImgWidth);
    int numYBlocks = num_4x4_blocks(kImgHeight);

    for (int y = 0; y < numYBlocks; ++y) {
        for (int x = 0; x < numXBlocks; ++x) {
            dstBlocks[y*numXBlocks + x] = (y < numYBlocks/2) ? transBlock : opaqueBlock;
        }
    }

    return tmp;
}

static sk_sp<SkImage> data_to_img(GrContext *context, sk_sp<SkData> data,
                                  SkImage::CompressionType compression) {
    if (context) {
        return SkImage::MakeTextureFromCompressed(context, std::move(data),
                                                  kImgWidth,
                                                  kImgHeight,
                                                  compression,
                                                  GrMipMapped::kNo);
    } else {
        return SkImage::MakeRasterFromCompressed(std::move(data),
                                                 kImgWidth,
                                                 kImgHeight,
                                                 compression);
    }
}

static void draw_image(GrRecordingContext* context, SkCanvas* canvas,
                       sk_sp<SkImage> image, int x, int y) {

    bool isCompressed = false;
    if (image && image->isTextureBacked()) {
        const GrCaps* caps = context->priv().caps();

        GrTextureProxy* proxy = as_IB(image)->peekProxy();
        isCompressed = caps->isFormatCompressed(proxy->backendFormat());
    }

    canvas->drawImage(image, x, y);

    if (!isCompressed) {
        SkRect r = SkRect::MakeXYWH(x, y, kImgWidth, kImgHeight);
        r.outset(1.0f, 1.0f);

        SkPaint redStroke;
        redStroke.setColor(SK_ColorRED);
        redStroke.setStyle(SkPaint::kStroke_Style);
        redStroke.setStrokeWidth(2.0f);

        canvas->drawRect(r, redStroke);
    }
}

namespace skiagm {

// This GM draws the BC1 compressed texture filled with "make_compressed_data"s data twice.
//
// It is drawn once (on the top) as a kBC1_RGB8_UNORM texture and then again (on the bottom)
// as a kBC1_RGBA8_UNORM texture.
//
// If BC1 behaves as expected we should see:
//
//   RGB8             Black MidGrey Black*  White ...
//                    Black DrkGrey LtGrey  White ...
//
//   RGBA8            Black MidGrey Green+  White ...
//                    Black DrkGrey LtGrey  White ...
//
// * We expect this to be black bc the transparent black will be forced to opaque. If BC1 were
//   treating it as an opaque block then it would be LtGrey - not black.
// + This is just the background showing through the transparent black
class BC1TransparencyGM : public GM {
public:
    BC1TransparencyGM() {
        this->setBGColor(SK_ColorGREEN);
    }

protected:

    SkString onShortName() override {
        return SkString("bc1_transparency");
    }

    SkISize onISize() override {
        return SkISize::Make(kImgWidth + 2 * kPad, 2 * kImgHeight + 3 * kPad);
    }

    void onOnceBeforeDraw() override {
        fBC1Data = make_compressed_data();
    }

    void onDraw(SkCanvas* canvas) override {
        auto context = canvas->getGrContext();

        sk_sp<SkImage> rgbImg = data_to_img(context, fBC1Data,
                                            SkImage::CompressionType::kBC1_RGB8_UNORM);

        sk_sp<SkImage> rgbaImg = data_to_img(context, fBC1Data,
                                             SkImage::CompressionType::kBC1_RGBA8_UNORM);

        draw_image(context, canvas, rgbImg, kPad, kPad);
        draw_image(context, canvas, rgbaImg, kPad, 2 * kPad + kImgHeight);
    }

private:
    sk_sp<SkData> fBC1Data;

    typedef GM INHERITED;
};

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

DEF_GM(return new BC1TransparencyGM;)
}
