1 /*
2 * Copyright 2017 Google Inc.
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/GrAppliedClip.h"
9 #include "src/gpu/GrProcessorSet.h"
10 #include "src/gpu/GrUserStencilSettings.h"
11 #include "src/gpu/SkGr.h"
12 #include "src/gpu/geometry/GrRect.h"
13 #include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
14
GrSimpleMeshDrawOpHelper(const MakeArgs & args,GrAAType aaType,InputFlags inputFlags)15 GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(const MakeArgs& args, GrAAType aaType,
16 InputFlags inputFlags)
17 : fProcessors(args.fProcessorSet)
18 , fPipelineFlags((GrPipeline::InputFlags)inputFlags)
19 , fAAType((int)aaType)
20 , fUsesLocalCoords(false)
21 , fCompatibleWithCoverageAsAlpha(false) {
22 SkDEBUGCODE(fDidAnalysis = false);
23 SkDEBUGCODE(fMadePipeline = false);
24 if (GrAATypeIsHW(aaType)) {
25 fPipelineFlags |= GrPipeline::InputFlags::kHWAntialias;
26 }
27 }
28
~GrSimpleMeshDrawOpHelper()29 GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() {
30 if (fProcessors) {
31 fProcessors->~GrProcessorSet();
32 }
33 }
34
fixedFunctionFlags() const35 GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const {
36 return GrAATypeIsHW((this->aaType())) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA
37 : GrDrawOp::FixedFunctionFlags::kNone;
38 }
39
none_as_coverage_aa_compatible(GrAAType aa1,GrAAType aa2)40 static bool none_as_coverage_aa_compatible(GrAAType aa1, GrAAType aa2) {
41 return (aa1 == GrAAType::kNone && aa2 == GrAAType::kCoverage) ||
42 (aa1 == GrAAType::kCoverage && aa2 == GrAAType::kNone);
43 }
44
isCompatible(const GrSimpleMeshDrawOpHelper & that,const GrCaps & caps,const SkRect & thisBounds,const SkRect & thatBounds,bool noneAsCoverageAA) const45 bool GrSimpleMeshDrawOpHelper::isCompatible(const GrSimpleMeshDrawOpHelper& that,
46 const GrCaps& caps, const SkRect& thisBounds,
47 const SkRect& thatBounds, bool noneAsCoverageAA) const {
48 if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) {
49 return false;
50 }
51 if (fProcessors) {
52 if (*fProcessors != *that.fProcessors) {
53 return false;
54 }
55 }
56 bool result = fPipelineFlags == that.fPipelineFlags && (fAAType == that.fAAType ||
57 (noneAsCoverageAA && none_as_coverage_aa_compatible(this->aaType(), that.aaType())));
58 SkASSERT(!result || fCompatibleWithCoverageAsAlpha == that.fCompatibleWithCoverageAsAlpha);
59 SkASSERT(!result || fUsesLocalCoords == that.fUsesLocalCoords);
60 return result;
61 }
62
finalizeProcessors(const GrCaps & caps,const GrAppliedClip * clip,bool hasMixedSampledCoverage,GrClampType clampType,GrProcessorAnalysisCoverage geometryCoverage,SkPMColor4f * geometryColor,bool * wideColor)63 GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors(
64 const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
65 GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage,
66 SkPMColor4f* geometryColor, bool* wideColor) {
67 GrProcessorAnalysisColor color = *geometryColor;
68 auto result = this->finalizeProcessors(
69 caps, clip, hasMixedSampledCoverage, clampType, geometryCoverage, &color);
70 color.isConstant(geometryColor);
71 if (wideColor) {
72 *wideColor = SkPMColor4fNeedsWideColor(*geometryColor, clampType, caps);
73 }
74 return result;
75 }
76
finalizeProcessors(const GrCaps & caps,const GrAppliedClip * clip,const GrUserStencilSettings * userStencil,bool hasMixedSampledCoverage,GrClampType clampType,GrProcessorAnalysisCoverage geometryCoverage,GrProcessorAnalysisColor * geometryColor)77 GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors(
78 const GrCaps& caps, const GrAppliedClip* clip, const GrUserStencilSettings* userStencil,
79 bool hasMixedSampledCoverage, GrClampType clampType,
80 GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor* geometryColor) {
81 SkDEBUGCODE(fDidAnalysis = true);
82 GrProcessorSet::Analysis analysis;
83 if (fProcessors) {
84 GrProcessorAnalysisCoverage coverage = geometryCoverage;
85 if (GrProcessorAnalysisCoverage::kNone == coverage) {
86 coverage = clip->numClipCoverageFragmentProcessors()
87 ? GrProcessorAnalysisCoverage::kSingleChannel
88 : GrProcessorAnalysisCoverage::kNone;
89 }
90 SkPMColor4f overrideColor;
91 analysis = fProcessors->finalize(*geometryColor, coverage, clip, userStencil,
92 hasMixedSampledCoverage, caps, clampType, &overrideColor);
93 if (analysis.inputColorIsOverridden()) {
94 *geometryColor = overrideColor;
95 }
96 } else {
97 analysis = GrProcessorSet::EmptySetAnalysis();
98 }
99 fUsesLocalCoords = analysis.usesLocalCoords();
100 fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha();
101 return analysis;
102 }
103
executeDrawsAndUploads(const GrOp * op,GrOpFlushState * flushState,const SkRect & chainBounds)104 void GrSimpleMeshDrawOpHelper::executeDrawsAndUploads(
105 const GrOp* op, GrOpFlushState* flushState, const SkRect& chainBounds) {
106 if (fProcessors) {
107 flushState->executeDrawsAndUploadsForMeshDrawOp(
108 op, chainBounds, std::move(*fProcessors), fPipelineFlags);
109 } else {
110 flushState->executeDrawsAndUploadsForMeshDrawOp(
111 op, chainBounds, GrProcessorSet::MakeEmptySet(), fPipelineFlags);
112 }
113 }
114
115 #ifdef SK_DEBUG
dump_pipeline_flags(GrPipeline::InputFlags flags,SkString * result)116 static void dump_pipeline_flags(GrPipeline::InputFlags flags, SkString* result) {
117 if (GrPipeline::InputFlags::kNone != flags) {
118 if (flags & GrPipeline::InputFlags::kSnapVerticesToPixelCenters) {
119 result->append("Snap vertices to pixel center.\n");
120 }
121 if (flags & GrPipeline::InputFlags::kHWAntialias) {
122 result->append("HW Antialiasing enabled.\n");
123 }
124 return;
125 }
126 result->append("No pipeline flags\n");
127 }
128
dumpInfo() const129 SkString GrSimpleMeshDrawOpHelper::dumpInfo() const {
130 const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
131 SkString result = processors.dumpProcessors();
132 result.append("AA Type: ");
133 switch (this->aaType()) {
134 case GrAAType::kNone:
135 result.append(" none\n");
136 break;
137 case GrAAType::kCoverage:
138 result.append(" coverage\n");
139 break;
140 case GrAAType::kMSAA:
141 result.append(" msaa\n");
142 break;
143 }
144 dump_pipeline_flags(fPipelineFlags, &result);
145 return result;
146 }
147 #endif
148
GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs & args,GrAAType aaType,const GrUserStencilSettings * stencilSettings,InputFlags inputFlags)149 GrSimpleMeshDrawOpHelperWithStencil::GrSimpleMeshDrawOpHelperWithStencil(
150 const MakeArgs& args, GrAAType aaType, const GrUserStencilSettings* stencilSettings,
151 InputFlags inputFlags)
152 : INHERITED(args, aaType, inputFlags)
153 , fStencilSettings(stencilSettings ? stencilSettings : &GrUserStencilSettings::kUnused) {}
154
fixedFunctionFlags() const155 GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelperWithStencil::fixedFunctionFlags() const {
156 GrDrawOp::FixedFunctionFlags flags = INHERITED::fixedFunctionFlags();
157 if (fStencilSettings != &GrUserStencilSettings::kUnused) {
158 flags |= GrDrawOp::FixedFunctionFlags::kUsesStencil;
159 }
160 return flags;
161 }
162
finalizeProcessors(const GrCaps & caps,const GrAppliedClip * clip,bool hasMixedSampledCoverage,GrClampType clampType,GrProcessorAnalysisCoverage geometryCoverage,SkPMColor4f * geometryColor,bool * wideColor)163 GrProcessorSet::Analysis GrSimpleMeshDrawOpHelperWithStencil::finalizeProcessors(
164 const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
165 GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage,
166 SkPMColor4f* geometryColor, bool* wideColor) {
167 GrProcessorAnalysisColor color = *geometryColor;
168 auto result = this->finalizeProcessors(
169 caps, clip, hasMixedSampledCoverage, clampType, geometryCoverage, &color);
170 color.isConstant(geometryColor);
171 if (wideColor) {
172 *wideColor = SkPMColor4fNeedsWideColor(*geometryColor, clampType, caps);
173 }
174 return result;
175 }
176
isCompatible(const GrSimpleMeshDrawOpHelperWithStencil & that,const GrCaps & caps,const SkRect & thisBounds,const SkRect & thatBounds,bool noneAsCoverageAA) const177 bool GrSimpleMeshDrawOpHelperWithStencil::isCompatible(
178 const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps& caps,
179 const SkRect& thisBounds, const SkRect& thatBounds, bool noneAsCoverageAA) const {
180 return INHERITED::isCompatible(that, caps, thisBounds, thatBounds, noneAsCoverageAA) &&
181 fStencilSettings == that.fStencilSettings;
182 }
183
executeDrawsAndUploads(const GrOp * op,GrOpFlushState * flushState,const SkRect & chainBounds)184 void GrSimpleMeshDrawOpHelperWithStencil::executeDrawsAndUploads(
185 const GrOp* op, GrOpFlushState* flushState, const SkRect& chainBounds) {
186 if (fProcessors) {
187 flushState->executeDrawsAndUploadsForMeshDrawOp(
188 op, chainBounds, std::move(*fProcessors), fPipelineFlags, fStencilSettings);
189 } else {
190 flushState->executeDrawsAndUploadsForMeshDrawOp(
191 op, chainBounds, GrProcessorSet::MakeEmptySet(), fPipelineFlags, fStencilSettings);
192 }
193 }
194
195 #ifdef SK_DEBUG
dumpInfo() const196 SkString GrSimpleMeshDrawOpHelperWithStencil::dumpInfo() const {
197 SkString result = INHERITED::dumpInfo();
198 result.appendf("Stencil settings: %s\n", (fStencilSettings ? "yes" : "no"));
199 return result;
200 }
201 #endif
202