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