blob: 5b1f00891e991dc4cccafa02d93a03672ebd6c80 [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
joshualitt5478d422014-11-14 16:00:38 -080010#include "GrDefaultGeoProcFactory.h"
bsalomon@google.comc26d94f2013-03-25 18:19:00 +000011#include "GrDrawTargetCaps.h"
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000012#include "GrGpu.h"
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000013#include "GrTemplates.h"
jvanverth787cdf92014-12-04 10:46:50 -080014#include "GrFontCache.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)
bsalomon371bcbc2014-12-01 08:19:34 -080020 : INHERITED(gpu, vertexPool, indexPool)
cdalton6819df32014-10-15 13:43:48 -070021 , fCmdBuffer(kCmdBufferInitialSizeInBytes)
bsalomon932f8662014-11-24 06:47:48 -080022 , fPrevState(NULL)
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +000023 , fDrawID(0) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000024
bsalomon49f085d2014-09-05 13:34:00 -070025 SkASSERT(vertexPool);
26 SkASSERT(indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000027
cdalton3fc6a2f2014-11-13 11:54:20 -080028 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
29 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
reed@google.comac10a2d2010-12-22 21:39:39 +000030}
31
32GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000033 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000034}
35
bsalomon@google.com934c5702012-03-20 21:17:58 +000036////////////////////////////////////////////////////////////////////////////////
37
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000038namespace {
39void get_vertex_bounds(const void* vertices,
40 size_t vertexSize,
41 int vertexCount,
42 SkRect* bounds) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000043 SkASSERT(vertexSize >= sizeof(SkPoint));
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000044 SkASSERT(vertexCount > 0);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000045 const SkPoint* point = static_cast<const SkPoint*>(vertices);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000046 bounds->fLeft = bounds->fRight = point->fX;
47 bounds->fTop = bounds->fBottom = point->fY;
48 for (int i = 1; i < vertexCount; ++i) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000049 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000050 bounds->growToInclude(point->fX, point->fY);
51 }
52}
bsalomon@google.com934c5702012-03-20 21:17:58 +000053}
54
bsalomon62c447d2014-08-08 08:08:50 -070055/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
56 have explicit local coords and sometimes not. We *could* always provide explicit local coords
57 and just duplicate the positions when the caller hasn't provided a local coord rect, but we
58 haven't seen a use case which frequently switches between local rect and no local rect draws.
59
60 The color param is used to determine whether the opaque hint can be set on the draw state.
61 The caller must populate the vertex colors itself.
62
63 The vertex attrib order is always pos, color, [local coords].
64 */
joshualitt8fc6c2d2014-12-22 15:27:05 -080065static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords,
66 GrColor color,
67 const SkMatrix* localMatrix) {
joshualitt5478d422014-11-14 16:00:38 -080068 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
69 GrDefaultGeoProcFactory::kColor_GPType;
joshualitt8fc6c2d2014-12-22 15:27:05 -080070 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
71 if (localMatrix) {
joshualitt8059eb92014-12-29 15:10:07 -080072 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *localMatrix,
73 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080074 } else {
joshualitt8059eb92014-12-29 15:10:07 -080075 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMatrix::I(),
76 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080077 }
bsalomon62c447d2014-08-08 08:08:50 -070078}
robertphillips@google.com42903302013-04-20 12:26:07 +000079
cdalton3fc6a2f2014-11-13 11:54:20 -080080static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
81 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
82 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
83 if (isWinding) {
84 // Double check that it is in fact winding.
85 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
86 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
87 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
88 SkASSERT(!pathStencilSettings.isTwoSided());
89 }
90 return isWinding;
91}
92
93template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
94 // Assume the next time this buffer fills up it will use approximately the same amount
95 // of space as last time. Only resize if we're using less than a third of the
96 // allocated space, and leave enough for 50% growth over last time.
97 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
98 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
99 buffer->reset();
100 buffer->setReserve(reserve);
101 } else {
102 buffer->rewind();
103 }
104}
105
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000106enum {
107 kTraceCmdBit = 0x80,
108 kCmdMask = 0x7f,
109};
110
bsalomon62c447d2014-08-08 08:08:50 -0700111static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000112
bsalomon62c447d2014-08-08 08:08:50 -0700113static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000114
bsalomon62c447d2014-08-08 08:08:50 -0700115static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000116
joshualitt9853cce2014-11-17 14:22:48 -0800117void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
joshualitt2e3b3e32014-12-09 13:31:14 -0800118 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800119 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800120 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000121 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000122 const SkMatrix* localMatrix) {
joshualitt9853cce2014-11-17 14:22:48 -0800123 GrDrawState::AutoRestoreEffects are(ds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000124
joshualittd27f73e2014-12-29 07:43:36 -0800125 // Go to device coords to allow batching across matrix changes
joshualittd27f73e2014-12-29 07:43:36 -0800126 SkMatrix invert = SkMatrix::I();
127
128 // if we have a local rect, then we apply the localMatrix directly to the localRect to generate
129 // vertex local coords
joshualitt8fc6c2d2014-12-22 15:27:05 -0800130 bool hasExplicitLocalCoords = SkToBool(localRect);
joshualittd27f73e2014-12-29 07:43:36 -0800131 if (!hasExplicitLocalCoords) {
joshualitt8059eb92014-12-29 15:10:07 -0800132 if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
joshualittd27f73e2014-12-29 07:43:36 -0800133 SkDebugf("Could not invert\n");
134 return;
135 }
136
137 if (localMatrix) {
138 invert.preConcat(*localMatrix);
139 }
140 }
141
142 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCoords,
143 color,
144 &invert));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000145
joshualitt56995b52014-12-11 15:44:02 -0800146 size_t vstride = gp->getVertexStride();
joshualitt2dd1ae02014-12-03 06:24:10 -0800147 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
148 0));
149 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000150 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700151 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000152 return;
153 }
154
joshualitt8059eb92014-12-29 15:10:07 -0800155 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
156 viewMatrix.mapPointsWithStride(geo.positions(), vstride, 4);
157
jvanverth@google.com39768252013-02-14 15:25:44 +0000158 // 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 +0000159 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
joshualitt8059eb92014-12-29 15:10:07 -0800160 // the vertex positions then we have to account for the view matrix
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000161 SkRect devBounds;
joshualitt8059eb92014-12-29 15:10:07 -0800162
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000163 // since we already computed the dev verts, set the bounds hint. This will help us avoid
164 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700165 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000166
bsalomon49f085d2014-09-05 13:34:00 -0700167 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700168 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
169 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000170 coords->setRectFan(localRect->fLeft, localRect->fTop,
171 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700172 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700173 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700174 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000175 }
176 }
177
bsalomon62c447d2014-08-08 08:08:50 -0700178 static const int kColorOffset = sizeof(SkPoint);
179 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
180 for (int i = 0; i < 4; ++i) {
181 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700182 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000183 }
184
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000185 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualitt56995b52014-12-11 15:44:02 -0800186 this->drawIndexedInstances(ds, gp, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000187}
188
joshualitt54e0c122014-11-19 09:38:51 -0800189int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700190 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000191 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000192
bsalomon@google.com934c5702012-03-20 21:17:58 +0000193 const GeometrySrcState& geomSrc = this->getGeomSrc();
194
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000195 // we only attempt to concat the case when reserved verts are used with a client-specified index
196 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
197 // between draws.
198 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
199 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
200 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000201 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000202 // Check if there is a draw info that is compatible that uses the same VB from the pool and
203 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700204 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000205 return 0;
206 }
207
cdalton6819df32014-10-15 13:43:48 -0700208 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000209
cdalton6819df32014-10-15 13:43:48 -0700210 if (!draw->fInfo.isInstanced() ||
211 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
212 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800213 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800214 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000215 return 0;
216 }
bsalomon371bcbc2014-12-01 08:19:34 -0800217 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000218 return 0;
219 }
220
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000221 // how many instances can be concat'ed onto draw given the size of the index buffer
222 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700223 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000224 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000225
cdalton6819df32014-10-15 13:43:48 -0700226 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000227
228 // update last fGpuCmdMarkers to include any additional trace markers that have been added
229 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700230 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000231 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
232 } else {
233 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700234 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000235 }
236 }
237
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000238 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000239}
240
joshualitt9853cce2014-11-17 14:22:48 -0800241void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800242 const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800243 const DrawInfo& info,
bsalomon3e791242014-12-17 13:43:13 -0800244 const GrScissorState& scissorState,
joshualitt9176e2c2014-11-20 07:28:52 -0800245 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800246 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
247
joshualitt17e73142015-01-21 11:52:36 -0800248 if (!this->recordStateAndShouldDraw(ds, gp, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800249 return;
250 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000251
bsalomonb3e3a952014-09-19 11:10:40 -0700252 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000253 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800254 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000255 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800256 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700257 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000258 } else {
259 return;
260 }
261 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800262 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000263 }
cdalton6819df32014-10-15 13:43:48 -0700264 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000265}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000266
joshualitt9853cce2014-11-17 14:22:48 -0800267void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800268 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800269 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800270 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800271 const GrStencilSettings& stencilSettings) {
bsalomon3e791242014-12-17 13:43:13 -0800272 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
273 (path, ds.getRenderTarget()));
274 sp->fScissor = scissorState;
275 sp->fUseHWAA = ds.isHWAntialias();
joshualitt8059eb92014-12-29 15:10:07 -0800276 sp->fViewMatrix = pathProc->viewMatrix();
bsalomon3e791242014-12-17 13:43:13 -0800277 sp->fStencil = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700278 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000279}
280
joshualitt9853cce2014-11-17 14:22:48 -0800281void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800282 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800283 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800284 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800285 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700286 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000287 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt17e73142015-01-21 11:52:36 -0800288 if (!this->recordStateAndShouldDraw(ds, pathProc, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800289 return;
290 }
cdalton6819df32014-10-15 13:43:48 -0700291 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800292 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700293 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000294}
295
joshualitt9853cce2014-11-17 14:22:48 -0800296void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800297 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800298 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800299 const void* indices,
300 PathIndexType indexType,
301 const float transformValues[],
302 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800303 int count,
bsalomon3e791242014-12-17 13:43:13 -0800304 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800305 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700306 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700307 SkASSERT(pathRange);
308 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800309 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000310
joshualitt17e73142015-01-21 11:52:36 -0800311 if (!this->recordStateAndShouldDraw(ds, pathProc, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800312 return;
313 }
cdalton6819df32014-10-15 13:43:48 -0700314
cdalton55b24af2014-11-25 11:00:56 -0800315 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
316 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
317 // Add padding to the index buffer so the indices are aligned properly.
318 fPathIndexBuffer.append(indexBytes - misalign);
319 }
320
321 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
322 reinterpret_cast<const char*>(indices));
323 float* savedTransforms = fPathTransformBuffer.append(
324 count * GrPathRendering::PathTransformSize(transformType),
325 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700326
cdalton3fc6a2f2014-11-13 11:54:20 -0800327 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
328 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800329 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800330 // equivalent to two separate draw calls if there is overlap. Blending won't work,
331 // and the combined calls may also cancel each other's winding numbers in some
332 // places. For now the winding numbers are only an issue if the fill is even/odd,
333 // because DrawPaths is currently only used for glyphs, and glyphs in the same
334 // font tend to all wind in the same direction.
335 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
336 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800337 indexType == previous->fIndexType &&
338 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800339 stencilSettings == previous->fStencilSettings &&
340 path_fill_type_is_winding(stencilSettings) &&
joshualitt56995b52014-12-11 15:44:02 -0800341 !ds.willBlendWithDst(pathProc)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800342 // Fold this DrawPaths call into the one previous.
343 previous->fCount += count;
344 return;
345 }
346 }
347
348 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
bsalomonef3fcd82014-12-12 08:51:38 -0800349 dp->fIndicesLocation = SkToU32(savedIndices - fPathIndexBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800350 dp->fIndexType = indexType;
bsalomonef3fcd82014-12-12 08:51:38 -0800351 dp->fTransformsLocation = SkToU32(savedTransforms - fPathTransformBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800352 dp->fTransformType = transformType;
353 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800354 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700355
356 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000357}
358
bsalomon63b21962014-11-05 07:05:34 -0800359void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
360 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800361 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000362 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000363 if (NULL == rect) {
364 // We could do something smart and remove previous draws and clears to
365 // the current render target. If we get that smart we have to make sure
366 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000367 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000368 rect = &r;
369 }
cdalton6819df32014-10-15 13:43:48 -0700370 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000371 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000372 clr->fColor = color;
373 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000374 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700375 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000376}
377
joshualitt6db519c2014-10-29 08:48:18 -0700378void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
379 bool insideClip,
380 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800381 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700382 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
383 clr->fRect = rect;
384 clr->fInsideClip = insideClip;
385 this->recordTraceMarkersIfNecessary();
386}
387
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000388void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800389 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000390 if (!this->caps()->discardRenderTargetSupport()) {
391 return;
392 }
cdalton6819df32014-10-15 13:43:48 -0700393 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000394 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700395 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000396}
397
bsalomon371bcbc2014-12-01 08:19:34 -0800398void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700399 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800400 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800401 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
402 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000403 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000404}
405
bsalomon371bcbc2014-12-01 08:19:34 -0800406void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700407 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000408 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000409 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000410
reed@google.comac10a2d2010-12-22 21:39:39 +0000411
cdalton6819df32014-10-15 13:43:48 -0700412 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000413
cdalton6819df32014-10-15 13:43:48 -0700414 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700415
bsalomonae59b772014-11-19 08:23:49 -0800416 // Updated every time we find a set state cmd to reflect the current state in the playback
417 // stream.
joshualitt873ad0e2015-01-20 09:08:51 -0800418 SetState* currentState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800419
cdalton6819df32014-10-15 13:43:48 -0700420 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000421 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700422 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700423 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700424 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000425 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800426 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000427 ++currCmdMarker;
428 }
cdalton6819df32014-10-15 13:43:48 -0700429
joshualittd53a8272014-11-10 16:03:14 -0800430 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800431 SetState* ss = reinterpret_cast<SetState*>(iter.get());
joshualitt873ad0e2015-01-20 09:08:51 -0800432
433 this->getGpu()->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor, ss->fState,
joshualitt17e73142015-01-21 11:52:36 -0800434 ss->fState.descInfo(), ss->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800435 currentState = ss;
436
joshualittd53a8272014-11-10 16:03:14 -0800437 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800438 iter->execute(this, currentState);
joshualittd53a8272014-11-10 16:03:14 -0800439 }
cdalton6819df32014-10-15 13:43:48 -0700440
441 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800442 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000443 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000444 }
mtkleinf439c772014-10-14 14:29:30 -0700445
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000446 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000447 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000448}
449
joshualitt873ad0e2015-01-20 09:08:51 -0800450void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
451 SkASSERT(state);
452 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fState, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800453 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800454 buf->getGpu()->draw(args, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700455}
456
joshualitt873ad0e2015-01-20 09:08:51 -0800457void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon3e791242014-12-17 13:43:13 -0800458 GrGpu::StencilPathState state;
459 state.fRenderTarget = fRenderTarget.get();
460 state.fScissor = &fScissor;
461 state.fStencil = &fStencil;
462 state.fUseHWAA = fUseHWAA;
463 state.fViewMatrix = &fViewMatrix;
464
465 buf->getGpu()->stencilPath(this->path(), state);
cdalton6819df32014-10-15 13:43:48 -0700466}
467
joshualitt873ad0e2015-01-20 09:08:51 -0800468void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
469 SkASSERT(state);
470 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fState, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800471 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800472 buf->getGpu()->drawPath(args, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700473}
474
joshualitt873ad0e2015-01-20 09:08:51 -0800475void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
476 SkASSERT(state);
477 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fState, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800478 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800479 buf->getGpu()->drawPaths(args, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800480 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
481 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
482 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700483}
484
joshualitt873ad0e2015-01-20 09:08:51 -0800485void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const SetState*) {}
cdalton6819df32014-10-15 13:43:48 -0700486
joshualitt873ad0e2015-01-20 09:08:51 -0800487void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const SetState*) {
cdalton6819df32014-10-15 13:43:48 -0700488 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800489 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700490 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800491 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700492 }
493}
494
joshualitt873ad0e2015-01-20 09:08:51 -0800495void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800496 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700497}
498
joshualitt873ad0e2015-01-20 09:08:51 -0800499void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800500 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700501}
502
bsalomonf90a02b2014-11-26 12:28:00 -0800503bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
504 GrSurface* src,
505 const SkIRect& srcRect,
506 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800507 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700508 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000509 cs->fSrcRect = srcRect;
510 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700511 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000512 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000513 }
bsalomonf90a02b2014-11-26 12:28:00 -0800514 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000515}
516
bsalomonae59b772014-11-19 08:23:49 -0800517bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
joshualitt71c92602015-01-14 08:12:47 -0800518 const GrPrimitiveProcessor* primProc,
bsalomon3e791242014-12-17 13:43:13 -0800519 const GrScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800520 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800521 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
joshualitt71c92602015-01-14 08:12:47 -0800522 (ds, primProc, *this->getGpu()->caps(), scissor,
joshualitt17e73142015-01-21 11:52:36 -0800523 dstCopy));
bsalomon932f8662014-11-24 06:47:48 -0800524 if (ss->fState.mustSkip()) {
525 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800526 return false;
527 }
joshualitt873ad0e2015-01-20 09:08:51 -0800528
529 ss->fPrimitiveProcessor->initBatchTracker(&ss->fBatchTracker,
530 ss->fState.getInitBatchTracker());
531
532 if (fPrevState &&
533 fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker,
534 *ss->fPrimitiveProcessor,
535 ss->fBatchTracker) &&
536 fPrevState->fState.isEqual(ss->fState)) {
bsalomon932f8662014-11-24 06:47:48 -0800537 fCmdBuffer.pop_back();
538 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800539 fPrevState = ss;
cdalton6819df32014-10-15 13:43:48 -0700540 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700541 }
bsalomonae59b772014-11-19 08:23:49 -0800542 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000543}
544
cdalton6819df32014-10-15 13:43:48 -0700545void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
546 SkASSERT(!fCmdBuffer.empty());
547 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700548 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
549 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700550 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700551 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700552 }
mtklein07894c42014-10-13 14:00:42 -0700553}