1/*
2 * Copyright 2021 Google LLC.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef PathTessellateOp_DEFINED
9#define PathTessellateOp_DEFINED
10
11#include "src/gpu/ops/GrDrawOp.h"
12#include "src/gpu/tessellate/PathTessellator.h"
13#include "src/gpu/tessellate/Tessellation.h"
14#include "src/gpu/tessellate/shaders/GrTessellationShader.h"
15
16namespace skgpu::v1 {
17
18// Tessellates a path directly to the color buffer, using one single render pass. This currently
19// only works for convex paths.
20class PathTessellateOp final : public GrDrawOp {
21private:
22    DEFINE_OP_CLASS_ID
23
24    using PathDrawList = PathTessellator::PathDrawList;
25
26    PathTessellateOp(SkArenaAlloc* arena,
27                     GrAAType aaType,
28                     const GrUserStencilSettings* stencil,
29                     const SkMatrix& viewMatrix,
30                     const SkPath& path,
31                     GrPaint&& paint,
32                     const SkRect& drawBounds)
33            : GrDrawOp(ClassID())
34            , fAAType(aaType)
35            , fStencil(stencil)
36            , fTotalCombinedPathVerbCnt(path.countVerbs())
37            , fPathDrawList(arena->make<PathDrawList>(SkMatrix::I(), path, paint.getColor4f()))
38            , fPathDrawTail(&fPathDrawList->fNext)
39            , fProcessors(std::move(paint))
40            , fShaderMatrix(viewMatrix) {
41        SkASSERT(!path.isInverseFillType());
42        if (!this->headDraw().fColor.fitsInBytes()) {
43            fPatchAttribs |= PatchAttribs::kWideColorIfEnabled;
44        }
45        this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
46    }
47
48    PathDrawList& headDraw() { return *fPathDrawList; }
49
50    void prepareTessellator(const GrTessellationShader::ProgramArgs&, GrAppliedClip&& clip);
51
52    // GrDrawOp overrides.
53    const char* name() const override { return "PathTessellateOp"; }
54    bool usesMSAA() const override { return fAAType == GrAAType::kMSAA; }
55    void visitProxies(const GrVisitProxyFunc&) const override;
56    GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
57    bool usesStencil() const override { return !fStencil->isUnused(); }
58    CombineResult onCombineIfPossible(GrOp*, SkArenaAlloc*, const GrCaps&) override;
59    void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
60                      const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override;
61    void onPrepare(GrOpFlushState*) override;
62    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
63
64    const GrAAType fAAType;
65    const GrUserStencilSettings* const fStencil;
66    int fTotalCombinedPathVerbCnt;
67    PatchAttribs fPatchAttribs = PatchAttribs::kNone;
68    PathDrawList* const fPathDrawList;
69    PathDrawList** fPathDrawTail;
70    GrProcessorSet fProcessors;
71    SkMatrix fShaderMatrix;
72
73    // Decided during prepareTessellator.
74    PathTessellator* fTessellator = nullptr;
75    const GrProgramInfo* fTessellationProgram = nullptr;
76
77    friend class GrOp;  // For ctor.
78};
79
80} // namespace skgpu::v1
81
82#endif // PathTessellateOp_DEFINED
83