blob: 778b8cf590894d042f1c7b7b99d09bc7ff93c837 [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() ||
joshualitt7eb8c7b2014-11-18 14:24:27 -0800222 draw->fInfo.vertexBuffer() != vertexBuffer ||
223 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer ||
joshualitt2c93efe2014-11-06 12:57:13 -0800224 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) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800263 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
264
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000265 GeometryPoolState& poolState = fGeoPoolStateStack.back();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000266
joshualitt9853cce2014-11-17 14:22:48 -0800267 this->recordStateIfNecessary(ds,
268 GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualittd53a8272014-11-10 16:03:14 -0800269 info.getDstCopy());
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000270
bsalomonb3e3a952014-09-19 11:10:40 -0700271 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000272 if (info.isInstanced()) {
joshualitt9853cce2014-11-17 14:22:48 -0800273 int instancesConcated = this->concatInstancedDraw(ds, info, scissorState);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000274 if (info.instanceCount() > instancesConcated) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800275 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, scissorState));
cdalton6819df32014-10-15 13:43:48 -0700276 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000277 } else {
278 return;
279 }
280 } else {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800281 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, scissorState));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000282 }
cdalton6819df32014-10-15 13:43:48 -0700283 this->recordTraceMarkersIfNecessary();
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000284
bsalomonb3e3a952014-09-19 11:10:40 -0700285 // Adjust the starting vertex and index when we are using reserved or array sources to
286 // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
287 if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
joshualitt9853cce2014-11-17 14:22:48 -0800288 size_t bytes = (info.vertexCount() + info.startVertex()) * ds.getVertexStride();
bsalomonb3e3a952014-09-19 11:10:40 -0700289 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700290 draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +0000291 }
bsalomonb3e3a952014-09-19 11:10:40 -0700292
293 if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) {
294 size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
295 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700296 draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000297 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000298}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000299
joshualitt9853cce2014-11-17 14:22:48 -0800300void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
301 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800302 const GrClipMaskManager::ScissorState& scissorState,
303 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000304 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualitt9853cce2014-11-17 14:22:48 -0800305 this->recordStateIfNecessary(ds, GrGpu::kStencilPath_DrawType, NULL);
cdalton6819df32014-10-15 13:43:48 -0700306 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800307 sp->fScissorState = scissorState;
308 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700309 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000310}
311
joshualitt9853cce2014-11-17 14:22:48 -0800312void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
313 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800314 const GrClipMaskManager::ScissorState& scissorState,
315 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700316 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000317 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt9853cce2014-11-17 14:22:48 -0800318 this->recordStateIfNecessary(ds, GrGpu::kDrawPath_DrawType, dstCopy);
cdalton6819df32014-10-15 13:43:48 -0700319 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
bsalomon49f085d2014-09-05 13:34:00 -0700320 if (dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700321 dp->fDstCopy = *dstCopy;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000322 }
joshualitt2c93efe2014-11-06 12:57:13 -0800323 dp->fScissorState = scissorState;
324 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700325 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000326}
327
joshualitt9853cce2014-11-17 14:22:48 -0800328void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
329 const GrPathRange* pathRange,
joshualitt2c93efe2014-11-06 12:57:13 -0800330 const uint32_t indices[],
331 int count,
332 const float transforms[],
333 PathTransformType transformsType,
334 const GrClipMaskManager::ScissorState& scissorState,
335 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700336 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700337 SkASSERT(pathRange);
338 SkASSERT(indices);
339 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000340
joshualitt9853cce2014-11-17 14:22:48 -0800341 this->recordStateIfNecessary(ds, GrGpu::kDrawPaths_DrawType, dstCopy);
cdalton6819df32014-10-15 13:43:48 -0700342
cdalton3fc6a2f2014-11-13 11:54:20 -0800343 uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
344 float* savedTransforms = fPathTransformBuffer.append(count *
345 GrPathRendering::PathTransformSize(transformsType), transforms);
cdalton6819df32014-10-15 13:43:48 -0700346
cdalton3fc6a2f2014-11-13 11:54:20 -0800347 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
348 // The previous command was also DrawPaths. Try to collapse this call into the one
349 // before. Note that stencilling all the paths at once, then covering, may not be
350 // equivalent to two separate draw calls if there is overlap. Blending won't work,
351 // and the combined calls may also cancel each other's winding numbers in some
352 // places. For now the winding numbers are only an issue if the fill is even/odd,
353 // because DrawPaths is currently only used for glyphs, and glyphs in the same
354 // font tend to all wind in the same direction.
355 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
356 if (pathRange == previous->pathRange() &&
357 transformsType == previous->fTransformsType &&
358 scissorState == previous->fScissorState &&
359 stencilSettings == previous->fStencilSettings &&
360 path_fill_type_is_winding(stencilSettings) &&
joshualitt9853cce2014-11-17 14:22:48 -0800361 !ds.willBlendWithDst()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800362 // Fold this DrawPaths call into the one previous.
363 previous->fCount += count;
364 return;
365 }
366 }
367
368 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
369 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700370 dp->fCount = count;
cdalton3fc6a2f2014-11-13 11:54:20 -0800371 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700372 dp->fTransformsType = transformsType;
joshualitt2c93efe2014-11-06 12:57:13 -0800373 dp->fScissorState = scissorState;
374 dp->fStencilSettings = stencilSettings;
bsalomon49f085d2014-09-05 13:34:00 -0700375 if (dstCopy) {
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000376 dp->fDstCopy = *dstCopy;
377 }
cdalton6819df32014-10-15 13:43:48 -0700378
379 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000380}
381
bsalomon63b21962014-11-05 07:05:34 -0800382void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
383 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800384 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000385 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000386 if (NULL == rect) {
387 // We could do something smart and remove previous draws and clears to
388 // the current render target. If we get that smart we have to make sure
389 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000390 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000391 rect = &r;
392 }
cdalton6819df32014-10-15 13:43:48 -0700393 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000394 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000395 clr->fColor = color;
396 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000397 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700398 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000399}
400
joshualitt6db519c2014-10-29 08:48:18 -0700401void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
402 bool insideClip,
403 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800404 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700405 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
406 clr->fRect = rect;
407 clr->fInsideClip = insideClip;
408 this->recordTraceMarkersIfNecessary();
409}
410
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000411void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800412 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000413 if (!this->caps()->discardRenderTargetSupport()) {
414 return;
415 }
cdalton6819df32014-10-15 13:43:48 -0700416 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000417 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700418 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000419}
420
joshualitt7eb8c7b2014-11-18 14:24:27 -0800421void GrInOrderDrawBuffer::setDrawBuffers(DrawInfo* info) {
422 GeometryPoolState& poolState = fGeoPoolStateStack.back();
423 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
424 info->setVertexBuffer(this->getGeomSrc().fVertexBuffer);
425 } else {
426 info->setVertexBuffer(poolState.fPoolVertexBuffer);
427 }
428
429 if (info->isIndexed()) {
430 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
431 info->setIndexBuffer(this->getGeomSrc().fIndexBuffer);
432 } else {
433 info->setIndexBuffer(poolState.fPoolIndexBuffer);
434 }
435 }
436}
437
reed@google.comac10a2d2010-12-22 21:39:39 +0000438void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000439 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000440 this->resetVertexSource();
441 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700442
443 fCmdBuffer.reset();
444 fLastState = NULL;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000445 fVertexPool.reset();
446 fIndexPool.reset();
cdalton3fc6a2f2014-11-13 11:54:20 -0800447 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
448 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000449 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000450}
451
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000452void GrInOrderDrawBuffer::flush() {
453 if (fFlushing) {
454 return;
455 }
456
jvanverth8e80d172014-06-19 12:01:10 -0700457 this->getContext()->getFontCache()->updateTextures();
458
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000459 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
460 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000461
cdalton6819df32014-10-15 13:43:48 -0700462 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000463 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000464 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000465
466 GrAutoTRestore<bool> flushRestore(&fFlushing);
467 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000468
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000469 fVertexPool.unmap();
470 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000471
cdalton6819df32014-10-15 13:43:48 -0700472 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000473
cdalton6819df32014-10-15 13:43:48 -0700474 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700475 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700476
joshualittd53a8272014-11-10 16:03:14 -0800477 // Gpu no longer maintains the current drawstate, so we track the setstate calls below.
478 // NOTE: we always record a new drawstate at flush boundaries
479 SkAutoTUnref<const GrOptDrawState> currentOptState;
480
cdalton6819df32014-10-15 13:43:48 -0700481 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000482 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700483 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700484 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700485 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000486 newMarker.fMarker = traceString.c_str();
487 fDstGpu->addGpuTraceMarker(&newMarker);
488 ++currCmdMarker;
489 }
cdalton6819df32014-10-15 13:43:48 -0700490
joshualittd53a8272014-11-10 16:03:14 -0800491 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800492 SetState* ss = reinterpret_cast<SetState*>(iter.get());
joshualittd53a8272014-11-10 16:03:14 -0800493 currentOptState.reset(GrOptDrawState::Create(ss->fState,
494 fDstGpu,
495 &ss->fDstCopy,
496 ss->fDrawType));
497 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800498 iter->execute(this, currentOptState.get());
joshualittd53a8272014-11-10 16:03:14 -0800499 }
cdalton6819df32014-10-15 13:43:48 -0700500
501 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000502 fDstGpu->removeGpuTraceMarker(&newMarker);
503 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000504 }
mtkleinf439c772014-10-14 14:29:30 -0700505
cdalton6819df32014-10-15 13:43:48 -0700506 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000507 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000508
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000509 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000510 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000511}
512
cdalton3fc6a2f2014-11-13 11:54:20 -0800513void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800514 if (!optState) {
515 return;
516 }
joshualitt7eb8c7b2014-11-18 14:24:27 -0800517 buf->fDstGpu->draw(*optState, fInfo, fScissorState);
cdalton6819df32014-10-15 13:43:48 -0700518}
519
cdalton3fc6a2f2014-11-13 11:54:20 -0800520void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
521 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800522 if (!optState) {
523 return;
524 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800525 buf->fDstGpu->stencilPath(*optState, this->path(), fScissorState, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700526}
527
cdalton3fc6a2f2014-11-13 11:54:20 -0800528void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
529 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800530 if (!optState) {
531 return;
532 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800533 buf->fDstGpu->drawPath(*optState, this->path(), fScissorState, fStencilSettings,
534 fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700535}
536
cdalton3fc6a2f2014-11-13 11:54:20 -0800537void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
538 const GrOptDrawState* optState) {
joshualittd53a8272014-11-10 16:03:14 -0800539 if (!optState) {
540 return;
541 }
cdalton3fc6a2f2014-11-13 11:54:20 -0800542 buf->fDstGpu->drawPaths(*optState, this->pathRange(),
543 &buf->fPathIndexBuffer[fIndicesLocation], fCount,
544 &buf->fPathTransformBuffer[fTransformsLocation], fTransformsType,
545 fScissorState, fStencilSettings, fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700546}
547
cdalton3fc6a2f2014-11-13 11:54:20 -0800548void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700549}
550
cdalton3fc6a2f2014-11-13 11:54:20 -0800551void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700552 if (GrColor_ILLEGAL == fColor) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800553 buf->fDstGpu->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700554 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800555 buf->fDstGpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700556 }
557}
558
cdalton3fc6a2f2014-11-13 11:54:20 -0800559void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
560 const GrOptDrawState*) {
561 buf->fDstGpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700562}
563
cdalton3fc6a2f2014-11-13 11:54:20 -0800564void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
565 buf->fDstGpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700566}
567
joshualitta7024152014-11-03 14:16:35 -0800568bool GrInOrderDrawBuffer::copySurface(GrSurface* dst,
569 GrSurface* src,
570 const SkIRect& srcRect,
571 const SkIPoint& dstPoint) {
bsalomon@google.com116ad842013-04-09 15:38:19 +0000572 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700573 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000574 cs->fSrcRect = srcRect;
575 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700576 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000577 return true;
joshualitta7024152014-11-03 14:16:35 -0800578 } else if (GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) {
579 GrDrawTarget::copySurface(dst, src, srcRect, dstPoint);
580 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000581 } else {
582 return false;
583 }
584}
585
joshualitt9853cce2014-11-17 14:22:48 -0800586bool GrInOrderDrawBuffer::canCopySurface(const GrSurface* dst,
587 const GrSurface* src,
joshualitta7024152014-11-03 14:16:35 -0800588 const SkIRect& srcRect,
589 const SkIPoint& dstPoint) {
590 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint) ||
591 GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000592}
593
bsalomonf2703d82014-10-28 14:33:06 -0700594void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000595 fDstGpu->initCopySurfaceDstDesc(src, desc);
596}
597
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000598void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
joshualitt9853cce2014-11-17 14:22:48 -0800599 size_t vertexStride,
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000600 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000601 // We use geometryHints() to know whether to flush the draw buffer. We
602 // can't flush if we are inside an unbalanced pushGeometrySource.
603 // Moreover, flushing blows away vertex and index data that was
604 // previously reserved. So if the vertex or index data is pulled from
605 // reserved space and won't be released by this request then we can't
606 // flush.
607 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000608
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000609 bool unreleasedVertexSpace =
610 !vertexCount &&
611 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000612
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000613 bool unreleasedIndexSpace =
614 !indexCount &&
615 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000616
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000617 int vcount = vertexCount;
618 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000619
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000620 if (!insideGeoPush &&
621 !unreleasedVertexSpace &&
622 !unreleasedIndexSpace &&
joshualitt9853cce2014-11-17 14:22:48 -0800623 this->geometryHints(vertexStride, &vcount, &icount)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000624 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000625 }
626}
627
joshualitt9853cce2014-11-17 14:22:48 -0800628bool GrInOrderDrawBuffer::geometryHints(size_t vertexStride,
629 int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000630 int* indexCount) const {
631 // we will recommend a flush if the data could fit in a single
632 // preallocated buffer but none are left and it can't fit
633 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000634 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700635 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000636 int32_t currIndices = fIndexPool.currentBufferIndices();
637 if (*indexCount > currIndices &&
638 (!fIndexPool.preallocatedBuffersRemaining() &&
639 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
640
641 flush = true;
642 }
643 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000644 }
bsalomon49f085d2014-09-05 13:34:00 -0700645 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700646 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000647 if (*vertexCount > currVertices &&
648 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700649 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000650
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000651 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000652 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000653 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000654 }
655 return flush;
656}
657
jvanverth@google.coma6338982013-01-31 21:34:25 +0000658bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000659 int vertexCount,
660 void** vertices) {
661 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000662 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700663 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000664 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000665
jvanverth@google.coma6338982013-01-31 21:34:25 +0000666 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000667 vertexCount,
668 &poolState.fPoolVertexBuffer,
669 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700670 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000671}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000672
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000673bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
674 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000675 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700676 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000677 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000678
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000679 *indices = fIndexPool.makeSpace(indexCount,
680 &poolState.fPoolIndexBuffer,
681 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700682 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000683}
684
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000685void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
686 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000687 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000688
689 // If we get a release vertex space call then our current source should either be reserved
690 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800691 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000692
693 // When the caller reserved vertex buffer space we gave it back a pointer
694 // provided by the vertex buffer pool. At each draw we tracked the largest
695 // offset into the pool's pointer that was referenced. Now we return to the
696 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000697 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
joshualittd53a8272014-11-10 16:03:14 -0800698 fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000699 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000700 poolState.fPoolVertexBuffer = NULL;
701 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000702}
703
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000704void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
705 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000706 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000707
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000708 // If we get a release index space call then our current source should either be reserved
709 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800710 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000711
712 // Similar to releaseReservedVertexSpace we return any unused portion at
713 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000714 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
715 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
716 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000717 poolState.fPoolIndexBuffer = NULL;
718 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000719}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000720
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000721void GrInOrderDrawBuffer::geometrySourceWillPush() {
722 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
723 poolState.fUsedPoolVertexBytes = 0;
724 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000725#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000726 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
727 poolState.fPoolStartVertex = ~0;
728 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
729 poolState.fPoolStartIndex = ~0;
730#endif
731}
732
bsalomonb3e3a952014-09-19 11:10:40 -0700733void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000734 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000735 fGeoPoolStateStack.pop_back();
736 GeometryPoolState& poolState = fGeoPoolStateStack.back();
737 // we have to assume that any slack we had in our vertex/index data
738 // is now unreleasable because data may have been appended later in the
739 // pool.
joshualittd1aa8ff2014-11-04 07:47:55 -0800740 if (kReserved_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000741 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000742 }
joshualittd1aa8ff2014-11-04 07:47:55 -0800743 if (kReserved_GeometrySrcType == restoredState.fIndexSrc) {
joshualittd53a8272014-11-10 16:03:14 -0800744 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * restoredState.fIndexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000745 }
746}
747
joshualitt9853cce2014-11-17 14:22:48 -0800748void GrInOrderDrawBuffer::recordStateIfNecessary(const GrDrawState& ds,
749 GrGpu::DrawType drawType,
joshualittd53a8272014-11-10 16:03:14 -0800750 const GrDeviceCoordTexture* dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700751 if (!fLastState) {
joshualitt9853cce2014-11-17 14:22:48 -0800752 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (ds));
cdalton6819df32014-10-15 13:43:48 -0700753 fLastState = &ss->fState;
joshualittd53a8272014-11-10 16:03:14 -0800754 if (dstCopy) {
755 ss->fDstCopy = *dstCopy;
756 }
757 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700758 this->convertDrawStateToPendingExec(fLastState);
759 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700760 return;
761 }
joshualitt9853cce2014-11-17 14:22:48 -0800762 switch (GrDrawState::CombineIfPossible(*fLastState, ds, *this->caps())) {
joshualittd53a8272014-11-10 16:03:14 -0800763 case GrDrawState::kIncompatible_CombinedState: {
joshualitt9853cce2014-11-17 14:22:48 -0800764 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (ds));
joshualittd53a8272014-11-10 16:03:14 -0800765 fLastState = &ss->fState;
766 if (dstCopy) {
767 ss->fDstCopy = *dstCopy;
768 }
769 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700770 this->convertDrawStateToPendingExec(fLastState);
771 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700772 break;
joshualittd53a8272014-11-10 16:03:14 -0800773 }
bsalomon838f62d2014-08-05 07:15:57 -0700774 case GrDrawState::kA_CombinedState:
775 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA.
776 break;
777 case GrDrawState::kB_CombinedState:
bsalomon2a9ca782014-09-05 14:27:43 -0700778 // prev has already been converted to pending execution. That is a one-way ticket.
cdalton6819df32014-10-15 13:43:48 -0700779 // So here we just destruct the previous state and reinit with a new copy of curr.
780 // Note that this goes away when we move GrIODB over to taking optimized snapshots
781 // of draw states.
782 fLastState->~GrDrawState();
joshualitt9853cce2014-11-17 14:22:48 -0800783 SkNEW_PLACEMENT_ARGS(fLastState, GrDrawState, (ds));
cdalton6819df32014-10-15 13:43:48 -0700784 this->convertDrawStateToPendingExec(fLastState);
bsalomon838f62d2014-08-05 07:15:57 -0700785 break;
786 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000787}
788
cdalton6819df32014-10-15 13:43:48 -0700789void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
790 SkASSERT(!fCmdBuffer.empty());
791 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700792 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
793 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700794 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700795 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700796 }
mtklein07894c42014-10-13 14:00:42 -0700797}