blob: dcd09ddeb105773b3f2d5366ef88efe94ee07f05 [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"
bsalomon@google.comc26d94f2013-03-25 18:19:00 +000011#include "GrDrawTargetCaps.h"
jvanverth8e80d172014-06-19 12:01:10 -070012#include "GrTextStrike.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"
reed@google.comac10a2d2010-12-22 21:39:39 +000015#include "GrTexture.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000017GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
bsalomon@google.com471d4712011-08-23 15:45:25 +000018 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000019 GrIndexBufferAllocPool* indexPool)
joshualitt6db519c2014-10-29 08:48:18 -070020 : INHERITED(gpu->getContext())
cdalton6819df32014-10-15 13:43:48 -070021 , fCmdBuffer(kCmdBufferInitialSizeInBytes)
22 , fLastState(NULL)
23 , fLastClip(NULL)
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000024 , fDstGpu(gpu)
bsalomon@google.com97805382012-03-13 14:32:07 +000025 , fClipSet(true)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000026 , fClipProxyState(kUnknown_ClipProxyState)
robertphillips@google.com69705572012-03-21 19:46:50 +000027 , fVertexPool(*vertexPool)
28 , fIndexPool(*indexPool)
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +000029 , fFlushing(false)
30 , fDrawID(0) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000031
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000032 fDstGpu->ref();
bsalomon@google.combcce8922013-03-25 15:38:39 +000033 fCaps.reset(SkRef(fDstGpu->caps()));
bsalomon@google.com18c9c192011-09-22 21:01:31 +000034
bsalomon49f085d2014-09-05 13:34:00 -070035 SkASSERT(vertexPool);
36 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000037
38 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
39 poolState.fUsedPoolVertexBytes = 0;
40 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000041#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000042 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
43 poolState.fPoolStartVertex = ~0;
44 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
45 poolState.fPoolStartIndex = ~0;
46#endif
bsalomon@google.coma4f6b102012-06-26 21:04:22 +000047 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000048}
49
50GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000051 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000052 // This must be called by before the GrDrawTarget destructor
53 this->releaseGeometry();
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000054 fDstGpu->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +000055}
56
bsalomon@google.com934c5702012-03-20 21:17:58 +000057////////////////////////////////////////////////////////////////////////////////
58
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000059namespace {
60void get_vertex_bounds(const void* vertices,
61 size_t vertexSize,
62 int vertexCount,
63 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000064 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000065 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000066 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000067 bounds->fLeft = bounds->fRight = point->fX;
68 bounds->fTop = bounds->fBottom = point->fY;
69 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000070 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000071 bounds->growToInclude(point->fX, point->fY);
72 }
73}
bsalomon@google.com934c5702012-03-20 21:17:58 +000074}
75
robertphillips@google.com42903302013-04-20 12:26:07 +000076
77namespace {
78
bsalomon62c447d2014-08-08 08:08:50 -070079extern const GrVertexAttrib kRectAttribs[] = {
80 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
81 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
82 {kVec2f_GrVertexAttribType, sizeof(SkPoint)+sizeof(GrColor), kLocalCoord_GrVertexAttribBinding},
robertphillips@google.com42903302013-04-20 12:26:07 +000083};
robertphillips@google.com42903302013-04-20 12:26:07 +000084}
85
bsalomon62c447d2014-08-08 08:08:50 -070086/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
87 have explicit local coords and sometimes not. We *could* always provide explicit local coords
88 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
89 haven't seen a use case which frequently switches between local rect and no local rect draws.
90
91 The color param is used to determine whether the opaque hint can be set on the draw state.
92 The caller must populate the vertex colors itself.
93
94 The vertex attrib order is always pos, color, [local coords].
95 */
96static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
97 if (hasLocalCoords) {
egdaniel7b3d5ee2014-08-28 05:41:14 -070098 drawState->setVertexAttribs<kRectAttribs>(3, 2 * sizeof(SkPoint) + sizeof(SkColor));
bsalomon62c447d2014-08-08 08:08:50 -070099 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700100 drawState->setVertexAttribs<kRectAttribs>(2, sizeof(SkPoint) + sizeof(SkColor));
bsalomon62c447d2014-08-08 08:08:50 -0700101 }
102 if (0xFF == GrColorUnpackA(color)) {
103 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
104 }
105}
robertphillips@google.com42903302013-04-20 12:26:07 +0000106
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000107enum {
108 kTraceCmdBit = 0x80,
109 kCmdMask = 0x7f,
110};
111
bsalomon62c447d2014-08-08 08:08:50 -0700112static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000113
bsalomon62c447d2014-08-08 08:08:50 -0700114static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000115
bsalomon62c447d2014-08-08 08:08:50 -0700116static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000117
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000118void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000119 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000120 const SkMatrix* localMatrix) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000121 GrDrawState* drawState = this->drawState();
122
123 GrColor color = drawState->getColor();
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000124
bsalomon49f085d2014-09-05 13:34:00 -0700125 set_vertex_attributes(drawState, SkToBool(localRect), color);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000126
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000127 AutoReleaseGeometry geo(this, 4, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000128 if (!geo.succeeded()) {
129 GrPrintf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000130 return;
131 }
132
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000133 // Go to device coords to allow batching across matrix changes
bsalomon01c8da12014-08-04 09:21:30 -0700134 SkMatrix matrix = drawState->getViewMatrix();
135
jvanverth@google.com39768252013-02-14 15:25:44 +0000136 // 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 +0000137 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
138 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000139 GrDrawState::AutoViewMatrixRestore avmr;
140 if (!avmr.setIdentity(drawState)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000141 return;
142 }
143
egdaniel7b3d5ee2014-08-28 05:41:14 -0700144 size_t vstride = drawState->getVertexStride();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000145
egdaniel7b3d5ee2014-08-28 05:41:14 -0700146 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
147 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000148
149 SkRect devBounds;
150 // since we already computed the dev verts, set the bounds hint. This will help us avoid
151 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700152 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000153
bsalomon49f085d2014-09-05 13:34:00 -0700154 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700155 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
156 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000157 coords->setRectFan(localRect->fLeft, localRect->fTop,
158 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700159 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700160 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700161 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000162 }
163 }
164
bsalomon62c447d2014-08-08 08:08:50 -0700165 static const int kColorOffset = sizeof(SkPoint);
166 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
167 for (int i = 0; i < 4; ++i) {
168 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700169 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000170 }
171
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000172 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000173 this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000174
175 // to ensure that stashing the drawState ptr is valid
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000176 SkASSERT(this->drawState() == drawState);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000177}
178
179bool GrInOrderDrawBuffer::quickInsideClip(const SkRect& devBounds) {
180 if (!this->getDrawState().isClipState()) {
181 return true;
182 }
183 if (kUnknown_ClipProxyState == fClipProxyState) {
184 SkIRect rect;
185 bool iior;
186 this->getClip()->getConservativeBounds(this->getDrawState().getRenderTarget(), &rect, &iior);
187 if (iior) {
188 // The clip is a rect. We will remember that in fProxyClip. It is common for an edge (or
189 // all edges) of the clip to be at the edge of the RT. However, we get that clipping for
190 // free via the viewport. We don't want to think that clipping must be enabled in this
191 // case. So we extend the clip outward from the edge to avoid these false negatives.
192 fClipProxyState = kValid_ClipProxyState;
reed@google.com44699382013-10-31 17:28:30 +0000193 fClipProxy = SkRect::Make(rect);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000194
195 if (fClipProxy.fLeft <= 0) {
196 fClipProxy.fLeft = SK_ScalarMin;
197 }
198 if (fClipProxy.fTop <= 0) {
199 fClipProxy.fTop = SK_ScalarMin;
200 }
201 if (fClipProxy.fRight >= this->getDrawState().getRenderTarget()->width()) {
202 fClipProxy.fRight = SK_ScalarMax;
203 }
204 if (fClipProxy.fBottom >= this->getDrawState().getRenderTarget()->height()) {
205 fClipProxy.fBottom = SK_ScalarMax;
206 }
207 } else {
208 fClipProxyState = kInvalid_ClipProxyState;
209 }
210 }
211 if (kValid_ClipProxyState == fClipProxyState) {
212 return fClipProxy.contains(devBounds);
213 }
214 SkPoint originOffset = {SkIntToScalar(this->getClip()->fOrigin.fX),
215 SkIntToScalar(this->getClip()->fOrigin.fY)};
216 SkRect clipSpaceBounds = devBounds;
217 clipSpaceBounds.offset(originOffset);
218 return this->getClip()->fClipStack->quickContains(clipSpaceBounds);
219}
220
221int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700222 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000223 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000224
bsalomon@google.com934c5702012-03-20 21:17:58 +0000225 const GeometrySrcState& geomSrc = this->getGeomSrc();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000226 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com934c5702012-03-20 21:17:58 +0000227
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000228 // we only attempt to concat the case when reserved verts are used with a client-specified index
229 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
230 // between draws.
231 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
232 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
233 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000234 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000235 // Check if there is a draw info that is compatible that uses the same VB from the pool and
236 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700237 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000238 return 0;
239 }
240
cdalton6819df32014-10-15 13:43:48 -0700241 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000242 GeometryPoolState& poolState = fGeoPoolStateStack.back();
243 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
244
cdalton6819df32014-10-15 13:43:48 -0700245 if (!draw->fInfo.isInstanced() ||
246 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
247 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomonb3e3a952014-09-19 11:10:40 -0700248 draw->vertexBuffer() != vertexBuffer ||
249 draw->indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000250 return 0;
251 }
252 // info does not yet account for the offset from the start of the pool's VB while the previous
253 // draw record does.
254 int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
cdalton6819df32014-10-15 13:43:48 -0700255 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != adjustedStartVertex) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000256 return 0;
257 }
258
cdalton6819df32014-10-15 13:43:48 -0700259 SkASSERT(poolState.fPoolStartVertex == draw->fInfo.startVertex() + draw->fInfo.vertexCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000260
261 // how many instances can be concat'ed onto draw given the size of the index buffer
262 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700263 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000264 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000265
266 // update the amount of reserved vertex data actually referenced in draws
skia.committer@gmail.comae683922013-02-06 07:01:54 +0000267 size_t vertexBytes = instancesToConcat * info.verticesPerInstance() *
egdaniel7b3d5ee2014-08-28 05:41:14 -0700268 drawState.getVertexStride();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000269 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000270
cdalton6819df32014-10-15 13:43:48 -0700271 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000272
273 // update last fGpuCmdMarkers to include any additional trace markers that have been added
274 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700275 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000276 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
277 } else {
278 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700279 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000280 }
281 }
282
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000283 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000284}
285
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000286class AutoClipReenable {
287public:
288 AutoClipReenable() : fDrawState(NULL) {}
289 ~AutoClipReenable() {
bsalomon49f085d2014-09-05 13:34:00 -0700290 if (fDrawState) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000291 fDrawState->enableState(GrDrawState::kClip_StateBit);
292 }
293 }
294 void set(GrDrawState* drawState) {
295 if (drawState->isClipState()) {
296 fDrawState = drawState;
297 drawState->disableState(GrDrawState::kClip_StateBit);
298 }
299 }
300private:
301 GrDrawState* fDrawState;
302};
303
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000304void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000305
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000306 GeometryPoolState& poolState = fGeoPoolStateStack.back();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000307 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000308 AutoClipReenable acr;
309
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000310 if (drawState.isClipState() &&
bsalomon49f085d2014-09-05 13:34:00 -0700311 info.getDevBounds() &&
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000312 this->quickInsideClip(*info.getDevBounds())) {
313 acr.set(this->drawState());
314 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000315
cdalton6819df32014-10-15 13:43:48 -0700316 this->recordClipIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700317 this->recordStateIfNecessary();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000318
bsalomonb3e3a952014-09-19 11:10:40 -0700319 const GrVertexBuffer* vb;
320 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
321 vb = this->getGeomSrc().fVertexBuffer;
322 } else {
323 vb = poolState.fPoolVertexBuffer;
324 }
325
326 const GrIndexBuffer* ib = NULL;
327 if (info.isIndexed()) {
328 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
329 ib = this->getGeomSrc().fIndexBuffer;
330 } else {
331 ib = poolState.fPoolIndexBuffer;
332 }
333 }
334
335 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000336 if (info.isInstanced()) {
337 int instancesConcated = this->concatInstancedDraw(info);
338 if (info.instanceCount() > instancesConcated) {
cdalton6819df32014-10-15 13:43:48 -0700339 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, vb, ib));
340 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000341 } else {
342 return;
343 }
344 } else {
cdalton6819df32014-10-15 13:43:48 -0700345 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, vb, ib));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000346 }
cdalton6819df32014-10-15 13:43:48 -0700347 this->recordTraceMarkersIfNecessary();
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000348
bsalomonb3e3a952014-09-19 11:10:40 -0700349 // Adjust the starting vertex and index when we are using reserved or array sources to
350 // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
351 if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
352 size_t bytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexStride();
353 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700354 draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +0000355 }
bsalomonb3e3a952014-09-19 11:10:40 -0700356
357 if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) {
358 size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
359 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes);
cdalton6819df32014-10-15 13:43:48 -0700360 draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000361 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000362}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000363
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000364void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, SkPath::FillType fill) {
cdalton6819df32014-10-15 13:43:48 -0700365 this->recordClipIfNecessary();
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000366 // Only compare the subset of GrDrawState relevant to path stenciling?
bsalomon838f62d2014-08-05 07:15:57 -0700367 this->recordStateIfNecessary();
cdalton6819df32014-10-15 13:43:48 -0700368 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000369 sp->fFill = fill;
cdalton6819df32014-10-15 13:43:48 -0700370 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000371}
372
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000373void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000374 SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700375 this->recordClipIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000376 // TODO: Only compare the subset of GrDrawState relevant to path covering?
bsalomon838f62d2014-08-05 07:15:57 -0700377 this->recordStateIfNecessary();
cdalton6819df32014-10-15 13:43:48 -0700378 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
379 dp->fFill = fill;
bsalomon49f085d2014-09-05 13:34:00 -0700380 if (dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700381 dp->fDstCopy = *dstCopy;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000382 }
cdalton6819df32014-10-15 13:43:48 -0700383 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000384}
385
cdaltonb85a0aa2014-07-21 15:32:44 -0700386void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
387 const uint32_t indices[], int count,
388 const float transforms[], PathTransformType transformsType,
389 SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700390 SkASSERT(pathRange);
391 SkASSERT(indices);
392 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000393
cdalton6819df32014-10-15 13:43:48 -0700394 this->recordClipIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700395 this->recordStateIfNecessary();
cdalton6819df32014-10-15 13:43:48 -0700396
397 int sizeOfIndices = sizeof(uint32_t) * count;
398 int sizeOfTransforms = sizeof(float) * count *
399 GrPathRendering::PathTransformSize(transformsType);
400
401 DrawPaths* dp = GrNEW_APPEND_WITH_DATA_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange),
402 sizeOfIndices + sizeOfTransforms);
403 memcpy(dp->indices(), indices, sizeOfIndices);
cdaltonb85a0aa2014-07-21 15:32:44 -0700404 dp->fCount = count;
cdalton6819df32014-10-15 13:43:48 -0700405 memcpy(dp->transforms(), transforms, sizeOfTransforms);
cdaltonb85a0aa2014-07-21 15:32:44 -0700406 dp->fTransformsType = transformsType;
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000407 dp->fFill = fill;
bsalomon49f085d2014-09-05 13:34:00 -0700408 if (dstCopy) {
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000409 dp->fDstCopy = *dstCopy;
410 }
cdalton6819df32014-10-15 13:43:48 -0700411
412 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000413}
414
skia.committer@gmail.com18bb41e2013-11-01 07:02:15 +0000415void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000416 bool canIgnoreRect, GrRenderTarget* renderTarget) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000417 SkIRect r;
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000418 if (NULL == renderTarget) {
419 renderTarget = this->drawState()->getRenderTarget();
bsalomon49f085d2014-09-05 13:34:00 -0700420 SkASSERT(renderTarget);
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000421 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000422 if (NULL == rect) {
423 // We could do something smart and remove previous draws and clears to
424 // the current render target. If we get that smart we have to make sure
425 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000426 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000427 rect = &r;
428 }
cdalton6819df32014-10-15 13:43:48 -0700429 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000430 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000431 clr->fColor = color;
432 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000433 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700434 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000435}
436
joshualitt6db519c2014-10-29 08:48:18 -0700437void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
438 bool insideClip,
439 GrRenderTarget* renderTarget) {
440 if (NULL == renderTarget) {
441 renderTarget = this->drawState()->getRenderTarget();
442 SkASSERT(renderTarget);
443 }
444 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
445 clr->fRect = rect;
446 clr->fInsideClip = insideClip;
447 this->recordTraceMarkersIfNecessary();
448}
449
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000450void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
451 if (!this->caps()->discardRenderTargetSupport()) {
452 return;
453 }
454 if (NULL == renderTarget) {
455 renderTarget = this->drawState()->getRenderTarget();
bsalomon49f085d2014-09-05 13:34:00 -0700456 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000457 }
cdalton6819df32014-10-15 13:43:48 -0700458 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000459 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700460 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000461}
462
reed@google.comac10a2d2010-12-22 21:39:39 +0000463void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000464 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000465 this->resetVertexSource();
466 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700467
468 fCmdBuffer.reset();
469 fLastState = NULL;
470 fLastClip = NULL;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000471 fVertexPool.reset();
472 fIndexPool.reset();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000473 fGpuCmdMarkers.reset();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000474 fClipSet = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000475}
476
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000477void GrInOrderDrawBuffer::flush() {
478 if (fFlushing) {
479 return;
480 }
481
jvanverth8e80d172014-06-19 12:01:10 -0700482 this->getContext()->getFontCache()->updateTextures();
483
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000484 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
485 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000486
cdalton6819df32014-10-15 13:43:48 -0700487 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000488 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000489 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000490
491 GrAutoTRestore<bool> flushRestore(&fFlushing);
492 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000493
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000494 fVertexPool.unmap();
495 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000496
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000497 GrDrawTarget::AutoClipRestore acr(fDstGpu);
498 AutoGeometryAndStatePush agasp(fDstGpu, kPreserve_ASRInit);
bsalomon@google.comca432082013-01-23 19:53:46 +0000499
bsalomona70353e2014-07-07 08:15:07 -0700500 GrDrawState* prevDrawState = SkRef(fDstGpu->drawState());
reed@google.comac10a2d2010-12-22 21:39:39 +0000501
cdalton6819df32014-10-15 13:43:48 -0700502 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000503
cdalton6819df32014-10-15 13:43:48 -0700504 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700505 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700506
507 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000508 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700509 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700510 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700511 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000512 newMarker.fMarker = traceString.c_str();
513 fDstGpu->addGpuTraceMarker(&newMarker);
514 ++currCmdMarker;
515 }
cdalton6819df32014-10-15 13:43:48 -0700516
517 SkDEBUGCODE(bool isDraw = kDraw_Cmd == strip_trace_bit(iter->fType) ||
518 kStencilPath_Cmd == strip_trace_bit(iter->fType) ||
519 kDrawPath_Cmd == strip_trace_bit(iter->fType) ||
520 kDrawPaths_Cmd == strip_trace_bit(iter->fType));
521 SkASSERT(!isDraw || fDstGpu->drawState() != prevDrawState);
522
523 iter->execute(fDstGpu);
524
525 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000526 fDstGpu->removeGpuTraceMarker(&newMarker);
527 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000528 }
mtkleinf439c772014-10-14 14:29:30 -0700529
cdalton6819df32014-10-15 13:43:48 -0700530 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000531 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000532
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000533 fDstGpu->setDrawState(prevDrawState);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000534 prevDrawState->unref();
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000535 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000536 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000537}
538
joshualitt6db519c2014-10-29 08:48:18 -0700539void GrInOrderDrawBuffer::Draw::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700540 gpu->setVertexSourceToBuffer(this->vertexBuffer());
541 if (fInfo.isIndexed()) {
542 gpu->setIndexSourceToBuffer(this->indexBuffer());
543 }
544 gpu->executeDraw(fInfo);
545}
546
joshualitt6db519c2014-10-29 08:48:18 -0700547void GrInOrderDrawBuffer::StencilPath::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700548 gpu->stencilPath(this->path(), fFill);
549}
550
joshualitt6db519c2014-10-29 08:48:18 -0700551void GrInOrderDrawBuffer::DrawPath::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700552 gpu->executeDrawPath(this->path(), fFill, fDstCopy.texture() ? &fDstCopy : NULL);
553}
554
joshualitt6db519c2014-10-29 08:48:18 -0700555void GrInOrderDrawBuffer::DrawPaths::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700556 gpu->executeDrawPaths(this->pathRange(), this->indices(), fCount, this->transforms(),
557 fTransformsType, fFill, fDstCopy.texture() ? &fDstCopy : NULL);
558}
559
joshualitt6db519c2014-10-29 08:48:18 -0700560void GrInOrderDrawBuffer::SetState::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700561 gpu->setDrawState(&fState);
562}
563
joshualitt6db519c2014-10-29 08:48:18 -0700564void GrInOrderDrawBuffer::SetClip::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700565 // Our fClipData is referenced directly, so we must remain alive for the entire
566 // duration of the flush (after which the gpu's previous clip is restored).
567 gpu->setClip(&fClipData);
568}
569
joshualitt6db519c2014-10-29 08:48:18 -0700570void GrInOrderDrawBuffer::Clear::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700571 if (GrColor_ILLEGAL == fColor) {
572 gpu->discard(this->renderTarget());
573 } else {
574 gpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
575 }
576}
577
joshualitt6db519c2014-10-29 08:48:18 -0700578void GrInOrderDrawBuffer::ClearStencilClip::execute(GrClipTarget* gpu) {
579 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
580}
581
582void GrInOrderDrawBuffer::CopySurface::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700583 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
584}
585
bsalomon@google.com116ad842013-04-09 15:38:19 +0000586bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
587 GrSurface* src,
588 const SkIRect& srcRect,
589 const SkIPoint& dstPoint) {
590 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700591 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000592 cs->fSrcRect = srcRect;
593 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700594 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000595 return true;
596 } else {
597 return false;
598 }
599}
600
601bool GrInOrderDrawBuffer::onCanCopySurface(GrSurface* dst,
602 GrSurface* src,
603 const SkIRect& srcRect,
604 const SkIPoint& dstPoint) {
605 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint);
606}
607
bsalomonf2703d82014-10-28 14:33:06 -0700608void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000609 fDstGpu->initCopySurfaceDstDesc(src, desc);
610}
611
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000612void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
613 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000614 // We use geometryHints() to know whether to flush the draw buffer. We
615 // can't flush if we are inside an unbalanced pushGeometrySource.
616 // Moreover, flushing blows away vertex and index data that was
617 // previously reserved. So if the vertex or index data is pulled from
618 // reserved space and won't be released by this request then we can't
619 // flush.
620 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000621
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000622 bool unreleasedVertexSpace =
623 !vertexCount &&
624 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000625
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000626 bool unreleasedIndexSpace =
627 !indexCount &&
628 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000629
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000630 // we don't want to finalize any reserved geom on the target since
631 // we don't know that the client has finished writing to it.
632 bool targetHasReservedGeom = fDstGpu->hasReservedVerticesOrIndices();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000633
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000634 int vcount = vertexCount;
635 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000636
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000637 if (!insideGeoPush &&
638 !unreleasedVertexSpace &&
639 !unreleasedIndexSpace &&
640 !targetHasReservedGeom &&
641 this->geometryHints(&vcount, &icount)) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000642
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000643 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000644 }
645}
646
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000647bool GrInOrderDrawBuffer::geometryHints(int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000648 int* indexCount) const {
649 // we will recommend a flush if the data could fit in a single
650 // preallocated buffer but none are left and it can't fit
651 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000652 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700653 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000654 int32_t currIndices = fIndexPool.currentBufferIndices();
655 if (*indexCount > currIndices &&
656 (!fIndexPool.preallocatedBuffersRemaining() &&
657 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
658
659 flush = true;
660 }
661 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000662 }
bsalomon49f085d2014-09-05 13:34:00 -0700663 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700664 size_t vertexStride = this->getDrawState().getVertexStride();
665 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000666 if (*vertexCount > currVertices &&
667 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700668 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000669
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000670 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000671 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000672 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000673 }
674 return flush;
675}
676
jvanverth@google.coma6338982013-01-31 21:34:25 +0000677bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000678 int vertexCount,
679 void** vertices) {
680 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000681 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700682 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000683 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000684
jvanverth@google.coma6338982013-01-31 21:34:25 +0000685 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000686 vertexCount,
687 &poolState.fPoolVertexBuffer,
688 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700689 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000690}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000691
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000692bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
693 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000694 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700695 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000696 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000697
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000698 *indices = fIndexPool.makeSpace(indexCount,
699 &poolState.fPoolIndexBuffer,
700 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700701 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000702}
703
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000704void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
705 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000706 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000707
708 // If we get a release vertex space call then our current source should either be reserved
709 // or array (which we copied into reserved space).
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000710 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc ||
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000711 kArray_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000712
713 // When the caller reserved vertex buffer space we gave it back a pointer
714 // provided by the vertex buffer pool. At each draw we tracked the largest
715 // offset into the pool's pointer that was referenced. Now we return to the
716 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000717 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000718 fVertexPool.putBack(reservedVertexBytes -
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000719 poolState.fUsedPoolVertexBytes);
720 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000721 poolState.fPoolVertexBuffer = NULL;
722 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000723}
724
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000725void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
726 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000727 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000728
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000729 // If we get a release index space call then our current source should either be reserved
730 // or array (which we copied into reserved space).
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000731 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc ||
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000732 kArray_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000733
734 // Similar to releaseReservedVertexSpace we return any unused portion at
735 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000736 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
737 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
738 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000739 poolState.fPoolIndexBuffer = NULL;
740 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000741}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000742
bsalomonb3e3a952014-09-19 11:10:40 -0700743void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000744 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000745 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000746#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000747 bool success =
748#endif
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000749 fVertexPool.appendVertices(this->getVertexSize(),
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000750 vertexCount,
751 vertexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000752 &poolState.fPoolVertexBuffer,
753 &poolState.fPoolStartVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000754 GR_DEBUGASSERT(success);
755}
756
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000757void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
758 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000759 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000760 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000761#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000762 bool success =
763#endif
764 fIndexPool.appendIndices(indexCount,
765 indexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000766 &poolState.fPoolIndexBuffer,
767 &poolState.fPoolStartIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000768 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000769}
770
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000771void GrInOrderDrawBuffer::releaseVertexArray() {
772 // When the client provides an array as the vertex source we handled it
773 // by copying their array into reserved space.
774 this->GrInOrderDrawBuffer::releaseReservedVertexSpace();
775}
776
777void GrInOrderDrawBuffer::releaseIndexArray() {
778 // When the client provides an array as the index source we handled it
779 // by copying their array into reserved space.
780 this->GrInOrderDrawBuffer::releaseReservedIndexSpace();
781}
782
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000783void GrInOrderDrawBuffer::geometrySourceWillPush() {
784 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
785 poolState.fUsedPoolVertexBytes = 0;
786 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000787#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000788 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
789 poolState.fPoolStartVertex = ~0;
790 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
791 poolState.fPoolStartIndex = ~0;
792#endif
793}
794
bsalomonb3e3a952014-09-19 11:10:40 -0700795void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000796 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000797 fGeoPoolStateStack.pop_back();
798 GeometryPoolState& poolState = fGeoPoolStateStack.back();
799 // we have to assume that any slack we had in our vertex/index data
800 // is now unreleasable because data may have been appended later in the
801 // pool.
802 if (kReserved_GeometrySrcType == restoredState.fVertexSrc ||
803 kArray_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000804 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000805 }
806 if (kReserved_GeometrySrcType == restoredState.fIndexSrc ||
807 kArray_GeometrySrcType == restoredState.fIndexSrc) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000808 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000809 restoredState.fIndexCount;
810 }
811}
812
bsalomon838f62d2014-08-05 07:15:57 -0700813void GrInOrderDrawBuffer::recordStateIfNecessary() {
cdalton6819df32014-10-15 13:43:48 -0700814 if (!fLastState) {
815 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (this->getDrawState()));
816 fLastState = &ss->fState;
817 this->convertDrawStateToPendingExec(fLastState);
818 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700819 return;
820 }
821 const GrDrawState& curr = this->getDrawState();
cdalton6819df32014-10-15 13:43:48 -0700822 switch (GrDrawState::CombineIfPossible(*fLastState, curr, *this->caps())) {
bsalomon838f62d2014-08-05 07:15:57 -0700823 case GrDrawState::kIncompatible_CombinedState:
cdalton6819df32014-10-15 13:43:48 -0700824 fLastState = &GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (curr))->fState;
825 this->convertDrawStateToPendingExec(fLastState);
826 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700827 break;
828 case GrDrawState::kA_CombinedState:
829 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA.
830 break;
831 case GrDrawState::kB_CombinedState:
bsalomon2a9ca782014-09-05 14:27:43 -0700832 // prev has already been converted to pending execution. That is a one-way ticket.
cdalton6819df32014-10-15 13:43:48 -0700833 // So here we just destruct the previous state and reinit with a new copy of curr.
834 // Note that this goes away when we move GrIODB over to taking optimized snapshots
835 // of draw states.
836 fLastState->~GrDrawState();
837 SkNEW_PLACEMENT_ARGS(fLastState, GrDrawState, (curr));
838 this->convertDrawStateToPendingExec(fLastState);
bsalomon838f62d2014-08-05 07:15:57 -0700839 break;
840 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000841}
842
cdalton6819df32014-10-15 13:43:48 -0700843void GrInOrderDrawBuffer::recordClipIfNecessary() {
844 if (this->getDrawState().isClipState() &&
845 fClipSet &&
846 (!fLastClip || *fLastClip != *this->getClip())) {
847 fLastClip = &GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetClip, (this->getClip()))->fClipData;
848 this->recordTraceMarkersIfNecessary();
849 fClipSet = false;
mtkleinf439c772014-10-14 14:29:30 -0700850 }
mtkleinf439c772014-10-14 14:29:30 -0700851}
852
cdalton6819df32014-10-15 13:43:48 -0700853void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
854 SkASSERT(!fCmdBuffer.empty());
855 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700856 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
857 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700858 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700859 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700860 }
mtklein07894c42014-10-13 14:00:42 -0700861}
862
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000863void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) {
864 INHERITED::clipWillBeSet(newClipData);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000865 fClipSet = true;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000866 fClipProxyState = kUnknown_ClipProxyState;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000867}