blob: 9df54a807609719911ed4f3929ddfdb81c5fe687 [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"
14#include "GrIndexBuffer.h"
15#include "GrPath.h"
cdaltonb85a0aa2014-07-21 15:32:44 -070016#include "GrPathRange.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000017#include "GrRenderTarget.h"
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000018#include "GrTemplates.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000019#include "GrTexture.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000020#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000021
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000022GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
bsalomon@google.com471d4712011-08-23 15:45:25 +000023 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000024 GrIndexBufferAllocPool* indexPool)
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000025 : GrDrawTarget(gpu->getContext())
26 , fDstGpu(gpu)
bsalomon@google.com97805382012-03-13 14:32:07 +000027 , fClipSet(true)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000028 , fClipProxyState(kUnknown_ClipProxyState)
robertphillips@google.com69705572012-03-21 19:46:50 +000029 , fVertexPool(*vertexPool)
30 , fIndexPool(*indexPool)
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +000031 , fFlushing(false)
32 , fDrawID(0) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000033
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000034 fDstGpu->ref();
bsalomon@google.combcce8922013-03-25 15:38:39 +000035 fCaps.reset(SkRef(fDstGpu->caps()));
bsalomon@google.com18c9c192011-09-22 21:01:31 +000036
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000037 SkASSERT(NULL != vertexPool);
38 SkASSERT(NULL != indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000039
40 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
41 poolState.fUsedPoolVertexBytes = 0;
42 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000043#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000044 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
45 poolState.fPoolStartVertex = ~0;
46 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
47 poolState.fPoolStartIndex = ~0;
48#endif
bsalomon@google.coma4f6b102012-06-26 21:04:22 +000049 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000050}
51
52GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000053 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000054 // This must be called by before the GrDrawTarget destructor
55 this->releaseGeometry();
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000056 fDstGpu->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +000057}
58
bsalomon@google.com934c5702012-03-20 21:17:58 +000059////////////////////////////////////////////////////////////////////////////////
60
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000061namespace {
62void get_vertex_bounds(const void* vertices,
63 size_t vertexSize,
64 int vertexCount,
65 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000066 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000067 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000068 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000069 bounds->fLeft = bounds->fRight = point->fX;
70 bounds->fTop = bounds->fBottom = point->fY;
71 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000072 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000073 bounds->growToInclude(point->fX, point->fY);
74 }
75}
bsalomon@google.com934c5702012-03-20 21:17:58 +000076}
77
robertphillips@google.com42903302013-04-20 12:26:07 +000078
79namespace {
80
bsalomon62c447d2014-08-08 08:08:50 -070081extern const GrVertexAttrib kRectAttribs[] = {
82 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
83 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
84 {kVec2f_GrVertexAttribType, sizeof(SkPoint)+sizeof(GrColor), kLocalCoord_GrVertexAttribBinding},
robertphillips@google.com42903302013-04-20 12:26:07 +000085};
robertphillips@google.com42903302013-04-20 12:26:07 +000086}
87
bsalomon62c447d2014-08-08 08:08:50 -070088/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
89 have explicit local coords and sometimes not. We *could* always provide explicit local coords
90 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
91 haven't seen a use case which frequently switches between local rect and no local rect draws.
92
93 The color param is used to determine whether the opaque hint can be set on the draw state.
94 The caller must populate the vertex colors itself.
95
96 The vertex attrib order is always pos, color, [local coords].
97 */
98static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
99 if (hasLocalCoords) {
djsollenea81ced2014-08-27 13:07:34 -0700100 drawState->setVertexAttribs<kRectAttribs>(3);
bsalomon62c447d2014-08-08 08:08:50 -0700101 } else {
djsollenea81ced2014-08-27 13:07:34 -0700102 drawState->setVertexAttribs<kRectAttribs>(2);
bsalomon62c447d2014-08-08 08:08:50 -0700103 }
104 if (0xFF == GrColorUnpackA(color)) {
105 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
106 }
107}
robertphillips@google.com42903302013-04-20 12:26:07 +0000108
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000109enum {
110 kTraceCmdBit = 0x80,
111 kCmdMask = 0x7f,
112};
113
bsalomon62c447d2014-08-08 08:08:50 -0700114static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000115
bsalomon62c447d2014-08-08 08:08:50 -0700116static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000117
bsalomon62c447d2014-08-08 08:08:50 -0700118static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000119
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000120void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000121 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000122 const SkMatrix* localMatrix) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000123 GrDrawState* drawState = this->drawState();
124
125 GrColor color = drawState->getColor();
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000126
bsalomon62c447d2014-08-08 08:08:50 -0700127 set_vertex_attributes(drawState, NULL != localRect, color);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000128
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000129 AutoReleaseGeometry geo(this, 4, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000130 if (!geo.succeeded()) {
131 GrPrintf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000132 return;
133 }
134
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000135 // Go to device coords to allow batching across matrix changes
bsalomon01c8da12014-08-04 09:21:30 -0700136 SkMatrix matrix = drawState->getViewMatrix();
137
jvanverth@google.com39768252013-02-14 15:25:44 +0000138 // 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 +0000139 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
140 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000141 GrDrawState::AutoViewMatrixRestore avmr;
142 if (!avmr.setIdentity(drawState)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000143 return;
144 }
145
djsollenea81ced2014-08-27 13:07:34 -0700146 size_t vsize = drawState->getVertexSize();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000147
djsollenea81ced2014-08-27 13:07:34 -0700148 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
149 matrix.mapPointsWithStride(geo.positions(), vsize, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000150
151 SkRect devBounds;
152 // since we already computed the dev verts, set the bounds hint. This will help us avoid
153 // unnecessary clipping in our onDraw().
djsollenea81ced2014-08-27 13:07:34 -0700154 get_vertex_bounds(geo.vertices(), vsize, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000155
bsalomon62c447d2014-08-08 08:08:50 -0700156 if (NULL != localRect) {
157 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
158 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000159 coords->setRectFan(localRect->fLeft, localRect->fTop,
160 localRect->fRight, localRect->fBottom,
djsollenea81ced2014-08-27 13:07:34 -0700161 vsize);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000162 if (NULL != localMatrix) {
djsollenea81ced2014-08-27 13:07:34 -0700163 localMatrix->mapPointsWithStride(coords, vsize, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000164 }
165 }
166
bsalomon62c447d2014-08-08 08:08:50 -0700167 static const int kColorOffset = sizeof(SkPoint);
168 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
169 for (int i = 0; i < 4; ++i) {
170 *vertColor = color;
djsollenea81ced2014-08-27 13:07:34 -0700171 vertColor = (GrColor*) ((intptr_t) vertColor + vsize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000172 }
173
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000174 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000175 this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000176
177 // to ensure that stashing the drawState ptr is valid
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000178 SkASSERT(this->drawState() == drawState);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000179}
180
181bool GrInOrderDrawBuffer::quickInsideClip(const SkRect& devBounds) {
182 if (!this->getDrawState().isClipState()) {
183 return true;
184 }
185 if (kUnknown_ClipProxyState == fClipProxyState) {
186 SkIRect rect;
187 bool iior;
188 this->getClip()->getConservativeBounds(this->getDrawState().getRenderTarget(), &rect, &iior);
189 if (iior) {
190 // The clip is a rect. We will remember that in fProxyClip. It is common for an edge (or
191 // all edges) of the clip to be at the edge of the RT. However, we get that clipping for
192 // free via the viewport. We don't want to think that clipping must be enabled in this
193 // case. So we extend the clip outward from the edge to avoid these false negatives.
194 fClipProxyState = kValid_ClipProxyState;
reed@google.com44699382013-10-31 17:28:30 +0000195 fClipProxy = SkRect::Make(rect);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000196
197 if (fClipProxy.fLeft <= 0) {
198 fClipProxy.fLeft = SK_ScalarMin;
199 }
200 if (fClipProxy.fTop <= 0) {
201 fClipProxy.fTop = SK_ScalarMin;
202 }
203 if (fClipProxy.fRight >= this->getDrawState().getRenderTarget()->width()) {
204 fClipProxy.fRight = SK_ScalarMax;
205 }
206 if (fClipProxy.fBottom >= this->getDrawState().getRenderTarget()->height()) {
207 fClipProxy.fBottom = SK_ScalarMax;
208 }
209 } else {
210 fClipProxyState = kInvalid_ClipProxyState;
211 }
212 }
213 if (kValid_ClipProxyState == fClipProxyState) {
214 return fClipProxy.contains(devBounds);
215 }
216 SkPoint originOffset = {SkIntToScalar(this->getClip()->fOrigin.fX),
217 SkIntToScalar(this->getClip()->fOrigin.fY)};
218 SkRect clipSpaceBounds = devBounds;
219 clipSpaceBounds.offset(originOffset);
220 return this->getClip()->fClipStack->quickContains(clipSpaceBounds);
221}
222
223int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000224 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000225
bsalomon@google.com934c5702012-03-20 21:17:58 +0000226 const GeometrySrcState& geomSrc = this->getGeomSrc();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000227 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com934c5702012-03-20 21:17:58 +0000228
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000229 // we only attempt to concat the case when reserved verts are used with a client-specified index
230 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
231 // between draws.
232 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
233 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
234 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000235 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000236 // Check if there is a draw info that is compatible that uses the same VB from the pool and
237 // the same IB
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000238 if (kDraw_Cmd != strip_trace_bit(fCmds.back())) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000239 return 0;
240 }
241
242 DrawRecord* draw = &fDraws.back();
243 GeometryPoolState& poolState = fGeoPoolStateStack.back();
244 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
245
246 if (!draw->isInstanced() ||
247 draw->verticesPerInstance() != info.verticesPerInstance() ||
248 draw->indicesPerInstance() != info.indicesPerInstance() ||
249 draw->fVertexBuffer != vertexBuffer ||
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000250 draw->fIndexBuffer != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000251 return 0;
252 }
253 // info does not yet account for the offset from the start of the pool's VB while the previous
254 // draw record does.
255 int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
256 if (draw->startVertex() + draw->vertexCount() != adjustedStartVertex) {
257 return 0;
258 }
259
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000260 SkASSERT(poolState.fPoolStartVertex == draw->startVertex() + draw->vertexCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000261
262 // how many instances can be concat'ed onto draw given the size of the index buffer
263 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
264 instancesToConcat -= draw->instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000265 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000266
267 // update the amount of reserved vertex data actually referenced in draws
skia.committer@gmail.comae683922013-02-06 07:01:54 +0000268 size_t vertexBytes = instancesToConcat * info.verticesPerInstance() *
djsollenea81ced2014-08-27 13:07:34 -0700269 drawState.getVertexSize();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000270 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000271
272 draw->adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000273
274 // update last fGpuCmdMarkers to include any additional trace markers that have been added
275 if (this->getActiveTraceMarkers().count() > 0) {
276 if (cmd_has_trace_marker(fCmds.back())) {
277 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
278 } else {
279 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
280 fCmds.back() = add_trace_bit(fCmds.back());
281 }
282 }
283
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000284 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000285}
286
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000287class AutoClipReenable {
288public:
289 AutoClipReenable() : fDrawState(NULL) {}
290 ~AutoClipReenable() {
291 if (NULL != fDrawState) {
292 fDrawState->enableState(GrDrawState::kClip_StateBit);
293 }
294 }
295 void set(GrDrawState* drawState) {
296 if (drawState->isClipState()) {
297 fDrawState = drawState;
298 drawState->disableState(GrDrawState::kClip_StateBit);
299 }
300 }
301private:
302 GrDrawState* fDrawState;
303};
304
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000305void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000306
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000307 GeometryPoolState& poolState = fGeoPoolStateStack.back();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000308 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000309 AutoClipReenable acr;
310
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000311 if (drawState.isClipState() &&
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000312 NULL != info.getDevBounds() &&
313 this->quickInsideClip(*info.getDevBounds())) {
314 acr.set(this->drawState());
315 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000316
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000317 if (this->needsNewClip()) {
318 this->recordClip();
319 }
bsalomon838f62d2014-08-05 07:15:57 -0700320 this->recordStateIfNecessary();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000321
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000322 DrawRecord* draw;
323 if (info.isInstanced()) {
324 int instancesConcated = this->concatInstancedDraw(info);
325 if (info.instanceCount() > instancesConcated) {
326 draw = this->recordDraw(info);
327 draw->adjustInstanceCount(-instancesConcated);
328 } else {
329 return;
330 }
331 } else {
332 draw = this->recordDraw(info);
333 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000334
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000335 switch (this->getGeomSrc().fVertexSrc) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000336 case kBuffer_GeometrySrcType:
337 draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer;
338 break;
339 case kReserved_GeometrySrcType: // fallthrough
340 case kArray_GeometrySrcType: {
skia.committer@gmail.comae683922013-02-06 07:01:54 +0000341 size_t vertexBytes = (info.vertexCount() + info.startVertex()) *
djsollenea81ced2014-08-27 13:07:34 -0700342 drawState.getVertexSize();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000343 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000344 draw->fVertexBuffer = poolState.fPoolVertexBuffer;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000345 draw->adjustStartVertex(poolState.fPoolStartVertex);
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000346 break;
347 }
348 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000349 SkFAIL("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000350 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000351 draw->fVertexBuffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000352
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000353 if (info.isIndexed()) {
354 switch (this->getGeomSrc().fIndexSrc) {
355 case kBuffer_GeometrySrcType:
356 draw->fIndexBuffer = this->getGeomSrc().fIndexBuffer;
357 break;
358 case kReserved_GeometrySrcType: // fallthrough
359 case kArray_GeometrySrcType: {
360 size_t indexBytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000361 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, indexBytes);
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000362 draw->fIndexBuffer = poolState.fPoolIndexBuffer;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000363 draw->adjustStartIndex(poolState.fPoolStartIndex);
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000364 break;
365 }
366 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000367 SkFAIL("unknown geom src type");
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000368 }
369 draw->fIndexBuffer->ref();
370 } else {
371 draw->fIndexBuffer = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000372 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000373}
374
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000375GrInOrderDrawBuffer::StencilPath::StencilPath() {}
376GrInOrderDrawBuffer::DrawPath::DrawPath() {}
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000377GrInOrderDrawBuffer::DrawPaths::DrawPaths() {}
378GrInOrderDrawBuffer::DrawPaths::~DrawPaths() {
379 if (fTransforms) {
380 SkDELETE_ARRAY(fTransforms);
381 }
cdaltonb85a0aa2014-07-21 15:32:44 -0700382 if (fIndices) {
383 SkDELETE_ARRAY(fIndices);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000384 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000385}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000386
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000387void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, SkPath::FillType fill) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000388 if (this->needsNewClip()) {
389 this->recordClip();
390 }
391 // Only compare the subset of GrDrawState relevant to path stenciling?
bsalomon838f62d2014-08-05 07:15:57 -0700392 this->recordStateIfNecessary();
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000393 StencilPath* sp = this->recordStencilPath();
394 sp->fPath.reset(path);
395 path->ref();
396 sp->fFill = fill;
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000397}
398
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000399void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000400 SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
401 if (this->needsNewClip()) {
402 this->recordClip();
403 }
404 // TODO: Only compare the subset of GrDrawState relevant to path covering?
bsalomon838f62d2014-08-05 07:15:57 -0700405 this->recordStateIfNecessary();
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000406 DrawPath* cp = this->recordDrawPath();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000407 cp->fPath.reset(path);
408 path->ref();
409 cp->fFill = fill;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000410 if (NULL != dstCopy) {
411 cp->fDstCopy = *dstCopy;
412 }
413}
414
cdaltonb85a0aa2014-07-21 15:32:44 -0700415void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
416 const uint32_t indices[], int count,
417 const float transforms[], PathTransformType transformsType,
418 SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
419 SkASSERT(NULL != pathRange);
420 SkASSERT(NULL != indices);
421 SkASSERT(NULL != transforms);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000422
423 if (this->needsNewClip()) {
424 this->recordClip();
425 }
bsalomon838f62d2014-08-05 07:15:57 -0700426 this->recordStateIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000427 DrawPaths* dp = this->recordDrawPaths();
cdaltonb85a0aa2014-07-21 15:32:44 -0700428 dp->fPathRange.reset(SkRef(pathRange));
429 dp->fIndices = SkNEW_ARRAY(uint32_t, count); // TODO: Accomplish this without a malloc
430 memcpy(dp->fIndices, indices, sizeof(uint32_t) * count);
431 dp->fCount = count;
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000432
kkinnunenccdaa042014-08-20 01:36:23 -0700433 const int transformsLength = GrPathRendering::PathTransformSize(transformsType) * count;
cdaltonb85a0aa2014-07-21 15:32:44 -0700434 dp->fTransforms = SkNEW_ARRAY(float, transformsLength);
435 memcpy(dp->fTransforms, transforms, sizeof(float) * transformsLength);
436 dp->fTransformsType = transformsType;
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000437
438 dp->fFill = fill;
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000439
440 if (NULL != dstCopy) {
441 dp->fDstCopy = *dstCopy;
442 }
443}
444
skia.committer@gmail.com18bb41e2013-11-01 07:02:15 +0000445void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000446 bool canIgnoreRect, GrRenderTarget* renderTarget) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000447 SkIRect r;
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000448 if (NULL == renderTarget) {
449 renderTarget = this->drawState()->getRenderTarget();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000450 SkASSERT(NULL != renderTarget);
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000451 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000452 if (NULL == rect) {
453 // We could do something smart and remove previous draws and clears to
454 // the current render target. If we get that smart we have to make sure
455 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000456 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000457 rect = &r;
458 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000459 Clear* clr = this->recordClear();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000460 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000461 clr->fColor = color;
462 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000463 clr->fCanIgnoreRect = canIgnoreRect;
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000464 clr->fRenderTarget = renderTarget;
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000465 renderTarget->ref();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000466}
467
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000468void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
469 if (!this->caps()->discardRenderTargetSupport()) {
470 return;
471 }
472 if (NULL == renderTarget) {
473 renderTarget = this->drawState()->getRenderTarget();
474 SkASSERT(NULL != renderTarget);
475 }
476 Clear* clr = this->recordClear();
477 clr->fColor = GrColor_ILLEGAL;
478 clr->fRenderTarget = renderTarget;
479 renderTarget->ref();
480}
481
reed@google.comac10a2d2010-12-22 21:39:39 +0000482void GrInOrderDrawBuffer::reset() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000483 SkASSERT(1 == fGeoPoolStateStack.count());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000484 this->resetVertexSource();
485 this->resetIndexSource();
bsalomonbce3d6d2014-07-02 07:54:42 -0700486
487 DrawAllocator::Iter drawIter(&fDraws);
488 while (drawIter.next()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000489 // we always have a VB, but not always an IB
bsalomonbce3d6d2014-07-02 07:54:42 -0700490 SkASSERT(NULL != drawIter->fVertexBuffer);
491 drawIter->fVertexBuffer->unref();
492 SkSafeUnref(drawIter->fIndexBuffer);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000493 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000494 fCmds.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000495 fDraws.reset();
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000496 fStencilPaths.reset();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000497 fDrawPath.reset();
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000498 fDrawPaths.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000499 fStates.reset();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000500 fClears.reset();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000501 fVertexPool.reset();
502 fIndexPool.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000503 fClips.reset();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000504 fCopySurfaces.reset();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000505 fGpuCmdMarkers.reset();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000506 fClipSet = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000507}
508
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000509void GrInOrderDrawBuffer::flush() {
510 if (fFlushing) {
511 return;
512 }
513
jvanverth8e80d172014-06-19 12:01:10 -0700514 this->getContext()->getFontCache()->updateTextures();
515
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000516 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
517 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000518
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000519 int numCmds = fCmds.count();
bsalomon@google.com358e4272013-01-10 14:40:28 +0000520 if (0 == numCmds) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000521 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000522 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000523
524 GrAutoTRestore<bool> flushRestore(&fFlushing);
525 fFlushing = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000526
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000527 fVertexPool.unmap();
528 fIndexPool.unmap();
reed@google.comac10a2d2010-12-22 21:39:39 +0000529
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000530 GrDrawTarget::AutoClipRestore acr(fDstGpu);
531 AutoGeometryAndStatePush agasp(fDstGpu, kPreserve_ASRInit);
bsalomon@google.comca432082013-01-23 19:53:46 +0000532
bsalomona70353e2014-07-07 08:15:07 -0700533 GrDrawState* prevDrawState = SkRef(fDstGpu->drawState());
reed@google.comac10a2d2010-12-22 21:39:39 +0000534
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000535 GrClipData clipData;
536
bsalomonbce3d6d2014-07-02 07:54:42 -0700537 StateAllocator::Iter stateIter(&fStates);
538 ClipAllocator::Iter clipIter(&fClips);
bsalomonbce3d6d2014-07-02 07:54:42 -0700539 ClearAllocator::Iter clearIter(&fClears);
540 DrawAllocator::Iter drawIter(&fDraws);
541 StencilPathAllocator::Iter stencilPathIter(&fStencilPaths);
542 DrawPathAllocator::Iter drawPathIter(&fDrawPath);
543 DrawPathsAllocator::Iter drawPathsIter(&fDrawPaths);
544 CopySurfaceAllocator::Iter copySurfaceIter(&fCopySurfaces);
545
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000546 int currCmdMarker = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000547
egdaniel3eee3832014-06-18 13:09:11 -0700548 fDstGpu->saveActiveTraceMarkers();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000549 for (int c = 0; c < numCmds; ++c) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000550 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700551 SkString traceString;
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000552 if (cmd_has_trace_marker(fCmds[c])) {
egdanield78a1682014-07-09 10:41:26 -0700553 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000554 newMarker.fMarker = traceString.c_str();
555 fDstGpu->addGpuTraceMarker(&newMarker);
556 ++currCmdMarker;
557 }
558 switch (strip_trace_bit(fCmds[c])) {
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000559 case kDraw_Cmd: {
bsalomona70353e2014-07-07 08:15:07 -0700560 SkASSERT(fDstGpu->drawState() != prevDrawState);
bsalomonbce3d6d2014-07-02 07:54:42 -0700561 SkAssertResult(drawIter.next());
562 fDstGpu->setVertexSourceToBuffer(drawIter->fVertexBuffer);
563 if (drawIter->isIndexed()) {
564 fDstGpu->setIndexSourceToBuffer(drawIter->fIndexBuffer);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000565 }
bsalomonbce3d6d2014-07-02 07:54:42 -0700566 fDstGpu->executeDraw(*drawIter);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000567 break;
568 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000569 case kStencilPath_Cmd: {
bsalomona70353e2014-07-07 08:15:07 -0700570 SkASSERT(fDstGpu->drawState() != prevDrawState);
bsalomonbce3d6d2014-07-02 07:54:42 -0700571 SkAssertResult(stencilPathIter.next());
572 fDstGpu->stencilPath(stencilPathIter->fPath.get(), stencilPathIter->fFill);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000573 break;
574 }
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000575 case kDrawPath_Cmd: {
bsalomona70353e2014-07-07 08:15:07 -0700576 SkASSERT(fDstGpu->drawState() != prevDrawState);
bsalomonbce3d6d2014-07-02 07:54:42 -0700577 SkAssertResult(drawPathIter.next());
578 fDstGpu->executeDrawPath(drawPathIter->fPath.get(), drawPathIter->fFill,
579 NULL != drawPathIter->fDstCopy.texture() ?
580 &drawPathIter->fDstCopy :
581 NULL);
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000582 break;
583 }
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000584 case kDrawPaths_Cmd: {
bsalomona70353e2014-07-07 08:15:07 -0700585 SkASSERT(fDstGpu->drawState() != prevDrawState);
bsalomonbce3d6d2014-07-02 07:54:42 -0700586 SkAssertResult(drawPathsIter.next());
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000587 const GrDeviceCoordTexture* dstCopy =
bsalomonbce3d6d2014-07-02 07:54:42 -0700588 NULL !=drawPathsIter->fDstCopy.texture() ? &drawPathsIter->fDstCopy : NULL;
cdaltonb85a0aa2014-07-21 15:32:44 -0700589 fDstGpu->executeDrawPaths(drawPathsIter->fPathRange.get(),
590 drawPathsIter->fIndices,
591 drawPathsIter->fCount,
592 drawPathsIter->fTransforms,
593 drawPathsIter->fTransformsType,
594 drawPathsIter->fFill,
595 dstCopy);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000596 break;
597 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000598 case kSetState_Cmd:
bsalomonbce3d6d2014-07-02 07:54:42 -0700599 SkAssertResult(stateIter.next());
bsalomona70353e2014-07-07 08:15:07 -0700600 fDstGpu->setDrawState(stateIter.get());
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000601 break;
602 case kSetClip_Cmd:
bsalomonbce3d6d2014-07-02 07:54:42 -0700603 SkAssertResult(clipIter.next());
bsalomonf0480b12014-07-02 12:11:24 -0700604 clipData.fClipStack = &clipIter->fStack;
605 clipData.fOrigin = clipIter->fOrigin;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000606 fDstGpu->setClip(&clipData);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000607 break;
608 case kClear_Cmd:
bsalomonbce3d6d2014-07-02 07:54:42 -0700609 SkAssertResult(clearIter.next());
610 if (GrColor_ILLEGAL == clearIter->fColor) {
611 fDstGpu->discard(clearIter->fRenderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000612 } else {
bsalomonbce3d6d2014-07-02 07:54:42 -0700613 fDstGpu->clear(&clearIter->fRect,
614 clearIter->fColor,
615 clearIter->fCanIgnoreRect,
616 clearIter->fRenderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000617 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000618 break;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000619 case kCopySurface_Cmd:
bsalomonbce3d6d2014-07-02 07:54:42 -0700620 SkAssertResult(copySurfaceIter.next());
621 fDstGpu->copySurface(copySurfaceIter->fDst.get(),
622 copySurfaceIter->fSrc.get(),
623 copySurfaceIter->fSrcRect,
624 copySurfaceIter->fDstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000625 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000626 }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000627 if (cmd_has_trace_marker(fCmds[c])) {
628 fDstGpu->removeGpuTraceMarker(&newMarker);
629 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000630 }
egdaniel3eee3832014-06-18 13:09:11 -0700631 fDstGpu->restoreActiveTraceMarkers();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000632 // we should have consumed all the states, clips, etc.
bsalomonbce3d6d2014-07-02 07:54:42 -0700633 SkASSERT(!stateIter.next());
634 SkASSERT(!clipIter.next());
bsalomonbce3d6d2014-07-02 07:54:42 -0700635 SkASSERT(!clearIter.next());
636 SkASSERT(!drawIter.next());
637 SkASSERT(!copySurfaceIter.next());
638 SkASSERT(!stencilPathIter.next());
639 SkASSERT(!drawPathIter.next());
640 SkASSERT(!drawPathsIter.next());
641
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000642 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000643
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000644 fDstGpu->setDrawState(prevDrawState);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000645 prevDrawState->unref();
bsalomon@google.com55e4a202013-01-11 13:54:21 +0000646 this->reset();
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000647 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000648}
649
bsalomon@google.com116ad842013-04-09 15:38:19 +0000650bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
651 GrSurface* src,
652 const SkIRect& srcRect,
653 const SkIPoint& dstPoint) {
654 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
655 CopySurface* cs = this->recordCopySurface();
656 cs->fDst.reset(SkRef(dst));
657 cs->fSrc.reset(SkRef(src));
658 cs->fSrcRect = srcRect;
659 cs->fDstPoint = dstPoint;
660 return true;
661 } else {
662 return false;
663 }
664}
665
666bool GrInOrderDrawBuffer::onCanCopySurface(GrSurface* dst,
667 GrSurface* src,
668 const SkIRect& srcRect,
669 const SkIPoint& dstPoint) {
670 return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint);
671}
672
bsalomon@google.comeb851172013-04-15 13:51:00 +0000673void GrInOrderDrawBuffer::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) {
674 fDstGpu->initCopySurfaceDstDesc(src, desc);
675}
676
robertphillips@google.com9528bdb2013-09-18 22:33:57 +0000677void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
678 int indexCount) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000679 // We use geometryHints() to know whether to flush the draw buffer. We
680 // can't flush if we are inside an unbalanced pushGeometrySource.
681 // Moreover, flushing blows away vertex and index data that was
682 // previously reserved. So if the vertex or index data is pulled from
683 // reserved space and won't be released by this request then we can't
684 // flush.
685 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
bsalomon@google.com97805382012-03-13 14:32:07 +0000686
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000687 bool unreleasedVertexSpace =
688 !vertexCount &&
689 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000690
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000691 bool unreleasedIndexSpace =
692 !indexCount &&
693 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
bsalomon@google.com97805382012-03-13 14:32:07 +0000694
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000695 // we don't want to finalize any reserved geom on the target since
696 // we don't know that the client has finished writing to it.
697 bool targetHasReservedGeom = fDstGpu->hasReservedVerticesOrIndices();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000698
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000699 int vcount = vertexCount;
700 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000701
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000702 if (!insideGeoPush &&
703 !unreleasedVertexSpace &&
704 !unreleasedIndexSpace &&
705 !targetHasReservedGeom &&
706 this->geometryHints(&vcount, &icount)) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000707
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000708 this->flush();
bsalomon@google.com97805382012-03-13 14:32:07 +0000709 }
710}
711
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000712bool GrInOrderDrawBuffer::geometryHints(int* vertexCount,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000713 int* indexCount) const {
714 // we will recommend a flush if the data could fit in a single
715 // preallocated buffer but none are left and it can't fit
716 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000717 bool flush = false;
718 if (NULL != indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000719 int32_t currIndices = fIndexPool.currentBufferIndices();
720 if (*indexCount > currIndices &&
721 (!fIndexPool.preallocatedBuffersRemaining() &&
722 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
723
724 flush = true;
725 }
726 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000727 }
728 if (NULL != vertexCount) {
djsollenea81ced2014-08-27 13:07:34 -0700729 size_t vertexSize = this->getDrawState().getVertexSize();
730 int32_t currVertices = fVertexPool.currentBufferVertices(vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000731 if (*vertexCount > currVertices &&
732 (!fVertexPool.preallocatedBuffersRemaining() &&
djsollenea81ced2014-08-27 13:07:34 -0700733 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexSize))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000734
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000735 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000736 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000737 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000738 }
739 return flush;
740}
741
jvanverth@google.coma6338982013-01-31 21:34:25 +0000742bool GrInOrderDrawBuffer::onReserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000743 int vertexCount,
744 void** vertices) {
745 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000746 SkASSERT(vertexCount > 0);
747 SkASSERT(NULL != vertices);
748 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000749
jvanverth@google.coma6338982013-01-31 21:34:25 +0000750 *vertices = fVertexPool.makeSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000751 vertexCount,
752 &poolState.fPoolVertexBuffer,
753 &poolState.fPoolStartVertex);
754 return NULL != *vertices;
755}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000756
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000757bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
758 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000759 SkASSERT(indexCount > 0);
760 SkASSERT(NULL != indices);
761 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000762
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000763 *indices = fIndexPool.makeSpace(indexCount,
764 &poolState.fPoolIndexBuffer,
765 &poolState.fPoolStartIndex);
766 return NULL != *indices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000767}
768
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000769void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
770 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000771 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000772
773 // If we get a release vertex space call then our current source should either be reserved
774 // or array (which we copied into reserved space).
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000775 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc ||
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000776 kArray_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000777
778 // When the caller reserved vertex buffer space we gave it back a pointer
779 // provided by the vertex buffer pool. At each draw we tracked the largest
780 // offset into the pool's pointer that was referenced. Now we return to the
781 // pool any portion at the tail of the allocation that no draw referenced.
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000782 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000783 fVertexPool.putBack(reservedVertexBytes -
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000784 poolState.fUsedPoolVertexBytes);
785 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000786 poolState.fPoolVertexBuffer = NULL;
787 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000788}
789
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000790void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
791 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000792 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000793
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000794 // If we get a release index space call then our current source should either be reserved
795 // or array (which we copied into reserved space).
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000796 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc ||
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000797 kArray_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000798
799 // Similar to releaseReservedVertexSpace we return any unused portion at
800 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000801 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
802 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
803 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000804 poolState.fPoolIndexBuffer = NULL;
805 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000806}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000807
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000808void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray,
809 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000810
811 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000812 SkASSERT(0 == poolState.fUsedPoolVertexBytes);
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000813#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000814 bool success =
815#endif
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000816 fVertexPool.appendVertices(this->getVertexSize(),
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000817 vertexCount,
818 vertexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000819 &poolState.fPoolVertexBuffer,
820 &poolState.fPoolStartVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000821 GR_DEBUGASSERT(success);
822}
823
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000824void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
825 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000826 GeometryPoolState& poolState = fGeoPoolStateStack.back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000827 SkASSERT(0 == poolState.fUsedPoolIndexBytes);
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000828#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000829 bool success =
830#endif
831 fIndexPool.appendIndices(indexCount,
832 indexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000833 &poolState.fPoolIndexBuffer,
834 &poolState.fPoolStartIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000835 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000836}
837
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000838void GrInOrderDrawBuffer::releaseVertexArray() {
839 // When the client provides an array as the vertex source we handled it
840 // by copying their array into reserved space.
841 this->GrInOrderDrawBuffer::releaseReservedVertexSpace();
842}
843
844void GrInOrderDrawBuffer::releaseIndexArray() {
845 // When the client provides an array as the index source we handled it
846 // by copying their array into reserved space.
847 this->GrInOrderDrawBuffer::releaseReservedIndexSpace();
848}
849
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000850void GrInOrderDrawBuffer::geometrySourceWillPush() {
851 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
852 poolState.fUsedPoolVertexBytes = 0;
853 poolState.fUsedPoolIndexBytes = 0;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000854#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000855 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
856 poolState.fPoolStartVertex = ~0;
857 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
858 poolState.fPoolStartIndex = ~0;
859#endif
860}
861
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000862void GrInOrderDrawBuffer::geometrySourceWillPop(
863 const GeometrySrcState& restoredState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000864 SkASSERT(fGeoPoolStateStack.count() > 1);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000865 fGeoPoolStateStack.pop_back();
866 GeometryPoolState& poolState = fGeoPoolStateStack.back();
867 // we have to assume that any slack we had in our vertex/index data
868 // is now unreleasable because data may have been appended later in the
869 // pool.
870 if (kReserved_GeometrySrcType == restoredState.fVertexSrc ||
871 kArray_GeometrySrcType == restoredState.fVertexSrc) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000872 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredState.fVertexCount;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000873 }
874 if (kReserved_GeometrySrcType == restoredState.fIndexSrc ||
875 kArray_GeometrySrcType == restoredState.fIndexSrc) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000876 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000877 restoredState.fIndexCount;
878 }
879}
880
bsalomon838f62d2014-08-05 07:15:57 -0700881void GrInOrderDrawBuffer::recordStateIfNecessary() {
882 if (fStates.empty()) {
883 fStates.push_back() = this->getDrawState();
884 this->addToCmdBuffer(kSetState_Cmd);
885 return;
886 }
887 const GrDrawState& curr = this->getDrawState();
888 GrDrawState& prev = fStates.back();
bsalomon62c447d2014-08-08 08:08:50 -0700889 switch (GrDrawState::CombineIfPossible(prev, curr, *this->caps())) {
bsalomon838f62d2014-08-05 07:15:57 -0700890 case GrDrawState::kIncompatible_CombinedState:
891 fStates.push_back() = this->getDrawState();
892 this->addToCmdBuffer(kSetState_Cmd);
893 break;
894 case GrDrawState::kA_CombinedState:
895 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA.
896 break;
897 case GrDrawState::kB_CombinedState:
898 prev = curr;
899 break;
900 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000901}
902
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000903bool GrInOrderDrawBuffer::needsNewClip() const {
bsalomon@google.com358e4272013-01-10 14:40:28 +0000904 if (this->getDrawState().isClipState()) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000905 if (fClipSet &&
bsalomon@google.com358e4272013-01-10 14:40:28 +0000906 (fClips.empty() ||
bsalomonf0480b12014-07-02 12:11:24 -0700907 fClips.back().fStack != *this->getClip()->fClipStack ||
908 fClips.back().fOrigin != this->getClip()->fOrigin)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000909 return true;
910 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000911 }
912 return false;
913}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000914
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000915void GrInOrderDrawBuffer::addToCmdBuffer(uint8_t cmd) {
916 SkASSERT(!cmd_has_trace_marker(cmd));
917 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
918 if (activeTraceMarkers.count() > 0) {
919 fCmds.push_back(add_trace_bit(cmd));
920 fGpuCmdMarkers.push_back(activeTraceMarkers);
921 } else {
922 fCmds.push_back(cmd);
923 }
924}
925
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000926void GrInOrderDrawBuffer::recordClip() {
bsalomonf0480b12014-07-02 12:11:24 -0700927 fClips.push_back().fStack = *this->getClip()->fClipStack;
928 fClips.back().fOrigin = this->getClip()->fOrigin;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000929 fClipSet = false;
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000930 this->addToCmdBuffer(kSetClip_Cmd);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000931}
932
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000933GrInOrderDrawBuffer::DrawRecord* GrInOrderDrawBuffer::recordDraw(const DrawInfo& info) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000934 this->addToCmdBuffer(kDraw_Cmd);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000935 return &fDraws.push_back(info);
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000936}
937
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000938GrInOrderDrawBuffer::StencilPath* GrInOrderDrawBuffer::recordStencilPath() {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000939 this->addToCmdBuffer(kStencilPath_Cmd);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000940 return &fStencilPaths.push_back();
941}
942
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000943GrInOrderDrawBuffer::DrawPath* GrInOrderDrawBuffer::recordDrawPath() {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000944 this->addToCmdBuffer(kDrawPath_Cmd);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000945 return &fDrawPath.push_back();
946}
947
948GrInOrderDrawBuffer::DrawPaths* GrInOrderDrawBuffer::recordDrawPaths() {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000949 this->addToCmdBuffer(kDrawPaths_Cmd);
commit-bot@chromium.org32184d82013-10-09 15:14:18 +0000950 return &fDrawPaths.push_back();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000951}
952
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000953GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear() {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000954 this->addToCmdBuffer(kClear_Cmd);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000955 return &fClears.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000956}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000957
bsalomon@google.com116ad842013-04-09 15:38:19 +0000958GrInOrderDrawBuffer::CopySurface* GrInOrderDrawBuffer::recordCopySurface() {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000959 this->addToCmdBuffer(kCopySurface_Cmd);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000960 return &fCopySurfaces.push_back();
961}
962
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000963void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) {
964 INHERITED::clipWillBeSet(newClipData);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000965 fClipSet = true;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000966 fClipProxyState = kUnknown_ClipProxyState;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000967}