blob: efbe8611daabd656a5d114e8c65abd80cf47aaab [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)
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000020 : GrDrawTarget(gpu->getContext())
21 , fDstGpu(gpu)
bsalomon@google.com97805382012-03-13 14:32:07 +000022 , fClipSet(true)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000023 , fClipProxyState(kUnknown_ClipProxyState)
robertphillips@google.com69705572012-03-21 19:46:50 +000024 , fVertexPool(*vertexPool)
25 , fIndexPool(*indexPool)
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +000026 , fFlushing(false)
27 , fDrawID(0) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000028
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000029 fDstGpu->ref();
bsalomon@google.combcce8922013-03-25 15:38:39 +000030 fCaps.reset(SkRef(fDstGpu->caps()));
bsalomon@google.com18c9c192011-09-22 21:01:31 +000031
bsalomon49f085d2014-09-05 13:34:00 -070032 SkASSERT(vertexPool);
33 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000034
35 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
36 poolState.fUsedPoolVertexBytes = 0;
37 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000038#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000039 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
40 poolState.fPoolStartVertex = ~0;
41 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
42 poolState.fPoolStartIndex = ~0;
43#endif
bsalomon@google.coma4f6b102012-06-26 21:04:22 +000044 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000045}
46
47GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000048 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000049 // This must be called by before the GrDrawTarget destructor
50 this->releaseGeometry();
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000051 fDstGpu->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +000052}
53
bsalomon@google.com934c5702012-03-20 21:17:58 +000054////////////////////////////////////////////////////////////////////////////////
55
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000056namespace {
57void get_vertex_bounds(const void* vertices,
58 size_t vertexSize,
59 int vertexCount,
60 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000061 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000062 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000063 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000064 bounds->fLeft = bounds->fRight = point->fX;
65 bounds->fTop = bounds->fBottom = point->fY;
66 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000067 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000068 bounds->growToInclude(point->fX, point->fY);
69 }
70}
bsalomon@google.com934c5702012-03-20 21:17:58 +000071}
72
robertphillips@google.com42903302013-04-20 12:26:07 +000073
74namespace {
75
bsalomon62c447d2014-08-08 08:08:50 -070076extern const GrVertexAttrib kRectAttribs[] = {
77 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
78 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
79 {kVec2f_GrVertexAttribType, sizeof(SkPoint)+sizeof(GrColor), kLocalCoord_GrVertexAttribBinding},
robertphillips@google.com42903302013-04-20 12:26:07 +000080};
robertphillips@google.com42903302013-04-20 12:26:07 +000081}
82
bsalomon62c447d2014-08-08 08:08:50 -070083/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
84 have explicit local coords and sometimes not. We *could* always provide explicit local coords
85 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
86 haven't seen a use case which frequently switches between local rect and no local rect draws.
87
88 The color param is used to determine whether the opaque hint can be set on the draw state.
89 The caller must populate the vertex colors itself.
90
91 The vertex attrib order is always pos, color, [local coords].
92 */
93static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
94 if (hasLocalCoords) {
egdaniel7b3d5ee2014-08-28 05:41:14 -070095 drawState->setVertexAttribs<kRectAttribs>(3, 2 * sizeof(SkPoint) + sizeof(SkColor));
bsalomon62c447d2014-08-08 08:08:50 -070096 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -070097 drawState->setVertexAttribs<kRectAttribs>(2, sizeof(SkPoint) + sizeof(SkColor));
bsalomon62c447d2014-08-08 08:08:50 -070098 }
99 if (0xFF == GrColorUnpackA(color)) {
100 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
101 }
102}
robertphillips@google.com42903302013-04-20 12:26:07 +0000103
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000104enum {
105 kTraceCmdBit = 0x80,
106 kCmdMask = 0x7f,
107};
108
bsalomon62c447d2014-08-08 08:08:50 -0700109static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000110
bsalomon62c447d2014-08-08 08:08:50 -0700111static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000112
bsalomon62c447d2014-08-08 08:08:50 -0700113static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000114
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000115void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000116 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000117 const SkMatrix* localMatrix) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000118 GrDrawState* drawState = this->drawState();
119
120 GrColor color = drawState->getColor();
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000121
bsalomon49f085d2014-09-05 13:34:00 -0700122 set_vertex_attributes(drawState, SkToBool(localRect), color);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000123
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000124 AutoReleaseGeometry geo(this, 4, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000125 if (!geo.succeeded()) {
126 GrPrintf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000127 return;
128 }
129
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000130 // Go to device coords to allow batching across matrix changes
bsalomon01c8da12014-08-04 09:21:30 -0700131 SkMatrix matrix = drawState->getViewMatrix();
132
jvanverth@google.com39768252013-02-14 15:25:44 +0000133 // 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 +0000134 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
135 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000136 GrDrawState::AutoViewMatrixRestore avmr;
137 if (!avmr.setIdentity(drawState)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000138 return;
139 }
140
egdaniel7b3d5ee2014-08-28 05:41:14 -0700141 size_t vstride = drawState->getVertexStride();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000142
egdaniel7b3d5ee2014-08-28 05:41:14 -0700143 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
144 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000145
146 SkRect devBounds;
147 // since we already computed the dev verts, set the bounds hint. This will help us avoid
148 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700149 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000150
bsalomon49f085d2014-09-05 13:34:00 -0700151 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700152 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
153 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000154 coords->setRectFan(localRect->fLeft, localRect->fTop,
155 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700156 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700157 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700158 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000159 }
160 }
161
bsalomon62c447d2014-08-08 08:08:50 -0700162 static const int kColorOffset = sizeof(SkPoint);
163 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
164 for (int i = 0; i < 4; ++i) {
165 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700166 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000167 }
168
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000169 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000170 this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000171
172 // to ensure that stashing the drawState ptr is valid
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000173 SkASSERT(this->drawState() == drawState);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000174}
175
176bool GrInOrderDrawBuffer::quickInsideClip(const SkRect& devBounds) {
177 if (!this->getDrawState().isClipState()) {
178 return true;
179 }
180 if (kUnknown_ClipProxyState == fClipProxyState) {
181 SkIRect rect;
182 bool iior;
183 this->getClip()->getConservativeBounds(this->getDrawState().getRenderTarget(), &rect, &iior);
184 if (iior) {
185 // The clip is a rect. We will remember that in fProxyClip. It is common for an edge (or
186 // all edges) of the clip to be at the edge of the RT. However, we get that clipping for
187 // free via the viewport. We don't want to think that clipping must be enabled in this
188 // case. So we extend the clip outward from the edge to avoid these false negatives.
189 fClipProxyState = kValid_ClipProxyState;
reed@google.com44699382013-10-31 17:28:30 +0000190 fClipProxy = SkRect::Make(rect);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000191
192 if (fClipProxy.fLeft <= 0) {
193 fClipProxy.fLeft = SK_ScalarMin;
194 }
195 if (fClipProxy.fTop <= 0) {
196 fClipProxy.fTop = SK_ScalarMin;
197 }
198 if (fClipProxy.fRight >= this->getDrawState().getRenderTarget()->width()) {
199 fClipProxy.fRight = SK_ScalarMax;
200 }
201 if (fClipProxy.fBottom >= this->getDrawState().getRenderTarget()->height()) {
202 fClipProxy.fBottom = SK_ScalarMax;
203 }
204 } else {
205 fClipProxyState = kInvalid_ClipProxyState;
206 }
207 }
208 if (kValid_ClipProxyState == fClipProxyState) {
209 return fClipProxy.contains(devBounds);
210 }
211 SkPoint originOffset = {SkIntToScalar(this->getClip()->fOrigin.fX),
212 SkIntToScalar(this->getClip()->fOrigin.fY)};
213 SkRect clipSpaceBounds = devBounds;
214 clipSpaceBounds.offset(originOffset);
215 return this->getClip()->fClipStack->quickContains(clipSpaceBounds);
216}
217
218int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000219 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000220
bsalomon@google.com934c5702012-03-20 21:17:58 +0000221 const GeometrySrcState& geomSrc = this->getGeomSrc();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000222 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com934c5702012-03-20 21:17:58 +0000223
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000224 // we only attempt to concat the case when reserved verts are used with a client-specified index
225 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
226 // between draws.
227 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
228 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
229 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000230 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000231 // Check if there is a draw info that is compatible that uses the same VB from the pool and
232 // the same IB
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000233 if (kDraw_Cmd != strip_trace_bit(fCmds.back())) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000234 return 0;
235 }
236
bsalomonb3e3a952014-09-19 11:10:40 -0700237 Draw* draw = &fDraws.back();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000238 GeometryPoolState& poolState = fGeoPoolStateStack.back();
239 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
240
241 if (!draw->isInstanced() ||
242 draw->verticesPerInstance() != info.verticesPerInstance() ||
243 draw->indicesPerInstance() != info.indicesPerInstance() ||
bsalomonb3e3a952014-09-19 11:10:40 -0700244 draw->vertexBuffer() != vertexBuffer ||
245 draw->indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000246 return 0;
247 }
248 // info does not yet account for the offset from the start of the pool's VB while the previous
249 // draw record does.
250 int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
251 if (draw->startVertex() + draw->vertexCount() != adjustedStartVertex) {
252 return 0;
253 }
254
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000255 SkASSERT(poolState.fPoolStartVertex == draw->startVertex() + draw->vertexCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000256
257 // how many instances can be concat'ed onto draw given the size of the index buffer
258 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
259 instancesToConcat -= draw->instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000260 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000261
262 // update the amount of reserved vertex data actually referenced in draws
skia.committer@gmail.comae683922013-02-06 07:01:54 +0000263 size_t vertexBytes = instancesToConcat * info.verticesPerInstance() *
egdaniel7b3d5ee2014-08-28 05:41:14 -0700264 drawState.getVertexStride();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000265 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000266
267 draw->adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000268
269 // update last fGpuCmdMarkers to include any additional trace markers that have been added
270 if (this->getActiveTraceMarkers().count() > 0) {
271 if (cmd_has_trace_marker(fCmds.back())) {
272 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
273 } else {
274 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
275 fCmds.back() = add_trace_bit(fCmds.back());
276 }
277 }
278
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000279 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000280}
281
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000282class AutoClipReenable {
283public:
284 AutoClipReenable() : fDrawState(NULL) {}
285 ~AutoClipReenable() {
bsalomon49f085d2014-09-05 13:34:00 -0700286 if (fDrawState) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000287 fDrawState->enableState(GrDrawState::kClip_StateBit);
288 }
289 }
290 void set(GrDrawState* drawState) {
291 if (drawState->isClipState()) {
292 fDrawState = drawState;
293 drawState->disableState(GrDrawState::kClip_StateBit);
294 }
295 }
296private:
297 GrDrawState* fDrawState;
298};
299
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000300void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000301
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000302 GeometryPoolState& poolState = fGeoPoolStateStack.back();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000303 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000304 AutoClipReenable acr;
305
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000306 if (drawState.isClipState() &&
bsalomon49f085d2014-09-05 13:34:00 -0700307 info.getDevBounds() &&
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000308 this->quickInsideClip(*info.getDevBounds())) {
309 acr.set(this->drawState());
310 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000311
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000312 if (this->needsNewClip()) {
313 this->recordClip();
314 }
bsalomon838f62d2014-08-05 07:15:57 -0700315 this->recordStateIfNecessary();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000316
bsalomonb3e3a952014-09-19 11:10:40 -0700317 const GrVertexBuffer* vb;
318 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
319 vb = this->getGeomSrc().fVertexBuffer;
320 } else {
321 vb = poolState.fPoolVertexBuffer;
322 }
323
324 const GrIndexBuffer* ib = NULL;
325 if (info.isIndexed()) {
326 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) {
327 ib = this->getGeomSrc().fIndexBuffer;
328 } else {
329 ib = poolState.fPoolIndexBuffer;
330 }
331 }
332
333 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000334 if (info.isInstanced()) {
335 int instancesConcated = this->concatInstancedDraw(info);
336 if (info.instanceCount() > instancesConcated) {
bsalomonb3e3a952014-09-19 11:10:40 -0700337 draw = this->recordDraw(info, vb, ib);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000338 draw->adjustInstanceCount(-instancesConcated);
339 } else {
340 return;
341 }
342 } else {
bsalomonb3e3a952014-09-19 11:10:40 -0700343 draw = this->recordDraw(info, vb, ib);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000344 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000345
bsalomonb3e3a952014-09-19 11:10:40 -0700346 // Adjust the starting vertex and index when we are using reserved or array sources to
347 // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
348 if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
349 size_t bytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexStride();
350 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
351 draw->adjustStartVertex(poolState.fPoolStartVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +0000352 }
bsalomonb3e3a952014-09-19 11:10:40 -0700353
354 if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) {
355 size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
356 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes);
357 draw->adjustStartIndex(poolState.fPoolStartIndex);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000358 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000359}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000360
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000361void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, SkPath::FillType fill) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000362 if (this->needsNewClip()) {
363 this->recordClip();
364 }
365 // Only compare the subset of GrDrawState relevant to path stenciling?
bsalomon838f62d2014-08-05 07:15:57 -0700366 this->recordStateIfNecessary();
bsalomonb3e3a952014-09-19 11:10:40 -0700367 StencilPath* sp = this->recordStencilPath(path);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000368 sp->fFill = fill;
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000369}
370
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000371void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000372 SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
373 if (this->needsNewClip()) {
374 this->recordClip();
375 }
376 // TODO: Only compare the subset of GrDrawState relevant to path covering?
bsalomon838f62d2014-08-05 07:15:57 -0700377 this->recordStateIfNecessary();
bsalomonb3e3a952014-09-19 11:10:40 -0700378 DrawPath* cp = this->recordDrawPath(path);
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000379 cp->fFill = fill;
bsalomon49f085d2014-09-05 13:34:00 -0700380 if (dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000381 cp->fDstCopy = *dstCopy;
382 }
383}
384
cdaltonb85a0aa2014-07-21 15:32:44 -0700385void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
386 const uint32_t indices[], int count,
387 const float transforms[], PathTransformType transformsType,
388 SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700389 SkASSERT(pathRange);
390 SkASSERT(indices);
391 SkASSERT(transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000392
393 if (this->needsNewClip()) {
394 this->recordClip();
395 }
bsalomon838f62d2014-08-05 07:15:57 -0700396 this->recordStateIfNecessary();
bsalomonb3e3a952014-09-19 11:10:40 -0700397 DrawPaths* dp = this->recordDrawPaths(pathRange);
cdaltonb85a0aa2014-07-21 15:32:44 -0700398 dp->fIndices = SkNEW_ARRAY(uint32_t, count); // TODO: Accomplish this without a malloc
399 memcpy(dp->fIndices, indices, sizeof(uint32_t) * count);
400 dp->fCount = count;
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000401
kkinnunenccdaa042014-08-20 01:36:23 -0700402 const int transformsLength = GrPathRendering::PathTransformSize(transformsType) * count;
cdaltonb85a0aa2014-07-21 15:32:44 -0700403 dp->fTransforms = SkNEW_ARRAY(float, transformsLength);
404 memcpy(dp->fTransforms, transforms, sizeof(float) * transformsLength);
405 dp->fTransformsType = transformsType;
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000406
407 dp->fFill = fill;
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000408
bsalomon49f085d2014-09-05 13:34:00 -0700409 if (dstCopy) {
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000410 dp->fDstCopy = *dstCopy;
411 }
412}
413
skia.committer@gmail.com18bb41e2013-11-01 07:02:15 +0000414void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000415 bool canIgnoreRect, GrRenderTarget* renderTarget) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000416 SkIRect r;
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000417 if (NULL == renderTarget) {
418 renderTarget = this->drawState()->getRenderTarget();
bsalomon49f085d2014-09-05 13:34:00 -0700419 SkASSERT(renderTarget);
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000420 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000421 if (NULL == rect) {
422 // We could do something smart and remove previous draws and clears to
423 // the current render target. If we get that smart we have to make sure
424 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000425 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000426 rect = &r;
427 }
bsalomonb3e3a952014-09-19 11:10:40 -0700428 Clear* clr = this->recordClear(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000429 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000430 clr->fColor = color;
431 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000432 clr->fCanIgnoreRect = canIgnoreRect;
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000433}
434
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000435void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
436 if (!this->caps()->discardRenderTargetSupport()) {
437 return;
438 }
439 if (NULL == renderTarget) {
440 renderTarget = this->drawState()->getRenderTarget();
bsalomon49f085d2014-09-05 13:34:00 -0700441 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000442 }
bsalomonb3e3a952014-09-19 11:10:40 -0700443 Clear* clr = this->recordClear(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000444 clr->fColor = GrColor_ILLEGAL;
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000445}
446
reed@google.comac10a2d2010-12-22 21:39:39 +0000447void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000448 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000449 this->resetVertexSource();
450 this->resetIndexSource();
bsalomonbce3d6d2014-07-02 07:54:42 -0700451
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000452 fCmds.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000453 fDraws.reset();
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000454 fStencilPaths.reset();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000455 fDrawPath.reset();
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000456 fDrawPaths.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000457 fStates.reset();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000458 fClears.reset();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000459 fVertexPool.reset();
460 fIndexPool.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000461 fClips.reset();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000462 fCopySurfaces.reset();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000463 fGpuCmdMarkers.reset();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000464 fClipSet = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000465}
466
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000467void GrInOrderDrawBuffer::flush() {
468 if (fFlushing) {
469 return;
470 }
471
jvanverth8e80d172014-06-19 12:01:10 -0700472 this->getContext()->getFontCache()->updateTextures();
473
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000474 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
475 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000476
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000477 int numCmds = fCmds.count();
bsalomon@google.com358e4272013-01-10 14:40:28 +0000478 if (0 == numCmds) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000479 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000480 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000481
482 GrAutoTRestore<bool> flushRestore(&fFlushing);
483 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000484
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000485 fVertexPool.unmap();
486 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000487
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000488 GrDrawTarget::AutoClipRestore acr(fDstGpu);
489 AutoGeometryAndStatePush agasp(fDstGpu, kPreserve_ASRInit);
bsalomon@google.comca432082013-01-23 19:53:46 +0000490
bsalomona70353e2014-07-07 08:15:07 -0700491 GrDrawState* prevDrawState = SkRef(fDstGpu->drawState());
reed@google.comac10a2d2010-12-22 21:39:39 +0000492
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000493 GrClipData clipData;
494
bsalomonbce3d6d2014-07-02 07:54:42 -0700495 StateAllocator::Iter stateIter(&fStates);
496 ClipAllocator::Iter clipIter(&fClips);
bsalomonbce3d6d2014-07-02 07:54:42 -0700497 ClearAllocator::Iter clearIter(&fClears);
498 DrawAllocator::Iter drawIter(&fDraws);
499 StencilPathAllocator::Iter stencilPathIter(&fStencilPaths);
500 DrawPathAllocator::Iter drawPathIter(&fDrawPath);
501 DrawPathsAllocator::Iter drawPathsIter(&fDrawPaths);
502 CopySurfaceAllocator::Iter copySurfaceIter(&fCopySurfaces);
503
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000504 int currCmdMarker = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000505
egdaniel3eee3832014-06-18 13:09:11 -0700506 fDstGpu->saveActiveTraceMarkers();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000507 for (int c = 0; c < numCmds; ++c) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000508 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700509 SkString traceString;
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000510 if (cmd_has_trace_marker(fCmds[c])) {
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 }
516 switch (strip_trace_bit(fCmds[c])) {
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000517 case kDraw_Cmd: {
bsalomona70353e2014-07-07 08:15:07 -0700518 SkASSERT(fDstGpu->drawState() != prevDrawState);
bsalomonbce3d6d2014-07-02 07:54:42 -0700519 SkAssertResult(drawIter.next());
bsalomonb3e3a952014-09-19 11:10:40 -0700520 fDstGpu->setVertexSourceToBuffer(drawIter->vertexBuffer());
bsalomonbce3d6d2014-07-02 07:54:42 -0700521 if (drawIter->isIndexed()) {
bsalomonb3e3a952014-09-19 11:10:40 -0700522 fDstGpu->setIndexSourceToBuffer(drawIter->indexBuffer());
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000523 }
bsalomonbce3d6d2014-07-02 07:54:42 -0700524 fDstGpu->executeDraw(*drawIter);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000525 break;
526 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000527 case kStencilPath_Cmd: {
bsalomona70353e2014-07-07 08:15:07 -0700528 SkASSERT(fDstGpu->drawState() != prevDrawState);
bsalomonbce3d6d2014-07-02 07:54:42 -0700529 SkAssertResult(stencilPathIter.next());
bsalomonb3e3a952014-09-19 11:10:40 -0700530 fDstGpu->stencilPath(stencilPathIter->path(), stencilPathIter->fFill);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000531 break;
532 }
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000533 case kDrawPath_Cmd: {
bsalomona70353e2014-07-07 08:15:07 -0700534 SkASSERT(fDstGpu->drawState() != prevDrawState);
bsalomonbce3d6d2014-07-02 07:54:42 -0700535 SkAssertResult(drawPathIter.next());
bsalomonb3e3a952014-09-19 11:10:40 -0700536 fDstGpu->executeDrawPath(drawPathIter->path(), drawPathIter->fFill,
bsalomon49f085d2014-09-05 13:34:00 -0700537 drawPathIter->fDstCopy.texture() ?
bsalomonbce3d6d2014-07-02 07:54:42 -0700538 &drawPathIter->fDstCopy :
539 NULL);
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000540 break;
541 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000542 case kDrawPaths_Cmd: {
bsalomona70353e2014-07-07 08:15:07 -0700543 SkASSERT(fDstGpu->drawState() != prevDrawState);
bsalomonbce3d6d2014-07-02 07:54:42 -0700544 SkAssertResult(drawPathsIter.next());
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000545 const GrDeviceCoordTexture* dstCopy =
bsalomon49f085d2014-09-05 13:34:00 -0700546 drawPathsIter->fDstCopy.texture() ? &drawPathsIter->fDstCopy : NULL;
bsalomonb3e3a952014-09-19 11:10:40 -0700547 fDstGpu->executeDrawPaths(drawPathsIter->pathRange(),
cdaltonb85a0aa2014-07-21 15:32:44 -0700548 drawPathsIter->fIndices,
549 drawPathsIter->fCount,
550 drawPathsIter->fTransforms,
551 drawPathsIter->fTransformsType,
552 drawPathsIter->fFill,
553 dstCopy);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000554 break;
555 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000556 case kSetState_Cmd:
bsalomonbce3d6d2014-07-02 07:54:42 -0700557 SkAssertResult(stateIter.next());
bsalomona70353e2014-07-07 08:15:07 -0700558 fDstGpu->setDrawState(stateIter.get());
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000559 break;
560 case kSetClip_Cmd:
bsalomonbce3d6d2014-07-02 07:54:42 -0700561 SkAssertResult(clipIter.next());
bsalomonf0480b12014-07-02 12:11:24 -0700562 clipData.fClipStack = &clipIter->fStack;
563 clipData.fOrigin = clipIter->fOrigin;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000564 fDstGpu->setClip(&clipData);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000565 break;
566 case kClear_Cmd:
bsalomonbce3d6d2014-07-02 07:54:42 -0700567 SkAssertResult(clearIter.next());
568 if (GrColor_ILLEGAL == clearIter->fColor) {
bsalomonb3e3a952014-09-19 11:10:40 -0700569 fDstGpu->discard(clearIter->renderTarget());
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000570 } else {
bsalomonbce3d6d2014-07-02 07:54:42 -0700571 fDstGpu->clear(&clearIter->fRect,
572 clearIter->fColor,
573 clearIter->fCanIgnoreRect,
bsalomonb3e3a952014-09-19 11:10:40 -0700574 clearIter->renderTarget());
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000575 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000576 break;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000577 case kCopySurface_Cmd:
bsalomonbce3d6d2014-07-02 07:54:42 -0700578 SkAssertResult(copySurfaceIter.next());
bsalomonb3e3a952014-09-19 11:10:40 -0700579 fDstGpu->copySurface(copySurfaceIter->dst(),
580 copySurfaceIter->src(),
bsalomonbce3d6d2014-07-02 07:54:42 -0700581 copySurfaceIter->fSrcRect,
582 copySurfaceIter->fDstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000583 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000584 }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000585 if (cmd_has_trace_marker(fCmds[c])) {
586 fDstGpu->removeGpuTraceMarker(&newMarker);
587 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000588 }
egdaniel3eee3832014-06-18 13:09:11 -0700589 fDstGpu->restoreActiveTraceMarkers();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000590 // we should have consumed all the states, clips, etc.
bsalomonbce3d6d2014-07-02 07:54:42 -0700591 SkASSERT(!stateIter.next());
592 SkASSERT(!clipIter.next());
bsalomonbce3d6d2014-07-02 07:54:42 -0700593 SkASSERT(!clearIter.next());
594 SkASSERT(!drawIter.next());
595 SkASSERT(!copySurfaceIter.next());
596 SkASSERT(!stencilPathIter.next());
597 SkASSERT(!drawPathIter.next());
598 SkASSERT(!drawPathsIter.next());
599
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000600 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000601
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000602 fDstGpu->setDrawState(prevDrawState);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000603 prevDrawState->unref();
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000604 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000605 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000606}
607
bsalomon@google.com116ad842013-04-09 15:38:19 +0000608bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
609 GrSurface* src,
610 const SkIRect& srcRect,
611 const SkIPoint& dstPoint) {
612 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
bsalomonb3e3a952014-09-19 11:10:40 -0700613 CopySurface* cs = this->recordCopySurface(dst, src);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000614 cs->fSrcRect = srcRect;
615 cs->fDstPoint = dstPoint;
616 return true;
617 } else {
618 return false;
619 }
620}
621
622bool GrInOrderDrawBuffer::onCanCopySurface(GrSurface* dst,
623 GrSurface* src,
624 const SkIRect& srcRect,
625 const SkIPoint& dstPoint) {
626 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint);
627}
628
bsalomon@google.comeb851172013-04-15 13:51:00 +0000629void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) {
630 fDstGpu->initCopySurfaceDstDesc(src, desc);
631}
632
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000633void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
634 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000635 // We use geometryHints() to know whether to flush the draw buffer. We
636 // can't flush if we are inside an unbalanced pushGeometrySource.
637 // Moreover, flushing blows away vertex and index data that was
638 // previously reserved. So if the vertex or index data is pulled from
639 // reserved space and won't be released by this request then we can't
640 // flush.
641 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000642
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000643 bool unreleasedVertexSpace =
644 !vertexCount &&
645 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000646
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000647 bool unreleasedIndexSpace =
648 !indexCount &&
649 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000650
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000651 // we don't want to finalize any reserved geom on the target since
652 // we don't know that the client has finished writing to it.
653 bool targetHasReservedGeom = fDstGpu->hasReservedVerticesOrIndices();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000654
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000655 int vcount = vertexCount;
656 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000657
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000658 if (!insideGeoPush &&
659 !unreleasedVertexSpace &&
660 !unreleasedIndexSpace &&
661 !targetHasReservedGeom &&
662 this->geometryHints(&vcount, &icount)) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000663
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000664 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000665 }
666}
667
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000668bool GrInOrderDrawBuffer::geometryHints(int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000669 int* indexCount) const {
670 // we will recommend a flush if the data could fit in a single
671 // preallocated buffer but none are left and it can't fit
672 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000673 bool flush = false;
bsalomon49f085d2014-09-05 13:34:00 -0700674 if (indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000675 int32_t currIndices = fIndexPool.currentBufferIndices();
676 if (*indexCount > currIndices &&
677 (!fIndexPool.preallocatedBuffersRemaining() &&
678 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
679
680 flush = true;
681 }
682 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000683 }
bsalomon49f085d2014-09-05 13:34:00 -0700684 if (vertexCount) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700685 size_t vertexStride = this->getDrawState().getVertexStride();
686 int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000687 if (*vertexCount > currVertices &&
688 (!fVertexPool.preallocatedBuffersRemaining() &&
egdaniel7b3d5ee2014-08-28 05:41:14 -0700689 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexStride))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000690
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000691 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000692 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000693 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000694 }
695 return flush;
696}
697
jvanverth@google.coma6338982013-01-31 21:34:25 +0000698bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000699 int vertexCount,
700 void** vertices) {
701 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000702 SkASSERT(vertexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700703 SkASSERT(vertices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000704 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000705
jvanverth@google.coma6338982013-01-31 21:34:25 +0000706 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000707 vertexCount,
708 &poolState.fPoolVertexBuffer,
709 &poolState.fPoolStartVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700710 return SkToBool(*vertices);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000711}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000712
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000713bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
714 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000715 SkASSERT(indexCount > 0);
bsalomon49f085d2014-09-05 13:34:00 -0700716 SkASSERT(indices);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000717 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000718
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000719 *indices = fIndexPool.makeSpace(indexCount,
720 &poolState.fPoolIndexBuffer,
721 &poolState.fPoolStartIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700722 return SkToBool(*indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000723}
724
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000725void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
726 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000727 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000728
729 // If we get a release vertex 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.fVertexSrc ||
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000732 kArray_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000733
734 // When the caller reserved vertex buffer space we gave it back a pointer
735 // provided by the vertex buffer pool. At each draw we tracked the largest
736 // offset into the pool's pointer that was referenced. Now we return to the
737 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000738 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000739 fVertexPool.putBack(reservedVertexBytes -
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000740 poolState.fUsedPoolVertexBytes);
741 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000742 poolState.fPoolVertexBuffer = NULL;
743 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000744}
745
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000746void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
747 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000748 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000749
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000750 // If we get a release index space call then our current source should either be reserved
751 // or array (which we copied into reserved space).
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000752 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc ||
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000753 kArray_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000754
755 // Similar to releaseReservedVertexSpace we return any unused portion at
756 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000757 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
758 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
759 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000760 poolState.fPoolIndexBuffer = NULL;
761 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000762}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000763
bsalomonb3e3a952014-09-19 11:10:40 -0700764void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000765 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000766 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000767#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000768 bool success =
769#endif
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000770 fVertexPool.appendVertices(this->getVertexSize(),
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000771 vertexCount,
772 vertexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000773 &poolState.fPoolVertexBuffer,
774 &poolState.fPoolStartVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000775 GR_DEBUGASSERT(success);
776}
777
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000778void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
779 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000780 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000781 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000782#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000783 bool success =
784#endif
785 fIndexPool.appendIndices(indexCount,
786 indexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000787 &poolState.fPoolIndexBuffer,
788 &poolState.fPoolStartIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000789 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000790}
791
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000792void GrInOrderDrawBuffer::releaseVertexArray() {
793 // When the client provides an array as the vertex source we handled it
794 // by copying their array into reserved space.
795 this->GrInOrderDrawBuffer::releaseReservedVertexSpace();
796}
797
798void GrInOrderDrawBuffer::releaseIndexArray() {
799 // When the client provides an array as the index source we handled it
800 // by copying their array into reserved space.
801 this->GrInOrderDrawBuffer::releaseReservedIndexSpace();
802}
803
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000804void GrInOrderDrawBuffer::geometrySourceWillPush() {
805 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
806 poolState.fUsedPoolVertexBytes = 0;
807 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000808#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000809 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
810 poolState.fPoolStartVertex = ~0;
811 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
812 poolState.fPoolStartIndex = ~0;
813#endif
814}
815
bsalomonb3e3a952014-09-19 11:10:40 -0700816void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000817 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000818 fGeoPoolStateStack.pop_back();
819 GeometryPoolState& poolState = fGeoPoolStateStack.back();
820 // we have to assume that any slack we had in our vertex/index data
821 // is now unreleasable because data may have been appended later in the
822 // pool.
823 if (kReserved_GeometrySrcType == restoredState.fVertexSrc ||
824 kArray_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000825 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000826 }
827 if (kReserved_GeometrySrcType == restoredState.fIndexSrc ||
828 kArray_GeometrySrcType == restoredState.fIndexSrc) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000829 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000830 restoredState.fIndexCount;
831 }
832}
833
bsalomon838f62d2014-08-05 07:15:57 -0700834void GrInOrderDrawBuffer::recordStateIfNecessary() {
835 if (fStates.empty()) {
836 fStates.push_back() = this->getDrawState();
837 this->addToCmdBuffer(kSetState_Cmd);
838 return;
839 }
840 const GrDrawState& curr = this->getDrawState();
841 GrDrawState& prev = fStates.back();
bsalomon62c447d2014-08-08 08:08:50 -0700842 switch (GrDrawState::CombineIfPossible(prev, curr, *this->caps())) {
bsalomon838f62d2014-08-05 07:15:57 -0700843 case GrDrawState::kIncompatible_CombinedState:
bsalomon2a9ca782014-09-05 14:27:43 -0700844 this->convertDrawStateToPendingExec(&fStates.push_back(curr));
bsalomon838f62d2014-08-05 07:15:57 -0700845 this->addToCmdBuffer(kSetState_Cmd);
846 break;
847 case GrDrawState::kA_CombinedState:
848 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA.
849 break;
850 case GrDrawState::kB_CombinedState:
bsalomon2a9ca782014-09-05 14:27:43 -0700851 // prev has already been converted to pending execution. That is a one-way ticket.
852 // So here we just delete prev and push back a new copy of curr. Note that this
853 // goes away when we move GrIODB over to taking optimized snapshots of draw states.
854 fStates.pop_back();
855 this->convertDrawStateToPendingExec(&fStates.push_back(curr));
bsalomon838f62d2014-08-05 07:15:57 -0700856 break;
857 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000858}
859
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000860bool GrInOrderDrawBuffer::needsNewClip() const {
bsalomon@google.com358e4272013-01-10 14:40:28 +0000861 if (this->getDrawState().isClipState()) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000862 if (fClipSet &&
bsalomon@google.com358e4272013-01-10 14:40:28 +0000863 (fClips.empty() ||
bsalomonf0480b12014-07-02 12:11:24 -0700864 fClips.back().fStack != *this->getClip()->fClipStack ||
865 fClips.back().fOrigin != this->getClip()->fOrigin)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000866 return true;
867 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000868 }
869 return false;
870}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000871
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000872void GrInOrderDrawBuffer::addToCmdBuffer(uint8_t cmd) {
873 SkASSERT(!cmd_has_trace_marker(cmd));
874 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
875 if (activeTraceMarkers.count() > 0) {
876 fCmds.push_back(add_trace_bit(cmd));
877 fGpuCmdMarkers.push_back(activeTraceMarkers);
878 } else {
879 fCmds.push_back(cmd);
880 }
881}
882
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000883void GrInOrderDrawBuffer::recordClip() {
bsalomonf0480b12014-07-02 12:11:24 -0700884 fClips.push_back().fStack = *this->getClip()->fClipStack;
885 fClips.back().fOrigin = this->getClip()->fOrigin;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000886 fClipSet = false;
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000887 this->addToCmdBuffer(kSetClip_Cmd);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000888}
889
bsalomonb3e3a952014-09-19 11:10:40 -0700890GrInOrderDrawBuffer::Draw* GrInOrderDrawBuffer::recordDraw(const DrawInfo& info,
891 const GrVertexBuffer* vb,
892 const GrIndexBuffer* ib) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000893 this->addToCmdBuffer(kDraw_Cmd);
bsalomonb3e3a952014-09-19 11:10:40 -0700894 return GrNEW_APPEND_TO_ALLOCATOR(&fDraws, Draw, (info, vb, ib));
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000895}
896
bsalomonb3e3a952014-09-19 11:10:40 -0700897GrInOrderDrawBuffer::StencilPath* GrInOrderDrawBuffer::recordStencilPath(const GrPath* path) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000898 this->addToCmdBuffer(kStencilPath_Cmd);
bsalomonb3e3a952014-09-19 11:10:40 -0700899 return GrNEW_APPEND_TO_ALLOCATOR(&fStencilPaths, StencilPath, (path));
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000900}
901
bsalomonb3e3a952014-09-19 11:10:40 -0700902GrInOrderDrawBuffer::DrawPath* GrInOrderDrawBuffer::recordDrawPath(const GrPath* path) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000903 this->addToCmdBuffer(kDrawPath_Cmd);
bsalomonb3e3a952014-09-19 11:10:40 -0700904 return GrNEW_APPEND_TO_ALLOCATOR(&fDrawPath, DrawPath, (path));
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000905}
906
bsalomonb3e3a952014-09-19 11:10:40 -0700907GrInOrderDrawBuffer::DrawPaths* GrInOrderDrawBuffer::recordDrawPaths(const GrPathRange* pathRange) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000908 this->addToCmdBuffer(kDrawPaths_Cmd);
bsalomonb3e3a952014-09-19 11:10:40 -0700909 return GrNEW_APPEND_TO_ALLOCATOR(&fDrawPaths, DrawPaths, (pathRange));
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000910}
911
bsalomonb3e3a952014-09-19 11:10:40 -0700912GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear(GrRenderTarget* rt) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000913 this->addToCmdBuffer(kClear_Cmd);
bsalomonb3e3a952014-09-19 11:10:40 -0700914 return GrNEW_APPEND_TO_ALLOCATOR(&fClears, Clear, (rt));
reed@google.comac10a2d2010-12-22 21:39:39 +0000915}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000916
bsalomonb3e3a952014-09-19 11:10:40 -0700917GrInOrderDrawBuffer::CopySurface* GrInOrderDrawBuffer::recordCopySurface(GrSurface* dst,
918 GrSurface* src) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000919 this->addToCmdBuffer(kCopySurface_Cmd);
bsalomonb3e3a952014-09-19 11:10:40 -0700920 return GrNEW_APPEND_TO_ALLOCATOR(&fCopySurfaces, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000921}
922
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000923void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) {
924 INHERITED::clipWillBeSet(newClipData);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000925 fClipSet = true;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000926 fClipProxyState = kUnknown_ClipProxyState;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000927}