/*
 * Copyright 2024 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/precompile/PaintOption.h"

#include "include/core/SkBlender.h"
#include "include/gpu/graphite/precompile/PrecompileBlender.h"
#include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
#include "include/gpu/graphite/precompile/PrecompileShader.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/KeyContext.h"
#include "src/gpu/graphite/KeyHelpers.h"
#include "src/gpu/graphite/PaintParams.h"
#include "src/gpu/graphite/PaintParamsKey.h"
#include "src/gpu/graphite/PrecompileInternal.h"
#include "src/gpu/graphite/precompile/PrecompileBasePriv.h"
#include "src/gpu/graphite/precompile/PrecompileBlenderPriv.h"
#include "src/gpu/graphite/precompile/PrecompileColorFiltersPriv.h"
#include "src/gpu/graphite/precompile/PrecompileShaderPriv.h"

namespace skgpu::graphite {

PaintOption::PaintOption(bool opaquePaintColor,
                         const std::pair<sk_sp<PrecompileBlender>, int>& finalBlender,
                         const std::pair<sk_sp<PrecompileShader>, int>& shader,
                         const std::pair<sk_sp<PrecompileColorFilter>, int>& colorFilter,
                         bool hasPrimitiveBlender,
                         SkBlendMode primitiveBlendMode,
                         bool skipColorXform,
                         const std::pair<sk_sp<PrecompileShader>, int>& clipShader,
                         Coverage coverage,
                         TextureFormat targetFormat,
                         bool dither,
                         bool analyticClip)
        : fOpaquePaintColor(opaquePaintColor)
        , fFinalBlender(finalBlender)
        , fShader(shader)
        , fColorFilter(colorFilter)
        , fPrimitiveBlendMode(primitiveBlendMode)
        , fHasPrimitiveBlender(hasPrimitiveBlender)
        , fSkipColorXform(skipColorXform)
        , fClipShader(clipShader)
        , fRendererCoverage(coverage)
        , fTargetFormat(targetFormat)
        , fDither(dither)
        , fAnalyticClip(analyticClip) {
    if (this->finalBlender() && this->finalBlender()->priv().asBlendMode() == SkBlendMode::kClear) {
        // Convert all kClear final blends to kSrc + SolidColor(transparent), all other paint
        // effects can be discarded (we have to keep the analytic clip and clip shadow, though).
        fFinalBlender = {PrecompileBlenders::Mode(SkBlendMode::kSrc), 0};
        fOpaquePaintColor = false;
        fShader = { nullptr, 0 };
        fColorFilter = { nullptr, 0 };
        fHasPrimitiveBlender = false;
        fDither = false;
    } else if (!fHasPrimitiveBlender) {
        if (fShader.first && fShader.first->priv().isConstant(fShader.second)) {
            fShader = { nullptr, 0 };
        }
        if (!fShader.first && fColorFilter.first) {
            fColorFilter = { nullptr, 0 };
        }
    }
}

void PaintOption::toKey(const KeyContext& keyContext) const {
    // Don't bother checking the uniform data manager, precompile doesn't depend on those values
    SkDEBUGCODE(keyContext.paintParamsKeyBuilder()->checkReset();)

    // Root Node 0 is the source color, which is the output of all effects post dithering
    // TODO(michaelludwig): This will be used to change from src-over to src in certain scenarios.
    [[maybe_unused]] bool isOpaque = this->handleDithering(keyContext);

    // Root Node 1 is the final blender
    std::optional<SkBlendMode> finalBlendMode =
            this->finalBlender() ? this->finalBlender()->priv().asBlendMode()
                                 : SkBlendMode::kSrcOver;

    if (!finalBlendMode) {
        SkASSERT(this->finalBlender());
        fFinalBlender.first->priv().addToKey(keyContext, fFinalBlender.second);
    } else {
        // Clears are converted to kSrc + SolidColor in the constructor
        SkASSERT(finalBlendMode != SkBlendMode::kClear);

        const bool hasAnalyticClip = fClipShader.first || fAnalyticClip;
        Coverage effectiveCoverage = fRendererCoverage;
        if (effectiveCoverage == Coverage::kNone && hasAnalyticClip) {
            effectiveCoverage = Coverage::kSingleChannel;
        }

        // If the KeyContext has opted into prioritizing Src (no blending) and we don't need
        // blending or only need it for the renderer (e.g. inner fill eligible), then try to keep
        // the final blend snippet as Src when it wouldn't impact the rendering.
        // NOTE: The first two terms here are equivalent to PaintParams::toKey()'s check for
        // (dstUsage == kNone || dstUsage = kDstOnlyUsedByRenderer)
        const bool optimizeSrcBlend =
                !hasAnalyticClip &&
                (finalBlendMode == SkBlendMode::kSrc || finalBlendMode == SkBlendMode::kSrcOver) &&
                SkToBool(keyContext.flags() & KeyGenFlags::kPreferFixedSrcBlend);

        const bool dstReadReq = !CanUseHardwareBlending(keyContext.caps(),
                                                        fTargetFormat,
                                                        *finalBlendMode,
                                                        effectiveCoverage);
        // Match PaintParams::toKey's logic to convert kSrcOver to kSrc
        if (finalBlendMode == SkBlendMode::kSrcOver && isOpaque) {
            const bool dstUsageNone = !hasAnalyticClip && fRendererCoverage == Coverage::kNone;
            if (dstUsageNone && optimizeSrcBlend) {
                SkASSERT(CanUseHardwareBlending(keyContext.caps(), fTargetFormat,
                                                SkBlendMode::kSrc, fRendererCoverage));
                finalBlendMode = SkBlendMode::kSrc;
            }
        }
        if (!dstReadReq || (finalBlendMode == SkBlendMode::kSrc && optimizeSrcBlend)) {
            AddFixedBlendMode(keyContext, *finalBlendMode);
        } else {
            AddBlendMode(keyContext, *finalBlendMode);
        }
    }

    // Optional Root Node 2 is the clip
    this->handleClipping(keyContext);
}

bool PaintOption::addPaintColorToKey(const KeyContext& keyContext) const {
    if (fShader.first) {
        fShader.first->priv().addToKey(keyContext, fShader.second);
        return fShader.first->priv().isOpaque(fShader.second);
    } else {
        RGBPaintColorBlock::AddBlock(keyContext);
        return true;
    }
}

bool PaintOption::handlePrimitiveColor(const KeyContext& keyContext) const {
    if (!fHasPrimitiveBlender) {
        return this->addPaintColorToKey(keyContext);
    }

    if (fSkipColorXform && fPrimitiveBlendMode == SkBlendMode::kDst) {
        AddPrimitiveColor(keyContext, fSkipColorXform);
        return false;
    }

    bool srcIsOpaque = false;
    Blend(keyContext,
            /* addBlendToKey= */ [&] () -> void {
                /**
                 * TODO: Allow clients to provide precompile SkBlender options for primitive
                 * blending. For now we have a back door to internally specify an SkBlendMode.
                 */
                AddToKey(keyContext, GetBlendModeSingleton(fPrimitiveBlendMode));
            },
            /* addSrcToKey= */ [&]() -> void {
                srcIsOpaque = this->addPaintColorToKey(keyContext);
            },
            /* addDstToKey= */ [&]() -> void {
                AddPrimitiveColor(keyContext, fSkipColorXform);
            });
    // NOTE: PaintOption only takes an SkBlendMode for primitive blending, but if it is expanded
    // to accept SkBlenders, then this if should only be taken when the blender is a blend mode.
    if (/* primBlend.has_value() && */srcIsOpaque) {
        return fPrimitiveBlendMode == SkBlendMode::kSrc ||
               fPrimitiveBlendMode == SkBlendMode::kSrcOver;
    } else {
        return false;
    }
}

