/*
 * Copyright 2020 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/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkFont.h"
#include "include/core/SkTypeface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkUTF.h"
#include "src/core/SkUtils.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/SkGr.h"
#include "src/gpu/ganesh/text/GlyphData.h"
#include "src/text/GlyphRun.h"
#include "src/text/gpu/StrikeCache.h"
#include "src/text/gpu/TextBlob.h"
#include "tools/fonts/FontToolUtils.h"
#include "tools/ganesh/TestCanvas.h"
#include "tools/text/gpu/TextBlobTools.h"

// From Project Guttenberg. This is UTF-8 text.
static const char* gText =
        "Call me Ishmael.  Some years ago--never mind how long precisely";

class FillBench {};
template <> class skiatest::TestCanvas<FillBench> {
public:
    static SkDevice* GetDevice(SkCanvas* canvas) {
        return canvas->topDevice();
    }
};

class DirectMaskGlyphVertexFillBenchmark : public Benchmark {
    using Glyph = skgpu::ganesh::Glyph;
    using GlyphData = skgpu::ganesh::GlyphData;

    bool isSuitableFor(Backend backend) override {
        return backend == Backend::kGanesh;
    }

    const char* onGetName() override {
        return "DirectMaskGlyphVertexFillBenchmark";
    }

    void onPerCanvasPreDraw(SkCanvas* canvas) override {
        auto typeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
        SkFont font(typeface);

        SkMatrix view = SkMatrix::I();
        size_t len = strlen(gText);
        sktext::GlyphRunBuilder builder;
        SkPaint paint;
        auto glyphRunList = builder.textToGlyphRunList(font, paint, gText, len, {100, 100});
        SkASSERT_RELEASE(!glyphRunList.empty());
        auto device = skiatest::TestCanvas<FillBench>::GetDevice(canvas);
        SkMatrix drawMatrix = view;
        const SkPoint drawOrigin = glyphRunList.origin();
        drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
        fBlob = sktext::gpu::TextBlob::Make(glyphRunList,
                                            paint,
                                            drawMatrix,
                                            device->strikeDeviceInfo(),
                                            SkStrikeCache::GlobalStrikeCache());

        const sktext::gpu::AtlasSubRun* subRun =
                sktext::gpu::TextBlobTools::FirstSubRun(fBlob.get());
        SkASSERT_RELEASE(subRun);
        if (!subRun->glyphVector().hasBackendData()) {
            // Since isSuitableFor() requires Ganesh and this is nanobench, we know the canvas
            // will be backed by a direct context.
            GrDirectContext* ctx = canvas->recordingContext()->asDirectContext();
            GrAtlasManager* atlasMgr = ctx->priv().getAtlasManager();
            subRun->glyphVector().initBackendData<GlyphData>(&fCache,
                                                             atlasMgr,
                                                             subRun->maskFormat(),
                                                             subRun->glyphSrcPadding(),
                                                             /*isSDF=*/false);
        }
        const auto& glyphData = subRun->glyphVector().accessBackendData<GlyphData>();
        fVertices.reset(new char[glyphData.vertexStride(subRun->maskFormat(), drawMatrix) *
                                 subRun->glyphCount() * 4]);
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        const sktext::gpu::AtlasSubRun* subRun =
                sktext::gpu::TextBlobTools::FirstSubRun(fBlob.get());
        SkASSERT_RELEASE(subRun);

        SkIRect clip = SkIRect::MakeEmpty();
        SkPaint paint;
        SkPMColor4f pmColor = SkColorToPMColor4f(paint.getColor(), /*colorInfo=*/{});
        SkMatrix positionMatrix = SkMatrix::Translate(100, 100);

        auto& glyphData = subRun->glyphVector().accessBackendData<GlyphData>();
        SkSpan<const Glyph> glyphs = subRun->glyphVector().accessBackendGlyphs<Glyph>();
        for (int loop = 0; loop < loops; loop++) {
            glyphData.fillVertexData(subRun->vertexFiller(),
                                     glyphs,
                                     0,
                                     subRun->glyphCount(),
                                     pmColor,
                                     positionMatrix,
                                     clip,
                                     fVertices.get());
        }
    }

private:
    sk_sp<sktext::gpu::TextBlob> fBlob;
    sktext::gpu::StrikeCache fCache;
    std::unique_ptr<char[]> fVertices;
};

DEF_BENCH(return new DirectMaskGlyphVertexFillBenchmark{})
