/*
 * Copyright 2017 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"
#include "tests/Test.h"

#include "include/core/SkMatrix.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkRect.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/gpu/mock/GrMockTypes.h"
#include "src/core/SkPathPriv.h"
#include "src/gpu/GrClip.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrPaint.h"
#include "src/gpu/GrPathRenderer.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/GrTexture.h"
#include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
#include "src/gpu/geometry/GrStyledShape.h"
#include "tools/ToolUtils.h"

#include <cmath>

static constexpr int kCanvasSize = 100;

class CCPRClip : public GrClip {
public:
    CCPRClip(GrCoverageCountingPathRenderer* ccpr, const SkPath& path) : fCCPR(ccpr), fPath(path) {}

private:
    SkIRect getConservativeBounds() const final { return fPath.getBounds().roundOut(); }
    Effect apply(GrRecordingContext* context, GrSurfaceDrawContext* rtc, GrAAType,
                 GrAppliedClip* out, SkRect* bounds) const override {
        auto [success, fp] = fCCPR->makeClipProcessor(/*inputFP=*/nullptr,
                                                      rtc->getOpsTask()->uniqueID(), fPath,
                                                      SkIRect::MakeWH(rtc->width(), rtc->height()),
                                                      *context->priv().caps());
        if (success) {
            out->addCoverageFP(std::move(fp));
            return Effect::kClipped;
        } else {
            return Effect::kClippedOut;
        }
    }

    GrCoverageCountingPathRenderer* const fCCPR;
    const SkPath fPath;
};

class CCPRPathDrawer {
public:
    CCPRPathDrawer(sk_sp<GrDirectContext> dContext, skiatest::Reporter* reporter)
            : fDContext(dContext)
            , fCCPR(fDContext->priv().drawingManager()->getCoverageCountingPathRenderer())
            , fSDC(GrSurfaceDrawContext::Make(
                      fDContext.get(), GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact,
                      {kCanvasSize, kCanvasSize}, SkSurfaceProps())) {
        if (!fCCPR) {
            ERRORF(reporter, "ccpr not enabled in GrDirectContext for ccpr tests");
        }
        if (!fSDC) {
            ERRORF(reporter, "failed to create GrSurfaceDrawContext for ccpr tests");
        }
    }

    GrDirectContext* dContext() const { return fDContext.get(); }
    GrCoverageCountingPathRenderer* ccpr() const { return fCCPR; }

    bool valid() const { return fCCPR && fSDC; }
    void clear() const { fSDC->clear(SK_PMColor4fTRANSPARENT); }
    void destroyGrContext() {
        SkASSERT(fDContext->unique());
        fSDC.reset();
        fCCPR = nullptr;
        fDContext.reset();
    }

    void clipFullscreenRect(SkPath clipPath, const SkMatrix& matrix = SkMatrix::I()) const {
        SkASSERT(this->valid());

        GrPaint paint;
        paint.setColor4f({0, 1, 0, 1});

        CCPRClip clip(fCCPR, clipPath);
        fSDC->drawRect(&clip, std::move(paint), GrAA::kYes, SkMatrix::I(),
                       SkRect::MakeIWH(kCanvasSize, kCanvasSize));
    }

    void flush() const {
        SkASSERT(this->valid());
        fDContext->flushAndSubmit();
    }

private:
    sk_sp<GrDirectContext> fDContext;
    GrCoverageCountingPathRenderer* fCCPR;
    std::unique_ptr<GrSurfaceDrawContext> fSDC;
};