bool PaintOption::handlePaintAlpha(const KeyContext& keyContext) const {

    if (!fShader.first && !fHasPrimitiveBlender) {
        // If there is no shader and no primitive blending the input to the colorFilter stage
        // is just the premultiplied paint color.
        SolidColorShaderBlock::AddBlock(keyContext, SK_PMColor4fWHITE);
        return fOpaquePaintColor;
    }

    if (!fOpaquePaintColor) {
        Blend(keyContext,
              /* addBlendToKey= */ [&] () -> void {
                  AddFixedBlendMode(keyContext, SkBlendMode::kSrcIn);
              },
              /* addSrcToKey= */ [&]() -> void {
                  this->handlePrimitiveColor(keyContext);
              },
              /* addDstToKey= */ [&]() -> void {
                  AlphaOnlyPaintColorBlock::AddBlock(keyContext);
              });
        return false;
    } else {
        return this->handlePrimitiveColor(keyContext);
    }
}

bool PaintOption::handleColorFilter(const KeyContext& keyContext) const {
    if (fColorFilter.first) {
        bool srcIsOpaque = false;
        Compose(keyContext,
                /* addInnerToKey= */ [&]() -> void {
                    srcIsOpaque = this->handlePaintAlpha(keyContext);
                },
                /* addOuterToKey= */ [&]() -> void {
                    fColorFilter.first->priv().addToKey(keyContext, fColorFilter.second);
                });
        return srcIsOpaque && fColorFilter.first->priv().isAlphaUnchanged(fColorFilter.second);
    } else {
        return this->handlePaintAlpha(keyContext);
    }
}

