blob: 624c77476367c113d88900bf63720d41aaf4395a [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)
bsalomon932f8662014-11-24 06:47:48 -080023 , fPrevState(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,
cdalton55b24af2014-11-25 11:00:56 -0800327 const void* indices,
328 PathIndexType indexType,
329 const float transformValues[],
330 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800331 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800332 const GrClipMaskManager::ScissorState& scissorState,
333 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700334 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700335 SkASSERT(pathRange);
336 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800337 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000338
joshualitt54e0c122014-11-19 09:38:51 -0800339 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800340 return;
341 }
cdalton6819df32014-10-15 13:43:48 -0700342
cdalton55b24af2014-11-25 11:00:56 -0800343 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
344 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
345 // Add padding to the index buffer so the indices are aligned properly.
346 fPathIndexBuffer.append(indexBytes - misalign);
347 }
348
349 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
350 reinterpret_cast<const char*>(indices));
351 float* savedTransforms = fPathTransformBuffer.append(
352 count * GrPathRendering::PathTransformSize(transformType),
353 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700354
cdalton3fc6a2f2014-11-13 11:54:20 -0800355 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
356 // The previous command was also DrawPaths. Try to collapse this call into the one
357 // before. Note that stencilling all the paths at once, then covering, may not be
358 // equivalent to two separate draw calls if there is overlap. Blending won't work,
359 // and the combined calls may also cancel each other's winding numbers in some
360 // places. For now the winding numbers are only an issue if the fill is even/odd,
361 // because DrawPaths is currently only used for glyphs, and glyphs in the same
362 // font tend to all wind in the same direction.
363 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
364 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800365 indexType == previous->fIndexType &&
366 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800367 stencilSettings == previous->fStencilSettings &&
368 path_fill_type_is_winding(stencilSettings) &&
joshualitt9853cce2014-11-17 14:22:48 -0800369 !ds.willBlendWithDst()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800370 // Fold this DrawPaths call into the one previous.
371 previous->fCount += count;
372 return;
373 }
374 }
375
376 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
377 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800378 dp->fIndexType = indexType;
cdalton3fc6a2f2014-11-13 11:54:20 -0800379 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800380 dp->fTransformType = transformType;
381 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800382 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700383
384 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000385}
386
bsalomon63b21962014-11-05 07:05:34 -0800387void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
388 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800389 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000390 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000391 if (NULL == rect) {
392 // We could do something smart and remove previous draws and clears to
393 // the current render target. If we get that smart we have to make sure
394 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000395 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000396 rect = &r;
397 }
cdalton6819df32014-10-15 13:43:48 -0700398 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000399 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000400 clr->fColor = color;
401 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000402 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700403 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000404}
405
joshualitt6db519c2014-10-29 08:48:18 -0700406void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
407 bool insideClip,
408 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800409 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700410 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
411 clr->fRect = rect;
412 clr->fInsideClip = insideClip;
413 this->recordTraceMarkersIfNecessary();
414}
415
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000416void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800417 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000418 if (!this->caps()->discardRenderTargetSupport()) {
419 return;
420 }
cdalton6819df32014-10-15 13:43:48 -0700421 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000422 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700423 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000424}
425
joshualitt7eb8c7b2014-11-18 14:24:27 -0800426void GrInOrderDrawBuffer::setDrawBuffers(DrawInfo* info) {
427 GeometryPoolState& poolState = fGeoPoolStateStack.back();
428 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
429 info->setVertexBuffer(this->getGeomSrc().fVertexBuffer);
430 } else {
431 info->setVertexBuffer(poolState.fPoolVertexBuffer);
432 }
433
434 if (info->isIndexed()) {
435 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
436 info->setIndexBuffer(this->getGeomSrc().fIndexBuffer);
437 } else {
438 info->setIndexBuffer(poolState.fPoolIndexBuffer);
439 }
440 }
441}
442
reed@google.comac10a2d2010-12-22 21:39:39 +0000443void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000444 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000445 this->resetVertexSource();
446 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700447
448 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800449 fPrevState = NULL;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000450 fVertexPool.reset();
451 fIndexPool.reset();
cdalton3fc6a2f2014-11-13 11:54:20 -0800452 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
453 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000454 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000455}
456
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000457void GrInOrderDrawBuffer::flush() {
458 if (fFlushing) {
459 return;
460 }
461
jvanverth8e80d172014-06-19 12:01:10 -0700462 this->getContext()->getFontCache()->updateTextures();
463
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000464 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
465 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000466
cdalton6819df32014-10-15 13:43:48 -0700467 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000468 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000469 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000470
471 GrAutoTRestore<bool> flushRestore(&fFlushing);
472 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000473
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000474 fVertexPool.unmap();
475 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000476
cdalton6819df32014-10-15 13:43:48 -0700477 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000478
cdalton6819df32014-10-15 13:43:48 -0700479 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700480 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700481
bsalomonae59b772014-11-19 08:23:49 -0800482 // Updated every time we find a set state cmd to reflect the current state in the playback
483 // stream.
bsalomon932f8662014-11-24 06:47:48 -0800484 const GrOptDrawState* currentOptState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800485
cdalton6819df32014-10-15 13:43:48 -0700486 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000487 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700488 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700489 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700490 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000491 newMarker.fMarker = traceString.c_str();
492 fDstGpu->addGpuTraceMarker(&newMarker);
493 ++currCmdMarker;
494 }
cdalton6819df32014-10-15 13:43:48 -0700495
joshualittd53a8272014-11-10 16:03:14 -0800496 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800497 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomon932f8662014-11-24 06:47:48 -0800498 currentOptState = &ss->fState;
joshualittd53a8272014-11-10 16:03:14 -0800499 } else {
bsalomon932f8662014-11-24 06:47:48 -0800500 iter->execute(this, currentOptState);
joshualittd53a8272014-11-10 16:03:14 -0800501 }
cdalton6819df32014-10-15 13:43:48 -0700502
503 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000504 fDstGpu->removeGpuTraceMarker(&newMarker);
505 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000506 }
mtkleinf439c772014-10-14 14:29:30 -0700507
cdalton6819df32014-10-15 13:43:48 -0700508 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000509 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000510
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000511 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000512 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000513}
514
cdalton3fc6a2f2014-11-13 11:54:20 -0800515void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800516 SkASSERT(optState);
joshualitt54e0c122014-11-19 09:38:51 -0800517 buf->fDstGpu->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700518}
519
cdalton3fc6a2f2014-11-13 11:54:20 -0800520void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
521 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800522 SkASSERT(optState);
joshualitt54e0c122014-11-19 09:38:51 -0800523 buf->fDstGpu->stencilPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700524}
525
cdalton3fc6a2f2014-11-13 11:54:20 -0800526void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
527 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800528 SkASSERT(optState);
joshualitt9176e2c2014-11-20 07:28:52 -0800529 buf->fDstGpu->drawPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700530}
531
cdalton3fc6a2f2014-11-13 11:54:20 -0800532void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
533 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800534 SkASSERT(optState);
cdalton3fc6a2f2014-11-13 11:54:20 -0800535 buf->fDstGpu->drawPaths(*optState, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800536 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
537 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
538 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700539}
540
bsalomon932f8662014-11-24 06:47:48 -0800541void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {}
cdalton6819df32014-10-15 13:43:48 -0700542
cdalton3fc6a2f2014-11-13 11:54:20 -0800543void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700544 if (GrColor_ILLEGAL == fColor) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800545 buf->fDstGpu->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700546 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800547 buf->fDstGpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700548 }
549}
550
cdalton3fc6a2f2014-11-13 11:54:20 -0800551void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
552 const GrOptDrawState*) {
553 buf->fDstGpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700554}
555
cdalton3fc6a2f2014-11-13 11:54:20 -0800556void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
557 buf->fDstGpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700558}
559
joshualitta7024152014-11-03 14:16:35 -0800560bool GrInOrderDrawBuffer::copySurface(GrSurface* dst,
561 GrSurface* src,
562 const SkIRect& srcRect,
563 const SkIPoint& dstPoint) {
bsalomon@google.com116ad842013-04-09 15:38:19 +0000564 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700565 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000566 cs->fSrcRect = srcRect;
567 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700568 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000569 return true;
joshualitta7024152014-11-03 14:16:35 -0800570 } else if (GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) {
571 GrDrawTarget::copySurface(dst, src, srcRect, dstPoint);
572 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000573 } else {
574 return false;
575 }
576}
577
joshualitt9853cce2014-11-17 14:22:48 -0800578bool GrInOrderDrawBuffer::canCopySurface(const GrSurface* dst,
579 const GrSurface* src,
joshualitta7024152014-11-03 14:16:35 -0800580 const SkIRect& srcRect,
581 const SkIPoint& dstPoint) {
582 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint) ||
583 GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000584}
585
bsalomonf2703d82014-10-28 14:33:06 -0700586void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000587 fDstGpu->initCopySurfaceDstDesc(src, desc);
588}
589
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000590void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
joshualitt9853cce2014-11-17 14:22:48 -0800591 size_t vertexStride,
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000592 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000593 // We use geometryHints() to know whether to flush the draw buffer. We
594 // can't flush if we are inside an unbalanced pushGeometrySource.
595 // Moreover, flushing blows away vertex and index data that was
596 // previously reserved. So if the vertex or index data is pulled from
597 // reserved space and won't be released by this request then we can't
598 // flush.
599 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000600
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000601 bool unreleasedVertexSpace =
602 !vertexCount &&
603 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000604
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000605 bool unreleasedIndexSpace =
606 !indexCount &&
607 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000608
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000609 int vcount = vertexCount;
610 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000611
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000612 if (!insideGeoPush &&
613 !unreleasedVertexSpace &&
614 !unreleasedIndexSpace &&
joshualitt9853cce2014-11-17 14:22:48 -0800615 this->geometryHints(vertexStride, &vcount, &icount)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000616 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000617 }
618}
619
joshualitt9853cce2014-11-17 14:22:48 -0800620bool GrInOrderDrawBuffer::geometryHints(size_t vertexStride,
621 int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000622 int* indexCount) const {
623 // we will recommend a flush if the data could fit in a single
624 // preallocated buffer but none are left and it can't fit
625 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000626 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700627 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000628 int32_t currIndices = fIndexPool.currentBufferIndices();
629 if (*indexCount > currIndices &&
630 (!fIndexPool.preallocatedBuffersRemaining() &&
631 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
632
633 flush = true;
634 }
635 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000636 }
bsalomon49f085d2014-09-05 13:34:00 -0700637 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700638 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000639 if (*vertexCount > currVertices &&
640 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700641 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000642
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000643 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000644 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000645 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000646 }
647 return flush;
648}
649
jvanverth@google.coma6338982013-01-31 21:34:25 +0000650bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000651 int vertexCount,
652 void** vertices) {
653 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000654 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700655 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000656 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000657
jvanverth@google.coma6338982013-01-31 21:34:25 +0000658 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000659 vertexCount,
660 &poolState.fPoolVertexBuffer,
661 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700662 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000663}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000664
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000665bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
666 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000667 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700668 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000669 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000670
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000671 *indices = fIndexPool.makeSpace(indexCount,
672 &poolState.fPoolIndexBuffer,
673 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700674 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000675}
676
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000677void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
678 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000679 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000680
681 // If we get a release vertex space call then our current source should either be reserved
682 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800683 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000684
685 // When the caller reserved vertex buffer space we gave it back a pointer
686 // provided by the vertex buffer pool. At each draw we tracked the largest
687 // offset into the pool's pointer that was referenced. Now we return to the
688 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000689 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
joshualittd53a8272014-11-10 16:03:14 -0800690 fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000691 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000692 poolState.fPoolVertexBuffer = NULL;
693 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000694}
695
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000696void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
697 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000698 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000699
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000700 // If we get a release index space call then our current source should either be reserved
701 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800702 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000703
704 // Similar to releaseReservedVertexSpace we return any unused portion at
705 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000706 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
707 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
708 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000709 poolState.fPoolIndexBuffer = NULL;
710 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000711}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000712
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000713void GrInOrderDrawBuffer::geometrySourceWillPush() {
714 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
715 poolState.fUsedPoolVertexBytes = 0;
716 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000717#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000718 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
719 poolState.fPoolStartVertex = ~0;
720 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
721 poolState.fPoolStartIndex = ~0;
722#endif
723}
724
bsalomonb3e3a952014-09-19 11:10:40 -0700725void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000726 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000727 fGeoPoolStateStack.pop_back();
728 GeometryPoolState& poolState = fGeoPoolStateStack.back();
729 // we have to assume that any slack we had in our vertex/index data
730 // is now unreleasable because data may have been appended later in the
731 // pool.
joshualittd1aa8ff2014-11-04 07:47:55 -0800732 if (kReserved_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000733 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000734 }
joshualittd1aa8ff2014-11-04 07:47:55 -0800735 if (kReserved_GeometrySrcType == restoredState.fIndexSrc) {
joshualittd53a8272014-11-10 16:03:14 -0800736 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * restoredState.fIndexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000737 }
738}
739
bsalomonae59b772014-11-19 08:23:49 -0800740bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
741 GrGpu::DrawType drawType,
joshualitt54e0c122014-11-19 09:38:51 -0800742 const GrClipMaskManager::ScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800743 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800744 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
745 (ds, fDstGpu, scissor, dstCopy, drawType));
746 if (ss->fState.mustSkip()) {
747 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800748 return false;
749 }
bsalomon932f8662014-11-24 06:47:48 -0800750 if (fPrevState && *fPrevState == ss->fState) {
751 fCmdBuffer.pop_back();
752 } else {
753 fPrevState = &ss->fState;
cdalton6819df32014-10-15 13:43:48 -0700754 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700755 }
bsalomonae59b772014-11-19 08:23:49 -0800756 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000757}
758
cdalton6819df32014-10-15 13:43:48 -0700759void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
760 SkASSERT(!fCmdBuffer.empty());
761 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700762 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
763 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700764 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700765 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700766 }
mtklein07894c42014-10-13 14:00:42 -0700767}