/*
 * 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/PaintParams.h"

#include "include/core/SkColorSpace.h"
#include "include/core/SkShader.h"
#include "src/core/SkBlendModeBlender.h"
#include "src/core/SkBlenderBase.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkImageInfoPriv.h"
#include "src/effects/colorfilters/SkColorFilterBase.h"
#include "src/gpu/Blend.h"
#include "src/gpu/DitherUtils.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/DrawContext.h"
#include "src/gpu/graphite/KeyContext.h"
#include "src/gpu/graphite/KeyHelpers.h"
#include "src/gpu/graphite/PaintParamsKey.h"
#include "src/gpu/graphite/PipelineData.h"
#include "src/gpu/graphite/RecorderPriv.h"

namespace skgpu::graphite {

namespace {

// This should be kept in sync w/ SkPaintPriv::ShouldDither and PaintOption::shouldDither
bool should_dither(const PaintParams& p, SkColorType dstCT) {
    // The paint dither flag can veto.
    if (!p.dither()) {
        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 p.imageShader() || (p.shader() && !as_SB(p.shader())->isConstant());
}

std::pair<const SkBlender*, SkBlendMode> get_final_blend(const SkBlender* blender) {
    if (!blender) {
        return {nullptr, SkBlendMode::kSrcOver};
    }

    auto optionalBlendMode = as_BB(blender)->asBlendMode();
    if (optionalBlendMode.has_value()) {
        return {nullptr, *optionalBlendMode};
    } else {
        return {blender, SkBlendMode::kSrc};
    }
}

// This produces the final DstUsage flags except for the src-over case, which returns flags assuming
// that it is opaque and optimized to src. Once toKey() determines opacity, the flags only need to
// be adjusted if that assumption no longer holds.
SkEnumBitMask<DstUsage> get_dst_usage(const Caps* caps,
                                      TextureFormat targetFormat,
                                      const PaintParams& paint,
                                      Coverage rendererCoverage,
                                      const SkShader* clipShader,
                                      const NonMSAAClip& nonMSAAClip) {
    SkEnumBitMask<DstUsage> dstUsage = DstUsage::kDependsOnDst;
    if (paint.finalBlender()) {
        dstUsage |= DstUsage::kDstReadRequired;
    } else {
        const bool hasAnalyticClip = clipShader || !nonMSAAClip.isEmpty();
        Coverage effectiveCoverage = rendererCoverage;
        if (effectiveCoverage == Coverage::kNone && hasAnalyticClip) {
            effectiveCoverage = Coverage::kSingleChannel;
        }

        const SkBlendMode finalBlendMode = paint.finalBlendMode();
        if (!CanUseHardwareBlending(caps, targetFormat, finalBlendMode, effectiveCoverage)) {
            dstUsage |= DstUsage::kDstReadRequired;
        }
        if (finalBlendMode > SkBlendMode::kLastCoeffMode) {
            dstUsage |= DstUsage::kAdvancedBlend;
        }

        if (!hasAnalyticClip && (finalBlendMode == SkBlendMode::kSrc ||
                                 finalBlendMode == SkBlendMode::kSrcOver)) {
            if (rendererCoverage != Coverage::kNone) {
                // For kSrc, kDstOnlyUsedByRenderer is the correct final usage. For kSrcOver,
                // we optimistically add it on the assumption the rest of the paint will be
                // opaque. toKey() must remove this flag if it's not opaque.
                dstUsage |= DstUsage::kDstOnlyUsedByRenderer;
            } else {
                // For kSrc, we definitely now do not depend on the dst so we can remove that
                // flag entirely. Optimistically we also remove it for kSrcOver under the
                // assumption that the paint is opaque; if toKey() finds that is not the case,
                // it must restore the flag.
                SkASSERT(dstUsage == DstUsage::kDependsOnDst);
                dstUsage = DstUsage::kNone;
            }
        }

    }
    return dstUsage;
}

} // anonymous namespace

PaintParams::PaintParams(const SkPaint& paint,
                         const SimpleImage* imageOverride,
                         const SkBlender* primitiveBlender,
                         bool skipColorXform,
                         bool ignoreShader)
        : fColor(paint.getColor4f())
        , fFinalBlend(get_final_blend(paint.getBlender()))
        , fShader(ignoreShader ? nullptr : paint.getShader())
        , fImageShader(imageOverride)
        , fColorFilter(paint.getColorFilter())
        , fPrimitiveBlender(primitiveBlender)
        , fSkipColorXform(skipColorXform)
        , fDither(paint.isDither()) {
    if (fFinalBlend.second == SkBlendMode::kClear) {
        // None of the other effects are relevant, the final src color for blending is transparent
        // and we can consolidate its blend mode to kSrc. This is helpful to restrict the number of
        // pipelines that will actually have DstUsage::kNone.
        fFinalBlend.second = SkBlendMode::kSrc;
        fColor = SkColors::kTransparent;
        fShader = nullptr;
        fImageShader = nullptr;
        fColorFilter = nullptr;
        fPrimitiveBlender = nullptr;
        fDither = false;
    } else if (!fPrimitiveBlender) {
        // NOTE: We can still have an alpha-only fImageShader and still want to try simplifying the
        // paint's shader to a solid color for the alpha image's colorization.
        SkColor4f constantColor;
        if (fShader && as_SB(fShader)->isConstant(&constantColor)) {
            // The original fColor and `constantColor` are un-premul sRGB, but we need to preserve
            // the paint's alpha.
            float origA = fColor.fA;
            fColor = constantColor;
            fColor.fA *= origA;
            fShader = nullptr;
        }
        // We can't apply the color filter to the color if a shader modifies it, including when the
        // image shader is alpha-only. The image's per-pixel alpha modulates the paint color
        // *before* the color filter is evaluated.
        if (!fShader && !fImageShader && fColorFilter) {
            fColor = fColorFilter->filterColor4f(fColor,
                                                 sk_srgb_singleton(),
                                                 sk_srgb_singleton());
            fColorFilter = nullptr;
        }
    }
}

PaintParams::PaintParams(const SkPaint& paint,
                         const SkBlender* primitiveBlender,
                         bool skipColorXform,
                         bool ignoreShader)
        : PaintParams(paint,
                      /*imageOverride=*/nullptr,
                      primitiveBlender,
                      skipColorXform,
                      ignoreShader) {}


