blob: 349e8b6bda5dfdcbc5177079d5df5a1e385ca48e [file] [log] [blame]
bsalomon16b99132015-08-13 14:55:50 -07001/*
2 * Copyright 2015 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
Brian Salomon53e4c3c2016-12-21 11:38:53 -05008#ifndef GrMeshDrawOp_DEFINED
9#define GrMeshDrawOp_DEFINED
bsalomon16b99132015-08-13 14:55:50 -070010
Brian Salomon9afd3712016-12-01 10:59:09 -050011#include "GrDrawOp.h"
bsalomon342bfc22016-04-01 06:06:20 -070012#include "GrGeometryProcessor.h"
egdaniel0e1853c2016-03-17 11:35:45 -070013#include "GrMesh.h"
bsalomon75398562015-08-17 12:55:38 -070014#include "GrPendingProgramElement.h"
Brian Salomone14bd802017-04-04 15:13:25 -040015#include "GrPipelineBuilder.h"
bsalomon75398562015-08-17 12:55:38 -070016
17#include "SkTLList.h"
18
Brian Salomon54d212e2017-03-21 14:22:38 -040019class GrCaps;
Brian Salomon742e31d2016-12-07 17:06:19 -050020class GrOpFlushState;
bsalomon16b99132015-08-13 14:55:50 -070021
22/**
Brian Salomondad29232016-12-01 16:40:24 -050023 * Base class for mesh-drawing GrDrawOps.
bsalomon16b99132015-08-13 14:55:50 -070024 */
Brian Salomondad29232016-12-01 16:40:24 -050025class GrMeshDrawOp : public GrDrawOp {
bsalomon16b99132015-08-13 14:55:50 -070026public:
bsalomon75398562015-08-17 12:55:38 -070027 class Target;
28
Brian Salomond3ccb0a2017-04-03 10:38:00 -040029protected:
30 GrMeshDrawOp(uint32_t classID);
31
Chris Daltonff926502017-05-03 14:36:54 -040032 /** Helper for rendering repeating meshes using a patterned index buffer. This class creates the
33 space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
34 class PatternHelper {
Brian Salomond3ccb0a2017-04-03 10:38:00 -040035 public:
Chris Daltonbca46e22017-05-15 11:03:26 -060036 PatternHelper(GrPrimitiveType primitiveType) : fMesh(primitiveType) {}
Brian Salomond3ccb0a2017-04-03 10:38:00 -040037 /** Returns the allocated storage for the vertices. The caller should populate the vertices
38 before calling recordDraws(). */
Chris Daltonbca46e22017-05-15 11:03:26 -060039 void* init(Target*, size_t vertexStride, const GrBuffer*, int verticesPerRepetition,
40 int indicesPerRepetition, int repeatCount);
Brian Salomond3ccb0a2017-04-03 10:38:00 -040041
42 /** Call after init() to issue draws to the GrMeshDrawOp::Target.*/
43 void recordDraw(Target*, const GrGeometryProcessor*, const GrPipeline*);
44
45 private:
46 GrMesh fMesh;
47 };
48
49 static const int kVerticesPerQuad = 4;
50 static const int kIndicesPerQuad = 6;
51
52 /** A specialization of InstanceHelper for quad rendering. */
Chris Daltonff926502017-05-03 14:36:54 -040053 class QuadHelper : private PatternHelper {
Brian Salomond3ccb0a2017-04-03 10:38:00 -040054 public:
Chris Dalton3809bab2017-06-13 10:55:06 -060055 QuadHelper() : INHERITED(GrPrimitiveType::kTriangles) {}
Brian Salomond3ccb0a2017-04-03 10:38:00 -040056 /** Finds the cached quad index buffer and reserves vertex space. Returns nullptr on failure
57 and on success a pointer to the vertex data that the caller should populate before
58 calling recordDraws(). */
59 void* init(Target*, size_t vertexStride, int quadsToDraw);
60
Chris Daltonff926502017-05-03 14:36:54 -040061 using PatternHelper::recordDraw;
Brian Salomond3ccb0a2017-04-03 10:38:00 -040062
63 private:
Chris Daltonff926502017-05-03 14:36:54 -040064 typedef PatternHelper INHERITED;
Brian Salomond3ccb0a2017-04-03 10:38:00 -040065 };
66
67private:
68 void onPrepare(GrOpFlushState* state) final;
69 void onExecute(GrOpFlushState* state) final;
70
71 virtual void onPrepareDraws(Target*) const = 0;
72
73 // A set of contiguous draws that share a draw token and primitive processor. The draws all use
74 // the op's pipeline. The meshes for the draw are stored in the fMeshes array and each
75 // Queued draw uses fMeshCnt meshes from the fMeshes array. The reason for coallescing meshes
76 // that share a primitive processor into a QueuedDraw is that it allows the Gpu object to setup
77 // the shared state once and then issue draws for each mesh.
78 struct QueuedDraw {
79 int fMeshCnt = 0;
80 GrPendingProgramElement<const GrGeometryProcessor> fGeometryProcessor;
81 const GrPipeline* fPipeline;
82 };
83
84 // All draws in all the GrMeshDrawOps have implicit tokens based on the order they are enqueued
85 // globally across all ops. This is the offset of the first entry in fQueuedDraws.
86 // fQueuedDraws[i]'s token is fBaseDrawToken + i.
87 GrDrawOpUploadToken fBaseDrawToken;
88 SkSTArray<4, GrMesh> fMeshes;
89 SkSTArray<4, QueuedDraw, true> fQueuedDraws;
90
91 typedef GrDrawOp INHERITED;
92};
93
94/**
95 * Many of our ops derive from this class which initializes a GrPipeline just before being recorded.
96 * We are migrating away from use of this class.
97 */
98class GrLegacyMeshDrawOp : public GrMeshDrawOp {
99public:
Brian Salomon54d212e2017-03-21 14:22:38 -0400100 /**
101 * Performs analysis of the fragment processors in GrProcessorSet and GrAppliedClip using the
102 * initial color and coverage from this op's geometry processor.
103 */
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400104 GrProcessorSet::Analysis analyzeUpdateAndRecordProcessors(GrPipelineBuilder* pipelineBuilder,
105 const GrAppliedClip* appliedClip,
106 bool isMixedSamples,
107 const GrCaps& caps,
108 GrColor* overrideColor) const {
Brian Salomona811b122017-03-30 08:21:32 -0400109 GrProcessorAnalysisColor inputColor;
110 GrProcessorAnalysisCoverage inputCoverage;
111 this->getProcessorAnalysisInputs(&inputColor, &inputCoverage);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400112 return pipelineBuilder->finalizeProcessors(inputColor, inputCoverage, appliedClip,
113 isMixedSamples, caps, overrideColor);
Brian Salomon54d212e2017-03-21 14:22:38 -0400114 }
115
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400116 void initPipeline(const GrPipeline::InitArgs& args, const GrProcessorSet::Analysis& analysis,
117 GrColor overrideColor) {
Brian Salomone7d30482017-03-29 12:09:15 -0400118 fPipeline.init(args);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400119 this->applyPipelineOptimizations(PipelineOptimizations(analysis, overrideColor));
Brian Salomon54d212e2017-03-21 14:22:38 -0400120 }
121
Robert Phillipsf5442bb2017-04-17 14:18:34 -0400122 void addDependenciesTo(GrRenderTargetProxy* rtp) {
123 fPipeline.addDependenciesTo(rtp);
124 }
125
Brian Salomon54d212e2017-03-21 14:22:38 -0400126 /**
127 * Mesh draw ops use a legacy system in GrRenderTargetContext where the pipeline is created when
128 * the op is recorded. These methods are unnecessary as this information is in the pipeline.
129 */
130 FixedFunctionFlags fixedFunctionFlags() const override {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400131 SkFAIL("This should never be called for legacy mesh draw ops.");
Brian Salomon54d212e2017-03-21 14:22:38 -0400132 return FixedFunctionFlags::kNone;
133 }
134 bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400135 SkFAIL("Should never be called for legacy mesh draw ops.");
Brian Salomon54d212e2017-03-21 14:22:38 -0400136 return false;
137 }
Brian Salomon2bf4b3a2017-03-16 14:19:07 -0400138
Brian Salomonc48af932017-03-16 19:51:42 +0000139protected:
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400140 GrLegacyMeshDrawOp(uint32_t classID) : INHERITED(classID) {}
Brian Salomone7d30482017-03-29 12:09:15 -0400141 /**
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400142 * This is a legacy class only used by GrLegacyMeshDrawOp and will be removed. It presents some
143 * aspects of GrProcessorSet::Analysis to GrLegacyMeshDrawOp subclasses.
Brian Salomone7d30482017-03-29 12:09:15 -0400144 */
145 class PipelineOptimizations {
146 public:
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400147 PipelineOptimizations(const GrProcessorSet::Analysis& analysis, GrColor overrideColor) {
Brian Salomone7d30482017-03-29 12:09:15 -0400148 fFlags = 0;
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400149 if (analysis.inputColorIsOverridden()) {
Brian Salomone7d30482017-03-29 12:09:15 -0400150 fFlags |= kUseOverrideColor_Flag;
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400151 fOverrideColor = overrideColor;
Brian Salomone7d30482017-03-29 12:09:15 -0400152 }
153 if (analysis.usesLocalCoords()) {
154 fFlags |= kReadsLocalCoords_Flag;
155 }
156 if (analysis.isCompatibleWithCoverageAsAlpha()) {
157 fFlags |= kCanTweakAlphaForCoverage_Flag;
158 }
159 }
160
161 /** Does the pipeline require access to (implicit or explicit) local coordinates? */
162 bool readsLocalCoords() const { return SkToBool(kReadsLocalCoords_Flag & fFlags); }
163
164 /** Does the pipeline allow the GrPrimitiveProcessor to combine color and coverage into one
165 color output ? */
166 bool canTweakAlphaForCoverage() const {
167 return SkToBool(kCanTweakAlphaForCoverage_Flag & fFlags);
168 }
169
170 /** Does the pipeline require the GrPrimitiveProcessor to specify a specific color (and if
171 so get the color)? */
172 bool getOverrideColorIfSet(GrColor* overrideColor) const {
173 if (SkToBool(kUseOverrideColor_Flag & fFlags)) {
174 if (overrideColor) {
175 *overrideColor = fOverrideColor;
176 }
177 return true;
178 }
179 return false;
180 }
181
182 private:
183 enum {
184 // If this is not set the primitive processor need not produce local coordinates
185 kReadsLocalCoords_Flag = 0x1,
186 // If this flag is set then the primitive processor may produce color*coverage as
187 // its color output (and not output a separate coverage).
188 kCanTweakAlphaForCoverage_Flag = 0x2,
189 // If this flag is set the GrPrimitiveProcessor must produce fOverrideColor as its
190 // output color. If not set fOverrideColor is to be ignored.
191 kUseOverrideColor_Flag = 0x4,
192 };
193
194 uint32_t fFlags;
195 GrColor fOverrideColor;
196 };
Brian Salomon54d212e2017-03-21 14:22:38 -0400197
Brian Salomon54d212e2017-03-21 14:22:38 -0400198 const GrPipeline* pipeline() const {
199 SkASSERT(fPipeline.isInitialized());
200 return &fPipeline;
201 }
202
bsalomon16b99132015-08-13 14:55:50 -0700203private:
Brian Salomon54d212e2017-03-21 14:22:38 -0400204 /**
205 * Provides information about the GrPrimitiveProccesor color and coverage outputs which become
206 * inputs to the first color and coverage fragment processors.
207 */
Brian Salomona811b122017-03-30 08:21:32 -0400208 virtual void getProcessorAnalysisInputs(GrProcessorAnalysisColor*,
209 GrProcessorAnalysisCoverage*) const = 0;
Brian Salomon54d212e2017-03-21 14:22:38 -0400210
211 /**
Brian Salomona811b122017-03-30 08:21:32 -0400212 * After processor analysis is complete this is called so that the op can use the analysis
Brian Salomon54d212e2017-03-21 14:22:38 -0400213 * results when constructing its GrPrimitiveProcessor.
214 */
Brian Salomone7d30482017-03-29 12:09:15 -0400215 virtual void applyPipelineOptimizations(const PipelineOptimizations&) = 0;
Brian Salomon54d212e2017-03-21 14:22:38 -0400216
Brian Salomon54d212e2017-03-21 14:22:38 -0400217 GrPipeline fPipeline;
bsalomon75398562015-08-17 12:55:38 -0700218
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400219 typedef GrMeshDrawOp INHERITED;
bsalomon16b99132015-08-13 14:55:50 -0700220};
221
222#endif