blob: 24db2e08dd83730a193372563ed95c80ef12693b [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00006 */
7
reed@google.comac10a2d2010-12-22 21:39:39 +00008#include "GrInOrderDrawBuffer.h"
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +00009
joshualitt5478d422014-11-14 16:00:38 -080010#include "GrDefaultGeoProcFactory.h"
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000011#include "GrTemplates.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000012
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000013GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
bsalomon@google.com471d4712011-08-23 15:45:25 +000014 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000015 GrIndexBufferAllocPool* indexPool)
bsalomon371bcbc2014-12-01 08:19:34 -080016 : INHERITED(gpu, vertexPool, indexPool)
robertphillipsdad77942015-03-03 09:28:16 -080017 , fCommands(gpu, vertexPool, indexPool)
robertphillips9888b222015-02-27 08:50:34 -080018 , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4)
19 , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4)
robertphillipsdad77942015-03-03 09:28:16 -080020 , fDrawID(0) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000021
bsalomon49f085d2014-09-05 13:34:00 -070022 SkASSERT(vertexPool);
23 SkASSERT(indexPool);
reed@google.comac10a2d2010-12-22 21:39:39 +000024}
25
26GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000027 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000028}
29
bsalomon@google.com934c5702012-03-20 21:17:58 +000030////////////////////////////////////////////////////////////////////////////////
31
bsalomon62c447d2014-08-08 08:08:50 -070032/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
33 have explicit local coords and sometimes not. We *could* always provide explicit local coords
34 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
35 haven't seen a use case which frequently switches between local rect and no local rect draws.
36
37 The color param is used to determine whether the opaque hint can be set on the draw state.
38 The caller must populate the vertex colors itself.
39
40 The vertex attrib order is always pos, color, [local coords].
41 */
joshualitt8fc6c2d2014-12-22 15:27:05 -080042static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords,
43 GrColor color,
44 const SkMatrix* localMatrix) {
joshualitt5478d422014-11-14 16:00:38 -080045 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
46 GrDefaultGeoProcFactory::kColor_GPType;
joshualitt8fc6c2d2014-12-22 15:27:05 -080047 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
48 if (localMatrix) {
joshualitt8059eb92014-12-29 15:10:07 -080049 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *localMatrix,
50 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080051 } else {
joshualitt8059eb92014-12-29 15:10:07 -080052 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMatrix::I(),
53 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080054 }
bsalomon62c447d2014-08-08 08:08:50 -070055}
robertphillips@google.com42903302013-04-20 12:26:07 +000056
joshualitt58773332015-02-23 16:41:42 -080057class RectBatch : public GrBatch {
58public:
59 struct Geometry {
60 GrColor fColor;
61 SkMatrix fViewMatrix;
62 SkRect fRect;
63 bool fHasLocalRect;
64 bool fHasLocalMatrix;
65 SkRect fLocalRect;
66 SkMatrix fLocalMatrix;
67 };
68
69 static GrBatch* Create(const Geometry& geometry) {
70 return SkNEW_ARGS(RectBatch, (geometry));
71 }
72
73 const char* name() const SK_OVERRIDE { return "RectBatch"; }
74
75 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE {
76 // When this is called on a batch, there is only one geometry bundle
77 out->setKnownFourComponents(fGeoData[0].fColor);
78 }
79
80 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
81 out->setKnownSingleComponent(0xff);
82 }
83
84 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE {
85 // Handle any color overrides
86 if (init.fColorIgnored) {
87 fGeoData[0].fColor = GrColor_ILLEGAL;
88 } else if (GrColor_ILLEGAL != init.fOverrideColor) {
89 fGeoData[0].fColor = init.fOverrideColor;
90 }
91
92 // setup batch properties
93 fBatch.fColorIgnored = init.fColorIgnored;
94 fBatch.fColor = fGeoData[0].fColor;
95 fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
96 fBatch.fCoverageIgnored = init.fCoverageIgnored;
97 }
98
99 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE {
100 // Go to device coords to allow batching across matrix changes
101 SkMatrix invert = SkMatrix::I();
102
103 // if we have a local rect, then we apply the localMatrix directly to the localRect to
104 // generate vertex local coords
105 bool hasExplicitLocalCoords = this->hasLocalRect();
106 if (!hasExplicitLocalCoords) {
107 if (!this->viewMatrix().isIdentity() && !this->viewMatrix().invert(&invert)) {
108 SkDebugf("Could not invert\n");
109 return;
110 }
111
112 if (this->hasLocalMatrix()) {
113 invert.preConcat(this->localMatrix());
114 }
115 }
116
117 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCoords,
118 this->color(),
119 &invert));
120
121 batchTarget->initDraw(gp, pipeline);
122
123 // TODO this is hacky, but the only way we have to initialize the GP is to use the
124 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch
125 // everywhere we can remove this nastiness
126 GrPipelineInfo init;
127 init.fColorIgnored = fBatch.fColorIgnored;
128 init.fOverrideColor = GrColor_ILLEGAL;
129 init.fCoverageIgnored = fBatch.fCoverageIgnored;
130 init.fUsesLocalCoords = this->usesLocalCoords();
131 gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
132
133 size_t vertexStride = gp->getVertexStride();
134
135 SkASSERT(hasExplicitLocalCoords ?
136 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
137 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
138
139 int instanceCount = fGeoData.count();
140 int vertexCount = kVertsPerRect * instanceCount;
141
142 const GrVertexBuffer* vertexBuffer;
143 int firstVertex;
144
145 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
146 vertexCount,
147 &vertexBuffer,
148 &firstVertex);
149
150 for (int i = 0; i < instanceCount; i++) {
151 const Geometry& args = fGeoData[i];
152
153 intptr_t offset = GrTCast<intptr_t>(vertices) + kVertsPerRect * i * vertexStride;
154 SkPoint* positions = GrTCast<SkPoint*>(offset);
155
156 positions->setRectFan(args.fRect.fLeft, args.fRect.fTop,
157 args.fRect.fRight, args.fRect.fBottom, vertexStride);
158 args.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVertsPerRect);
159
160 if (args.fHasLocalRect) {
161 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
162 SkPoint* coords = GrTCast<SkPoint*>(offset + kLocalOffset);
163 coords->setRectFan(args.fLocalRect.fLeft, args.fLocalRect.fTop,
164 args.fLocalRect.fRight, args.fLocalRect.fBottom,
165 vertexStride);
166 if (args.fHasLocalMatrix) {
167 args.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVertsPerRect);
168 }
169 }
170
171 static const int kColorOffset = sizeof(SkPoint);
172 GrColor* vertColor = GrTCast<GrColor*>(offset + kColorOffset);
173 for (int j = 0; j < 4; ++j) {
174 *vertColor = args.fColor;
175 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
176 }
177 }
178
179 const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
180
181 GrDrawTarget::DrawInfo drawInfo;
182 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
183 drawInfo.setStartVertex(0);
184 drawInfo.setStartIndex(0);
185 drawInfo.setVerticesPerInstance(kVertsPerRect);
186 drawInfo.setIndicesPerInstance(kIndicesPerRect);
187 drawInfo.adjustStartVertex(firstVertex);
188 drawInfo.setVertexBuffer(vertexBuffer);
189 drawInfo.setIndexBuffer(quadIndexBuffer);
190
191 int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
192 while (instanceCount) {
193 drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
194 drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
195 drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
196
197 batchTarget->draw(drawInfo);
198
199 drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
200 instanceCount -= drawInfo.instanceCount();
201 }
202 }
203
204 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
205
206private:
207 RectBatch(const Geometry& geometry) {
208 this->initClassID<RectBatch>();
209 fGeoData.push_back(geometry);
210 }
211
212 GrColor color() const { return fBatch.fColor; }
213 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
214 bool colorIgnored() const { return fBatch.fColorIgnored; }
215 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
216 const SkMatrix& localMatrix() const { return fGeoData[0].fLocalMatrix; }
217 bool hasLocalRect() const { return fGeoData[0].fHasLocalRect; }
218 bool hasLocalMatrix() const { return fGeoData[0].fHasLocalMatrix; }
219
220 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
221 RectBatch* that = t->cast<RectBatch>();
222
223 if (this->hasLocalRect() != that->hasLocalRect()) {
224 return false;
225 }
226
227 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
228 if (!this->hasLocalRect() && this->usesLocalCoords()) {
229 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
230 return false;
231 }
232
233 if (this->hasLocalMatrix() != that->hasLocalMatrix()) {
234 return false;
235 }
236
237 if (this->hasLocalMatrix() && !this->localMatrix().cheapEqualTo(that->localMatrix())) {
238 return false;
239 }
240 }
241
242 if (this->color() != that->color()) {
243 fBatch.fColor = GrColor_ILLEGAL;
244 }
245 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
246 return true;
247 }
248
249 struct BatchTracker {
250 GrColor fColor;
251 bool fUsesLocalCoords;
252 bool fColorIgnored;
253 bool fCoverageIgnored;
254 };
255
256 const static int kVertsPerRect = 4;
257 const static int kIndicesPerRect = 6;
258
259 BatchTracker fBatch;
260 SkSTArray<1, Geometry, true> fGeoData;
261};
262
egdaniel8dd688b2015-01-22 10:16:09 -0800263void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -0800264 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800265 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800266 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000267 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000268 const SkMatrix* localMatrix) {
joshualitt58773332015-02-23 16:41:42 -0800269 RectBatch::Geometry geometry;
270 geometry.fColor = color;
271 geometry.fViewMatrix = viewMatrix;
272 geometry.fRect = rect;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000273
bsalomon49f085d2014-09-05 13:34:00 -0700274 if (localRect) {
joshualitt58773332015-02-23 16:41:42 -0800275 geometry.fHasLocalRect = true;
276 geometry.fLocalRect = *localRect;
277 } else {
278 geometry.fHasLocalRect = false;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000279 }
280
joshualitt58773332015-02-23 16:41:42 -0800281 if (localMatrix) {
282 geometry.fHasLocalMatrix = true;
283 geometry.fLocalMatrix = *localMatrix;
284 } else {
285 geometry.fHasLocalMatrix = false;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000286 }
287
joshualitt58773332015-02-23 16:41:42 -0800288 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry));
289
290 SkRect bounds = rect;
291 viewMatrix.mapRect(&bounds);
292 this->drawBatch(pipelineBuilder, batch, &bounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000293}
294
egdaniele36914c2015-02-13 09:00:33 -0800295void GrInOrderDrawBuffer::onDraw(const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800296 const DrawInfo& info,
egdaniele36914c2015-02-13 09:00:33 -0800297 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800298 GrTargetCommands::Cmd* cmd = fCommands.recordDraw(this, gp, info, pipelineInfo);
299 this->recordTraceMarkersIfNecessary(cmd);
300}
301
joshualitt4d8da812015-01-28 12:53:54 -0800302void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
egdaniele36914c2015-02-13 09:00:33 -0800303 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800304 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipelineInfo);
305 this->recordTraceMarkersIfNecessary(cmd);
306}
307
egdaniel8dd688b2015-01-22 10:16:09 -0800308void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800309 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800310 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800311 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800312 const GrStencilSettings& stencilSettings) {
robertphillipsdad77942015-03-03 09:28:16 -0800313 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuilder,
314 pathProc, path, scissorState,
315 stencilSettings);
316 this->recordTraceMarkersIfNecessary(cmd);
317}
318
egdaniele36914c2015-02-13 09:00:33 -0800319void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800320 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800321 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800322 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800323 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc,
324 path, stencilSettings,
325 pipelineInfo);
326 this->recordTraceMarkersIfNecessary(cmd);
327}
328
egdaniele36914c2015-02-13 09:00:33 -0800329void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800330 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800331 const void* indices,
332 PathIndexType indexType,
333 const float transformValues[],
334 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800335 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800336 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800337 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800338 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathRange,
339 indices, indexType, transformValues,
340 transformType, count,
341 stencilSettings, pipelineInfo);
342 this->recordTraceMarkersIfNecessary(cmd);
343}
344
bsalomon63b21962014-11-05 07:05:34 -0800345void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
346 bool canIgnoreRect, GrRenderTarget* renderTarget) {
robertphillipsdad77942015-03-03 09:28:16 -0800347 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color,
348 canIgnoreRect, renderTarget);
349 this->recordTraceMarkersIfNecessary(cmd);
350}
351
joshualitt6db519c2014-10-29 08:48:18 -0700352void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
353 bool insideClip,
354 GrRenderTarget* renderTarget) {
robertphillipsdad77942015-03-03 09:28:16 -0800355 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect,
356 insideClip, renderTarget);
357 this->recordTraceMarkersIfNecessary(cmd);
358}
359
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000360void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
361 if (!this->caps()->discardRenderTargetSupport()) {
362 return;
363 }
robertphillipsdad77942015-03-03 09:28:16 -0800364
365 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget);
366 this->recordTraceMarkersIfNecessary(cmd);
367}
368
bsalomon371bcbc2014-12-01 08:19:34 -0800369void GrInOrderDrawBuffer::onReset() {
robertphillipsdad77942015-03-03 09:28:16 -0800370 fCommands.reset();
robertphillips9888b222015-02-27 08:50:34 -0800371 fPathIndexBuffer.rewind();
372 fPathTransformBuffer.rewind();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000373 fGpuCmdMarkers.reset();
robertphillipsdad77942015-03-03 09:28:16 -0800374}
375
bsalomon371bcbc2014-12-01 08:19:34 -0800376void GrInOrderDrawBuffer::onFlush() {
robertphillipsdad77942015-03-03 09:28:16 -0800377 fCommands.flush(this);
378 ++fDrawID;
379}
380
bsalomonf90a02b2014-11-26 12:28:00 -0800381bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
382 GrSurface* src,
383 const SkIRect& srcRect,
384 const SkIPoint& dstPoint) {
robertphillipsdad77942015-03-03 09:28:16 -0800385 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(this, dst, src,
386 srcRect, dstPoint);
387 this->recordTraceMarkersIfNecessary(cmd);
388 return SkToBool(cmd);
389}
390
robertphillipsdad77942015-03-03 09:28:16 -0800391void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* cmd) {
robertphillips7f966f42015-03-02 06:40:12 -0800392 if (!cmd) {
393 return;
394 }
mtkleinf439c772014-10-14 14:29:30 -0700395 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
396 if (activeTraceMarkers.count() > 0) {
robertphillips7f966f42015-03-02 06:40:12 -0800397 if (cmd->isTraced()) {
398 fGpuCmdMarkers.back().addSet(activeTraceMarkers);
399 } else {
400 cmd->makeTraced();
401 fGpuCmdMarkers.push_back(activeTraceMarkers);
402 }
mtklein07894c42014-10-13 14:00:42 -0700403 }
mtklein07894c42014-10-13 14:00:42 -0700404}
joshualitt4d8da812015-01-28 12:53:54 -0800405
joshualitt4d8da812015-01-28 12:53:54 -0800406void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
407 size_t vertexStride,
408 int indexCount) {
robertphillipsdad77942015-03-03 09:28:16 -0800409 fCommands.closeBatch();
joshualitt4d8da812015-01-28 12:53:54 -0800410
robertphillips54fac8b2015-02-16 09:35:50 -0800411 this->INHERITED::willReserveVertexAndIndexSpace(vertexCount, vertexStride, indexCount);
joshualitt4d8da812015-01-28 12:53:54 -0800412}