class CCPRTest {
public:
    void run(skiatest::Reporter* reporter) {
        GrMockOptions mockOptions;
        mockOptions.fDrawInstancedSupport = true;
        mockOptions.fHalfFloatVertexAttributeSupport = true;
        mockOptions.fMapBufferFlags = GrCaps::kCanMap_MapFlag;
        mockOptions.fConfigOptions[(int)GrColorType::kAlpha_F16].fRenderability =
                GrMockOptions::ConfigOptions::Renderability::kNonMSAA;
        mockOptions.fConfigOptions[(int)GrColorType::kAlpha_F16].fTexturable = true;
        mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fRenderability =
                GrMockOptions::ConfigOptions::Renderability::kMSAA;
        mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fTexturable = true;
        mockOptions.fGeometryShaderSupport = true;
        mockOptions.fIntegerSupport = true;
        mockOptions.fFlatInterpolationSupport = true;

        GrContextOptions ctxOptions;
        ctxOptions.fAllowPathMaskCaching = false;
        ctxOptions.fGpuPathRenderers = GpuPathRenderers::kCoverageCounting;

        this->customizeOptions(&mockOptions, &ctxOptions);

        sk_sp<GrDirectContext> mockContext = GrDirectContext::MakeMock(&mockOptions, ctxOptions);
        if (!mockContext) {
            ERRORF(reporter, "could not create mock context");
            return;
        }
        if (!mockContext->unique()) {
            ERRORF(reporter, "mock context is not unique");
            return;
        }

        CCPRPathDrawer ccpr(std::exchange(mockContext, nullptr), reporter);
        if (!ccpr.valid()) {
            return;
        }

        fPath.moveTo(0, 0);
        fPath.cubicTo(50, 50, 0, 50, 50, 0);
        this->onRun(reporter, ccpr);
    }

    virtual ~CCPRTest() {}

protected:
    virtual void customizeOptions(GrMockOptions*, GrContextOptions*) {}
    virtual void onRun(skiatest::Reporter* reporter, CCPRPathDrawer& ccpr) = 0;

    SkPath fPath;
};

#define DEF_CCPR_TEST(name) \
    DEF_GPUTEST(name, reporter, /* options */) { \
        name test; \
        test.run(reporter); \
    }

class CCPR_cleanup : public CCPRTest {
protected:
    void onRun(skiatest::Reporter* reporter, CCPRPathDrawer& ccpr) override {
        REPORTER_ASSERT(reporter, SkPathPriv::TestingOnly_unique(fPath));

        // Ensure paths get unreffed when we delete the context without flushing.
        for (int i = 0; i < 10; ++i) {
            ccpr.clipFullscreenRect(fPath);
            ccpr.clipFullscreenRect(fPath);
        }
        REPORTER_ASSERT(reporter, !SkPathPriv::TestingOnly_unique(fPath));

        ccpr.destroyGrContext();
        REPORTER_ASSERT(reporter, SkPathPriv::TestingOnly_unique(fPath));
    }
};
DEF_CCPR_TEST(CCPR_cleanup)

class CCPR_cleanupWithTexAllocFail : public CCPR_cleanup {
    void customizeOptions(GrMockOptions* mockOptions, GrContextOptions*) override {
        mockOptions->fFailTextureAllocations = true;
    }
    void onRun(skiatest::Reporter* reporter, CCPRPathDrawer& ccpr) override {
        ((GrRecordingContext*)ccpr.dContext())->priv().incrSuppressWarningMessages();
        this->CCPR_cleanup::onRun(reporter, ccpr);
    }
};
DEF_CCPR_TEST(CCPR_cleanupWithTexAllocFail)

class CCPR_parseEmptyPath : public CCPRTest {
    void onRun(skiatest::Reporter* reporter, CCPRPathDrawer& ccpr) override {
        REPORTER_ASSERT(reporter, SkPathPriv::TestingOnly_unique(fPath));

        // Make a path large enough that ccpr chooses to crop it by the RT bounds, and ends up with
        // an empty path.
        SkPath largeOutsidePath = SkPath::Polygon({
            {-1e30f, -1e30f},
            {-1e30f, +1e30f},
            {-1e10f, +1e30f},
        }, false);
        ccpr.clipFullscreenRect(largeOutsidePath);

        // Normally an empty path is culled before reaching ccpr, however we use a back door for
        // testing so this path will make it.
        SkPath emptyPath;
        SkASSERT(emptyPath.isEmpty());
        ccpr.clipFullscreenRect(emptyPath);

        // This is the test. It will exercise various internal asserts and verify we do not crash.
        ccpr.flush();

        // Now try again with clips.
        ccpr.clipFullscreenRect(largeOutsidePath);
        ccpr.clipFullscreenRect(emptyPath);
        ccpr.flush();

        // ... and both.
        ccpr.clipFullscreenRect(largeOutsidePath);
        ccpr.clipFullscreenRect(largeOutsidePath);
        ccpr.clipFullscreenRect(emptyPath);
        ccpr.clipFullscreenRect(emptyPath);
        ccpr.flush();
    }
};
DEF_CCPR_TEST(CCPR_parseEmptyPath)

