blob: 1840ca32d7f6cf235dd13545ef4bb933650d63f4 [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
joshualitt4d8da812015-01-28 12:53:54 -080010#include "GrBufferAllocPool.h"
joshualitt5478d422014-11-14 16:00:38 -080011#include "GrDefaultGeoProcFactory.h"
bsalomon@google.comc26d94f2013-03-25 18:19:00 +000012#include "GrDrawTargetCaps.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"
jvanverth787cdf92014-12-04 10:46:50 -080015#include "GrFontCache.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016#include "GrTexture.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000018GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
bsalomon@google.com471d4712011-08-23 15:45:25 +000019 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000020 GrIndexBufferAllocPool* indexPool)
bsalomon371bcbc2014-12-01 08:19:34 -080021 : INHERITED(gpu, vertexPool, indexPool)
cdalton6819df32014-10-15 13:43:48 -070022 , fCmdBuffer(kCmdBufferInitialSizeInBytes)
bsalomon932f8662014-11-24 06:47:48 -080023 , fPrevState(NULL)
joshualitt4d8da812015-01-28 12:53:54 -080024 , fDrawID(0)
25 , fBatchTarget(gpu, vertexPool, indexPool)
26 , fDrawBatch(NULL) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000027
bsalomon49f085d2014-09-05 13:34:00 -070028 SkASSERT(vertexPool);
29 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000030
cdalton3fc6a2f2014-11-13 11:54:20 -080031 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
32 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
reed@google.comac10a2d2010-12-22 21:39:39 +000033}
34
35GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000036 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000037}
38
bsalomon@google.com934c5702012-03-20 21:17:58 +000039////////////////////////////////////////////////////////////////////////////////
40
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000041namespace {
42void get_vertex_bounds(const void* vertices,
43 size_t vertexSize,
44 int vertexCount,
45 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000046 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000047 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000048 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000049 bounds->fLeft = bounds->fRight = point->fX;
50 bounds->fTop = bounds->fBottom = point->fY;
51 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000052 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000053 bounds->growToInclude(point->fX, point->fY);
54 }
55}
bsalomon@google.com934c5702012-03-20 21:17:58 +000056}
57
bsalomon62c447d2014-08-08 08:08:50 -070058/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
59 have explicit local coords and sometimes not. We *could* always provide explicit local coords
60 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
61 haven't seen a use case which frequently switches between local rect and no local rect draws.
62
63 The color param is used to determine whether the opaque hint can be set on the draw state.
64 The caller must populate the vertex colors itself.
65
66 The vertex attrib order is always pos, color, [local coords].
67 */
joshualitt8fc6c2d2014-12-22 15:27:05 -080068static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords,
69 GrColor color,
70 const SkMatrix* localMatrix) {
joshualitt5478d422014-11-14 16:00:38 -080071 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
72 GrDefaultGeoProcFactory::kColor_GPType;
joshualitt8fc6c2d2014-12-22 15:27:05 -080073 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
74 if (localMatrix) {
joshualitt8059eb92014-12-29 15:10:07 -080075 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *localMatrix,
76 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080077 } else {
joshualitt8059eb92014-12-29 15:10:07 -080078 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMatrix::I(),
79 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080080 }
bsalomon62c447d2014-08-08 08:08:50 -070081}
robertphillips@google.com42903302013-04-20 12:26:07 +000082
cdalton3fc6a2f2014-11-13 11:54:20 -080083static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
84 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
85 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
86 if (isWinding) {
87 // Double check that it is in fact winding.
88 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
89 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
90 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
91 SkASSERT(!pathStencilSettings.isTwoSided());
92 }
93 return isWinding;
94}
95
96template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
97 // Assume the next time this buffer fills up it will use approximately the same amount
98 // of space as last time. Only resize if we're using less than a third of the
99 // allocated space, and leave enough for 50% growth over last time.
100 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
101 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
102 buffer->reset();
103 buffer->setReserve(reserve);
104 } else {
105 buffer->rewind();
106 }
107}
108
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
egdaniel8dd688b2015-01-22 10:16:09 -0800120void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -0800121 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800122 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800123 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000124 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000125 const SkMatrix* localMatrix) {
egdaniel8dd688b2015-01-22 10:16:09 -0800126 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000127
joshualittd27f73e2014-12-29 07:43:36 -0800128 // Go to device coords to allow batching across matrix changes
joshualittd27f73e2014-12-29 07:43:36 -0800129 SkMatrix invert = SkMatrix::I();
130
131 // if we have a local rect, then we apply the localMatrix directly to the localRect to generate
132 // vertex local coords
joshualitt8fc6c2d2014-12-22 15:27:05 -0800133 bool hasExplicitLocalCoords = SkToBool(localRect);
joshualittd27f73e2014-12-29 07:43:36 -0800134 if (!hasExplicitLocalCoords) {
joshualitt8059eb92014-12-29 15:10:07 -0800135 if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
joshualittd27f73e2014-12-29 07:43:36 -0800136 SkDebugf("Could not invert\n");
137 return;
138 }
139
140 if (localMatrix) {
141 invert.preConcat(*localMatrix);
142 }
143 }
144
145 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCoords,
146 color,
147 &invert));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000148
joshualitt56995b52014-12-11 15:44:02 -0800149 size_t vstride = gp->getVertexStride();
joshualitt2dd1ae02014-12-03 06:24:10 -0800150 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
151 0));
152 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000153 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700154 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000155 return;
156 }
157
joshualitt8059eb92014-12-29 15:10:07 -0800158 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
159 viewMatrix.mapPointsWithStride(geo.positions(), vstride, 4);
160
jvanverth@google.com39768252013-02-14 15:25:44 +0000161 // 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 +0000162 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
joshualitt8059eb92014-12-29 15:10:07 -0800163 // the vertex positions then we have to account for the view matrix
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000164 SkRect devBounds;
joshualitt8059eb92014-12-29 15:10:07 -0800165
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000166 // since we already computed the dev verts, set the bounds hint. This will help us avoid
167 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700168 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000169
bsalomon49f085d2014-09-05 13:34:00 -0700170 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700171 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
172 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000173 coords->setRectFan(localRect->fLeft, localRect->fTop,
174 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700175 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700176 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700177 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000178 }
179 }
180
bsalomon62c447d2014-08-08 08:08:50 -0700181 static const int kColorOffset = sizeof(SkPoint);
182 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
183 for (int i = 0; i < 4; ++i) {
184 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700185 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000186 }
187
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000188 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
egdaniel8dd688b2015-01-22 10:16:09 -0800189 this->drawIndexedInstances(pipelineBuilder, gp, kTriangles_GrPrimitiveType, 1, 4, 6,
190 &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000191}
192
egdaniel8dd688b2015-01-22 10:16:09 -0800193int GrInOrderDrawBuffer::concatInstancedDraw(const GrPipelineBuilder& pipelineBuilder,
194 const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700195 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000196 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000197
bsalomon@google.com934c5702012-03-20 21:17:58 +0000198 const GeometrySrcState& geomSrc = this->getGeomSrc();
199
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000200 // we only attempt to concat the case when reserved verts are used with a client-specified index
201 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
202 // between draws.
203 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
204 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
205 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000206 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000207 // Check if there is a draw info that is compatible that uses the same VB from the pool and
208 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700209 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000210 return 0;
211 }
212
cdalton6819df32014-10-15 13:43:48 -0700213 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000214
cdalton6819df32014-10-15 13:43:48 -0700215 if (!draw->fInfo.isInstanced() ||
joshualitt4d8da812015-01-28 12:53:54 -0800216 draw->fInfo.primitiveType() != info.primitiveType() ||
cdalton6819df32014-10-15 13:43:48 -0700217 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
218 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800219 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800220 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000221 return 0;
222 }
bsalomon371bcbc2014-12-01 08:19:34 -0800223 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000224 return 0;
225 }
226
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000227 // how many instances can be concat'ed onto draw given the size of the index buffer
228 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700229 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000230 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000231
cdalton6819df32014-10-15 13:43:48 -0700232 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000233
234 // update last fGpuCmdMarkers to include any additional trace markers that have been added
235 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700236 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000237 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
238 } else {
239 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700240 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000241 }
242 }
243
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000244 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000245}
246
egdaniel8dd688b2015-01-22 10:16:09 -0800247void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800248 const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800249 const DrawInfo& info,
bsalomon50785a32015-02-06 07:02:37 -0800250 const GrScissorState& scissorState) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800251 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
joshualitt4d8da812015-01-28 12:53:54 -0800252 this->closeBatch();
253
bsalomon50785a32015-02-06 07:02:37 -0800254 if (!this->recordStateAndShouldDraw(pipelineBuilder, gp, scissorState, info.getDevBounds())) {
bsalomonae59b772014-11-19 08:23:49 -0800255 return;
256 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000257
bsalomonb3e3a952014-09-19 11:10:40 -0700258 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000259 if (info.isInstanced()) {
egdaniel8dd688b2015-01-22 10:16:09 -0800260 int instancesConcated = this->concatInstancedDraw(pipelineBuilder, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000261 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800262 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700263 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000264 } else {
265 return;
266 }
267 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800268 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000269 }
cdalton6819df32014-10-15 13:43:48 -0700270 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000271}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000272
joshualitt4d8da812015-01-28 12:53:54 -0800273void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
274 const GrPipelineBuilder& pipelineBuilder,
275 const GrScissorState& scissorState,
bsalomon50785a32015-02-06 07:02:37 -0800276 const SkRect* devBounds) {
277 if (!this->recordStateAndShouldDraw(batch, pipelineBuilder, scissorState, devBounds)) {
joshualitt4d8da812015-01-28 12:53:54 -0800278 return;
279 }
280
281 // Check if there is a Batch Draw we can batch with
282 if (kDrawBatch_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
283 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch));
284 return;
285 }
286
287 DrawBatch* draw = static_cast<DrawBatch*>(&fCmdBuffer.back());
288 if (draw->fBatch->combineIfPossible(batch)) {
289 return;
290 } else {
291 this->closeBatch();
292 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch));
293 }
294 this->recordTraceMarkersIfNecessary();
295}
296
egdaniel8dd688b2015-01-22 10:16:09 -0800297void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800298 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800299 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800300 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800301 const GrStencilSettings& stencilSettings) {
joshualitt70f00042015-02-06 15:53:59 -0800302 this->closeBatch();
303
bsalomon3e791242014-12-17 13:43:13 -0800304 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
egdaniel8dd688b2015-01-22 10:16:09 -0800305 (path, pipelineBuilder.getRenderTarget()));
bsalomon3e791242014-12-17 13:43:13 -0800306 sp->fScissor = scissorState;
egdaniel8dd688b2015-01-22 10:16:09 -0800307 sp->fUseHWAA = pipelineBuilder.isHWAntialias();
joshualitt8059eb92014-12-29 15:10:07 -0800308 sp->fViewMatrix = pathProc->viewMatrix();
bsalomon3e791242014-12-17 13:43:13 -0800309 sp->fStencil = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700310 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000311}
312
egdaniel8dd688b2015-01-22 10:16:09 -0800313void GrInOrderDrawBuffer::onDrawPath(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800314 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800315 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800316 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800317 const GrStencilSettings& stencilSettings,
bsalomon50785a32015-02-06 07:02:37 -0800318 const SkRect* devBounds) {
joshualitt4d8da812015-01-28 12:53:54 -0800319 this->closeBatch();
320
egdaniel8dd688b2015-01-22 10:16:09 -0800321 // TODO: Only compare the subset of GrPipelineBuilder relevant to path covering?
bsalomon50785a32015-02-06 07:02:37 -0800322 if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, devBounds)) {
bsalomonae59b772014-11-19 08:23:49 -0800323 return;
324 }
cdalton6819df32014-10-15 13:43:48 -0700325 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800326 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700327 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000328}
329
egdaniel8dd688b2015-01-22 10:16:09 -0800330void GrInOrderDrawBuffer::onDrawPaths(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800331 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800332 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800333 const void* indices,
334 PathIndexType indexType,
335 const float transformValues[],
336 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800337 int count,
bsalomon3e791242014-12-17 13:43:13 -0800338 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800339 const GrStencilSettings& stencilSettings,
bsalomon50785a32015-02-06 07:02:37 -0800340 const SkRect* devBounds) {
bsalomon49f085d2014-09-05 13:34:00 -0700341 SkASSERT(pathRange);
342 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800343 SkASSERT(transformValues);
joshualitt4d8da812015-01-28 12:53:54 -0800344 this->closeBatch();
345
bsalomon50785a32015-02-06 07:02:37 -0800346 if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, devBounds)) {
bsalomonae59b772014-11-19 08:23:49 -0800347 return;
348 }
cdalton6819df32014-10-15 13:43:48 -0700349
cdalton55b24af2014-11-25 11:00:56 -0800350 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
351 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
352 // Add padding to the index buffer so the indices are aligned properly.
353 fPathIndexBuffer.append(indexBytes - misalign);
354 }
355
356 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
357 reinterpret_cast<const char*>(indices));
358 float* savedTransforms = fPathTransformBuffer.append(
359 count * GrPathRendering::PathTransformSize(transformType),
360 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700361
cdalton3fc6a2f2014-11-13 11:54:20 -0800362 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
363 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800364 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800365 // equivalent to two separate draw calls if there is overlap. Blending won't work,
366 // and the combined calls may also cancel each other's winding numbers in some
367 // places. For now the winding numbers are only an issue if the fill is even/odd,
368 // because DrawPaths is currently only used for glyphs, and glyphs in the same
369 // font tend to all wind in the same direction.
370 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
371 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800372 indexType == previous->fIndexType &&
373 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800374 stencilSettings == previous->fStencilSettings &&
375 path_fill_type_is_winding(stencilSettings) &&
egdaniel8dd688b2015-01-22 10:16:09 -0800376 !pipelineBuilder.willBlendWithDst(pathProc)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800377 // Fold this DrawPaths call into the one previous.
378 previous->fCount += count;
379 return;
380 }
381 }
382
383 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
bsalomonef3fcd82014-12-12 08:51:38 -0800384 dp->fIndicesLocation = SkToU32(savedIndices - fPathIndexBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800385 dp->fIndexType = indexType;
bsalomonef3fcd82014-12-12 08:51:38 -0800386 dp->fTransformsLocation = SkToU32(savedTransforms - fPathTransformBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800387 dp->fTransformType = transformType;
388 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800389 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700390
391 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000392}
393
bsalomon63b21962014-11-05 07:05:34 -0800394void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
395 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800396 SkASSERT(renderTarget);
joshualitt70f00042015-02-06 15:53:59 -0800397 this->closeBatch();
398
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000399 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000400 if (NULL == rect) {
401 // We could do something smart and remove previous draws and clears to
402 // the current render target. If we get that smart we have to make sure
403 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000404 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000405 rect = &r;
406 }
cdalton6819df32014-10-15 13:43:48 -0700407 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000408 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000409 clr->fColor = color;
410 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000411 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700412 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000413}
414
joshualitt6db519c2014-10-29 08:48:18 -0700415void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
416 bool insideClip,
417 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800418 SkASSERT(renderTarget);
joshualitt70f00042015-02-06 15:53:59 -0800419 this->closeBatch();
420
joshualitt6db519c2014-10-29 08:48:18 -0700421 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
422 clr->fRect = rect;
423 clr->fInsideClip = insideClip;
424 this->recordTraceMarkersIfNecessary();
425}
426
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000427void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800428 SkASSERT(renderTarget);
joshualitt70f00042015-02-06 15:53:59 -0800429 this->closeBatch();
430
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000431 if (!this->caps()->discardRenderTargetSupport()) {
432 return;
433 }
cdalton6819df32014-10-15 13:43:48 -0700434 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000435 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700436 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000437}
438
bsalomon371bcbc2014-12-01 08:19:34 -0800439void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700440 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800441 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800442 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
443 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000444 fGpuCmdMarkers.reset();
joshualitt4d8da812015-01-28 12:53:54 -0800445 fDrawBatch = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000446}
447
bsalomon371bcbc2014-12-01 08:19:34 -0800448void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700449 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000450 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000451 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000452
joshualittc2893c52015-01-28 06:54:30 -0800453 // Updated every time we find a set state cmd to reflect the current state in the playback
454 // stream.
455 SetState* currentState = NULL;
456
joshualitt4d8da812015-01-28 12:53:54 -0800457 // TODO this is temporary while batch is being rolled out
458 this->closeBatch();
459 this->getVertexAllocPool()->unmap();
460 this->getIndexAllocPool()->unmap();
461 fBatchTarget.preFlush();
462
463 currentState = NULL;
464 CmdBuffer::Iter iter(fCmdBuffer);
465
466 int currCmdMarker = 0;
467
joshualitt7bc18b72015-02-03 16:41:41 -0800468 int i = 0;
cdalton6819df32014-10-15 13:43:48 -0700469 while (iter.next()) {
joshualitt7bc18b72015-02-03 16:41:41 -0800470 i++;
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000471 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700472 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700473 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700474 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000475 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800476 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000477 ++currCmdMarker;
478 }
cdalton6819df32014-10-15 13:43:48 -0700479
joshualitt4d8da812015-01-28 12:53:54 -0800480 // TODO temporary hack
481 if (kDrawBatch_Cmd == strip_trace_bit(iter->fType)) {
joshualitt7bc18b72015-02-03 16:41:41 -0800482 DrawBatch* db = reinterpret_cast<DrawBatch*>(iter.get());
483 fBatchTarget.flushNext(db->fBatch->numberOfDraws());
joshualitt4d8da812015-01-28 12:53:54 -0800484 continue;
485 }
486
487 bool isSetState = kSetState_Cmd == strip_trace_bit(iter->fType);
488 if (isSetState) {
joshualitt9853cce2014-11-17 14:22:48 -0800489 SetState* ss = reinterpret_cast<SetState*>(iter.get());
joshualitt873ad0e2015-01-20 09:08:51 -0800490
joshualitt4d8da812015-01-28 12:53:54 -0800491 // TODO sometimes we have a prim proc, othertimes we have a GrBatch. Eventually we will
492 // only have GrBatch and we can delete this
493 if (ss->fPrimitiveProcessor) {
494 this->getGpu()->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor,
495 ss->fPipeline,
joshualitt4d8da812015-01-28 12:53:54 -0800496 ss->fBatchTracker);
497 }
joshualitt873ad0e2015-01-20 09:08:51 -0800498 currentState = ss;
joshualittd53a8272014-11-10 16:03:14 -0800499 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800500 iter->execute(this, currentState);
joshualittd53a8272014-11-10 16:03:14 -0800501 }
cdalton6819df32014-10-15 13:43:48 -0700502
503 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800504 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000505 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000506 }
mtkleinf439c772014-10-14 14:29:30 -0700507
joshualitt4d8da812015-01-28 12:53:54 -0800508 // TODO see copious notes about hack
509 fBatchTarget.postFlush();
510
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000511 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000512 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000513}
514
joshualitt873ad0e2015-01-20 09:08:51 -0800515void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
516 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800517 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800518 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800519 buf->getGpu()->draw(args, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700520}
521
joshualitt873ad0e2015-01-20 09:08:51 -0800522void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon3e791242014-12-17 13:43:13 -0800523 GrGpu::StencilPathState state;
524 state.fRenderTarget = fRenderTarget.get();
525 state.fScissor = &fScissor;
526 state.fStencil = &fStencil;
527 state.fUseHWAA = fUseHWAA;
528 state.fViewMatrix = &fViewMatrix;
529
530 buf->getGpu()->stencilPath(this->path(), state);
cdalton6819df32014-10-15 13:43:48 -0700531}
532
joshualitt873ad0e2015-01-20 09:08:51 -0800533void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
534 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800535 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800536 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800537 buf->getGpu()->drawPath(args, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700538}
539
joshualitt873ad0e2015-01-20 09:08:51 -0800540void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
541 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800542 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800543 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800544 buf->getGpu()->drawPaths(args, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800545 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
546 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
547 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700548}
549
joshualitt4d8da812015-01-28 12:53:54 -0800550void GrInOrderDrawBuffer::DrawBatch::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
551 SkASSERT(state);
552 fBatch->generateGeometry(buf->getBatchTarget(), &state->fPipeline);
553}
554
joshualitt873ad0e2015-01-20 09:08:51 -0800555void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const SetState*) {}
cdalton6819df32014-10-15 13:43:48 -0700556
joshualitt873ad0e2015-01-20 09:08:51 -0800557void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const SetState*) {
cdalton6819df32014-10-15 13:43:48 -0700558 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800559 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700560 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800561 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700562 }
563}
564
joshualitt873ad0e2015-01-20 09:08:51 -0800565void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800566 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700567}
568
joshualitt873ad0e2015-01-20 09:08:51 -0800569void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800570 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700571}
572
bsalomonf90a02b2014-11-26 12:28:00 -0800573bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
574 GrSurface* src,
575 const SkIRect& srcRect,
576 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800577 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
joshualitt95964c62015-02-11 13:45:50 -0800578 this->closeBatch();
cdalton6819df32014-10-15 13:43:48 -0700579 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000580 cs->fSrcRect = srcRect;
581 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700582 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000583 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000584 }
bsalomonf90a02b2014-11-26 12:28:00 -0800585 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000586}
587
egdaniel8dd688b2015-01-22 10:16:09 -0800588bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipelineBuilder,
joshualitt71c92602015-01-14 08:12:47 -0800589 const GrPrimitiveProcessor* primProc,
bsalomon3e791242014-12-17 13:43:13 -0800590 const GrScissorState& scissor,
bsalomon50785a32015-02-06 07:02:37 -0800591 const SkRect* devBounds) {
592 GrDeviceCoordTexture dstCopy;
593 if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
594 return false;
595 }
bsalomon932f8662014-11-24 06:47:48 -0800596 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
egdaniel8dd688b2015-01-22 10:16:09 -0800597 (pipelineBuilder, primProc, *this->getGpu()->caps(),
bsalomon50785a32015-02-06 07:02:37 -0800598 scissor, &dstCopy));
egdaniel8dd688b2015-01-22 10:16:09 -0800599 if (ss->fPipeline.mustSkip()) {
bsalomon932f8662014-11-24 06:47:48 -0800600 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800601 return false;
602 }
joshualitt873ad0e2015-01-20 09:08:51 -0800603
604 ss->fPrimitiveProcessor->initBatchTracker(&ss->fBatchTracker,
egdaniel8dd688b2015-01-22 10:16:09 -0800605 ss->fPipeline.getInitBatchTracker());
joshualitt873ad0e2015-01-20 09:08:51 -0800606
joshualitt4d8da812015-01-28 12:53:54 -0800607 if (fPrevState && fPrevState->fPrimitiveProcessor.get() &&
joshualitt873ad0e2015-01-20 09:08:51 -0800608 fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker,
609 *ss->fPrimitiveProcessor,
610 ss->fBatchTracker) &&
egdaniel8dd688b2015-01-22 10:16:09 -0800611 fPrevState->fPipeline.isEqual(ss->fPipeline)) {
bsalomon932f8662014-11-24 06:47:48 -0800612 fCmdBuffer.pop_back();
613 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800614 fPrevState = ss;
cdalton6819df32014-10-15 13:43:48 -0700615 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700616 }
bsalomonae59b772014-11-19 08:23:49 -0800617 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000618}
619
joshualitt4d8da812015-01-28 12:53:54 -0800620bool GrInOrderDrawBuffer::recordStateAndShouldDraw(GrBatch* batch,
621 const GrPipelineBuilder& pipelineBuilder,
622 const GrScissorState& scissor,
bsalomon50785a32015-02-06 07:02:37 -0800623 const SkRect* devBounds) {
624 GrDeviceCoordTexture dstCopy;
625 if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
626 return false;
627 }
joshualitt4d8da812015-01-28 12:53:54 -0800628 // TODO this gets much simpler when we have batches everywhere.
629 // If the previous command is also a set state, then we check to see if it has a Batch. If so,
630 // and we can make the two batches equal, and we can combine the states, then we make them equal
631 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
632 (batch, pipelineBuilder, *this->getGpu()->caps(), scissor,
bsalomon50785a32015-02-06 07:02:37 -0800633 &dstCopy));
joshualitt4d8da812015-01-28 12:53:54 -0800634 if (ss->fPipeline.mustSkip()) {
635 fCmdBuffer.pop_back();
636 return false;
637 }
638
639 batch->initBatchTracker(ss->fPipeline.getInitBatchTracker());
640
641 if (fPrevState && !fPrevState->fPrimitiveProcessor.get() &&
642 fPrevState->fPipeline.isEqual(ss->fPipeline)) {
643 fCmdBuffer.pop_back();
644 } else {
645 this->closeBatch();
646 fPrevState = ss;
647 this->recordTraceMarkersIfNecessary();
648 }
649 return true;
650}
651
cdalton6819df32014-10-15 13:43:48 -0700652void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
653 SkASSERT(!fCmdBuffer.empty());
654 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700655 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
656 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700657 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700658 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700659 }
mtklein07894c42014-10-13 14:00:42 -0700660}
joshualitt4d8da812015-01-28 12:53:54 -0800661
joshualitt4d8da812015-01-28 12:53:54 -0800662void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
663 size_t vertexStride,
664 int indexCount) {
665 this->closeBatch();
666
667 // We use geometryHints() to know whether to flush the draw buffer. We
668 // can't flush if we are inside an unbalanced pushGeometrySource.
669 // Moreover, flushing blows away vertex and index data that was
670 // previously reserved. So if the vertex or index data is pulled from
671 // reserved space and won't be released by this request then we can't
672 // flush.
673 bool insideGeoPush = this->getGeoPoolStateStack().count() > 1;
674
675 bool unreleasedVertexSpace =
676 !vertexCount &&
677 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
678
679 bool unreleasedIndexSpace =
680 !indexCount &&
681 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
682
683 int vcount = vertexCount;
684 int icount = indexCount;
685
686 if (!insideGeoPush &&
687 !unreleasedVertexSpace &&
688 !unreleasedIndexSpace &&
689 this->geometryHints(vertexStride, &vcount, &icount)) {
690 this->flush();
691 }
692}