PaintParams::PaintParams(const SkPaint& paint, const SimpleImage& imageOverride, float xtraAlpha)
        : PaintParams(paint,
                      &imageOverride,
                      /*primitiveBlender=*/nullptr,
                      /*skipColorXform=*/false,
                      // For color images, the paint's original shader is ignored.
                      /*ignoreShader=*/!SkColorTypeIsAlphaOnly(imageOverride.fImage->colorType())) {
    // Multiply in the extra alpha that's allowed to be set on an ImageSetEntry. Accepting it here
    // avoids needing to modify the SkPaint providing the base color.
    fColor.fA *= xtraAlpha;
}

PaintParams::PaintParams(const SkPaint& paint, const SkColor4f& colorOverride)
        : PaintParams(paint,
                      /*imageOverride=*/nullptr,
                      /*primitiveBlender=*/nullptr,
                      /*skipColorXform=*/false,
                      /*ignoreShader*/true) {
    float newAlpha = fColor.fA * colorOverride.fA;
    fColor = colorOverride.withAlpha(newAlpha);
}

PaintParams::PaintParams(const SkColor4f& color, SkBlendMode finalBlendMode)
        : fColor(finalBlendMode == SkBlendMode::kClear ? SkColors::kTransparent : color)
        , fFinalBlend({nullptr, finalBlendMode == SkBlendMode::kClear ? SkBlendMode::kSrc
                                                                      : finalBlendMode})
        , fShader(nullptr)
        , fImageShader(nullptr)
        , fColorFilter(nullptr)
        , fPrimitiveBlender(nullptr)
        , fSkipColorXform(false)
        , fDither(false) {}

PaintParams PaintParams::makeWithPrimitiveColor(const SkBlender* primitiveBlender,
                                                const SkColor4f& primitiveColorOverride) const {
    PaintParams copy = *this;
    copy.fPrimitiveBlender = primitiveBlender;
    copy.fPrimitiveColorOverride = primitiveColorOverride;
    return copy;
}