class CCPRRenderingTest {
public:
    void run(skiatest::Reporter* reporter, GrDirectContext* dContext) const {
        if (dContext->priv().drawingManager()->getCoverageCountingPathRenderer()) {
            CCPRPathDrawer drawer(sk_ref_sp(dContext), reporter);
            if (!drawer.valid()) {
                return;
            }
            this->onRun(reporter, drawer);
        }
    }

    virtual ~CCPRRenderingTest() {}

protected:
    virtual void onRun(skiatest::Reporter* reporter, const CCPRPathDrawer& ccpr) const = 0;
};

#define DEF_CCPR_RENDERING_TEST(name) \
    DEF_GPUTEST_FOR_RENDERING_CONTEXTS(name, reporter, ctxInfo) { \
        name test; \
        test.run(reporter, ctxInfo.directContext()); \
    }

class CCPR_busyPath : public CCPRRenderingTest {
    void onRun(skiatest::Reporter* reporter, const CCPRPathDrawer& ccpr) const override {
        static constexpr int kNumBusyVerbs = 1 << 17;
        ccpr.clear();
        SkPathBuilder busyPath;
        busyPath.moveTo(0, 0); // top left
        busyPath.lineTo(kCanvasSize, kCanvasSize); // bottom right
        for (int i = 2; i < kNumBusyVerbs; ++i) {
            float offset = i * ((float)kCanvasSize / kNumBusyVerbs);
            busyPath.lineTo(kCanvasSize - offset, kCanvasSize + offset); // offscreen
        }
        ccpr.clipFullscreenRect(busyPath.detach());

        ccpr.flush(); // If this doesn't crash, the test passed.
                      // If it does, maybe fiddle with fMaxInstancesPerDrawArraysWithoutCrashing in
                      // your platform's GrGLCaps.
    }
};
DEF_CCPR_RENDERING_TEST(CCPR_busyPath)

// https://bugs.chromium.org/p/chromium/issues/detail?id=1102117
class CCPR_evictCacheEntryForPendingDrawOp : public CCPRRenderingTest {
    void onRun(skiatest::Reporter* reporter, const CCPRPathDrawer& ccpr) const override {
        static constexpr SkRect kRect = SkRect::MakeWH(50, 50);
        ccpr.clear();

        // make sure path is cached.
        for (int i = 0; i < 2; i++) {
            SkPath path;
            path.addRect(kRect);

            ccpr.clipFullscreenRect(path);
            ccpr.flush();
        }

        // make enough cached draws to make DoCopies happen.
        for (int i = 0; i <= GrCoverageCountingPathRenderer::kDoCopiesThreshold; i++) {
            SkPath path;
            path.addRect(kRect);
            ccpr.clipFullscreenRect(path);
        }

        // now draw the path in an incompatible matrix. Previous draw's cached atlas should
        // not be invalidated. otherwise, this flush would render more paths than allocated for.
        auto m = SkMatrix::Translate(0.1f, 0.1f);
        SkPath path;
        path.addRect(kRect);
        ccpr.clipFullscreenRect(path, m);
        ccpr.flush();

        // if this test does not crash, it is passed.
    }
};
DEF_CCPR_RENDERING_TEST(CCPR_evictCacheEntryForPendingDrawOp)
