blob: c180cc67d2974d587963388c5c5020793acd4b5d [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
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000010#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"
joshualittd53a8272014-11-10 16:03:14 -080014#include "GrOptDrawState.h"
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000015#include "GrTemplates.h"
joshualittd53a8272014-11-10 16:03:14 -080016#include "GrTextStrike.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017#include "GrTexture.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000018
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000019GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
bsalomon@google.com471d4712011-08-23 15:45:25 +000020 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000021 GrIndexBufferAllocPool* indexPool)
joshualitt6db519c2014-10-29 08:48:18 -070022 : INHERITED(gpu->getContext())
cdalton6819df32014-10-15 13:43:48 -070023 , fCmdBuffer(kCmdBufferInitialSizeInBytes)
24 , fLastState(NULL)
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000025 , fDstGpu(gpu)
robertphillips@google.com69705572012-03-21 19:46:50 +000026 , fVertexPool(*vertexPool)
27 , fIndexPool(*indexPool)
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +000028 , fFlushing(false)
29 , fDrawID(0) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000030
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000031 fDstGpu->ref();
bsalomon@google.combcce8922013-03-25 15:38:39 +000032 fCaps.reset(SkRef(fDstGpu->caps()));
bsalomon@google.com18c9c192011-09-22 21:01:31 +000033
bsalomon49f085d2014-09-05 13:34:00 -070034 SkASSERT(vertexPool);
35 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000036
cdalton3fc6a2f2014-11-13 11:54:20 -080037 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
38 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
39
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000040 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
41 poolState.fUsedPoolVertexBytes = 0;
42 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000043#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000044 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
45 poolState.fPoolStartVertex = ~0;
46 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
47 poolState.fPoolStartIndex = ~0;
48#endif
bsalomon@google.coma4f6b102012-06-26 21:04:22 +000049 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000050}
51
52GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000053 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000054 // This must be called by before the GrDrawTarget destructor
55 this->releaseGeometry();
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000056 fDstGpu->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +000057}
58
bsalomon@google.com934c5702012-03-20 21:17:58 +000059////////////////////////////////////////////////////////////////////////////////
60
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000061namespace {
62void get_vertex_bounds(const void* vertices,
63 size_t vertexSize,
64 int vertexCount,
65 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000066 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000067 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000068 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000069 bounds->fLeft = bounds->fRight = point->fX;
70 bounds->fTop = bounds->fBottom = point->fY;
71 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000072 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000073 bounds->growToInclude(point->fX, point->fY);
74 }
75}
bsalomon@google.com934c5702012-03-20 21:17:58 +000076}
77
bsalomon62c447d2014-08-08 08:08:50 -070078/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
79 have explicit local coords and sometimes not. We *could* always provide explicit local coords
80 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
81 haven't seen a use case which frequently switches between local rect and no local rect draws.
82
83 The color param is used to determine whether the opaque hint can be set on the draw state.
84 The caller must populate the vertex colors itself.
85
86 The vertex attrib order is always pos, color, [local coords].
87 */
88static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
joshualitt5478d422014-11-14 16:00:38 -080089 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
90 GrDefaultGeoProcFactory::kColor_GPType;
91 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
92 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::CreateAndSetAttribs(drawState,
93 flags))->unref();
bsalomon62c447d2014-08-08 08:08:50 -070094 if (0xFF == GrColorUnpackA(color)) {
95 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
96 }
97}
robertphillips@google.com42903302013-04-20 12:26:07 +000098
cdalton3fc6a2f2014-11-13 11:54:20 -080099static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
100 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
101 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
102 if (isWinding) {
103 // Double check that it is in fact winding.
104 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
105 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
106 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
107 SkASSERT(!pathStencilSettings.isTwoSided());
108 }
109 return isWinding;
110}
111
112template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
113 // Assume the next time this buffer fills up it will use approximately the same amount
114 // of space as last time. Only resize if we're using less than a third of the
115 // allocated space, and leave enough for 50% growth over last time.
116 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
117 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
118 buffer->reset();
119 buffer->setReserve(reserve);
120 } else {
121 buffer->rewind();
122 }
123}
124
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000125enum {
126 kTraceCmdBit = 0x80,
127 kCmdMask = 0x7f,
128};
129
bsalomon62c447d2014-08-08 08:08:50 -0700130static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000131
bsalomon62c447d2014-08-08 08:08:50 -0700132static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000133
bsalomon62c447d2014-08-08 08:08:50 -0700134static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000135
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000136void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000137 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000138 const SkMatrix* localMatrix) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000139 GrDrawState* drawState = this->drawState();
joshualitt5478d422014-11-14 16:00:38 -0800140 GrDrawState::AutoRestoreEffects are(drawState);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000141
142 GrColor color = drawState->getColor();
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000143
bsalomon49f085d2014-09-05 13:34:00 -0700144 set_vertex_attributes(drawState, SkToBool(localRect), color);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000145
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000146 AutoReleaseGeometry geo(this, 4, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000147 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700148 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000149 return;
150 }
151
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000152 // Go to device coords to allow batching across matrix changes
bsalomon01c8da12014-08-04 09:21:30 -0700153 SkMatrix matrix = drawState->getViewMatrix();
154
jvanverth@google.com39768252013-02-14 15:25:44 +0000155 // 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 +0000156 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
157 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000158 GrDrawState::AutoViewMatrixRestore avmr;
159 if (!avmr.setIdentity(drawState)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000160 return;
161 }
162
egdaniel7b3d5ee2014-08-28 05:41:14 -0700163 size_t vstride = drawState->getVertexStride();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000164
egdaniel7b3d5ee2014-08-28 05:41:14 -0700165 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
166 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000167
168 SkRect devBounds;
169 // since we already computed the dev verts, set the bounds hint. This will help us avoid
170 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700171 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000172
bsalomon49f085d2014-09-05 13:34:00 -0700173 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700174 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
175 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000176 coords->setRectFan(localRect->fLeft, localRect->fTop,
177 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700178 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700179 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700180 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000181 }
182 }
183
bsalomon62c447d2014-08-08 08:08:50 -0700184 static const int kColorOffset = sizeof(SkPoint);
185 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
186 for (int i = 0; i < 4; ++i) {
187 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700188 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000189 }
190
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000191 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000192 this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000193
194 // to ensure that stashing the drawState ptr is valid
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000195 SkASSERT(this->drawState() == drawState);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000196}
197
joshualitt2c93efe2014-11-06 12:57:13 -0800198int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info,
199 const GrClipMaskManager::ScissorState& scissorState) {
cdalton6819df32014-10-15 13:43:48 -0700200 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000201 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000202
bsalomon@google.com934c5702012-03-20 21:17:58 +0000203 const GeometrySrcState& geomSrc = this->getGeomSrc();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000204 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com934c5702012-03-20 21:17:58 +0000205
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000206 // we only attempt to concat the case when reserved verts are used with a client-specified index
207 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
208 // between draws.
209 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
210 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
211 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000212 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000213 // Check if there is a draw info that is compatible that uses the same VB from the pool and
214 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700215 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000216 return 0;
217 }
218
cdalton6819df32014-10-15 13:43:48 -0700219 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000220 GeometryPoolState& poolState = fGeoPoolStateStack.back();
221 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
222
cdalton6819df32014-10-15 13:43:48 -0700223 if (!draw->fInfo.isInstanced() ||
224 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
225 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomonb3e3a952014-09-19 11:10:40 -0700226 draw->vertexBuffer() != vertexBuffer ||
joshualitt2c93efe2014-11-06 12:57:13 -0800227 draw->indexBuffer() != geomSrc.fIndexBuffer ||
228 draw->fScissorState != scissorState) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000229 return 0;
230 }
231 // info does not yet account for the offset from the start of the pool's VB while the previous
232 // draw record does.
233 int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
cdalton6819df32014-10-15 13:43:48 -0700234 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != adjustedStartVertex) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000235 return 0;
236 }
237
cdalton6819df32014-10-15 13:43:48 -0700238 SkASSERT(poolState.fPoolStartVertex == draw->fInfo.startVertex() + draw->fInfo.vertexCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000239
240 // how many instances can be concat'ed onto draw given the size of the index buffer
241 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700242 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000243 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000244
245 // update the amount of reserved vertex data actually referenced in draws
skia.committer@gmail.comae683922013-02-06 07:01:54 +0000246 size_t vertexBytes = instancesToConcat * info.verticesPerInstance() *
egdaniel7b3d5ee2014-08-28 05:41:14 -0700247 drawState.getVertexStride();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000248 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000249
cdalton6819df32014-10-15 13:43:48 -0700250 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000251
252 // update last fGpuCmdMarkers to include any additional trace markers that have been added
253 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700254 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000255 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
256 } else {
257 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700258 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000259 }
260 }
261
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000262 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000263}
264
joshualitt2c93efe2014-11-06 12:57:13 -0800265void GrInOrderDrawBuffer::onDraw(const DrawInfo& info,
266 const GrClipMaskManager::ScissorState& scissorState) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000267 GeometryPoolState& poolState = fGeoPoolStateStack.back();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000268 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000269
joshualittd53a8272014-11-10 16:03:14 -0800270 this->recordStateIfNecessary(GrGpu::PrimTypeToDrawType(info.primitiveType()),
271 info.getDstCopy());
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000272
bsalomonb3e3a952014-09-19 11:10:40 -0700273 const GrVertexBuffer* vb;
274 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
275 vb = this->getGeomSrc().fVertexBuffer;
276 } else {
277 vb = poolState.fPoolVertexBuffer;
278 }
279
280 const GrIndexBuffer* ib = NULL;
281 if (info.isIndexed()) {
282 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
283 ib = this->getGeomSrc().fIndexBuffer;
284 } else {
285 ib = poolState.fPoolIndexBuffer;
286 }
287 }
288
289 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000290 if (info.isInstanced()) {
joshualitt2c93efe2014-11-06 12:57:13 -0800291 int instancesConcated = this->concatInstancedDraw(info, scissorState);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000292 if (info.instanceCount() > instancesConcated) {
joshualitt2c93efe2014-11-06 12:57:13 -0800293 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, scissorState, vb, ib));
cdalton6819df32014-10-15 13:43:48 -0700294 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000295 } else {
296 return;
297 }
298 } else {
joshualitt2c93efe2014-11-06 12:57:13 -0800299 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, scissorState, vb, ib));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000300 }
cdalton6819df32014-10-15 13:43:48 -0700301 this->recordTraceMarkersIfNecessary();
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000302
bsalomonb3e3a952014-09-19 11:10:40 -0700303 // Adjust the starting vertex and index when we are using reserved or array sources to
304 // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
305 if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
306 size_t bytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexStride();
307 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700308 draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +0000309 }
bsalomonb3e3a952014-09-19 11:10:40 -0700310
311 if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) {
312 size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
313 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700314 draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000315 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000316}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000317
joshualitt2c93efe2014-11-06 12:57:13 -0800318void GrInOrderDrawBuffer::onStencilPath(const GrPath* path,
319 const GrClipMaskManager::ScissorState& scissorState,
320 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000321 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualittd53a8272014-11-10 16:03:14 -0800322 this->recordStateIfNecessary(GrGpu::kStencilPath_DrawType, NULL);
cdalton6819df32014-10-15 13:43:48 -0700323 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800324 sp->fScissorState = scissorState;
325 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700326 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000327}
328
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000329void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800330 const GrClipMaskManager::ScissorState& scissorState,
331 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700332 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000333 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualittd53a8272014-11-10 16:03:14 -0800334 this->recordStateIfNecessary(GrGpu::kDrawPath_DrawType, dstCopy);
cdalton6819df32014-10-15 13:43:48 -0700335 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
bsalomon49f085d2014-09-05 13:34:00 -0700336 if (dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700337 dp->fDstCopy = *dstCopy;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000338 }
joshualitt2c93efe2014-11-06 12:57:13 -0800339 dp->fScissorState = scissorState;
340 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700341 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000342}
343
cdaltonb85a0aa2014-07-21 15:32:44 -0700344void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
joshualitt2c93efe2014-11-06 12:57:13 -0800345 const uint32_t indices[],
346 int count,
347 const float transforms[],
348 PathTransformType transformsType,
349 const GrClipMaskManager::ScissorState& scissorState,
350 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700351 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700352 SkASSERT(pathRange);
353 SkASSERT(indices);
354 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000355
joshualittd53a8272014-11-10 16:03:14 -0800356 this->recordStateIfNecessary(GrGpu::kDrawPaths_DrawType, dstCopy);
cdalton6819df32014-10-15 13:43:48 -0700357
cdalton3fc6a2f2014-11-13 11:54:20 -0800358 uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
359 float* savedTransforms = fPathTransformBuffer.append(count *
360 GrPathRendering::PathTransformSize(transformsType), transforms);
cdalton6819df32014-10-15 13:43:48 -0700361
cdalton3fc6a2f2014-11-13 11:54:20 -0800362 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
363 // The previous command was also DrawPaths. Try to collapse this call into the one
364 // before. Note that stencilling all the paths at once, then covering, may not be
365 // equivalent to two separate draw calls if there is overlap. Blending won't work,
366 // and the combined calls may also cancel each other's winding numbers in some
367 // places. For now the winding numbers are only an issue if the fill is even/odd,
368 // because DrawPaths is currently only used for glyphs, and glyphs in the same
369 // font tend to all wind in the same direction.
370 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
371 if (pathRange == previous->pathRange() &&
372 transformsType == previous->fTransformsType &&
373 scissorState == previous->fScissorState &&
374 stencilSettings == previous->fStencilSettings &&
375 path_fill_type_is_winding(stencilSettings) &&
376 !this->getDrawState().willBlendWithDst()) {
377 // Fold this DrawPaths call into the one previous.
378 previous->fCount += count;
379 return;
380 }
381 }
382
383 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
384 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700385 dp->fCount = count;
cdalton3fc6a2f2014-11-13 11:54:20 -0800386 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700387 dp->fTransformsType = transformsType;
joshualitt2c93efe2014-11-06 12:57:13 -0800388 dp->fScissorState = scissorState;
389 dp->fStencilSettings = stencilSettings;
bsalomon49f085d2014-09-05 13:34:00 -0700390 if (dstCopy) {
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000391 dp->fDstCopy = *dstCopy;
392 }
cdalton6819df32014-10-15 13:43:48 -0700393
394 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000395}
396
bsalomon63b21962014-11-05 07:05:34 -0800397void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
398 bool canIgnoreRect, GrRenderTarget* renderTarget) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000399 SkIRect r;
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000400 if (NULL == renderTarget) {
401 renderTarget = this->drawState()->getRenderTarget();
bsalomon49f085d2014-09-05 13:34:00 -0700402 SkASSERT(renderTarget);
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000403 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000404 if (NULL == rect) {
405 // We could do something smart and remove previous draws and clears to
406 // the current render target. If we get that smart we have to make sure
407 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000408 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000409 rect = &r;
410 }
cdalton6819df32014-10-15 13:43:48 -0700411 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000412 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000413 clr->fColor = color;
414 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000415 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700416 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000417}
418
joshualitt6db519c2014-10-29 08:48:18 -0700419void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
420 bool insideClip,
421 GrRenderTarget* renderTarget) {
422 if (NULL == renderTarget) {
423 renderTarget = this->drawState()->getRenderTarget();
424 SkASSERT(renderTarget);
425 }
426 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
427 clr->fRect = rect;
428 clr->fInsideClip = insideClip;
429 this->recordTraceMarkersIfNecessary();
430}
431
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000432void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800433 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000434 if (!this->caps()->discardRenderTargetSupport()) {
435 return;
436 }
cdalton6819df32014-10-15 13:43:48 -0700437 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000438 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700439 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000440}
441
reed@google.comac10a2d2010-12-22 21:39:39 +0000442void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000443 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000444 this->resetVertexSource();
445 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700446
447 fCmdBuffer.reset();
448 fLastState = NULL;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000449 fVertexPool.reset();
450 fIndexPool.reset();
cdalton3fc6a2f2014-11-13 11:54:20 -0800451 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
452 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000453 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000454}
455
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000456void GrInOrderDrawBuffer::flush() {
457 if (fFlushing) {
458 return;
459 }
460
jvanverth8e80d172014-06-19 12:01:10 -0700461 this->getContext()->getFontCache()->updateTextures();
462
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000463 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
464 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000465
cdalton6819df32014-10-15 13:43:48 -0700466 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000467 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000468 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000469
470 GrAutoTRestore<bool> flushRestore(&fFlushing);
471 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000472
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000473 fVertexPool.unmap();
474 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000475
cdalton6819df32014-10-15 13:43:48 -0700476 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000477
cdalton6819df32014-10-15 13:43:48 -0700478 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700479 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700480
joshualittd53a8272014-11-10 16:03:14 -0800481 // Gpu no longer maintains the current drawstate, so we track the setstate calls below.
482 // NOTE: we always record a new drawstate at flush boundaries
483 SkAutoTUnref<const GrOptDrawState> currentOptState;
484
cdalton6819df32014-10-15 13:43:48 -0700485 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000486 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700487 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700488 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700489 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000490 newMarker.fMarker = traceString.c_str();
491 fDstGpu->addGpuTraceMarker(&newMarker);
492 ++currCmdMarker;
493 }
cdalton6819df32014-10-15 13:43:48 -0700494
joshualittd53a8272014-11-10 16:03:14 -0800495 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
496 const SetState* ss = reinterpret_cast<const SetState*>(iter.get());
497 currentOptState.reset(GrOptDrawState::Create(ss->fState,
498 fDstGpu,
499 &ss->fDstCopy,
500 ss->fDrawType));
501 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800502 iter->execute(this, currentOptState.get());
joshualittd53a8272014-11-10 16:03:14 -0800503 }
cdalton6819df32014-10-15 13:43:48 -0700504
505 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000506 fDstGpu->removeGpuTraceMarker(&newMarker);
507 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000508 }
mtkleinf439c772014-10-14 14:29:30 -0700509
cdalton6819df32014-10-15 13:43:48 -0700510 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000511 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000512
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000513 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000514 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000515}
516
cdalton3fc6a2f2014-11-13 11:54:20 -0800517void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800518 if (!optState) {
519 return;
520 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800521 GrGpu* dstGpu = buf->fDstGpu;
522 dstGpu->setVertexSourceToBuffer(this->vertexBuffer(), optState->getVertexStride());
cdalton6819df32014-10-15 13:43:48 -0700523 if (fInfo.isIndexed()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800524 dstGpu->setIndexSourceToBuffer(this->indexBuffer());
cdalton6819df32014-10-15 13:43:48 -0700525 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800526 dstGpu->draw(*optState, fInfo, fScissorState);
cdalton6819df32014-10-15 13:43:48 -0700527}
528
cdalton3fc6a2f2014-11-13 11:54:20 -0800529void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
530 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800531 if (!optState) {
532 return;
533 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800534 buf->fDstGpu->stencilPath(*optState, this->path(), fScissorState, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700535}
536
cdalton3fc6a2f2014-11-13 11:54:20 -0800537void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
538 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800539 if (!optState) {
540 return;
541 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800542 buf->fDstGpu->drawPath(*optState, this->path(), fScissorState, fStencilSettings,
543 fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700544}
545
cdalton3fc6a2f2014-11-13 11:54:20 -0800546void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
547 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800548 if (!optState) {
549 return;
550 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800551 buf->fDstGpu->drawPaths(*optState, this->pathRange(),
552 &buf->fPathIndexBuffer[fIndicesLocation], fCount,
553 &buf->fPathTransformBuffer[fTransformsLocation], fTransformsType,
554 fScissorState, fStencilSettings, fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700555}
556
cdalton3fc6a2f2014-11-13 11:54:20 -0800557void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700558}
559
cdalton3fc6a2f2014-11-13 11:54:20 -0800560void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700561 if (GrColor_ILLEGAL == fColor) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800562 buf->fDstGpu->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700563 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800564 buf->fDstGpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700565 }
566}
567
cdalton3fc6a2f2014-11-13 11:54:20 -0800568void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
569 const GrOptDrawState*) {
570 buf->fDstGpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700571}
572
cdalton3fc6a2f2014-11-13 11:54:20 -0800573void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
574 buf->fDstGpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700575}
576
joshualitta7024152014-11-03 14:16:35 -0800577bool GrInOrderDrawBuffer::copySurface(GrSurface* dst,
578 GrSurface* src,
579 const SkIRect& srcRect,
580 const SkIPoint& dstPoint) {
bsalomon@google.com116ad842013-04-09 15:38:19 +0000581 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700582 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000583 cs->fSrcRect = srcRect;
584 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700585 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000586 return true;
joshualitta7024152014-11-03 14:16:35 -0800587 } else if (GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) {
588 GrDrawTarget::copySurface(dst, src, srcRect, dstPoint);
589 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000590 } else {
591 return false;
592 }
593}
594
joshualitta7024152014-11-03 14:16:35 -0800595bool GrInOrderDrawBuffer::canCopySurface(GrSurface* dst,
596 GrSurface* src,
597 const SkIRect& srcRect,
598 const SkIPoint& dstPoint) {
599 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint) ||
600 GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000601}
602
bsalomonf2703d82014-10-28 14:33:06 -0700603void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000604 fDstGpu->initCopySurfaceDstDesc(src, desc);
605}
606
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000607void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
608 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000609 // We use geometryHints() to know whether to flush the draw buffer. We
610 // can't flush if we are inside an unbalanced pushGeometrySource.
611 // Moreover, flushing blows away vertex and index data that was
612 // previously reserved. So if the vertex or index data is pulled from
613 // reserved space and won't be released by this request then we can't
614 // flush.
615 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000616
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000617 bool unreleasedVertexSpace =
618 !vertexCount &&
619 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000620
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000621 bool unreleasedIndexSpace =
622 !indexCount &&
623 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000624
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000625 int vcount = vertexCount;
626 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000627
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000628 if (!insideGeoPush &&
629 !unreleasedVertexSpace &&
630 !unreleasedIndexSpace &&
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000631 this->geometryHints(&vcount, &icount)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000632 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000633 }
634}
635
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000636bool GrInOrderDrawBuffer::geometryHints(int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000637 int* indexCount) const {
638 // we will recommend a flush if the data could fit in a single
639 // preallocated buffer but none are left and it can't fit
640 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000641 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700642 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000643 int32_t currIndices = fIndexPool.currentBufferIndices();
644 if (*indexCount > currIndices &&
645 (!fIndexPool.preallocatedBuffersRemaining() &&
646 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
647
648 flush = true;
649 }
650 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000651 }
bsalomon49f085d2014-09-05 13:34:00 -0700652 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700653 size_t vertexStride = this->getDrawState().getVertexStride();
654 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000655 if (*vertexCount > currVertices &&
656 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700657 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000658
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000659 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000660 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000661 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000662 }
663 return flush;
664}
665
jvanverth@google.coma6338982013-01-31 21:34:25 +0000666bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000667 int vertexCount,
668 void** vertices) {
669 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000670 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700671 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000672 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000673
jvanverth@google.coma6338982013-01-31 21:34:25 +0000674 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000675 vertexCount,
676 &poolState.fPoolVertexBuffer,
677 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700678 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000679}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000680
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000681bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
682 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000683 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700684 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000685 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000686
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000687 *indices = fIndexPool.makeSpace(indexCount,
688 &poolState.fPoolIndexBuffer,
689 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700690 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000691}
692
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000693void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
694 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000695 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000696
697 // If we get a release vertex space call then our current source should either be reserved
698 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800699 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000700
701 // When the caller reserved vertex buffer space we gave it back a pointer
702 // provided by the vertex buffer pool. At each draw we tracked the largest
703 // offset into the pool's pointer that was referenced. Now we return to the
704 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000705 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
joshualittd53a8272014-11-10 16:03:14 -0800706 fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000707 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000708 poolState.fPoolVertexBuffer = NULL;
709 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000710}
711
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000712void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
713 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000714 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000715
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000716 // If we get a release index space call then our current source should either be reserved
717 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800718 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000719
720 // Similar to releaseReservedVertexSpace we return any unused portion at
721 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000722 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
723 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
724 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000725 poolState.fPoolIndexBuffer = NULL;
726 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000727}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000728
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000729void GrInOrderDrawBuffer::geometrySourceWillPush() {
730 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
731 poolState.fUsedPoolVertexBytes = 0;
732 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000733#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000734 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
735 poolState.fPoolStartVertex = ~0;
736 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
737 poolState.fPoolStartIndex = ~0;
738#endif
739}
740
bsalomonb3e3a952014-09-19 11:10:40 -0700741void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000742 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000743 fGeoPoolStateStack.pop_back();
744 GeometryPoolState& poolState = fGeoPoolStateStack.back();
745 // we have to assume that any slack we had in our vertex/index data
746 // is now unreleasable because data may have been appended later in the
747 // pool.
joshualittd1aa8ff2014-11-04 07:47:55 -0800748 if (kReserved_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000749 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000750 }
joshualittd1aa8ff2014-11-04 07:47:55 -0800751 if (kReserved_GeometrySrcType == restoredState.fIndexSrc) {
joshualittd53a8272014-11-10 16:03:14 -0800752 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * restoredState.fIndexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000753 }
754}
755
joshualittd53a8272014-11-10 16:03:14 -0800756void GrInOrderDrawBuffer::recordStateIfNecessary(GrGpu::DrawType drawType,
757 const GrDeviceCoordTexture* dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700758 if (!fLastState) {
759 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (this->getDrawState()));
760 fLastState = &ss->fState;
joshualittd53a8272014-11-10 16:03:14 -0800761 if (dstCopy) {
762 ss->fDstCopy = *dstCopy;
763 }
764 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700765 this->convertDrawStateToPendingExec(fLastState);
766 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700767 return;
768 }
769 const GrDrawState& curr = this->getDrawState();
cdalton6819df32014-10-15 13:43:48 -0700770 switch (GrDrawState::CombineIfPossible(*fLastState, curr, *this->caps())) {
joshualittd53a8272014-11-10 16:03:14 -0800771 case GrDrawState::kIncompatible_CombinedState: {
772 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (curr));
773 fLastState = &ss->fState;
774 if (dstCopy) {
775 ss->fDstCopy = *dstCopy;
776 }
777 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700778 this->convertDrawStateToPendingExec(fLastState);
779 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700780 break;
joshualittd53a8272014-11-10 16:03:14 -0800781 }
bsalomon838f62d2014-08-05 07:15:57 -0700782 case GrDrawState::kA_CombinedState:
783 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA.
784 break;
785 case GrDrawState::kB_CombinedState:
bsalomon2a9ca782014-09-05 14:27:43 -0700786 // prev has already been converted to pending execution. That is a one-way ticket.
cdalton6819df32014-10-15 13:43:48 -0700787 // So here we just destruct the previous state and reinit with a new copy of curr.
788 // Note that this goes away when we move GrIODB over to taking optimized snapshots
789 // of draw states.
790 fLastState->~GrDrawState();
791 SkNEW_PLACEMENT_ARGS(fLastState, GrDrawState, (curr));
792 this->convertDrawStateToPendingExec(fLastState);
bsalomon838f62d2014-08-05 07:15:57 -0700793 break;
794 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000795}
796
cdalton6819df32014-10-15 13:43:48 -0700797void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
798 SkASSERT(!fCmdBuffer.empty());
799 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700800 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
801 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700802 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700803 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700804 }
mtklein07894c42014-10-13 14:00:42 -0700805}