blob: e298be6c8bffb575798ae14250512495626e0fe5 [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
bsalomona73239a2015-04-28 13:35:17 -070013GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrContext* context,
bsalomon@google.com471d4712011-08-23 15:45:25 +000014 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000015 GrIndexBufferAllocPool* indexPool)
bsalomona73239a2015-04-28 13:35:17 -070016 : INHERITED(context, vertexPool, indexPool)
17 , fCommands(context->getGpu(), 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) {
joshualitt50cb76b2015-04-28 09:17:05 -070049 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *localMatrix,
50 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080051 } else {
joshualitt50cb76b2015-04-28 09:17:05 -070052 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
mtklein36352bf2015-03-25 18:17:31 -070073 const char* name() const override { return "RectBatch"; }
joshualitt58773332015-02-23 16:41:42 -080074
mtklein36352bf2015-03-25 18:17:31 -070075 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
joshualitt58773332015-02-23 16:41:42 -080076 // When this is called on a batch, there is only one geometry bundle
77 out->setKnownFourComponents(fGeoData[0].fColor);
78 }
79
mtklein36352bf2015-03-25 18:17:31 -070080 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
joshualitt58773332015-02-23 16:41:42 -080081 out->setKnownSingleComponent(0xff);
82 }
83
mtklein36352bf2015-03-25 18:17:31 -070084 void initBatchTracker(const GrPipelineInfo& init) override {
joshualitt58773332015-02-23 16:41:42 -080085 // 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
mtklein36352bf2015-03-25 18:17:31 -070099 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
joshualitt58773332015-02-23 16:41:42 -0800100 // 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
joshualitt4b31de82015-03-05 14:33:41 -0800150 if (!vertices || !batchTarget->quadIndexBuffer()) {
151 SkDebugf("Could not allocate buffers\n");
152 return;
153 }
154
joshualitt58773332015-02-23 16:41:42 -0800155 for (int i = 0; i < instanceCount; i++) {
156 const Geometry& args = fGeoData[i];
157
158 intptr_t offset = GrTCast<intptr_t>(vertices) + kVertsPerRect * i * vertexStride;
159 SkPoint* positions = GrTCast<SkPoint*>(offset);
160
161 positions->setRectFan(args.fRect.fLeft, args.fRect.fTop,
162 args.fRect.fRight, args.fRect.fBottom, vertexStride);
163 args.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVertsPerRect);
164
165 if (args.fHasLocalRect) {
166 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
167 SkPoint* coords = GrTCast<SkPoint*>(offset + kLocalOffset);
168 coords->setRectFan(args.fLocalRect.fLeft, args.fLocalRect.fTop,
169 args.fLocalRect.fRight, args.fLocalRect.fBottom,
170 vertexStride);
171 if (args.fHasLocalMatrix) {
172 args.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVertsPerRect);
173 }
174 }
175
176 static const int kColorOffset = sizeof(SkPoint);
177 GrColor* vertColor = GrTCast<GrColor*>(offset + kColorOffset);
178 for (int j = 0; j < 4; ++j) {
179 *vertColor = args.fColor;
180 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
181 }
182 }
183
184 const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
185
186 GrDrawTarget::DrawInfo drawInfo;
187 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
188 drawInfo.setStartVertex(0);
189 drawInfo.setStartIndex(0);
190 drawInfo.setVerticesPerInstance(kVertsPerRect);
191 drawInfo.setIndicesPerInstance(kIndicesPerRect);
192 drawInfo.adjustStartVertex(firstVertex);
193 drawInfo.setVertexBuffer(vertexBuffer);
194 drawInfo.setIndexBuffer(quadIndexBuffer);
195
196 int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
197 while (instanceCount) {
198 drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
199 drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
200 drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
201
202 batchTarget->draw(drawInfo);
203
204 drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
205 instanceCount -= drawInfo.instanceCount();
206 }
207 }
208
209 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
210
211private:
212 RectBatch(const Geometry& geometry) {
213 this->initClassID<RectBatch>();
214 fGeoData.push_back(geometry);
joshualitt99c7c072015-05-01 13:43:30 -0700215
216 fBounds = geometry.fRect;
217 geometry.fViewMatrix.mapRect(&fBounds);
joshualitt58773332015-02-23 16:41:42 -0800218 }
219
220 GrColor color() const { return fBatch.fColor; }
221 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
222 bool colorIgnored() const { return fBatch.fColorIgnored; }
223 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
224 const SkMatrix& localMatrix() const { return fGeoData[0].fLocalMatrix; }
225 bool hasLocalRect() const { return fGeoData[0].fHasLocalRect; }
226 bool hasLocalMatrix() const { return fGeoData[0].fHasLocalMatrix; }
227
mtklein36352bf2015-03-25 18:17:31 -0700228 bool onCombineIfPossible(GrBatch* t) override {
joshualitt58773332015-02-23 16:41:42 -0800229 RectBatch* that = t->cast<RectBatch>();
230
231 if (this->hasLocalRect() != that->hasLocalRect()) {
232 return false;
233 }
234
235 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
236 if (!this->hasLocalRect() && this->usesLocalCoords()) {
237 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
238 return false;
239 }
240
241 if (this->hasLocalMatrix() != that->hasLocalMatrix()) {
242 return false;
243 }
244
245 if (this->hasLocalMatrix() && !this->localMatrix().cheapEqualTo(that->localMatrix())) {
246 return false;
247 }
248 }
249
250 if (this->color() != that->color()) {
251 fBatch.fColor = GrColor_ILLEGAL;
252 }
253 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
joshualitt99c7c072015-05-01 13:43:30 -0700254 this->joinBounds(that->bounds());
joshualitt58773332015-02-23 16:41:42 -0800255 return true;
256 }
257
258 struct BatchTracker {
259 GrColor fColor;
260 bool fUsesLocalCoords;
261 bool fColorIgnored;
262 bool fCoverageIgnored;
263 };
264
265 const static int kVertsPerRect = 4;
266 const static int kIndicesPerRect = 6;
267
268 BatchTracker fBatch;
269 SkSTArray<1, Geometry, true> fGeoData;
270};
271
egdaniel8dd688b2015-01-22 10:16:09 -0800272void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -0800273 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800274 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800275 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000276 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000277 const SkMatrix* localMatrix) {
joshualitt58773332015-02-23 16:41:42 -0800278 RectBatch::Geometry geometry;
279 geometry.fColor = color;
280 geometry.fViewMatrix = viewMatrix;
281 geometry.fRect = rect;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000282
bsalomon49f085d2014-09-05 13:34:00 -0700283 if (localRect) {
joshualitt58773332015-02-23 16:41:42 -0800284 geometry.fHasLocalRect = true;
285 geometry.fLocalRect = *localRect;
286 } else {
287 geometry.fHasLocalRect = false;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000288 }
289
joshualitt58773332015-02-23 16:41:42 -0800290 if (localMatrix) {
291 geometry.fHasLocalMatrix = true;
292 geometry.fLocalMatrix = *localMatrix;
293 } else {
294 geometry.fHasLocalMatrix = false;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000295 }
296
joshualitt58773332015-02-23 16:41:42 -0800297 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry));
joshualitt99c7c072015-05-01 13:43:30 -0700298 this->drawBatch(pipelineBuilder, batch);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000299}
300
joshualitt4d8da812015-01-28 12:53:54 -0800301void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
egdaniele36914c2015-02-13 09:00:33 -0800302 const PipelineInfo& pipelineInfo) {
joshualittedae3092015-05-04 07:51:09 -0700303 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipelineInfo);
robertphillipsdad77942015-03-03 09:28:16 -0800304 this->recordTraceMarkersIfNecessary(cmd);
305}
306
egdaniel8dd688b2015-01-22 10:16:09 -0800307void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800308 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800309 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800310 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800311 const GrStencilSettings& stencilSettings) {
joshualittedae3092015-05-04 07:51:09 -0700312 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuilder,
robertphillipsdad77942015-03-03 09:28:16 -0800313 pathProc, path, scissorState,
314 stencilSettings);
315 this->recordTraceMarkersIfNecessary(cmd);
316}
317
egdaniele36914c2015-02-13 09:00:33 -0800318void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800319 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800320 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800321 const PipelineInfo& pipelineInfo) {
joshualittedae3092015-05-04 07:51:09 -0700322 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc,
323 path, stencilSettings,
324 pipelineInfo);
robertphillipsdad77942015-03-03 09:28:16 -0800325 this->recordTraceMarkersIfNecessary(cmd);
326}
327
egdaniele36914c2015-02-13 09:00:33 -0800328void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800329 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800330 const void* indices,
331 PathIndexType indexType,
332 const float transformValues[],
333 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800334 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800335 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800336 const PipelineInfo& pipelineInfo) {
joshualittedae3092015-05-04 07:51:09 -0700337 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathRange,
robertphillipsdad77942015-03-03 09:28:16 -0800338 indices, indexType, transformValues,
339 transformType, count,
340 stencilSettings, pipelineInfo);
341 this->recordTraceMarkersIfNecessary(cmd);
342}
343
bsalomon63b21962014-11-05 07:05:34 -0800344void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
345 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualittedae3092015-05-04 07:51:09 -0700346 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color,
347 canIgnoreRect, renderTarget);
robertphillipsdad77942015-03-03 09:28:16 -0800348 this->recordTraceMarkersIfNecessary(cmd);
349}
350
joshualitt6db519c2014-10-29 08:48:18 -0700351void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
352 bool insideClip,
353 GrRenderTarget* renderTarget) {
joshualittedae3092015-05-04 07:51:09 -0700354 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect,
355 insideClip, renderTarget);
robertphillipsdad77942015-03-03 09:28:16 -0800356 this->recordTraceMarkersIfNecessary(cmd);
357}
358
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000359void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
360 if (!this->caps()->discardRenderTargetSupport()) {
361 return;
362 }
robertphillipsdad77942015-03-03 09:28:16 -0800363
joshualittedae3092015-05-04 07:51:09 -0700364 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget);
robertphillipsdad77942015-03-03 09:28:16 -0800365 this->recordTraceMarkersIfNecessary(cmd);
366}
367
bsalomon371bcbc2014-12-01 08:19:34 -0800368void GrInOrderDrawBuffer::onReset() {
robertphillipsdad77942015-03-03 09:28:16 -0800369 fCommands.reset();
robertphillips9888b222015-02-27 08:50:34 -0800370 fPathIndexBuffer.rewind();
371 fPathTransformBuffer.rewind();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000372 fGpuCmdMarkers.reset();
robertphillipsdad77942015-03-03 09:28:16 -0800373}
374
bsalomon371bcbc2014-12-01 08:19:34 -0800375void GrInOrderDrawBuffer::onFlush() {
robertphillipsdad77942015-03-03 09:28:16 -0800376 fCommands.flush(this);
377 ++fDrawID;
378}
379
bsalomona73239a2015-04-28 13:35:17 -0700380void GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
bsalomonf90a02b2014-11-26 12:28:00 -0800381 GrSurface* src,
382 const SkIRect& srcRect,
383 const SkIPoint& dstPoint) {
bsalomona73239a2015-04-28 13:35:17 -0700384 SkASSERT(this->getGpu()->canCopySurface(dst, src, srcRect, dstPoint));
385 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(dst, src, srcRect, dstPoint);
robertphillipsdad77942015-03-03 09:28:16 -0800386 this->recordTraceMarkersIfNecessary(cmd);
robertphillipsdad77942015-03-03 09:28:16 -0800387}
388
robertphillipsdad77942015-03-03 09:28:16 -0800389void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* cmd) {
robertphillips7f966f42015-03-02 06:40:12 -0800390 if (!cmd) {
391 return;
392 }
mtkleinf439c772014-10-14 14:29:30 -0700393 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
394 if (activeTraceMarkers.count() > 0) {
robertphillips7f966f42015-03-02 06:40:12 -0800395 if (cmd->isTraced()) {
robertphillipsbca3c9f2015-03-05 09:17:17 -0800396 fGpuCmdMarkers[cmd->markerID()].addSet(activeTraceMarkers);
robertphillips7f966f42015-03-02 06:40:12 -0800397 } else {
robertphillipsbca3c9f2015-03-05 09:17:17 -0800398 cmd->setMarkerID(fGpuCmdMarkers.count());
robertphillips7f966f42015-03-02 06:40:12 -0800399 fGpuCmdMarkers.push_back(activeTraceMarkers);
400 }
mtklein07894c42014-10-13 14:00:42 -0700401 }
mtklein07894c42014-10-13 14:00:42 -0700402}