blob: 62d6818c2ba0b072d737a04bc1d9c9a49be9d16a [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 */
joshualitt56995b52014-12-11 15:44:02 -080065static const GrGeometryProcessor* create_rect_gp(GrDrawState* drawState,
66 bool hasLocalCoords,
67 GrColor color) {
joshualitt5478d422014-11-14 16:00:38 -080068 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
69 GrDefaultGeoProcFactory::kColor_GPType;
70 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
joshualitt56995b52014-12-11 15:44:02 -080071 return GrDefaultGeoProcFactory::Create(color, flags, GrColorIsOpaque(color));
bsalomon62c447d2014-08-08 08:08:50 -070072}
robertphillips@google.com42903302013-04-20 12:26:07 +000073
cdalton3fc6a2f2014-11-13 11:54:20 -080074static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
75 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
76 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
77 if (isWinding) {
78 // Double check that it is in fact winding.
79 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
80 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
81 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
82 SkASSERT(!pathStencilSettings.isTwoSided());
83 }
84 return isWinding;
85}
86
87template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
88 // Assume the next time this buffer fills up it will use approximately the same amount
89 // of space as last time. Only resize if we're using less than a third of the
90 // allocated space, and leave enough for 50% growth over last time.
91 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
92 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
93 buffer->reset();
94 buffer->setReserve(reserve);
95 } else {
96 buffer->rewind();
97 }
98}
99
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000100enum {
101 kTraceCmdBit = 0x80,
102 kCmdMask = 0x7f,
103};
104
bsalomon62c447d2014-08-08 08:08:50 -0700105static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000106
bsalomon62c447d2014-08-08 08:08:50 -0700107static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000108
bsalomon62c447d2014-08-08 08:08:50 -0700109static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000110
joshualitt9853cce2014-11-17 14:22:48 -0800111void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
joshualitt2e3b3e32014-12-09 13:31:14 -0800112 GrColor color,
joshualitt9853cce2014-11-17 14:22:48 -0800113 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000114 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000115 const SkMatrix* localMatrix) {
joshualitt9853cce2014-11-17 14:22:48 -0800116 GrDrawState::AutoRestoreEffects are(ds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000117
joshualitt56995b52014-12-11 15:44:02 -0800118 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(ds, SkToBool(localRect), color));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000119
joshualitt56995b52014-12-11 15:44:02 -0800120 size_t vstride = gp->getVertexStride();
joshualitt2dd1ae02014-12-03 06:24:10 -0800121 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
122 0));
123 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000124 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700125 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000126 return;
127 }
128
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000129 // Go to device coords to allow batching across matrix changes
joshualitt9853cce2014-11-17 14:22:48 -0800130 SkMatrix matrix = ds->getViewMatrix();
bsalomon01c8da12014-08-04 09:21:30 -0700131
jvanverth@google.com39768252013-02-14 15:25:44 +0000132 // 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 +0000133 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
134 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000135 GrDrawState::AutoViewMatrixRestore avmr;
joshualitt9853cce2014-11-17 14:22:48 -0800136 if (!avmr.setIdentity(ds)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000137 return;
138 }
139
egdaniel7b3d5ee2014-08-28 05:41:14 -0700140 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
141 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000142
143 SkRect devBounds;
144 // since we already computed the dev verts, set the bounds hint. This will help us avoid
145 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700146 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000147
bsalomon49f085d2014-09-05 13:34:00 -0700148 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700149 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
150 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000151 coords->setRectFan(localRect->fLeft, localRect->fTop,
152 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700153 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700154 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700155 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000156 }
157 }
158
bsalomon62c447d2014-08-08 08:08:50 -0700159 static const int kColorOffset = sizeof(SkPoint);
160 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
161 for (int i = 0; i < 4; ++i) {
162 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700163 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000164 }
165
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000166 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualitt56995b52014-12-11 15:44:02 -0800167 this->drawIndexedInstances(ds, gp, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000168}
169
joshualitt54e0c122014-11-19 09:38:51 -0800170int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700171 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000172 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000173
bsalomon@google.com934c5702012-03-20 21:17:58 +0000174 const GeometrySrcState& geomSrc = this->getGeomSrc();
175
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000176 // we only attempt to concat the case when reserved verts are used with a client-specified index
177 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
178 // between draws.
179 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
180 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
181 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000182 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000183 // Check if there is a draw info that is compatible that uses the same VB from the pool and
184 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700185 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000186 return 0;
187 }
188
cdalton6819df32014-10-15 13:43:48 -0700189 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000190
cdalton6819df32014-10-15 13:43:48 -0700191 if (!draw->fInfo.isInstanced() ||
192 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
193 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800194 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800195 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000196 return 0;
197 }
bsalomon371bcbc2014-12-01 08:19:34 -0800198 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000199 return 0;
200 }
201
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000202 // how many instances can be concat'ed onto draw given the size of the index buffer
203 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700204 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000205 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000206
cdalton6819df32014-10-15 13:43:48 -0700207 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000208
209 // update last fGpuCmdMarkers to include any additional trace markers that have been added
210 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700211 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000212 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
213 } else {
214 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700215 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000216 }
217 }
218
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000219 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000220}
221
joshualitt9853cce2014-11-17 14:22:48 -0800222void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800223 const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800224 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
joshualitt56995b52014-12-11 15:44:02 -0800229 if (!this->recordStateAndShouldDraw(ds, gp, NULL,
joshualitt2e3b3e32014-12-09 13:31:14 -0800230 GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualitt9176e2c2014-11-20 07:28:52 -0800231 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800232 return;
233 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000234
bsalomonb3e3a952014-09-19 11:10:40 -0700235 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000236 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800237 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000238 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800239 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700240 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000241 } else {
242 return;
243 }
244 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800245 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000246 }
cdalton6819df32014-10-15 13:43:48 -0700247 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000248}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000249
joshualitt9853cce2014-11-17 14:22:48 -0800250void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800251 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800252 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?
joshualitt56995b52014-12-11 15:44:02 -0800256 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kStencilPath_DrawType,
joshualitt2e3b3e32014-12-09 13:31:14 -0800257 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,
joshualitt56995b52014-12-11 15:44:02 -0800266 const GrPathProcessor* pathProc,
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?
joshualitt56995b52014-12-11 15:44:02 -0800272 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType,
273 scissorState, 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,
joshualitt56995b52014-12-11 15:44:02 -0800282 const GrPathProcessor* pathProc,
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
joshualitt56995b52014-12-11 15:44:02 -0800296 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType, scissorState,
joshualitt2e3b3e32014-12-09 13:31:14 -0800297 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) &&
joshualitt56995b52014-12-11 15:44:02 -0800327 !ds.willBlendWithDst(pathProc)) {
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));
bsalomonef3fcd82014-12-12 08:51:38 -0800335 dp->fIndicesLocation = SkToU32(savedIndices - fPathIndexBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800336 dp->fIndexType = indexType;
bsalomonef3fcd82014-12-12 08:51:38 -0800337 dp->fTransformsLocation = SkToU32(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,
joshualitt56995b52014-12-11 15:44:02 -0800493 const GrGeometryProcessor* gp,
494 const GrPathProcessor* pathProc,
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,
joshualitt56995b52014-12-11 15:44:02 -0800499 (ds, gp, pathProc, *this->getGpu()->caps(), scissor,
joshualitt2e3b3e32014-12-09 13:31:14 -0800500 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}