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 "GrSimpleMeshDrawOpHelper.h"
9 #include "GrAppliedClip.h"
10 #include "GrProcessorSet.h"
11 #include "GrRect.h"
12 #include "GrUserStencilSettings.h"
13
GrSimpleMeshDrawOpHelper(const MakeArgs & args,GrAAType aaType,Flags flags)14 GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(const MakeArgs& args, GrAAType aaType,
15 Flags flags)
16 : fProcessors(args.fProcessorSet)
17 , fPipelineFlags(args.fSRGBFlags)
18 , fAAType((int)aaType)
19 , fRequiresDstTexture(false)
20 , fUsesLocalCoords(false)
21 , fCompatibleWithAlphaAsCoveage(false) {
22 SkDEBUGCODE(fDidAnalysis = false);
23 SkDEBUGCODE(fMadePipeline = false);
24 if (GrAATypeIsHW(aaType)) {
25 fPipelineFlags |= GrPipeline::kHWAntialias_Flag;
26 }
27 if (flags & Flags::kSnapVerticesToPixelCenters) {
28 fPipelineFlags |= GrPipeline::kSnapVerticesToPixelCenters_Flag;
29 }
30 }
31
~GrSimpleMeshDrawOpHelper()32 GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() {
33 if (fProcessors) {
34 fProcessors->~GrProcessorSet();
35 }
36 }
37
fixedFunctionFlags() const38 GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const {
39 return GrAATypeIsHW((this->aaType())) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA
40 : GrDrawOp::FixedFunctionFlags::kNone;
41 }
42
isCompatible(const GrSimpleMeshDrawOpHelper & that,const GrCaps & caps,const SkRect & thisBounds,const SkRect & thatBounds) const43 bool GrSimpleMeshDrawOpHelper::isCompatible(const GrSimpleMeshDrawOpHelper& that,
44 const GrCaps& caps, const SkRect& thisBounds,
45 const SkRect& thatBounds) const {
46 if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) {
47 return false;
48 }
49 if (fProcessors) {
50 if (*fProcessors != *that.fProcessors) {
51 return false;
52 }
53 if (fRequiresDstTexture ||
54 (fProcessors->xferProcessor() && fProcessors->xferProcessor()->xferBarrierType(caps))) {
55 if (GrRectsTouchOrOverlap(thisBounds, thatBounds)) {
56 return false;
57 }
58 }
59 }
60 bool result = fPipelineFlags == that.fPipelineFlags && fAAType == that.fAAType;
61 SkASSERT(!result || fCompatibleWithAlphaAsCoveage == that.fCompatibleWithAlphaAsCoveage);
62 SkASSERT(!result || fUsesLocalCoords == that.fUsesLocalCoords);
63 return result;
64 }
65
xpRequiresDstTexture(const GrCaps & caps,const GrAppliedClip * clip,GrPixelConfigIsClamped dstIsClamped,GrProcessorAnalysisCoverage geometryCoverage,GrProcessorAnalysisColor * geometryColor)66 GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture(
67 const GrCaps& caps, const GrAppliedClip* clip, GrPixelConfigIsClamped dstIsClamped,
68 GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor* geometryColor) {
69 SkDEBUGCODE(fDidAnalysis = true);
70 GrProcessorSet::Analysis analysis;
71 if (fProcessors) {
72 GrProcessorAnalysisCoverage coverage = geometryCoverage;
73 if (GrProcessorAnalysisCoverage::kNone == coverage) {
74 coverage = clip->numClipCoverageFragmentProcessors()
75 ? GrProcessorAnalysisCoverage::kSingleChannel
76 : GrProcessorAnalysisCoverage::kNone;
77 }
78 bool isMixedSamples = this->aaType() == GrAAType::kMixedSamples;
79 GrColor overrideColor;
80 analysis = fProcessors->finalize(*geometryColor, coverage, clip, isMixedSamples, caps,
81 dstIsClamped, &overrideColor);
82 if (analysis.inputColorIsOverridden()) {
83 *geometryColor = overrideColor;
84 }
85 } else {
86 analysis = GrProcessorSet::EmptySetAnalysis();
87 }
88 fRequiresDstTexture = analysis.requiresDstTexture();
89 fUsesLocalCoords = analysis.usesLocalCoords();
90 fCompatibleWithAlphaAsCoveage = analysis.isCompatibleWithCoverageAsAlpha();
91 return analysis.requiresDstTexture() ? GrDrawOp::RequiresDstTexture::kYes
92 : GrDrawOp::RequiresDstTexture::kNo;
93 }
94
xpRequiresDstTexture(const GrCaps & caps,const GrAppliedClip * clip,GrPixelConfigIsClamped dstIsClamped,GrProcessorAnalysisCoverage geometryCoverage,GrColor * geometryColor)95 GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture(
96 const GrCaps& caps, const GrAppliedClip* clip, GrPixelConfigIsClamped dstIsClamped,
97 GrProcessorAnalysisCoverage geometryCoverage, GrColor* geometryColor) {
98 GrProcessorAnalysisColor color = *geometryColor;
99 auto result = this->xpRequiresDstTexture(caps, clip, dstIsClamped, geometryCoverage, &color);
100 color.isConstant(geometryColor);
101 return result;
102 }
103
dumpInfo() const104 SkString GrSimpleMeshDrawOpHelper::dumpInfo() const {
105 const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
106 SkString result = processors.dumpProcessors();
107 result.append("AA Type: ");
108 switch (this->aaType()) {
109 case GrAAType::kNone:
110 result.append(" none\n");
111 break;
112 case GrAAType::kCoverage:
113 result.append(" coverage\n");
114 break;
115 case GrAAType::kMSAA:
116 result.append(" msaa\n");
117 break;
118 case GrAAType::kMixedSamples:
119 result.append(" mixed samples\n");
120 break;
121 }
122 result.append(GrPipeline::DumpFlags(fPipelineFlags));
123 return result;
124 }
125
pipelineInitArgs(GrMeshDrawOp::Target * target) const126 GrPipeline::InitArgs GrSimpleMeshDrawOpHelper::pipelineInitArgs(
127 GrMeshDrawOp::Target* target) const {
128 GrPipeline::InitArgs args;
129 args.fFlags = this->pipelineFlags();
130 args.fProxy = target->proxy();
131 args.fDstProxy = target->dstProxy();
132 args.fCaps = &target->caps();
133 args.fResourceProvider = target->resourceProvider();
134 return args;
135 }
136
internalMakePipeline(GrMeshDrawOp::Target * target,const GrPipeline::InitArgs & args)137 GrPipeline* GrSimpleMeshDrawOpHelper::internalMakePipeline(GrMeshDrawOp::Target* target,
138 const GrPipeline::InitArgs& args) {
139 // A caller really should only call this once as the processor set and applied clip get
140 // moved into the GrPipeline.
141 SkASSERT(!fMadePipeline);
142 SkDEBUGCODE(fMadePipeline = true);
143 if (fProcessors) {
144 return target->allocPipeline(args, std::move(*fProcessors), target->detachAppliedClip());
145 } else {
146 return target->allocPipeline(args, GrProcessorSet::MakeEmptySet(),
147 target->detachAppliedClip());
148 }
149 }
150
GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs & args,GrAAType aaType,const GrUserStencilSettings * stencilSettings,Flags flags)151 GrSimpleMeshDrawOpHelperWithStencil::GrSimpleMeshDrawOpHelperWithStencil(
152 const MakeArgs& args, GrAAType aaType, const GrUserStencilSettings* stencilSettings,
153 Flags flags)
154 : INHERITED(args, aaType, flags)
155 , fStencilSettings(stencilSettings ? stencilSettings : &GrUserStencilSettings::kUnused) {}
156
fixedFunctionFlags() const157 GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelperWithStencil::fixedFunctionFlags() const {
158 GrDrawOp::FixedFunctionFlags flags = INHERITED::fixedFunctionFlags();
159 if (fStencilSettings != &GrUserStencilSettings::kUnused) {
160 flags |= GrDrawOp::FixedFunctionFlags::kUsesStencil;
161 }
162 return flags;
163 }
164
isCompatible(const GrSimpleMeshDrawOpHelperWithStencil & that,const GrCaps & caps,const SkRect & thisBounds,const SkRect & thatBounds) const165 bool GrSimpleMeshDrawOpHelperWithStencil::isCompatible(
166 const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps& caps,
167 const SkRect& thisBounds, const SkRect& thatBounds) const {
168 return INHERITED::isCompatible(that, caps, thisBounds, thatBounds) &&
169 fStencilSettings == that.fStencilSettings;
170 }
171
makePipeline(GrMeshDrawOp::Target * target)172 const GrPipeline* GrSimpleMeshDrawOpHelperWithStencil::makePipeline(
173 GrMeshDrawOp::Target* target) {
174 auto args = INHERITED::pipelineInitArgs(target);
175 args.fUserStencil = fStencilSettings;
176 return this->internalMakePipeline(target, args);
177 }
178
dumpInfo() const179 SkString GrSimpleMeshDrawOpHelperWithStencil::dumpInfo() const {
180 SkString result = INHERITED::dumpInfo();
181 result.appendf("Stencil settings: %s\n", (fStencilSettings ? "yes" : "no"));
182 return result;
183 }
184