/*
 * 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/render/AnalyticRRectRenderStep.h"
#include "src/gpu/graphite/render/BitmapTextRenderStep.h"
#include "src/gpu/graphite/render/CommonDepthStencilSettings.h"
#include "src/gpu/graphite/render/CoverBoundsRenderStep.h"
#include "src/gpu/graphite/render/MiddleOutFanRenderStep.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"

namespace skgpu::graphite {

RendererProvider::RendererProvider(const Caps* caps, StaticBufferManager* bufferManager) {
    // This constructor requires all Renderers be densely packed so that it can simply iterate over
    // the fields directly and fill 'fRenderers' with every one that was initialized with a
    // non-empty renderer. While this is a little magical, it simplifies the rest of the logic
    // and can be enforced statically.
    static constexpr size_t kRendererSize = offsetof(RendererProvider, fRenderers) -
                                            offsetof(RendererProvider, fStencilTessellatedCurves);
    static_assert(kRendererSize % sizeof(Renderer) == 0, "Renderer declarations are not dense");

    const bool infinitySupport = caps->shaderCaps()->fInfinitySupport;

    // Single-step renderers don't share RenderSteps
    auto makeFromStep = [&](std::unique_ptr<RenderStep> singleStep, DrawTypeFlags drawTypes) {
        std::string name = "SingleStep[";
        name += singleStep->name();
        name += "]";
        fRenderSteps.push_back(std::move(singleStep));
        return Renderer(name, drawTypes, fRenderSteps.back().get());
    };

    fConvexTessellatedWedges =
            makeFromStep(std::make_unique<TessellateWedgesRenderStep>(
                                 "convex", infinitySupport, kDirectDepthGreaterPass, bufferManager),
                         DrawTypeFlags::kShape);
    fTessellatedStrokes = makeFromStep(
            std::make_unique<TessellateStrokesRenderStep>(infinitySupport), DrawTypeFlags::kShape);
    fBitmapText = makeFromStep(std::make_unique<BitmapTextRenderStep>(),
                               DrawTypeFlags::kText);
    for (bool lcd : {false, true}) {
        fSDFText[lcd] = makeFromStep(std::make_unique<SDFTextRenderStep>(lcd),
                                     DrawTypeFlags::kText);
    }
    fAnalyticRRect = makeFromStep(std::make_unique<AnalyticRRectRenderStep>(bufferManager),
                                  DrawTypeFlags::kShape);
    for (PrimitiveType primType : {PrimitiveType::kTriangles, PrimitiveType::kTriangleStrip}) {
        for (bool color : {false, true}) {
            for (bool texCoords : {false, true}) {
                int index = 4*(primType == PrimitiveType::kTriangleStrip) + 2*color + texCoords;
                fVertices[index] = makeFromStep(
                        std::make_unique<VerticesRenderStep>(primType, color, texCoords),
                        DrawTypeFlags::kDrawVertices);
            }
        }
    }

    // The tessellating path renderers that use stencil can share the cover steps.
    auto coverFill = std::make_unique<CoverBoundsRenderStep>(false);
    auto coverInverse = std::make_unique<CoverBoundsRenderStep>(true);

    for (bool evenOdd : {false, true}) {
        // These steps can be shared by regular and inverse fills
        auto stencilFan = std::make_unique<MiddleOutFanRenderStep>(evenOdd);
        auto stencilCurve = std::make_unique<TessellateCurvesRenderStep>(
                evenOdd, infinitySupport, bufferManager);
        auto stencilWedge =
                evenOdd ? std::make_unique<TessellateWedgesRenderStep>(
                                  "evenodd", infinitySupport, kEvenOddStencilPass, bufferManager)
                        : std::make_unique<TessellateWedgesRenderStep>(
                                  "winding", infinitySupport, kWindingStencilPass, 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];

            constexpr DrawTypeFlags kTextAndShape =
                    static_cast<DrawTypeFlags>(DrawTypeFlags::kText|DrawTypeFlags::kShape);

            const RenderStep* coverStep = inverse ? coverInverse.get() : coverFill.get();
            fStencilTessellatedCurves[index] = Renderer("StencilTessellatedCurvesAndTris" + variant,
                                                        kTextAndShape,
                                                        stencilFan.get(),
                                                        stencilCurve.get(),
                                                        coverStep);

            fStencilTessellatedWedges[index] = Renderer("StencilTessellatedWedges" + variant,
                                                        kTextAndShape,
                                                        stencilWedge.get(),
                                                        coverStep);
        }

        fRenderSteps.push_back(std::move(stencilFan));
        fRenderSteps.push_back(std::move(stencilCurve));
        fRenderSteps.push_back(std::move(stencilWedge));
    }

    fRenderSteps.push_back(std::move(coverInverse));
    fRenderSteps.push_back(std::move(coverFill));

    // Fill out 'fRenderers' by iterating the "span" from fStencilTessellatedCurves to fRenderers
    // and checking if they've been skipped or not.
    SkSpan<Renderer> allRenderers = {fStencilTessellatedCurves, kRendererSize / sizeof(Renderer)};
    for (const Renderer& r : allRenderers) {
        if (r.numRenderSteps() > 0) {
            fRenderers.push_back(&r);
        }
    }
}

const RenderStep* RendererProvider::lookup(uint32_t uniqueID) const {
    for (auto&& rs : fRenderSteps) {
        if (rs->uniqueID() == uniqueID) {
            return rs.get();
        }
    }
    return nullptr;
}

} // namespace skgpu::graphite
