/*
 * 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 "include/private/SkAttributes.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(SK_UNSAFE_TODO(&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(SK_UNSAFE_TODO(&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 = SK_UNSAFE_TODO(kTessVariants[index]);

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

            this->initRenderer(SK_UNSAFE_TODO(&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
