/*
 * 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 "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/gpu/graphite/PrecompileContext.h"
#include "include/gpu/graphite/precompile/Precompile.h"
#include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
#include "include/private/SkAttributes.h"
#include "include/private/SkLog.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/GraphicsPipeline.h"
#include "src/gpu/graphite/GraphicsPipelineDesc.h"
#include "src/gpu/graphite/GraphicsPipelineHandle.h"
#include "src/gpu/graphite/KeyContext.h"
#include "src/gpu/graphite/PipelineCreationTask.h"
#include "src/gpu/graphite/PipelineData.h"
#include "src/gpu/graphite/PrecompileContextPriv.h"
#include "src/gpu/graphite/PrecompileInternal.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/Renderer.h"
#include "src/gpu/graphite/RendererProvider.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "src/gpu/graphite/RuntimeEffectDictionary.h"
#include "src/gpu/graphite/TextureInfoPriv.h"
#include "src/gpu/graphite/UniquePaintParamsID.h"
#include "src/gpu/graphite/precompile/PaintOptionsPriv.h"
#include "src/gpu/graphite/precompile/PrecompileColorFiltersPriv.h"

namespace {

using namespace skgpu::graphite;

void compile(SharedContext* sharedContext,
             const KeyContext& keyContext,
             UniquePaintParamsID uniqueID,
             DrawTypeFlags drawTypes,
             const RenderPassDesc& renderPassDesc,
             bool withPrimitiveBlender,
             Coverage coverage) {

    const RendererProvider* rendererProvider = sharedContext->rendererProvider();
    PipelineManager* pipelineManager = sharedContext->pipelineManager();

    const TextureFormat dsFormat = renderPassDesc.fDepthStencilAttachment.fFormat;
    for (const Renderer* r : rendererProvider->renderers()) {
        if (!(r->drawTypes() & drawTypes)) {
            continue;
        }

        if (r->emitsPrimitiveColor() != withPrimitiveBlender) {
            // UniqueIDs are explicitly built either w/ or w/o primitiveBlending so must
            // match what the Renderer requires
            continue;
        }

        if (r->coverage() != coverage) {
            // For now, UniqueIDs are explicitly built with a specific type of coverage so must
            // match what the Renderer requires
            continue;
        }

        if (r->requiresDepth() && !TextureFormatHasDepth(dsFormat)) {
            // This renderer requires depth, which is incompatible with the requested render pass,
            // so skip it.
            continue;
        }
        if (r->usesStencil() && !TextureFormatHasStencil(dsFormat)) {
            // This renderer requires stencil, which is incompatible with the requested render pass,
            // so skip it.
            continue;
        }
        if (r->requiresMSAA() && renderPassDesc.fSampleCount == SampleCount::k1) {
            // This renderer expects MSAA, which is incompatible with the requested render pass,
            // so skip it.
            continue;
        }

        for (auto&& s : r->steps()) {
            SkASSERT(!s->performsShading() || s->emitsPrimitiveColor() == withPrimitiveBlender);

            UniquePaintParamsID paintID = s->performsShading() ? uniqueID
                                                               : UniquePaintParamsID::Invalid();

            GraphicsPipelineHandle handle = pipelineManager->createHandle(
                    sharedContext,
                    keyContext.rtEffectDict(),
                    { s->renderStepID(), paintID },
                    renderPassDesc,
                    PipelineCreationFlags::kForPrecompilation);
        }
    }
}

} // anonymous namespace

namespace skgpu::graphite {

void Precompile(PrecompileContext* precompileContext,
                const PaintOptions& options,
                DrawTypeFlags drawTypes,
                SkSpan<const RenderPassProperties> renderPassProperties) {

    ShaderCodeDictionary* dict = precompileContext->priv().shaderCodeDictionary();
    const RendererProvider* rendererProvider = precompileContext->priv().rendererProvider();
    SharedContext* sharedContext = precompileContext->priv().sharedContext();
    PipelineManager* pipelineManager = sharedContext->pipelineManager();
    const Caps* caps = precompileContext->priv().caps();

    sk_sp<RuntimeEffectDictionary> rtEffectDict = sk_make_sp<RuntimeEffectDictionary>();

    for (const RenderPassProperties& rpp : renderPassProperties) {
        // TODO: Allow the client to pass in mipmapping and protection too?
        TextureInfo info = caps->getDefaultSampledTextureInfo(rpp.fDstCT,
                                                              Mipmapped::kNo,
                                                              Protected::kNo,
                                                              Renderable::kYes);
        std::optional<Swizzle> writeSwizzle = WriteSwizzleForColorType(
                rpp.fDstCT, TextureInfoPriv::ViewFormat(info));
        if (!writeSwizzle.has_value()) {
            continue; // Skip generating pipelines that would never show up at runtime
        }

        // TODO(robertphillips): address mismatches between the MSAA requirements of the Renderers
        // associated w/ the requested drawTypes and the specified MSAA setting

        // On Native Metal, the LoadOp, StoreOp and clearColor fields don't influence
        // the actual RenderPassDescKey.
        // For Dawn, the LoadOp will sometimes matter. We add an extra LoadOp::kLoad combination
        // when necessary.
        const LoadOp kLoadOps[2] = { LoadOp::kClear, LoadOp::kLoad };

        int numLoadOps = 1;
        if (rpp.fRequiresMSAA &&
            !caps->msaaRenderToSingleSampledSupport() &&
            caps->loadOpAffectsMSAAPipelines()) {
            numLoadOps = 2;
        }

        for (int loadOpIndex = 0; loadOpIndex < numLoadOps; ++loadOpIndex) {
            const RenderPassDesc renderPassDesc =
                    RenderPassDesc::Make(caps,
                                         info,
                                         SK_UNSAFE_TODO(kLoadOps[loadOpIndex]),
                                         StoreOp::kStore,
                                         rpp.fDSFlags,
                                         /* clearColor= */ { .0f, .0f, .0f, .0f },
                                         rpp.fRequiresMSAA,
                                         *writeSwizzle,
                                         caps->getDstReadStrategy());

            SkColorInfo ci(rpp.fDstCT, kPremul_SkAlphaType, rpp.fDstCS);

            // The PipelineDataGatherer handles uniform data; in the pre-compile case we don't need
            // to record the uniform data but the process of generating it is required to create the
            // correct key.
            PipelineDataGatherer gatherer(Layout::kMetal);
            PaintParamsKeyBuilder builder(dict);
            KeyContext keyContext(caps, &builder, &gatherer, dict, rtEffectDict, ci);

            for (Coverage coverage : { Coverage::kNone, Coverage::kSingleChannel }) {
                PrecompileCombinations(
                        sharedContext,
                        options, keyContext,
                        static_cast<DrawTypeFlags>(drawTypes & ~(DrawTypeFlags::kBitmapText_Color |
                                                                 DrawTypeFlags::kBitmapText_LCD |
                                                                 DrawTypeFlags::kSDFText_LCD |
                                                                 DrawTypeFlags::kDrawVertices |
                                                                 DrawTypeFlags::kDropShadows)),
                        /* withPrimitiveBlender= */ false,
                        coverage,
                        renderPassDesc);
            }

            if (drawTypes & DrawTypeFlags::kNonSimpleShape) {
                // Special case handling to pick up the:
                //     "CoverBoundsRenderStep[InverseCover] + (empty)"
                // pipelines.
                const RenderStep* renderStep =
                    rendererProvider->lookup(RenderStep::RenderStepID::kCoverBounds_InverseCover);

                if (rpp.fDSFlags & DepthStencilFlags::kStencil) {
                    GraphicsPipelineHandle handle = pipelineManager->createHandle(
                            sharedContext,
                            keyContext.rtEffectDict(),
                            { renderStep->renderStepID(), UniquePaintParamsID::Invalid() },
                            renderPassDesc,
                            PipelineCreationFlags::kForPrecompilation);
                }
            }

            if (drawTypes & DrawTypeFlags::kBitmapText_Color) {
                DrawTypeFlags reducedTypes =
                        static_cast<DrawTypeFlags>(drawTypes & (DrawTypeFlags::kBitmapText_Color |
                                                                DrawTypeFlags::kAnalyticClip));
                // For color emoji text, shaders don't affect the final color
                PaintOptions tmp = options;
                tmp.setShaders({});
                tmp.priv().setPrimitiveBlendMode(SkBlendMode::kDstIn);

                // ARGB text doesn't emit coverage and always has a primitive blender
                PrecompileCombinations(sharedContext,
                                       tmp,
                                       keyContext,
                                       reducedTypes,
                                       /* withPrimitiveBlender= */ true,
                                       Coverage::kNone,
                                       renderPassDesc);
            }

            if (drawTypes & (DrawTypeFlags::kBitmapText_LCD | DrawTypeFlags::kSDFText_LCD)) {
                DrawTypeFlags reducedTypes =
                        static_cast<DrawTypeFlags>(drawTypes & (DrawTypeFlags::kBitmapText_LCD |
                                                                DrawTypeFlags::kSDFText_LCD |
                                                                DrawTypeFlags::kAnalyticClip));
                // LCD-based text always emits LCD coverage but never has primitiveBlenders
                PrecompileCombinations(
                        sharedContext,
                        options, keyContext,
                        reducedTypes,
                        /* withPrimitiveBlender= */ false,
                        Coverage::kLCD,
                        renderPassDesc);
            }

            if (drawTypes & DrawTypeFlags::kDrawVertices) {
                DrawTypeFlags reducedTypes =
                        static_cast<DrawTypeFlags>(drawTypes & (DrawTypeFlags::kDrawVertices |
                                                                DrawTypeFlags::kAnalyticClip));
                // drawVertices w/ colors use a primitiveBlender while those w/o don't. It never
                // emits coverage.
                for (bool withPrimitiveBlender : { true, false }) {
                    PrecompileCombinations(sharedContext,
                                           options, keyContext,
                                           reducedTypes,
                                           withPrimitiveBlender,
                                           Coverage::kNone,
                                           renderPassDesc);
                }
            }

            if (drawTypes & DrawTypeFlags::kDropShadows) {
                DrawTypeFlags reducedTypes =
                        static_cast<DrawTypeFlags>(drawTypes & (DrawTypeFlags::kDropShadows |
                                                                DrawTypeFlags::kAnalyticClip));

                PaintOptions newOptions;
                newOptions.setBlendModes(SKSPAN_INIT_ONE(SkBlendMode::kSrcOver));

                // Analytic
                {
                    PrecompileCombinations(sharedContext,
                                           newOptions, keyContext,
                                           reducedTypes,
                                           /* withPrimitiveBlender= */ false,
                                           Coverage::kSingleChannel,
                                           renderPassDesc);
                }

                // Geometric
                {
                    sk_sp<PrecompileColorFilter> cf = PrecompileColorFilters::Compose(
                            {{ PrecompileColorFilters::Blend(SKSPAN_INIT_ONE(SkBlendMode::kModulate)) }},
                            {{ PrecompileColorFiltersPriv::Gaussian() }});

                    newOptions.setColorFilters({{ std::move(cf) }});
                    newOptions.priv().setPrimitiveBlendMode(SkBlendMode::kDst);
                    newOptions.priv().setSkipColorXform(true);

                    PrecompileCombinations(sharedContext,
                                           newOptions, keyContext,
                                           reducedTypes,
                                           /* withPrimitiveBlender= */ true,
                                           Coverage::kNone,
                                           renderPassDesc);
                }
            }
        }
    }
}

void PrecompileCombinations(SharedContext* sharedContext,
                            const PaintOptions& options,
                            const KeyContext& keyContext,
                            DrawTypeFlags drawTypes,
                            bool withPrimitiveBlender,
                            Coverage coverage,
                            const RenderPassDesc& renderPassDescIn) {
    if (drawTypes == DrawTypeFlags::kNone) {
        return;
    }

    options.priv().buildCombinations(
        keyContext,
        drawTypes,
        withPrimitiveBlender,
        coverage,
        renderPassDescIn,
        [sharedContext, &keyContext](UniquePaintParamsID uniqueID,
                                     DrawTypeFlags drawTypes,
                                     bool withPrimitiveBlender,
                                     Coverage coverage,
                                     const RenderPassDesc& renderPassDesc) {
               compile(sharedContext,
                       keyContext,
                       uniqueID,
                       drawTypes,
                       renderPassDesc,
                       withPrimitiveBlender,
                       coverage);
        });
}

} // namespace skgpu::graphite
