blob: 493420db0b1d111448f078383cf249918f3b02c9 [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 */
65static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
joshualitt5478d422014-11-14 16:00:38 -080066 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
67 GrDefaultGeoProcFactory::kColor_GPType;
68 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
joshualitt2e3b3e32014-12-09 13:31:14 -080069 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(color, flags))->unref();
bsalomon62c447d2014-08-08 08:08:50 -070070 if (0xFF == GrColorUnpackA(color)) {
71 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
72 }
73}
robertphillips@google.com42903302013-04-20 12:26:07 +000074
cdalton3fc6a2f2014-11-13 11:54:20 -080075static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
76 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
77 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
78 if (isWinding) {
79 // Double check that it is in fact winding.
80 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
81 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
82 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
83 SkASSERT(!pathStencilSettings.isTwoSided());
84 }
85 return isWinding;
86}
87
88template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
89 // Assume the next time this buffer fills up it will use approximately the same amount
90 // of space as last time. Only resize if we're using less than a third of the
91 // allocated space, and leave enough for 50% growth over last time.
92 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
93 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
94 buffer->reset();
95 buffer->setReserve(reserve);
96 } else {
97 buffer->rewind();
98 }
99}
100
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000101enum {
102 kTraceCmdBit = 0x80,
103 kCmdMask = 0x7f,
104};
105
bsalomon62c447d2014-08-08 08:08:50 -0700106static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000107
bsalomon62c447d2014-08-08 08:08:50 -0700108static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000109
bsalomon62c447d2014-08-08 08:08:50 -0700110static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000111
joshualitt9853cce2014-11-17 14:22:48 -0800112void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
joshualitt2e3b3e32014-12-09 13:31:14 -0800113 GrColor color,
joshualitt9853cce2014-11-17 14:22:48 -0800114 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000115 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000116 const SkMatrix* localMatrix) {
joshualitt9853cce2014-11-17 14:22:48 -0800117 GrDrawState::AutoRestoreEffects are(ds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000118
joshualitt9853cce2014-11-17 14:22:48 -0800119 set_vertex_attributes(ds, SkToBool(localRect), color);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000120
joshualitt2dd1ae02014-12-03 06:24:10 -0800121 size_t vstride = ds->getGeometryProcessor()->getVertexStride();
122 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
123 0));
124 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000125 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700126 SkDebugf("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
joshualitt9853cce2014-11-17 14:22:48 -0800131 SkMatrix matrix = ds->getViewMatrix();
bsalomon01c8da12014-08-04 09:21:30 -0700132
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;
joshualitt9853cce2014-11-17 14:22:48 -0800137 if (!avmr.setIdentity(ds)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000138 return;
139 }
140
egdaniel7b3d5ee2014-08-28 05:41:14 -0700141 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
142 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000143
144 SkRect devBounds;
145 // since we already computed the dev verts, set the bounds hint. This will help us avoid
146 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700147 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000148
bsalomon49f085d2014-09-05 13:34:00 -0700149 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700150 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
151 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000152 coords->setRectFan(localRect->fLeft, localRect->fTop,
153 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700154 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700155 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700156 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000157 }
158 }
159
bsalomon62c447d2014-08-08 08:08:50 -0700160 static const int kColorOffset = sizeof(SkPoint);
161 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
162 for (int i = 0; i < 4; ++i) {
163 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700164 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000165 }
166
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000167 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualitt9853cce2014-11-17 14:22:48 -0800168 this->drawIndexedInstances(ds, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000169}
170
joshualitt54e0c122014-11-19 09:38:51 -0800171int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700172 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000173 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000174
bsalomon@google.com934c5702012-03-20 21:17:58 +0000175 const GeometrySrcState& geomSrc = this->getGeomSrc();
176
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000177 // we only attempt to concat the case when reserved verts are used with a client-specified index
178 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
179 // between draws.
180 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
181 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
182 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000183 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000184 // Check if there is a draw info that is compatible that uses the same VB from the pool and
185 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700186 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000187 return 0;
188 }
189
cdalton6819df32014-10-15 13:43:48 -0700190 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000191
cdalton6819df32014-10-15 13:43:48 -0700192 if (!draw->fInfo.isInstanced() ||
193 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
194 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800195 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800196 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000197 return 0;
198 }
bsalomon371bcbc2014-12-01 08:19:34 -0800199 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000200 return 0;
201 }
202
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000203 // how many instances can be concat'ed onto draw given the size of the index buffer
204 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700205 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000206 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000207
cdalton6819df32014-10-15 13:43:48 -0700208 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000209
210 // update last fGpuCmdMarkers to include any additional trace markers that have been added
211 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700212 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000213 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
214 } else {
215 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700216 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000217 }
218 }
219
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000220 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000221}
222
joshualitt9853cce2014-11-17 14:22:48 -0800223void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
224 const DrawInfo& info,
joshualitt9176e2c2014-11-20 07:28:52 -0800225 const ScissorState& scissorState,
226 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800227 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
228
joshualitt2e3b3e32014-12-09 13:31:14 -0800229 const GrGeometryProcessor* gp = ds.getGeometryProcessor();
230 if (!this->recordStateAndShouldDraw(ds, gp->getColor(), gp->getCoverage(),
231 GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualitt9176e2c2014-11-20 07:28:52 -0800232 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800233 return;
234 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000235
bsalomonb3e3a952014-09-19 11:10:40 -0700236 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000237 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800238 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000239 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800240 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700241 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000242 } else {
243 return;
244 }
245 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800246 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000247 }
cdalton6819df32014-10-15 13:43:48 -0700248 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000249}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000250
joshualitt9853cce2014-11-17 14:22:48 -0800251void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
252 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800253 const GrClipMaskManager::ScissorState& scissorState,
254 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000255 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualitt2e3b3e32014-12-09 13:31:14 -0800256 if (!this->recordStateAndShouldDraw(ds, GrColor_WHITE, 0xff, GrGpu::kStencilPath_DrawType,
257 scissorState, NULL)) {
bsalomonae59b772014-11-19 08:23:49 -0800258 return;
259 }
cdalton6819df32014-10-15 13:43:48 -0700260 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800261 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700262 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000263}
264
joshualitt9853cce2014-11-17 14:22:48 -0800265void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
joshualitt2e3b3e32014-12-09 13:31:14 -0800266 GrColor color,
joshualitt9853cce2014-11-17 14:22:48 -0800267 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800268 const GrClipMaskManager::ScissorState& scissorState,
269 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700270 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000271 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt2e3b3e32014-12-09 13:31:14 -0800272 if (!this->recordStateAndShouldDraw(ds, color, 0xff, GrGpu::kDrawPath_DrawType, scissorState,
273 dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800274 return;
275 }
cdalton6819df32014-10-15 13:43:48 -0700276 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800277 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700278 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000279}
280
joshualitt9853cce2014-11-17 14:22:48 -0800281void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
joshualitt2e3b3e32014-12-09 13:31:14 -0800282 GrColor color,
joshualitt9853cce2014-11-17 14:22:48 -0800283 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800284 const void* indices,
285 PathIndexType indexType,
286 const float transformValues[],
287 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800288 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800289 const GrClipMaskManager::ScissorState& scissorState,
290 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700291 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700292 SkASSERT(pathRange);
293 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800294 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000295
joshualitt2e3b3e32014-12-09 13:31:14 -0800296 if (!this->recordStateAndShouldDraw(ds, color, 0xff, GrGpu::kDrawPath_DrawType, scissorState,
297 dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800298 return;
299 }
cdalton6819df32014-10-15 13:43:48 -0700300
cdalton55b24af2014-11-25 11:00:56 -0800301 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
302 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
303 // Add padding to the index buffer so the indices are aligned properly.
304 fPathIndexBuffer.append(indexBytes - misalign);
305 }
306
307 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
308 reinterpret_cast<const char*>(indices));
309 float* savedTransforms = fPathTransformBuffer.append(
310 count * GrPathRendering::PathTransformSize(transformType),
311 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700312
cdalton3fc6a2f2014-11-13 11:54:20 -0800313 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
314 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800315 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800316 // equivalent to two separate draw calls if there is overlap. Blending won't work,
317 // and the combined calls may also cancel each other's winding numbers in some
318 // places. For now the winding numbers are only an issue if the fill is even/odd,
319 // because DrawPaths is currently only used for glyphs, and glyphs in the same
320 // font tend to all wind in the same direction.
321 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
322 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800323 indexType == previous->fIndexType &&
324 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800325 stencilSettings == previous->fStencilSettings &&
326 path_fill_type_is_winding(stencilSettings) &&
joshualitt2e3b3e32014-12-09 13:31:14 -0800327 !ds.willBlendWithDst(color, GrColor_WHITE)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800328 // Fold this DrawPaths call into the one previous.
329 previous->fCount += count;
330 return;
331 }
332 }
333
334 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
335 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800336 dp->fIndexType = indexType;
cdalton3fc6a2f2014-11-13 11:54:20 -0800337 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800338 dp->fTransformType = transformType;
339 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800340 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700341
342 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000343}
344
bsalomon63b21962014-11-05 07:05:34 -0800345void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
346 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800347 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000348 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000349 if (NULL == rect) {
350 // We could do something smart and remove previous draws and clears to
351 // the current render target. If we get that smart we have to make sure
352 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000353 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000354 rect = &r;
355 }
cdalton6819df32014-10-15 13:43:48 -0700356 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000357 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000358 clr->fColor = color;
359 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000360 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700361 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000362}
363
joshualitt6db519c2014-10-29 08:48:18 -0700364void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
365 bool insideClip,
366 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800367 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700368 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
369 clr->fRect = rect;
370 clr->fInsideClip = insideClip;
371 this->recordTraceMarkersIfNecessary();
372}
373
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000374void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800375 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000376 if (!this->caps()->discardRenderTargetSupport()) {
377 return;
378 }
cdalton6819df32014-10-15 13:43:48 -0700379 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000380 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700381 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000382}
383
bsalomon371bcbc2014-12-01 08:19:34 -0800384void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700385 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800386 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800387 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
388 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000389 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000390}
391
bsalomon371bcbc2014-12-01 08:19:34 -0800392void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700393 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000394 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000395 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000396
reed@google.comac10a2d2010-12-22 21:39:39 +0000397
cdalton6819df32014-10-15 13:43:48 -0700398 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000399
cdalton6819df32014-10-15 13:43:48 -0700400 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700401
bsalomonae59b772014-11-19 08:23:49 -0800402 // Updated every time we find a set state cmd to reflect the current state in the playback
403 // stream.
joshualittdafa4d02014-12-04 08:59:10 -0800404 GrOptDrawState* currentOptState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800405
cdalton6819df32014-10-15 13:43:48 -0700406 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000407 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700408 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700409 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700410 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000411 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800412 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000413 ++currCmdMarker;
414 }
cdalton6819df32014-10-15 13:43:48 -0700415
joshualittd53a8272014-11-10 16:03:14 -0800416 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800417 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomon932f8662014-11-24 06:47:48 -0800418 currentOptState = &ss->fState;
joshualittdafa4d02014-12-04 08:59:10 -0800419 currentOptState->finalize(this->getGpu());
joshualittd53a8272014-11-10 16:03:14 -0800420 } else {
bsalomon932f8662014-11-24 06:47:48 -0800421 iter->execute(this, currentOptState);
joshualittd53a8272014-11-10 16:03:14 -0800422 }
cdalton6819df32014-10-15 13:43:48 -0700423
424 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800425 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000426 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000427 }
mtkleinf439c772014-10-14 14:29:30 -0700428
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000429 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000430 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000431}
432
cdalton3fc6a2f2014-11-13 11:54:20 -0800433void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800434 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800435 buf->getGpu()->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700436}
437
cdalton3fc6a2f2014-11-13 11:54:20 -0800438void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
439 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800440 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800441 buf->getGpu()->stencilPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700442}
443
cdalton3fc6a2f2014-11-13 11:54:20 -0800444void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
445 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800446 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800447 buf->getGpu()->drawPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700448}
449
cdalton3fc6a2f2014-11-13 11:54:20 -0800450void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
451 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800452 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800453 buf->getGpu()->drawPaths(*optState, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800454 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
455 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
456 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700457}
458
bsalomon932f8662014-11-24 06:47:48 -0800459void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {}
cdalton6819df32014-10-15 13:43:48 -0700460
cdalton3fc6a2f2014-11-13 11:54:20 -0800461void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700462 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800463 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700464 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800465 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700466 }
467}
468
cdalton3fc6a2f2014-11-13 11:54:20 -0800469void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
470 const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800471 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700472}
473
cdalton3fc6a2f2014-11-13 11:54:20 -0800474void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800475 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700476}
477
bsalomonf90a02b2014-11-26 12:28:00 -0800478bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
479 GrSurface* src,
480 const SkIRect& srcRect,
481 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800482 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700483 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000484 cs->fSrcRect = srcRect;
485 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700486 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000487 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000488 }
bsalomonf90a02b2014-11-26 12:28:00 -0800489 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000490}
491
bsalomonae59b772014-11-19 08:23:49 -0800492bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
joshualitt2e3b3e32014-12-09 13:31:14 -0800493 GrColor color,
494 uint8_t coverage,
bsalomonae59b772014-11-19 08:23:49 -0800495 GrGpu::DrawType drawType,
joshualitt54e0c122014-11-19 09:38:51 -0800496 const GrClipMaskManager::ScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800497 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800498 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
joshualitt2e3b3e32014-12-09 13:31:14 -0800499 (ds, color, coverage, *this->getGpu()->caps(), scissor,
500 dstCopy, drawType));
bsalomon932f8662014-11-24 06:47:48 -0800501 if (ss->fState.mustSkip()) {
502 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800503 return false;
504 }
bsalomon932f8662014-11-24 06:47:48 -0800505 if (fPrevState && *fPrevState == ss->fState) {
506 fCmdBuffer.pop_back();
507 } else {
508 fPrevState = &ss->fState;
cdalton6819df32014-10-15 13:43:48 -0700509 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700510 }
bsalomonae59b772014-11-19 08:23:49 -0800511 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000512}
513
cdalton6819df32014-10-15 13:43:48 -0700514void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
515 SkASSERT(!fCmdBuffer.empty());
516 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700517 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
518 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700519 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700520 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700521 }
mtklein07894c42014-10-13 14:00:42 -0700522}