blob: 41d3848666e6f399e355624087d8b165fb844b98 [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
32 /** Helper for rendering instances using an instanced index buffer. This class creates the space
33 for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
34 class InstancedHelper {
35 public:
36 InstancedHelper() {}
37 /** Returns the allocated storage for the vertices. The caller should populate the vertices
38 before calling recordDraws(). */
39 void* init(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*,
40 int verticesPerInstance, int indicesPerInstance, int instancesToDraw);
41
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. */
53 class QuadHelper : private InstancedHelper {
54 public:
55 QuadHelper() : INHERITED() {}
56 /** 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
61 using InstancedHelper::recordDraw;
62
63 private:
64 typedef InstancedHelper INHERITED;
65 };
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 Salomon5dac9b32017-04-08 02:53:30 +0000104 void analyzeProcessors(GrProcessorSet::Analysis* analysis,
105 GrPipelineBuilder* pipelineBuilder,
106 const GrAppliedClip* appliedClip,
107 const GrCaps& caps) const {
Brian Salomona811b122017-03-30 08:21:32 -0400108 GrProcessorAnalysisColor inputColor;
109 GrProcessorAnalysisCoverage inputCoverage;
110 this->getProcessorAnalysisInputs(&inputColor, &inputCoverage);
Brian Salomon5dac9b32017-04-08 02:53:30 +0000111 pipelineBuilder->analyzeAndEliminateFragmentProcessors(analysis, inputColor, inputCoverage,
112 appliedClip, caps);
Brian Salomon54d212e2017-03-21 14:22:38 -0400113 }
114
Brian Salomon5dac9b32017-04-08 02:53:30 +0000115 void initPipeline(const GrPipeline::InitArgs& args, const GrProcessorSet::Analysis& analysis) {
Brian Salomone7d30482017-03-29 12:09:15 -0400116 fPipeline.init(args);
Brian Salomon5dac9b32017-04-08 02:53:30 +0000117 this->applyPipelineOptimizations(PipelineOptimizations(analysis));
Brian Salomon54d212e2017-03-21 14:22:38 -0400118 }
119
120 /**
121 * Mesh draw ops use a legacy system in GrRenderTargetContext where the pipeline is created when
122 * the op is recorded. These methods are unnecessary as this information is in the pipeline.
123 */
124 FixedFunctionFlags fixedFunctionFlags() const override {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400125 SkFAIL("This should never be called for legacy mesh draw ops.");
Brian Salomon54d212e2017-03-21 14:22:38 -0400126 return FixedFunctionFlags::kNone;
127 }
128 bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400129 SkFAIL("Should never be called for legacy mesh draw ops.");
Brian Salomon54d212e2017-03-21 14:22:38 -0400130 return false;
131 }
Brian Salomon2bf4b3a2017-03-16 14:19:07 -0400132
Brian Salomonc48af932017-03-16 19:51:42 +0000133protected:
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400134 GrLegacyMeshDrawOp(uint32_t classID) : INHERITED(classID) {}
Brian Salomone7d30482017-03-29 12:09:15 -0400135 /**
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400136 * This is a legacy class only used by GrLegacyMeshDrawOp and will be removed. It presents some
137 * aspects of GrProcessorSet::Analysis to GrLegacyMeshDrawOp subclasses.
Brian Salomone7d30482017-03-29 12:09:15 -0400138 */
139 class PipelineOptimizations {
140 public:
Brian Salomon5dac9b32017-04-08 02:53:30 +0000141 PipelineOptimizations(const GrProcessorSet::Analysis& analysis) {
Brian Salomone7d30482017-03-29 12:09:15 -0400142 fFlags = 0;
Brian Salomon5dac9b32017-04-08 02:53:30 +0000143 if (analysis.getInputColorOverrideAndColorProcessorEliminationCount(&fOverrideColor) >=
144 0) {
Brian Salomone7d30482017-03-29 12:09:15 -0400145 fFlags |= kUseOverrideColor_Flag;
146 }
147 if (analysis.usesLocalCoords()) {
148 fFlags |= kReadsLocalCoords_Flag;
149 }
150 if (analysis.isCompatibleWithCoverageAsAlpha()) {
151 fFlags |= kCanTweakAlphaForCoverage_Flag;
152 }
153 }
154
155 /** Does the pipeline require access to (implicit or explicit) local coordinates? */
156 bool readsLocalCoords() const { return SkToBool(kReadsLocalCoords_Flag & fFlags); }
157
158 /** Does the pipeline allow the GrPrimitiveProcessor to combine color and coverage into one
159 color output ? */
160 bool canTweakAlphaForCoverage() const {
161 return SkToBool(kCanTweakAlphaForCoverage_Flag & fFlags);
162 }
163
164 /** Does the pipeline require the GrPrimitiveProcessor to specify a specific color (and if
165 so get the color)? */
166 bool getOverrideColorIfSet(GrColor* overrideColor) const {
167 if (SkToBool(kUseOverrideColor_Flag & fFlags)) {
168 if (overrideColor) {
169 *overrideColor = fOverrideColor;
170 }
171 return true;
172 }
173 return false;
174 }
175
176 private:
177 enum {
178 // If this is not set the primitive processor need not produce local coordinates
179 kReadsLocalCoords_Flag = 0x1,
180 // If this flag is set then the primitive processor may produce color*coverage as
181 // its color output (and not output a separate coverage).
182 kCanTweakAlphaForCoverage_Flag = 0x2,
183 // If this flag is set the GrPrimitiveProcessor must produce fOverrideColor as its
184 // output color. If not set fOverrideColor is to be ignored.
185 kUseOverrideColor_Flag = 0x4,
186 };
187
188 uint32_t fFlags;
189 GrColor fOverrideColor;
190 };
Brian Salomon54d212e2017-03-21 14:22:38 -0400191
Brian Salomon54d212e2017-03-21 14:22:38 -0400192 const GrPipeline* pipeline() const {
193 SkASSERT(fPipeline.isInitialized());
194 return &fPipeline;
195 }
196
bsalomon16b99132015-08-13 14:55:50 -0700197private:
Brian Salomon54d212e2017-03-21 14:22:38 -0400198 /**
199 * Provides information about the GrPrimitiveProccesor color and coverage outputs which become
200 * inputs to the first color and coverage fragment processors.
201 */
Brian Salomona811b122017-03-30 08:21:32 -0400202 virtual void getProcessorAnalysisInputs(GrProcessorAnalysisColor*,
203 GrProcessorAnalysisCoverage*) const = 0;
Brian Salomon54d212e2017-03-21 14:22:38 -0400204
205 /**
Brian Salomona811b122017-03-30 08:21:32 -0400206 * After processor analysis is complete this is called so that the op can use the analysis
Brian Salomon54d212e2017-03-21 14:22:38 -0400207 * results when constructing its GrPrimitiveProcessor.
208 */
Brian Salomone7d30482017-03-29 12:09:15 -0400209 virtual void applyPipelineOptimizations(const PipelineOptimizations&) = 0;
Brian Salomon54d212e2017-03-21 14:22:38 -0400210
Brian Salomon54d212e2017-03-21 14:22:38 -0400211 GrPipeline fPipeline;
bsalomon75398562015-08-17 12:55:38 -0700212
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400213 typedef GrMeshDrawOp INHERITED;
bsalomon16b99132015-08-13 14:55:50 -0700214};
215
216#endif