SkColor4f PaintParams::Color4fPrepForDst(SkColor4f srcColor, const SkColorInfo& dstColorInfo) {
    // xform from sRGB to the destination colorspace
    SkColorSpaceXformSteps steps(sk_srgb_singleton(),       kUnpremul_SkAlphaType,
                                 dstColorInfo.colorSpace(), kUnpremul_SkAlphaType);

    SkColor4f result = srcColor;
    steps.apply(result.vec());
    return result;
}

#if defined(SK_DEBUG)
PaintParams PaintParams::MakeOpaque(const PaintParams& paint) {
    PaintParams opaque = paint;
    opaque.fFinalBlend = {nullptr, SkBlendMode::kSrc};
    opaque.fColor = opaque.fColor.makeOpaque();
    return opaque;
}
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////

ShadingParams::ShadingParams(const Caps* caps,
                             const PaintParams& paint,
                             const NonMSAAClip& nonMSAAClip,
                             const SkShader* clipShader,
                             Coverage coverage,
                             TextureFormat targetFormat)
        : fPaint(paint)
        , fNonMSAAClip(nonMSAAClip)
        , fClipShader(clipShader)
        , fDstUsage(get_dst_usage(caps, targetFormat, paint, coverage, fClipShader, fNonMSAAClip))
#if defined(SK_DEBUG)
        , fCoverage(coverage)
#endif
        {}

bool ShadingParams::addPaintColorToKey(const KeyContext& keyContext) const {
    const auto& simpleImage = fPaint.imageShader();
    if (simpleImage) {
        // There is an implicit image shader, match handling of SkModifyPaintForDrawImageRect
        if (fPaint.shader()) {
            // Alpha-only images for drawImageRect() get colorized with the paint's shader. This
            // differs from alpha-only image shaders that might be encountered within an SkShader
            // graph, which get colorized by the paint's opaque color.
            SkASSERT(SkColorTypeIsAlphaOnly(simpleImage->fImage->colorType()));
            Blend(keyContext,
                  /* addBlendToKey */ [&] () -> void {
                      AddFixedBlendMode(keyContext, SkBlendMode::kDstIn);
                  },
                  /* addSrcToKey = */ [&] () -> void {
                      // Since colorization is handled here, disable paint color-colorization later.
                      AddToKey(keyContext.withExtraFlags(
                                       KeyGenFlags::kDisableAlphaOnlyImageColorization),
                               *simpleImage);
                  },
                  /* addDstToKey = */ [&] () -> void {
                      AddToKey(keyContext, fPaint.shader());
                  });
            return false; // Colorizing with an alpha-only texture probably isn't opaque
        } else {
            // Encode the image structure directly, which includes handling alpha-only images that
            // combine with the paint's color (RGB1) stored on `keyContext`.
            AddToKey(keyContext, *simpleImage);
            return simpleImage->fImage->isOpaque();
        }
    } else if (fPaint.shader()) {
        AddToKey(keyContext, fPaint.shader());
        return fPaint.shader()->isOpaque();
    } else {
        RGBPaintColorBlock::AddBlock(keyContext);
        return true; // rgb1, always opaque
    }
}

/**
 * Primitive blend blocks are used to blend either the paint color or the output of another shader
 * with a primitive color emitted by certain draw geometry calls (drawVertices, drawAtlas, etc.).
 * Dst: primitiveColor Src: Paint color/shader output
 */
