1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/ops/PathTessellateOp.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "src/gpu/GrAppliedClip.h"
11cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h"
12cb93a386Sopenharmony_ci#include "src/gpu/tessellate/PathWedgeTessellator.h"
13cb93a386Sopenharmony_ci#include "src/gpu/tessellate/shaders/GrPathTessellationShader.h"
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_cinamespace skgpu::v1 {
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_civoid PathTessellateOp::visitProxies(const GrVisitProxyFunc& func) const {
18cb93a386Sopenharmony_ci    if (fTessellationProgram) {
19cb93a386Sopenharmony_ci        fTessellationProgram->pipeline().visitProxies(func);
20cb93a386Sopenharmony_ci    } else {
21cb93a386Sopenharmony_ci        fProcessors.visitProxies(func);
22cb93a386Sopenharmony_ci    }
23cb93a386Sopenharmony_ci}
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ciGrProcessorSet::Analysis PathTessellateOp::finalize(const GrCaps& caps,
26cb93a386Sopenharmony_ci                                                    const GrAppliedClip* clip,
27cb93a386Sopenharmony_ci                                                    GrClampType clampType) {
28cb93a386Sopenharmony_ci    auto analysis = fProcessors.finalize(this->headDraw().fColor,
29cb93a386Sopenharmony_ci                                         GrProcessorAnalysisCoverage::kNone,
30cb93a386Sopenharmony_ci                                         clip,
31cb93a386Sopenharmony_ci                                         nullptr,
32cb93a386Sopenharmony_ci                                         caps,
33cb93a386Sopenharmony_ci                                         clampType,
34cb93a386Sopenharmony_ci                                         &this->headDraw().fColor);
35cb93a386Sopenharmony_ci    if (!analysis.usesLocalCoords()) {
36cb93a386Sopenharmony_ci        // Since we don't need local coords, we can transform on CPU instead of in the shader. This
37cb93a386Sopenharmony_ci        // gives us better batching potential.
38cb93a386Sopenharmony_ci        this->headDraw().fPathMatrix = fShaderMatrix;
39cb93a386Sopenharmony_ci        fShaderMatrix = SkMatrix::I();
40cb93a386Sopenharmony_ci    }
41cb93a386Sopenharmony_ci    return analysis;
42cb93a386Sopenharmony_ci}
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ciGrDrawOp::CombineResult PathTessellateOp::onCombineIfPossible(GrOp* grOp,
45cb93a386Sopenharmony_ci                                                              SkArenaAlloc*,
46cb93a386Sopenharmony_ci                                                              const GrCaps&) {
47cb93a386Sopenharmony_ci    auto* op = grOp->cast<PathTessellateOp>();
48cb93a386Sopenharmony_ci    bool canMerge = fAAType == op->fAAType &&
49cb93a386Sopenharmony_ci                    fStencil == op->fStencil &&
50cb93a386Sopenharmony_ci                    fProcessors == op->fProcessors &&
51cb93a386Sopenharmony_ci                    fShaderMatrix == op->fShaderMatrix;
52cb93a386Sopenharmony_ci    if (canMerge) {
53cb93a386Sopenharmony_ci        fTotalCombinedPathVerbCnt += op->fTotalCombinedPathVerbCnt;
54cb93a386Sopenharmony_ci        fPatchAttribs |= op->fPatchAttribs;
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci        if (!(fPatchAttribs & PatchAttribs::kColor) &&
57cb93a386Sopenharmony_ci            this->headDraw().fColor != op->headDraw().fColor) {
58cb93a386Sopenharmony_ci            // Color is no longer uniform. Move it into patch attribs.
59cb93a386Sopenharmony_ci            fPatchAttribs |= PatchAttribs::kColor;
60cb93a386Sopenharmony_ci        }
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ci        *fPathDrawTail = op->fPathDrawList;
63cb93a386Sopenharmony_ci        fPathDrawTail = op->fPathDrawTail;
64cb93a386Sopenharmony_ci        return CombineResult::kMerged;
65cb93a386Sopenharmony_ci    }
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci    return CombineResult::kCannotCombine;
68cb93a386Sopenharmony_ci}
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_civoid PathTessellateOp::prepareTessellator(const GrTessellationShader::ProgramArgs& args,
71cb93a386Sopenharmony_ci                                          GrAppliedClip&& appliedClip) {
72cb93a386Sopenharmony_ci    SkASSERT(!fTessellator);
73cb93a386Sopenharmony_ci    SkASSERT(!fTessellationProgram);
74cb93a386Sopenharmony_ci    auto* pipeline = GrTessellationShader::MakePipeline(args, fAAType, std::move(appliedClip),
75cb93a386Sopenharmony_ci                                                        std::move(fProcessors));
76cb93a386Sopenharmony_ci    fTessellator = PathWedgeTessellator::Make(args.fArena,
77cb93a386Sopenharmony_ci                                              args.fCaps->shaderCaps()->infinitySupport(),
78cb93a386Sopenharmony_ci                                              fPatchAttribs);
79cb93a386Sopenharmony_ci    auto* tessShader = GrPathTessellationShader::Make(args.fArena,
80cb93a386Sopenharmony_ci                                                      fShaderMatrix,
81cb93a386Sopenharmony_ci                                                      this->headDraw().fColor,
82cb93a386Sopenharmony_ci                                                      fTotalCombinedPathVerbCnt,
83cb93a386Sopenharmony_ci                                                      *pipeline,
84cb93a386Sopenharmony_ci                                                      fTessellator->patchAttribs(),
85cb93a386Sopenharmony_ci                                                      *args.fCaps);
86cb93a386Sopenharmony_ci    fTessellationProgram = GrTessellationShader::MakeProgram(args, tessShader, pipeline, fStencil);
87cb93a386Sopenharmony_ci}
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_civoid PathTessellateOp::onPrePrepare(GrRecordingContext* context,
90cb93a386Sopenharmony_ci                                    const GrSurfaceProxyView& writeView, GrAppliedClip* clip,
91cb93a386Sopenharmony_ci                                    const GrDstProxyView& dstProxyView,
92cb93a386Sopenharmony_ci                                    GrXferBarrierFlags renderPassXferBarriers,
93cb93a386Sopenharmony_ci                                    GrLoadOp colorLoadOp) {
94cb93a386Sopenharmony_ci    // DMSAA is not supported on DDL.
95cb93a386Sopenharmony_ci    bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;
96cb93a386Sopenharmony_ci    this->prepareTessellator({context->priv().recordTimeAllocator(), writeView, usesMSAASurface,
97cb93a386Sopenharmony_ci                             &dstProxyView, renderPassXferBarriers, colorLoadOp,
98cb93a386Sopenharmony_ci                             context->priv().caps()},
99cb93a386Sopenharmony_ci                             (clip) ? std::move(*clip) : GrAppliedClip::Disabled());
100cb93a386Sopenharmony_ci    SkASSERT(fTessellationProgram);
101cb93a386Sopenharmony_ci    context->priv().recordProgramInfo(fTessellationProgram);
102cb93a386Sopenharmony_ci}
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_civoid PathTessellateOp::onPrepare(GrOpFlushState* flushState) {
105cb93a386Sopenharmony_ci    if (!fTessellator) {
106cb93a386Sopenharmony_ci        this->prepareTessellator({flushState->allocator(), flushState->writeView(),
107cb93a386Sopenharmony_ci                                 flushState->usesMSAASurface(), &flushState->dstProxyView(),
108cb93a386Sopenharmony_ci                                 flushState->renderPassBarriers(), flushState->colorLoadOp(),
109cb93a386Sopenharmony_ci                                 &flushState->caps()}, flushState->detachAppliedClip());
110cb93a386Sopenharmony_ci        SkASSERT(fTessellator);
111cb93a386Sopenharmony_ci    }
112cb93a386Sopenharmony_ci    auto tessShader = &fTessellationProgram->geomProc().cast<GrPathTessellationShader>();
113cb93a386Sopenharmony_ci    fTessellator->prepare(flushState,
114cb93a386Sopenharmony_ci                          tessShader->maxTessellationSegments(*flushState->caps().shaderCaps()),
115cb93a386Sopenharmony_ci                          fShaderMatrix,
116cb93a386Sopenharmony_ci                          *fPathDrawList,
117cb93a386Sopenharmony_ci                          fTotalCombinedPathVerbCnt,
118cb93a386Sopenharmony_ci                          tessShader->willUseTessellationShaders());
119cb93a386Sopenharmony_ci}
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_civoid PathTessellateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
122cb93a386Sopenharmony_ci    SkASSERT(fTessellator);
123cb93a386Sopenharmony_ci    SkASSERT(fTessellationProgram);
124cb93a386Sopenharmony_ci    flushState->bindPipelineAndScissorClip(*fTessellationProgram, this->bounds());
125cb93a386Sopenharmony_ci    flushState->bindTextures(fTessellationProgram->geomProc(), nullptr,
126cb93a386Sopenharmony_ci                             fTessellationProgram->pipeline());
127cb93a386Sopenharmony_ci    fTessellator->draw(flushState, fTessellationProgram->geomProc().willUseTessellationShaders());
128cb93a386Sopenharmony_ci}
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ci} // namespace skgpu::v1
131