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

#include "src/gpu/graphite/RendererProvider.h"

#include "include/core/SkPathTypes.h"
#include "include/core/SkVertices.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/InternalDrawTypeFlags.h"
#include "src/gpu/graphite/UniformManager.h"
#include "src/gpu/graphite/render/AnalyticBlurRenderStep.h"
#include "src/gpu/graphite/render/AnalyticRRectBlurRenderStep.h"
#include "src/gpu/graphite/render/AnalyticRRectRenderStep.h"
#include "src/gpu/graphite/render/BitmapTextRenderStep.h"
#include "src/gpu/graphite/render/CircularArcRenderStep.h"
#include "src/gpu/graphite/render/CommonDepthStencilSettings.h"
#include "src/gpu/graphite/render/CoverBoundsRenderStep.h"
#include "src/gpu/graphite/render/CoverageMaskRenderStep.h"
#include "src/gpu/graphite/render/MeshRenderStep.h"
#include "src/gpu/graphite/render/MiddleOutFanRenderStep.h"
#include "src/gpu/graphite/render/PerEdgeAAQuadRenderStep.h"
#include "src/gpu/graphite/render/SDFTextLCDRenderStep.h"
#include "src/gpu/graphite/render/SDFTextRenderStep.h"
#include "src/gpu/graphite/render/TessellateCurvesRenderStep.h"
#include "src/gpu/graphite/render/TessellateStrokesRenderStep.h"
#include "src/gpu/graphite/render/TessellateWedgesRenderStep.h"
#include "src/gpu/graphite/render/VerticesRenderStep.h"
#include "src/sksl/SkSLUtil.h"

#ifdef SK_ENABLE_VELLO_SHADERS
#include "src/gpu/graphite/compute/VelloRenderer.h"
#endif

#if defined(SK_ENABLE_SPARSE_STRIPS)
#include "src/gpu/graphite/render/EndCapRenderStep.h"
#include "src/gpu/graphite/render/WideTileRenderStep.h"
#endif

