blob: 8a136cdb2bfce910fa174627d958e4d561e27934 [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"
joshualittd53a8272014-11-10 16:03:14 -080014#include "GrTextStrike.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;
69 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::CreateAndSetAttribs(drawState,
70 flags))->unref();
bsalomon62c447d2014-08-08 08:08:50 -070071 if (0xFF == GrColorUnpackA(color)) {
72 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
73 }
74}
robertphillips@google.com42903302013-04-20 12:26:07 +000075
cdalton3fc6a2f2014-11-13 11:54:20 -080076static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
77 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
78 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
79 if (isWinding) {
80 // Double check that it is in fact winding.
81 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
82 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
83 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
84 SkASSERT(!pathStencilSettings.isTwoSided());
85 }
86 return isWinding;
87}
88
89template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
90 // Assume the next time this buffer fills up it will use approximately the same amount
91 // of space as last time. Only resize if we're using less than a third of the
92 // allocated space, and leave enough for 50% growth over last time.
93 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
94 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
95 buffer->reset();
96 buffer->setReserve(reserve);
97 } else {
98 buffer->rewind();
99 }
100}
101
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000102enum {
103 kTraceCmdBit = 0x80,
104 kCmdMask = 0x7f,
105};
106
bsalomon62c447d2014-08-08 08:08:50 -0700107static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000108
bsalomon62c447d2014-08-08 08:08:50 -0700109static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000110
bsalomon62c447d2014-08-08 08:08:50 -0700111static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000112
joshualitt9853cce2014-11-17 14:22:48 -0800113void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
114 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 GrColor color = ds->getColor();
120 set_vertex_attributes(ds, SkToBool(localRect), color);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000121
joshualitt9853cce2014-11-17 14:22:48 -0800122 AutoReleaseGeometry geo(this, 4, ds->getVertexStride(), 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000123 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700124 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000125 return;
126 }
127
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000128 // Go to device coords to allow batching across matrix changes
joshualitt9853cce2014-11-17 14:22:48 -0800129 SkMatrix matrix = ds->getViewMatrix();
bsalomon01c8da12014-08-04 09:21:30 -0700130
jvanverth@google.com39768252013-02-14 15:25:44 +0000131 // 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 +0000132 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
133 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000134 GrDrawState::AutoViewMatrixRestore avmr;
joshualitt9853cce2014-11-17 14:22:48 -0800135 if (!avmr.setIdentity(ds)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000136 return;
137 }
138
joshualitt9853cce2014-11-17 14:22:48 -0800139 size_t vstride = ds->getVertexStride();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000140
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
bsalomonae59b772014-11-19 08:23:49 -0800229 if (!this->recordStateAndShouldDraw(ds, GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualitt9176e2c2014-11-20 07:28:52 -0800230 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800231 return;
232 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000233
bsalomonb3e3a952014-09-19 11:10:40 -0700234 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000235 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800236 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000237 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800238 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700239 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000240 } else {
241 return;
242 }
243 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800244 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000245 }
cdalton6819df32014-10-15 13:43:48 -0700246 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000247}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000248
joshualitt9853cce2014-11-17 14:22:48 -0800249void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
250 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800251 const GrClipMaskManager::ScissorState& scissorState,
252 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000253 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualitt54e0c122014-11-19 09:38:51 -0800254 if (!this->recordStateAndShouldDraw(ds, GrGpu::kStencilPath_DrawType, scissorState, NULL)) {
bsalomonae59b772014-11-19 08:23:49 -0800255 return;
256 }
cdalton6819df32014-10-15 13:43:48 -0700257 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800258 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700259 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000260}
261
joshualitt9853cce2014-11-17 14:22:48 -0800262void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
263 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800264 const GrClipMaskManager::ScissorState& scissorState,
265 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700266 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000267 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt54e0c122014-11-19 09:38:51 -0800268 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800269 return;
270 }
cdalton6819df32014-10-15 13:43:48 -0700271 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800272 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700273 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000274}
275
joshualitt9853cce2014-11-17 14:22:48 -0800276void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
277 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800278 const void* indices,
279 PathIndexType indexType,
280 const float transformValues[],
281 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800282 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800283 const GrClipMaskManager::ScissorState& scissorState,
284 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700285 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700286 SkASSERT(pathRange);
287 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800288 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000289
joshualitt54e0c122014-11-19 09:38:51 -0800290 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800291 return;
292 }
cdalton6819df32014-10-15 13:43:48 -0700293
cdalton55b24af2014-11-25 11:00:56 -0800294 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
295 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
296 // Add padding to the index buffer so the indices are aligned properly.
297 fPathIndexBuffer.append(indexBytes - misalign);
298 }
299
300 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
301 reinterpret_cast<const char*>(indices));
302 float* savedTransforms = fPathTransformBuffer.append(
303 count * GrPathRendering::PathTransformSize(transformType),
304 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700305
cdalton3fc6a2f2014-11-13 11:54:20 -0800306 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
307 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800308 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800309 // equivalent to two separate draw calls if there is overlap. Blending won't work,
310 // and the combined calls may also cancel each other's winding numbers in some
311 // places. For now the winding numbers are only an issue if the fill is even/odd,
312 // because DrawPaths is currently only used for glyphs, and glyphs in the same
313 // font tend to all wind in the same direction.
314 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
315 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800316 indexType == previous->fIndexType &&
317 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800318 stencilSettings == previous->fStencilSettings &&
319 path_fill_type_is_winding(stencilSettings) &&
joshualitt9853cce2014-11-17 14:22:48 -0800320 !ds.willBlendWithDst()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800321 // Fold this DrawPaths call into the one previous.
322 previous->fCount += count;
323 return;
324 }
325 }
326
327 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
328 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800329 dp->fIndexType = indexType;
cdalton3fc6a2f2014-11-13 11:54:20 -0800330 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800331 dp->fTransformType = transformType;
332 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800333 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700334
335 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000336}
337
bsalomon63b21962014-11-05 07:05:34 -0800338void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
339 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800340 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000341 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000342 if (NULL == rect) {
343 // We could do something smart and remove previous draws and clears to
344 // the current render target. If we get that smart we have to make sure
345 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000346 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000347 rect = &r;
348 }
cdalton6819df32014-10-15 13:43:48 -0700349 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000350 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000351 clr->fColor = color;
352 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000353 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700354 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000355}
356
joshualitt6db519c2014-10-29 08:48:18 -0700357void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
358 bool insideClip,
359 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800360 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700361 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
362 clr->fRect = rect;
363 clr->fInsideClip = insideClip;
364 this->recordTraceMarkersIfNecessary();
365}
366
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000367void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800368 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000369 if (!this->caps()->discardRenderTargetSupport()) {
370 return;
371 }
cdalton6819df32014-10-15 13:43:48 -0700372 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000373 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700374 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000375}
376
bsalomon371bcbc2014-12-01 08:19:34 -0800377void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700378 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800379 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800380 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
381 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000382 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000383}
384
bsalomon371bcbc2014-12-01 08:19:34 -0800385void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700386 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000387 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000388 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000389
reed@google.comac10a2d2010-12-22 21:39:39 +0000390
cdalton6819df32014-10-15 13:43:48 -0700391 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000392
cdalton6819df32014-10-15 13:43:48 -0700393 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700394
bsalomonae59b772014-11-19 08:23:49 -0800395 // Updated every time we find a set state cmd to reflect the current state in the playback
396 // stream.
bsalomon932f8662014-11-24 06:47:48 -0800397 const GrOptDrawState* currentOptState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800398
cdalton6819df32014-10-15 13:43:48 -0700399 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000400 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700401 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700402 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700403 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000404 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800405 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000406 ++currCmdMarker;
407 }
cdalton6819df32014-10-15 13:43:48 -0700408
joshualittd53a8272014-11-10 16:03:14 -0800409 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800410 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomon932f8662014-11-24 06:47:48 -0800411 currentOptState = &ss->fState;
joshualittd53a8272014-11-10 16:03:14 -0800412 } else {
bsalomon932f8662014-11-24 06:47:48 -0800413 iter->execute(this, currentOptState);
joshualittd53a8272014-11-10 16:03:14 -0800414 }
cdalton6819df32014-10-15 13:43:48 -0700415
416 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800417 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000418 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000419 }
mtkleinf439c772014-10-14 14:29:30 -0700420
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000421 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000422 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000423}
424
cdalton3fc6a2f2014-11-13 11:54:20 -0800425void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800426 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800427 buf->getGpu()->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700428}
429
cdalton3fc6a2f2014-11-13 11:54:20 -0800430void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
431 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800432 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800433 buf->getGpu()->stencilPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700434}
435
cdalton3fc6a2f2014-11-13 11:54:20 -0800436void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
437 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800438 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800439 buf->getGpu()->drawPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700440}
441
cdalton3fc6a2f2014-11-13 11:54:20 -0800442void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
443 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800444 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800445 buf->getGpu()->drawPaths(*optState, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800446 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
447 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
448 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700449}
450
bsalomon932f8662014-11-24 06:47:48 -0800451void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {}
cdalton6819df32014-10-15 13:43:48 -0700452
cdalton3fc6a2f2014-11-13 11:54:20 -0800453void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700454 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800455 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700456 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800457 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700458 }
459}
460
cdalton3fc6a2f2014-11-13 11:54:20 -0800461void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
462 const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800463 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700464}
465
cdalton3fc6a2f2014-11-13 11:54:20 -0800466void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800467 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700468}
469
bsalomonf90a02b2014-11-26 12:28:00 -0800470bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
471 GrSurface* src,
472 const SkIRect& srcRect,
473 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800474 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700475 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000476 cs->fSrcRect = srcRect;
477 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700478 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000479 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000480 }
bsalomonf90a02b2014-11-26 12:28:00 -0800481 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000482}
483
bsalomonf90a02b2014-11-26 12:28:00 -0800484bool GrInOrderDrawBuffer::onCanCopySurface(const GrSurface* dst,
joshualitt9853cce2014-11-17 14:22:48 -0800485 const GrSurface* src,
joshualitta7024152014-11-03 14:16:35 -0800486 const SkIRect& srcRect,
487 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800488 return getGpu()->canCopySurface(dst, src, srcRect, dstPoint);
bsalomon@google.com116ad842013-04-09 15:38:19 +0000489}
490
bsalomonf90a02b2014-11-26 12:28:00 -0800491bool GrInOrderDrawBuffer::onInitCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
bsalomon371bcbc2014-12-01 08:19:34 -0800492 return getGpu()->initCopySurfaceDstDesc(src, desc);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000493}
494
bsalomonae59b772014-11-19 08:23:49 -0800495bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
496 GrGpu::DrawType drawType,
joshualitt54e0c122014-11-19 09:38:51 -0800497 const GrClipMaskManager::ScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800498 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800499 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
bsalomon371bcbc2014-12-01 08:19:34 -0800500 (ds, this->getGpu(), scissor, 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}