blob: 8daa62b374161516a96d4053f2d3aedc7310e21d [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"
bsalomon75398562015-08-17 12:55:38 -070015
16#include "SkTLList.h"
17
Brian Salomon54d212e2017-03-21 14:22:38 -040018class GrCaps;
Brian Salomon742e31d2016-12-07 17:06:19 -050019class GrOpFlushState;
bsalomon16b99132015-08-13 14:55:50 -070020
21/**
Brian Salomondad29232016-12-01 16:40:24 -050022 * Base class for mesh-drawing GrDrawOps.
bsalomon16b99132015-08-13 14:55:50 -070023 */
Brian Salomondad29232016-12-01 16:40:24 -050024class GrMeshDrawOp : public GrDrawOp {
bsalomon16b99132015-08-13 14:55:50 -070025public:
bsalomon75398562015-08-17 12:55:38 -070026 class Target;
27
Brian Salomond3ccb0a2017-04-03 10:38:00 -040028protected:
29 GrMeshDrawOp(uint32_t classID);
30
31 /** Helper for rendering instances using an instanced index buffer. This class creates the space
32 for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
33 class InstancedHelper {
34 public:
35 InstancedHelper() {}
36 /** Returns the allocated storage for the vertices. The caller should populate the vertices
37 before calling recordDraws(). */
38 void* init(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*,
39 int verticesPerInstance, int indicesPerInstance, int instancesToDraw);
40
41 /** Call after init() to issue draws to the GrMeshDrawOp::Target.*/
42 void recordDraw(Target*, const GrGeometryProcessor*, const GrPipeline*);
43
44 private:
45 GrMesh fMesh;
46 };
47
48 static const int kVerticesPerQuad = 4;
49 static const int kIndicesPerQuad = 6;
50
51 /** A specialization of InstanceHelper for quad rendering. */
52 class QuadHelper : private InstancedHelper {
53 public:
54 QuadHelper() : INHERITED() {}
55 /** Finds the cached quad index buffer and reserves vertex space. Returns nullptr on failure
56 and on success a pointer to the vertex data that the caller should populate before
57 calling recordDraws(). */
58 void* init(Target*, size_t vertexStride, int quadsToDraw);
59
60 using InstancedHelper::recordDraw;
61
62 private:
63 typedef InstancedHelper INHERITED;
64 };
65
66private:
67 void onPrepare(GrOpFlushState* state) final;
68 void onExecute(GrOpFlushState* state) final;
69
70 virtual void onPrepareDraws(Target*) const = 0;
71
72 // A set of contiguous draws that share a draw token and primitive processor. The draws all use
73 // the op's pipeline. The meshes for the draw are stored in the fMeshes array and each
74 // Queued draw uses fMeshCnt meshes from the fMeshes array. The reason for coallescing meshes
75 // that share a primitive processor into a QueuedDraw is that it allows the Gpu object to setup
76 // the shared state once and then issue draws for each mesh.
77 struct QueuedDraw {
78 int fMeshCnt = 0;
79 GrPendingProgramElement<const GrGeometryProcessor> fGeometryProcessor;
80 const GrPipeline* fPipeline;
81 };
82
83 // All draws in all the GrMeshDrawOps have implicit tokens based on the order they are enqueued
84 // globally across all ops. This is the offset of the first entry in fQueuedDraws.
85 // fQueuedDraws[i]'s token is fBaseDrawToken + i.
86 GrDrawOpUploadToken fBaseDrawToken;
87 SkSTArray<4, GrMesh> fMeshes;
88 SkSTArray<4, QueuedDraw, true> fQueuedDraws;
89
90 typedef GrDrawOp INHERITED;
91};
92
93/**
94 * Many of our ops derive from this class which initializes a GrPipeline just before being recorded.
95 * We are migrating away from use of this class.
96 */
97class GrLegacyMeshDrawOp : public GrMeshDrawOp {
98public:
Brian Salomon54d212e2017-03-21 14:22:38 -040099 /**
100 * Performs analysis of the fragment processors in GrProcessorSet and GrAppliedClip using the
101 * initial color and coverage from this op's geometry processor.
102 */
Brian Salomona811b122017-03-30 08:21:32 -0400103 void analyzeProcessors(GrProcessorSet::Analysis* analysis,
Brian Salomon54d212e2017-03-21 14:22:38 -0400104 const GrProcessorSet& processors,
105 const GrAppliedClip* appliedClip,
106 const GrCaps& caps) const {
Brian Salomona811b122017-03-30 08:21:32 -0400107 GrProcessorAnalysisColor inputColor;
108 GrProcessorAnalysisCoverage inputCoverage;
109 this->getProcessorAnalysisInputs(&inputColor, &inputCoverage);
Brian Salomonc0b642c2017-03-27 13:09:36 -0400110 analysis->init(inputColor, inputCoverage, processors, appliedClip, caps);
Brian Salomon54d212e2017-03-21 14:22:38 -0400111 }
112
113 void initPipeline(const GrPipeline::InitArgs& args) {
Brian Salomone7d30482017-03-29 12:09:15 -0400114 fPipeline.init(args);
115 this->applyPipelineOptimizations(PipelineOptimizations(*args.fAnalysis));
Brian Salomon54d212e2017-03-21 14:22:38 -0400116 }
117
118 /**
119 * Mesh draw ops use a legacy system in GrRenderTargetContext where the pipeline is created when
120 * the op is recorded. These methods are unnecessary as this information is in the pipeline.
121 */
122 FixedFunctionFlags fixedFunctionFlags() const override {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400123 SkFAIL("This should never be called for legacy mesh draw ops.");
Brian Salomon54d212e2017-03-21 14:22:38 -0400124 return FixedFunctionFlags::kNone;
125 }
126 bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400127 SkFAIL("Should never be called for legacy mesh draw ops.");
Brian Salomon54d212e2017-03-21 14:22:38 -0400128 return false;
129 }
Brian Salomon2bf4b3a2017-03-16 14:19:07 -0400130
Brian Salomonc48af932017-03-16 19:51:42 +0000131protected:
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400132 GrLegacyMeshDrawOp(uint32_t classID) : INHERITED(classID) {}
Brian Salomone7d30482017-03-29 12:09:15 -0400133 /**
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400134 * This is a legacy class only used by GrLegacyMeshDrawOp and will be removed. It presents some
135 * aspects of GrProcessorSet::Analysis to GrLegacyMeshDrawOp subclasses.
Brian Salomone7d30482017-03-29 12:09:15 -0400136 */
137 class PipelineOptimizations {
138 public:
Brian Salomona811b122017-03-30 08:21:32 -0400139 PipelineOptimizations(const GrProcessorSet::Analysis& analysis) {
Brian Salomone7d30482017-03-29 12:09:15 -0400140 fFlags = 0;
141 if (analysis.getInputColorOverrideAndColorProcessorEliminationCount(&fOverrideColor) >=
142 0) {
143 fFlags |= kUseOverrideColor_Flag;
144 }
145 if (analysis.usesLocalCoords()) {
146 fFlags |= kReadsLocalCoords_Flag;
147 }
148 if (analysis.isCompatibleWithCoverageAsAlpha()) {
149 fFlags |= kCanTweakAlphaForCoverage_Flag;
150 }
151 }
152
153 /** Does the pipeline require access to (implicit or explicit) local coordinates? */
154 bool readsLocalCoords() const { return SkToBool(kReadsLocalCoords_Flag & fFlags); }
155
156 /** Does the pipeline allow the GrPrimitiveProcessor to combine color and coverage into one
157 color output ? */
158 bool canTweakAlphaForCoverage() const {
159 return SkToBool(kCanTweakAlphaForCoverage_Flag & fFlags);
160 }
161
162 /** Does the pipeline require the GrPrimitiveProcessor to specify a specific color (and if
163 so get the color)? */
164 bool getOverrideColorIfSet(GrColor* overrideColor) const {
165 if (SkToBool(kUseOverrideColor_Flag & fFlags)) {
166 if (overrideColor) {
167 *overrideColor = fOverrideColor;
168 }
169 return true;
170 }
171 return false;
172 }
173
174 private:
175 enum {
176 // If this is not set the primitive processor need not produce local coordinates
177 kReadsLocalCoords_Flag = 0x1,
178 // If this flag is set then the primitive processor may produce color*coverage as
179 // its color output (and not output a separate coverage).
180 kCanTweakAlphaForCoverage_Flag = 0x2,
181 // If this flag is set the GrPrimitiveProcessor must produce fOverrideColor as its
182 // output color. If not set fOverrideColor is to be ignored.
183 kUseOverrideColor_Flag = 0x4,
184 };
185
186 uint32_t fFlags;
187 GrColor fOverrideColor;
188 };
Brian Salomon54d212e2017-03-21 14:22:38 -0400189
Brian Salomon54d212e2017-03-21 14:22:38 -0400190 const GrPipeline* pipeline() const {
191 SkASSERT(fPipeline.isInitialized());
192 return &fPipeline;
193 }
194
bsalomon16b99132015-08-13 14:55:50 -0700195private:
Brian Salomon54d212e2017-03-21 14:22:38 -0400196 /**
197 * Provides information about the GrPrimitiveProccesor color and coverage outputs which become
198 * inputs to the first color and coverage fragment processors.
199 */
Brian Salomona811b122017-03-30 08:21:32 -0400200 virtual void getProcessorAnalysisInputs(GrProcessorAnalysisColor*,
201 GrProcessorAnalysisCoverage*) const = 0;
Brian Salomon54d212e2017-03-21 14:22:38 -0400202
203 /**
Brian Salomona811b122017-03-30 08:21:32 -0400204 * After processor analysis is complete this is called so that the op can use the analysis
Brian Salomon54d212e2017-03-21 14:22:38 -0400205 * results when constructing its GrPrimitiveProcessor.
206 */
Brian Salomone7d30482017-03-29 12:09:15 -0400207 virtual void applyPipelineOptimizations(const PipelineOptimizations&) = 0;
Brian Salomon54d212e2017-03-21 14:22:38 -0400208
Brian Salomon54d212e2017-03-21 14:22:38 -0400209 GrPipeline fPipeline;
bsalomon75398562015-08-17 12:55:38 -0700210
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400211 typedef GrMeshDrawOp INHERITED;
bsalomon16b99132015-08-13 14:55:50 -0700212};
213
214#endif