bool ShadingParams::handlePrimitiveColor(const KeyContext& keyContext) const {
    // If no primitive blending is required, simply add the paint color.
    if (!fPaint.primitiveBlender()) {
        return this->addPaintColorToKey(keyContext);
    }

    // If no color space conversion is required and the primitive blend mode is kDst, the src
    // branch of the blend does not matter and we can simply emit the primitive color.
    std::optional<SkBlendMode> primBlend = as_BB(fPaint.primitiveBlender())->asBlendMode();
    const bool canSkipBlendStep = fPaint.skipPrimitiveColorXform() &&
                                  primBlend == SkBlendMode::kDst;

    std::optional<SkPMColor4f> primColorOverride;
    if (fPaint.primitiveColorOverride()) {
        primColorOverride = PaintParams::Color4fPrepForDst(*fPaint.primitiveColorOverride(),
                                                           keyContext.dstColorInfo()).premul();
    }

    if (canSkipBlendStep) {
        if (primColorOverride) {
            SolidColorShaderBlock::AddBlock(keyContext, *primColorOverride);
        } else {
            AddPrimitiveColor(keyContext, fPaint.skipPrimitiveColorXform(),
                              fPaint.primitiveColorSpace(), fPaint.primitiveAlphaType());
        }
        return false;
    }

    bool srcIsOpaque = false;
    Blend(keyContext,
        /* addBlendToKey= */ [&] () -> void {
            AddToKey(keyContext, fPaint.primitiveBlender());
        },
        /* addSrcToKey= */ [&] () -> void {
            srcIsOpaque = this->addPaintColorToKey(keyContext);
        },
        /* addDstToKey= */ [&] () -> void {
            if (primColorOverride) {
                SolidColorShaderBlock::AddBlock(keyContext, *primColorOverride);
            } else {
                AddPrimitiveColor(keyContext, fPaint.skipPrimitiveColorXform(),
                                  fPaint.primitiveColorSpace(), fPaint.primitiveAlphaType());
            }
        });
    if (primBlend.has_value() && srcIsOpaque) {
        // If the input paint/shader is opaque, the result is only opaque if the primitive blend
        // mode is kSrc or kSrcOver. All other modes can introduce transparency.
        return *primBlend == SkBlendMode::kSrc || *primBlend == SkBlendMode::kSrcOver;
    }

    // If the input was already transparent, or if it's a runtime/complex blend mode,
    // the result cannot be considered opaque.
    return false;
}

// Apply the paint's alpha value.
bool ShadingParams::handlePaintAlpha(const KeyContext& keyContext) const {
    if (!fPaint.shader() && !fPaint.imageShader() && !fPaint.primitiveBlender()) {
        // If there is no shader and no primitive blending the input to the colorFilter stage
        // is just the premultiplied paint color.
        SkPMColor4f paintColor = PaintParams::Color4fPrepForDst(fPaint.color(),
                                                                keyContext.dstColorInfo()).premul();
        SolidColorShaderBlock::AddBlock(keyContext, paintColor);
        return fPaint.color().isOpaque();
    }

    if (!fPaint.color().isOpaque()) {
        Blend(keyContext,
              /* addBlendToKey= */ [&] () -> void {
                  AddFixedBlendMode(keyContext, SkBlendMode::kSrcIn);
              },
              /* addSrcToKey= */ [&]() -> void {
                  this->handlePrimitiveColor(keyContext);
              },
              /* addDstToKey= */ [&]() -> void {
                  AlphaOnlyPaintColorBlock::AddBlock(keyContext);
              });
        // The result is guaranteed to be non-opaque because we're blending with fColor's alpha.
        return false;
    } else {
        return this->handlePrimitiveColor(keyContext);
    }
}

bool ShadingParams::handleColorFilter(const KeyContext& keyContext) const {
    if (fPaint.colorFilter()) {
        bool srcIsOpaque = false;
        Compose(keyContext,
                /* addInnerToKey= */ [&]() -> void {
                    srcIsOpaque = this->handlePaintAlpha(keyContext);
                },
                /* addOuterToKey= */ [&]() -> void {
                    AddToKey(keyContext, fPaint.colorFilter());
                });
        return srcIsOpaque && fPaint.colorFilter()->isAlphaUnchanged();
    } else {
        return this->handlePaintAlpha(keyContext);
    }
}

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

