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

#include "bench/Benchmark.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/gpu/GrDirectContext.h"
#include "include/utils/SkRandom.h"
#include "src/core/SkCanvasPriv.h"
#include "src/gpu/ganesh/GrOpsTypes.h"
#include "src/gpu/ganesh/SkGr.h"
#include "src/gpu/ganesh/v1/SurfaceDrawContext_v1.h"

// Benchmarks that exercise the bulk image and solid color quad APIs, under a variety of patterns:
enum class ImageMode {
    kShared, // 1. One shared image referenced by every rectangle
    kUnique, // 2. Unique image for every rectangle
    kNone    // 3. No image, solid color shading per rectangle
};
//   X
enum class DrawMode {
    kBatch,  // Bulk API submission, one call to draw every rectangle
    kRef,    // One standard SkCanvas draw call per rectangle
    kQuad    // One experimental draw call per rectangle, only for solid color draws
};
//   X
enum class RectangleLayout {
    kRandom,  // Random overlapping rectangles
    kGrid     // Small, non-overlapping rectangles in a grid covering the output surface
};

// Benchmark runner that can be configured by template arguments.
template<int kRectCount, RectangleLayout kLayout, ImageMode kImageMode, DrawMode kDrawMode>
class BulkRectBench : public Benchmark {
public:
    static_assert(kImageMode == ImageMode::kNone || kDrawMode != DrawMode::kQuad,
                  "kQuad only supported for solid color draws");

    inline static constexpr int kWidth      = 1024;
    inline static constexpr int kHeight     = 1024;

    // There will either be 0 images, 1 image, or 1 image per rect
    inline static constexpr int kImageCount = kImageMode == ImageMode::kShared ?
            1 : (kImageMode == ImageMode::kNone ? 0 : kRectCount);

    bool isSuitableFor(Backend backend) override {
        if (kDrawMode == DrawMode::kBatch && kImageMode == ImageMode::kNone) {
            // Currently the bulk color quad API is only available on skgpu::v1::SurfaceDrawContext
            return backend == kGPU_Backend;
        } else {
            return this->INHERITED::isSuitableFor(backend);
        }
    }

protected:
    SkRect         fRects[kRectCount];
    sk_sp<SkImage> fImages[kImageCount];
    SkColor4f      fColors[kRectCount];
    SkString       fName;

    void computeName()  {
        fName = "bulkrect";
        fName.appendf("_%d", kRectCount);
        if (kLayout == RectangleLayout::kRandom) {
            fName.append("_random");
        } else {
            fName.append("_grid");
        }
        if (kImageMode == ImageMode::kShared) {
            fName.append("_sharedimage");
        } else if (kImageMode == ImageMode::kUnique) {
            fName.append("_uniqueimages");
        } else {
            fName.append("_solidcolor");
        }
        if (kDrawMode == DrawMode::kBatch) {
            fName.append("_batch");
        } else if (kDrawMode == DrawMode::kRef) {
            fName.append("_ref");
        } else {
            fName.append("_quad");
        }
    }

    void drawImagesBatch(SkCanvas* canvas) const {
        SkASSERT(kImageMode != ImageMode::kNone);
        SkASSERT(kDrawMode == DrawMode::kBatch);

        SkCanvas::ImageSetEntry batch[kRectCount];
        for (int i = 0; i < kRectCount; ++i) {
            int imageIndex = kImageMode == ImageMode::kShared ? 0 : i;
            batch[i].fImage = fImages[imageIndex];
            batch[i].fSrcRect = SkRect::MakeIWH(fImages[imageIndex]->width(),
                                                fImages[imageIndex]->height());
            batch[i].fDstRect = fRects[i];
            batch[i].fAAFlags = SkCanvas::kAll_QuadAAFlags;
        }

        SkPaint paint;
        paint.setAntiAlias(true);

        canvas->experimental_DrawEdgeAAImageSet(batch, kRectCount, nullptr, nullptr,
                                                SkSamplingOptions(SkFilterMode::kLinear), &paint,
                                                SkCanvas::kFast_SrcRectConstraint);
    }

    void drawImagesRef(SkCanvas* canvas) const {
        SkASSERT(kImageMode != ImageMode::kNone);
        SkASSERT(kDrawMode == DrawMode::kRef);

        SkPaint paint;
        paint.setAntiAlias(true);

        for (int i = 0; i < kRectCount; ++i) {
            int imageIndex = kImageMode == ImageMode::kShared ? 0 : i;
            SkRect srcRect = SkRect::MakeIWH(fImages[imageIndex]->width(),
                                             fImages[imageIndex]->height());
            canvas->drawImageRect(fImages[imageIndex].get(), srcRect, fRects[i],
                                  SkSamplingOptions(SkFilterMode::kLinear), &paint,
                                  SkCanvas::kFast_SrcRectConstraint);
        }
    }

