/*
 * 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 "include/core/SkTypes.h"

#if !defined(SK_BUILD_FOR_GOOGLE3)  // Google3 doesn't have etc1.h

#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPath.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTextureCompressionType.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "src/core/SkCompressedDataUtils.h"
#include "src/core/SkMipmap.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDataUtils.h"
#include "src/gpu/ganesh/GrImageContextPriv.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/image/SkImage_GaneshBase.h"
#include "src/image/SkImage_Base.h"
#include "third_party/etc1/etc1.h"
#include "tools/gpu/ProxyUtils.h"

#if defined(SK_GRAPHITE)
#include "include/gpu/graphite/Image.h"
#include "include/gpu/graphite/Recorder.h"
#include "src/gpu/GpuTypesPriv.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "tools/gpu/ManagedBackendTexture.h"
#endif

static SkPoint gen_pt(float angle, const SkVector& scale) {
    SkScalar s = SkScalarSin(angle);
    SkScalar c = SkScalarCos(angle);

    return { scale.fX * c, scale.fY * s };
}

// The resulting path will be centered at (0,0) and its size will match 'dimensions'
static SkPath make_gear(SkISize dimensions, int numTeeth) {
    SkVector outerRad{ dimensions.fWidth / 2.0f, dimensions.fHeight / 2.0f };
    SkVector innerRad{ dimensions.fWidth / 2.5f, dimensions.fHeight / 2.5f };
    const float kAnglePerTooth = 2.0f * SK_ScalarPI / (3 * numTeeth);

    float angle = 0.0f;

    SkPath tmp;
    tmp.setFillType(SkPathFillType::kWinding);

    tmp.moveTo(gen_pt(angle, outerRad));

    for (int i = 0; i < numTeeth; ++i, angle += 3*kAnglePerTooth) {
        tmp.lineTo(gen_pt(angle+kAnglePerTooth, outerRad));
        tmp.lineTo(gen_pt(angle+(1.5f*kAnglePerTooth), innerRad));
        tmp.lineTo(gen_pt(angle+(2.5f*kAnglePerTooth), innerRad));
        tmp.lineTo(gen_pt(angle+(3.0f*kAnglePerTooth), outerRad));
    }

    tmp.close();

    float fInnerRad = 0.1f * std::min(dimensions.fWidth, dimensions.fHeight);
    if (fInnerRad > 0.5f) {
        tmp.addCircle(0.0f, 0.0f, fInnerRad, SkPathDirection::kCCW);
    }

    return tmp;
}

// Render one level of a mipmap
SkBitmap render_level(SkISize dimensions, SkColor color, SkColorType colorType, bool opaque) {
    SkPath path = make_gear(dimensions, 9);

    SkImageInfo ii = SkImageInfo::Make(dimensions.width(), dimensions.height(),
                                       colorType, opaque ? kOpaque_SkAlphaType
                                                         : kPremul_SkAlphaType);
    SkBitmap bm;
    bm.allocPixels(ii);

    bm.eraseColor(opaque ? SK_ColorBLACK : SK_ColorTRANSPARENT);

    SkCanvas c(bm);

    SkPaint paint;
    paint.setColor(color | 0xFF000000);
    paint.setAntiAlias(false);

    c.translate(dimensions.width() / 2.0f, dimensions.height() / 2.0f);
    c.drawPath(path, paint);

    return bm;
}

struct CompressedImageObjects {
    sk_sp<SkImage> fImage;
#if defined(SK_GRAPHITE)
    sk_sp<sk_gpu_test::ManagedGraphiteTexture> fGraphiteTexture;
#else
    void* fGraphiteTexture = nullptr;
#endif
};

// Create the compressed data blob needed to represent a mipmapped 2-color texture of the specified
// compression format. In this case 2-color means either opaque black or transparent black plus
// one other color.
// Note that ETC1/ETC2_RGB8_UNORM only supports 565 opaque textures.
static CompressedImageObjects make_compressed_image(SkCanvas* canvas,
                                                    const SkISize dimensions,
                                                    SkColorType colorType,
                                                    bool opaque,
                                                    SkTextureCompressionType compression) {
    size_t totalSize = SkCompressedDataSize(compression, dimensions, nullptr, true);

    sk_sp<SkData> tmp = SkData::MakeUninitialized(totalSize);
    char* pixels = (char*) tmp->writable_data();

    int numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;

    size_t offset = 0;

    // Use a different color for each mipmap level so we can visually evaluate the draws
    static const SkColor kColors[] = {
        SK_ColorRED,
        SK_ColorGREEN,
        SK_ColorBLUE,
        SK_ColorCYAN,
        SK_ColorMAGENTA,
        SK_ColorYELLOW,
        SK_ColorWHITE,
    };

    SkISize levelDims = dimensions;
    for (int i = 0; i < numMipLevels; ++i) {
        size_t levelSize = SkCompressedDataSize(compression, levelDims, nullptr, false);

        SkBitmap bm = render_level(levelDims, kColors[i%7], colorType, opaque);
        if (compression == SkTextureCompressionType::kETC2_RGB8_UNORM) {
            SkASSERT(bm.colorType() == kRGB_565_SkColorType);
            SkASSERT(opaque);

            if (etc1_encode_image((unsigned char*)bm.getAddr16(0, 0),
                                  bm.width(), bm.height(), 2, bm.rowBytes(),
                                  (unsigned char*) &pixels[offset])) {
                return {nullptr, nullptr};
            }
        } else {
            GrTwoColorBC1Compress(bm.pixmap(), kColors[i%7], &pixels[offset]);
        }

        offset += levelSize;
        levelDims = {std::max(1, levelDims.width()/2), std::max(1, levelDims.height()/2)};
    }

    sk_sp<SkImage> image;
#if defined(SK_GRAPHITE)
    skgpu::graphite::Recorder* recorder = canvas->recorder();
    if (recorder) {
        sk_sp<sk_gpu_test::ManagedGraphiteTexture> texture =
                sk_gpu_test::ManagedGraphiteTexture::MakeFromCompressedData(recorder,
                                                                            dimensions,
                                                                            compression,
                                                                            tmp,
                                                                            skgpu::Mipmapped::kYes);
        if (texture) {
            image = SkImages::WrapTexture(recorder,
                                          texture->texture(),
                                          skgpu::CompressionTypeToSkColorType(compression),
                                          kPremul_SkAlphaType,
                                          /*colorSpace=*/nullptr);
            if (image) {
                return {image, texture};
            }
        }
    }