#ifndef SK_IGNORE_GPU_DITHER
    SkColorType ct = keyContext.dstColorInfo().colorType();
    if (should_dither(fPaint, 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 ShadingParams::handleClipping(const KeyContext& keyContext) const {
    SkASSERT(!fNonMSAAClip.isEmpty() || fClipShader);
    if (!fNonMSAAClip.isEmpty()) {
#if defined(SK_GRAPHITE_USE_LEGACY_RRECT_CLIP_SHADER)
        const AnalyticClip& analyticClip = fNonMSAAClip.fAnalyticClip;
        SkPoint radiusPair;
        SkRect analyticBounds;
        if (!analyticClip.isEmpty()) {
            float radius = analyticClip.fRadius + 0.5f;
            // N.B.: Because the clip data is normally used with depth-based clipping,
            // the shape is inverted from its usual state. We re-invert here to
            // match what the shader snippet expects.
            radiusPair = {(analyticClip.fInverted) ? radius : -radius, 1.0f/radius};
            analyticBounds = analyticClip.fBounds.makeOutset(0.5f).asSkRect();
        } else {
            // This will generate no analytic clip.
            radiusPair = { -0.5f, 1.f };
            analyticBounds = { 0, 0, 0, 0 };
        }

        const AtlasClip& atlasClip = fNonMSAAClip.fAtlasClip;
        SkISize maskSize = atlasClip.fMaskBounds.size();
        SkRect texMaskBounds = SkRect::MakeXYWH(atlasClip.fOutPos.x(), atlasClip.fOutPos.y(),
                                                maskSize.width(), maskSize.height());
        // Outset bounds to capture some of the padding (necessary for inverse clip)
        texMaskBounds.outset(0.5f, 0.5f);
        SkPoint texCoordOffset = SkPoint::Make(atlasClip.fOutPos.x() - atlasClip.fMaskBounds.left(),
                                               atlasClip.fOutPos.y() - atlasClip.fMaskBounds.top());

        NonMSAAClipBlock::NonMSAAClipData data(
                analyticBounds,
                radiusPair,
                analyticClip.edgeSelectRect(),
                texCoordOffset,
                texMaskBounds,
                atlasClip.fAtlasTexture);
        if (fClipShader) {
            // 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 {
                      AddToKey(keyContext, fClipShader);
                  });
        } else {
            // Without a clip shader, the analytic clip can be the clipping root node.
            NonMSAAClipBlock::AddBlock(keyContext, data);
        }
#else
        if (fClipShader) {
            // 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, fNonMSAAClip);
                  },
                  /* addDstToKey= */ [&]() -> void {
                      AddToKey(keyContext, fClipShader);
                  });
        } else {
            // Without a clip shader, the analytic clip can be the clipping root node.
            AddAnalyticClip(keyContext, fNonMSAAClip);
        }
#endif // SK_GRAPHITE_USE_LEGACY_RRECT_CLIP_SHADER
    } else {
        // Since there's no analytic clip, the clipping root node can be fClipShader directly.
        SkASSERT(fClipShader);
        AddToKey(keyContext, fClipShader);
    }
}

