blob: e59df80e96c1cf7768803f40393a18e44cfdd289 [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
joshualitt4d8da812015-01-28 12:53:54 -080010#include "GrBufferAllocPool.h"
joshualitt5478d422014-11-14 16:00:38 -080011#include "GrDefaultGeoProcFactory.h"
bsalomon@google.comc26d94f2013-03-25 18:19:00 +000012#include "GrDrawTargetCaps.h"
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000013#include "GrGpu.h"
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000014#include "GrTemplates.h"
jvanverth787cdf92014-12-04 10:46:50 -080015#include "GrFontCache.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016#include "GrTexture.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000018GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
bsalomon@google.com471d4712011-08-23 15:45:25 +000019 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000020 GrIndexBufferAllocPool* indexPool)
bsalomon371bcbc2014-12-01 08:19:34 -080021 : INHERITED(gpu, vertexPool, indexPool)
cdalton6819df32014-10-15 13:43:48 -070022 , fCmdBuffer(kCmdBufferInitialSizeInBytes)
bsalomon932f8662014-11-24 06:47:48 -080023 , fPrevState(NULL)
joshualitt4d8da812015-01-28 12:53:54 -080024 , fDrawID(0)
25 , fBatchTarget(gpu, vertexPool, indexPool)
26 , fDrawBatch(NULL) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000027
bsalomon49f085d2014-09-05 13:34:00 -070028 SkASSERT(vertexPool);
29 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000030
cdalton3fc6a2f2014-11-13 11:54:20 -080031 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
32 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
reed@google.comac10a2d2010-12-22 21:39:39 +000033}
34
35GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000036 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000037}
38
bsalomon@google.com934c5702012-03-20 21:17:58 +000039////////////////////////////////////////////////////////////////////////////////
40
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000041namespace {
42void get_vertex_bounds(const void* vertices,
43 size_t vertexSize,
44 int vertexCount,
45 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000046 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000047 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000048 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000049 bounds->fLeft = bounds->fRight = point->fX;
50 bounds->fTop = bounds->fBottom = point->fY;
51 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000052 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000053 bounds->growToInclude(point->fX, point->fY);
54 }
55}
bsalomon@google.com934c5702012-03-20 21:17:58 +000056}
57
bsalomon62c447d2014-08-08 08:08:50 -070058/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
59 have explicit local coords and sometimes not. We *could* always provide explicit local coords
60 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
61 haven't seen a use case which frequently switches between local rect and no local rect draws.
62
63 The color param is used to determine whether the opaque hint can be set on the draw state.
64 The caller must populate the vertex colors itself.
65
66 The vertex attrib order is always pos, color, [local coords].
67 */
joshualitt8fc6c2d2014-12-22 15:27:05 -080068static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords,
69 GrColor color,
70 const SkMatrix* localMatrix) {
joshualitt5478d422014-11-14 16:00:38 -080071 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
72 GrDefaultGeoProcFactory::kColor_GPType;
joshualitt8fc6c2d2014-12-22 15:27:05 -080073 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
74 if (localMatrix) {
joshualitt8059eb92014-12-29 15:10:07 -080075 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *localMatrix,
76 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080077 } else {
joshualitt8059eb92014-12-29 15:10:07 -080078 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMatrix::I(),
79 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080080 }
bsalomon62c447d2014-08-08 08:08:50 -070081}
robertphillips@google.com42903302013-04-20 12:26:07 +000082
cdalton3fc6a2f2014-11-13 11:54:20 -080083static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
84 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
85 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
86 if (isWinding) {
87 // Double check that it is in fact winding.
88 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
89 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
90 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
91 SkASSERT(!pathStencilSettings.isTwoSided());
92 }
93 return isWinding;
94}
95
96template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
97 // Assume the next time this buffer fills up it will use approximately the same amount
98 // of space as last time. Only resize if we're using less than a third of the
99 // allocated space, and leave enough for 50% growth over last time.
100 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
101 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
102 buffer->reset();
103 buffer->setReserve(reserve);
104 } else {
105 buffer->rewind();
106 }
107}
108
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000109enum {
110 kTraceCmdBit = 0x80,
111 kCmdMask = 0x7f,
112};
113
bsalomon62c447d2014-08-08 08:08:50 -0700114static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000115
bsalomon62c447d2014-08-08 08:08:50 -0700116static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000117
bsalomon62c447d2014-08-08 08:08:50 -0700118static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000119
egdaniel8dd688b2015-01-22 10:16:09 -0800120void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -0800121 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800122 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800123 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000124 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000125 const SkMatrix* localMatrix) {
egdaniel8dd688b2015-01-22 10:16:09 -0800126 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000127
joshualittd27f73e2014-12-29 07:43:36 -0800128 // Go to device coords to allow batching across matrix changes
joshualittd27f73e2014-12-29 07:43:36 -0800129 SkMatrix invert = SkMatrix::I();
130
131 // if we have a local rect, then we apply the localMatrix directly to the localRect to generate
132 // vertex local coords
joshualitt8fc6c2d2014-12-22 15:27:05 -0800133 bool hasExplicitLocalCoords = SkToBool(localRect);
joshualittd27f73e2014-12-29 07:43:36 -0800134 if (!hasExplicitLocalCoords) {
joshualitt8059eb92014-12-29 15:10:07 -0800135 if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
joshualittd27f73e2014-12-29 07:43:36 -0800136 SkDebugf("Could not invert\n");
137 return;
138 }
139
140 if (localMatrix) {
141 invert.preConcat(*localMatrix);
142 }
143 }
144
145 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCoords,
146 color,
147 &invert));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000148
joshualitt56995b52014-12-11 15:44:02 -0800149 size_t vstride = gp->getVertexStride();
joshualitt2dd1ae02014-12-03 06:24:10 -0800150 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
151 0));
152 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000153 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700154 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000155 return;
156 }
157
joshualitt8059eb92014-12-29 15:10:07 -0800158 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
159 viewMatrix.mapPointsWithStride(geo.positions(), vstride, 4);
160
jvanverth@google.com39768252013-02-14 15:25:44 +0000161 // When the caller has provided an explicit source rect for a stage then we don't want to
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000162 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
joshualitt8059eb92014-12-29 15:10:07 -0800163 // the vertex positions then we have to account for the view matrix
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000164 SkRect devBounds;
joshualitt8059eb92014-12-29 15:10:07 -0800165
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000166 // since we already computed the dev verts, set the bounds hint. This will help us avoid
167 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700168 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000169
bsalomon49f085d2014-09-05 13:34:00 -0700170 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700171 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
172 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000173 coords->setRectFan(localRect->fLeft, localRect->fTop,
174 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700175 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700176 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700177 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000178 }
179 }
180
bsalomon62c447d2014-08-08 08:08:50 -0700181 static const int kColorOffset = sizeof(SkPoint);
182 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
183 for (int i = 0; i < 4; ++i) {
184 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700185 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000186 }
187
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000188 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
egdaniel8dd688b2015-01-22 10:16:09 -0800189 this->drawIndexedInstances(pipelineBuilder, gp, kTriangles_GrPrimitiveType, 1, 4, 6,
190 &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000191}
192
egdaniel8dd688b2015-01-22 10:16:09 -0800193int GrInOrderDrawBuffer::concatInstancedDraw(const GrPipelineBuilder& pipelineBuilder,
194 const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700195 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000196 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000197
bsalomon@google.com934c5702012-03-20 21:17:58 +0000198 const GeometrySrcState& geomSrc = this->getGeomSrc();
199
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000200 // we only attempt to concat the case when reserved verts are used with a client-specified index
201 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
202 // between draws.
203 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
204 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
205 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000206 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000207 // Check if there is a draw info that is compatible that uses the same VB from the pool and
208 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700209 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000210 return 0;
211 }
212
cdalton6819df32014-10-15 13:43:48 -0700213 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000214
cdalton6819df32014-10-15 13:43:48 -0700215 if (!draw->fInfo.isInstanced() ||
joshualitt4d8da812015-01-28 12:53:54 -0800216 draw->fInfo.primitiveType() != info.primitiveType() ||
cdalton6819df32014-10-15 13:43:48 -0700217 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
218 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800219 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800220 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000221 return 0;
222 }
bsalomon371bcbc2014-12-01 08:19:34 -0800223 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000224 return 0;
225 }
226
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000227 // how many instances can be concat'ed onto draw given the size of the index buffer
228 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700229 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000230 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000231
cdalton6819df32014-10-15 13:43:48 -0700232 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000233
234 // update last fGpuCmdMarkers to include any additional trace markers that have been added
235 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700236 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000237 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
238 } else {
239 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700240 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000241 }
242 }
243
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000244 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000245}
246
egdaniel8dd688b2015-01-22 10:16:09 -0800247void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800248 const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800249 const DrawInfo& info,
bsalomon21b2c532015-02-05 14:18:05 -0800250 const GrScissorState& scissorState,
251 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800252 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
253
joshualitt4d8da812015-01-28 12:53:54 -0800254 // This closeBatch call is required because we may introduce new draws when we setup clip
255 this->closeBatch();
256
bsalomon21b2c532015-02-05 14:18:05 -0800257 if (!this->recordStateAndShouldDraw(pipelineBuilder, gp, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800258 return;
259 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000260
bsalomonb3e3a952014-09-19 11:10:40 -0700261 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000262 if (info.isInstanced()) {
egdaniel8dd688b2015-01-22 10:16:09 -0800263 int instancesConcated = this->concatInstancedDraw(pipelineBuilder, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000264 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800265 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700266 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000267 } else {
268 return;
269 }
270 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800271 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000272 }
cdalton6819df32014-10-15 13:43:48 -0700273 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000274}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000275
joshualitt4d8da812015-01-28 12:53:54 -0800276void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
277 const GrPipelineBuilder& pipelineBuilder,
278 const GrScissorState& scissorState,
bsalomon21b2c532015-02-05 14:18:05 -0800279 const GrDeviceCoordTexture* dstCopy) {
280 if (!this->recordStateAndShouldDraw(batch, pipelineBuilder, scissorState, dstCopy)) {
joshualitt4d8da812015-01-28 12:53:54 -0800281 return;
282 }
283
284 // Check if there is a Batch Draw we can batch with
285 if (kDrawBatch_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
286 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch));
287 return;
288 }
289
290 DrawBatch* draw = static_cast<DrawBatch*>(&fCmdBuffer.back());
291 if (draw->fBatch->combineIfPossible(batch)) {
292 return;
293 } else {
294 this->closeBatch();
295 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch));
296 }
297 this->recordTraceMarkersIfNecessary();
298}
299
egdaniel8dd688b2015-01-22 10:16:09 -0800300void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800301 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800302 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800303 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800304 const GrStencilSettings& stencilSettings) {
bsalomon3e791242014-12-17 13:43:13 -0800305 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
egdaniel8dd688b2015-01-22 10:16:09 -0800306 (path, pipelineBuilder.getRenderTarget()));
bsalomon3e791242014-12-17 13:43:13 -0800307 sp->fScissor = scissorState;
egdaniel8dd688b2015-01-22 10:16:09 -0800308 sp->fUseHWAA = pipelineBuilder.isHWAntialias();
joshualitt8059eb92014-12-29 15:10:07 -0800309 sp->fViewMatrix = pathProc->viewMatrix();
bsalomon3e791242014-12-17 13:43:13 -0800310 sp->fStencil = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700311 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000312}
313
egdaniel8dd688b2015-01-22 10:16:09 -0800314void GrInOrderDrawBuffer::onDrawPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800315 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800316 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800317 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800318 const GrStencilSettings& stencilSettings,
bsalomon21b2c532015-02-05 14:18:05 -0800319 const GrDeviceCoordTexture* dstCopy) {
joshualitt4d8da812015-01-28 12:53:54 -0800320 this->closeBatch();
321
egdaniel8dd688b2015-01-22 10:16:09 -0800322 // TODO: Only compare the subset of GrPipelineBuilder relevant to path covering?
bsalomon21b2c532015-02-05 14:18:05 -0800323 if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800324 return;
325 }
cdalton6819df32014-10-15 13:43:48 -0700326 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800327 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700328 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000329}
330
egdaniel8dd688b2015-01-22 10:16:09 -0800331void GrInOrderDrawBuffer::onDrawPaths(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800332 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800333 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800334 const void* indices,
335 PathIndexType indexType,
336 const float transformValues[],
337 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800338 int count,
bsalomon3e791242014-12-17 13:43:13 -0800339 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800340 const GrStencilSettings& stencilSettings,
bsalomon21b2c532015-02-05 14:18:05 -0800341 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700342 SkASSERT(pathRange);
343 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800344 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000345
joshualitt4d8da812015-01-28 12:53:54 -0800346 this->closeBatch();
347
bsalomon21b2c532015-02-05 14:18:05 -0800348 if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800349 return;
350 }
cdalton6819df32014-10-15 13:43:48 -0700351
cdalton55b24af2014-11-25 11:00:56 -0800352 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
353 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
354 // Add padding to the index buffer so the indices are aligned properly.
355 fPathIndexBuffer.append(indexBytes - misalign);
356 }
357
358 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
359 reinterpret_cast<const char*>(indices));
360 float* savedTransforms = fPathTransformBuffer.append(
361 count * GrPathRendering::PathTransformSize(transformType),
362 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700363
cdalton3fc6a2f2014-11-13 11:54:20 -0800364 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
365 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800366 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800367 // equivalent to two separate draw calls if there is overlap. Blending won't work,
368 // and the combined calls may also cancel each other's winding numbers in some
369 // places. For now the winding numbers are only an issue if the fill is even/odd,
370 // because DrawPaths is currently only used for glyphs, and glyphs in the same
371 // font tend to all wind in the same direction.
372 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
373 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800374 indexType == previous->fIndexType &&
375 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800376 stencilSettings == previous->fStencilSettings &&
377 path_fill_type_is_winding(stencilSettings) &&
egdaniel8dd688b2015-01-22 10:16:09 -0800378 !pipelineBuilder.willBlendWithDst(pathProc)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800379 // Fold this DrawPaths call into the one previous.
380 previous->fCount += count;
381 return;
382 }
383 }
384
385 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
bsalomonef3fcd82014-12-12 08:51:38 -0800386 dp->fIndicesLocation = SkToU32(savedIndices - fPathIndexBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800387 dp->fIndexType = indexType;
bsalomonef3fcd82014-12-12 08:51:38 -0800388 dp->fTransformsLocation = SkToU32(savedTransforms - fPathTransformBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800389 dp->fTransformType = transformType;
390 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800391 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700392
393 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000394}
395
bsalomon63b21962014-11-05 07:05:34 -0800396void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
397 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800398 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000399 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000400 if (NULL == rect) {
401 // We could do something smart and remove previous draws and clears to
402 // the current render target. If we get that smart we have to make sure
403 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000404 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000405 rect = &r;
406 }
cdalton6819df32014-10-15 13:43:48 -0700407 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000408 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000409 clr->fColor = color;
410 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000411 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700412 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000413}
414
joshualitt6db519c2014-10-29 08:48:18 -0700415void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
416 bool insideClip,
417 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800418 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700419 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
420 clr->fRect = rect;
421 clr->fInsideClip = insideClip;
422 this->recordTraceMarkersIfNecessary();
423}
424
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000425void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800426 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000427 if (!this->caps()->discardRenderTargetSupport()) {
428 return;
429 }
cdalton6819df32014-10-15 13:43:48 -0700430 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000431 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700432 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000433}
434
bsalomon371bcbc2014-12-01 08:19:34 -0800435void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700436 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800437 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800438 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
439 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000440 fGpuCmdMarkers.reset();
joshualitt4d8da812015-01-28 12:53:54 -0800441 fDrawBatch = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000442}
443
bsalomon371bcbc2014-12-01 08:19:34 -0800444void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700445 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000446 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000447 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000448
joshualittc2893c52015-01-28 06:54:30 -0800449 // Updated every time we find a set state cmd to reflect the current state in the playback
450 // stream.
451 SetState* currentState = NULL;
452
joshualitt4d8da812015-01-28 12:53:54 -0800453 // TODO this is temporary while batch is being rolled out
454 this->closeBatch();
455 this->getVertexAllocPool()->unmap();
456 this->getIndexAllocPool()->unmap();
457 fBatchTarget.preFlush();
458
459 currentState = NULL;
460 CmdBuffer::Iter iter(fCmdBuffer);
461
462 int currCmdMarker = 0;
463
joshualitt7bc18b72015-02-03 16:41:41 -0800464 int i = 0;
cdalton6819df32014-10-15 13:43:48 -0700465 while (iter.next()) {
joshualitt7bc18b72015-02-03 16:41:41 -0800466 i++;
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000467 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700468 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700469 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700470 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000471 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800472 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000473 ++currCmdMarker;
474 }
cdalton6819df32014-10-15 13:43:48 -0700475
joshualitt4d8da812015-01-28 12:53:54 -0800476 // TODO temporary hack
477 if (kDrawBatch_Cmd == strip_trace_bit(iter->fType)) {
joshualitt7bc18b72015-02-03 16:41:41 -0800478 DrawBatch* db = reinterpret_cast<DrawBatch*>(iter.get());
479 fBatchTarget.flushNext(db->fBatch->numberOfDraws());
joshualitt4d8da812015-01-28 12:53:54 -0800480 continue;
481 }
482
483 bool isSetState = kSetState_Cmd == strip_trace_bit(iter->fType);
484 if (isSetState) {
joshualitt9853cce2014-11-17 14:22:48 -0800485 SetState* ss = reinterpret_cast<SetState*>(iter.get());
joshualitt873ad0e2015-01-20 09:08:51 -0800486
joshualitt4d8da812015-01-28 12:53:54 -0800487 // TODO sometimes we have a prim proc, othertimes we have a GrBatch. Eventually we will
488 // only have GrBatch and we can delete this
489 if (ss->fPrimitiveProcessor) {
490 this->getGpu()->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor,
491 ss->fPipeline,
bsalomon21b2c532015-02-05 14:18:05 -0800492 ss->fPipeline.descInfo(),
joshualitt4d8da812015-01-28 12:53:54 -0800493 ss->fBatchTracker);
494 }
joshualitt873ad0e2015-01-20 09:08:51 -0800495 currentState = ss;
joshualittd53a8272014-11-10 16:03:14 -0800496 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800497 iter->execute(this, currentState);
joshualittd53a8272014-11-10 16:03:14 -0800498 }
cdalton6819df32014-10-15 13:43:48 -0700499
500 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800501 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000502 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000503 }
mtkleinf439c772014-10-14 14:29:30 -0700504
joshualitt4d8da812015-01-28 12:53:54 -0800505 // TODO see copious notes about hack
506 fBatchTarget.postFlush();
507
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000508 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000509 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000510}
511
joshualitt873ad0e2015-01-20 09:08:51 -0800512void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
513 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800514 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800515 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800516 buf->getGpu()->draw(args, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700517}
518
joshualitt873ad0e2015-01-20 09:08:51 -0800519void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon3e791242014-12-17 13:43:13 -0800520 GrGpu::StencilPathState state;
521 state.fRenderTarget = fRenderTarget.get();
522 state.fScissor = &fScissor;
523 state.fStencil = &fStencil;
524 state.fUseHWAA = fUseHWAA;
525 state.fViewMatrix = &fViewMatrix;
526
527 buf->getGpu()->stencilPath(this->path(), state);
cdalton6819df32014-10-15 13:43:48 -0700528}
529
joshualitt873ad0e2015-01-20 09:08:51 -0800530void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
531 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800532 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800533 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800534 buf->getGpu()->drawPath(args, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700535}
536
joshualitt873ad0e2015-01-20 09:08:51 -0800537void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
538 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800539 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800540 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800541 buf->getGpu()->drawPaths(args, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800542 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
543 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
544 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700545}
546
joshualitt4d8da812015-01-28 12:53:54 -0800547void GrInOrderDrawBuffer::DrawBatch::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
548 SkASSERT(state);
549 fBatch->generateGeometry(buf->getBatchTarget(), &state->fPipeline);
550}
551
joshualitt873ad0e2015-01-20 09:08:51 -0800552void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const SetState*) {}
cdalton6819df32014-10-15 13:43:48 -0700553
joshualitt873ad0e2015-01-20 09:08:51 -0800554void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const SetState*) {
cdalton6819df32014-10-15 13:43:48 -0700555 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800556 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700557 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800558 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700559 }
560}
561
joshualitt873ad0e2015-01-20 09:08:51 -0800562void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800563 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700564}
565
joshualitt873ad0e2015-01-20 09:08:51 -0800566void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800567 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700568}
569
bsalomonf90a02b2014-11-26 12:28:00 -0800570bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
571 GrSurface* src,
572 const SkIRect& srcRect,
573 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800574 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700575 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000576 cs->fSrcRect = srcRect;
577 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700578 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000579 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000580 }
bsalomonf90a02b2014-11-26 12:28:00 -0800581 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000582}
583
egdaniel8dd688b2015-01-22 10:16:09 -0800584bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipelineBuilder,
joshualitt71c92602015-01-14 08:12:47 -0800585 const GrPrimitiveProcessor* primProc,
bsalomon3e791242014-12-17 13:43:13 -0800586 const GrScissorState& scissor,
bsalomon21b2c532015-02-05 14:18:05 -0800587 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800588 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
egdaniel8dd688b2015-01-22 10:16:09 -0800589 (pipelineBuilder, primProc, *this->getGpu()->caps(),
bsalomon21b2c532015-02-05 14:18:05 -0800590 scissor, dstCopy));
egdaniel8dd688b2015-01-22 10:16:09 -0800591 if (ss->fPipeline.mustSkip()) {
bsalomon932f8662014-11-24 06:47:48 -0800592 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800593 return false;
594 }
joshualitt873ad0e2015-01-20 09:08:51 -0800595
596 ss->fPrimitiveProcessor->initBatchTracker(&ss->fBatchTracker,
egdaniel8dd688b2015-01-22 10:16:09 -0800597 ss->fPipeline.getInitBatchTracker());
joshualitt873ad0e2015-01-20 09:08:51 -0800598
joshualitt4d8da812015-01-28 12:53:54 -0800599 if (fPrevState && fPrevState->fPrimitiveProcessor.get() &&
joshualitt873ad0e2015-01-20 09:08:51 -0800600 fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker,
601 *ss->fPrimitiveProcessor,
602 ss->fBatchTracker) &&
egdaniel8dd688b2015-01-22 10:16:09 -0800603 fPrevState->fPipeline.isEqual(ss->fPipeline)) {
bsalomon932f8662014-11-24 06:47:48 -0800604 fCmdBuffer.pop_back();
605 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800606 fPrevState = ss;
cdalton6819df32014-10-15 13:43:48 -0700607 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700608 }
bsalomonae59b772014-11-19 08:23:49 -0800609 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000610}
611
joshualitt4d8da812015-01-28 12:53:54 -0800612bool GrInOrderDrawBuffer::recordStateAndShouldDraw(GrBatch* batch,
613 const GrPipelineBuilder& pipelineBuilder,
614 const GrScissorState& scissor,
bsalomon21b2c532015-02-05 14:18:05 -0800615 const GrDeviceCoordTexture* dstCopy) {
joshualitt4d8da812015-01-28 12:53:54 -0800616 // TODO this gets much simpler when we have batches everywhere.
617 // If the previous command is also a set state, then we check to see if it has a Batch. If so,
618 // and we can make the two batches equal, and we can combine the states, then we make them equal
619 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
620 (batch, pipelineBuilder, *this->getGpu()->caps(), scissor,
bsalomon21b2c532015-02-05 14:18:05 -0800621 dstCopy));
joshualitt4d8da812015-01-28 12:53:54 -0800622 if (ss->fPipeline.mustSkip()) {
623 fCmdBuffer.pop_back();
624 return false;
625 }
626
627 batch->initBatchTracker(ss->fPipeline.getInitBatchTracker());
628
629 if (fPrevState && !fPrevState->fPrimitiveProcessor.get() &&
630 fPrevState->fPipeline.isEqual(ss->fPipeline)) {
631 fCmdBuffer.pop_back();
632 } else {
633 this->closeBatch();
634 fPrevState = ss;
635 this->recordTraceMarkersIfNecessary();
636 }
637 return true;
638}
639
cdalton6819df32014-10-15 13:43:48 -0700640void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
641 SkASSERT(!fCmdBuffer.empty());
642 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700643 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
644 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700645 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700646 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700647 }
mtklein07894c42014-10-13 14:00:42 -0700648}
joshualitt4d8da812015-01-28 12:53:54 -0800649
650void GrInOrderDrawBuffer::closeBatch() {
651 if (fDrawBatch) {
joshualitt7bc18b72015-02-03 16:41:41 -0800652 fBatchTarget.resetNumberOfDraws();
joshualitt4d8da812015-01-28 12:53:54 -0800653 fDrawBatch->execute(this, fPrevState);
joshualitt7bc18b72015-02-03 16:41:41 -0800654 fDrawBatch->fBatch->setNumberOfDraws(fBatchTarget.numberOfDraws());
joshualitt4d8da812015-01-28 12:53:54 -0800655 fDrawBatch = NULL;
656 }
657}
658
659void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
660 size_t vertexStride,
661 int indexCount) {
662 this->closeBatch();
663
664 // We use geometryHints() to know whether to flush the draw buffer. We
665 // can't flush if we are inside an unbalanced pushGeometrySource.
666 // Moreover, flushing blows away vertex and index data that was
667 // previously reserved. So if the vertex or index data is pulled from
668 // reserved space and won't be released by this request then we can't
669 // flush.
670 bool insideGeoPush = this->getGeoPoolStateStack().count() > 1;
671
672 bool unreleasedVertexSpace =
673 !vertexCount &&
674 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
675
676 bool unreleasedIndexSpace =
677 !indexCount &&
678 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
679
680 int vcount = vertexCount;
681 int icount = indexCount;
682
683 if (!insideGeoPush &&
684 !unreleasedVertexSpace &&
685 !unreleasedIndexSpace &&
686 this->geometryHints(vertexStride, &vcount, &icount)) {
687 this->flush();
688 }
689}