blob: b0504b75a970e1c19cfbecfc9a32d7129085d488 [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
joshualitt9853cce2014-11-17 14:22:48 -0800136void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
137 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000138 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000139 const SkMatrix* localMatrix) {
joshualitt9853cce2014-11-17 14:22:48 -0800140 GrDrawState::AutoRestoreEffects are(ds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000141
joshualitt9853cce2014-11-17 14:22:48 -0800142 GrColor color = ds->getColor();
143 set_vertex_attributes(ds, SkToBool(localRect), color);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000144
joshualitt9853cce2014-11-17 14:22:48 -0800145 AutoReleaseGeometry geo(this, 4, ds->getVertexStride(), 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000146 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700147 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000148 return;
149 }
150
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000151 // Go to device coords to allow batching across matrix changes
joshualitt9853cce2014-11-17 14:22:48 -0800152 SkMatrix matrix = ds->getViewMatrix();
bsalomon01c8da12014-08-04 09:21:30 -0700153
jvanverth@google.com39768252013-02-14 15:25:44 +0000154 // 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 +0000155 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
156 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000157 GrDrawState::AutoViewMatrixRestore avmr;
joshualitt9853cce2014-11-17 14:22:48 -0800158 if (!avmr.setIdentity(ds)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000159 return;
160 }
161
joshualitt9853cce2014-11-17 14:22:48 -0800162 size_t vstride = ds->getVertexStride();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000163
egdaniel7b3d5ee2014-08-28 05:41:14 -0700164 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
165 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000166
167 SkRect devBounds;
168 // since we already computed the dev verts, set the bounds hint. This will help us avoid
169 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700170 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000171
bsalomon49f085d2014-09-05 13:34:00 -0700172 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700173 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
174 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000175 coords->setRectFan(localRect->fLeft, localRect->fTop,
176 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700177 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700178 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700179 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000180 }
181 }
182
bsalomon62c447d2014-08-08 08:08:50 -0700183 static const int kColorOffset = sizeof(SkPoint);
184 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
185 for (int i = 0; i < 4; ++i) {
186 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700187 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000188 }
189
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000190 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualitt9853cce2014-11-17 14:22:48 -0800191 this->drawIndexedInstances(ds, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000192}
193
joshualitt9853cce2014-11-17 14:22:48 -0800194int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds,
195 const DrawInfo& info,
joshualitt2c93efe2014-11-06 12:57:13 -0800196 const GrClipMaskManager::ScissorState& scissorState) {
cdalton6819df32014-10-15 13:43:48 -0700197 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000198 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000199
bsalomon@google.com934c5702012-03-20 21:17:58 +0000200 const GeometrySrcState& geomSrc = this->getGeomSrc();
201
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000202 // we only attempt to concat the case when reserved verts are used with a client-specified index
203 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
204 // between draws.
205 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
206 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
207 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000208 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000209 // Check if there is a draw info that is compatible that uses the same VB from the pool and
210 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700211 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000212 return 0;
213 }
214
cdalton6819df32014-10-15 13:43:48 -0700215 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000216 GeometryPoolState& poolState = fGeoPoolStateStack.back();
217 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
218
cdalton6819df32014-10-15 13:43:48 -0700219 if (!draw->fInfo.isInstanced() ||
220 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
221 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomonb3e3a952014-09-19 11:10:40 -0700222 draw->vertexBuffer() != vertexBuffer ||
joshualitt2c93efe2014-11-06 12:57:13 -0800223 draw->indexBuffer() != geomSrc.fIndexBuffer ||
224 draw->fScissorState != scissorState) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000225 return 0;
226 }
227 // info does not yet account for the offset from the start of the pool's VB while the previous
228 // draw record does.
229 int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
cdalton6819df32014-10-15 13:43:48 -0700230 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != adjustedStartVertex) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000231 return 0;
232 }
233
cdalton6819df32014-10-15 13:43:48 -0700234 SkASSERT(poolState.fPoolStartVertex == draw->fInfo.startVertex() + draw->fInfo.vertexCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000235
236 // how many instances can be concat'ed onto draw given the size of the index buffer
237 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700238 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000239 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000240
241 // update the amount of reserved vertex data actually referenced in draws
joshualitt9853cce2014-11-17 14:22:48 -0800242 size_t vertexBytes = instancesToConcat * info.verticesPerInstance() * ds.getVertexStride();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000243 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000244
cdalton6819df32014-10-15 13:43:48 -0700245 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000246
247 // update last fGpuCmdMarkers to include any additional trace markers that have been added
248 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700249 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000250 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
251 } else {
252 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700253 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000254 }
255 }
256
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000257 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000258}
259
joshualitt9853cce2014-11-17 14:22:48 -0800260void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
261 const DrawInfo& info,
joshualitt2c93efe2014-11-06 12:57:13 -0800262 const GrClipMaskManager::ScissorState& scissorState) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000263 GeometryPoolState& poolState = fGeoPoolStateStack.back();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000264
joshualitt9853cce2014-11-17 14:22:48 -0800265 this->recordStateIfNecessary(ds,
266 GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualittd53a8272014-11-10 16:03:14 -0800267 info.getDstCopy());
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000268
bsalomonb3e3a952014-09-19 11:10:40 -0700269 const GrVertexBuffer* vb;
270 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
271 vb = this->getGeomSrc().fVertexBuffer;
272 } else {
273 vb = poolState.fPoolVertexBuffer;
274 }
275
276 const GrIndexBuffer* ib = NULL;
277 if (info.isIndexed()) {
278 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
279 ib = this->getGeomSrc().fIndexBuffer;
280 } else {
281 ib = poolState.fPoolIndexBuffer;
282 }
283 }
284
285 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000286 if (info.isInstanced()) {
joshualitt9853cce2014-11-17 14:22:48 -0800287 int instancesConcated = this->concatInstancedDraw(ds, info, scissorState);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000288 if (info.instanceCount() > instancesConcated) {
joshualitt2c93efe2014-11-06 12:57:13 -0800289 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, scissorState, vb, ib));
cdalton6819df32014-10-15 13:43:48 -0700290 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000291 } else {
292 return;
293 }
294 } else {
joshualitt2c93efe2014-11-06 12:57:13 -0800295 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, scissorState, vb, ib));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000296 }
cdalton6819df32014-10-15 13:43:48 -0700297 this->recordTraceMarkersIfNecessary();
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000298
bsalomonb3e3a952014-09-19 11:10:40 -0700299 // Adjust the starting vertex and index when we are using reserved or array sources to
300 // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
301 if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
joshualitt9853cce2014-11-17 14:22:48 -0800302 size_t bytes = (info.vertexCount() + info.startVertex()) * ds.getVertexStride();
bsalomonb3e3a952014-09-19 11:10:40 -0700303 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700304 draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +0000305 }
bsalomonb3e3a952014-09-19 11:10:40 -0700306
307 if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) {
308 size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
309 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700310 draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000311 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000312}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000313
joshualitt9853cce2014-11-17 14:22:48 -0800314void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
315 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800316 const GrClipMaskManager::ScissorState& scissorState,
317 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000318 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualitt9853cce2014-11-17 14:22:48 -0800319 this->recordStateIfNecessary(ds, GrGpu::kStencilPath_DrawType, NULL);
cdalton6819df32014-10-15 13:43:48 -0700320 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800321 sp->fScissorState = scissorState;
322 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700323 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000324}
325
joshualitt9853cce2014-11-17 14:22:48 -0800326void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
327 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800328 const GrClipMaskManager::ScissorState& scissorState,
329 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700330 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000331 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt9853cce2014-11-17 14:22:48 -0800332 this->recordStateIfNecessary(ds, GrGpu::kDrawPath_DrawType, dstCopy);
cdalton6819df32014-10-15 13:43:48 -0700333 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
bsalomon49f085d2014-09-05 13:34:00 -0700334 if (dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700335 dp->fDstCopy = *dstCopy;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000336 }
joshualitt2c93efe2014-11-06 12:57:13 -0800337 dp->fScissorState = scissorState;
338 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700339 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000340}
341
joshualitt9853cce2014-11-17 14:22:48 -0800342void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
343 const GrPathRange* pathRange,
joshualitt2c93efe2014-11-06 12:57:13 -0800344 const uint32_t indices[],
345 int count,
346 const float transforms[],
347 PathTransformType transformsType,
348 const GrClipMaskManager::ScissorState& scissorState,
349 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700350 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700351 SkASSERT(pathRange);
352 SkASSERT(indices);
353 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000354
joshualitt9853cce2014-11-17 14:22:48 -0800355 this->recordStateIfNecessary(ds, GrGpu::kDrawPaths_DrawType, dstCopy);
cdalton6819df32014-10-15 13:43:48 -0700356
cdalton3fc6a2f2014-11-13 11:54:20 -0800357 uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
358 float* savedTransforms = fPathTransformBuffer.append(count *
359 GrPathRendering::PathTransformSize(transformsType), transforms);
cdalton6819df32014-10-15 13:43:48 -0700360
cdalton3fc6a2f2014-11-13 11:54:20 -0800361 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
362 // The previous command was also DrawPaths. Try to collapse this call into the one
363 // before. Note that stencilling all the paths at once, then covering, may not be
364 // equivalent to two separate draw calls if there is overlap. Blending won't work,
365 // and the combined calls may also cancel each other's winding numbers in some
366 // places. For now the winding numbers are only an issue if the fill is even/odd,
367 // because DrawPaths is currently only used for glyphs, and glyphs in the same
368 // font tend to all wind in the same direction.
369 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
370 if (pathRange == previous->pathRange() &&
371 transformsType == previous->fTransformsType &&
372 scissorState == previous->fScissorState &&
373 stencilSettings == previous->fStencilSettings &&
374 path_fill_type_is_winding(stencilSettings) &&
joshualitt9853cce2014-11-17 14:22:48 -0800375 !ds.willBlendWithDst()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800376 // Fold this DrawPaths call into the one previous.
377 previous->fCount += count;
378 return;
379 }
380 }
381
382 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
383 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700384 dp->fCount = count;
cdalton3fc6a2f2014-11-13 11:54:20 -0800385 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700386 dp->fTransformsType = transformsType;
joshualitt2c93efe2014-11-06 12:57:13 -0800387 dp->fScissorState = scissorState;
388 dp->fStencilSettings = stencilSettings;
bsalomon49f085d2014-09-05 13:34:00 -0700389 if (dstCopy) {
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000390 dp->fDstCopy = *dstCopy;
391 }
cdalton6819df32014-10-15 13:43:48 -0700392
393 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000394}
395
bsalomon63b21962014-11-05 07:05:34 -0800396void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
397 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800398 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000399 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000400 if (NULL == rect) {
401 // We could do something smart and remove previous draws and clears to
402 // the current render target. If we get that smart we have to make sure
403 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000404 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000405 rect = &r;
406 }
cdalton6819df32014-10-15 13:43:48 -0700407 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000408 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000409 clr->fColor = color;
410 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000411 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700412 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000413}
414
joshualitt6db519c2014-10-29 08:48:18 -0700415void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
416 bool insideClip,
417 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800418 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700419 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
420 clr->fRect = rect;
421 clr->fInsideClip = insideClip;
422 this->recordTraceMarkersIfNecessary();
423}
424
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000425void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800426 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000427 if (!this->caps()->discardRenderTargetSupport()) {
428 return;
429 }
cdalton6819df32014-10-15 13:43:48 -0700430 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000431 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700432 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000433}
434
reed@google.comac10a2d2010-12-22 21:39:39 +0000435void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000436 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000437 this->resetVertexSource();
438 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700439
440 fCmdBuffer.reset();
441 fLastState = NULL;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000442 fVertexPool.reset();
443 fIndexPool.reset();
cdalton3fc6a2f2014-11-13 11:54:20 -0800444 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
445 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000446 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000447}
448
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000449void GrInOrderDrawBuffer::flush() {
450 if (fFlushing) {
451 return;
452 }
453
jvanverth8e80d172014-06-19 12:01:10 -0700454 this->getContext()->getFontCache()->updateTextures();
455
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000456 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
457 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000458
cdalton6819df32014-10-15 13:43:48 -0700459 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000460 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000461 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000462
463 GrAutoTRestore<bool> flushRestore(&fFlushing);
464 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000465
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000466 fVertexPool.unmap();
467 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000468
cdalton6819df32014-10-15 13:43:48 -0700469 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000470
cdalton6819df32014-10-15 13:43:48 -0700471 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700472 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700473
joshualittd53a8272014-11-10 16:03:14 -0800474 // Gpu no longer maintains the current drawstate, so we track the setstate calls below.
475 // NOTE: we always record a new drawstate at flush boundaries
476 SkAutoTUnref<const GrOptDrawState> currentOptState;
477
cdalton6819df32014-10-15 13:43:48 -0700478 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000479 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700480 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700481 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700482 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000483 newMarker.fMarker = traceString.c_str();
484 fDstGpu->addGpuTraceMarker(&newMarker);
485 ++currCmdMarker;
486 }
cdalton6819df32014-10-15 13:43:48 -0700487
joshualittd53a8272014-11-10 16:03:14 -0800488 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800489 SetState* ss = reinterpret_cast<SetState*>(iter.get());
joshualittd53a8272014-11-10 16:03:14 -0800490 currentOptState.reset(GrOptDrawState::Create(ss->fState,
491 fDstGpu,
492 &ss->fDstCopy,
493 ss->fDrawType));
494 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800495 iter->execute(this, currentOptState.get());
joshualittd53a8272014-11-10 16:03:14 -0800496 }
cdalton6819df32014-10-15 13:43:48 -0700497
498 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000499 fDstGpu->removeGpuTraceMarker(&newMarker);
500 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000501 }
mtkleinf439c772014-10-14 14:29:30 -0700502
cdalton6819df32014-10-15 13:43:48 -0700503 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000504 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000505
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000506 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000507 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000508}
509
cdalton3fc6a2f2014-11-13 11:54:20 -0800510void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800511 if (!optState) {
512 return;
513 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800514 GrGpu* dstGpu = buf->fDstGpu;
515 dstGpu->setVertexSourceToBuffer(this->vertexBuffer(), optState->getVertexStride());
cdalton6819df32014-10-15 13:43:48 -0700516 if (fInfo.isIndexed()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800517 dstGpu->setIndexSourceToBuffer(this->indexBuffer());
cdalton6819df32014-10-15 13:43:48 -0700518 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800519 dstGpu->draw(*optState, fInfo, fScissorState);
cdalton6819df32014-10-15 13:43:48 -0700520}
521
cdalton3fc6a2f2014-11-13 11:54:20 -0800522void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
523 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800524 if (!optState) {
525 return;
526 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800527 buf->fDstGpu->stencilPath(*optState, this->path(), fScissorState, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700528}
529
cdalton3fc6a2f2014-11-13 11:54:20 -0800530void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
531 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800532 if (!optState) {
533 return;
534 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800535 buf->fDstGpu->drawPath(*optState, this->path(), fScissorState, fStencilSettings,
536 fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700537}
538
cdalton3fc6a2f2014-11-13 11:54:20 -0800539void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
540 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800541 if (!optState) {
542 return;
543 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800544 buf->fDstGpu->drawPaths(*optState, this->pathRange(),
545 &buf->fPathIndexBuffer[fIndicesLocation], fCount,
546 &buf->fPathTransformBuffer[fTransformsLocation], fTransformsType,
547 fScissorState, fStencilSettings, fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700548}
549
cdalton3fc6a2f2014-11-13 11:54:20 -0800550void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700551}
552
cdalton3fc6a2f2014-11-13 11:54:20 -0800553void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700554 if (GrColor_ILLEGAL == fColor) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800555 buf->fDstGpu->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700556 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800557 buf->fDstGpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700558 }
559}
560
cdalton3fc6a2f2014-11-13 11:54:20 -0800561void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
562 const GrOptDrawState*) {
563 buf->fDstGpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700564}
565
cdalton3fc6a2f2014-11-13 11:54:20 -0800566void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
567 buf->fDstGpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700568}
569
joshualitta7024152014-11-03 14:16:35 -0800570bool GrInOrderDrawBuffer::copySurface(GrSurface* dst,
571 GrSurface* src,
572 const SkIRect& srcRect,
573 const SkIPoint& dstPoint) {
bsalomon@google.com116ad842013-04-09 15:38:19 +0000574 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700575 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000576 cs->fSrcRect = srcRect;
577 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700578 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000579 return true;
joshualitta7024152014-11-03 14:16:35 -0800580 } else if (GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) {
581 GrDrawTarget::copySurface(dst, src, srcRect, dstPoint);
582 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000583 } else {
584 return false;
585 }
586}
587
joshualitt9853cce2014-11-17 14:22:48 -0800588bool GrInOrderDrawBuffer::canCopySurface(const GrSurface* dst,
589 const GrSurface* src,
joshualitta7024152014-11-03 14:16:35 -0800590 const SkIRect& srcRect,
591 const SkIPoint& dstPoint) {
592 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint) ||
593 GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000594}
595
bsalomonf2703d82014-10-28 14:33:06 -0700596void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000597 fDstGpu->initCopySurfaceDstDesc(src, desc);
598}
599
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000600void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
joshualitt9853cce2014-11-17 14:22:48 -0800601 size_t vertexStride,
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000602 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000603 // We use geometryHints() to know whether to flush the draw buffer. We
604 // can't flush if we are inside an unbalanced pushGeometrySource.
605 // Moreover, flushing blows away vertex and index data that was
606 // previously reserved. So if the vertex or index data is pulled from
607 // reserved space and won't be released by this request then we can't
608 // flush.
609 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000610
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000611 bool unreleasedVertexSpace =
612 !vertexCount &&
613 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000614
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000615 bool unreleasedIndexSpace =
616 !indexCount &&
617 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000618
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000619 int vcount = vertexCount;
620 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000621
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000622 if (!insideGeoPush &&
623 !unreleasedVertexSpace &&
624 !unreleasedIndexSpace &&
joshualitt9853cce2014-11-17 14:22:48 -0800625 this->geometryHints(vertexStride, &vcount, &icount)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000626 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000627 }
628}
629
joshualitt9853cce2014-11-17 14:22:48 -0800630bool GrInOrderDrawBuffer::geometryHints(size_t vertexStride,
631 int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000632 int* indexCount) const {
633 // we will recommend a flush if the data could fit in a single
634 // preallocated buffer but none are left and it can't fit
635 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000636 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700637 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000638 int32_t currIndices = fIndexPool.currentBufferIndices();
639 if (*indexCount > currIndices &&
640 (!fIndexPool.preallocatedBuffersRemaining() &&
641 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
642
643 flush = true;
644 }
645 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000646 }
bsalomon49f085d2014-09-05 13:34:00 -0700647 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700648 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000649 if (*vertexCount > currVertices &&
650 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700651 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000652
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000653 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000654 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000655 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000656 }
657 return flush;
658}
659
jvanverth@google.coma6338982013-01-31 21:34:25 +0000660bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000661 int vertexCount,
662 void** vertices) {
663 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000664 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700665 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000666 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000667
jvanverth@google.coma6338982013-01-31 21:34:25 +0000668 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000669 vertexCount,
670 &poolState.fPoolVertexBuffer,
671 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700672 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000673}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000674
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000675bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
676 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000677 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700678 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000679 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000680
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000681 *indices = fIndexPool.makeSpace(indexCount,
682 &poolState.fPoolIndexBuffer,
683 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700684 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000685}
686
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000687void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
688 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000689 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000690
691 // If we get a release vertex space call then our current source should either be reserved
692 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800693 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000694
695 // When the caller reserved vertex buffer space we gave it back a pointer
696 // provided by the vertex buffer pool. At each draw we tracked the largest
697 // offset into the pool's pointer that was referenced. Now we return to the
698 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000699 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
joshualittd53a8272014-11-10 16:03:14 -0800700 fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000701 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000702 poolState.fPoolVertexBuffer = NULL;
703 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000704}
705
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000706void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
707 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000708 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000709
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000710 // If we get a release index space call then our current source should either be reserved
711 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800712 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000713
714 // Similar to releaseReservedVertexSpace we return any unused portion at
715 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000716 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
717 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
718 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000719 poolState.fPoolIndexBuffer = NULL;
720 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000721}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000722
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000723void GrInOrderDrawBuffer::geometrySourceWillPush() {
724 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
725 poolState.fUsedPoolVertexBytes = 0;
726 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000727#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000728 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
729 poolState.fPoolStartVertex = ~0;
730 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
731 poolState.fPoolStartIndex = ~0;
732#endif
733}
734
bsalomonb3e3a952014-09-19 11:10:40 -0700735void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000736 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000737 fGeoPoolStateStack.pop_back();
738 GeometryPoolState& poolState = fGeoPoolStateStack.back();
739 // we have to assume that any slack we had in our vertex/index data
740 // is now unreleasable because data may have been appended later in the
741 // pool.
joshualittd1aa8ff2014-11-04 07:47:55 -0800742 if (kReserved_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000743 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000744 }
joshualittd1aa8ff2014-11-04 07:47:55 -0800745 if (kReserved_GeometrySrcType == restoredState.fIndexSrc) {
joshualittd53a8272014-11-10 16:03:14 -0800746 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * restoredState.fIndexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000747 }
748}
749
joshualitt9853cce2014-11-17 14:22:48 -0800750void GrInOrderDrawBuffer::recordStateIfNecessary(const GrDrawState& ds,
751 GrGpu::DrawType drawType,
joshualittd53a8272014-11-10 16:03:14 -0800752 const GrDeviceCoordTexture* dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700753 if (!fLastState) {
joshualitt9853cce2014-11-17 14:22:48 -0800754 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (ds));
cdalton6819df32014-10-15 13:43:48 -0700755 fLastState = &ss->fState;
joshualittd53a8272014-11-10 16:03:14 -0800756 if (dstCopy) {
757 ss->fDstCopy = *dstCopy;
758 }
759 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700760 this->convertDrawStateToPendingExec(fLastState);
761 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700762 return;
763 }
joshualitt9853cce2014-11-17 14:22:48 -0800764 switch (GrDrawState::CombineIfPossible(*fLastState, ds, *this->caps())) {
joshualittd53a8272014-11-10 16:03:14 -0800765 case GrDrawState::kIncompatible_CombinedState: {
joshualitt9853cce2014-11-17 14:22:48 -0800766 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (ds));
joshualittd53a8272014-11-10 16:03:14 -0800767 fLastState = &ss->fState;
768 if (dstCopy) {
769 ss->fDstCopy = *dstCopy;
770 }
771 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700772 this->convertDrawStateToPendingExec(fLastState);
773 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700774 break;
joshualittd53a8272014-11-10 16:03:14 -0800775 }
bsalomon838f62d2014-08-05 07:15:57 -0700776 case GrDrawState::kA_CombinedState:
777 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA.
778 break;
779 case GrDrawState::kB_CombinedState:
bsalomon2a9ca782014-09-05 14:27:43 -0700780 // prev has already been converted to pending execution. That is a one-way ticket.
cdalton6819df32014-10-15 13:43:48 -0700781 // So here we just destruct the previous state and reinit with a new copy of curr.
782 // Note that this goes away when we move GrIODB over to taking optimized snapshots
783 // of draw states.
784 fLastState->~GrDrawState();
joshualitt9853cce2014-11-17 14:22:48 -0800785 SkNEW_PLACEMENT_ARGS(fLastState, GrDrawState, (ds));
cdalton6819df32014-10-15 13:43:48 -0700786 this->convertDrawStateToPendingExec(fLastState);
bsalomon838f62d2014-08-05 07:15:57 -0700787 break;
788 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000789}
790
cdalton6819df32014-10-15 13:43:48 -0700791void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
792 SkASSERT(!fCmdBuffer.empty());
793 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700794 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
795 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700796 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700797 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700798 }
mtklein07894c42014-10-13 14:00:42 -0700799}