blob: e5d67952147866cfe221b3cfb4ca20263daa7ac5 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00006 */
7
reed@google.comac10a2d2010-12-22 21:39:39 +00008#include "GrInOrderDrawBuffer.h"
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +00009
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000010#include "GrBufferAllocPool.h"
joshualitt5478d422014-11-14 16:00:38 -080011#include "GrDefaultGeoProcFactory.h"
bsalomon@google.comc26d94f2013-03-25 18:19:00 +000012#include "GrDrawTargetCaps.h"
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000013#include "GrGpu.h"
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000014#include "GrTemplates.h"
joshualittd53a8272014-11-10 16:03:14 -080015#include "GrTextStrike.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016#include "GrTexture.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000018GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
bsalomon@google.com471d4712011-08-23 15:45:25 +000019 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000020 GrIndexBufferAllocPool* indexPool)
joshualitt6db519c2014-10-29 08:48:18 -070021 : INHERITED(gpu->getContext())
cdalton6819df32014-10-15 13:43:48 -070022 , fCmdBuffer(kCmdBufferInitialSizeInBytes)
23 , fLastState(NULL)
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000024 , fDstGpu(gpu)
robertphillips@google.com69705572012-03-21 19:46:50 +000025 , fVertexPool(*vertexPool)
26 , fIndexPool(*indexPool)
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +000027 , fFlushing(false)
28 , fDrawID(0) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000029
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000030 fDstGpu->ref();
bsalomon@google.combcce8922013-03-25 15:38:39 +000031 fCaps.reset(SkRef(fDstGpu->caps()));
bsalomon@google.com18c9c192011-09-22 21:01:31 +000032
bsalomon49f085d2014-09-05 13:34:00 -070033 SkASSERT(vertexPool);
34 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000035
cdalton3fc6a2f2014-11-13 11:54:20 -080036 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
37 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
38
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000039 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
40 poolState.fUsedPoolVertexBytes = 0;
41 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000042#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000043 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
44 poolState.fPoolStartVertex = ~0;
45 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
46 poolState.fPoolStartIndex = ~0;
47#endif
bsalomon@google.coma4f6b102012-06-26 21:04:22 +000048 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000049}
50
51GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000052 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000053 // This must be called by before the GrDrawTarget destructor
54 this->releaseGeometry();
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000055 fDstGpu->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +000056}
57
bsalomon@google.com934c5702012-03-20 21:17:58 +000058////////////////////////////////////////////////////////////////////////////////
59
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000060namespace {
61void get_vertex_bounds(const void* vertices,
62 size_t vertexSize,
63 int vertexCount,
64 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000065 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000066 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000067 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000068 bounds->fLeft = bounds->fRight = point->fX;
69 bounds->fTop = bounds->fBottom = point->fY;
70 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000071 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000072 bounds->growToInclude(point->fX, point->fY);
73 }
74}
bsalomon@google.com934c5702012-03-20 21:17:58 +000075}
76
bsalomon62c447d2014-08-08 08:08:50 -070077/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
78 have explicit local coords and sometimes not. We *could* always provide explicit local coords
79 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
80 haven't seen a use case which frequently switches between local rect and no local rect draws.
81
82 The color param is used to determine whether the opaque hint can be set on the draw state.
83 The caller must populate the vertex colors itself.
84
85 The vertex attrib order is always pos, color, [local coords].
86 */
87static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
joshualitt5478d422014-11-14 16:00:38 -080088 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
89 GrDefaultGeoProcFactory::kColor_GPType;
90 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
91 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::CreateAndSetAttribs(drawState,
92 flags))->unref();
bsalomon62c447d2014-08-08 08:08:50 -070093 if (0xFF == GrColorUnpackA(color)) {
94 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
95 }
96}
robertphillips@google.com42903302013-04-20 12:26:07 +000097
cdalton3fc6a2f2014-11-13 11:54:20 -080098static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
99 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
100 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
101 if (isWinding) {
102 // Double check that it is in fact winding.
103 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
104 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
105 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
106 SkASSERT(!pathStencilSettings.isTwoSided());
107 }
108 return isWinding;
109}
110
111template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
112 // Assume the next time this buffer fills up it will use approximately the same amount
113 // of space as last time. Only resize if we're using less than a third of the
114 // allocated space, and leave enough for 50% growth over last time.
115 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
116 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
117 buffer->reset();
118 buffer->setReserve(reserve);
119 } else {
120 buffer->rewind();
121 }
122}
123
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000124enum {
125 kTraceCmdBit = 0x80,
126 kCmdMask = 0x7f,
127};
128
bsalomon62c447d2014-08-08 08:08:50 -0700129static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000130
bsalomon62c447d2014-08-08 08:08:50 -0700131static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000132
bsalomon62c447d2014-08-08 08:08:50 -0700133static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000134
joshualitt9853cce2014-11-17 14:22:48 -0800135void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
136 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000137 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000138 const SkMatrix* localMatrix) {
joshualitt9853cce2014-11-17 14:22:48 -0800139 GrDrawState::AutoRestoreEffects are(ds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000140
joshualitt9853cce2014-11-17 14:22:48 -0800141 GrColor color = ds->getColor();
142 set_vertex_attributes(ds, SkToBool(localRect), color);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000143
joshualitt9853cce2014-11-17 14:22:48 -0800144 AutoReleaseGeometry geo(this, 4, ds->getVertexStride(), 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000145 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700146 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000147 return;
148 }
149
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000150 // Go to device coords to allow batching across matrix changes
joshualitt9853cce2014-11-17 14:22:48 -0800151 SkMatrix matrix = ds->getViewMatrix();
bsalomon01c8da12014-08-04 09:21:30 -0700152
jvanverth@google.com39768252013-02-14 15:25:44 +0000153 // When the caller has provided an explicit source rect for a stage then we don't want to
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000154 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
155 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000156 GrDrawState::AutoViewMatrixRestore avmr;
joshualitt9853cce2014-11-17 14:22:48 -0800157 if (!avmr.setIdentity(ds)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000158 return;
159 }
160
joshualitt9853cce2014-11-17 14:22:48 -0800161 size_t vstride = ds->getVertexStride();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000162
egdaniel7b3d5ee2014-08-28 05:41:14 -0700163 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
164 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000165
166 SkRect devBounds;
167 // since we already computed the dev verts, set the bounds hint. This will help us avoid
168 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700169 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000170
bsalomon49f085d2014-09-05 13:34:00 -0700171 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700172 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
173 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000174 coords->setRectFan(localRect->fLeft, localRect->fTop,
175 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700176 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700177 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700178 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000179 }
180 }
181
bsalomon62c447d2014-08-08 08:08:50 -0700182 static const int kColorOffset = sizeof(SkPoint);
183 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
184 for (int i = 0; i < 4; ++i) {
185 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700186 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000187 }
188
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000189 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualitt9853cce2014-11-17 14:22:48 -0800190 this->drawIndexedInstances(ds, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000191}
192
joshualitt54e0c122014-11-19 09:38:51 -0800193int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700194 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000195 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000196
bsalomon@google.com934c5702012-03-20 21:17:58 +0000197 const GeometrySrcState& geomSrc = this->getGeomSrc();
198
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000199 // we only attempt to concat the case when reserved verts are used with a client-specified index
200 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
201 // between draws.
202 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
203 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
204 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000205 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000206 // Check if there is a draw info that is compatible that uses the same VB from the pool and
207 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700208 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000209 return 0;
210 }
211
cdalton6819df32014-10-15 13:43:48 -0700212 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000213 GeometryPoolState& poolState = fGeoPoolStateStack.back();
214 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
215
cdalton6819df32014-10-15 13:43:48 -0700216 if (!draw->fInfo.isInstanced() ||
217 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
218 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
joshualitt7eb8c7b2014-11-18 14:24:27 -0800219 draw->fInfo.vertexBuffer() != vertexBuffer ||
joshualitt54e0c122014-11-19 09:38:51 -0800220 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000221 return 0;
222 }
223 // info does not yet account for the offset from the start of the pool's VB while the previous
224 // draw record does.
225 int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
cdalton6819df32014-10-15 13:43:48 -0700226 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != adjustedStartVertex) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000227 return 0;
228 }
229
cdalton6819df32014-10-15 13:43:48 -0700230 SkASSERT(poolState.fPoolStartVertex == draw->fInfo.startVertex() + draw->fInfo.vertexCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000231
232 // how many instances can be concat'ed onto draw given the size of the index buffer
233 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700234 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000235 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000236
237 // update the amount of reserved vertex data actually referenced in draws
joshualitt9853cce2014-11-17 14:22:48 -0800238 size_t vertexBytes = instancesToConcat * info.verticesPerInstance() * ds.getVertexStride();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000239 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000240
cdalton6819df32014-10-15 13:43:48 -0700241 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000242
243 // update last fGpuCmdMarkers to include any additional trace markers that have been added
244 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700245 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000246 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
247 } else {
248 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700249 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000250 }
251 }
252
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000253 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000254}
255
joshualitt9853cce2014-11-17 14:22:48 -0800256void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
257 const DrawInfo& info,
joshualitt54e0c122014-11-19 09:38:51 -0800258 const ScissorState& scissorState) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800259 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
260
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000261 GeometryPoolState& poolState = fGeoPoolStateStack.back();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000262
bsalomonae59b772014-11-19 08:23:49 -0800263 if (!this->recordStateAndShouldDraw(ds, GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualitt54e0c122014-11-19 09:38:51 -0800264 scissorState, info.getDstCopy())) {
bsalomonae59b772014-11-19 08:23:49 -0800265 return;
266 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000267
bsalomonb3e3a952014-09-19 11:10:40 -0700268 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000269 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800270 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000271 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800272 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700273 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000274 } else {
275 return;
276 }
277 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800278 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000279 }
cdalton6819df32014-10-15 13:43:48 -0700280 this->recordTraceMarkersIfNecessary();
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000281
bsalomonb3e3a952014-09-19 11:10:40 -0700282 // Adjust the starting vertex and index when we are using reserved or array sources to
283 // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
284 if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
joshualitt9853cce2014-11-17 14:22:48 -0800285 size_t bytes = (info.vertexCount() + info.startVertex()) * ds.getVertexStride();
bsalomonb3e3a952014-09-19 11:10:40 -0700286 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700287 draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +0000288 }
bsalomonb3e3a952014-09-19 11:10:40 -0700289
290 if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) {
291 size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
292 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700293 draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000294 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000295}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000296
joshualitt9853cce2014-11-17 14:22:48 -0800297void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
298 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800299 const GrClipMaskManager::ScissorState& scissorState,
300 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000301 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualitt54e0c122014-11-19 09:38:51 -0800302 if (!this->recordStateAndShouldDraw(ds, GrGpu::kStencilPath_DrawType, scissorState, NULL)) {
bsalomonae59b772014-11-19 08:23:49 -0800303 return;
304 }
cdalton6819df32014-10-15 13:43:48 -0700305 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800306 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700307 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000308}
309
joshualitt9853cce2014-11-17 14:22:48 -0800310void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
311 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800312 const GrClipMaskManager::ScissorState& scissorState,
313 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700314 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000315 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt54e0c122014-11-19 09:38:51 -0800316 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800317 return;
318 }
cdalton6819df32014-10-15 13:43:48 -0700319 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
bsalomon49f085d2014-09-05 13:34:00 -0700320 if (dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700321 dp->fDstCopy = *dstCopy;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000322 }
joshualitt2c93efe2014-11-06 12:57:13 -0800323 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700324 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000325}
326
joshualitt9853cce2014-11-17 14:22:48 -0800327void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
328 const GrPathRange* pathRange,
joshualitt2c93efe2014-11-06 12:57:13 -0800329 const uint32_t indices[],
330 int count,
331 const float transforms[],
332 PathTransformType transformsType,
333 const GrClipMaskManager::ScissorState& scissorState,
334 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700335 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700336 SkASSERT(pathRange);
337 SkASSERT(indices);
338 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000339
joshualitt54e0c122014-11-19 09:38:51 -0800340 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800341 return;
342 }
cdalton6819df32014-10-15 13:43:48 -0700343
cdalton3fc6a2f2014-11-13 11:54:20 -0800344 uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
345 float* savedTransforms = fPathTransformBuffer.append(count *
346 GrPathRendering::PathTransformSize(transformsType), transforms);
cdalton6819df32014-10-15 13:43:48 -0700347
cdalton3fc6a2f2014-11-13 11:54:20 -0800348 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
349 // The previous command was also DrawPaths. Try to collapse this call into the one
350 // before. Note that stencilling all the paths at once, then covering, may not be
351 // equivalent to two separate draw calls if there is overlap. Blending won't work,
352 // and the combined calls may also cancel each other's winding numbers in some
353 // places. For now the winding numbers are only an issue if the fill is even/odd,
354 // because DrawPaths is currently only used for glyphs, and glyphs in the same
355 // font tend to all wind in the same direction.
356 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
357 if (pathRange == previous->pathRange() &&
358 transformsType == previous->fTransformsType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800359 stencilSettings == previous->fStencilSettings &&
360 path_fill_type_is_winding(stencilSettings) &&
joshualitt9853cce2014-11-17 14:22:48 -0800361 !ds.willBlendWithDst()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800362 // Fold this DrawPaths call into the one previous.
363 previous->fCount += count;
364 return;
365 }
366 }
367
368 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
369 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700370 dp->fCount = count;
cdalton3fc6a2f2014-11-13 11:54:20 -0800371 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdaltonb85a0aa2014-07-21 15:32:44 -0700372 dp->fTransformsType = transformsType;
joshualitt2c93efe2014-11-06 12:57:13 -0800373 dp->fStencilSettings = stencilSettings;
bsalomon49f085d2014-09-05 13:34:00 -0700374 if (dstCopy) {
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000375 dp->fDstCopy = *dstCopy;
376 }
cdalton6819df32014-10-15 13:43:48 -0700377
378 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000379}
380
bsalomon63b21962014-11-05 07:05:34 -0800381void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
382 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800383 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000384 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000385 if (NULL == rect) {
386 // We could do something smart and remove previous draws and clears to
387 // the current render target. If we get that smart we have to make sure
388 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000389 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000390 rect = &r;
391 }
cdalton6819df32014-10-15 13:43:48 -0700392 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000393 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000394 clr->fColor = color;
395 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000396 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700397 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000398}
399
joshualitt6db519c2014-10-29 08:48:18 -0700400void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
401 bool insideClip,
402 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800403 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700404 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
405 clr->fRect = rect;
406 clr->fInsideClip = insideClip;
407 this->recordTraceMarkersIfNecessary();
408}
409
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000410void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800411 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000412 if (!this->caps()->discardRenderTargetSupport()) {
413 return;
414 }
cdalton6819df32014-10-15 13:43:48 -0700415 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000416 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700417 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000418}
419
joshualitt7eb8c7b2014-11-18 14:24:27 -0800420void GrInOrderDrawBuffer::setDrawBuffers(DrawInfo* info) {
421 GeometryPoolState& poolState = fGeoPoolStateStack.back();
422 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
423 info->setVertexBuffer(this->getGeomSrc().fVertexBuffer);
424 } else {
425 info->setVertexBuffer(poolState.fPoolVertexBuffer);
426 }
427
428 if (info->isIndexed()) {
429 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
430 info->setIndexBuffer(this->getGeomSrc().fIndexBuffer);
431 } else {
432 info->setIndexBuffer(poolState.fPoolIndexBuffer);
433 }
434 }
435}
436
reed@google.comac10a2d2010-12-22 21:39:39 +0000437void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000438 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000439 this->resetVertexSource();
440 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700441
442 fCmdBuffer.reset();
bsalomonae59b772014-11-19 08:23:49 -0800443 fLastState.reset(NULL);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000444 fVertexPool.reset();
445 fIndexPool.reset();
cdalton3fc6a2f2014-11-13 11:54:20 -0800446 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
447 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000448 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000449}
450
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000451void GrInOrderDrawBuffer::flush() {
452 if (fFlushing) {
453 return;
454 }
455
jvanverth8e80d172014-06-19 12:01:10 -0700456 this->getContext()->getFontCache()->updateTextures();
457
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000458 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
459 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000460
cdalton6819df32014-10-15 13:43:48 -0700461 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000462 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000463 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000464
465 GrAutoTRestore<bool> flushRestore(&fFlushing);
466 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000467
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000468 fVertexPool.unmap();
469 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000470
cdalton6819df32014-10-15 13:43:48 -0700471 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000472
cdalton6819df32014-10-15 13:43:48 -0700473 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700474 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700475
bsalomonae59b772014-11-19 08:23:49 -0800476 // Updated every time we find a set state cmd to reflect the current state in the playback
477 // stream.
joshualittd53a8272014-11-10 16:03:14 -0800478 SkAutoTUnref<const GrOptDrawState> currentOptState;
479
cdalton6819df32014-10-15 13:43:48 -0700480 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000481 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700482 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700483 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700484 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000485 newMarker.fMarker = traceString.c_str();
486 fDstGpu->addGpuTraceMarker(&newMarker);
487 ++currCmdMarker;
488 }
cdalton6819df32014-10-15 13:43:48 -0700489
joshualittd53a8272014-11-10 16:03:14 -0800490 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800491 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomonae59b772014-11-19 08:23:49 -0800492 currentOptState.reset(SkRef(ss->fState.get()));
joshualittd53a8272014-11-10 16:03:14 -0800493 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800494 iter->execute(this, currentOptState.get());
joshualittd53a8272014-11-10 16:03:14 -0800495 }
cdalton6819df32014-10-15 13:43:48 -0700496
497 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000498 fDstGpu->removeGpuTraceMarker(&newMarker);
499 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000500 }
mtkleinf439c772014-10-14 14:29:30 -0700501
cdalton6819df32014-10-15 13:43:48 -0700502 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000503 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000504
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000505 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000506 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000507}
508
cdalton3fc6a2f2014-11-13 11:54:20 -0800509void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
joshualitt54e0c122014-11-19 09:38:51 -0800510 buf->fDstGpu->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700511}
512
cdalton3fc6a2f2014-11-13 11:54:20 -0800513void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
514 const GrOptDrawState* optState) {
joshualitt54e0c122014-11-19 09:38:51 -0800515 buf->fDstGpu->stencilPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700516}
517
cdalton3fc6a2f2014-11-13 11:54:20 -0800518void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
519 const GrOptDrawState* optState) {
joshualitt54e0c122014-11-19 09:38:51 -0800520 buf->fDstGpu->drawPath(*optState, this->path(), fStencilSettings,
cdalton3fc6a2f2014-11-13 11:54:20 -0800521 fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700522}
523
cdalton3fc6a2f2014-11-13 11:54:20 -0800524void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
525 const GrOptDrawState* optState) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800526 buf->fDstGpu->drawPaths(*optState, this->pathRange(),
527 &buf->fPathIndexBuffer[fIndicesLocation], fCount,
528 &buf->fPathTransformBuffer[fTransformsLocation], fTransformsType,
joshualitt54e0c122014-11-19 09:38:51 -0800529 fStencilSettings, fDstCopy.texture() ? &fDstCopy : NULL);
cdalton6819df32014-10-15 13:43:48 -0700530}
531
cdalton3fc6a2f2014-11-13 11:54:20 -0800532void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700533}
534
cdalton3fc6a2f2014-11-13 11:54:20 -0800535void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700536 if (GrColor_ILLEGAL == fColor) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800537 buf->fDstGpu->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700538 } else {
cdalton3fc6a2f2014-11-13 11:54:20 -0800539 buf->fDstGpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700540 }
541}
542
cdalton3fc6a2f2014-11-13 11:54:20 -0800543void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
544 const GrOptDrawState*) {
545 buf->fDstGpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700546}
547
cdalton3fc6a2f2014-11-13 11:54:20 -0800548void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
549 buf->fDstGpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700550}
551
joshualitta7024152014-11-03 14:16:35 -0800552bool GrInOrderDrawBuffer::copySurface(GrSurface* dst,
553 GrSurface* src,
554 const SkIRect& srcRect,
555 const SkIPoint& dstPoint) {
bsalomon@google.com116ad842013-04-09 15:38:19 +0000556 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700557 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000558 cs->fSrcRect = srcRect;
559 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700560 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000561 return true;
joshualitta7024152014-11-03 14:16:35 -0800562 } else if (GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) {
563 GrDrawTarget::copySurface(dst, src, srcRect, dstPoint);
564 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000565 } else {
566 return false;
567 }
568}
569
joshualitt9853cce2014-11-17 14:22:48 -0800570bool GrInOrderDrawBuffer::canCopySurface(const GrSurface* dst,
571 const GrSurface* src,
joshualitta7024152014-11-03 14:16:35 -0800572 const SkIRect& srcRect,
573 const SkIPoint& dstPoint) {
574 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint) ||
575 GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000576}
577
bsalomonf2703d82014-10-28 14:33:06 -0700578void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000579 fDstGpu->initCopySurfaceDstDesc(src, desc);
580}
581
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000582void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
joshualitt9853cce2014-11-17 14:22:48 -0800583 size_t vertexStride,
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000584 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000585 // We use geometryHints() to know whether to flush the draw buffer. We
586 // can't flush if we are inside an unbalanced pushGeometrySource.
587 // Moreover, flushing blows away vertex and index data that was
588 // previously reserved. So if the vertex or index data is pulled from
589 // reserved space and won't be released by this request then we can't
590 // flush.
591 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000592
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000593 bool unreleasedVertexSpace =
594 !vertexCount &&
595 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000596
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000597 bool unreleasedIndexSpace =
598 !indexCount &&
599 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000600
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000601 int vcount = vertexCount;
602 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000603
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000604 if (!insideGeoPush &&
605 !unreleasedVertexSpace &&
606 !unreleasedIndexSpace &&
joshualitt9853cce2014-11-17 14:22:48 -0800607 this->geometryHints(vertexStride, &vcount, &icount)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000608 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000609 }
610}
611
joshualitt9853cce2014-11-17 14:22:48 -0800612bool GrInOrderDrawBuffer::geometryHints(size_t vertexStride,
613 int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000614 int* indexCount) const {
615 // we will recommend a flush if the data could fit in a single
616 // preallocated buffer but none are left and it can't fit
617 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000618 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700619 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000620 int32_t currIndices = fIndexPool.currentBufferIndices();
621 if (*indexCount > currIndices &&
622 (!fIndexPool.preallocatedBuffersRemaining() &&
623 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
624
625 flush = true;
626 }
627 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000628 }
bsalomon49f085d2014-09-05 13:34:00 -0700629 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700630 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000631 if (*vertexCount > currVertices &&
632 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700633 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000634
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000635 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000636 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000637 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000638 }
639 return flush;
640}
641
jvanverth@google.coma6338982013-01-31 21:34:25 +0000642bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000643 int vertexCount,
644 void** vertices) {
645 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000646 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700647 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000648 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000649
jvanverth@google.coma6338982013-01-31 21:34:25 +0000650 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000651 vertexCount,
652 &poolState.fPoolVertexBuffer,
653 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700654 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000655}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000656
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000657bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
658 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000659 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700660 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000661 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000662
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000663 *indices = fIndexPool.makeSpace(indexCount,
664 &poolState.fPoolIndexBuffer,
665 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700666 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000667}
668
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000669void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
670 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000671 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000672
673 // If we get a release vertex space call then our current source should either be reserved
674 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800675 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000676
677 // When the caller reserved vertex buffer space we gave it back a pointer
678 // provided by the vertex buffer pool. At each draw we tracked the largest
679 // offset into the pool's pointer that was referenced. Now we return to the
680 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000681 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
joshualittd53a8272014-11-10 16:03:14 -0800682 fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000683 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000684 poolState.fPoolVertexBuffer = NULL;
685 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000686}
687
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000688void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
689 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000690 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000691
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000692 // If we get a release index space call then our current source should either be reserved
693 // or array (which we copied into reserved space).
joshualittd1aa8ff2014-11-04 07:47:55 -0800694 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000695
696 // Similar to releaseReservedVertexSpace we return any unused portion at
697 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000698 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
699 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
700 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000701 poolState.fPoolIndexBuffer = NULL;
702 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000703}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000704
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000705void GrInOrderDrawBuffer::geometrySourceWillPush() {
706 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
707 poolState.fUsedPoolVertexBytes = 0;
708 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000709#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000710 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
711 poolState.fPoolStartVertex = ~0;
712 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
713 poolState.fPoolStartIndex = ~0;
714#endif
715}
716
bsalomonb3e3a952014-09-19 11:10:40 -0700717void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000718 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000719 fGeoPoolStateStack.pop_back();
720 GeometryPoolState& poolState = fGeoPoolStateStack.back();
721 // we have to assume that any slack we had in our vertex/index data
722 // is now unreleasable because data may have been appended later in the
723 // pool.
joshualittd1aa8ff2014-11-04 07:47:55 -0800724 if (kReserved_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000725 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000726 }
joshualittd1aa8ff2014-11-04 07:47:55 -0800727 if (kReserved_GeometrySrcType == restoredState.fIndexSrc) {
joshualittd53a8272014-11-10 16:03:14 -0800728 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * restoredState.fIndexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000729 }
730}
731
bsalomonae59b772014-11-19 08:23:49 -0800732bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
733 GrGpu::DrawType drawType,
joshualitt54e0c122014-11-19 09:38:51 -0800734 const GrClipMaskManager::ScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800735 const GrDeviceCoordTexture* dstCopy) {
joshualitt54e0c122014-11-19 09:38:51 -0800736 SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(ds, fDstGpu, scissor, dstCopy,
737 drawType));
bsalomonae59b772014-11-19 08:23:49 -0800738 if (!optState) {
739 return false;
740 }
741 if (!fLastState || *optState != *fLastState) {
742 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (optState));
743 fLastState.reset(SkRef(optState.get()));
joshualittd53a8272014-11-10 16:03:14 -0800744 if (dstCopy) {
745 ss->fDstCopy = *dstCopy;
746 }
747 ss->fDrawType = drawType;
cdalton6819df32014-10-15 13:43:48 -0700748 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700749 }
bsalomonae59b772014-11-19 08:23:49 -0800750 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000751}
752
cdalton6819df32014-10-15 13:43:48 -0700753void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
754 SkASSERT(!fCmdBuffer.empty());
755 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700756 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
757 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700758 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700759 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700760 }
mtklein07894c42014-10-13 14:00:42 -0700761}