blob: cb1e741ec44ec704c194403ca782dc13583ccaf9 [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);
215 }
216
217 GrColor color() const { return fBatch.fColor; }
218 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
219 bool colorIgnored() const { return fBatch.fColorIgnored; }
220 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
221 const SkMatrix& localMatrix() const { return fGeoData[0].fLocalMatrix; }
222 bool hasLocalRect() const { return fGeoData[0].fHasLocalRect; }
223 bool hasLocalMatrix() const { return fGeoData[0].fHasLocalMatrix; }
224
mtklein36352bf2015-03-25 18:17:31 -0700225 bool onCombineIfPossible(GrBatch* t) override {
joshualitt58773332015-02-23 16:41:42 -0800226 RectBatch* that = t->cast<RectBatch>();
227
228 if (this->hasLocalRect() != that->hasLocalRect()) {
229 return false;
230 }
231
232 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
233 if (!this->hasLocalRect() && this->usesLocalCoords()) {
234 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
235 return false;
236 }
237
238 if (this->hasLocalMatrix() != that->hasLocalMatrix()) {
239 return false;
240 }
241
242 if (this->hasLocalMatrix() && !this->localMatrix().cheapEqualTo(that->localMatrix())) {
243 return false;
244 }
245 }
246
247 if (this->color() != that->color()) {
248 fBatch.fColor = GrColor_ILLEGAL;
249 }
250 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
251 return true;
252 }
253
254 struct BatchTracker {
255 GrColor fColor;
256 bool fUsesLocalCoords;
257 bool fColorIgnored;
258 bool fCoverageIgnored;
259 };
260
261 const static int kVertsPerRect = 4;
262 const static int kIndicesPerRect = 6;
263
264 BatchTracker fBatch;
265 SkSTArray<1, Geometry, true> fGeoData;
266};
267
egdaniel8dd688b2015-01-22 10:16:09 -0800268void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -0800269 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800270 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800271 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000272 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000273 const SkMatrix* localMatrix) {
joshualitt58773332015-02-23 16:41:42 -0800274 RectBatch::Geometry geometry;
275 geometry.fColor = color;
276 geometry.fViewMatrix = viewMatrix;
277 geometry.fRect = rect;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000278
bsalomon49f085d2014-09-05 13:34:00 -0700279 if (localRect) {
joshualitt58773332015-02-23 16:41:42 -0800280 geometry.fHasLocalRect = true;
281 geometry.fLocalRect = *localRect;
282 } else {
283 geometry.fHasLocalRect = false;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000284 }
285
joshualitt58773332015-02-23 16:41:42 -0800286 if (localMatrix) {
287 geometry.fHasLocalMatrix = true;
288 geometry.fLocalMatrix = *localMatrix;
289 } else {
290 geometry.fHasLocalMatrix = false;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000291 }
292
joshualitt58773332015-02-23 16:41:42 -0800293 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry));
294
295 SkRect bounds = rect;
296 viewMatrix.mapRect(&bounds);
297 this->drawBatch(pipelineBuilder, batch, &bounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000298}
299
joshualitt4d8da812015-01-28 12:53:54 -0800300void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
egdaniele36914c2015-02-13 09:00:33 -0800301 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800302 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipelineInfo);
303 this->recordTraceMarkersIfNecessary(cmd);
304}
305
egdaniel8dd688b2015-01-22 10:16:09 -0800306void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800307 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800308 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800309 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800310 const GrStencilSettings& stencilSettings) {
robertphillipsdad77942015-03-03 09:28:16 -0800311 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuilder,
312 pathProc, path, scissorState,
313 stencilSettings);
314 this->recordTraceMarkersIfNecessary(cmd);
315}
316
egdaniele36914c2015-02-13 09:00:33 -0800317void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800318 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800319 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800320 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800321 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc,
322 path, stencilSettings,
323 pipelineInfo);
324 this->recordTraceMarkersIfNecessary(cmd);
325}
326
egdaniele36914c2015-02-13 09:00:33 -0800327void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800328 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800329 const void* indices,
330 PathIndexType indexType,
331 const float transformValues[],
332 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800333 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800334 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800335 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800336 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathRange,
337 indices, indexType, transformValues,
338 transformType, count,
339 stencilSettings, pipelineInfo);
340 this->recordTraceMarkersIfNecessary(cmd);
341}
342
bsalomon63b21962014-11-05 07:05:34 -0800343void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
344 bool canIgnoreRect, GrRenderTarget* renderTarget) {
robertphillipsdad77942015-03-03 09:28:16 -0800345 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color,
346 canIgnoreRect, renderTarget);
347 this->recordTraceMarkersIfNecessary(cmd);
348}
349
joshualitt6db519c2014-10-29 08:48:18 -0700350void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
351 bool insideClip,
352 GrRenderTarget* renderTarget) {
robertphillipsdad77942015-03-03 09:28:16 -0800353 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect,
354 insideClip, renderTarget);
355 this->recordTraceMarkersIfNecessary(cmd);
356}
357
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000358void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
359 if (!this->caps()->discardRenderTargetSupport()) {
360 return;
361 }
robertphillipsdad77942015-03-03 09:28:16 -0800362
363 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget);
364 this->recordTraceMarkersIfNecessary(cmd);
365}
366
bsalomon371bcbc2014-12-01 08:19:34 -0800367void GrInOrderDrawBuffer::onReset() {
robertphillipsdad77942015-03-03 09:28:16 -0800368 fCommands.reset();
robertphillips9888b222015-02-27 08:50:34 -0800369 fPathIndexBuffer.rewind();
370 fPathTransformBuffer.rewind();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000371 fGpuCmdMarkers.reset();
robertphillipsdad77942015-03-03 09:28:16 -0800372}
373
bsalomon371bcbc2014-12-01 08:19:34 -0800374void GrInOrderDrawBuffer::onFlush() {
robertphillipsdad77942015-03-03 09:28:16 -0800375 fCommands.flush(this);
376 ++fDrawID;
377}
378
bsalomona73239a2015-04-28 13:35:17 -0700379void GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
bsalomonf90a02b2014-11-26 12:28:00 -0800380 GrSurface* src,
381 const SkIRect& srcRect,
382 const SkIPoint& dstPoint) {
bsalomona73239a2015-04-28 13:35:17 -0700383 SkASSERT(this->getGpu()->canCopySurface(dst, src, srcRect, dstPoint));
384 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(dst, src, srcRect, dstPoint);
robertphillipsdad77942015-03-03 09:28:16 -0800385 this->recordTraceMarkersIfNecessary(cmd);
robertphillipsdad77942015-03-03 09:28:16 -0800386}
387
robertphillipsdad77942015-03-03 09:28:16 -0800388void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* cmd) {
robertphillips7f966f42015-03-02 06:40:12 -0800389 if (!cmd) {
390 return;
391 }
mtkleinf439c772014-10-14 14:29:30 -0700392 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
393 if (activeTraceMarkers.count() > 0) {
robertphillips7f966f42015-03-02 06:40:12 -0800394 if (cmd->isTraced()) {
robertphillipsbca3c9f2015-03-05 09:17:17 -0800395 fGpuCmdMarkers[cmd->markerID()].addSet(activeTraceMarkers);
robertphillips7f966f42015-03-02 06:40:12 -0800396 } else {
robertphillipsbca3c9f2015-03-05 09:17:17 -0800397 cmd->setMarkerID(fGpuCmdMarkers.count());
robertphillips7f966f42015-03-02 06:40:12 -0800398 fGpuCmdMarkers.push_back(activeTraceMarkers);
399 }
mtklein07894c42014-10-13 14:00:42 -0700400 }
mtklein07894c42014-10-13 14:00:42 -0700401}