blob: cb44c2bb459d933f176e1adae7caefe2a2aba7e2 [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"
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000014#include "GrTemplates.h"
joshualittd53a8272014-11-10 16:03:14 -080015#include "GrTextStrike.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016#include "GrTexture.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000018GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
bsalomon@google.com471d4712011-08-23 15:45:25 +000019 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000020 GrIndexBufferAllocPool* indexPool)
joshualitt6db519c2014-10-29 08:48:18 -070021 : INHERITED(gpu->getContext())
cdalton6819df32014-10-15 13:43:48 -070022 , fCmdBuffer(kCmdBufferInitialSizeInBytes)
23 , fLastState(NULL)
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000024 , fDstGpu(gpu)
robertphillips@google.com69705572012-03-21 19:46:50 +000025 , fVertexPool(*vertexPool)
26 , fIndexPool(*indexPool)
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +000027 , fFlushing(false)
28 , fDrawID(0) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000029
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000030 fDstGpu->ref();
bsalomon@google.combcce8922013-03-25 15:38:39 +000031 fCaps.reset(SkRef(fDstGpu->caps()));
bsalomon@google.com18c9c192011-09-22 21:01:31 +000032
bsalomon49f085d2014-09-05 13:34:00 -070033 SkASSERT(vertexPool);
34 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000035
cdalton3fc6a2f2014-11-13 11:54:20 -080036 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
37 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
38
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000039 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
40 poolState.fUsedPoolVertexBytes = 0;
41 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000042#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000043 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
44 poolState.fPoolStartVertex = ~0;
45 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
46 poolState.fPoolStartIndex = ~0;
47#endif
bsalomon@google.coma4f6b102012-06-26 21:04:22 +000048 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000049}
50
51GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000052 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000053 // This must be called by before the GrDrawTarget destructor
54 this->releaseGeometry();
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000055 fDstGpu->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +000056}
57
bsalomon@google.com934c5702012-03-20 21:17:58 +000058////////////////////////////////////////////////////////////////////////////////
59
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000060namespace {
61void get_vertex_bounds(const void* vertices,
62 size_t vertexSize,
63 int vertexCount,
64 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000065 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000066 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000067 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000068 bounds->fLeft = bounds->fRight = point->fX;
69 bounds->fTop = bounds->fBottom = point->fY;
70 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000071 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000072 bounds->growToInclude(point->fX, point->fY);
73 }
74}
bsalomon@google.com934c5702012-03-20 21:17:58 +000075}
76
bsalomon62c447d2014-08-08 08:08:50 -070077/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
78 have explicit local coords and sometimes not. We *could* always provide explicit local coords
79 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
80 haven't seen a use case which frequently switches between local rect and no local rect draws.
81
82 The color param is used to determine whether the opaque hint can be set on the draw state.
83 The caller must populate the vertex colors itself.
84
85 The vertex attrib order is always pos, color, [local coords].
86 */
87static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
joshualitt5478d422014-11-14 16:00:38 -080088 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
89 GrDefaultGeoProcFactory::kColor_GPType;
90 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
91 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::CreateAndSetAttribs(drawState,
92 flags))->unref();
bsalomon62c447d2014-08-08 08:08:50 -070093 if (0xFF == GrColorUnpackA(color)) {
94 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
95 }
96}
robertphillips@google.com42903302013-04-20 12:26:07 +000097
cdalton3fc6a2f2014-11-13 11:54:20 -080098static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
99 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
100 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
101 if (isWinding) {
102 // Double check that it is in fact winding.
103 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
104 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
105 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
106 SkASSERT(!pathStencilSettings.isTwoSided());
107 }
108 return isWinding;
109}
110
111template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
112 // Assume the next time this buffer fills up it will use approximately the same amount
113 // of space as last time. Only resize if we're using less than a third of the
114 // allocated space, and leave enough for 50% growth over last time.
115 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
116 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
117 buffer->reset();
118 buffer->setReserve(reserve);
119 } else {
120 buffer->rewind();
121 }
122}
123
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000124enum {
125 kTraceCmdBit = 0x80,
126 kCmdMask = 0x7f,
127};
128
bsalomon62c447d2014-08-08 08:08:50 -0700129static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000130
bsalomon62c447d2014-08-08 08:08:50 -0700131static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000132
bsalomon62c447d2014-08-08 08:08:50 -0700133static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000134
joshualitt9853cce2014-11-17 14:22:48 -0800135void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
136 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000137 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000138 const SkMatrix* localMatrix) {
joshualitt9853cce2014-11-17 14:22:48 -0800139 GrDrawState::AutoRestoreEffects are(ds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000140
joshualitt9853cce2014-11-17 14:22:48 -0800141 GrColor color = ds->getColor();
142 set_vertex_attributes(ds, SkToBool(localRect), color);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000143
joshualitt9853cce2014-11-17 14:22:48 -0800144 AutoReleaseGeometry geo(this, 4, ds->getVertexStride(), 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000145 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700146 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000147 return;
148 }
149
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000150 // Go to device coords to allow batching across matrix changes
joshualitt9853cce2014-11-17 14:22:48 -0800151 SkMatrix matrix = ds->getViewMatrix();
bsalomon01c8da12014-08-04 09:21:30 -0700152
jvanverth@google.com39768252013-02-14 15:25:44 +0000153 // 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 +0000154 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
155 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000156 GrDrawState::AutoViewMatrixRestore avmr;
joshualitt9853cce2014-11-17 14:22:48 -0800157 if (!avmr.setIdentity(ds)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000158 return;
159 }
160
joshualitt9853cce2014-11-17 14:22:48 -0800161 size_t vstride = ds->getVertexStride();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000162
egdaniel7b3d5ee2014-08-28 05:41:14 -0700163 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
164 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000165
166 SkRect devBounds;
167 // since we already computed the dev verts, set the bounds hint. This will help us avoid
168 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700169 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000170
bsalomon49f085d2014-09-05 13:34:00 -0700171 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700172 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
173 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000174 coords->setRectFan(localRect->fLeft, localRect->fTop,
175 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700176 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700177 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700178 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000179 }
180 }
181
bsalomon62c447d2014-08-08 08:08:50 -0700182 static const int kColorOffset = sizeof(SkPoint);
183 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
184 for (int i = 0; i < 4; ++i) {
185 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700186 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000187 }
188
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000189 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualitt9853cce2014-11-17 14:22:48 -0800190 this->drawIndexedInstances(ds, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000191}
192
joshualitt54e0c122014-11-19 09:38:51 -0800193int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700194 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000195 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000196
bsalomon@google.com934c5702012-03-20 21:17:58 +0000197 const GeometrySrcState& geomSrc = this->getGeomSrc();
198
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000199 // we only attempt to concat the case when reserved verts are used with a client-specified index
200 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
201 // between draws.
202 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
203 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
204 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000205 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000206 // Check if there is a draw info that is compatible that uses the same VB from the pool and
207 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700208 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000209 return 0;
210 }
211
cdalton6819df32014-10-15 13:43:48 -0700212 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000213 GeometryPoolState& poolState = fGeoPoolStateStack.back();
214 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
215
cdalton6819df32014-10-15 13:43:48 -0700216 if (!draw->fInfo.isInstanced() ||
217 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
218 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
joshualitt7eb8c7b2014-11-18 14:24:27 -0800219 draw->fInfo.vertexBuffer() != vertexBuffer ||
joshualitt54e0c122014-11-19 09:38:51 -0800220 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000221 return 0;
222 }
223 // info does not yet account for the offset from the start of the pool's VB while the previous
224 // draw record does.
225 int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
cdalton6819df32014-10-15 13:43:48 -0700226 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != adjustedStartVertex) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000227 return 0;
228 }
229
cdalton6819df32014-10-15 13:43:48 -0700230 SkASSERT(poolState.fPoolStartVertex == draw->fInfo.startVertex() + draw->fInfo.vertexCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000231
232 // how many instances can be concat'ed onto draw given the size of the index buffer
233 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700234 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000235 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000236
237 // update the amount of reserved vertex data actually referenced in draws
joshualitt9853cce2014-11-17 14:22:48 -0800238 size_t vertexBytes = instancesToConcat * info.verticesPerInstance() * ds.getVertexStride();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000239 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000240
cdalton6819df32014-10-15 13:43:48 -0700241 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000242
243 // update last fGpuCmdMarkers to include any additional trace markers that have been added
244 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700245 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000246 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
247 } else {
248 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700249 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000250 }
251 }
252
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000253 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000254}
255
joshualitt9853cce2014-11-17 14:22:48 -0800256void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
257 const DrawInfo& info,
joshualitt9176e2c2014-11-20 07:28:52 -0800258 const ScissorState& scissorState,
259 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800260 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
261
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000262 GeometryPoolState& poolState = fGeoPoolStateStack.back();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000263
bsalomonae59b772014-11-19 08:23:49 -0800264 if (!this->recordStateAndShouldDraw(ds, GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualitt9176e2c2014-11-20 07:28:52 -0800265 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800266 return;
267 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000268
bsalomonb3e3a952014-09-19 11:10:40 -0700269 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000270 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800271 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000272 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800273 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700274 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000275 } else {
276 return;
277 }
278 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800279 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000280 }
cdalton6819df32014-10-15 13:43:48 -0700281 this->recordTraceMarkersIfNecessary();
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000282
bsalomonb3e3a952014-09-19 11:10:40 -0700283 // Adjust the starting vertex and index when we are using reserved or array sources to
284 // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
285 if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
joshualitt9853cce2014-11-17 14:22:48 -0800286 size_t bytes = (info.vertexCount() + info.startVertex()) * ds.getVertexStride();
bsalomonb3e3a952014-09-19 11:10:40 -0700287 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700288 draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +0000289 }
bsalomonb3e3a952014-09-19 11:10:40 -0700290
291 if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) {
292 size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
293 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700294 draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000295 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000296}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000297
joshualitt9853cce2014-11-17 14:22:48 -0800298void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
299 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800300 const GrClipMaskManager::ScissorState& scissorState,
301 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000302 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualitt54e0c122014-11-19 09:38:51 -0800303 if (!this->recordStateAndShouldDraw(ds, GrGpu::kStencilPath_DrawType, scissorState, NULL)) {
bsalomonae59b772014-11-19 08:23:49 -0800304 return;
305 }
cdalton6819df32014-10-15 13:43:48 -0700306 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800307 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700308 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000309}
310
joshualitt9853cce2014-11-17 14:22:48 -0800311void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
312 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800313 const GrClipMaskManager::ScissorState& scissorState,
314 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700315 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000316 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt54e0c122014-11-19 09:38:51 -0800317 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800318 return;
319 }
cdalton6819df32014-10-15 13:43:48 -0700320 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800321 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700322 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000323}
324
joshualitt9853cce2014-11-17 14:22:48 -0800325void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
326 const GrPathRange* pathRange,
joshualitt2c93efe2014-11-06 12:57:13 -0800327 const uint32_t indices[],
328 int count,
329 const float transforms[],
330 PathTransformType transformsType,
331 const GrClipMaskManager::ScissorState& scissorState,
332 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700333 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700334 SkASSERT(pathRange);
335 SkASSERT(indices);
336 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000337
joshualitt54e0c122014-11-19 09:38:51 -0800338 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800339 return;
340 }
cdalton6819df32014-10-15 13:43:48 -0700341
cdalton3fc6a2f2014-11-13 11:54:20 -0800342 uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
343 float* savedTransforms = fPathTransformBuffer.append(count *
344 GrPathRendering::PathTransformSize(transformsType), transforms);
cdalton6819df32014-10-15 13:43:48 -0700345
cdalton3fc6a2f2014-11-13 11:54:20 -0800346 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
347 // The previous command was also DrawPaths. Try to collapse this call into the one
348 // before. Note that stencilling all the paths at once, then covering, may not be
349 // equivalent to two separate draw calls if there is overlap. Blending won't work,
350 // and the combined calls may also cancel each other's winding numbers in some
351 // places. For now the winding numbers are only an issue if the fill is even/odd,
352 // because DrawPaths is currently only used for glyphs, and glyphs in the same
353 // font tend to all wind in the same direction.
354 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
355 if (pathRange == previous->pathRange() &&
356 transformsType == previous->fTransformsType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800357 stencilSettings == previous->fStencilSettings &&
358 path_fill_type_is_winding(stencilSettings) &&
joshualitt9853cce2014-11-17 14:22:48 -0800359 !ds.willBlendWithDst()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800360 // Fold this DrawPaths call into the one previous.
361 previous->fCount += count;
362 return;
363 }
364 }
365
366 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
367 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700368 dp->fCount = count;
cdalton3fc6a2f2014-11-13 11:54:20 -0800369 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700370 dp->fTransformsType = transformsType;
joshualitt2c93efe2014-11-06 12:57:13 -0800371 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700372
373 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000374}
375
bsalomon63b21962014-11-05 07:05:34 -0800376void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
377 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800378 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000379 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000380 if (NULL == rect) {
381 // We could do something smart and remove previous draws and clears to
382 // the current render target. If we get that smart we have to make sure
383 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000384 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000385 rect = &r;
386 }
cdalton6819df32014-10-15 13:43:48 -0700387 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000388 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000389 clr->fColor = color;
390 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000391 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700392 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000393}
394
joshualitt6db519c2014-10-29 08:48:18 -0700395void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
396 bool insideClip,
397 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800398 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700399 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
400 clr->fRect = rect;
401 clr->fInsideClip = insideClip;
402 this->recordTraceMarkersIfNecessary();
403}
404
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000405void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800406 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000407 if (!this->caps()->discardRenderTargetSupport()) {
408 return;
409 }
cdalton6819df32014-10-15 13:43:48 -0700410 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000411 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700412 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000413}
414
joshualitt7eb8c7b2014-11-18 14:24:27 -0800415void GrInOrderDrawBuffer::setDrawBuffers(DrawInfo* info) {
416 GeometryPoolState& poolState = fGeoPoolStateStack.back();
417 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
418 info->setVertexBuffer(this->getGeomSrc().fVertexBuffer);
419 } else {
420 info->setVertexBuffer(poolState.fPoolVertexBuffer);
421 }
422
423 if (info->isIndexed()) {
424 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
425 info->setIndexBuffer(this->getGeomSrc().fIndexBuffer);
426 } else {
427 info->setIndexBuffer(poolState.fPoolIndexBuffer);
428 }
429 }
430}
431
reed@google.comac10a2d2010-12-22 21:39:39 +0000432void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000433 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000434 this->resetVertexSource();
435 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700436
437 fCmdBuffer.reset();
bsalomonae59b772014-11-19 08:23:49 -0800438 fLastState.reset(NULL);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000439 fVertexPool.reset();
440 fIndexPool.reset();
cdalton3fc6a2f2014-11-13 11:54:20 -0800441 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
442 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000443 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000444}
445
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000446void GrInOrderDrawBuffer::flush() {
447 if (fFlushing) {
448 return;
449 }
450
jvanverth8e80d172014-06-19 12:01:10 -0700451 this->getContext()->getFontCache()->updateTextures();
452
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000453 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
454 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000455
cdalton6819df32014-10-15 13:43:48 -0700456 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000457 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000458 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000459
460 GrAutoTRestore<bool> flushRestore(&fFlushing);
461 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000462
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000463 fVertexPool.unmap();
464 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000465
cdalton6819df32014-10-15 13:43:48 -0700466 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000467
cdalton6819df32014-10-15 13:43:48 -0700468 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700469 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700470
bsalomonae59b772014-11-19 08:23:49 -0800471 // Updated every time we find a set state cmd to reflect the current state in the playback
472 // stream.
joshualittd53a8272014-11-10 16:03:14 -0800473 SkAutoTUnref<const GrOptDrawState> currentOptState;
474
cdalton6819df32014-10-15 13:43:48 -0700475 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000476 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700477 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700478 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700479 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000480 newMarker.fMarker = traceString.c_str();
481 fDstGpu->addGpuTraceMarker(&newMarker);
482 ++currCmdMarker;
483 }
cdalton6819df32014-10-15 13:43:48 -0700484
joshualittd53a8272014-11-10 16:03:14 -0800485 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800486 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomonae59b772014-11-19 08:23:49 -0800487 currentOptState.reset(SkRef(ss->fState.get()));
joshualittd53a8272014-11-10 16:03:14 -0800488 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800489 iter->execute(this, currentOptState.get());
joshualittd53a8272014-11-10 16:03:14 -0800490 }
cdalton6819df32014-10-15 13:43:48 -0700491
492 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000493 fDstGpu->removeGpuTraceMarker(&newMarker);
494 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000495 }
mtkleinf439c772014-10-14 14:29:30 -0700496
cdalton6819df32014-10-15 13:43:48 -0700497 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000498 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000499
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000500 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000501 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000502}
503
cdalton3fc6a2f2014-11-13 11:54:20 -0800504void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
joshualitt54e0c122014-11-19 09:38:51 -0800505 buf->fDstGpu->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700506}
507
cdalton3fc6a2f2014-11-13 11:54:20 -0800508void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
509 const GrOptDrawState* optState) {
joshualitt54e0c122014-11-19 09:38:51 -0800510 buf->fDstGpu->stencilPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700511}
512
cdalton3fc6a2f2014-11-13 11:54:20 -0800513void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
514 const GrOptDrawState* optState) {
joshualitt9176e2c2014-11-20 07:28:52 -0800515 buf->fDstGpu->drawPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700516}
517
cdalton3fc6a2f2014-11-13 11:54:20 -0800518void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
519 const GrOptDrawState* optState) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800520 buf->fDstGpu->drawPaths(*optState, this->pathRange(),
521 &buf->fPathIndexBuffer[fIndicesLocation], fCount,
522 &buf->fPathTransformBuffer[fTransformsLocation], fTransformsType,
joshualitt9176e2c2014-11-20 07:28:52 -0800523 fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700524}
525
cdalton3fc6a2f2014-11-13 11:54:20 -0800526void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700527}
528
cdalton3fc6a2f2014-11-13 11:54:20 -0800529void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700530 if (GrColor_ILLEGAL == fColor) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800531 buf->fDstGpu->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700532 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800533 buf->fDstGpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700534 }
535}
536
cdalton3fc6a2f2014-11-13 11:54:20 -0800537void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
538 const GrOptDrawState*) {
539 buf->fDstGpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700540}
541
cdalton3fc6a2f2014-11-13 11:54:20 -0800542void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
543 buf->fDstGpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700544}
545
joshualitta7024152014-11-03 14:16:35 -0800546bool GrInOrderDrawBuffer::copySurface(GrSurface* dst,
547 GrSurface* src,
548 const SkIRect& srcRect,
549 const SkIPoint& dstPoint) {
bsalomon@google.com116ad842013-04-09 15:38:19 +0000550 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700551 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000552 cs->fSrcRect = srcRect;
553 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700554 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000555 return true;
joshualitta7024152014-11-03 14:16:35 -0800556 } else if (GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) {
557 GrDrawTarget::copySurface(dst, src, srcRect, dstPoint);
558 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000559 } else {
560 return false;
561 }
562}
563
joshualitt9853cce2014-11-17 14:22:48 -0800564bool GrInOrderDrawBuffer::canCopySurface(const GrSurface* dst,
565 const GrSurface* src,
joshualitta7024152014-11-03 14:16:35 -0800566 const SkIRect& srcRect,
567 const SkIPoint& dstPoint) {
568 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint) ||
569 GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000570}
571
bsalomonf2703d82014-10-28 14:33:06 -0700572void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000573 fDstGpu->initCopySurfaceDstDesc(src, desc);
574}
575
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000576void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
joshualitt9853cce2014-11-17 14:22:48 -0800577 size_t vertexStride,
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000578 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000579 // We use geometryHints() to know whether to flush the draw buffer. We
580 // can't flush if we are inside an unbalanced pushGeometrySource.
581 // Moreover, flushing blows away vertex and index data that was
582 // previously reserved. So if the vertex or index data is pulled from
583 // reserved space and won't be released by this request then we can't
584 // flush.
585 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000586
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000587 bool unreleasedVertexSpace =
588 !vertexCount &&
589 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000590
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000591 bool unreleasedIndexSpace =
592 !indexCount &&
593 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000594
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000595 int vcount = vertexCount;
596 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000597
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000598 if (!insideGeoPush &&
599 !unreleasedVertexSpace &&
600 !unreleasedIndexSpace &&
joshualitt9853cce2014-11-17 14:22:48 -0800601 this->geometryHints(vertexStride, &vcount, &icount)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000602 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000603 }
604}
605
joshualitt9853cce2014-11-17 14:22:48 -0800606bool GrInOrderDrawBuffer::geometryHints(size_t vertexStride,
607 int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000608 int* indexCount) const {
609 // we will recommend a flush if the data could fit in a single
610 // preallocated buffer but none are left and it can't fit
611 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000612 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700613 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000614 int32_t currIndices = fIndexPool.currentBufferIndices();
615 if (*indexCount > currIndices &&
616 (!fIndexPool.preallocatedBuffersRemaining() &&
617 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
618
619 flush = true;
620 }
621 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000622 }
bsalomon49f085d2014-09-05 13:34:00 -0700623 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700624 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000625 if (*vertexCount > currVertices &&
626 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700627 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000628
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000629 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000630 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000631 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000632 }
633 return flush;
634}
635
jvanverth@google.coma6338982013-01-31 21:34:25 +0000636bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000637 int vertexCount,
638 void** vertices) {
639 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000640 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700641 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000642 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000643
jvanverth@google.coma6338982013-01-31 21:34:25 +0000644 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000645 vertexCount,
646 &poolState.fPoolVertexBuffer,
647 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700648 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000649}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000650
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000651bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
652 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000653 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700654 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000655 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000656
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000657 *indices = fIndexPool.makeSpace(indexCount,
658 &poolState.fPoolIndexBuffer,
659 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700660 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000661}
662
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000663void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
664 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000665 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000666
667 // If we get a release vertex space call then our current source should either be reserved
668 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800669 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000670
671 // When the caller reserved vertex buffer space we gave it back a pointer
672 // provided by the vertex buffer pool. At each draw we tracked the largest
673 // offset into the pool's pointer that was referenced. Now we return to the
674 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000675 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
joshualittd53a8272014-11-10 16:03:14 -0800676 fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000677 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000678 poolState.fPoolVertexBuffer = NULL;
679 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000680}
681
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000682void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
683 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000684 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000685
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000686 // If we get a release index space call then our current source should either be reserved
687 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800688 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000689
690 // Similar to releaseReservedVertexSpace we return any unused portion at
691 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000692 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
693 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
694 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000695 poolState.fPoolIndexBuffer = NULL;
696 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000697}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000698
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000699void GrInOrderDrawBuffer::geometrySourceWillPush() {
700 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
701 poolState.fUsedPoolVertexBytes = 0;
702 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000703#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000704 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
705 poolState.fPoolStartVertex = ~0;
706 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
707 poolState.fPoolStartIndex = ~0;
708#endif
709}
710
bsalomonb3e3a952014-09-19 11:10:40 -0700711void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000712 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000713 fGeoPoolStateStack.pop_back();
714 GeometryPoolState& poolState = fGeoPoolStateStack.back();
715 // we have to assume that any slack we had in our vertex/index data
716 // is now unreleasable because data may have been appended later in the
717 // pool.
joshualittd1aa8ff2014-11-04 07:47:55 -0800718 if (kReserved_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000719 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000720 }
joshualittd1aa8ff2014-11-04 07:47:55 -0800721 if (kReserved_GeometrySrcType == restoredState.fIndexSrc) {
joshualittd53a8272014-11-10 16:03:14 -0800722 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * restoredState.fIndexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000723 }
724}
725
bsalomonae59b772014-11-19 08:23:49 -0800726bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
727 GrGpu::DrawType drawType,
joshualitt54e0c122014-11-19 09:38:51 -0800728 const GrClipMaskManager::ScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800729 const GrDeviceCoordTexture* dstCopy) {
joshualitt54e0c122014-11-19 09:38:51 -0800730 SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(ds, fDstGpu, scissor, dstCopy,
731 drawType));
bsalomonae59b772014-11-19 08:23:49 -0800732 if (!optState) {
733 return false;
734 }
735 if (!fLastState || *optState != *fLastState) {
736 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (optState));
737 fLastState.reset(SkRef(optState.get()));
joshualittd53a8272014-11-10 16:03:14 -0800738 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700739 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700740 }
bsalomonae59b772014-11-19 08:23:49 -0800741 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000742}
743
cdalton6819df32014-10-15 13:43:48 -0700744void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
745 SkASSERT(!fCmdBuffer.empty());
746 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700747 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
748 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700749 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700750 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700751 }
mtklein07894c42014-10-13 14:00:42 -0700752}