std::optional<ShadingParams::Result> ShadingParams::toKey(const KeyContext& keyContext) const {
    SkDEBUGCODE(keyContext.pipelineDataGatherer()->checkReset());
    SkDEBUGCODE(keyContext.paintParamsKeyBuilder()->checkReset());
    SkDEBUGCODE(const Caps* caps = keyContext.caps();)
    SkDEBUGCODE(TextureFormat format = keyContext.drawContext()->target().proxy()->format();)
    SkDEBUGCODE(bool paintDependsOnDst = true;)

    // Root Node 0 is the source color, which is the output of all effects post dithering
    keyContext.paintParamsKeyBuilder()->addRootBlockHeader(RootBlockType::kSrcColor);
    bool isOpaque = this->handleDithering(keyContext);

    // Root Node 1 is the final blender
    keyContext.paintParamsKeyBuilder()->addRootBlockHeader(RootBlockType::kFinalBlend);
    SkEnumBitMask<DstUsage> dstUsage = fDstUsage;
    if (fPaint.finalBlender()) {
        AddToKey(keyContext, fPaint.finalBlender());
    } else {
        // We converted kClear blends to kSrc; the PaintParams constructor already set every other
        // paint effect to match a transparent solid color.
        SkBlendMode finalBlendMode = fPaint.finalBlendMode();
        SkASSERT(finalBlendMode != SkBlendMode::kClear);

        // If the KeyContext has opted into prioritizing Src (no blending) and we actually don't
        // need blending or only need blending due to the renderer (e.g. inner fill eligible), then
        // try to keep the final blend snippet as Src when it wouldn't impact the rendering.
        const bool optimizeSrcBlend =
                (dstUsage == DstUsage::kNone ||
                        SkToBool(dstUsage & DstUsage::kDstOnlyUsedByRenderer)) &&
                SkToBool(keyContext.flags() & KeyGenFlags::kPreferFixedSrcBlend);

        // fDstUsage was almost fully specified, except for kSrcOver, which was assumed to be
        // opaque and eligible for conversion to kSrc. If we're src over and not opaque, or not
        // eligible for reducing to kSrc, we have to adjust flags.
        if (finalBlendMode == SkBlendMode::kSrcOver) {
            if (isOpaque) {
                if (dstUsage == DstUsage::kNone && optimizeSrcBlend) {
                    // We can change the blend mode here without re-checking
                    // CanUseHardwareBlending() because DstUsage::kNone implies there's no analytic
                    // coverage and we're just changing from one Porter-Duff blend mode to another.
                    SkASSERT(CanUseHardwareBlending(caps, format, SkBlendMode::kSrc, fCoverage));
                    finalBlendMode = SkBlendMode::kSrc;
                } else {
                    // We don't have to remove kDstOnlyUsedByRenderer, but since we aren't
                    // optimizing to Src, add the optimistically avoided kDependsOnDst
                    dstUsage |= DstUsage::kDependsOnDst;
                }
            } else {
                // Definitely not eligible for conversion to kSrc, remove optimistically added flag
                dstUsage &= ~DstUsage::kDstOnlyUsedByRenderer;
                dstUsage |= DstUsage::kDependsOnDst;
            }
        }

        SkDEBUGCODE(paintDependsOnDst = finalBlendMode != SkBlendMode::kSrc;)
        // Reset isOpaque to false if we aren't src-over to ensure later assert logic is narrow.
        SkDEBUGCODE(isOpaque &= finalBlendMode == SkBlendMode::kSrcOver;)
        if (!(dstUsage & DstUsage::kDstReadRequired) ||
            (finalBlendMode == SkBlendMode::kSrc && optimizeSrcBlend)) {
            // With no shader blending, be as explicit as possible about the final blend. We also
            // keep a fixed Src mode if it means a follow-up inner fill could be used.
            AddFixedBlendMode(keyContext, finalBlendMode);
        } else {
            // With shader blending, use AddBlendMode() to select the more universal blend functions
            // when possible. Technically we could always use a fixed blend mode but would then
            // over-generate when encountering certain classes of blends. This is most problematic
            // on devices that wouldn't support dual-source blending, so help them out by at least
            // not requiring lots of pipelines.
            AddBlendMode(keyContext, finalBlendMode);
        }
    }

    // Optional Root Node 2 is the clip
    if (fClipShader || !fNonMSAAClip.isEmpty()) {
        keyContext.paintParamsKeyBuilder()->addRootBlockHeader(RootBlockType::kClip);
        this->handleClipping(keyContext);
    }

    // If dstUsage is not kNone, then kDependsOnDst must be set (all other bits only apply *because*
    // the shading depends on dst).
    SkASSERT(dstUsage == DstUsage::kNone || (dstUsage & DstUsage::kDependsOnDst));

    // If dstUsage is kNone, then there cannot be renderer coverage, analytic clipping, or the paint
    // depending on the dst color.
    SkASSERT(dstUsage != DstUsage::kNone || !(paintDependsOnDst ||
                                              fClipShader ||
                                              !fNonMSAAClip.isEmpty() ||
                                              fCoverage != Coverage::kNone));

    // If kDstOnlyUsedByRenderer is set, the paint shouldn't depend on the dst and the dst usage
    // when the Renderer has Coverage::kNone should equal kNone.
    SkDEBUGCODE(auto dstUsageNoCoverage =
            get_dst_usage(caps, format, fPaint, Coverage::kNone, fClipShader, fNonMSAAClip);)
    // This checks isOpaque in addition to !paintDependsOnDst to handle the case where src-over +
    // opaque wasn't converted to src for *this* pipeline but remains kDstOnlyUsedByRenderer for
    // a possible inner fill.
    SkASSERT(!(dstUsage & DstUsage::kDstOnlyUsedByRenderer) ||
             ((isOpaque || !paintDependsOnDst) && dstUsageNoCoverage == DstUsage::kNone));
    UniquePaintParamsID paintID =
            keyContext.recorder()->priv().shaderCodeDictionary()->findOrCreate(
                    keyContext.paintParamsKeyBuilder());
    if (!paintID.isValid()) {
        return {};
    } else {
        return Result{paintID, dstUsage};
    }
}

