blob: b9e84c0a999fed09ae8304e60376b22b1d2ee332 [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
mtklein07894c42014-10-13 14:00:42 -0700233 if (kDraw_Cmd != strip_trace_bit(fCmds.back())) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000234 return 0;
235 }
236
mtklein07894c42014-10-13 14:00:42 -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
mtklein07894c42014-10-13 14:00:42 -0700241 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();
mtklein07894c42014-10-13 14:00:42 -0700251 if (draw->startVertex() + draw->vertexCount() != adjustedStartVertex) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000252 return 0;
253 }
254
mtklein07894c42014-10-13 14:00:42 -0700255 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();
mtklein07894c42014-10-13 14:00:42 -0700259 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
mtklein07894c42014-10-13 14:00:42 -0700267 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) {
mtklein07894c42014-10-13 14:00:42 -0700271 if (cmd_has_trace_marker(fCmds.back())) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000272 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
273 } else {
274 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
mtklein07894c42014-10-13 14:00:42 -0700275 fCmds.back() = add_trace_bit(fCmds.back());
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000276 }
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
mtklein07894c42014-10-13 14:00:42 -0700312 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) {
mtklein07894c42014-10-13 14:00:42 -0700337 draw = this->recordDraw(info, vb, ib);
338 draw->adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000339 } else {
340 return;
341 }
342 } else {
mtklein07894c42014-10-13 14:00:42 -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);
mtklein07894c42014-10-13 14:00:42 -0700351 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);
mtklein07894c42014-10-13 14:00:42 -0700357 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) {
mtklein07894c42014-10-13 14:00:42 -0700362 if (this->needsNewClip()) {
363 this->recordClip();
364 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000365 // Only compare the subset of GrDrawState relevant to path stenciling?
bsalomon838f62d2014-08-05 07:15:57 -0700366 this->recordStateIfNecessary();
mtklein07894c42014-10-13 14:00:42 -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) {
mtklein07894c42014-10-13 14:00:42 -0700373 if (this->needsNewClip()) {
374 this->recordClip();
375 }
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000376 // TODO: Only compare the subset of GrDrawState relevant to path covering?
bsalomon838f62d2014-08-05 07:15:57 -0700377 this->recordStateIfNecessary();
mtklein07894c42014-10-13 14:00:42 -0700378 DrawPath* cp = this->recordDrawPath(path);
379 cp->fFill = fill;
bsalomon49f085d2014-09-05 13:34:00 -0700380 if (dstCopy) {
mtklein07894c42014-10-13 14:00:42 -0700381 cp->fDstCopy = *dstCopy;
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000382 }
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
mtklein07894c42014-10-13 14:00:42 -0700393 if (this->needsNewClip()) {
394 this->recordClip();
395 }
bsalomon838f62d2014-08-05 07:15:57 -0700396 this->recordStateIfNecessary();
mtklein07894c42014-10-13 14:00:42 -0700397 DrawPaths* dp = this->recordDrawPaths(pathRange);
398 dp->fIndices = SkNEW_ARRAY(uint32_t, count); // TODO: Accomplish this without a malloc
399 memcpy(dp->fIndices, indices, sizeof(uint32_t) * count);
cdaltonb85a0aa2014-07-21 15:32:44 -0700400 dp->fCount = count;
mtklein07894c42014-10-13 14:00:42 -0700401
402 const int transformsLength = GrPathRendering::PathTransformSize(transformsType) * count;
403 dp->fTransforms = SkNEW_ARRAY(float, transformsLength);
404 memcpy(dp->fTransforms, transforms, sizeof(float) * transformsLength);
cdaltonb85a0aa2014-07-21 15:32:44 -0700405 dp->fTransformsType = transformsType;
mtklein07894c42014-10-13 14:00:42 -0700406
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000407 dp->fFill = fill;
mtklein07894c42014-10-13 14:00:42 -0700408
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 }
mtklein07894c42014-10-13 14:00:42 -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 }
mtklein07894c42014-10-13 14:00:42 -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();
mtklein07894c42014-10-13 14:00:42 -0700451
452 fCmds.reset();
453 fDraws.reset();
454 fStencilPaths.reset();
455 fDrawPath.reset();
456 fDrawPaths.reset();
457 fStates.reset();
458 fClears.reset();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000459 fVertexPool.reset();
460 fIndexPool.reset();
mtklein07894c42014-10-13 14:00:42 -0700461 fClips.reset();
462 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
mtklein07894c42014-10-13 14:00:42 -0700477 int numCmds = fCmds.count();
478 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
mtklein07894c42014-10-13 14:00:42 -0700493 GrClipData clipData;
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000494
mtklein07894c42014-10-13 14:00:42 -0700495 StateAllocator::Iter stateIter(&fStates);
496 ClipAllocator::Iter clipIter(&fClips);
497 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
504 int currCmdMarker = 0;
505
egdaniel3eee3832014-06-18 13:09:11 -0700506 fDstGpu->saveActiveTraceMarkers();
mtklein07894c42014-10-13 14:00:42 -0700507 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;
mtklein07894c42014-10-13 14:00:42 -0700510 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 }
mtklein07894c42014-10-13 14:00:42 -0700516 switch (strip_trace_bit(fCmds[c])) {
517 case kDraw_Cmd: {
518 SkASSERT(fDstGpu->drawState() != prevDrawState);
519 SkAssertResult(drawIter.next());
520 fDstGpu->setVertexSourceToBuffer(drawIter->vertexBuffer());
521 if (drawIter->isIndexed()) {
522 fDstGpu->setIndexSourceToBuffer(drawIter->indexBuffer());
523 }
524 fDstGpu->executeDraw(*drawIter);
525 break;
526 }
527 case kStencilPath_Cmd: {
528 SkASSERT(fDstGpu->drawState() != prevDrawState);
529 SkAssertResult(stencilPathIter.next());
530 fDstGpu->stencilPath(stencilPathIter->path(), stencilPathIter->fFill);
531 break;
532 }
533 case kDrawPath_Cmd: {
534 SkASSERT(fDstGpu->drawState() != prevDrawState);
535 SkAssertResult(drawPathIter.next());
536 fDstGpu->executeDrawPath(drawPathIter->path(), drawPathIter->fFill,
537 drawPathIter->fDstCopy.texture() ?
538 &drawPathIter->fDstCopy :
539 NULL);
540 break;
541 }
542 case kDrawPaths_Cmd: {
543 SkASSERT(fDstGpu->drawState() != prevDrawState);
544 SkAssertResult(drawPathsIter.next());
545 const GrDeviceCoordTexture* dstCopy =
546 drawPathsIter->fDstCopy.texture() ? &drawPathsIter->fDstCopy : NULL;
547 fDstGpu->executeDrawPaths(drawPathsIter->pathRange(),
548 drawPathsIter->fIndices,
549 drawPathsIter->fCount,
550 drawPathsIter->fTransforms,
551 drawPathsIter->fTransformsType,
552 drawPathsIter->fFill,
553 dstCopy);
554 break;
555 }
556 case kSetState_Cmd:
557 SkAssertResult(stateIter.next());
558 fDstGpu->setDrawState(stateIter.get());
559 break;
560 case kSetClip_Cmd:
561 SkAssertResult(clipIter.next());
562 clipData.fClipStack = &clipIter->fStack;
563 clipData.fOrigin = clipIter->fOrigin;
564 fDstGpu->setClip(&clipData);
565 break;
566 case kClear_Cmd:
567 SkAssertResult(clearIter.next());
568 if (GrColor_ILLEGAL == clearIter->fColor) {
569 fDstGpu->discard(clearIter->renderTarget());
570 } else {
571 fDstGpu->clear(&clearIter->fRect,
572 clearIter->fColor,
573 clearIter->fCanIgnoreRect,
574 clearIter->renderTarget());
575 }
576 break;
577 case kCopySurface_Cmd:
578 SkAssertResult(copySurfaceIter.next());
579 fDstGpu->copySurface(copySurfaceIter->dst(),
580 copySurfaceIter->src(),
581 copySurfaceIter->fSrcRect,
582 copySurfaceIter->fDstPoint);
583 break;
584 }
585 if (cmd_has_trace_marker(fCmds[c])) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000586 fDstGpu->removeGpuTraceMarker(&newMarker);
587 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000588 }
cdalton47c844a2014-10-13 12:43:10 -0700589 fDstGpu->restoreActiveTraceMarkers();
mtklein07894c42014-10-13 14:00:42 -0700590 // we should have consumed all the states, clips, etc.
591 SkASSERT(!stateIter.next());
592 SkASSERT(!clipIter.next());
593 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)) {
mtklein07894c42014-10-13 14:00:42 -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() {
mtklein07894c42014-10-13 14:00:42 -0700835 if (fStates.empty()) {
836 this->convertDrawStateToPendingExec(&fStates.push_back(this->getDrawState()));
837 this->addToCmdBuffer(kSetState_Cmd);
bsalomon838f62d2014-08-05 07:15:57 -0700838 return;
839 }
840 const GrDrawState& curr = this->getDrawState();
mtklein07894c42014-10-13 14:00:42 -0700841 GrDrawState& prev = fStates.back();
842 switch (GrDrawState::CombineIfPossible(prev, curr, *this->caps())) {
bsalomon838f62d2014-08-05 07:15:57 -0700843 case GrDrawState::kIncompatible_CombinedState:
mtklein07894c42014-10-13 14:00:42 -0700844 this->convertDrawStateToPendingExec(&fStates.push_back(curr));
845 this->addToCmdBuffer(kSetState_Cmd);
bsalomon838f62d2014-08-05 07:15:57 -0700846 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.
mtklein07894c42014-10-13 14:00:42 -0700852 // 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
mtklein07894c42014-10-13 14:00:42 -0700860bool GrInOrderDrawBuffer::needsNewClip() const {
861 if (this->getDrawState().isClipState()) {
862 if (fClipSet &&
863 (fClips.empty() ||
864 fClips.back().fStack != *this->getClip()->fClipStack ||
865 fClips.back().fOrigin != this->getClip()->fOrigin)) {
866 return true;
867 }
868 }
869 return false;
870}
871
872void 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);
reed@google.comac10a2d2010-12-22 21:39:39 +0000880 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000881}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000882
mtklein07894c42014-10-13 14:00:42 -0700883void GrInOrderDrawBuffer::recordClip() {
884 fClips.push_back().fStack = *this->getClip()->fClipStack;
885 fClips.back().fOrigin = this->getClip()->fOrigin;
886 fClipSet = false;
887 this->addToCmdBuffer(kSetClip_Cmd);
888}
889
890GrInOrderDrawBuffer::Draw* GrInOrderDrawBuffer::recordDraw(const DrawInfo& info,
891 const GrVertexBuffer* vb,
892 const GrIndexBuffer* ib) {
893 this->addToCmdBuffer(kDraw_Cmd);
894 return GrNEW_APPEND_TO_ALLOCATOR(&fDraws, Draw, (info, vb, ib));
895}
896
897GrInOrderDrawBuffer::StencilPath* GrInOrderDrawBuffer::recordStencilPath(const GrPath* path) {
898 this->addToCmdBuffer(kStencilPath_Cmd);
899 return GrNEW_APPEND_TO_ALLOCATOR(&fStencilPaths, StencilPath, (path));
900}
901
902GrInOrderDrawBuffer::DrawPath* GrInOrderDrawBuffer::recordDrawPath(const GrPath* path) {
903 this->addToCmdBuffer(kDrawPath_Cmd);
904 return GrNEW_APPEND_TO_ALLOCATOR(&fDrawPath, DrawPath, (path));
905}
906
907GrInOrderDrawBuffer::DrawPaths* GrInOrderDrawBuffer::recordDrawPaths(const GrPathRange* pathRange) {
908 this->addToCmdBuffer(kDrawPaths_Cmd);
909 return GrNEW_APPEND_TO_ALLOCATOR(&fDrawPaths, DrawPaths, (pathRange));
910}
911
912GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear(GrRenderTarget* rt) {
913 this->addToCmdBuffer(kClear_Cmd);
914 return GrNEW_APPEND_TO_ALLOCATOR(&fClears, Clear, (rt));
915}
916
917GrInOrderDrawBuffer::CopySurface* GrInOrderDrawBuffer::recordCopySurface(GrSurface* dst,
918 GrSurface* src) {
919 this->addToCmdBuffer(kCopySurface_Cmd);
920 return GrNEW_APPEND_TO_ALLOCATOR(&fCopySurfaces, CopySurface, (dst, src));
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +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}