blob: 42b8d451e1ead05c6b3804200b3972609bb9501d [file] [log] [blame]
Chris Dalton0e543092020-11-03 14:09:16 -07001/*
2 * Copyright 2020 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
Chris Dalton05007df2021-02-04 00:24:52 -07008#ifndef GrStrokeTessellateOp_DEFINED
9#define GrStrokeTessellateOp_DEFINED
Chris Dalton0e543092020-11-03 14:09:16 -070010
11#include "include/core/SkStrokeRec.h"
Chris Dalton0e543092020-11-03 14:09:16 -070012#include "src/gpu/GrSTArenaList.h"
Chris Dalton22241002021-02-04 09:47:40 -070013#include "src/gpu/ops/GrMeshDrawOp.h"
14#include "src/gpu/tessellate/GrPathShader.h"
Chris Dalton42582fc2021-02-18 11:29:49 -070015#include "src/gpu/tessellate/GrStrokeTessellateShader.h"
Chris Dalton0e543092020-11-03 14:09:16 -070016
Chris Dalton22241002021-02-04 09:47:40 -070017class GrRecordingContext;
18
19// Prepares GPU data for, and then draws a stroke's tessellated geometry.
20class GrStrokeTessellator {
21public:
Chris Dalton42582fc2021-02-18 11:29:49 -070022 using ShaderFlags = GrStrokeTessellateShader::ShaderFlags;
Chris Dalton22241002021-02-04 09:47:40 -070023
Chris Dalton42582fc2021-02-18 11:29:49 -070024 GrStrokeTessellator(ShaderFlags shaderFlags) : fShaderFlags(shaderFlags) {}
25
26 struct PathStroke {
Chris Dalton1017a352021-02-18 15:22:54 -070027 PathStroke(const SkPath& path, const SkStrokeRec& stroke, const SkPMColor4f& color)
28 : fPath(path), fStroke(stroke), fColor(color) {}
Chris Dalton42582fc2021-02-18 11:29:49 -070029 SkPath fPath;
30 SkStrokeRec fStroke;
Chris Dalton1017a352021-02-18 15:22:54 -070031 SkPMColor4f fColor;
Chris Dalton42582fc2021-02-18 11:29:49 -070032 };
33
34 // Called before draw(). Prepares GPU buffers containing the geometry to tessellate.
35 virtual void prepare(GrMeshDrawOp::Target*, const SkMatrix&, const GrSTArenaList<PathStroke>&,
36 int totalCombinedVerbCnt) = 0;
37
38 // Issues draw calls for the tessellated stroke. The caller is responsible for binding its
Chris Dalton22241002021-02-04 09:47:40 -070039 // desired pipeline ahead of time.
40 virtual void draw(GrOpFlushState*) const = 0;
41
42 virtual ~GrStrokeTessellator() {}
Chris Dalton0e543092020-11-03 14:09:16 -070043
Chris Dalton22241002021-02-04 09:47:40 -070044protected:
Chris Dalton42582fc2021-02-18 11:29:49 -070045 const ShaderFlags fShaderFlags;
46};
47
48// Renders strokes by linearizing them into sorted "parametric" and "radial" edges. See
49// GrStrokeTessellateShader.
50class GrStrokeTessellateOp : public GrDrawOp {
51public:
52 GrStrokeTessellateOp(GrAAType, const SkMatrix&, const SkPath&, const SkStrokeRec&, GrPaint&&);
53
54private:
55 using ShaderFlags = GrStrokeTessellateShader::ShaderFlags;
56 using PathStroke = GrStrokeTessellator::PathStroke;
Chris Dalton22241002021-02-04 09:47:40 -070057 DEFINE_OP_CLASS_ID
58
Chris Dalton42582fc2021-02-18 11:29:49 -070059 SkStrokeRec& headStroke() { return fPathStrokeList.head().fStroke; }
Chris Dalton1017a352021-02-18 15:22:54 -070060 SkPMColor4f& headColor() { return fPathStrokeList.head().fColor; }
Chris Dalton42582fc2021-02-18 11:29:49 -070061
Chris Dalton1017a352021-02-18 15:22:54 -070062 // Returns whether it is a good tradeoff to use the dynamic states flagged in the given
63 // bitfield. Dynamic states improve batching, but if they aren't already enabled, they come at
64 // the cost of having to write out more data with each patch or instance.
65 bool shouldUseDynamicStates(ShaderFlags neededDynamicStates) const {
66 // Use the dynamic states if either (1) they are all already enabled anyway, or (2) we don't
Chris Dalton42582fc2021-02-18 11:29:49 -070067 // have many verbs.
68 constexpr static int kMaxVerbsToEnableDynamicState = 50;
Chris Dalton1017a352021-02-18 15:22:54 -070069 bool anyStateDisabled = (bool)(~fShaderFlags & neededDynamicStates);
70 bool allStatesEnabled = !anyStateDisabled;
71 return allStatesEnabled || (fTotalCombinedVerbCnt <= kMaxVerbsToEnableDynamicState);
72 }
73
74 bool canUseHardwareTessellation(const GrCaps& caps) {
75 SkASSERT(!fStencilProgram && !fFillProgram); // Ensure we haven't std::moved fProcessors.
76 // Our back door for HW tessellation shaders isn't currently capable of passing varyings to
77 // the fragment shader, so if the processors have varyings we need to use indirect draws.
78 return caps.shaderCaps()->tessellationSupport() && !fProcessors.usesVaryingCoords();
Chris Dalton42582fc2021-02-18 11:29:49 -070079 }
80
Chris Dalton05007df2021-02-04 00:24:52 -070081 const char* name() const override { return "GrStrokeTessellateOp"; }
Chris Daltonb0643342020-12-15 01:04:12 -070082 void visitProxies(const VisitProxyFunc& fn) const override;
Chris Dalton0e543092020-11-03 14:09:16 -070083 FixedFunctionFlags fixedFunctionFlags() const override;
84 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
85 bool hasMixedSampledCoverage, GrClampType) override;
86 CombineResult onCombineIfPossible(GrOp*, SkArenaAlloc*, const GrCaps&) override;
87
Chris Dalton22241002021-02-04 09:47:40 -070088 // Creates the tessellator and the stencil/fill program(s) we will use with it.
89 void prePrepareTessellator(GrPathShader::ProgramArgs&&, GrAppliedClip&&);
Chris Dalton0e543092020-11-03 14:09:16 -070090
Chris Dalton22241002021-02-04 09:47:40 -070091 void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
92 const GrXferProcessor::DstProxyView&, GrXferBarrierFlags,
93 GrLoadOp colorLoadOp) override;
Chris Dalton0e543092020-11-03 14:09:16 -070094
Chris Dalton22241002021-02-04 09:47:40 -070095 void onPrepare(GrOpFlushState*) override;
Chris Dalton0e543092020-11-03 14:09:16 -070096
Chris Dalton22241002021-02-04 09:47:40 -070097 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
Chris Dalton06b52ad2020-12-15 10:01:35 -070098
Chris Dalton0e543092020-11-03 14:09:16 -070099 const GrAAType fAAType;
100 const SkMatrix fViewMatrix;
Chris Dalton42582fc2021-02-18 11:29:49 -0700101 ShaderFlags fShaderFlags = ShaderFlags::kNone;
102 GrSTArenaList<PathStroke> fPathStrokeList;
Chris Dalton7b807262020-12-10 10:22:50 -0700103 int fTotalCombinedVerbCnt = 0;
Chris Dalton1017a352021-02-18 15:22:54 -0700104 GrProcessorSet fProcessors;
105 bool fNeedsStencil = false;
Chris Dalton0e543092020-11-03 14:09:16 -0700106
Chris Dalton22241002021-02-04 09:47:40 -0700107 GrStrokeTessellator* fTessellator = nullptr;
108 const GrProgramInfo* fStencilProgram = nullptr; // Only used if the stroke has transparency.
Chris Dalton55abaf52020-12-08 10:25:13 -0700109 const GrProgramInfo* fFillProgram = nullptr;
Chris Dalton0e543092020-11-03 14:09:16 -0700110};
111
112#endif