/*
 * 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 "include/core/SkAlphaType.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/gpu/GrTypes.h"
#include "include/private/SkColorData.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkBlendModePriv.h"
#include "src/gpu/Swizzle.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrColorSpaceXform.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrOpsTypes.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrSamplerState.h"
#include "src/gpu/ganesh/GrSurfaceProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/SurfaceDrawContext.h"
#include "src/gpu/ganesh/geometry/GrQuad.h"
#include "src/gpu/ganesh/ops/FillRectOp.h"
#include "src/gpu/ganesh/ops/GrDrawOp.h"
#include "src/gpu/ganesh/ops/GrOp.h"
#include "src/gpu/ganesh/ops/OpsTask.h"
#include "src/gpu/ganesh/ops/TextureOp.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"

#include <cstdint>
#include <memory>
#include <utility>

struct GrContextOptions;

using namespace skgpu::ganesh;

static std::unique_ptr<skgpu::v1::SurfaceDrawContext> new_SDC(GrRecordingContext* rContext) {
    return skgpu::v1::SurfaceDrawContext::Make(
            rContext, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact, {128, 128},
            SkSurfaceProps(), /*label=*/{});
}

static sk_sp<GrSurfaceProxy> create_proxy(GrRecordingContext* rContext) {
    static constexpr SkISize kDimensions = {128, 128};

    const GrBackendFormat format = rContext->priv().caps()->getDefaultBackendFormat(
                                                                           GrColorType::kRGBA_8888,
                                                                           GrRenderable::kYes);
    return rContext->priv().proxyProvider()->createProxy(
            format, kDimensions, GrRenderable::kYes, 1, GrMipmapped::kNo, SkBackingFit::kExact,
            SkBudgeted::kNo, GrProtected::kNo, /*label=*/"CreateSurfaceProxy",
            GrInternalSurfaceFlags::kNone);
}

typedef GrQuadAAFlags (*PerQuadAAFunc)(int i);

typedef void (*BulkRectTest)(skiatest::Reporter*,
                             GrDirectContext*,
                             PerQuadAAFunc,
                             GrAAType overallAA,
                             SkBlendMode,
                             bool addOneByOne,
                             bool allUniqueProxies,
                             int requestedTotNumQuads,
                             int expectedNumOps);

//-------------------------------------------------------------------------------------------------
static void fillrectop_creation_test(skiatest::Reporter* reporter, GrDirectContext* dContext,
                                     PerQuadAAFunc perQuadAA, GrAAType overallAA,
                                     SkBlendMode blendMode, bool addOneByOne,
                                     bool allUniqueProxies,
                                     int requestedTotNumQuads, int expectedNumOps) {

    if (addOneByOne || allUniqueProxies) {
        return;
    }

    std::unique_ptr<skgpu::v1::SurfaceDrawContext> sdc = new_SDC(dContext);

    auto quads = new GrQuadSetEntry[requestedTotNumQuads];

    for (int i = 0; i < requestedTotNumQuads; ++i) {
        quads[i].fRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
        quads[i].fColor = SK_PMColor4fWHITE;
        quads[i].fLocalMatrix = SkMatrix::I();
        quads[i].fAAFlags = perQuadAA(i);
    }

    GrPaint paint;
    paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode));

    skgpu::v1::FillRectOp::AddFillRectOps(sdc.get(), nullptr, dContext, std::move(paint), overallAA,
                                          SkMatrix::I(), quads, requestedTotNumQuads);

    auto opsTask = sdc->testingOnly_PeekLastOpsTask();
    int actualNumOps = opsTask->numOpChains();

    int actualTotNumQuads = 0;

    for (int i = 0; i < actualNumOps; ++i) {
        const GrOp* tmp = opsTask->getChain(i);
        REPORTER_ASSERT(reporter, tmp->classID() == skgpu::v1::FillRectOp::ClassID());
        REPORTER_ASSERT(reporter, tmp->isChainTail());
        actualTotNumQuads += ((GrDrawOp*) tmp)->numQuads();
    }

    REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
    REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);

    dContext->flushAndSubmit();

    delete[] quads;
}