#endif
    auto dContext = GrAsDirectContext(canvas->recordingContext());
    if (dContext) {
        image = SkImages::TextureFromCompressedTextureData(dContext,
                                                           std::move(tmp),
                                                           dimensions.width(),
                                                           dimensions.height(),
                                                           compression,
                                                           skgpu::Mipmapped::kYes);
    } else {
        image = SkImages::RasterFromCompressedTextureData(
                std::move(tmp), dimensions.width(), dimensions.height(), compression);
    }
    return {image, nullptr};
}

// Basic test of Ganesh's ETC1 and BC1 support
// The layout is:
//               ETC2                BC1
//         --------------------------------------
//  RGB8  | kETC2_RGB8_UNORM  | kBC1_RGB8_UNORM  |
//        |--------------------------------------|
//  RGBA8 |                   | kBC1_RGBA8_UNORM |
//         --------------------------------------
//
// The nonPowerOfTwo and nonMultipleOfFour cases exercise some compression edge cases.
class CompressedTexturesGM : public skiagm::GM {
public:
    enum class Type {
        kNormal,
        kNonPowerOfTwo,
        kNonMultipleOfFour
    };

    CompressedTexturesGM(Type type) : fType(type) {
        this->setBGColor(0xFFCCCCCC);

        switch (fType) {
            case Type::kNonPowerOfTwo:
                // These dimensions force the top two mip levels to be 1x3 and 1x1
                fImgDimensions.set(20, 60);
                break;
            case Type::kNonMultipleOfFour:
                // These dimensions force the top three mip levels to be 1x7, 1x3 and 1x1
                fImgDimensions.set(13, 61); // prime numbers - just bc
                break;
            default:
                fImgDimensions.set(kBaseTexWidth, kBaseTexHeight);
                break;
        }

    }

protected:
    SkString getName() const override {
        SkString name("compressed_textures");

        if (fType == Type::kNonPowerOfTwo) {
            name.append("_npot");
        } else if (fType == Type::kNonMultipleOfFour) {
            name.append("_nmof");
        }

        return name;
    }

    SkISize getISize() override {
        return SkISize::Make(2*kCellWidth + 3*kPad, 2*kBaseTexHeight + 3*kPad);
    }

