blob: dc074b7b511e5ebf95fe7a1c13df9f1b9cd4132b [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,
bsalomon3e791242014-12-17 13:43:13 -0800225 const GrScissorState& scissorState,
joshualitt9176e2c2014-11-20 07:28:52 -0800226 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,
bsalomon3e791242014-12-17 13:43:13 -0800253 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800254 const GrStencilSettings& stencilSettings) {
bsalomon3e791242014-12-17 13:43:13 -0800255 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
256 (path, ds.getRenderTarget()));
257 sp->fScissor = scissorState;
258 sp->fUseHWAA = ds.isHWAntialias();
259 sp->fViewMatrix = ds.getViewMatrix();
260 sp->fStencil = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700261 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000262}
263
joshualitt9853cce2014-11-17 14:22:48 -0800264void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800265 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800266 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800267 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800268 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700269 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000270 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt56995b52014-12-11 15:44:02 -0800271 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType,
272 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800273 return;
274 }
cdalton6819df32014-10-15 13:43:48 -0700275 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800276 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700277 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000278}
279
joshualitt9853cce2014-11-17 14:22:48 -0800280void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800281 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800282 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800283 const void* indices,
284 PathIndexType indexType,
285 const float transformValues[],
286 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800287 int count,
bsalomon3e791242014-12-17 13:43:13 -0800288 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800289 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700290 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700291 SkASSERT(pathRange);
292 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800293 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000294
joshualitt56995b52014-12-11 15:44:02 -0800295 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType, scissorState,
joshualitt2e3b3e32014-12-09 13:31:14 -0800296 dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800297 return;
298 }
cdalton6819df32014-10-15 13:43:48 -0700299
cdalton55b24af2014-11-25 11:00:56 -0800300 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
301 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
302 // Add padding to the index buffer so the indices are aligned properly.
303 fPathIndexBuffer.append(indexBytes - misalign);
304 }
305
306 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
307 reinterpret_cast<const char*>(indices));
308 float* savedTransforms = fPathTransformBuffer.append(
309 count * GrPathRendering::PathTransformSize(transformType),
310 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700311
cdalton3fc6a2f2014-11-13 11:54:20 -0800312 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
313 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800314 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800315 // equivalent to two separate draw calls if there is overlap. Blending won't work,
316 // and the combined calls may also cancel each other's winding numbers in some
317 // places. For now the winding numbers are only an issue if the fill is even/odd,
318 // because DrawPaths is currently only used for glyphs, and glyphs in the same
319 // font tend to all wind in the same direction.
320 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
321 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800322 indexType == previous->fIndexType &&
323 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800324 stencilSettings == previous->fStencilSettings &&
325 path_fill_type_is_winding(stencilSettings) &&
joshualitt56995b52014-12-11 15:44:02 -0800326 !ds.willBlendWithDst(pathProc)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800327 // Fold this DrawPaths call into the one previous.
328 previous->fCount += count;
329 return;
330 }
331 }
332
333 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
bsalomonef3fcd82014-12-12 08:51:38 -0800334 dp->fIndicesLocation = SkToU32(savedIndices - fPathIndexBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800335 dp->fIndexType = indexType;
bsalomonef3fcd82014-12-12 08:51:38 -0800336 dp->fTransformsLocation = SkToU32(savedTransforms - fPathTransformBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800337 dp->fTransformType = transformType;
338 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800339 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700340
341 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000342}
343
bsalomon63b21962014-11-05 07:05:34 -0800344void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
345 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800346 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000347 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000348 if (NULL == rect) {
349 // We could do something smart and remove previous draws and clears to
350 // the current render target. If we get that smart we have to make sure
351 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000352 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000353 rect = &r;
354 }
cdalton6819df32014-10-15 13:43:48 -0700355 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000356 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000357 clr->fColor = color;
358 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000359 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700360 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000361}
362
joshualitt6db519c2014-10-29 08:48:18 -0700363void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
364 bool insideClip,
365 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800366 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700367 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
368 clr->fRect = rect;
369 clr->fInsideClip = insideClip;
370 this->recordTraceMarkersIfNecessary();
371}
372
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000373void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800374 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000375 if (!this->caps()->discardRenderTargetSupport()) {
376 return;
377 }
cdalton6819df32014-10-15 13:43:48 -0700378 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000379 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700380 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000381}
382
bsalomon371bcbc2014-12-01 08:19:34 -0800383void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700384 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800385 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800386 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
387 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000388 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000389}
390
bsalomon371bcbc2014-12-01 08:19:34 -0800391void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700392 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000393 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000394 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000395
reed@google.comac10a2d2010-12-22 21:39:39 +0000396
cdalton6819df32014-10-15 13:43:48 -0700397 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000398
cdalton6819df32014-10-15 13:43:48 -0700399 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700400
bsalomonae59b772014-11-19 08:23:49 -0800401 // Updated every time we find a set state cmd to reflect the current state in the playback
402 // stream.
joshualittdafa4d02014-12-04 08:59:10 -0800403 GrOptDrawState* currentOptState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800404
cdalton6819df32014-10-15 13:43:48 -0700405 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000406 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700407 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700408 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700409 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000410 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800411 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000412 ++currCmdMarker;
413 }
cdalton6819df32014-10-15 13:43:48 -0700414
joshualittd53a8272014-11-10 16:03:14 -0800415 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800416 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomon932f8662014-11-24 06:47:48 -0800417 currentOptState = &ss->fState;
joshualittdafa4d02014-12-04 08:59:10 -0800418 currentOptState->finalize(this->getGpu());
joshualittd53a8272014-11-10 16:03:14 -0800419 } else {
bsalomon932f8662014-11-24 06:47:48 -0800420 iter->execute(this, currentOptState);
joshualittd53a8272014-11-10 16:03:14 -0800421 }
cdalton6819df32014-10-15 13:43:48 -0700422
423 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800424 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000425 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000426 }
mtkleinf439c772014-10-14 14:29:30 -0700427
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000428 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000429 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000430}
431
cdalton3fc6a2f2014-11-13 11:54:20 -0800432void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800433 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800434 buf->getGpu()->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700435}
436
bsalomon3e791242014-12-17 13:43:13 -0800437void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
438 GrGpu::StencilPathState state;
439 state.fRenderTarget = fRenderTarget.get();
440 state.fScissor = &fScissor;
441 state.fStencil = &fStencil;
442 state.fUseHWAA = fUseHWAA;
443 state.fViewMatrix = &fViewMatrix;
444
445 buf->getGpu()->stencilPath(this->path(), state);
cdalton6819df32014-10-15 13:43:48 -0700446}
447
cdalton3fc6a2f2014-11-13 11:54:20 -0800448void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
449 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800450 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800451 buf->getGpu()->drawPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700452}
453
cdalton3fc6a2f2014-11-13 11:54:20 -0800454void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
455 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800456 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800457 buf->getGpu()->drawPaths(*optState, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800458 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
459 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
460 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700461}
462
bsalomon932f8662014-11-24 06:47:48 -0800463void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {}
cdalton6819df32014-10-15 13:43:48 -0700464
cdalton3fc6a2f2014-11-13 11:54:20 -0800465void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700466 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800467 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700468 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800469 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700470 }
471}
472
cdalton3fc6a2f2014-11-13 11:54:20 -0800473void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
474 const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800475 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700476}
477
cdalton3fc6a2f2014-11-13 11:54:20 -0800478void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800479 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700480}
481
bsalomonf90a02b2014-11-26 12:28:00 -0800482bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
483 GrSurface* src,
484 const SkIRect& srcRect,
485 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800486 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700487 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000488 cs->fSrcRect = srcRect;
489 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700490 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000491 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000492 }
bsalomonf90a02b2014-11-26 12:28:00 -0800493 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000494}
495
bsalomonae59b772014-11-19 08:23:49 -0800496bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800497 const GrGeometryProcessor* gp,
498 const GrPathProcessor* pathProc,
bsalomonae59b772014-11-19 08:23:49 -0800499 GrGpu::DrawType drawType,
bsalomon3e791242014-12-17 13:43:13 -0800500 const GrScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800501 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800502 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
joshualitt56995b52014-12-11 15:44:02 -0800503 (ds, gp, pathProc, *this->getGpu()->caps(), scissor,
joshualitt2e3b3e32014-12-09 13:31:14 -0800504 dstCopy, drawType));
bsalomon932f8662014-11-24 06:47:48 -0800505 if (ss->fState.mustSkip()) {
506 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800507 return false;
508 }
joshualitt9b989322014-12-15 14:16:27 -0800509 if (fPrevState && fPrevState->combineIfPossible(ss->fState)) {
bsalomon932f8662014-11-24 06:47:48 -0800510 fCmdBuffer.pop_back();
511 } else {
512 fPrevState = &ss->fState;
cdalton6819df32014-10-15 13:43:48 -0700513 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700514 }
bsalomonae59b772014-11-19 08:23:49 -0800515 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000516}
517
cdalton6819df32014-10-15 13:43:48 -0700518void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
519 SkASSERT(!fCmdBuffer.empty());
520 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700521 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
522 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700523 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700524 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700525 }
mtklein07894c42014-10-13 14:00:42 -0700526}