//-------------------------------------------------------------------------------------------------
static void textureop_creation_test(skiatest::Reporter* reporter, GrDirectContext* dContext,
                                    PerQuadAAFunc perQuadAA, GrAAType overallAA,
                                    SkBlendMode blendMode, bool addOneByOne,
                                    bool allUniqueProxies,
                                    int requestedTotNumQuads, int expectedNumOps) {

    std::unique_ptr<skgpu::v1::SurfaceDrawContext> sdc = new_SDC(dContext);

    GrSurfaceProxyView proxyViewA, proxyViewB;

    if (!allUniqueProxies) {
        sk_sp<GrSurfaceProxy> proxyA = create_proxy(dContext);
        sk_sp<GrSurfaceProxy> proxyB = create_proxy(dContext);
        proxyViewA = GrSurfaceProxyView(std::move(proxyA),
                                        kTopLeft_GrSurfaceOrigin,
                                        skgpu::Swizzle::RGBA());
        proxyViewB = GrSurfaceProxyView(std::move(proxyB),
                                        kTopLeft_GrSurfaceOrigin,
                                        skgpu::Swizzle::RGBA());
    }

    auto set = new GrTextureSetEntry[requestedTotNumQuads];

    for (int i = 0; i < requestedTotNumQuads; ++i) {
        if (!allUniqueProxies) {
            // Alternate between two proxies to prevent op merging if the batch API was forced to
            // submit one op at a time (to work, this does require that all fDstRects overlap).
            set[i].fProxyView = i % 2 == 0 ? proxyViewA : proxyViewB;
        } else {
            // Each op gets its own proxy to force chaining only
            sk_sp<GrSurfaceProxy> proxyA = create_proxy(dContext);
            set[i].fProxyView = GrSurfaceProxyView(std::move(proxyA),
                                                   kTopLeft_GrSurfaceOrigin,
                                                   skgpu::Swizzle::RGBA());
        }

        set[i].fSrcAlphaType = kPremul_SkAlphaType;
        set[i].fSrcRect = SkRect::MakeWH(100.0f, 100.0f);
        set[i].fDstRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
        set[i].fDstClipQuad = nullptr;
        set[i].fPreViewMatrix = nullptr;
        set[i].fColor = {1.f, 1.f, 1.f, 1.f};
        set[i].fAAFlags = perQuadAA(i);
    }

    if (addOneByOne) {
        for (int i = 0; i < requestedTotNumQuads; ++i) {
            DrawQuad quad;

            quad.fDevice = GrQuad::MakeFromRect(set[i].fDstRect,  SkMatrix::I());
            quad.fLocal = GrQuad(set[i].fSrcRect);
            quad.fEdgeFlags = set[i].fAAFlags;

            GrOp::Owner op = TextureOp::Make(dContext,
                                             set[i].fProxyView,
                                             set[i].fSrcAlphaType,
                                             nullptr,
                                             GrSamplerState::Filter::kNearest,
                                             GrSamplerState::MipmapMode::kNone,
                                             set[i].fColor,
                                             TextureOp::Saturate::kYes,
                                             blendMode,
                                             overallAA,
                                             &quad,
                                             nullptr);
            sdc->addDrawOp(nullptr, std::move(op));
        }
    } else {
        TextureOp::AddTextureSetOps(sdc.get(),
                                    nullptr,
                                    dContext,
                                    set,
                                    requestedTotNumQuads,
                                    requestedTotNumQuads,  // We alternate so proxyCnt == cnt
                                    GrSamplerState::Filter::kNearest,
                                    GrSamplerState::MipmapMode::kNone,
                                    TextureOp::Saturate::kYes,
                                    blendMode,
                                    overallAA,
                                    SkCanvas::kStrict_SrcRectConstraint,
                                    SkMatrix::I(),
                                    nullptr);
    }

    auto opsTask = sdc->testingOnly_PeekLastOpsTask();
    int actualNumOps = opsTask->numOpChains();

    int actualTotNumQuads = 0;

    if (blendMode != SkBlendMode::kSrcOver ||
        !dContext->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
        // In either of these two cases, TextureOp creates one op per quad instead. Since
        // each entry alternates proxies but overlaps geometrically, this will prevent the ops
        // from being merged back into fewer ops.
        expectedNumOps = requestedTotNumQuads;
    }
    uint32_t expectedOpID = blendMode == SkBlendMode::kSrcOver
                                                 ? TextureOp::ClassID()
                                                 : skgpu::v1::FillRectOp::ClassID();
    for (int i = 0; i < actualNumOps; ++i) {
        const GrOp* tmp = opsTask->getChain(i);
        REPORTER_ASSERT(reporter, allUniqueProxies || tmp->isChainTail());
        while (tmp) {
            REPORTER_ASSERT(reporter, tmp->classID() == expectedOpID);
            actualTotNumQuads += ((GrDrawOp*) tmp)->numQuads();
            tmp = tmp->nextInChain();
        }
    }

    REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
    REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);

    dContext->flushAndSubmit();

    delete[] set;
}

