blob: 0af137d6962d2153c433d912d7e3dbc510dffc11 [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) {
joshualittef292a02015-04-28 09:08:28 -070049 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *localMatrix);
joshualitt8fc6c2d2014-12-22 15:27:05 -080050 } else {
joshualittef292a02015-04-28 09:08:28 -070051 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMatrix::I());
joshualitt8fc6c2d2014-12-22 15:27:05 -080052 }
bsalomon62c447d2014-08-08 08:08:50 -070053}
robertphillips@google.com42903302013-04-20 12:26:07 +000054
joshualitt58773332015-02-23 16:41:42 -080055class RectBatch : public GrBatch {
56public:
57 struct Geometry {
58 GrColor fColor;
59 SkMatrix fViewMatrix;
60 SkRect fRect;
61 bool fHasLocalRect;
62 bool fHasLocalMatrix;
63 SkRect fLocalRect;
64 SkMatrix fLocalMatrix;
65 };
66
67 static GrBatch* Create(const Geometry& geometry) {
68 return SkNEW_ARGS(RectBatch, (geometry));
69 }
70
mtklein36352bf2015-03-25 18:17:31 -070071 const char* name() const override { return "RectBatch"; }
joshualitt58773332015-02-23 16:41:42 -080072
mtklein36352bf2015-03-25 18:17:31 -070073 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
joshualitt58773332015-02-23 16:41:42 -080074 // When this is called on a batch, there is only one geometry bundle
75 out->setKnownFourComponents(fGeoData[0].fColor);
76 }
77
mtklein36352bf2015-03-25 18:17:31 -070078 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
joshualitt58773332015-02-23 16:41:42 -080079 out->setKnownSingleComponent(0xff);
80 }
81
mtklein36352bf2015-03-25 18:17:31 -070082 void initBatchTracker(const GrPipelineInfo& init) override {
joshualitt58773332015-02-23 16:41:42 -080083 // Handle any color overrides
84 if (init.fColorIgnored) {
85 fGeoData[0].fColor = GrColor_ILLEGAL;
86 } else if (GrColor_ILLEGAL != init.fOverrideColor) {
87 fGeoData[0].fColor = init.fOverrideColor;
88 }
89
90 // setup batch properties
91 fBatch.fColorIgnored = init.fColorIgnored;
92 fBatch.fColor = fGeoData[0].fColor;
93 fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
94 fBatch.fCoverageIgnored = init.fCoverageIgnored;
95 }
96
mtklein36352bf2015-03-25 18:17:31 -070097 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
joshualitt58773332015-02-23 16:41:42 -080098 // Go to device coords to allow batching across matrix changes
99 SkMatrix invert = SkMatrix::I();
100
101 // if we have a local rect, then we apply the localMatrix directly to the localRect to
102 // generate vertex local coords
103 bool hasExplicitLocalCoords = this->hasLocalRect();
104 if (!hasExplicitLocalCoords) {
105 if (!this->viewMatrix().isIdentity() && !this->viewMatrix().invert(&invert)) {
106 SkDebugf("Could not invert\n");
107 return;
108 }
109
110 if (this->hasLocalMatrix()) {
111 invert.preConcat(this->localMatrix());
112 }
113 }
114
115 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCoords,
116 this->color(),
117 &invert));
118
119 batchTarget->initDraw(gp, pipeline);
120
121 // TODO this is hacky, but the only way we have to initialize the GP is to use the
122 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch
123 // everywhere we can remove this nastiness
124 GrPipelineInfo init;
125 init.fColorIgnored = fBatch.fColorIgnored;
126 init.fOverrideColor = GrColor_ILLEGAL;
127 init.fCoverageIgnored = fBatch.fCoverageIgnored;
128 init.fUsesLocalCoords = this->usesLocalCoords();
129 gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
130
131 size_t vertexStride = gp->getVertexStride();
132
133 SkASSERT(hasExplicitLocalCoords ?
134 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
135 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
136
137 int instanceCount = fGeoData.count();
138 int vertexCount = kVertsPerRect * instanceCount;
139
140 const GrVertexBuffer* vertexBuffer;
141 int firstVertex;
142
143 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
144 vertexCount,
145 &vertexBuffer,
146 &firstVertex);
147
joshualitt4b31de82015-03-05 14:33:41 -0800148 if (!vertices || !batchTarget->quadIndexBuffer()) {
149 SkDebugf("Could not allocate buffers\n");
150 return;
151 }
152
joshualitt58773332015-02-23 16:41:42 -0800153 for (int i = 0; i < instanceCount; i++) {
154 const Geometry& args = fGeoData[i];
155
156 intptr_t offset = GrTCast<intptr_t>(vertices) + kVertsPerRect * i * vertexStride;
157 SkPoint* positions = GrTCast<SkPoint*>(offset);
158
159 positions->setRectFan(args.fRect.fLeft, args.fRect.fTop,
160 args.fRect.fRight, args.fRect.fBottom, vertexStride);
161 args.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVertsPerRect);
162
163 if (args.fHasLocalRect) {
164 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
165 SkPoint* coords = GrTCast<SkPoint*>(offset + kLocalOffset);
166 coords->setRectFan(args.fLocalRect.fLeft, args.fLocalRect.fTop,
167 args.fLocalRect.fRight, args.fLocalRect.fBottom,
168 vertexStride);
169 if (args.fHasLocalMatrix) {
170 args.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVertsPerRect);
171 }
172 }
173
174 static const int kColorOffset = sizeof(SkPoint);
175 GrColor* vertColor = GrTCast<GrColor*>(offset + kColorOffset);
176 for (int j = 0; j < 4; ++j) {
177 *vertColor = args.fColor;
178 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
179 }
180 }
181
182 const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
183
184 GrDrawTarget::DrawInfo drawInfo;
185 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
186 drawInfo.setStartVertex(0);
187 drawInfo.setStartIndex(0);
188 drawInfo.setVerticesPerInstance(kVertsPerRect);
189 drawInfo.setIndicesPerInstance(kIndicesPerRect);
190 drawInfo.adjustStartVertex(firstVertex);
191 drawInfo.setVertexBuffer(vertexBuffer);
192 drawInfo.setIndexBuffer(quadIndexBuffer);
193
194 int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
195 while (instanceCount) {
196 drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
197 drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
198 drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
199
200 batchTarget->draw(drawInfo);
201
202 drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
203 instanceCount -= drawInfo.instanceCount();
204 }
205 }
206
207 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
208
209private:
210 RectBatch(const Geometry& geometry) {
211 this->initClassID<RectBatch>();
212 fGeoData.push_back(geometry);
213 }
214
215 GrColor color() const { return fBatch.fColor; }
216 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
217 bool colorIgnored() const { return fBatch.fColorIgnored; }
218 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
219 const SkMatrix& localMatrix() const { return fGeoData[0].fLocalMatrix; }
220 bool hasLocalRect() const { return fGeoData[0].fHasLocalRect; }
221 bool hasLocalMatrix() const { return fGeoData[0].fHasLocalMatrix; }
222
mtklein36352bf2015-03-25 18:17:31 -0700223 bool onCombineIfPossible(GrBatch* t) override {
joshualitt58773332015-02-23 16:41:42 -0800224 RectBatch* that = t->cast<RectBatch>();
225
226 if (this->hasLocalRect() != that->hasLocalRect()) {
227 return false;
228 }
229
230 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
231 if (!this->hasLocalRect() && this->usesLocalCoords()) {
232 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
233 return false;
234 }
235
236 if (this->hasLocalMatrix() != that->hasLocalMatrix()) {
237 return false;
238 }
239
240 if (this->hasLocalMatrix() && !this->localMatrix().cheapEqualTo(that->localMatrix())) {
241 return false;
242 }
243 }
244
245 if (this->color() != that->color()) {
246 fBatch.fColor = GrColor_ILLEGAL;
247 }
248 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
249 return true;
250 }
251
252 struct BatchTracker {
253 GrColor fColor;
254 bool fUsesLocalCoords;
255 bool fColorIgnored;
256 bool fCoverageIgnored;
257 };
258
259 const static int kVertsPerRect = 4;
260 const static int kIndicesPerRect = 6;
261
262 BatchTracker fBatch;
263 SkSTArray<1, Geometry, true> fGeoData;
264};
265
egdaniel8dd688b2015-01-22 10:16:09 -0800266void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -0800267 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800268 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800269 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000270 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000271 const SkMatrix* localMatrix) {
joshualitt58773332015-02-23 16:41:42 -0800272 RectBatch::Geometry geometry;
273 geometry.fColor = color;
274 geometry.fViewMatrix = viewMatrix;
275 geometry.fRect = rect;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000276
bsalomon49f085d2014-09-05 13:34:00 -0700277 if (localRect) {
joshualitt58773332015-02-23 16:41:42 -0800278 geometry.fHasLocalRect = true;
279 geometry.fLocalRect = *localRect;
280 } else {
281 geometry.fHasLocalRect = false;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000282 }
283
joshualitt58773332015-02-23 16:41:42 -0800284 if (localMatrix) {
285 geometry.fHasLocalMatrix = true;
286 geometry.fLocalMatrix = *localMatrix;
287 } else {
288 geometry.fHasLocalMatrix = false;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000289 }
290
joshualitt58773332015-02-23 16:41:42 -0800291 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry));
292
293 SkRect bounds = rect;
294 viewMatrix.mapRect(&bounds);
295 this->drawBatch(pipelineBuilder, batch, &bounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000296}
297
joshualitt4d8da812015-01-28 12:53:54 -0800298void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
egdaniele36914c2015-02-13 09:00:33 -0800299 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800300 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipelineInfo);
301 this->recordTraceMarkersIfNecessary(cmd);
302}
303
egdaniel8dd688b2015-01-22 10:16:09 -0800304void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800305 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800306 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800307 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800308 const GrStencilSettings& stencilSettings) {
robertphillipsdad77942015-03-03 09:28:16 -0800309 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuilder,
310 pathProc, path, scissorState,
311 stencilSettings);
312 this->recordTraceMarkersIfNecessary(cmd);
313}
314
egdaniele36914c2015-02-13 09:00:33 -0800315void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800316 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800317 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800318 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800319 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc,
320 path, stencilSettings,
321 pipelineInfo);
322 this->recordTraceMarkersIfNecessary(cmd);
323}
324
egdaniele36914c2015-02-13 09:00:33 -0800325void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800326 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800327 const void* indices,
328 PathIndexType indexType,
329 const float transformValues[],
330 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800331 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800332 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800333 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800334 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathRange,
335 indices, indexType, transformValues,
336 transformType, count,
337 stencilSettings, pipelineInfo);
338 this->recordTraceMarkersIfNecessary(cmd);
339}
340
bsalomon63b21962014-11-05 07:05:34 -0800341void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
342 bool canIgnoreRect, GrRenderTarget* renderTarget) {
robertphillipsdad77942015-03-03 09:28:16 -0800343 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color,
344 canIgnoreRect, renderTarget);
345 this->recordTraceMarkersIfNecessary(cmd);
346}
347
joshualitt6db519c2014-10-29 08:48:18 -0700348void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
349 bool insideClip,
350 GrRenderTarget* renderTarget) {
robertphillipsdad77942015-03-03 09:28:16 -0800351 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect,
352 insideClip, renderTarget);
353 this->recordTraceMarkersIfNecessary(cmd);
354}
355
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000356void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
357 if (!this->caps()->discardRenderTargetSupport()) {
358 return;
359 }
robertphillipsdad77942015-03-03 09:28:16 -0800360
361 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget);
362 this->recordTraceMarkersIfNecessary(cmd);
363}
364
bsalomon371bcbc2014-12-01 08:19:34 -0800365void GrInOrderDrawBuffer::onReset() {
robertphillipsdad77942015-03-03 09:28:16 -0800366 fCommands.reset();
robertphillips9888b222015-02-27 08:50:34 -0800367 fPathIndexBuffer.rewind();
368 fPathTransformBuffer.rewind();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000369 fGpuCmdMarkers.reset();
robertphillipsdad77942015-03-03 09:28:16 -0800370}
371
bsalomon371bcbc2014-12-01 08:19:34 -0800372void GrInOrderDrawBuffer::onFlush() {
robertphillipsdad77942015-03-03 09:28:16 -0800373 fCommands.flush(this);
374 ++fDrawID;
375}
376
bsalomonf90a02b2014-11-26 12:28:00 -0800377bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
378 GrSurface* src,
379 const SkIRect& srcRect,
380 const SkIPoint& dstPoint) {
robertphillipsdad77942015-03-03 09:28:16 -0800381 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(this, dst, src,
382 srcRect, dstPoint);
383 this->recordTraceMarkersIfNecessary(cmd);
384 return SkToBool(cmd);
385}
386
robertphillipsdad77942015-03-03 09:28:16 -0800387void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* cmd) {
robertphillips7f966f42015-03-02 06:40:12 -0800388 if (!cmd) {
389 return;
390 }
mtkleinf439c772014-10-14 14:29:30 -0700391 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
392 if (activeTraceMarkers.count() > 0) {
robertphillips7f966f42015-03-02 06:40:12 -0800393 if (cmd->isTraced()) {
robertphillipsbca3c9f2015-03-05 09:17:17 -0800394 fGpuCmdMarkers[cmd->markerID()].addSet(activeTraceMarkers);
robertphillips7f966f42015-03-02 06:40:12 -0800395 } else {
robertphillipsbca3c9f2015-03-05 09:17:17 -0800396 cmd->setMarkerID(fGpuCmdMarkers.count());
robertphillips7f966f42015-03-02 06:40:12 -0800397 fGpuCmdMarkers.push_back(activeTraceMarkers);
398 }
mtklein07894c42014-10-13 14:00:42 -0700399 }
mtklein07894c42014-10-13 14:00:42 -0700400}