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