//-------------------------------------------------------------------------------------------------
static void run_test(GrDirectContext* dContext, skiatest::Reporter* reporter, BulkRectTest test) {

    // This is the simple case where there is no AA at all. We expect 2 non-AA clumps of quads.
    {
        auto noAA = [](int i) -> GrQuadAAFlags {
            return GrQuadAAFlags::kNone;
        };

        static const int kNumExpectedOps = 2;

        test(reporter, dContext, noAA, GrAAType::kNone, SkBlendMode::kSrcOver,
             false, false, 2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
    }

    // This is the same as the above case except the overall AA is kCoverage. However, since
    // the per-quad AA is still none, all the quads should be downgraded to non-AA.
    {
        auto noAA = [](int i) -> GrQuadAAFlags {
            return GrQuadAAFlags::kNone;
        };

        static const int kNumExpectedOps = 2;

        test(reporter, dContext, noAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
             false, false, 2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
    }

    // This case has an overall AA of kCoverage but the per-quad AA alternates.
    // We should end up with several aa-sized clumps
    {
        auto alternateAA = [](int i) -> GrQuadAAFlags {
            return (i % 2) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
        };

        int numExpectedOps = 2*GrResourceProvider::MaxNumNonAAQuads() /
                                                 GrResourceProvider::MaxNumAAQuads();

        test(reporter, dContext, alternateAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
             false, false, 2*GrResourceProvider::MaxNumNonAAQuads(), numExpectedOps);
    }

    // In this case we have a run of MaxNumAAQuads non-AA quads and then AA quads. This
    // exercises the case where we have a clump of quads that can't be upgraded to AA bc of
    // its size. We expect one clump of non-AA quads followed by one clump of AA quads.
    {
        auto runOfNonAA = [](int i) -> GrQuadAAFlags {
            return (i < GrResourceProvider::MaxNumAAQuads()) ? GrQuadAAFlags::kNone
                                                             : GrQuadAAFlags::kAll;
        };

        static const int kNumExpectedOps = 2;

        test(reporter, dContext, runOfNonAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
             false, false, 2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
    }

    // In this case we use a blend mode other than src-over, which hits the FillRectOp fallback
    // code path for TextureOp. We pass in the expected results if batching was successful, to
    // that bulk_fill_rect_create_test batches on all modes; bulk_texture_rect_create_test is
    // responsible for revising its expectations.
    {
        auto fixedAA = [](int i) -> GrQuadAAFlags {
            return GrQuadAAFlags::kAll;
        };

        static const int kNumExpectedOps = 2;

        test(reporter, dContext, fixedAA, GrAAType::kCoverage, SkBlendMode::kSrcATop,
             false, false, 2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
    }

    // This repros crbug.com/1108475, where we create 1024 non-AA texture ops w/ one coverage-AA
    // texture op in the middle. Because each op has its own texture, all the texture ops
    // get chained together so the quad count can exceed the AA maximum.
    {
        auto onlyOneAA = [](int i) -> GrQuadAAFlags {
            return i == 256 ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
        };

        static const int kNumExpectedOps = 3;

        test(reporter, dContext, onlyOneAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
             true, true, 1024, kNumExpectedOps);
    }

    // This repros a problem related to crbug.com/1108475. In this case, the bulk creation
    // method had no way to break up the set of texture ops at the AA quad limit.
    {
        auto onlyOneAA = [](int i) -> GrQuadAAFlags {
            return i == 256 ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
        };

        static const int kNumExpectedOps = 2;

        test(reporter, dContext, onlyOneAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
             false, true, 1024, kNumExpectedOps);
    }

}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BulkFillRectTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    run_test(ctxInfo.directContext(), reporter, fillrectop_creation_test);
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BulkTextureRectTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    run_test(ctxInfo.directContext(), reporter, textureop_creation_test);
}
