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/GrProgramInfo.h"
11 #include "src/gpu/GrUserStencilSettings.h"
12 #include "src/gpu/SkGr.h"
13 #include "src/gpu/geometry/GrRect.h"
14 #include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
15 
GrSimpleMeshDrawOpHelper(GrProcessorSet * processorSet,GrAAType aaType,InputFlags inputFlags)16 GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(GrProcessorSet* processorSet,
17                                                    GrAAType aaType,
18                                                    InputFlags inputFlags)
19         : fProcessors(processorSet)
20         , fPipelineFlags((GrPipeline::InputFlags)inputFlags)
21         , fAAType((int)aaType)
22         , fUsesLocalCoords(false)
23         , fCompatibleWithCoverageAsAlpha(false) {
24     SkDEBUGCODE(fDidAnalysis = false);
25     SkDEBUGCODE(fMadePipeline = false);
26     if (GrAATypeIsHW(aaType)) {
27         fPipelineFlags |= GrPipeline::InputFlags::kHWAntialias;
28     }
29 }
30 
~GrSimpleMeshDrawOpHelper()31 GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() {
32     if (fProcessors) {
33         fProcessors->~GrProcessorSet();
34     }
35 }
36 
fixedFunctionFlags() const37 GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const {
38     return GrAATypeIsHW(this->aaType()) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA
39                                         : GrDrawOp::FixedFunctionFlags::kNone;
40 }
41 
isCompatible(const GrSimpleMeshDrawOpHelper & that,const GrCaps & caps,const SkRect & thisBounds,const SkRect & thatBounds,bool ignoreAAType) const42 bool GrSimpleMeshDrawOpHelper::isCompatible(const GrSimpleMeshDrawOpHelper& that,
43                                             const GrCaps& caps, const SkRect& thisBounds,
44                                             const SkRect& thatBounds, bool ignoreAAType) const {
45     if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) {
46         return false;
47     }
48     if (fProcessors) {
49         if (*fProcessors != *that.fProcessors) {
50             return false;
51         }
52     }
53 
54 #ifdef SK_DEBUG
55     if (ignoreAAType) {
56         // If we're ignoring AA it should be bc we already know they are the same or that
57         // the are different but are compatible (i.e., one is AA and the other is None)
58         SkASSERT(fAAType == that.fAAType ||
59                  GrMeshDrawOp::CanUpgradeAAOnMerge(this->aaType(), that.aaType()));
60     }
61 #endif
62 
63     bool result = fPipelineFlags == that.fPipelineFlags &&
64                   (ignoreAAType || fAAType == that.fAAType);
65     SkASSERT(!result || fCompatibleWithCoverageAsAlpha == that.fCompatibleWithCoverageAsAlpha);
66     SkASSERT(!result || fUsesLocalCoords == that.fUsesLocalCoords);
67     return result;
68 }
69 
finalizeProcessors(const GrCaps & caps,const GrAppliedClip * clip,bool hasMixedSampledCoverage,GrClampType clampType,GrProcessorAnalysisCoverage geometryCoverage,SkPMColor4f * geometryColor,bool * wideColor)70 GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors(
71         const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
72         GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage,
73         SkPMColor4f* geometryColor, bool* wideColor) {
74     GrProcessorAnalysisColor color = *geometryColor;
75     auto result = this->finalizeProcessors(
76             caps, clip, hasMixedSampledCoverage, clampType, geometryCoverage, &color);
77     color.isConstant(geometryColor);
78     if (wideColor) {
79         *wideColor = !geometryColor->fitsInBytes();
80     }
81     return result;
82 }
83 
finalizeProcessors(const GrCaps & caps,const GrAppliedClip * clip,const GrUserStencilSettings * userStencil,bool hasMixedSampledCoverage,GrClampType clampType,GrProcessorAnalysisCoverage geometryCoverage,GrProcessorAnalysisColor * geometryColor)84 GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors(
85         const GrCaps& caps, const GrAppliedClip* clip, const GrUserStencilSettings* userStencil,
86         bool hasMixedSampledCoverage, GrClampType clampType,
87         GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor* geometryColor) {
88     SkDEBUGCODE(fDidAnalysis = true);
89     GrProcessorSet::Analysis analysis;
90     if (fProcessors) {
91         GrProcessorAnalysisCoverage coverage = geometryCoverage;
92         if (GrProcessorAnalysisCoverage::kNone == coverage) {
93             coverage = clip->hasCoverageFragmentProcessor()
94                                ? GrProcessorAnalysisCoverage::kSingleChannel
95                                : GrProcessorAnalysisCoverage::kNone;
96         }
97         SkPMColor4f overrideColor;
98         analysis = fProcessors->finalize(*geometryColor, coverage, clip, userStencil,
99                                          hasMixedSampledCoverage, caps, clampType, &overrideColor);
100         if (analysis.inputColorIsOverridden()) {
101             *geometryColor = overrideColor;
102         }
103     } else {
104         analysis = GrProcessorSet::EmptySetAnalysis();
105     }
106     fUsesLocalCoords = analysis.usesLocalCoords();
107     fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha();
108     return analysis;
109 }
110 
CreatePipeline(const GrCaps * caps,SkArenaAlloc * arena,GrSwizzle writeViewSwizzle,GrAppliedClip && appliedClip,const GrXferProcessor::DstProxyView & dstProxyView,GrProcessorSet && processorSet,GrPipeline::InputFlags pipelineFlags)111 const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(
112                                                 const GrCaps* caps,
113                                                 SkArenaAlloc* arena,
114                                                 GrSwizzle writeViewSwizzle,
115                                                 GrAppliedClip&& appliedClip,
116                                                 const GrXferProcessor::DstProxyView& dstProxyView,
117                                                 GrProcessorSet&& processorSet,
118                                                 GrPipeline::InputFlags pipelineFlags) {
119     GrPipeline::InitArgs pipelineArgs;
120 
121     pipelineArgs.fInputFlags = pipelineFlags;
122     pipelineArgs.fCaps = caps;
123     pipelineArgs.fDstProxyView = dstProxyView;
124     pipelineArgs.fWriteSwizzle = writeViewSwizzle;
125 
126     return arena->make<GrPipeline>(pipelineArgs,
127                                    std::move(processorSet),
128                                    std::move(appliedClip));
129 }
130 
CreatePipeline(GrOpFlushState * flushState,GrProcessorSet && processorSet,GrPipeline::InputFlags pipelineFlags)131 const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(
132                                                 GrOpFlushState* flushState,
133                                                 GrProcessorSet&& processorSet,
134                                                 GrPipeline::InputFlags pipelineFlags) {
135     return CreatePipeline(&flushState->caps(),
136                           flushState->allocator(),
137                           flushState->writeView()->swizzle(),
138                           flushState->detachAppliedClip(),
139                           flushState->dstProxyView(),
140                           std::move(processorSet),
141                           pipelineFlags);
142 }
143 
createPipeline(GrOpFlushState * flushState)144 const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(GrOpFlushState* flushState) {
145     return CreatePipeline(&flushState->caps(),
146                           flushState->allocator(),
147                           flushState->writeView()->swizzle(),
148                           flushState->detachAppliedClip(),
149                           flushState->dstProxyView(),
150                           this->detachProcessorSet(),
151                           this->pipelineFlags());
152 }
153 
createPipeline(const GrCaps * caps,SkArenaAlloc * arena,GrSwizzle writeViewSwizzle,GrAppliedClip && appliedClip,const GrXferProcessor::DstProxyView & dstProxyView)154 const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(
155         const GrCaps* caps,
156         SkArenaAlloc* arena,
157         GrSwizzle writeViewSwizzle,
158         GrAppliedClip&& appliedClip,
159         const GrXferProcessor::DstProxyView& dstProxyView) {
160     return GrSimpleMeshDrawOpHelper::CreatePipeline(caps,
161                                                     arena,
162                                                     writeViewSwizzle,
163                                                     std::move(appliedClip),
164                                                     dstProxyView,
165                                                     this->detachProcessorSet(),
166                                                     this->pipelineFlags());
167 }
168 
CreateProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView * writeView,GrAppliedClip && appliedClip,const GrXferProcessor::DstProxyView & dstProxyView,GrGeometryProcessor * geometryProcessor,GrProcessorSet && processorSet,GrPrimitiveType primitiveType,GrXferBarrierFlags renderPassXferBarriers,GrPipeline::InputFlags pipelineFlags,const GrUserStencilSettings * stencilSettings)169 GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(
170             const GrCaps* caps,
171             SkArenaAlloc* arena,
172             const GrSurfaceProxyView* writeView,
173             GrAppliedClip&& appliedClip,
174             const GrXferProcessor::DstProxyView& dstProxyView,
175             GrGeometryProcessor* geometryProcessor,
176             GrProcessorSet&& processorSet,
177             GrPrimitiveType primitiveType,
178             GrXferBarrierFlags renderPassXferBarriers,
179             GrPipeline::InputFlags pipelineFlags,
180             const GrUserStencilSettings* stencilSettings) {
181     auto pipeline = CreatePipeline(caps,
182                                    arena,
183                                    writeView->swizzle(),
184                                    std::move(appliedClip),
185                                    dstProxyView,
186                                    std::move(processorSet),
187                                    pipelineFlags);
188 
189     return CreateProgramInfo(arena, pipeline, writeView, geometryProcessor, primitiveType,
190                              renderPassXferBarriers, stencilSettings);
191 }
192 
CreateProgramInfo(SkArenaAlloc * arena,const GrPipeline * pipeline,const GrSurfaceProxyView * writeView,GrGeometryProcessor * geometryProcessor,GrPrimitiveType primitiveType,GrXferBarrierFlags xferBarrierFlags,const GrUserStencilSettings * stencilSettings)193 GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(SkArenaAlloc* arena,
194                                                            const GrPipeline* pipeline,
195                                                            const GrSurfaceProxyView* writeView,
196                                                            GrGeometryProcessor* geometryProcessor,
197                                                            GrPrimitiveType primitiveType,
198                                                            GrXferBarrierFlags xferBarrierFlags,
199                                                            const GrUserStencilSettings* stencilSettings) {
200     GrRenderTargetProxy* outputProxy = writeView->asRenderTargetProxy();
201 
202     auto tmp = arena->make<GrProgramInfo>(outputProxy->numSamples(),
203                                           outputProxy->numStencilSamples(),
204                                           outputProxy->backendFormat(),
205                                           writeView->origin(),
206                                           pipeline,
207                                           stencilSettings,
208                                           geometryProcessor,
209                                           primitiveType,
210                                           0,
211                                           xferBarrierFlags);
212     return tmp;
213 }
214 
createProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView * writeView,GrAppliedClip && appliedClip,const GrXferProcessor::DstProxyView & dstProxyView,GrGeometryProcessor * gp,GrPrimitiveType primType,GrXferBarrierFlags renderPassXferBarriers)215 GrProgramInfo* GrSimpleMeshDrawOpHelper::createProgramInfo(
216                                             const GrCaps* caps,
217                                             SkArenaAlloc* arena,
218                                             const GrSurfaceProxyView* writeView,
219                                             GrAppliedClip&& appliedClip,
220                                             const GrXferProcessor::DstProxyView& dstProxyView,
221                                             GrGeometryProcessor* gp,
222                                             GrPrimitiveType primType,
223                                             GrXferBarrierFlags renderPassXferBarriers) {
224     return CreateProgramInfo(caps,
225                              arena,
226                              writeView,
227                              std::move(appliedClip),
228                              dstProxyView,
229                              gp,
230                              this->detachProcessorSet(),
231                              primType,
232                              renderPassXferBarriers,
233                              this->pipelineFlags());
234 }
235 
236 #if GR_TEST_UTILS
dump_pipeline_flags(GrPipeline::InputFlags flags,SkString * result)237 static void dump_pipeline_flags(GrPipeline::InputFlags flags, SkString* result) {
238     if (GrPipeline::InputFlags::kNone != flags) {
239         if (flags & GrPipeline::InputFlags::kSnapVerticesToPixelCenters) {
240             result->append("Snap vertices to pixel center.\n");
241         }
242         if (flags & GrPipeline::InputFlags::kHWAntialias) {
243             result->append("HW Antialiasing enabled.\n");
244         }
245         if (flags & GrPipeline::InputFlags::kWireframe) {
246             result->append("Wireframe enabled.\n");
247         }
248         if (flags & GrPipeline::InputFlags::kConservativeRaster) {
249             result->append("Conservative raster enabled.\n");
250         }
251         return;
252     }
253     result->append("No pipeline flags\n");
254 }
255 
dumpInfo() const256 SkString GrSimpleMeshDrawOpHelper::dumpInfo() const {
257     const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
258     SkString result = processors.dumpProcessors();
259     result.append("AA Type: ");
260     switch (this->aaType()) {
261         case GrAAType::kNone:
262             result.append(" none\n");
263             break;
264         case GrAAType::kCoverage:
265             result.append(" coverage\n");
266             break;
267         case GrAAType::kMSAA:
268             result.append(" msaa\n");
269             break;
270     }
271     dump_pipeline_flags(fPipelineFlags, &result);
272     return result;
273 }
274 #endif
275