    DrawResult onGpuSetup(SkCanvas* canvas, SkString* errorMsg,
                          GraphiteTestContext* graphiteTestContext) override {
        auto dContext = GrAsDirectContext(canvas->recordingContext());
        if (dContext && dContext->abandoned()) {
            // This isn't a GpuGM so a null 'context' is okay but an abandoned context
            // if forbidden.
            return DrawResult::kSkip;
        }

        if (dContext &&
            dContext->backend() == GrBackendApi::kDirect3D && fType == Type::kNonMultipleOfFour) {
            // skbug.com/10541 - Are non-multiple-of-four BC1 textures supported in D3D?
            return DrawResult::kSkip;
        }

        fOpaqueETC2Image = make_compressed_image(canvas, fImgDimensions,
                                                 kRGB_565_SkColorType, true,
                                                 SkTextureCompressionType::kETC2_RGB8_UNORM);

        fOpaqueBC1Image = make_compressed_image(canvas, fImgDimensions,
                                                kRGBA_8888_SkColorType, true,
                                                SkTextureCompressionType::kBC1_RGB8_UNORM);

        fTransparentBC1Image = make_compressed_image(canvas, fImgDimensions,
                                                     kRGBA_8888_SkColorType, false,
                                                     SkTextureCompressionType::kBC1_RGBA8_UNORM);

        if (!fOpaqueETC2Image.fImage || !fOpaqueBC1Image.fImage || !fTransparentBC1Image.fImage) {
            *errorMsg = "Failed to create compressed images.";
            return DrawResult::kFail;
        }

        return DrawResult::kOk;
    }

    void onGpuTeardown() override {
        fOpaqueETC2Image.fImage = nullptr;
        fOpaqueBC1Image.fImage = nullptr;
        fTransparentBC1Image.fImage = nullptr;
        fOpaqueETC2Image.fGraphiteTexture = nullptr;
        fOpaqueBC1Image.fGraphiteTexture = nullptr;
        fTransparentBC1Image.fGraphiteTexture = nullptr;
    }

    void onDraw(SkCanvas* canvas) override {
        this->drawCell(canvas, fOpaqueETC2Image.fImage.get(), { kPad, kPad });

        this->drawCell(canvas, fOpaqueBC1Image.fImage.get(), { 2*kPad + kCellWidth, kPad });

        this->drawCell(canvas, fTransparentBC1Image.fImage.get(),
                       { 2*kPad + kCellWidth, 2*kPad + kBaseTexHeight });
    }

private:
    void drawCell(SkCanvas* canvas, SkImage* image, SkIVector offset) {

        SkISize levelDimensions = fImgDimensions;
        int numMipLevels = SkMipmap::ComputeLevelCount(levelDimensions.width(),
                                                       levelDimensions.height()) + 1;

        SkSamplingOptions sampling(SkCubicResampler::Mitchell());

        bool isCompressed = false;
        if (image->isTextureBacked()) {
            auto dContext = GrAsDirectContext(canvas->recordingContext());
            if (dContext) {
                const GrCaps* caps = as_IB(image)->context()->priv().caps();
                GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(
                        image, canvas->recordingContext());
                isCompressed = caps->isFormatCompressed(proxy->backendFormat());
            } else {
                // Graphite has no fallback to upload the compressed data to a non-compressed
                // format. So if the image is texture backed and graphite then it will be a
                // compressed format.
                isCompressed = true;
            }
        }

        SkPaint redStrokePaint;
        redStrokePaint.setColor(SK_ColorRED);
        redStrokePaint.setStyle(SkPaint::kStroke_Style);

        for (int i = 0; i < numMipLevels; ++i) {
            SkRect r = SkRect::MakeXYWH(offset.fX, offset.fY,
                                        levelDimensions.width(), levelDimensions.height());

            canvas->drawImageRect(image, r, sampling);
            if (!isCompressed) {
                // Make it obvious which drawImages used decompressed images
                canvas->drawRect(r, redStrokePaint);
            }

            if (i == 0) {
                offset.fX += levelDimensions.width()+1;
            } else {
                offset.fY += levelDimensions.height()+1;
            }

            levelDimensions = {std::max(1, levelDimensions.width()/2),
                               std::max(1, levelDimensions.height()/2)};
        }
    }

    static const int kPad = 8;
    static const int kBaseTexWidth = 64;
    static const int kCellWidth = 1.5f * kBaseTexWidth;
    static const int kBaseTexHeight = 64;

    Type           fType;
    SkISize        fImgDimensions;


    CompressedImageObjects fOpaqueETC2Image;
    CompressedImageObjects fOpaqueBC1Image;
    CompressedImageObjects fTransparentBC1Image;

    using INHERITED = GM;
};

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

DEF_GM(return new CompressedTexturesGM(CompressedTexturesGM::Type::kNormal);)
DEF_GM(return new CompressedTexturesGM(CompressedTexturesGM::Type::kNonPowerOfTwo);)
DEF_GM(return new CompressedTexturesGM(CompressedTexturesGM::Type::kNonMultipleOfFour);)

#endif