    void drawSolidColorsBatch(SkCanvas* canvas) const {
        SkASSERT(kImageMode == ImageMode::kNone);
        SkASSERT(kDrawMode == DrawMode::kBatch);

        auto context = canvas->recordingContext();
        SkASSERT(context);

        GrQuadSetEntry batch[kRectCount];
        for (int i = 0; i < kRectCount; ++i) {
            batch[i].fRect = fRects[i];
            batch[i].fColor = fColors[i].premul();
            batch[i].fLocalMatrix = SkMatrix::I();
            batch[i].fAAFlags = GrQuadAAFlags::kAll;
        }

        SkPaint paint;
        paint.setColor(SK_ColorWHITE);
        paint.setAntiAlias(true);

        auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas);
        SkMatrix view = canvas->getLocalToDeviceAs3x3();
        SkMatrixProvider matrixProvider(view);
        GrPaint grPaint;
        SkPaintToGrPaint(context, sdc->colorInfo(), paint, matrixProvider, &grPaint);
        sdc->drawQuadSet(nullptr, std::move(grPaint), view, batch, kRectCount);
    }

    void drawSolidColorsRef(SkCanvas* canvas) const {
        SkASSERT(kImageMode == ImageMode::kNone);
        SkASSERT(kDrawMode == DrawMode::kRef || kDrawMode == DrawMode::kQuad);

        SkPaint paint;
        paint.setAntiAlias(true);
        for (int i = 0; i < kRectCount; ++i) {
            if (kDrawMode == DrawMode::kRef) {
                paint.setColor4f(fColors[i]);
                canvas->drawRect(fRects[i], paint);
            } else {
                canvas->experimental_DrawEdgeAAQuad(fRects[i], nullptr, SkCanvas::kAll_QuadAAFlags,
                                                    fColors[i], SkBlendMode::kSrcOver);
            }
        }
    }

    const char* onGetName() override {
        if (fName.isEmpty()) {
            this->computeName();
        }
        return fName.c_str();
    }

    void onDelayedSetup() override {
        static constexpr SkScalar kMinRectSize = 0.2f;
        static constexpr SkScalar kMaxRectSize = 300.f;

        SkRandom rand;
        for (int i = 0; i < kRectCount; i++) {
            if (kLayout == RectangleLayout::kRandom) {
                SkScalar w = rand.nextF() * (kMaxRectSize - kMinRectSize) + kMinRectSize;
                SkScalar h = rand.nextF() * (kMaxRectSize - kMinRectSize) + kMinRectSize;

                SkScalar x = rand.nextF() * (kWidth - w);
                SkScalar y = rand.nextF() * (kHeight - h);

                fRects[i].setXYWH(x, y, w, h);
            } else {
                int gridSize = SkScalarCeilToInt(SkScalarSqrt(kRectCount));
                SkASSERT(gridSize * gridSize >= kRectCount);

                SkScalar w = (kWidth - 1.f) / gridSize;
                SkScalar h = (kHeight - 1.f) / gridSize;

                SkScalar x = (i % gridSize) * w + 0.5f; // Offset to ensure AA doesn't get disabled
                SkScalar y = (i / gridSize) * h + 0.5f;

                fRects[i].setXYWH(x, y, w, h);
            }

            // Make sure we don't extend outside the render target, don't want to include clipping
            // in the benchmark.
            SkASSERT(SkRect::MakeWH(kWidth, kHeight).contains(fRects[i]));

            fColors[i] = {rand.nextF(), rand.nextF(), rand.nextF(), 1.f};
        }
    }

    void onPerCanvasPreDraw(SkCanvas* canvas) override {
        // Push the skimages to the GPU when using the GPU backend so that the texture creation is
        // not part of the bench measurements. Always remake the images since they are so simple,
        // and since they are context-specific, this works when the bench runs multiple GPU backends
        auto direct = GrAsDirectContext(canvas->recordingContext());
        for (int i = 0; i < kImageCount; ++i) {
            SkBitmap bm;
            bm.allocN32Pixels(256, 256);
            bm.eraseColor(fColors[i].toSkColor());
            auto image = bm.asImage();

            fImages[i] = direct ? image->makeTextureImage(direct) : std::move(image);
        }
    }

    void onPerCanvasPostDraw(SkCanvas* canvas) override {
        for (int i = 0; i < kImageCount; ++i) {
            // For Vulkan we need to make sure the bench isn't holding onto any refs to the
            // GrContext when we go to delete the vulkan context (which happens before the bench is
            // deleted). So reset all the images here so they aren't holding GrContext refs.
            fImages[i].reset();
        }
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        for (int i = 0; i < loops; i++) {
            if (kImageMode == ImageMode::kNone) {
                if (kDrawMode == DrawMode::kBatch) {
                    this->drawSolidColorsBatch(canvas);
                } else {
                    this->drawSolidColorsRef(canvas);
                }
            } else {
                if (kDrawMode == DrawMode::kBatch) {
                    this->drawImagesBatch(canvas);
                } else {
                    this->drawImagesRef(canvas);
                }
            }
        }
    }

    SkIPoint onGetSize() override {
        return { kWidth, kHeight };
    }

    using INHERITED = Benchmark;
};

// constructor call is wrapped in () so the macro doesn't break parsing the commas in the template
#define ADD_BENCH(n, layout, imageMode, drawMode)                              \
    DEF_BENCH( return (new BulkRectBench<n, layout, imageMode, drawMode>()); )

#define ADD_BENCH_FAMILY(n, layout)                                            \
    ADD_BENCH(n, layout, ImageMode::kShared, DrawMode::kBatch)                 \
    ADD_BENCH(n, layout, ImageMode::kShared, DrawMode::kRef)                   \
    ADD_BENCH(n, layout, ImageMode::kUnique, DrawMode::kBatch)                 \
    ADD_BENCH(n, layout, ImageMode::kUnique, DrawMode::kRef)                   \
    ADD_BENCH(n, layout, ImageMode::kNone,   DrawMode::kBatch)                 \
    ADD_BENCH(n, layout, ImageMode::kNone,   DrawMode::kRef)                   \
    ADD_BENCH(n, layout, ImageMode::kNone,   DrawMode::kQuad)

ADD_BENCH_FAMILY(1000,  RectangleLayout::kRandom)
ADD_BENCH_FAMILY(1000,  RectangleLayout::kGrid)

#undef ADD_BENCH_FAMILY
#undef ADD_BENCH