UniquePaintParamsID ShadingParams::optimizeForOpacity(const KeyContext& keyContext,
                                                      UniquePaintParamsID origPaint) const {
    // The builder should be starting from exactly the same state toKey() ended in.
    PaintParamsKeyBuilder* builder = keyContext.paintParamsKeyBuilder();
    SkASSERT(*builder == keyContext.recorder()->priv().shaderCodeDictionary()->lookup(origPaint));

    // We only support optimizing opacity when our dst usage is none and the final blend mode can
    // be switched to kSrc. This requires that there is no analytic clipping that adds a 3rd render
    // node, or an SkBlender that may have child blocks. With these conditions, we can simply
    // replace the last block ID with kSrc.
    //
    // Assuming the originally generated key returned kNone or kDstOnlyUsedByRenderer, these
    // requirements should be met. If these assumptions are violated, it'll be detected in
    // debug-only builds that regenerate the opaque coverage-less PaintParams from scratch.
    BuiltInCodeSnippetID oldID = builder->replaceLastBlock(BuiltInCodeSnippetID::kFixedBlend_Src);
    // We should only be calling into optimizeForOpacity for src and src-over blends
    SkASSERT(oldID == BuiltInCodeSnippetID::kFixedBlend_Src ||
             oldID == BuiltInCodeSnippetID::kFixedBlend_SrcOver);
    // And if we are already kSrc, the opaque paint ID is the original ID so skip lookup
    if (oldID == BuiltInCodeSnippetID::kFixedBlend_Src) {
        return origPaint;
    }

    // NOTE: If we choose to include paint-alpha multiplication in pipelines by default to avoid
    // 2x combinations just because the SkPaint changed from 1 to anything else, we could include
    // removing the paint alpha multiplication as part of this rewriting if we restructure paint
    // alpha handling to maintain an equivalent ShaderNode structure while just eliding the multiply

    UniquePaintParamsID opaqueID =
            keyContext.recorder()->priv().shaderCodeDictionary()->findOrCreate(builder);
    SkASSERT(opaqueID == this->validateOpacityOptimization(keyContext));
    return opaqueID;
}

#if defined(SK_DEBUG)

UniquePaintParamsID ShadingParams::validateOpacityOptimization(const KeyContext& keyContext) const {
    // Validate that the modified paint ID matches what we would have reached with a ShadingParams
    // and PaintParams adjusted to use kSrc blending and have no renderer coverage. These extracted
    // uniforms should match what was originally extracted as well.
    PaintParams opaquePaint = PaintParams::MakeOpaque(fPaint);
    NonMSAAClip emptyClip{};
    ShadingParams opaqueShading{keyContext.recorder()->priv().caps(),
                                opaquePaint,
                                /*nonMSAAClip=*/emptyClip,
                                /*clipShader=*/nullptr,
                                Coverage::kNone,
                                keyContext.targetFormat()};

    // Create a new KeyContext that writes to a different key builder and pipeline data gatherer.
    // Since the opaqueKeyContext will inherit the drawContext (and therefore storageContext) from
    // the existing keyContext, verify that the cache hit by checking the size of the storageContext
    // cache before and after creation.
    SkASSERT(keyContext.drawContext()->storageContext());
    SkDEBUGCODE(const int scSize = keyContext.drawContext()->storageContext()->size());

    const Layout layout = keyContext.pipelineDataGatherer()->uniformManager()->layout();
    PaintParamsKeyBuilder opaqueBuilder{keyContext.dict()};
    PipelineDataGatherer opaqueGatherer{layout};
    KeyContext opaqueContext{keyContext.recorder(),
                             keyContext.drawContext(),
                             &opaqueBuilder,
                             &opaqueGatherer,
                             keyContext.local2Dev(),
                             keyContext.clipDrawBounds(),
                             keyContext.dstColorInfo(),
                             keyContext.flags(),
                             opaqueShading.fPaint.color()};

    auto result = opaqueShading.toKey(opaqueContext);
    SkASSERT(result.has_value());

    auto [actualOpaqueID, actualDstUsage] = *result;
    SkASSERT(actualDstUsage == DstUsage::kNone);
    opaqueGatherer.checkEquivalent(keyContext.pipelineDataGatherer());
    SkASSERT(keyContext.drawContext()->storageContext()->size() == scSize);

    return actualOpaqueID;
}

#endif

} // namespace skgpu::graphite
