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

#ifndef GrFillPathShader_DEFINED
#define GrFillPathShader_DEFINED

#include "src/gpu/tessellate/GrPathShader.h"

class GrGLSLUniformHandler;
class GrGLSLVertexBuilder;

// This is the base class for shaders that fill a path's pixels in the final render target.
class GrFillPathShader : public GrPathShader {
public:
    GrFillPathShader(ClassID classID, const SkMatrix& viewMatrix, SkPMColor4f color,
                     GrPrimitiveType primitiveType)
            : GrPathShader(classID, viewMatrix, primitiveType, 0)
            , fColor(color) {
    }

    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
    GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const final;

    static const GrPipeline* MakeFillPassPipeline(const GrPathShader::ProgramArgs& args,
                                                  GrAAType aaType, GrAppliedClip&& appliedClip,
                                                  GrProcessorSet&& processors) {
        auto pipelineFlags = GrPipeline::InputFlags::kNone;
        if (aaType != GrAAType::kNone) {
            if (args.fWriteView.asRenderTargetProxy()->numSamples() == 1) {
                // We are mixed sampled. We need to either enable conservative raster (preferred) or
                // disable MSAA in order to avoid double blend artifacts. (Even if we disable MSAA for
                // the cover geometry, the stencil test is still multisampled and will still produce
                // smooth results.)
                SkASSERT(aaType == GrAAType::kCoverage);
                if (args.fCaps->conservativeRasterSupport()) {
                    pipelineFlags |= GrPipeline::InputFlags::kHWAntialias;
                    pipelineFlags |= GrPipeline::InputFlags::kConservativeRaster;
                }
            } else {
                // We are standard MSAA. Leave MSAA enabled for the cover geometry.
                pipelineFlags |= GrPipeline::InputFlags::kHWAntialias;
            }
        }
        return GrSimpleMeshDrawOpHelper::CreatePipeline(
                args.fCaps, args.fArena, args.fWriteView.swizzle(), std::move(appliedClip),
                *args.fDstProxyView, std::move(processors), pipelineFlags);
    }

    // Allows non-zero stencil values to pass and write a color, and resets the stencil value back
    // to zero; discards immediately on stencil values of zero.
    static const GrUserStencilSettings* TestAndResetStencilSettings() {
        constexpr static GrUserStencilSettings kTestAndResetStencil(
            GrUserStencilSettings::StaticInit<
                0x0000,
                // No need to check the clip because the previous stencil pass will have only
                // written to samples already inside the clip.
                GrUserStencilTest::kNotEqual,
                0xffff,
                GrUserStencilOp::kZero,
                GrUserStencilOp::kKeep,
                0xffff>());
        return &kTestAndResetStencil;
    }

protected:
    class Impl;

    virtual void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix,
                                GrGLSLUniformHandler*) const = 0;

private:
    const SkPMColor4f fColor;
};

// Fills a simple array of triangles.
class GrFillTriangleShader : public GrFillPathShader {
public:
    GrFillTriangleShader(const SkMatrix& viewMatrix, SkPMColor4f color)
            : GrFillPathShader(kTessellate_GrFillTriangleShader_ClassID, viewMatrix, color,
                               GrPrimitiveType::kTriangles) {
        static constexpr Attribute kPtAttrib = {
                "input_point", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
        this->setVertexAttributes(&kPtAttrib, 1);
    }

private:
    const char* name() const override { return "GrFillTriangleShader"; }
    void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix,
                        GrGLSLUniformHandler*) const override;
};

// Fills an array of convex hulls surrounding 4-point cubic instances.
class GrFillCubicHullShader : public GrFillPathShader {
public:
    GrFillCubicHullShader(const SkMatrix& viewMatrix, SkPMColor4f color)
            : GrFillPathShader(kTessellate_GrFillCubicHullShader_ClassID, viewMatrix, color,
                               GrPrimitiveType::kTriangleStrip) {
        static constexpr Attribute kPtsAttribs[] = {
                {"input_points_0_1", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
                {"input_points_2_3", kFloat4_GrVertexAttribType, kFloat4_GrSLType}};
        this->setInstanceAttributes(kPtsAttribs, SK_ARRAY_COUNT(kPtsAttribs));
    }

private:
    const char* name() const override { return "GrFillCubicHullShader"; }
    void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix,
                        GrGLSLUniformHandler*) const override;
};

// Fills a path's bounding box, with subpixel outset to avoid possible T-junctions with extreme
// edges of the path.
// NOTE: The emitted geometry may not be axis-aligned, depending on the view matrix.
class GrFillBoundingBoxShader : public GrFillPathShader {
public:
    GrFillBoundingBoxShader(const SkMatrix& viewMatrix, SkPMColor4f color, const SkRect& pathBounds)
            : GrFillPathShader(kTessellate_GrFillBoundingBoxShader_ClassID, viewMatrix, color,
                               GrPrimitiveType::kTriangleStrip)
            , fPathBounds(pathBounds) {
    }

    const SkRect& pathBounds() const { return fPathBounds; }

private:
    const char* name() const override { return "GrFillBoundingBoxShader"; }
    void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix,
                        GrGLSLUniformHandler*) const override;

    const SkRect fPathBounds;
};

#endif
