blob: 4d8fa5e1d9d13a0be47056a10ad875b237f4c285 [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
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
225 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
226 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
egdaniele36914c2015-02-13 09:00:33 -0800300void GrInOrderDrawBuffer::onDraw(const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800301 const DrawInfo& info,
egdaniele36914c2015-02-13 09:00:33 -0800302 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800303 GrTargetCommands::Cmd* cmd = fCommands.recordDraw(this, gp, info, pipelineInfo);
304 this->recordTraceMarkersIfNecessary(cmd);
305}
306
joshualitt4d8da812015-01-28 12:53:54 -0800307void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
egdaniele36914c2015-02-13 09:00:33 -0800308 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800309 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipelineInfo);
310 this->recordTraceMarkersIfNecessary(cmd);
311}
312
egdaniel8dd688b2015-01-22 10:16:09 -0800313void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800314 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800315 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800316 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800317 const GrStencilSettings& stencilSettings) {
robertphillipsdad77942015-03-03 09:28:16 -0800318 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuilder,
319 pathProc, path, scissorState,
320 stencilSettings);
321 this->recordTraceMarkersIfNecessary(cmd);
322}
323
egdaniele36914c2015-02-13 09:00:33 -0800324void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800325 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800326 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800327 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800328 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc,
329 path, stencilSettings,
330 pipelineInfo);
331 this->recordTraceMarkersIfNecessary(cmd);
332}
333
egdaniele36914c2015-02-13 09:00:33 -0800334void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800335 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800336 const void* indices,
337 PathIndexType indexType,
338 const float transformValues[],
339 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800340 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800341 const GrStencilSettings& stencilSettings,
egdaniele36914c2015-02-13 09:00:33 -0800342 const PipelineInfo& pipelineInfo) {
robertphillipsdad77942015-03-03 09:28:16 -0800343 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathRange,
344 indices, indexType, transformValues,
345 transformType, count,
346 stencilSettings, pipelineInfo);
347 this->recordTraceMarkersIfNecessary(cmd);
348}
349
bsalomon63b21962014-11-05 07:05:34 -0800350void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
351 bool canIgnoreRect, GrRenderTarget* renderTarget) {
robertphillipsdad77942015-03-03 09:28:16 -0800352 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color,
353 canIgnoreRect, renderTarget);
354 this->recordTraceMarkersIfNecessary(cmd);
355}
356
joshualitt6db519c2014-10-29 08:48:18 -0700357void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
358 bool insideClip,
359 GrRenderTarget* renderTarget) {
robertphillipsdad77942015-03-03 09:28:16 -0800360 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect,
361 insideClip, renderTarget);
362 this->recordTraceMarkersIfNecessary(cmd);
363}
364
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000365void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
366 if (!this->caps()->discardRenderTargetSupport()) {
367 return;
368 }
robertphillipsdad77942015-03-03 09:28:16 -0800369
370 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget);
371 this->recordTraceMarkersIfNecessary(cmd);
372}
373
bsalomon371bcbc2014-12-01 08:19:34 -0800374void GrInOrderDrawBuffer::onReset() {
robertphillipsdad77942015-03-03 09:28:16 -0800375 fCommands.reset();
robertphillips9888b222015-02-27 08:50:34 -0800376 fPathIndexBuffer.rewind();
377 fPathTransformBuffer.rewind();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000378 fGpuCmdMarkers.reset();
robertphillipsdad77942015-03-03 09:28:16 -0800379}
380
bsalomon371bcbc2014-12-01 08:19:34 -0800381void GrInOrderDrawBuffer::onFlush() {
robertphillipsdad77942015-03-03 09:28:16 -0800382 fCommands.flush(this);
383 ++fDrawID;
384}
385
bsalomonf90a02b2014-11-26 12:28:00 -0800386bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
387 GrSurface* src,
388 const SkIRect& srcRect,
389 const SkIPoint& dstPoint) {
robertphillipsdad77942015-03-03 09:28:16 -0800390 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(this, dst, src,
391 srcRect, dstPoint);
392 this->recordTraceMarkersIfNecessary(cmd);
393 return SkToBool(cmd);
394}
395
robertphillipsdad77942015-03-03 09:28:16 -0800396void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* cmd) {
robertphillips7f966f42015-03-02 06:40:12 -0800397 if (!cmd) {
398 return;
399 }
mtkleinf439c772014-10-14 14:29:30 -0700400 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
401 if (activeTraceMarkers.count() > 0) {
robertphillips7f966f42015-03-02 06:40:12 -0800402 if (cmd->isTraced()) {
robertphillipsbca3c9f2015-03-05 09:17:17 -0800403 fGpuCmdMarkers[cmd->markerID()].addSet(activeTraceMarkers);
robertphillips7f966f42015-03-02 06:40:12 -0800404 } else {
robertphillipsbca3c9f2015-03-05 09:17:17 -0800405 cmd->setMarkerID(fGpuCmdMarkers.count());
robertphillips7f966f42015-03-02 06:40:12 -0800406 fGpuCmdMarkers.push_back(activeTraceMarkers);
407 }
mtklein07894c42014-10-13 14:00:42 -0700408 }
mtklein07894c42014-10-13 14:00:42 -0700409}
joshualitt4d8da812015-01-28 12:53:54 -0800410
joshualitt4d8da812015-01-28 12:53:54 -0800411void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
412 size_t vertexStride,
413 int indexCount) {
robertphillipsdad77942015-03-03 09:28:16 -0800414 fCommands.closeBatch();
joshualitt4d8da812015-01-28 12:53:54 -0800415
robertphillips54fac8b2015-02-16 09:35:50 -0800416 this->INHERITED::willReserveVertexAndIndexSpace(vertexCount, vertexStride, indexCount);
joshualitt4d8da812015-01-28 12:53:54 -0800417}