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
16GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(const MakeArgs& args,
17 GrAAType aaType,
18 InputFlags inputFlags)
19 : fProcessors(args.fProcessorSet)
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
31GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() {
32 if (fProcessors) {
33 fProcessors->~GrProcessorSet();
34 }
35}
36
37GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const {
38 return GrAATypeIsHW(this->aaType()) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA
39 : GrDrawOp::FixedFunctionFlags::kNone;
40}
41
42bool 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
70GrProcessorSet::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
84GrProcessorSet::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->numClipCoverageFragmentProcessors()
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
111const 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 const GrUserStencilSettings* stencilSettings) {
120 GrPipeline::InitArgs pipelineArgs;
121
122 pipelineArgs.fInputFlags = pipelineFlags;
123 pipelineArgs.fUserStencil = stencilSettings;
124 pipelineArgs.fCaps = caps;
125 pipelineArgs.fDstProxyView = dstProxyView;
126 pipelineArgs.fWriteSwizzle = writeViewSwizzle;
127
128 return arena->make<GrPipeline>(pipelineArgs,
129 std::move(processorSet),
130 std::move(appliedClip));
131}
132
133const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(
134 GrOpFlushState* flushState,
135 GrProcessorSet&& processorSet,
136 GrPipeline::InputFlags pipelineFlags,
137 const GrUserStencilSettings* stencilSettings) {
138 return CreatePipeline(&flushState->caps(),
139 flushState->allocator(),
140 flushState->writeView()->swizzle(),
141 flushState->detachAppliedClip(),
142 flushState->dstProxyView(),
143 std::move(processorSet),
144 pipelineFlags,
145 stencilSettings);
146}
147
148const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(GrOpFlushState* flushState) {
149 return CreatePipeline(&flushState->caps(),
150 flushState->allocator(),
151 flushState->writeView()->swizzle(),
152 flushState->detachAppliedClip(),
153 flushState->dstProxyView(),
154 this->detachProcessorSet(),
155 this->pipelineFlags());
156}
157
158GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(
159 const GrCaps* caps,
160 SkArenaAlloc* arena,
161 const GrSurfaceProxyView* writeView,
162 GrAppliedClip&& appliedClip,
163 const GrXferProcessor::DstProxyView& dstProxyView,
164 GrGeometryProcessor* geometryProcessor,
165 GrProcessorSet&& processorSet,
166 GrPrimitiveType primitiveType,
167 GrPipeline::InputFlags pipelineFlags,
168 const GrUserStencilSettings* stencilSettings) {
169 auto pipeline = CreatePipeline(caps,
170 arena,
171 writeView->swizzle(),
172 std::move(appliedClip),
173 dstProxyView,
174 std::move(processorSet),
175 pipelineFlags,
176 stencilSettings);
177
178 return CreateProgramInfo(arena, pipeline, writeView, geometryProcessor, primitiveType);
179}
180
181GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(SkArenaAlloc* arena,
182 const GrPipeline* pipeline,
183 const GrSurfaceProxyView* writeView,
184 GrGeometryProcessor* geometryProcessor,
185 GrPrimitiveType primitiveType) {
186 GrRenderTargetProxy* outputProxy = writeView->asRenderTargetProxy();
187
188 auto tmp = arena->make<GrProgramInfo>(outputProxy->numSamples(),
189 outputProxy->numStencilSamples(),
190 outputProxy->backendFormat(),
191 writeView->origin(),
192 pipeline,
193 geometryProcessor,
194 primitiveType);
195 return tmp;
196}
197
198GrProgramInfo* GrSimpleMeshDrawOpHelper::createProgramInfo(
199 const GrCaps* caps,
200 SkArenaAlloc* arena,
201 const GrSurfaceProxyView* writeView,
202 GrAppliedClip&& appliedClip,
203 const GrXferProcessor::DstProxyView& dstProxyView,
204 GrGeometryProcessor* gp,
205 GrPrimitiveType primType) {
206 return CreateProgramInfo(caps,
207 arena,
208 writeView,
209 std::move(appliedClip),
210 dstProxyView,
211 gp,
212 this->detachProcessorSet(),
213 primType,
214 this->pipelineFlags());
215}
216
217#ifdef SK_DEBUG
218static void dump_pipeline_flags(GrPipeline::InputFlags flags, SkString* result) {
219 if (GrPipeline::InputFlags::kNone != flags) {
220 if (flags & GrPipeline::InputFlags::kSnapVerticesToPixelCenters) {
221 result->append("Snap vertices to pixel center.\n");
222 }
223 if (flags & GrPipeline::InputFlags::kHWAntialias) {
224 result->append("HW Antialiasing enabled.\n");
225 }
226 return;
227 }
228 result->append("No pipeline flags\n");
229}
230
231SkString GrSimpleMeshDrawOpHelper::dumpInfo() const {
232 const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
233 SkString result = processors.dumpProcessors();
234 result.append("AA Type: ");
235 switch (this->aaType()) {
236 case GrAAType::kNone:
237 result.append(" none\n");
238 break;
239 case GrAAType::kCoverage:
240 result.append(" coverage\n");
241 break;
242 case GrAAType::kMSAA:
243 result.append(" msaa\n");
244 break;
245 }
246 dump_pipeline_flags(fPipelineFlags, &result);
247 return result;
248}
249#endif
250