blob: 38994f1d35eec84b4a784227fba6614c56cda2af [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"
bsalomon@google.comc26d94f2013-03-25 18:19:00 +000011#include "GrDrawTargetCaps.h"
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000012#include "GrGpu.h"
joshualittd53a8272014-11-10 16:03:14 -080013#include "GrOptDrawState.h"
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000014#include "GrTemplates.h"
joshualittd53a8272014-11-10 16:03:14 -080015#include "GrTextStrike.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)
joshualitt6db519c2014-10-29 08:48:18 -070021 : INHERITED(gpu->getContext())
cdalton6819df32014-10-15 13:43:48 -070022 , fCmdBuffer(kCmdBufferInitialSizeInBytes)
23 , fLastState(NULL)
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000024 , fDstGpu(gpu)
robertphillips@google.com69705572012-03-21 19:46:50 +000025 , fVertexPool(*vertexPool)
26 , fIndexPool(*indexPool)
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +000027 , fFlushing(false)
28 , fDrawID(0) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000029
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000030 fDstGpu->ref();
bsalomon@google.combcce8922013-03-25 15:38:39 +000031 fCaps.reset(SkRef(fDstGpu->caps()));
bsalomon@google.com18c9c192011-09-22 21:01:31 +000032
bsalomon49f085d2014-09-05 13:34:00 -070033 SkASSERT(vertexPool);
34 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000035
cdalton3fc6a2f2014-11-13 11:54:20 -080036 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
37 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
38
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000039 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
40 poolState.fUsedPoolVertexBytes = 0;
41 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000042#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000043 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
44 poolState.fPoolStartVertex = ~0;
45 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
46 poolState.fPoolStartIndex = ~0;
47#endif
bsalomon@google.coma4f6b102012-06-26 21:04:22 +000048 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000049}
50
51GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000052 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000053 // This must be called by before the GrDrawTarget destructor
54 this->releaseGeometry();
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000055 fDstGpu->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +000056}
57
bsalomon@google.com934c5702012-03-20 21:17:58 +000058////////////////////////////////////////////////////////////////////////////////
59
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000060namespace {
61void get_vertex_bounds(const void* vertices,
62 size_t vertexSize,
63 int vertexCount,
64 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000065 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000066 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000067 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000068 bounds->fLeft = bounds->fRight = point->fX;
69 bounds->fTop = bounds->fBottom = point->fY;
70 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000071 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000072 bounds->growToInclude(point->fX, point->fY);
73 }
74}
bsalomon@google.com934c5702012-03-20 21:17:58 +000075}
76
robertphillips@google.com42903302013-04-20 12:26:07 +000077
78namespace {
79
bsalomon62c447d2014-08-08 08:08:50 -070080extern const GrVertexAttrib kRectAttribs[] = {
81 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
82 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
83 {kVec2f_GrVertexAttribType, sizeof(SkPoint)+sizeof(GrColor), kLocalCoord_GrVertexAttribBinding},
robertphillips@google.com42903302013-04-20 12:26:07 +000084};
robertphillips@google.com42903302013-04-20 12:26:07 +000085}
86
bsalomon62c447d2014-08-08 08:08:50 -070087/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
88 have explicit local coords and sometimes not. We *could* always provide explicit local coords
89 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
90 haven't seen a use case which frequently switches between local rect and no local rect draws.
91
92 The color param is used to determine whether the opaque hint can be set on the draw state.
93 The caller must populate the vertex colors itself.
94
95 The vertex attrib order is always pos, color, [local coords].
96 */
97static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
98 if (hasLocalCoords) {
egdaniel7b3d5ee2014-08-28 05:41:14 -070099 drawState->setVertexAttribs<kRectAttribs>(3, 2 * sizeof(SkPoint) + sizeof(SkColor));
bsalomon62c447d2014-08-08 08:08:50 -0700100 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700101 drawState->setVertexAttribs<kRectAttribs>(2, sizeof(SkPoint) + sizeof(SkColor));
bsalomon62c447d2014-08-08 08:08:50 -0700102 }
103 if (0xFF == GrColorUnpackA(color)) {
104 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
105 }
106}
robertphillips@google.com42903302013-04-20 12:26:07 +0000107
cdalton3fc6a2f2014-11-13 11:54:20 -0800108static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
109 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
110 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
111 if (isWinding) {
112 // Double check that it is in fact winding.
113 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
114 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
115 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
116 SkASSERT(!pathStencilSettings.isTwoSided());
117 }
118 return isWinding;
119}
120
121template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
122 // Assume the next time this buffer fills up it will use approximately the same amount
123 // of space as last time. Only resize if we're using less than a third of the
124 // allocated space, and leave enough for 50% growth over last time.
125 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
126 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
127 buffer->reset();
128 buffer->setReserve(reserve);
129 } else {
130 buffer->rewind();
131 }
132}
133
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000134enum {
135 kTraceCmdBit = 0x80,
136 kCmdMask = 0x7f,
137};
138
bsalomon62c447d2014-08-08 08:08:50 -0700139static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000140
bsalomon62c447d2014-08-08 08:08:50 -0700141static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000142
bsalomon62c447d2014-08-08 08:08:50 -0700143static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000144
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000145void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000146 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000147 const SkMatrix* localMatrix) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000148 GrDrawState* drawState = this->drawState();
149
150 GrColor color = drawState->getColor();
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000151
bsalomon49f085d2014-09-05 13:34:00 -0700152 set_vertex_attributes(drawState, SkToBool(localRect), color);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000153
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000154 AutoReleaseGeometry geo(this, 4, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000155 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700156 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000157 return;
158 }
159
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000160 // Go to device coords to allow batching across matrix changes
bsalomon01c8da12014-08-04 09:21:30 -0700161 SkMatrix matrix = drawState->getViewMatrix();
162
jvanverth@google.com39768252013-02-14 15:25:44 +0000163 // 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 +0000164 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
165 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000166 GrDrawState::AutoViewMatrixRestore avmr;
167 if (!avmr.setIdentity(drawState)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000168 return;
169 }
170
egdaniel7b3d5ee2014-08-28 05:41:14 -0700171 size_t vstride = drawState->getVertexStride();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000172
egdaniel7b3d5ee2014-08-28 05:41:14 -0700173 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
174 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000175
176 SkRect devBounds;
177 // since we already computed the dev verts, set the bounds hint. This will help us avoid
178 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700179 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000180
bsalomon49f085d2014-09-05 13:34:00 -0700181 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700182 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
183 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000184 coords->setRectFan(localRect->fLeft, localRect->fTop,
185 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700186 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700187 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700188 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000189 }
190 }
191
bsalomon62c447d2014-08-08 08:08:50 -0700192 static const int kColorOffset = sizeof(SkPoint);
193 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
194 for (int i = 0; i < 4; ++i) {
195 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700196 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000197 }
198
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000199 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000200 this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000201
202 // to ensure that stashing the drawState ptr is valid
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000203 SkASSERT(this->drawState() == drawState);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000204}
205
joshualitt2c93efe2014-11-06 12:57:13 -0800206int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info,
207 const GrClipMaskManager::ScissorState& scissorState) {
cdalton6819df32014-10-15 13:43:48 -0700208 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000209 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000210
bsalomon@google.com934c5702012-03-20 21:17:58 +0000211 const GeometrySrcState& geomSrc = this->getGeomSrc();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000212 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com934c5702012-03-20 21:17:58 +0000213
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000214 // we only attempt to concat the case when reserved verts are used with a client-specified index
215 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
216 // between draws.
217 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
218 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
219 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000220 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000221 // Check if there is a draw info that is compatible that uses the same VB from the pool and
222 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700223 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000224 return 0;
225 }
226
cdalton6819df32014-10-15 13:43:48 -0700227 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000228 GeometryPoolState& poolState = fGeoPoolStateStack.back();
229 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
230
cdalton6819df32014-10-15 13:43:48 -0700231 if (!draw->fInfo.isInstanced() ||
232 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
233 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomonb3e3a952014-09-19 11:10:40 -0700234 draw->vertexBuffer() != vertexBuffer ||
joshualitt2c93efe2014-11-06 12:57:13 -0800235 draw->indexBuffer() != geomSrc.fIndexBuffer ||
236 draw->fScissorState != scissorState) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000237 return 0;
238 }
239 // info does not yet account for the offset from the start of the pool's VB while the previous
240 // draw record does.
241 int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
cdalton6819df32014-10-15 13:43:48 -0700242 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != adjustedStartVertex) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000243 return 0;
244 }
245
cdalton6819df32014-10-15 13:43:48 -0700246 SkASSERT(poolState.fPoolStartVertex == draw->fInfo.startVertex() + draw->fInfo.vertexCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000247
248 // how many instances can be concat'ed onto draw given the size of the index buffer
249 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700250 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000251 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000252
253 // update the amount of reserved vertex data actually referenced in draws
skia.committer@gmail.comae683922013-02-06 07:01:54 +0000254 size_t vertexBytes = instancesToConcat * info.verticesPerInstance() *
egdaniel7b3d5ee2014-08-28 05:41:14 -0700255 drawState.getVertexStride();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000256 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000257
cdalton6819df32014-10-15 13:43:48 -0700258 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000259
260 // update last fGpuCmdMarkers to include any additional trace markers that have been added
261 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700262 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000263 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
264 } else {
265 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700266 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000267 }
268 }
269
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000270 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000271}
272
joshualitt2c93efe2014-11-06 12:57:13 -0800273void GrInOrderDrawBuffer::onDraw(const DrawInfo& info,
274 const GrClipMaskManager::ScissorState& scissorState) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000275
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000276 GeometryPoolState& poolState = fGeoPoolStateStack.back();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000277 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000278
joshualittd53a8272014-11-10 16:03:14 -0800279 this->recordStateIfNecessary(GrGpu::PrimTypeToDrawType(info.primitiveType()),
280 info.getDstCopy());
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000281
bsalomonb3e3a952014-09-19 11:10:40 -0700282 const GrVertexBuffer* vb;
283 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
284 vb = this->getGeomSrc().fVertexBuffer;
285 } else {
286 vb = poolState.fPoolVertexBuffer;
287 }
288
289 const GrIndexBuffer* ib = NULL;
290 if (info.isIndexed()) {
291 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
292 ib = this->getGeomSrc().fIndexBuffer;
293 } else {
294 ib = poolState.fPoolIndexBuffer;
295 }
296 }
297
298 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000299 if (info.isInstanced()) {
joshualitt2c93efe2014-11-06 12:57:13 -0800300 int instancesConcated = this->concatInstancedDraw(info, scissorState);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000301 if (info.instanceCount() > instancesConcated) {
joshualitt2c93efe2014-11-06 12:57:13 -0800302 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, scissorState, vb, ib));
cdalton6819df32014-10-15 13:43:48 -0700303 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000304 } else {
305 return;
306 }
307 } else {
joshualitt2c93efe2014-11-06 12:57:13 -0800308 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, scissorState, vb, ib));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000309 }
cdalton6819df32014-10-15 13:43:48 -0700310 this->recordTraceMarkersIfNecessary();
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000311
bsalomonb3e3a952014-09-19 11:10:40 -0700312 // Adjust the starting vertex and index when we are using reserved or array sources to
313 // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
314 if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
315 size_t bytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexStride();
316 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700317 draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +0000318 }
bsalomonb3e3a952014-09-19 11:10:40 -0700319
320 if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) {
321 size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
322 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700323 draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000324 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000325}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000326
joshualitt2c93efe2014-11-06 12:57:13 -0800327void GrInOrderDrawBuffer::onStencilPath(const GrPath* path,
328 const GrClipMaskManager::ScissorState& scissorState,
329 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000330 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualittd53a8272014-11-10 16:03:14 -0800331 this->recordStateIfNecessary(GrGpu::kStencilPath_DrawType, NULL);
cdalton6819df32014-10-15 13:43:48 -0700332 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800333 sp->fScissorState = scissorState;
334 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700335 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000336}
337
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000338void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800339 const GrClipMaskManager::ScissorState& scissorState,
340 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700341 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000342 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualittd53a8272014-11-10 16:03:14 -0800343 this->recordStateIfNecessary(GrGpu::kDrawPath_DrawType, dstCopy);
cdalton6819df32014-10-15 13:43:48 -0700344 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
bsalomon49f085d2014-09-05 13:34:00 -0700345 if (dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700346 dp->fDstCopy = *dstCopy;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000347 }
joshualitt2c93efe2014-11-06 12:57:13 -0800348 dp->fScissorState = scissorState;
349 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700350 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000351}
352
cdaltonb85a0aa2014-07-21 15:32:44 -0700353void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
joshualitt2c93efe2014-11-06 12:57:13 -0800354 const uint32_t indices[],
355 int count,
356 const float transforms[],
357 PathTransformType transformsType,
358 const GrClipMaskManager::ScissorState& scissorState,
359 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700360 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700361 SkASSERT(pathRange);
362 SkASSERT(indices);
363 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000364
joshualittd53a8272014-11-10 16:03:14 -0800365 this->recordStateIfNecessary(GrGpu::kDrawPaths_DrawType, dstCopy);
cdalton6819df32014-10-15 13:43:48 -0700366
cdalton3fc6a2f2014-11-13 11:54:20 -0800367 uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
368 float* savedTransforms = fPathTransformBuffer.append(count *
369 GrPathRendering::PathTransformSize(transformsType), transforms);
cdalton6819df32014-10-15 13:43:48 -0700370
cdalton3fc6a2f2014-11-13 11:54:20 -0800371 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
372 // The previous command was also DrawPaths. Try to collapse this call into the one
373 // before. Note that stencilling all the paths at once, then covering, may not be
374 // equivalent to two separate draw calls if there is overlap. Blending won't work,
375 // and the combined calls may also cancel each other's winding numbers in some
376 // places. For now the winding numbers are only an issue if the fill is even/odd,
377 // because DrawPaths is currently only used for glyphs, and glyphs in the same
378 // font tend to all wind in the same direction.
379 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
380 if (pathRange == previous->pathRange() &&
381 transformsType == previous->fTransformsType &&
382 scissorState == previous->fScissorState &&
383 stencilSettings == previous->fStencilSettings &&
384 path_fill_type_is_winding(stencilSettings) &&
385 !this->getDrawState().willBlendWithDst()) {
386 // Fold this DrawPaths call into the one previous.
387 previous->fCount += count;
388 return;
389 }
390 }
391
392 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
393 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700394 dp->fCount = count;
cdalton3fc6a2f2014-11-13 11:54:20 -0800395 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700396 dp->fTransformsType = transformsType;
joshualitt2c93efe2014-11-06 12:57:13 -0800397 dp->fScissorState = scissorState;
398 dp->fStencilSettings = stencilSettings;
bsalomon49f085d2014-09-05 13:34:00 -0700399 if (dstCopy) {
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000400 dp->fDstCopy = *dstCopy;
401 }
cdalton6819df32014-10-15 13:43:48 -0700402
403 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000404}
405
bsalomon63b21962014-11-05 07:05:34 -0800406void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
407 bool canIgnoreRect, GrRenderTarget* renderTarget) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000408 SkIRect r;
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000409 if (NULL == renderTarget) {
410 renderTarget = this->drawState()->getRenderTarget();
bsalomon49f085d2014-09-05 13:34:00 -0700411 SkASSERT(renderTarget);
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000412 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000413 if (NULL == rect) {
414 // We could do something smart and remove previous draws and clears to
415 // the current render target. If we get that smart we have to make sure
416 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000417 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000418 rect = &r;
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 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000422 clr->fColor = color;
423 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000424 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700425 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000426}
427
joshualitt6db519c2014-10-29 08:48:18 -0700428void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
429 bool insideClip,
430 GrRenderTarget* renderTarget) {
431 if (NULL == renderTarget) {
432 renderTarget = this->drawState()->getRenderTarget();
433 SkASSERT(renderTarget);
434 }
435 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
436 clr->fRect = rect;
437 clr->fInsideClip = insideClip;
438 this->recordTraceMarkersIfNecessary();
439}
440
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000441void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800442 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000443 if (!this->caps()->discardRenderTargetSupport()) {
444 return;
445 }
cdalton6819df32014-10-15 13:43:48 -0700446 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000447 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700448 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000449}
450
reed@google.comac10a2d2010-12-22 21:39:39 +0000451void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000452 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000453 this->resetVertexSource();
454 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700455
456 fCmdBuffer.reset();
457 fLastState = NULL;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000458 fVertexPool.reset();
459 fIndexPool.reset();
cdalton3fc6a2f2014-11-13 11:54:20 -0800460 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
461 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000462 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000463}
464
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000465void GrInOrderDrawBuffer::flush() {
466 if (fFlushing) {
467 return;
468 }
469
jvanverth8e80d172014-06-19 12:01:10 -0700470 this->getContext()->getFontCache()->updateTextures();
471
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000472 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
473 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000474
cdalton6819df32014-10-15 13:43:48 -0700475 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000476 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000477 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000478
479 GrAutoTRestore<bool> flushRestore(&fFlushing);
480 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000481
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000482 fVertexPool.unmap();
483 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000484
cdalton6819df32014-10-15 13:43:48 -0700485 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000486
cdalton6819df32014-10-15 13:43:48 -0700487 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700488 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700489
joshualittd53a8272014-11-10 16:03:14 -0800490 // Gpu no longer maintains the current drawstate, so we track the setstate calls below.
491 // NOTE: we always record a new drawstate at flush boundaries
492 SkAutoTUnref<const GrOptDrawState> currentOptState;
493
cdalton6819df32014-10-15 13:43:48 -0700494 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000495 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700496 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700497 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700498 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000499 newMarker.fMarker = traceString.c_str();
500 fDstGpu->addGpuTraceMarker(&newMarker);
501 ++currCmdMarker;
502 }
cdalton6819df32014-10-15 13:43:48 -0700503
joshualittd53a8272014-11-10 16:03:14 -0800504 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
505 const SetState* ss = reinterpret_cast<const SetState*>(iter.get());
506 currentOptState.reset(GrOptDrawState::Create(ss->fState,
507 fDstGpu,
508 &ss->fDstCopy,
509 ss->fDrawType));
510 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800511 iter->execute(this, currentOptState.get());
joshualittd53a8272014-11-10 16:03:14 -0800512 }
cdalton6819df32014-10-15 13:43:48 -0700513
514 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000515 fDstGpu->removeGpuTraceMarker(&newMarker);
516 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000517 }
mtkleinf439c772014-10-14 14:29:30 -0700518
cdalton6819df32014-10-15 13:43:48 -0700519 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000520 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000521
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000522 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000523 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000524}
525
cdalton3fc6a2f2014-11-13 11:54:20 -0800526void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800527 if (!optState) {
528 return;
529 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800530 GrGpu* dstGpu = buf->fDstGpu;
531 dstGpu->setVertexSourceToBuffer(this->vertexBuffer(), optState->getVertexStride());
cdalton6819df32014-10-15 13:43:48 -0700532 if (fInfo.isIndexed()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800533 dstGpu->setIndexSourceToBuffer(this->indexBuffer());
cdalton6819df32014-10-15 13:43:48 -0700534 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800535 dstGpu->draw(*optState, fInfo, fScissorState);
cdalton6819df32014-10-15 13:43:48 -0700536}
537
cdalton3fc6a2f2014-11-13 11:54:20 -0800538void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
539 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800540 if (!optState) {
541 return;
542 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800543 buf->fDstGpu->stencilPath(*optState, this->path(), fScissorState, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700544}
545
cdalton3fc6a2f2014-11-13 11:54:20 -0800546void GrInOrderDrawBuffer::DrawPath::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->drawPath(*optState, this->path(), fScissorState, fStencilSettings,
552 fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700553}
554
cdalton3fc6a2f2014-11-13 11:54:20 -0800555void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
556 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800557 if (!optState) {
558 return;
559 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800560 buf->fDstGpu->drawPaths(*optState, this->pathRange(),
561 &buf->fPathIndexBuffer[fIndicesLocation], fCount,
562 &buf->fPathTransformBuffer[fTransformsLocation], fTransformsType,
563 fScissorState, fStencilSettings, fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700564}
565
cdalton3fc6a2f2014-11-13 11:54:20 -0800566void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700567}
568
cdalton3fc6a2f2014-11-13 11:54:20 -0800569void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700570 if (GrColor_ILLEGAL == fColor) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800571 buf->fDstGpu->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700572 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800573 buf->fDstGpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700574 }
575}
576
cdalton3fc6a2f2014-11-13 11:54:20 -0800577void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
578 const GrOptDrawState*) {
579 buf->fDstGpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700580}
581
cdalton3fc6a2f2014-11-13 11:54:20 -0800582void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
583 buf->fDstGpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700584}
585
joshualitta7024152014-11-03 14:16:35 -0800586bool GrInOrderDrawBuffer::copySurface(GrSurface* dst,
587 GrSurface* src,
588 const SkIRect& srcRect,
589 const SkIPoint& dstPoint) {
bsalomon@google.com116ad842013-04-09 15:38:19 +0000590 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700591 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000592 cs->fSrcRect = srcRect;
593 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700594 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000595 return true;
joshualitta7024152014-11-03 14:16:35 -0800596 } else if (GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) {
597 GrDrawTarget::copySurface(dst, src, srcRect, dstPoint);
598 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000599 } else {
600 return false;
601 }
602}
603
joshualitta7024152014-11-03 14:16:35 -0800604bool GrInOrderDrawBuffer::canCopySurface(GrSurface* dst,
605 GrSurface* src,
606 const SkIRect& srcRect,
607 const SkIPoint& dstPoint) {
608 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint) ||
609 GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000610}
611
bsalomonf2703d82014-10-28 14:33:06 -0700612void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000613 fDstGpu->initCopySurfaceDstDesc(src, desc);
614}
615
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000616void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
617 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000618 // We use geometryHints() to know whether to flush the draw buffer. We
619 // can't flush if we are inside an unbalanced pushGeometrySource.
620 // Moreover, flushing blows away vertex and index data that was
621 // previously reserved. So if the vertex or index data is pulled from
622 // reserved space and won't be released by this request then we can't
623 // flush.
624 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000625
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000626 bool unreleasedVertexSpace =
627 !vertexCount &&
628 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000629
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000630 bool unreleasedIndexSpace =
631 !indexCount &&
632 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000633
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000634 int vcount = vertexCount;
635 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000636
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000637 if (!insideGeoPush &&
638 !unreleasedVertexSpace &&
639 !unreleasedIndexSpace &&
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000640 this->geometryHints(&vcount, &icount)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000641 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000642 }
643}
644
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000645bool GrInOrderDrawBuffer::geometryHints(int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000646 int* indexCount) const {
647 // we will recommend a flush if the data could fit in a single
648 // preallocated buffer but none are left and it can't fit
649 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000650 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700651 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000652 int32_t currIndices = fIndexPool.currentBufferIndices();
653 if (*indexCount > currIndices &&
654 (!fIndexPool.preallocatedBuffersRemaining() &&
655 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
656
657 flush = true;
658 }
659 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000660 }
bsalomon49f085d2014-09-05 13:34:00 -0700661 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700662 size_t vertexStride = this->getDrawState().getVertexStride();
663 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000664 if (*vertexCount > currVertices &&
665 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700666 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000667
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000668 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000669 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000670 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000671 }
672 return flush;
673}
674
jvanverth@google.coma6338982013-01-31 21:34:25 +0000675bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000676 int vertexCount,
677 void** vertices) {
678 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000679 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700680 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000681 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000682
jvanverth@google.coma6338982013-01-31 21:34:25 +0000683 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000684 vertexCount,
685 &poolState.fPoolVertexBuffer,
686 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700687 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000688}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000689
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000690bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
691 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000692 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700693 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000694 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000695
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000696 *indices = fIndexPool.makeSpace(indexCount,
697 &poolState.fPoolIndexBuffer,
698 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700699 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000700}
701
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000702void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
703 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000704 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000705
706 // If we get a release vertex space call then our current source should either be reserved
707 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800708 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000709
710 // When the caller reserved vertex buffer space we gave it back a pointer
711 // provided by the vertex buffer pool. At each draw we tracked the largest
712 // offset into the pool's pointer that was referenced. Now we return to the
713 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000714 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
joshualittd53a8272014-11-10 16:03:14 -0800715 fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000716 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000717 poolState.fPoolVertexBuffer = NULL;
718 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000719}
720
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000721void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
722 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000723 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000724
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000725 // If we get a release index space call then our current source should either be reserved
726 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800727 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000728
729 // Similar to releaseReservedVertexSpace we return any unused portion at
730 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000731 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
732 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
733 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000734 poolState.fPoolIndexBuffer = NULL;
735 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000736}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000737
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000738void GrInOrderDrawBuffer::geometrySourceWillPush() {
739 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
740 poolState.fUsedPoolVertexBytes = 0;
741 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000742#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000743 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
744 poolState.fPoolStartVertex = ~0;
745 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
746 poolState.fPoolStartIndex = ~0;
747#endif
748}
749
bsalomonb3e3a952014-09-19 11:10:40 -0700750void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000751 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000752 fGeoPoolStateStack.pop_back();
753 GeometryPoolState& poolState = fGeoPoolStateStack.back();
754 // we have to assume that any slack we had in our vertex/index data
755 // is now unreleasable because data may have been appended later in the
756 // pool.
joshualittd1aa8ff2014-11-04 07:47:55 -0800757 if (kReserved_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000758 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000759 }
joshualittd1aa8ff2014-11-04 07:47:55 -0800760 if (kReserved_GeometrySrcType == restoredState.fIndexSrc) {
joshualittd53a8272014-11-10 16:03:14 -0800761 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * restoredState.fIndexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000762 }
763}
764
joshualittd53a8272014-11-10 16:03:14 -0800765void GrInOrderDrawBuffer::recordStateIfNecessary(GrGpu::DrawType drawType,
766 const GrDeviceCoordTexture* dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700767 if (!fLastState) {
768 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (this->getDrawState()));
769 fLastState = &ss->fState;
joshualittd53a8272014-11-10 16:03:14 -0800770 if (dstCopy) {
771 ss->fDstCopy = *dstCopy;
772 }
773 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700774 this->convertDrawStateToPendingExec(fLastState);
775 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700776 return;
777 }
778 const GrDrawState& curr = this->getDrawState();
cdalton6819df32014-10-15 13:43:48 -0700779 switch (GrDrawState::CombineIfPossible(*fLastState, curr, *this->caps())) {
joshualittd53a8272014-11-10 16:03:14 -0800780 case GrDrawState::kIncompatible_CombinedState: {
781 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (curr));
782 fLastState = &ss->fState;
783 if (dstCopy) {
784 ss->fDstCopy = *dstCopy;
785 }
786 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700787 this->convertDrawStateToPendingExec(fLastState);
788 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700789 break;
joshualittd53a8272014-11-10 16:03:14 -0800790 }
bsalomon838f62d2014-08-05 07:15:57 -0700791 case GrDrawState::kA_CombinedState:
792 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA.
793 break;
794 case GrDrawState::kB_CombinedState:
bsalomon2a9ca782014-09-05 14:27:43 -0700795 // prev has already been converted to pending execution. That is a one-way ticket.
cdalton6819df32014-10-15 13:43:48 -0700796 // So here we just destruct the previous state and reinit with a new copy of curr.
797 // Note that this goes away when we move GrIODB over to taking optimized snapshots
798 // of draw states.
799 fLastState->~GrDrawState();
800 SkNEW_PLACEMENT_ARGS(fLastState, GrDrawState, (curr));
801 this->convertDrawStateToPendingExec(fLastState);
bsalomon838f62d2014-08-05 07:15:57 -0700802 break;
803 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000804}
805
cdalton6819df32014-10-15 13:43:48 -0700806void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
807 SkASSERT(!fCmdBuffer.empty());
808 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700809 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
810 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700811 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700812 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700813 }
mtklein07894c42014-10-13 14:00:42 -0700814}