namespace skgpu::graphite {

bool RendererProvider::IsSupported(PathRendererStrategy strategy, const Caps* caps) {
    switch (strategy) {
        case PathRendererStrategy::kTessellationAndSmallAtlas:
            if (caps->minPathSizeForMSAA() <= 0) {
                return false; // Disabled explicitly
            }
            [[fallthrough]]; // Must support kTessellation too
        case PathRendererStrategy::kTessellation:
            // This strategy requires MSAA, which will use a supported MSAA count returned by
            // Caps::getDefaultMSAASampleCount(target). When avoidMSAA() returns false, this should
            // always be at least 4x on Graphite's supported devices.
            return !caps->avoidMSAA();

        case PathRendererStrategy::kRasterAtlas:
            // The raster path atlas is currently always supported
            return true;

        case PathRendererStrategy::kComputeAnalyticAA: [[fallthrough]];
        case PathRendererStrategy::kComputeMSAA16:
        case PathRendererStrategy::kComputeMSAA8:
            // The Vello compute strategies are supported if included in the build and has compute.
#if defined(SK_ENABLE_VELLO_SHADERS)
            return caps->computeSupport();
#else
            return false;
#endif
        case PathRendererStrategy::kCPUSparseStripsMSAA8:
#if defined(SK_ENABLE_SPARSE_STRIPS)
            return true;
#else
            return false;
#endif
    }

    SkUNREACHABLE;
}

// The destructor is intentionally defined here and not in the header file to allow forward
// declared types (such as `VelloRenderer`) to be defined as a `std::unique_ptr` parameter type
// in members.
RendererProvider::~RendererProvider() = default;

RendererProvider::RendererProvider(const Caps* caps, StaticBufferManager* bufferManager) {
    // Determine path rendering strategy
#if defined(GPU_TEST_UTILS)
    if (caps->requestedPathRendererStrategy().has_value() &&
        IsSupported(*caps->requestedPathRendererStrategy(), caps)) {
        // Use the explicitly overridden strategy
        fStrategy = *caps->requestedPathRendererStrategy();
    } else
#endif
    {
        // By default, prefer vello > tessellation [w/ atlas] > raster atlas
        if (IsSupported(PathRendererStrategy::kComputeMSAA8, caps)) {
            fStrategy = PathRendererStrategy::kComputeMSAA8;
        } else if (caps->avoidMSAA()) {
            fStrategy = PathRendererStrategy::kRasterAtlas;
        } else if (caps->minPathSizeForMSAA() > 0) {
            fStrategy = PathRendererStrategy::kTessellationAndSmallAtlas;
        } else {
            fStrategy = PathRendererStrategy::kTessellation;
        }

        SkASSERT(IsSupported(fStrategy, caps));
    }

    const bool infinitySupport = caps->shaderCaps()->fInfinitySupport;
    const bool useStorageBuffers = caps->storageBufferSupport();
    const auto& bindingReq = caps->resourceBindingRequirements();
    auto layout = useStorageBuffers ? bindingReq.fStorageBufferLayout
                                    : bindingReq.fUniformBufferLayout;

    // Single-step renderers don't share RenderSteps
    auto initFromStep = [&](Renderer* renderer,
                            std::unique_ptr<RenderStep> singleStep,
                            DrawTypeFlags drawTypes) {
        std::string name = "SingleStep[";
        name += singleStep->name();
        name += "]";
        this->initRenderer(renderer, name, drawTypes, this->assumeOwnership(std::move(singleStep)));
    };

    // NOTE: We always initialize the tessellation RenderSteps because they are used for fallback
    // with all of the other atlas'ing path renderer strategies. We always initialize the
    // CoverageMaskRenderStep because it is used for mask filters even when the path renderer
    // strategy wouldn't use it to sample an atlas.
    initFromStep(&fConvexTessellatedWedges,
                 TessellateWedgesRenderStep::ConvexFill(layout, infinitySupport, bufferManager),
                 DrawTypeFlags::kNonSimpleShape);
    initFromStep(&fCoverageMask,
                 std::make_unique<CoverageMaskRenderStep>(layout),
                 static_cast<DrawTypeFlags>((int) DrawTypeFlags::kNonSimpleShape |
                                            (int) InternalDrawTypeFlags::kCoverageMask));

    static constexpr struct {
        skgpu::MaskFormat fFormat;
        DrawTypeFlags     fDrawType;
    } kBitmapTextVariants [] = {
        // We are using 565 here to represent LCD text, regardless of texture format
        { skgpu::MaskFormat::kA8,   DrawTypeFlags::kBitmapText_Mask  },
        { skgpu::MaskFormat::kA565, DrawTypeFlags::kBitmapText_LCD   },
        { skgpu::MaskFormat::kARGB, DrawTypeFlags::kBitmapText_Color }
    };

    for (auto textVariant : kBitmapTextVariants) {
        initFromStep(&fBitmapText[int(textVariant.fFormat)],
                     std::make_unique<BitmapTextRenderStep>(layout, textVariant.fFormat),
                     textVariant.fDrawType);
    }

    // SDF text (lcd and single channel)
    initFromStep(&fSDFText[/*lcd=*/true],
                 std::make_unique<SDFTextLCDRenderStep>(layout),
                 DrawTypeFlags::kSDFText_LCD);
    initFromStep(&fSDFText[/*lcd=*/false],
                 std::make_unique<SDFTextRenderStep>(layout),
                 DrawTypeFlags::kSDFText);

    initFromStep(&fAnalyticRRect,
                 std::make_unique<AnalyticRRectRenderStep>(layout, bufferManager),
                 DrawTypeFlags::kAnalyticRRect);
    initFromStep(&fPerEdgeAAQuad,
                 std::make_unique<PerEdgeAAQuadRenderStep>(layout, bufferManager),
                 DrawTypeFlags::kPerEdgeAAQuad);
    initFromStep(&fNonAABoundsFill,
                 CoverBoundsRenderStep::NonAAInnerFill(layout),
                 DrawTypeFlags::kNonAAFillRect);
    initFromStep(&fCircularArc,
                 std::make_unique<CircularArcRenderStep>(layout, bufferManager),
                 DrawTypeFlags::kCircularArc);
    initFromStep(&fAnalyticBlur,
                 std::make_unique<AnalyticBlurRenderStep>(layout),
                 DrawTypeFlags::kDropShadows);
    initFromStep(&fAnalyticRRectBlur,
                 std::make_unique<AnalyticRRectBlurRenderStep>(layout, bufferManager),
                 DrawTypeFlags::kDropShadows);

    // vertices
    for (bool color : {false, true}) {
        for (bool texCoords : {false, true}) {
            DrawTypeFlags dtFlags = DrawTypeFlags::kDrawVertices;
            if (color && !texCoords) {
                // Android uses this drawVertices combination for drop shadows
                dtFlags = static_cast<DrawTypeFlags>(dtFlags | DrawTypeFlags::kDropShadows);
            }

            int index = 2*color + texCoords;
            initFromStep(&fVertices[index],
                         std::make_unique<VerticesRenderStep>(layout, color, texCoords),
                         dtFlags);
        }
    }

    initFromStep(&fMesh, std::make_unique<MeshRenderStep>(layout), DrawTypeFlags::kDrawMesh);

    // The tessellating path renderers that use stencil can share the cover steps.
    auto coverFill = CoverBoundsRenderStep::StencilCover(layout, /*inverseFill=*/false);
    auto coverInverse = CoverBoundsRenderStep::StencilCover(layout, /*inverseFill=*/true);

    for (bool evenOdd : {false, true}) {
        // These steps can be shared by regular and inverse fills
        auto stencilFan = std::make_unique<MiddleOutFanRenderStep>(layout, evenOdd);
        auto stencilCurve = std::make_unique<TessellateCurvesRenderStep>(
                layout, evenOdd, infinitySupport, bufferManager);
        auto stencilWedge = TessellateWedgesRenderStep::StencilFill(
                layout, evenOdd, infinitySupport, bufferManager);

        for (bool inverse : {false, true}) {
            static const char* kTessVariants[4] =
                    {"[winding]", "[evenodd]", "[inverse-winding]", "[inverse-evenodd]"};

            int index = 2*inverse + evenOdd; // matches SkPathFillType
            std::string variant = kTessVariants[index];

            const RenderStep* coverStep = inverse ? coverInverse.get() : coverFill.get();
            this->initRenderer(&fStencilTessellatedCurves[index],
                               "StencilTessellatedCurvesAndTris" + variant,
                               DrawTypeFlags::kNonSimpleShape,
                               stencilFan.get(),
                               stencilCurve.get(),
                               coverStep);

            this->initRenderer(&fStencilTessellatedWedges[index],
                               "StencilTessellatedWedges" + variant,
                               DrawTypeFlags::kNonSimpleShape,
                               stencilWedge.get(),
                               coverStep);
        }

        this->assumeOwnership(std::move(stencilFan));
        this->assumeOwnership(std::move(stencilCurve));
        this->assumeOwnership(std::move(stencilWedge));
    }

    initFromStep(&fTessellatedStrokes[/*inverseFill=*/false],
                 std::make_unique<TessellateStrokesRenderStep>(layout, infinitySupport,
                                                               /*inverseFill=*/false),
                 DrawTypeFlags::kNonSimpleShape);
    auto tessellatedStrokesInverseFillStep
            = std::make_unique<TessellateStrokesRenderStep>(layout, infinitySupport,
                                                            /*inverseFill=*/true);
    this->initRenderer(&fTessellatedStrokes[/*inverseFill=*/true],
                       "TessellatedStrokesInverseFill",
                       DrawTypeFlags::kNonSimpleShape,
                       tessellatedStrokesInverseFillStep.get(),
                       coverInverse.get());
    this->assumeOwnership(std::move(tessellatedStrokesInverseFillStep));

    this->assumeOwnership(std::move(coverInverse));
    this->assumeOwnership(std::move(coverFill));

#if defined(SK_ENABLE_SPARSE_STRIPS)
    {
        initFromStep(&fSparseStrips[0],
                     std::make_unique<EndCapRenderStep>(layout),
                     DrawTypeFlags::kSparseStrips);
        initFromStep(&fSparseStrips[1],
                     std::make_unique<WideTileRenderStep>(layout),
                     DrawTypeFlags::kSparseStrips);
    }
#endif

#ifdef SK_ENABLE_VELLO_SHADERS
    // Don't initialize Vello if the strategy wouldn't use it.
    if (fStrategy == PathRendererStrategy::kComputeAnalyticAA ||
        fStrategy == PathRendererStrategy::kComputeMSAA16 ||
        fStrategy == PathRendererStrategy::kComputeMSAA8) {
        fVelloRenderer = std::make_unique<VelloRenderer>(caps);
    }
#endif
}

} // namespace skgpu::graphite
