blob: 1453276e4944cef93d747e3f9bfa24a8f8f34d89 [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.comc26d94f2013-03-25 18:19:00 +000011#include "GrDrawTargetCaps.h"
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000012#include "GrGpu.h"
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000013#include "GrTemplates.h"
jvanverth787cdf92014-12-04 10:46:50 -080014#include "GrFontCache.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000015#include "GrTexture.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000017GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
bsalomon@google.com471d4712011-08-23 15:45:25 +000018 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000019 GrIndexBufferAllocPool* indexPool)
bsalomon371bcbc2014-12-01 08:19:34 -080020 : INHERITED(gpu, vertexPool, indexPool)
cdalton6819df32014-10-15 13:43:48 -070021 , fCmdBuffer(kCmdBufferInitialSizeInBytes)
bsalomon932f8662014-11-24 06:47:48 -080022 , fPrevState(NULL)
joshualittd15e4e42015-01-26 13:30:10 -080023 , fDrawID(0)
24 , fBatchTarget(gpu, vertexPool, indexPool) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000025
bsalomon49f085d2014-09-05 13:34:00 -070026 SkASSERT(vertexPool);
27 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000028
cdalton3fc6a2f2014-11-13 11:54:20 -080029 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
30 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
reed@google.comac10a2d2010-12-22 21:39:39 +000031}
32
33GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000034 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000035}
36
bsalomon@google.com934c5702012-03-20 21:17:58 +000037////////////////////////////////////////////////////////////////////////////////
38
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000039namespace {
40void get_vertex_bounds(const void* vertices,
41 size_t vertexSize,
42 int vertexCount,
43 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000044 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000045 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000046 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000047 bounds->fLeft = bounds->fRight = point->fX;
48 bounds->fTop = bounds->fBottom = point->fY;
49 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000050 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000051 bounds->growToInclude(point->fX, point->fY);
52 }
53}
bsalomon@google.com934c5702012-03-20 21:17:58 +000054}
55
bsalomon62c447d2014-08-08 08:08:50 -070056/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
57 have explicit local coords and sometimes not. We *could* always provide explicit local coords
58 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
59 haven't seen a use case which frequently switches between local rect and no local rect draws.
60
61 The color param is used to determine whether the opaque hint can be set on the draw state.
62 The caller must populate the vertex colors itself.
63
64 The vertex attrib order is always pos, color, [local coords].
65 */
joshualitt8fc6c2d2014-12-22 15:27:05 -080066static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords,
67 GrColor color,
68 const SkMatrix* localMatrix) {
joshualitt5478d422014-11-14 16:00:38 -080069 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
70 GrDefaultGeoProcFactory::kColor_GPType;
joshualitt8fc6c2d2014-12-22 15:27:05 -080071 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
72 if (localMatrix) {
joshualitt8059eb92014-12-29 15:10:07 -080073 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *localMatrix,
74 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080075 } else {
joshualitt8059eb92014-12-29 15:10:07 -080076 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMatrix::I(),
77 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080078 }
bsalomon62c447d2014-08-08 08:08:50 -070079}
robertphillips@google.com42903302013-04-20 12:26:07 +000080
cdalton3fc6a2f2014-11-13 11:54:20 -080081static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
82 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
83 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
84 if (isWinding) {
85 // Double check that it is in fact winding.
86 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
87 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
88 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
89 SkASSERT(!pathStencilSettings.isTwoSided());
90 }
91 return isWinding;
92}
93
94template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
95 // Assume the next time this buffer fills up it will use approximately the same amount
96 // of space as last time. Only resize if we're using less than a third of the
97 // allocated space, and leave enough for 50% growth over last time.
98 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
99 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
100 buffer->reset();
101 buffer->setReserve(reserve);
102 } else {
103 buffer->rewind();
104 }
105}
106
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000107enum {
108 kTraceCmdBit = 0x80,
109 kCmdMask = 0x7f,
110};
111
bsalomon62c447d2014-08-08 08:08:50 -0700112static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000113
bsalomon62c447d2014-08-08 08:08:50 -0700114static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000115
bsalomon62c447d2014-08-08 08:08:50 -0700116static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000117
egdaniel8dd688b2015-01-22 10:16:09 -0800118void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -0800119 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800120 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800121 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000122 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000123 const SkMatrix* localMatrix) {
egdaniel8dd688b2015-01-22 10:16:09 -0800124 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000125
joshualittd27f73e2014-12-29 07:43:36 -0800126 // Go to device coords to allow batching across matrix changes
joshualittd27f73e2014-12-29 07:43:36 -0800127 SkMatrix invert = SkMatrix::I();
128
129 // if we have a local rect, then we apply the localMatrix directly to the localRect to generate
130 // vertex local coords
joshualitt8fc6c2d2014-12-22 15:27:05 -0800131 bool hasExplicitLocalCoords = SkToBool(localRect);
joshualittd27f73e2014-12-29 07:43:36 -0800132 if (!hasExplicitLocalCoords) {
joshualitt8059eb92014-12-29 15:10:07 -0800133 if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
joshualittd27f73e2014-12-29 07:43:36 -0800134 SkDebugf("Could not invert\n");
135 return;
136 }
137
138 if (localMatrix) {
139 invert.preConcat(*localMatrix);
140 }
141 }
142
143 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCoords,
144 color,
145 &invert));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000146
joshualitt56995b52014-12-11 15:44:02 -0800147 size_t vstride = gp->getVertexStride();
joshualitt2dd1ae02014-12-03 06:24:10 -0800148 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
149 0));
150 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000151 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700152 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000153 return;
154 }
155
joshualitt8059eb92014-12-29 15:10:07 -0800156 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
157 viewMatrix.mapPointsWithStride(geo.positions(), vstride, 4);
158
jvanverth@google.com39768252013-02-14 15:25:44 +0000159 // 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 +0000160 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
joshualitt8059eb92014-12-29 15:10:07 -0800161 // the vertex positions then we have to account for the view matrix
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000162 SkRect devBounds;
joshualitt8059eb92014-12-29 15:10:07 -0800163
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000164 // since we already computed the dev verts, set the bounds hint. This will help us avoid
165 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700166 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000167
bsalomon49f085d2014-09-05 13:34:00 -0700168 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700169 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
170 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000171 coords->setRectFan(localRect->fLeft, localRect->fTop,
172 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700173 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700174 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700175 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000176 }
177 }
178
bsalomon62c447d2014-08-08 08:08:50 -0700179 static const int kColorOffset = sizeof(SkPoint);
180 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
181 for (int i = 0; i < 4; ++i) {
182 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700183 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000184 }
185
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000186 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
egdaniel8dd688b2015-01-22 10:16:09 -0800187 this->drawIndexedInstances(pipelineBuilder, gp, kTriangles_GrPrimitiveType, 1, 4, 6,
188 &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000189}
190
egdaniel8dd688b2015-01-22 10:16:09 -0800191int GrInOrderDrawBuffer::concatInstancedDraw(const GrPipelineBuilder& pipelineBuilder,
192 const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700193 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000194 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000195
bsalomon@google.com934c5702012-03-20 21:17:58 +0000196 const GeometrySrcState& geomSrc = this->getGeomSrc();
197
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000198 // we only attempt to concat the case when reserved verts are used with a client-specified index
199 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
200 // between draws.
201 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
202 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
203 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000204 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000205 // Check if there is a draw info that is compatible that uses the same VB from the pool and
206 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700207 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000208 return 0;
209 }
210
cdalton6819df32014-10-15 13:43:48 -0700211 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000212
cdalton6819df32014-10-15 13:43:48 -0700213 if (!draw->fInfo.isInstanced() ||
joshualittd15e4e42015-01-26 13:30:10 -0800214 draw->fInfo.primitiveType() != info.primitiveType() ||
cdalton6819df32014-10-15 13:43:48 -0700215 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
216 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800217 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800218 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000219 return 0;
220 }
bsalomon371bcbc2014-12-01 08:19:34 -0800221 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000222 return 0;
223 }
224
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000225 // how many instances can be concat'ed onto draw given the size of the index buffer
226 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700227 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000228 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000229
cdalton6819df32014-10-15 13:43:48 -0700230 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000231
232 // update last fGpuCmdMarkers to include any additional trace markers that have been added
233 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700234 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000235 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
236 } else {
237 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700238 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000239 }
240 }
241
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000242 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000243}
244
egdaniel8dd688b2015-01-22 10:16:09 -0800245void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800246 const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800247 const DrawInfo& info,
bsalomon3e791242014-12-17 13:43:13 -0800248 const GrScissorState& scissorState,
joshualitt9176e2c2014-11-20 07:28:52 -0800249 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800250 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
251
egdaniel8dd688b2015-01-22 10:16:09 -0800252 if (!this->recordStateAndShouldDraw(pipelineBuilder, gp, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800253 return;
254 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000255
bsalomonb3e3a952014-09-19 11:10:40 -0700256 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000257 if (info.isInstanced()) {
egdaniel8dd688b2015-01-22 10:16:09 -0800258 int instancesConcated = this->concatInstancedDraw(pipelineBuilder, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000259 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800260 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700261 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000262 } else {
263 return;
264 }
265 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800266 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000267 }
cdalton6819df32014-10-15 13:43:48 -0700268 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000269}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000270
joshualittd15e4e42015-01-26 13:30:10 -0800271void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
272 const GrPipelineBuilder& pipelineBuilder,
273 const GrScissorState& scissorState,
274 const GrDeviceCoordTexture* dstCopy) {
275 if (!this->recordStateAndShouldDraw(batch, pipelineBuilder, scissorState, dstCopy)) {
276 return;
277 }
278
279 // Check if there is a Batch Draw we can batch with
280 if (kDrawBatch_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
281 GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch));
282 return;
283 }
284
285 DrawBatch* draw = static_cast<DrawBatch*>(&fCmdBuffer.back());
286 if (draw->fBatch->combineIfPossible(batch)) {
287 return;
288 } else {
289 GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch));
290 }
291 this->recordTraceMarkersIfNecessary();
292}
293
egdaniel8dd688b2015-01-22 10:16:09 -0800294void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800295 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800296 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800297 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800298 const GrStencilSettings& stencilSettings) {
bsalomon3e791242014-12-17 13:43:13 -0800299 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
egdaniel8dd688b2015-01-22 10:16:09 -0800300 (path, pipelineBuilder.getRenderTarget()));
bsalomon3e791242014-12-17 13:43:13 -0800301 sp->fScissor = scissorState;
egdaniel8dd688b2015-01-22 10:16:09 -0800302 sp->fUseHWAA = pipelineBuilder.isHWAntialias();
joshualitt8059eb92014-12-29 15:10:07 -0800303 sp->fViewMatrix = pathProc->viewMatrix();
bsalomon3e791242014-12-17 13:43:13 -0800304 sp->fStencil = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700305 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000306}
307
egdaniel8dd688b2015-01-22 10:16:09 -0800308void GrInOrderDrawBuffer::onDrawPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800309 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800310 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800311 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800312 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700313 const GrDeviceCoordTexture* dstCopy) {
egdaniel8dd688b2015-01-22 10:16:09 -0800314 // TODO: Only compare the subset of GrPipelineBuilder relevant to path covering?
315 if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800316 return;
317 }
cdalton6819df32014-10-15 13:43:48 -0700318 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800319 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700320 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000321}
322
egdaniel8dd688b2015-01-22 10:16:09 -0800323void GrInOrderDrawBuffer::onDrawPaths(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800324 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800325 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800326 const void* indices,
327 PathIndexType indexType,
328 const float transformValues[],
329 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800330 int count,
bsalomon3e791242014-12-17 13:43:13 -0800331 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800332 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700333 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700334 SkASSERT(pathRange);
335 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800336 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000337
egdaniel8dd688b2015-01-22 10:16:09 -0800338 if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800339 return;
340 }
cdalton6819df32014-10-15 13:43:48 -0700341
cdalton55b24af2014-11-25 11:00:56 -0800342 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
343 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
344 // Add padding to the index buffer so the indices are aligned properly.
345 fPathIndexBuffer.append(indexBytes - misalign);
346 }
347
348 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
349 reinterpret_cast<const char*>(indices));
350 float* savedTransforms = fPathTransformBuffer.append(
351 count * GrPathRendering::PathTransformSize(transformType),
352 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700353
cdalton3fc6a2f2014-11-13 11:54:20 -0800354 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
355 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800356 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800357 // equivalent to two separate draw calls if there is overlap. Blending won't work,
358 // and the combined calls may also cancel each other's winding numbers in some
359 // places. For now the winding numbers are only an issue if the fill is even/odd,
360 // because DrawPaths is currently only used for glyphs, and glyphs in the same
361 // font tend to all wind in the same direction.
362 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
363 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800364 indexType == previous->fIndexType &&
365 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800366 stencilSettings == previous->fStencilSettings &&
367 path_fill_type_is_winding(stencilSettings) &&
egdaniel8dd688b2015-01-22 10:16:09 -0800368 !pipelineBuilder.willBlendWithDst(pathProc)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800369 // Fold this DrawPaths call into the one previous.
370 previous->fCount += count;
371 return;
372 }
373 }
374
375 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
bsalomonef3fcd82014-12-12 08:51:38 -0800376 dp->fIndicesLocation = SkToU32(savedIndices - fPathIndexBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800377 dp->fIndexType = indexType;
bsalomonef3fcd82014-12-12 08:51:38 -0800378 dp->fTransformsLocation = SkToU32(savedTransforms - fPathTransformBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800379 dp->fTransformType = transformType;
380 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800381 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700382
383 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000384}
385
bsalomon63b21962014-11-05 07:05:34 -0800386void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
387 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800388 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000389 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000390 if (NULL == rect) {
391 // We could do something smart and remove previous draws and clears to
392 // the current render target. If we get that smart we have to make sure
393 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000394 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000395 rect = &r;
396 }
cdalton6819df32014-10-15 13:43:48 -0700397 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000398 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000399 clr->fColor = color;
400 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000401 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700402 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000403}
404
joshualitt6db519c2014-10-29 08:48:18 -0700405void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
406 bool insideClip,
407 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800408 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700409 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
410 clr->fRect = rect;
411 clr->fInsideClip = insideClip;
412 this->recordTraceMarkersIfNecessary();
413}
414
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000415void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800416 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000417 if (!this->caps()->discardRenderTargetSupport()) {
418 return;
419 }
cdalton6819df32014-10-15 13:43:48 -0700420 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000421 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700422 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000423}
424
bsalomon371bcbc2014-12-01 08:19:34 -0800425void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700426 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800427 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800428 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
429 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000430 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000431}
432
bsalomon371bcbc2014-12-01 08:19:34 -0800433void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700434 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000435 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000436 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000437
cdalton6819df32014-10-15 13:43:48 -0700438 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000439
cdalton6819df32014-10-15 13:43:48 -0700440 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700441
bsalomonae59b772014-11-19 08:23:49 -0800442 // Updated every time we find a set state cmd to reflect the current state in the playback
443 // stream.
joshualitt873ad0e2015-01-20 09:08:51 -0800444 SetState* currentState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800445
joshualittd15e4e42015-01-26 13:30:10 -0800446 // TODO to prevent flushing the batch buffer too much, we only flush when wasBatch && !isBatch
447 // In the long term we can delete this and just flush once at the end of all geometry generation
448 bool wasBatch = false;
449
cdalton6819df32014-10-15 13:43:48 -0700450 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000451 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700452 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700453 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700454 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000455 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800456 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000457 ++currCmdMarker;
458 }
cdalton6819df32014-10-15 13:43:48 -0700459
joshualittd15e4e42015-01-26 13:30:10 -0800460 bool isSetState = kSetState_Cmd == strip_trace_bit(iter->fType);
461
462 if (!isSetState && kDrawBatch_Cmd != strip_trace_bit(iter->fType)) {
463 // TODO see note above, this gets deleted once everyone uses batch drawing
464 if (wasBatch) {
465 wasBatch = false;
466 fBatchTarget.flush();
467 }
468 }
469
470 if (isSetState) {
joshualitt9853cce2014-11-17 14:22:48 -0800471 SetState* ss = reinterpret_cast<SetState*>(iter.get());
joshualitt873ad0e2015-01-20 09:08:51 -0800472
joshualittd15e4e42015-01-26 13:30:10 -0800473 // TODO sometimes we have a prim proc, othertimes we have a GrBatch. Eventually we will
474 // only have GrBatch and we can delete this
475 if (ss->fPrimitiveProcessor) {
476 this->getGpu()->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor,
477 ss->fPipeline,
478 ss->fPipeline.descInfo(),
479 ss->fBatchTracker);
480 } else {
481 wasBatch = true;
482 }
joshualitt873ad0e2015-01-20 09:08:51 -0800483 currentState = ss;
joshualittd53a8272014-11-10 16:03:14 -0800484 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800485 iter->execute(this, currentState);
joshualittd53a8272014-11-10 16:03:14 -0800486 }
cdalton6819df32014-10-15 13:43:48 -0700487
488 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800489 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000490 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000491 }
mtkleinf439c772014-10-14 14:29:30 -0700492
joshualittd15e4e42015-01-26 13:30:10 -0800493 // TODO see note above, one last catch
494 if (wasBatch) {
495 fBatchTarget.flush();
496 }
497
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000498 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000499 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000500}
501
joshualitt873ad0e2015-01-20 09:08:51 -0800502void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
503 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800504 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800505 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800506 buf->getGpu()->draw(args, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700507}
508
joshualitt873ad0e2015-01-20 09:08:51 -0800509void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon3e791242014-12-17 13:43:13 -0800510 GrGpu::StencilPathState state;
511 state.fRenderTarget = fRenderTarget.get();
512 state.fScissor = &fScissor;
513 state.fStencil = &fStencil;
514 state.fUseHWAA = fUseHWAA;
515 state.fViewMatrix = &fViewMatrix;
516
517 buf->getGpu()->stencilPath(this->path(), state);
cdalton6819df32014-10-15 13:43:48 -0700518}
519
joshualitt873ad0e2015-01-20 09:08:51 -0800520void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
521 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800522 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800523 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800524 buf->getGpu()->drawPath(args, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700525}
526
joshualitt873ad0e2015-01-20 09:08:51 -0800527void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
528 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800529 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800530 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800531 buf->getGpu()->drawPaths(args, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800532 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
533 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
534 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700535}
536
joshualittd15e4e42015-01-26 13:30:10 -0800537void GrInOrderDrawBuffer::DrawBatch::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
538 SkASSERT(state);
539 fBatch->generateGeometry(buf->getBatchTarget(), &state->fPipeline);
540}
541
joshualitt873ad0e2015-01-20 09:08:51 -0800542void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const SetState*) {}
cdalton6819df32014-10-15 13:43:48 -0700543
joshualitt873ad0e2015-01-20 09:08:51 -0800544void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const SetState*) {
cdalton6819df32014-10-15 13:43:48 -0700545 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800546 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700547 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800548 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700549 }
550}
551
joshualitt873ad0e2015-01-20 09:08:51 -0800552void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800553 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700554}
555
joshualitt873ad0e2015-01-20 09:08:51 -0800556void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800557 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700558}
559
bsalomonf90a02b2014-11-26 12:28:00 -0800560bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
561 GrSurface* src,
562 const SkIRect& srcRect,
563 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800564 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700565 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000566 cs->fSrcRect = srcRect;
567 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700568 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000569 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000570 }
bsalomonf90a02b2014-11-26 12:28:00 -0800571 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000572}
573
egdaniel8dd688b2015-01-22 10:16:09 -0800574bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipelineBuilder,
joshualitt71c92602015-01-14 08:12:47 -0800575 const GrPrimitiveProcessor* primProc,
bsalomon3e791242014-12-17 13:43:13 -0800576 const GrScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800577 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800578 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
egdaniel8dd688b2015-01-22 10:16:09 -0800579 (pipelineBuilder, primProc, *this->getGpu()->caps(),
580 scissor, dstCopy));
581 if (ss->fPipeline.mustSkip()) {
bsalomon932f8662014-11-24 06:47:48 -0800582 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800583 return false;
584 }
joshualitt873ad0e2015-01-20 09:08:51 -0800585
586 ss->fPrimitiveProcessor->initBatchTracker(&ss->fBatchTracker,
egdaniel8dd688b2015-01-22 10:16:09 -0800587 ss->fPipeline.getInitBatchTracker());
joshualitt873ad0e2015-01-20 09:08:51 -0800588
joshualittd15e4e42015-01-26 13:30:10 -0800589 if (fPrevState && fPrevState->fPrimitiveProcessor.get() &&
joshualitt873ad0e2015-01-20 09:08:51 -0800590 fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker,
591 *ss->fPrimitiveProcessor,
592 ss->fBatchTracker) &&
egdaniel8dd688b2015-01-22 10:16:09 -0800593 fPrevState->fPipeline.isEqual(ss->fPipeline)) {
bsalomon932f8662014-11-24 06:47:48 -0800594 fCmdBuffer.pop_back();
595 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800596 fPrevState = ss;
cdalton6819df32014-10-15 13:43:48 -0700597 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700598 }
bsalomonae59b772014-11-19 08:23:49 -0800599 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000600}
601
joshualittd15e4e42015-01-26 13:30:10 -0800602bool GrInOrderDrawBuffer::recordStateAndShouldDraw(GrBatch* batch,
603 const GrPipelineBuilder& pipelineBuilder,
604 const GrScissorState& scissor,
605 const GrDeviceCoordTexture* dstCopy) {
606 // TODO this gets much simpler when we have batches everywhere.
607 // If the previous command is also a set state, then we check to see if it has a Batch. If so,
608 // and we can make the two batches equal, and we can combine the states, then we make them equal
609 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
610 (batch, pipelineBuilder, *this->getGpu()->caps(), scissor,
611 dstCopy));
612 if (ss->fPipeline.mustSkip()) {
613 fCmdBuffer.pop_back();
614 return false;
615 }
616
617 batch->initBatchTracker(ss->fPipeline.getInitBatchTracker());
618
619 if (fPrevState && !fPrevState->fPrimitiveProcessor.get() &&
620 fPrevState->fPipeline.isEqual(ss->fPipeline)) {
621 fCmdBuffer.pop_back();
622 } else {
623 fPrevState = ss;
624 this->recordTraceMarkersIfNecessary();
625 }
626 return true;
627}
628
cdalton6819df32014-10-15 13:43:48 -0700629void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
630 SkASSERT(!fCmdBuffer.empty());
631 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700632 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
633 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700634 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700635 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700636 }
mtklein07894c42014-10-13 14:00:42 -0700637}