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