blob: 7535a8d0617cb4d4211acce6313846db167bd7e5 [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
joshualitt9853cce2014-11-17 14:22:48 -0800193int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds,
194 const DrawInfo& info,
joshualitt2c93efe2014-11-06 12:57:13 -0800195 const GrClipMaskManager::ScissorState& scissorState) {
cdalton6819df32014-10-15 13:43:48 -0700196 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000197 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000198
bsalomon@google.com934c5702012-03-20 21:17:58 +0000199 const GeometrySrcState& geomSrc = this->getGeomSrc();
200
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000201 // we only attempt to concat the case when reserved verts are used with a client-specified index
202 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
203 // between draws.
204 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
205 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
206 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000207 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000208 // Check if there is a draw info that is compatible that uses the same VB from the pool and
209 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700210 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000211 return 0;
212 }
213
cdalton6819df32014-10-15 13:43:48 -0700214 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000215 GeometryPoolState& poolState = fGeoPoolStateStack.back();
216 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
217
cdalton6819df32014-10-15 13:43:48 -0700218 if (!draw->fInfo.isInstanced() ||
219 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
220 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
joshualitt7eb8c7b2014-11-18 14:24:27 -0800221 draw->fInfo.vertexBuffer() != vertexBuffer ||
222 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer ||
joshualitt2c93efe2014-11-06 12:57:13 -0800223 draw->fScissorState != scissorState) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000224 return 0;
225 }
226 // info does not yet account for the offset from the start of the pool's VB while the previous
227 // draw record does.
228 int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
cdalton6819df32014-10-15 13:43:48 -0700229 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != adjustedStartVertex) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000230 return 0;
231 }
232
cdalton6819df32014-10-15 13:43:48 -0700233 SkASSERT(poolState.fPoolStartVertex == draw->fInfo.startVertex() + draw->fInfo.vertexCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000234
235 // how many instances can be concat'ed onto draw given the size of the index buffer
236 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700237 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000238 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000239
240 // update the amount of reserved vertex data actually referenced in draws
joshualitt9853cce2014-11-17 14:22:48 -0800241 size_t vertexBytes = instancesToConcat * info.verticesPerInstance() * ds.getVertexStride();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000242 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000243
cdalton6819df32014-10-15 13:43:48 -0700244 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000245
246 // update last fGpuCmdMarkers to include any additional trace markers that have been added
247 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700248 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000249 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
250 } else {
251 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700252 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000253 }
254 }
255
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000256 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000257}
258
joshualitt9853cce2014-11-17 14:22:48 -0800259void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
260 const DrawInfo& info,
joshualitt2c93efe2014-11-06 12:57:13 -0800261 const GrClipMaskManager::ScissorState& scissorState) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800262 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
263
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000264 GeometryPoolState& poolState = fGeoPoolStateStack.back();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000265
bsalomonae59b772014-11-19 08:23:49 -0800266 if (!this->recordStateAndShouldDraw(ds, GrGpu::PrimTypeToDrawType(info.primitiveType()),
267 info.getDstCopy())) {
268 return;
269 }
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?
bsalomonae59b772014-11-19 08:23:49 -0800305 if (!this->recordStateAndShouldDraw(ds, GrGpu::kStencilPath_DrawType, NULL)) {
306 return;
307 }
cdalton6819df32014-10-15 13:43:48 -0700308 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800309 sp->fScissorState = scissorState;
310 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700311 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000312}
313
joshualitt9853cce2014-11-17 14:22:48 -0800314void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
315 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800316 const GrClipMaskManager::ScissorState& scissorState,
317 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700318 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000319 // TODO: Only compare the subset of GrDrawState relevant to path covering?
bsalomonae59b772014-11-19 08:23:49 -0800320 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, dstCopy)) {
321 return;
322 }
cdalton6819df32014-10-15 13:43:48 -0700323 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
bsalomon49f085d2014-09-05 13:34:00 -0700324 if (dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700325 dp->fDstCopy = *dstCopy;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000326 }
joshualitt2c93efe2014-11-06 12:57:13 -0800327 dp->fScissorState = scissorState;
328 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700329 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000330}
331
joshualitt9853cce2014-11-17 14:22:48 -0800332void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
333 const GrPathRange* pathRange,
joshualitt2c93efe2014-11-06 12:57:13 -0800334 const uint32_t indices[],
335 int count,
336 const float transforms[],
337 PathTransformType transformsType,
338 const GrClipMaskManager::ScissorState& scissorState,
339 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700340 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700341 SkASSERT(pathRange);
342 SkASSERT(indices);
343 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000344
bsalomonae59b772014-11-19 08:23:49 -0800345 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, dstCopy)) {
346 return;
347 }
cdalton6819df32014-10-15 13:43:48 -0700348
cdalton3fc6a2f2014-11-13 11:54:20 -0800349 uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
350 float* savedTransforms = fPathTransformBuffer.append(count *
351 GrPathRendering::PathTransformSize(transformsType), transforms);
cdalton6819df32014-10-15 13:43:48 -0700352
cdalton3fc6a2f2014-11-13 11:54:20 -0800353 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
354 // The previous command was also DrawPaths. Try to collapse this call into the one
355 // before. Note that stencilling all the paths at once, then covering, may not be
356 // equivalent to two separate draw calls if there is overlap. Blending won't work,
357 // and the combined calls may also cancel each other's winding numbers in some
358 // places. For now the winding numbers are only an issue if the fill is even/odd,
359 // because DrawPaths is currently only used for glyphs, and glyphs in the same
360 // font tend to all wind in the same direction.
361 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
362 if (pathRange == previous->pathRange() &&
363 transformsType == previous->fTransformsType &&
364 scissorState == previous->fScissorState &&
365 stencilSettings == previous->fStencilSettings &&
366 path_fill_type_is_winding(stencilSettings) &&
joshualitt9853cce2014-11-17 14:22:48 -0800367 !ds.willBlendWithDst()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800368 // Fold this DrawPaths call into the one previous.
369 previous->fCount += count;
370 return;
371 }
372 }
373
374 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
375 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700376 dp->fCount = count;
cdalton3fc6a2f2014-11-13 11:54:20 -0800377 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700378 dp->fTransformsType = transformsType;
joshualitt2c93efe2014-11-06 12:57:13 -0800379 dp->fScissorState = scissorState;
380 dp->fStencilSettings = stencilSettings;
bsalomon49f085d2014-09-05 13:34:00 -0700381 if (dstCopy) {
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000382 dp->fDstCopy = *dstCopy;
383 }
cdalton6819df32014-10-15 13:43:48 -0700384
385 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000386}
387
bsalomon63b21962014-11-05 07:05:34 -0800388void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
389 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800390 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000391 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000392 if (NULL == rect) {
393 // We could do something smart and remove previous draws and clears to
394 // the current render target. If we get that smart we have to make sure
395 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000396 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000397 rect = &r;
398 }
cdalton6819df32014-10-15 13:43:48 -0700399 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000400 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000401 clr->fColor = color;
402 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000403 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700404 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000405}
406
joshualitt6db519c2014-10-29 08:48:18 -0700407void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
408 bool insideClip,
409 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800410 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700411 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
412 clr->fRect = rect;
413 clr->fInsideClip = insideClip;
414 this->recordTraceMarkersIfNecessary();
415}
416
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000417void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800418 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000419 if (!this->caps()->discardRenderTargetSupport()) {
420 return;
421 }
cdalton6819df32014-10-15 13:43:48 -0700422 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000423 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700424 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000425}
426
joshualitt7eb8c7b2014-11-18 14:24:27 -0800427void GrInOrderDrawBuffer::setDrawBuffers(DrawInfo* info) {
428 GeometryPoolState& poolState = fGeoPoolStateStack.back();
429 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
430 info->setVertexBuffer(this->getGeomSrc().fVertexBuffer);
431 } else {
432 info->setVertexBuffer(poolState.fPoolVertexBuffer);
433 }
434
435 if (info->isIndexed()) {
436 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
437 info->setIndexBuffer(this->getGeomSrc().fIndexBuffer);
438 } else {
439 info->setIndexBuffer(poolState.fPoolIndexBuffer);
440 }
441 }
442}
443
reed@google.comac10a2d2010-12-22 21:39:39 +0000444void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000445 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000446 this->resetVertexSource();
447 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700448
449 fCmdBuffer.reset();
bsalomonae59b772014-11-19 08:23:49 -0800450 fLastState.reset(NULL);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000451 fVertexPool.reset();
452 fIndexPool.reset();
cdalton3fc6a2f2014-11-13 11:54:20 -0800453 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
454 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000455 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000456}
457
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000458void GrInOrderDrawBuffer::flush() {
459 if (fFlushing) {
460 return;
461 }
462
jvanverth8e80d172014-06-19 12:01:10 -0700463 this->getContext()->getFontCache()->updateTextures();
464
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000465 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
466 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000467
cdalton6819df32014-10-15 13:43:48 -0700468 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000469 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000470 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000471
472 GrAutoTRestore<bool> flushRestore(&fFlushing);
473 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000474
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000475 fVertexPool.unmap();
476 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000477
cdalton6819df32014-10-15 13:43:48 -0700478 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000479
cdalton6819df32014-10-15 13:43:48 -0700480 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700481 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700482
bsalomonae59b772014-11-19 08:23:49 -0800483 // Updated every time we find a set state cmd to reflect the current state in the playback
484 // stream.
joshualittd53a8272014-11-10 16:03:14 -0800485 SkAutoTUnref<const GrOptDrawState> currentOptState;
486
cdalton6819df32014-10-15 13:43:48 -0700487 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000488 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700489 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700490 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700491 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000492 newMarker.fMarker = traceString.c_str();
493 fDstGpu->addGpuTraceMarker(&newMarker);
494 ++currCmdMarker;
495 }
cdalton6819df32014-10-15 13:43:48 -0700496
joshualittd53a8272014-11-10 16:03:14 -0800497 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800498 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomonae59b772014-11-19 08:23:49 -0800499 currentOptState.reset(SkRef(ss->fState.get()));
joshualittd53a8272014-11-10 16:03:14 -0800500 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800501 iter->execute(this, currentOptState.get());
joshualittd53a8272014-11-10 16:03:14 -0800502 }
cdalton6819df32014-10-15 13:43:48 -0700503
504 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000505 fDstGpu->removeGpuTraceMarker(&newMarker);
506 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000507 }
mtkleinf439c772014-10-14 14:29:30 -0700508
cdalton6819df32014-10-15 13:43:48 -0700509 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000510 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000511
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000512 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000513 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000514}
515
cdalton3fc6a2f2014-11-13 11:54:20 -0800516void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
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) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800522 buf->fDstGpu->stencilPath(*optState, this->path(), fScissorState, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700523}
524
cdalton3fc6a2f2014-11-13 11:54:20 -0800525void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
526 const GrOptDrawState* optState) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800527 buf->fDstGpu->drawPath(*optState, this->path(), fScissorState, fStencilSettings,
528 fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700529}
530
cdalton3fc6a2f2014-11-13 11:54:20 -0800531void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
532 const GrOptDrawState* optState) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800533 buf->fDstGpu->drawPaths(*optState, this->pathRange(),
534 &buf->fPathIndexBuffer[fIndicesLocation], fCount,
535 &buf->fPathTransformBuffer[fTransformsLocation], fTransformsType,
536 fScissorState, fStencilSettings, fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700537}
538
cdalton3fc6a2f2014-11-13 11:54:20 -0800539void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700540}
541
cdalton3fc6a2f2014-11-13 11:54:20 -0800542void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700543 if (GrColor_ILLEGAL == fColor) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800544 buf->fDstGpu->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700545 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800546 buf->fDstGpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700547 }
548}
549
cdalton3fc6a2f2014-11-13 11:54:20 -0800550void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
551 const GrOptDrawState*) {
552 buf->fDstGpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700553}
554
cdalton3fc6a2f2014-11-13 11:54:20 -0800555void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
556 buf->fDstGpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700557}
558
joshualitta7024152014-11-03 14:16:35 -0800559bool GrInOrderDrawBuffer::copySurface(GrSurface* dst,
560 GrSurface* src,
561 const SkIRect& srcRect,
562 const SkIPoint& dstPoint) {
bsalomon@google.com116ad842013-04-09 15:38:19 +0000563 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700564 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000565 cs->fSrcRect = srcRect;
566 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700567 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000568 return true;
joshualitta7024152014-11-03 14:16:35 -0800569 } else if (GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) {
570 GrDrawTarget::copySurface(dst, src, srcRect, dstPoint);
571 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000572 } else {
573 return false;
574 }
575}
576
joshualitt9853cce2014-11-17 14:22:48 -0800577bool GrInOrderDrawBuffer::canCopySurface(const GrSurface* dst,
578 const GrSurface* src,
joshualitta7024152014-11-03 14:16:35 -0800579 const SkIRect& srcRect,
580 const SkIPoint& dstPoint) {
581 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint) ||
582 GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000583}
584
bsalomonf2703d82014-10-28 14:33:06 -0700585void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000586 fDstGpu->initCopySurfaceDstDesc(src, desc);
587}
588
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000589void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
joshualitt9853cce2014-11-17 14:22:48 -0800590 size_t vertexStride,
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000591 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000592 // We use geometryHints() to know whether to flush the draw buffer. We
593 // can't flush if we are inside an unbalanced pushGeometrySource.
594 // Moreover, flushing blows away vertex and index data that was
595 // previously reserved. So if the vertex or index data is pulled from
596 // reserved space and won't be released by this request then we can't
597 // flush.
598 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000599
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000600 bool unreleasedVertexSpace =
601 !vertexCount &&
602 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000603
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000604 bool unreleasedIndexSpace =
605 !indexCount &&
606 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000607
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000608 int vcount = vertexCount;
609 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000610
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000611 if (!insideGeoPush &&
612 !unreleasedVertexSpace &&
613 !unreleasedIndexSpace &&
joshualitt9853cce2014-11-17 14:22:48 -0800614 this->geometryHints(vertexStride, &vcount, &icount)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000615 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000616 }
617}
618
joshualitt9853cce2014-11-17 14:22:48 -0800619bool GrInOrderDrawBuffer::geometryHints(size_t vertexStride,
620 int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000621 int* indexCount) const {
622 // we will recommend a flush if the data could fit in a single
623 // preallocated buffer but none are left and it can't fit
624 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000625 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700626 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000627 int32_t currIndices = fIndexPool.currentBufferIndices();
628 if (*indexCount > currIndices &&
629 (!fIndexPool.preallocatedBuffersRemaining() &&
630 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
631
632 flush = true;
633 }
634 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000635 }
bsalomon49f085d2014-09-05 13:34:00 -0700636 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700637 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000638 if (*vertexCount > currVertices &&
639 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700640 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000641
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000642 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000643 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000644 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000645 }
646 return flush;
647}
648
jvanverth@google.coma6338982013-01-31 21:34:25 +0000649bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000650 int vertexCount,
651 void** vertices) {
652 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000653 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700654 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000655 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000656
jvanverth@google.coma6338982013-01-31 21:34:25 +0000657 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000658 vertexCount,
659 &poolState.fPoolVertexBuffer,
660 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700661 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000662}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000663
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000664bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
665 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000666 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700667 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000668 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000669
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000670 *indices = fIndexPool.makeSpace(indexCount,
671 &poolState.fPoolIndexBuffer,
672 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700673 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000674}
675
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000676void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
677 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000678 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000679
680 // If we get a release vertex space call then our current source should either be reserved
681 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800682 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000683
684 // When the caller reserved vertex buffer space we gave it back a pointer
685 // provided by the vertex buffer pool. At each draw we tracked the largest
686 // offset into the pool's pointer that was referenced. Now we return to the
687 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000688 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
joshualittd53a8272014-11-10 16:03:14 -0800689 fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000690 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000691 poolState.fPoolVertexBuffer = NULL;
692 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000693}
694
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000695void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
696 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000697 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000698
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000699 // If we get a release index space call then our current source should either be reserved
700 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800701 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000702
703 // Similar to releaseReservedVertexSpace we return any unused portion at
704 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000705 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
706 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
707 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000708 poolState.fPoolIndexBuffer = NULL;
709 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000710}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000711
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000712void GrInOrderDrawBuffer::geometrySourceWillPush() {
713 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
714 poolState.fUsedPoolVertexBytes = 0;
715 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000716#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000717 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
718 poolState.fPoolStartVertex = ~0;
719 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
720 poolState.fPoolStartIndex = ~0;
721#endif
722}
723
bsalomonb3e3a952014-09-19 11:10:40 -0700724void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000725 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000726 fGeoPoolStateStack.pop_back();
727 GeometryPoolState& poolState = fGeoPoolStateStack.back();
728 // we have to assume that any slack we had in our vertex/index data
729 // is now unreleasable because data may have been appended later in the
730 // pool.
joshualittd1aa8ff2014-11-04 07:47:55 -0800731 if (kReserved_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000732 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000733 }
joshualittd1aa8ff2014-11-04 07:47:55 -0800734 if (kReserved_GeometrySrcType == restoredState.fIndexSrc) {
joshualittd53a8272014-11-10 16:03:14 -0800735 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * restoredState.fIndexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000736 }
737}
738
bsalomonae59b772014-11-19 08:23:49 -0800739bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
740 GrGpu::DrawType drawType,
741 const GrDeviceCoordTexture* dstCopy) {
742 SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(ds, fDstGpu, dstCopy, drawType));
743 if (!optState) {
744 return false;
745 }
746 if (!fLastState || *optState != *fLastState) {
747 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (optState));
748 fLastState.reset(SkRef(optState.get()));
joshualittd53a8272014-11-10 16:03:14 -0800749 if (dstCopy) {
750 ss->fDstCopy = *dstCopy;
751 }
752 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700753 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700754 }
bsalomonae59b772014-11-19 08:23:49 -0800755 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000756}
757
cdalton6819df32014-10-15 13:43:48 -0700758void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
759 SkASSERT(!fCmdBuffer.empty());
760 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700761 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
762 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700763 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700764 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700765 }
mtklein07894c42014-10-13 14:00:42 -0700766}