blob: 61c3e0c21d186f2e7dad5bb4f82228757a9ac8f6 [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()) {
tfarina38406c82014-10-31 07:11:12 -0700129 SkDebugf("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
joshualitt92e496f2014-10-31 13:56:50 -0700364void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, GrPathRendering::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,
joshualitt92e496f2014-10-31 13:56:50 -0700374 GrPathRendering::FillType fill,
375 const GrDeviceCoordTexture* dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700376 this->recordClipIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000377 // TODO: Only compare the subset of GrDrawState relevant to path covering?
bsalomon838f62d2014-08-05 07:15:57 -0700378 this->recordStateIfNecessary();
cdalton6819df32014-10-15 13:43:48 -0700379 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
380 dp->fFill = fill;
bsalomon49f085d2014-09-05 13:34:00 -0700381 if (dstCopy) {
cdalton6819df32014-10-15 13:43:48 -0700382 dp->fDstCopy = *dstCopy;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000383 }
cdalton6819df32014-10-15 13:43:48 -0700384 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000385}
386
cdaltonb85a0aa2014-07-21 15:32:44 -0700387void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
388 const uint32_t indices[], int count,
389 const float transforms[], PathTransformType transformsType,
joshualitt92e496f2014-10-31 13:56:50 -0700390 GrPathRendering::FillType fill,
391 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700392 SkASSERT(pathRange);
393 SkASSERT(indices);
394 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000395
cdalton6819df32014-10-15 13:43:48 -0700396 this->recordClipIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700397 this->recordStateIfNecessary();
cdalton6819df32014-10-15 13:43:48 -0700398
399 int sizeOfIndices = sizeof(uint32_t) * count;
400 int sizeOfTransforms = sizeof(float) * count *
401 GrPathRendering::PathTransformSize(transformsType);
402
403 DrawPaths* dp = GrNEW_APPEND_WITH_DATA_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange),
404 sizeOfIndices + sizeOfTransforms);
405 memcpy(dp->indices(), indices, sizeOfIndices);
cdaltonb85a0aa2014-07-21 15:32:44 -0700406 dp->fCount = count;
cdalton6819df32014-10-15 13:43:48 -0700407 memcpy(dp->transforms(), transforms, sizeOfTransforms);
cdaltonb85a0aa2014-07-21 15:32:44 -0700408 dp->fTransformsType = transformsType;
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000409 dp->fFill = fill;
bsalomon49f085d2014-09-05 13:34:00 -0700410 if (dstCopy) {
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000411 dp->fDstCopy = *dstCopy;
412 }
cdalton6819df32014-10-15 13:43:48 -0700413
414 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000415}
416
skia.committer@gmail.com18bb41e2013-11-01 07:02:15 +0000417void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000418 bool canIgnoreRect, GrRenderTarget* renderTarget) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000419 SkIRect r;
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000420 if (NULL == renderTarget) {
421 renderTarget = this->drawState()->getRenderTarget();
bsalomon49f085d2014-09-05 13:34:00 -0700422 SkASSERT(renderTarget);
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000423 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000424 if (NULL == rect) {
425 // We could do something smart and remove previous draws and clears to
426 // the current render target. If we get that smart we have to make sure
427 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000428 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000429 rect = &r;
430 }
cdalton6819df32014-10-15 13:43:48 -0700431 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000432 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000433 clr->fColor = color;
434 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000435 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700436 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000437}
438
joshualitt6db519c2014-10-29 08:48:18 -0700439void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
440 bool insideClip,
441 GrRenderTarget* renderTarget) {
442 if (NULL == renderTarget) {
443 renderTarget = this->drawState()->getRenderTarget();
444 SkASSERT(renderTarget);
445 }
446 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
447 clr->fRect = rect;
448 clr->fInsideClip = insideClip;
449 this->recordTraceMarkersIfNecessary();
450}
451
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000452void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
453 if (!this->caps()->discardRenderTargetSupport()) {
454 return;
455 }
456 if (NULL == renderTarget) {
457 renderTarget = this->drawState()->getRenderTarget();
bsalomon49f085d2014-09-05 13:34:00 -0700458 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000459 }
cdalton6819df32014-10-15 13:43:48 -0700460 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000461 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700462 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000463}
464
reed@google.comac10a2d2010-12-22 21:39:39 +0000465void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000466 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000467 this->resetVertexSource();
468 this->resetIndexSource();
cdalton6819df32014-10-15 13:43:48 -0700469
470 fCmdBuffer.reset();
471 fLastState = NULL;
472 fLastClip = NULL;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000473 fVertexPool.reset();
474 fIndexPool.reset();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000475 fGpuCmdMarkers.reset();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000476 fClipSet = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000477}
478
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000479void GrInOrderDrawBuffer::flush() {
480 if (fFlushing) {
481 return;
482 }
483
jvanverth8e80d172014-06-19 12:01:10 -0700484 this->getContext()->getFontCache()->updateTextures();
485
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000486 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
487 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000488
cdalton6819df32014-10-15 13:43:48 -0700489 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000490 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000491 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000492
493 GrAutoTRestore<bool> flushRestore(&fFlushing);
494 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000495
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000496 fVertexPool.unmap();
497 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000498
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000499 GrDrawTarget::AutoClipRestore acr(fDstGpu);
500 AutoGeometryAndStatePush agasp(fDstGpu, kPreserve_ASRInit);
bsalomon@google.comca432082013-01-23 19:53:46 +0000501
bsalomona70353e2014-07-07 08:15:07 -0700502 GrDrawState* prevDrawState = SkRef(fDstGpu->drawState());
reed@google.comac10a2d2010-12-22 21:39:39 +0000503
cdalton6819df32014-10-15 13:43:48 -0700504 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000505
cdalton6819df32014-10-15 13:43:48 -0700506 int currCmdMarker = 0;
egdaniel3eee3832014-06-18 13:09:11 -0700507 fDstGpu->saveActiveTraceMarkers();
cdalton6819df32014-10-15 13:43:48 -0700508
509 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000510 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700511 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700512 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700513 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000514 newMarker.fMarker = traceString.c_str();
515 fDstGpu->addGpuTraceMarker(&newMarker);
516 ++currCmdMarker;
517 }
cdalton6819df32014-10-15 13:43:48 -0700518
519 SkDEBUGCODE(bool isDraw = kDraw_Cmd == strip_trace_bit(iter->fType) ||
520 kStencilPath_Cmd == strip_trace_bit(iter->fType) ||
521 kDrawPath_Cmd == strip_trace_bit(iter->fType) ||
522 kDrawPaths_Cmd == strip_trace_bit(iter->fType));
523 SkASSERT(!isDraw || fDstGpu->drawState() != prevDrawState);
524
525 iter->execute(fDstGpu);
526
527 if (cmd_has_trace_marker(iter->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000528 fDstGpu->removeGpuTraceMarker(&newMarker);
529 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000530 }
mtkleinf439c772014-10-14 14:29:30 -0700531
cdalton6819df32014-10-15 13:43:48 -0700532 fDstGpu->restoreActiveTraceMarkers();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000533 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000534
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000535 fDstGpu->setDrawState(prevDrawState);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000536 prevDrawState->unref();
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000537 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000538 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000539}
540
joshualitt6db519c2014-10-29 08:48:18 -0700541void GrInOrderDrawBuffer::Draw::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700542 gpu->setVertexSourceToBuffer(this->vertexBuffer());
543 if (fInfo.isIndexed()) {
544 gpu->setIndexSourceToBuffer(this->indexBuffer());
545 }
546 gpu->executeDraw(fInfo);
547}
548
joshualitt6db519c2014-10-29 08:48:18 -0700549void GrInOrderDrawBuffer::StencilPath::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700550 gpu->stencilPath(this->path(), fFill);
551}
552
joshualitt6db519c2014-10-29 08:48:18 -0700553void GrInOrderDrawBuffer::DrawPath::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700554 gpu->executeDrawPath(this->path(), fFill, fDstCopy.texture() ? &fDstCopy : NULL);
555}
556
joshualitt6db519c2014-10-29 08:48:18 -0700557void GrInOrderDrawBuffer::DrawPaths::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700558 gpu->executeDrawPaths(this->pathRange(), this->indices(), fCount, this->transforms(),
559 fTransformsType, fFill, fDstCopy.texture() ? &fDstCopy : NULL);
560}
561
joshualitt6db519c2014-10-29 08:48:18 -0700562void GrInOrderDrawBuffer::SetState::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700563 gpu->setDrawState(&fState);
564}
565
joshualitt6db519c2014-10-29 08:48:18 -0700566void GrInOrderDrawBuffer::SetClip::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700567 // Our fClipData is referenced directly, so we must remain alive for the entire
568 // duration of the flush (after which the gpu's previous clip is restored).
569 gpu->setClip(&fClipData);
570}
571
joshualitt6db519c2014-10-29 08:48:18 -0700572void GrInOrderDrawBuffer::Clear::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700573 if (GrColor_ILLEGAL == fColor) {
574 gpu->discard(this->renderTarget());
575 } else {
576 gpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
577 }
578}
579
joshualitt6db519c2014-10-29 08:48:18 -0700580void GrInOrderDrawBuffer::ClearStencilClip::execute(GrClipTarget* gpu) {
581 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
582}
583
584void GrInOrderDrawBuffer::CopySurface::execute(GrClipTarget* gpu) {
cdalton6819df32014-10-15 13:43:48 -0700585 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
586}
587
bsalomon@google.com116ad842013-04-09 15:38:19 +0000588bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
589 GrSurface* src,
590 const SkIRect& srcRect,
591 const SkIPoint& dstPoint) {
592 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700593 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000594 cs->fSrcRect = srcRect;
595 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700596 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000597 return true;
598 } else {
599 return false;
600 }
601}
602
603bool GrInOrderDrawBuffer::onCanCopySurface(GrSurface* dst,
604 GrSurface* src,
605 const SkIRect& srcRect,
606 const SkIPoint& dstPoint) {
607 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint);
608}
609
bsalomonf2703d82014-10-28 14:33:06 -0700610void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon@google.comeb851172013-04-15 13:51:00 +0000611 fDstGpu->initCopySurfaceDstDesc(src, desc);
612}
613
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000614void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
615 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000616 // We use geometryHints() to know whether to flush the draw buffer. We
617 // can't flush if we are inside an unbalanced pushGeometrySource.
618 // Moreover, flushing blows away vertex and index data that was
619 // previously reserved. So if the vertex or index data is pulled from
620 // reserved space and won't be released by this request then we can't
621 // flush.
622 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000623
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000624 bool unreleasedVertexSpace =
625 !vertexCount &&
626 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000627
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000628 bool unreleasedIndexSpace =
629 !indexCount &&
630 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000631
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000632 // we don't want to finalize any reserved geom on the target since
633 // we don't know that the client has finished writing to it.
634 bool targetHasReservedGeom = fDstGpu->hasReservedVerticesOrIndices();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000635
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000636 int vcount = vertexCount;
637 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000638
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000639 if (!insideGeoPush &&
640 !unreleasedVertexSpace &&
641 !unreleasedIndexSpace &&
642 !targetHasReservedGeom &&
643 this->geometryHints(&vcount, &icount)) {
joshualittb9e82302014-10-31 12:20:08 -0700644
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000645 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000646 }
647}
648
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000649bool GrInOrderDrawBuffer::geometryHints(int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000650 int* indexCount) const {
651 // we will recommend a flush if the data could fit in a single
652 // preallocated buffer but none are left and it can't fit
653 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000654 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700655 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000656 int32_t currIndices = fIndexPool.currentBufferIndices();
657 if (*indexCount > currIndices &&
658 (!fIndexPool.preallocatedBuffersRemaining() &&
659 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
660
661 flush = true;
662 }
663 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000664 }
bsalomon49f085d2014-09-05 13:34:00 -0700665 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700666 size_t vertexStride = this->getDrawState().getVertexStride();
667 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000668 if (*vertexCount > currVertices &&
669 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700670 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000671
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000672 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000673 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000674 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000675 }
676 return flush;
677}
678
jvanverth@google.coma6338982013-01-31 21:34:25 +0000679bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000680 int vertexCount,
681 void** vertices) {
682 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000683 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700684 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000685 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000686
jvanverth@google.coma6338982013-01-31 21:34:25 +0000687 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000688 vertexCount,
689 &poolState.fPoolVertexBuffer,
690 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700691 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000692}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000693
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000694bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
695 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000696 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700697 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000698 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000699
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000700 *indices = fIndexPool.makeSpace(indexCount,
701 &poolState.fPoolIndexBuffer,
702 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700703 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000704}
705
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000706void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
707 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000708 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000709
710 // If we get a release vertex space call then our current source should either be reserved
711 // or array (which we copied into reserved space).
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000712 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc ||
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000713 kArray_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000714
715 // When the caller reserved vertex buffer space we gave it back a pointer
716 // provided by the vertex buffer pool. At each draw we tracked the largest
717 // offset into the pool's pointer that was referenced. Now we return to the
718 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000719 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000720 fVertexPool.putBack(reservedVertexBytes -
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000721 poolState.fUsedPoolVertexBytes);
722 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000723 poolState.fPoolVertexBuffer = NULL;
724 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000725}
726
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000727void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
728 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000729 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000730
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000731 // If we get a release index space call then our current source should either be reserved
732 // or array (which we copied into reserved space).
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000733 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc ||
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000734 kArray_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000735
736 // Similar to releaseReservedVertexSpace we return any unused portion at
737 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000738 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
739 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
740 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000741 poolState.fPoolIndexBuffer = NULL;
742 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000743}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000744
bsalomonb3e3a952014-09-19 11:10:40 -0700745void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000746 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000747 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000748#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000749 bool success =
750#endif
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000751 fVertexPool.appendVertices(this->getVertexSize(),
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000752 vertexCount,
753 vertexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000754 &poolState.fPoolVertexBuffer,
755 &poolState.fPoolStartVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000756 GR_DEBUGASSERT(success);
757}
758
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000759void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
760 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000761 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000762 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000763#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000764 bool success =
765#endif
766 fIndexPool.appendIndices(indexCount,
767 indexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000768 &poolState.fPoolIndexBuffer,
769 &poolState.fPoolStartIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000770 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000771}
772
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000773void GrInOrderDrawBuffer::releaseVertexArray() {
774 // When the client provides an array as the vertex source we handled it
775 // by copying their array into reserved space.
776 this->GrInOrderDrawBuffer::releaseReservedVertexSpace();
777}
778
779void GrInOrderDrawBuffer::releaseIndexArray() {
780 // When the client provides an array as the index source we handled it
781 // by copying their array into reserved space.
782 this->GrInOrderDrawBuffer::releaseReservedIndexSpace();
783}
784
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000785void GrInOrderDrawBuffer::geometrySourceWillPush() {
786 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
787 poolState.fUsedPoolVertexBytes = 0;
788 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000789#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000790 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
791 poolState.fPoolStartVertex = ~0;
792 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
793 poolState.fPoolStartIndex = ~0;
794#endif
795}
796
bsalomonb3e3a952014-09-19 11:10:40 -0700797void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000798 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000799 fGeoPoolStateStack.pop_back();
800 GeometryPoolState& poolState = fGeoPoolStateStack.back();
801 // we have to assume that any slack we had in our vertex/index data
802 // is now unreleasable because data may have been appended later in the
803 // pool.
804 if (kReserved_GeometrySrcType == restoredState.fVertexSrc ||
805 kArray_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000806 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000807 }
808 if (kReserved_GeometrySrcType == restoredState.fIndexSrc ||
809 kArray_GeometrySrcType == restoredState.fIndexSrc) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000810 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000811 restoredState.fIndexCount;
812 }
813}
814
bsalomon838f62d2014-08-05 07:15:57 -0700815void GrInOrderDrawBuffer::recordStateIfNecessary() {
cdalton6819df32014-10-15 13:43:48 -0700816 if (!fLastState) {
817 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (this->getDrawState()));
818 fLastState = &ss->fState;
819 this->convertDrawStateToPendingExec(fLastState);
820 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700821 return;
822 }
823 const GrDrawState& curr = this->getDrawState();
cdalton6819df32014-10-15 13:43:48 -0700824 switch (GrDrawState::CombineIfPossible(*fLastState, curr, *this->caps())) {
bsalomon838f62d2014-08-05 07:15:57 -0700825 case GrDrawState::kIncompatible_CombinedState:
cdalton6819df32014-10-15 13:43:48 -0700826 fLastState = &GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (curr))->fState;
827 this->convertDrawStateToPendingExec(fLastState);
828 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700829 break;
830 case GrDrawState::kA_CombinedState:
831 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA.
832 break;
833 case GrDrawState::kB_CombinedState:
bsalomon2a9ca782014-09-05 14:27:43 -0700834 // prev has already been converted to pending execution. That is a one-way ticket.
cdalton6819df32014-10-15 13:43:48 -0700835 // So here we just destruct the previous state and reinit with a new copy of curr.
836 // Note that this goes away when we move GrIODB over to taking optimized snapshots
837 // of draw states.
838 fLastState->~GrDrawState();
839 SkNEW_PLACEMENT_ARGS(fLastState, GrDrawState, (curr));
840 this->convertDrawStateToPendingExec(fLastState);
bsalomon838f62d2014-08-05 07:15:57 -0700841 break;
842 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000843}
844
cdalton6819df32014-10-15 13:43:48 -0700845void GrInOrderDrawBuffer::recordClipIfNecessary() {
846 if (this->getDrawState().isClipState() &&
847 fClipSet &&
848 (!fLastClip || *fLastClip != *this->getClip())) {
849 fLastClip = &GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetClip, (this->getClip()))->fClipData;
850 this->recordTraceMarkersIfNecessary();
851 fClipSet = false;
mtkleinf439c772014-10-14 14:29:30 -0700852 }
mtkleinf439c772014-10-14 14:29:30 -0700853}
854
cdalton6819df32014-10-15 13:43:48 -0700855void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
856 SkASSERT(!fCmdBuffer.empty());
857 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700858 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
859 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700860 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700861 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700862 }
mtklein07894c42014-10-13 14:00:42 -0700863}
864
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000865void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) {
866 INHERITED::clipWillBeSet(newClipData);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000867 fClipSet = true;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000868 fClipProxyState = kUnknown_ClipProxyState;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000869}