/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef skgpu_graphite_PaintParams_DEFINED
#define skgpu_graphite_PaintParams_DEFINED

#include "include/core/SkColor.h"
#include "include/core/SkPaint.h"
#include "src/base/SkEnumBitMask.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/Renderer.h"
#include "src/gpu/graphite/geom/NonMSAAClip.h"

class SkColorInfo;
class SkShader;

namespace skgpu::graphite {

class DrawContext;
class KeyContext;
class FloatStorageManager;
class PaintParamsKeyBuilder;
class PipelineDataGatherer;
class Recorder;
class TextureProxy;
class UniquePaintParamsID;

// NOTE: Only represents the shading state of an SkPaint. Style and complex effects (mask filters,
// image filters, path effects) must be handled higher up. AA is not tracked since everything is
// assumed to be anti-aliased.
//
// The full shading of a draw is a combination of the PaintParams extracted from an SkPaint, any
// analytic NonMSAA clipping, analytic coverage from a RenderStep, and the target TextureFormat
// being rendered into. These additional parameters are aggregated together in ShadingParams.
//
// Both PaintParams and ShadingParams are meant to be short-lived objects used for processing a
// draw's effects into a UniquePaintID and extracted uniforms and textures. As such, they do not
// keep high-level Skia objects alive since these Params types should go out of scope by the end of
// the draw call.
class PaintParams {
public:
    // Converts an SkPaint to PaintParams, possibly adding a primitive blender (e.g. for
    // drawVertices or text rendering).
    explicit PaintParams(const SkPaint&,
                         const SkBlender* primitiveBlender = nullptr,
                         bool skipColorXform = false,
                         bool ignoreShader = false);


    // Creates a constant color PaintParams with the specific blend mode.
    PaintParams(const SkColor4f& color, SkBlendMode finalBlendMode);

    const SkColor4f& color() const { return fColor; }
    const SkShader* shader() const { return fShader; }
    const SkColorFilter* colorFilter() const { return fColorFilter; }
    const SkBlender* primitiveBlender() const { return fPrimitiveBlender; }
    bool skipPrimitiveColorXform() const { return fSkipColorXform; }

    const SkBlender* finalBlender() const { return fFinalBlend.first; }
    // Must also check finalBlender() to see if that overrides finalBlendMode() behavior.
    SkBlendMode finalBlendMode() const { SkASSERT(!fFinalBlend.first); return fFinalBlend.second; }

    bool dither() const { return fDither; }

    /** Converts an SkColor4f to the destination color space. */
    static SkColor4f Color4fPrepForDst(SkColor4f srgb, const SkColorInfo& dstColorInfo);

private:
    SkColor4f fColor;

    // Either a non-null SkBlender for runtime blending, or the SkBlendMode to use instead. If
    // the blender is non-null, the blend mode is set to kSrc to match the HW blend config used for
    // shader-based blending.
    std::pair<const SkBlender*, SkBlendMode> fFinalBlend;

    const SkShader*      fShader;
    const SkColorFilter* fColorFilter;

    // A nullptr fPrimitiveBlender means there's no primitive color blending and it is skipped.
    // In the case where there is primitive blending, the primitive color is the source color and
    // the dest is the paint's color (or the paint's shader's computed color).
    const SkBlender* fPrimitiveBlender;
    bool             fSkipColorXform;
    bool             fDither;
};

// ShadingParams wraps a PaintParams with the additional per-pixel state to handle clipping and
// anti-aliasing, as well as making the final determinations for how blending will be implemented
// given the current hardware.
class ShadingParams {
public:
    // NOTE: Does not copy `paint`, `nonMSAAClip` or `clipShader`; these must outlive ShadingParams.
    ShadingParams(const Caps* caps,
                  const PaintParams& paint,
                  const NonMSAAClip& nonMSAAClip,
                  const SkShader* clipShader,
                  Coverage coverage,
                  TextureFormat targetFormat);

    Coverage rendererCoverage()  const { return fRendererCoverage; }
    bool dstReadRequired() const { return SkToBool(fDstUsage & DstUsage::kDstReadRequired); }

    using Result = std::tuple<UniquePaintParamsID, SkEnumBitMask<DstUsage>>;
    std::optional<Result> toKey(const KeyContext&) const;

private:
    bool addPaintColorToKey(const KeyContext&) const;
    bool handlePrimitiveColor(const KeyContext&) const;
    bool handlePaintAlpha(const KeyContext&) const;
    bool handleColorFilter(const KeyContext&) const;
    bool handleDithering(const KeyContext&) const;
    bool handleDstRead(const KeyContext&) const;
    void handleClipping(const KeyContext&) const;

    const PaintParams&      fPaint;
    const NonMSAAClip&      fNonMSAAClip;
    const SkShader*         fClipShader;

    Coverage                fRendererCoverage;
    TextureFormat           fTargetFormat;
    SkEnumBitMask<DstUsage> fDstUsage;
};

} // namespace skgpu::graphite

#endif // skgpu_PaintParams_DEFINED