// This should be kept in sync w/ SkPaintPriv::ShouldDither and PaintParams::should_dither
bool PaintOption::shouldDither(SkColorType dstCT) const {
    // The paint dither flag can veto.
    if (!fDither) {
        return false;
    }

    if (dstCT == kUnknown_SkColorType) {
        return false;
    }

    // We always dither 565 or 4444 when requested.
    if (dstCT == kRGB_565_SkColorType || dstCT == kARGB_4444_SkColorType) {
        return true;
    }

    // Otherwise, dither is only needed for non-const paints.
    return fShader.first && !fShader.first->priv().isConstant(fShader.second);
}

bool PaintOption::handleDithering(const KeyContext& keyContext) const {

#ifndef SK_IGNORE_GPU_DITHER
    SkColorType ct = keyContext.dstColorInfo().colorType();
    if (this->shouldDither(ct)) {
        bool srcIsOpaque = false;
        Compose(keyContext,
                /* addInnerToKey= */ [&]() -> void {
                    srcIsOpaque = this->handleColorFilter(keyContext);
                },
                /* addOuterToKey= */ [&]() -> void {
                    AddDitherBlock(keyContext, ct);
                });
        return srcIsOpaque;
    } else
#endif
    {
        return this->handleColorFilter(keyContext);
    }
}

void PaintOption::handleClipping(const KeyContext& keyContext) const {
    if (fAnalyticClip) {
#if defined(SK_GRAPHITE_USE_LEGACY_RRECT_CLIP_SHADER)
        NonMSAAClipBlock::NonMSAAClipData data(
                /* rect= */ {},
                /* radiusPlusHalf= */ {},
                /* edgeSelect= */ {},
                /* texCoordOffset= */ {},
                /* maskBounds= */ {},
                // TODO: the kAnalyticAndAtlasClip vs. kAnalyticClip decision is based on this
                // being a valid TextureProxy.
                /* atlasTexture= */ nullptr);
        if (fClipShader.first) {
            // For both an analytic clip and clip shader, we need to compose them together into
            // a single clipping root node.
            Blend(keyContext,
                    /* addBlendToKey= */ [&]() -> void {
                        AddFixedBlendMode(keyContext, SkBlendMode::kModulate);
                    },
                    /* addSrcToKey= */ [&]() -> void {
                        NonMSAAClipBlock::AddBlock(keyContext, data);
                    },
                    /* addDstToKey= */ [&]() -> void {
                        fClipShader.first->priv().addToKey(keyContext, fClipShader.second);
                    });
        } else {
            // Without a clip shader, the analytic clip can be the clipping root node.
            NonMSAAClipBlock::AddBlock(keyContext, data);
        }
#else
        NonMSAAClip clip{
            .fAnalyticClip = {
                .fBounds = {0, 0, 1, 1}, // just needs to be non-empty
            },
            // TODO: kAnalyticAndAtlasClip vs. kAnalyticClip decision is based on this being
            // a valid TextureProxy
            .fAtlasClip = {
                .fMaskBounds = {},
                .fOutPos = {},
                .fAtlasTexture = nullptr,
            },
        };
        if (fClipShader.first) {
            // For both an analytic clip and clip shader, we need to compose them together into
            // a single clipping root node.
            Blend(keyContext,
                    /* addBlendToKey= */ [&]() -> void {
                        AddFixedBlendMode(keyContext, SkBlendMode::kModulate);
                    },
                    /* addSrcToKey= */ [&]() -> void {
                        AddAnalyticClip(keyContext, clip);
                    },
                    /* addDstToKey= */ [&]() -> void {
                        fClipShader.first->priv().addToKey(keyContext, fClipShader.second);
                    });
        } else {
            // Without a clip shader, the analytic clip can be the clipping root node.
            AddAnalyticClip(keyContext, clip);
        }
#endif // SK_GRAPHITE_USE_LEGACY_RRECT_CLIP_SHADER
    } else if (fClipShader.first) {
        // Since there's no analytic clip, the clipping root node can be fClipShader directly.
        fClipShader.first->priv().addToKey(keyContext, fClipShader.second);
    }
}

} // namespace skgpu::graphite
