blob: 0b5c96889b854ab4080ce66b31ec1363ad32a5e1 [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 */
joshualittc6bc58e2014-12-10 13:48:57 -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;
joshualittc6bc58e2014-12-10 13:48:57 -080071 const GrGeometryProcessor* gp = GrDefaultGeoProcFactory::Create(color, flags);
bsalomon62c447d2014-08-08 08:08:50 -070072 if (0xFF == GrColorUnpackA(color)) {
73 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
74 }
joshualittc6bc58e2014-12-10 13:48:57 -080075 return gp;
bsalomon62c447d2014-08-08 08:08:50 -070076}
robertphillips@google.com42903302013-04-20 12:26:07 +000077
cdalton3fc6a2f2014-11-13 11:54:20 -080078static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
79 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
80 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
81 if (isWinding) {
82 // Double check that it is in fact winding.
83 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
84 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
85 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
86 SkASSERT(!pathStencilSettings.isTwoSided());
87 }
88 return isWinding;
89}
90
91template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
92 // Assume the next time this buffer fills up it will use approximately the same amount
93 // of space as last time. Only resize if we're using less than a third of the
94 // allocated space, and leave enough for 50% growth over last time.
95 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
96 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
97 buffer->reset();
98 buffer->setReserve(reserve);
99 } else {
100 buffer->rewind();
101 }
102}
103
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000104enum {
105 kTraceCmdBit = 0x80,
106 kCmdMask = 0x7f,
107};
108
bsalomon62c447d2014-08-08 08:08:50 -0700109static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000110
bsalomon62c447d2014-08-08 08:08:50 -0700111static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000112
bsalomon62c447d2014-08-08 08:08:50 -0700113static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000114
joshualitt9853cce2014-11-17 14:22:48 -0800115void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
joshualitt2e3b3e32014-12-09 13:31:14 -0800116 GrColor color,
joshualitt9853cce2014-11-17 14:22:48 -0800117 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000118 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000119 const SkMatrix* localMatrix) {
joshualitt9853cce2014-11-17 14:22:48 -0800120 GrDrawState::AutoRestoreEffects are(ds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000121
joshualittc6bc58e2014-12-10 13:48:57 -0800122 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(ds, SkToBool(localRect),
123 color));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000124
joshualittc6bc58e2014-12-10 13:48:57 -0800125 size_t vstride = gp->getVertexStride();
joshualitt2dd1ae02014-12-03 06:24:10 -0800126 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
127 0));
128 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000129 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700130 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000131 return;
132 }
133
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000134 // Go to device coords to allow batching across matrix changes
joshualitt9853cce2014-11-17 14:22:48 -0800135 SkMatrix matrix = ds->getViewMatrix();
bsalomon01c8da12014-08-04 09:21:30 -0700136
jvanverth@google.com39768252013-02-14 15:25:44 +0000137 // 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 +0000138 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
139 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000140 GrDrawState::AutoViewMatrixRestore avmr;
joshualitt9853cce2014-11-17 14:22:48 -0800141 if (!avmr.setIdentity(ds)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000142 return;
143 }
144
egdaniel7b3d5ee2014-08-28 05:41:14 -0700145 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
146 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000147
148 SkRect devBounds;
149 // since we already computed the dev verts, set the bounds hint. This will help us avoid
150 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700151 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000152
bsalomon49f085d2014-09-05 13:34:00 -0700153 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700154 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
155 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000156 coords->setRectFan(localRect->fLeft, localRect->fTop,
157 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700158 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700159 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700160 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000161 }
162 }
163
bsalomon62c447d2014-08-08 08:08:50 -0700164 static const int kColorOffset = sizeof(SkPoint);
165 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
166 for (int i = 0; i < 4; ++i) {
167 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700168 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000169 }
170
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000171 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualittc6bc58e2014-12-10 13:48:57 -0800172 this->drawIndexedInstances(ds, gp, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000173}
174
joshualitt54e0c122014-11-19 09:38:51 -0800175int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700176 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000177 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000178
bsalomon@google.com934c5702012-03-20 21:17:58 +0000179 const GeometrySrcState& geomSrc = this->getGeomSrc();
180
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000181 // we only attempt to concat the case when reserved verts are used with a client-specified index
182 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
183 // between draws.
184 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
185 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
186 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000187 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000188 // Check if there is a draw info that is compatible that uses the same VB from the pool and
189 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700190 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000191 return 0;
192 }
193
cdalton6819df32014-10-15 13:43:48 -0700194 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000195
cdalton6819df32014-10-15 13:43:48 -0700196 if (!draw->fInfo.isInstanced() ||
197 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
198 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800199 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800200 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000201 return 0;
202 }
bsalomon371bcbc2014-12-01 08:19:34 -0800203 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000204 return 0;
205 }
206
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000207 // how many instances can be concat'ed onto draw given the size of the index buffer
208 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700209 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000210 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000211
cdalton6819df32014-10-15 13:43:48 -0700212 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000213
214 // update last fGpuCmdMarkers to include any additional trace markers that have been added
215 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700216 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000217 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
218 } else {
219 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700220 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000221 }
222 }
223
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000224 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000225}
226
joshualitt9853cce2014-11-17 14:22:48 -0800227void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
joshualittc6bc58e2014-12-10 13:48:57 -0800228 const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800229 const DrawInfo& info,
joshualitt9176e2c2014-11-20 07:28:52 -0800230 const ScissorState& scissorState,
231 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800232 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
233
joshualittc6bc58e2014-12-10 13:48:57 -0800234 if (!this->recordStateAndShouldDraw(ds, gp, NULL,
joshualitt2e3b3e32014-12-09 13:31:14 -0800235 GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualitt9176e2c2014-11-20 07:28:52 -0800236 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800237 return;
238 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000239
bsalomonb3e3a952014-09-19 11:10:40 -0700240 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000241 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800242 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000243 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800244 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700245 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000246 } else {
247 return;
248 }
249 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800250 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000251 }
cdalton6819df32014-10-15 13:43:48 -0700252 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000253}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000254
joshualitt9853cce2014-11-17 14:22:48 -0800255void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
joshualittc6bc58e2014-12-10 13:48:57 -0800256 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800257 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800258 const GrClipMaskManager::ScissorState& scissorState,
259 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000260 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualittc6bc58e2014-12-10 13:48:57 -0800261 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kStencilPath_DrawType,
joshualitt2e3b3e32014-12-09 13:31:14 -0800262 scissorState, NULL)) {
bsalomonae59b772014-11-19 08:23:49 -0800263 return;
264 }
cdalton6819df32014-10-15 13:43:48 -0700265 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800266 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700267 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000268}
269
joshualitt9853cce2014-11-17 14:22:48 -0800270void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
joshualittc6bc58e2014-12-10 13:48:57 -0800271 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800272 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800273 const GrClipMaskManager::ScissorState& scissorState,
274 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700275 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000276 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualittc6bc58e2014-12-10 13:48:57 -0800277 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType,
278 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800279 return;
280 }
cdalton6819df32014-10-15 13:43:48 -0700281 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800282 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700283 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000284}
285
joshualitt9853cce2014-11-17 14:22:48 -0800286void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
joshualittc6bc58e2014-12-10 13:48:57 -0800287 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800288 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800289 const void* indices,
290 PathIndexType indexType,
291 const float transformValues[],
292 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800293 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800294 const GrClipMaskManager::ScissorState& scissorState,
295 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700296 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700297 SkASSERT(pathRange);
298 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800299 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000300
joshualittc6bc58e2014-12-10 13:48:57 -0800301 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType, scissorState,
joshualitt2e3b3e32014-12-09 13:31:14 -0800302 dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800303 return;
304 }
cdalton6819df32014-10-15 13:43:48 -0700305
cdalton55b24af2014-11-25 11:00:56 -0800306 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
307 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
308 // Add padding to the index buffer so the indices are aligned properly.
309 fPathIndexBuffer.append(indexBytes - misalign);
310 }
311
312 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
313 reinterpret_cast<const char*>(indices));
314 float* savedTransforms = fPathTransformBuffer.append(
315 count * GrPathRendering::PathTransformSize(transformType),
316 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700317
cdalton3fc6a2f2014-11-13 11:54:20 -0800318 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
319 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800320 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800321 // equivalent to two separate draw calls if there is overlap. Blending won't work,
322 // and the combined calls may also cancel each other's winding numbers in some
323 // places. For now the winding numbers are only an issue if the fill is even/odd,
324 // because DrawPaths is currently only used for glyphs, and glyphs in the same
325 // font tend to all wind in the same direction.
326 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
327 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800328 indexType == previous->fIndexType &&
329 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800330 stencilSettings == previous->fStencilSettings &&
331 path_fill_type_is_winding(stencilSettings) &&
joshualittc6bc58e2014-12-10 13:48:57 -0800332 !ds.willBlendWithDst(pathProc)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800333 // Fold this DrawPaths call into the one previous.
334 previous->fCount += count;
335 return;
336 }
337 }
338
339 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
340 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800341 dp->fIndexType = indexType;
cdalton3fc6a2f2014-11-13 11:54:20 -0800342 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800343 dp->fTransformType = transformType;
344 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800345 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700346
347 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000348}
349
bsalomon63b21962014-11-05 07:05:34 -0800350void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
351 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800352 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000353 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000354 if (NULL == rect) {
355 // We could do something smart and remove previous draws and clears to
356 // the current render target. If we get that smart we have to make sure
357 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000358 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000359 rect = &r;
360 }
cdalton6819df32014-10-15 13:43:48 -0700361 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000362 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000363 clr->fColor = color;
364 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000365 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700366 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000367}
368
joshualitt6db519c2014-10-29 08:48:18 -0700369void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
370 bool insideClip,
371 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800372 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700373 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
374 clr->fRect = rect;
375 clr->fInsideClip = insideClip;
376 this->recordTraceMarkersIfNecessary();
377}
378
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000379void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800380 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000381 if (!this->caps()->discardRenderTargetSupport()) {
382 return;
383 }
cdalton6819df32014-10-15 13:43:48 -0700384 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000385 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700386 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000387}
388
bsalomon371bcbc2014-12-01 08:19:34 -0800389void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700390 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800391 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800392 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
393 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000394 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000395}
396
bsalomon371bcbc2014-12-01 08:19:34 -0800397void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700398 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000399 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000400 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000401
reed@google.comac10a2d2010-12-22 21:39:39 +0000402
cdalton6819df32014-10-15 13:43:48 -0700403 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000404
cdalton6819df32014-10-15 13:43:48 -0700405 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700406
bsalomonae59b772014-11-19 08:23:49 -0800407 // Updated every time we find a set state cmd to reflect the current state in the playback
408 // stream.
joshualittdafa4d02014-12-04 08:59:10 -0800409 GrOptDrawState* currentOptState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800410
cdalton6819df32014-10-15 13:43:48 -0700411 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000412 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700413 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700414 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700415 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000416 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800417 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000418 ++currCmdMarker;
419 }
cdalton6819df32014-10-15 13:43:48 -0700420
joshualittd53a8272014-11-10 16:03:14 -0800421 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800422 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomon932f8662014-11-24 06:47:48 -0800423 currentOptState = &ss->fState;
joshualittdafa4d02014-12-04 08:59:10 -0800424 currentOptState->finalize(this->getGpu());
joshualittd53a8272014-11-10 16:03:14 -0800425 } else {
bsalomon932f8662014-11-24 06:47:48 -0800426 iter->execute(this, currentOptState);
joshualittd53a8272014-11-10 16:03:14 -0800427 }
cdalton6819df32014-10-15 13:43:48 -0700428
429 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800430 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000431 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000432 }
mtkleinf439c772014-10-14 14:29:30 -0700433
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000434 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000435 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000436}
437
cdalton3fc6a2f2014-11-13 11:54:20 -0800438void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800439 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800440 buf->getGpu()->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700441}
442
cdalton3fc6a2f2014-11-13 11:54:20 -0800443void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
444 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800445 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800446 buf->getGpu()->stencilPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700447}
448
cdalton3fc6a2f2014-11-13 11:54:20 -0800449void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
450 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800451 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800452 buf->getGpu()->drawPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700453}
454
cdalton3fc6a2f2014-11-13 11:54:20 -0800455void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
456 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800457 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800458 buf->getGpu()->drawPaths(*optState, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800459 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
460 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
461 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700462}
463
bsalomon932f8662014-11-24 06:47:48 -0800464void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {}
cdalton6819df32014-10-15 13:43:48 -0700465
cdalton3fc6a2f2014-11-13 11:54:20 -0800466void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700467 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800468 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700469 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800470 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700471 }
472}
473
cdalton3fc6a2f2014-11-13 11:54:20 -0800474void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
475 const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800476 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700477}
478
cdalton3fc6a2f2014-11-13 11:54:20 -0800479void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800480 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700481}
482
bsalomonf90a02b2014-11-26 12:28:00 -0800483bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
484 GrSurface* src,
485 const SkIRect& srcRect,
486 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800487 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700488 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000489 cs->fSrcRect = srcRect;
490 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700491 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000492 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000493 }
bsalomonf90a02b2014-11-26 12:28:00 -0800494 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000495}
496
bsalomonae59b772014-11-19 08:23:49 -0800497bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
joshualittc6bc58e2014-12-10 13:48:57 -0800498 const GrGeometryProcessor* gp,
499 const GrPathProcessor* pathProc,
bsalomonae59b772014-11-19 08:23:49 -0800500 GrGpu::DrawType drawType,
joshualitt54e0c122014-11-19 09:38:51 -0800501 const GrClipMaskManager::ScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800502 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800503 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
joshualittc6bc58e2014-12-10 13:48:57 -0800504 (ds, gp, pathProc, *this->getGpu()->caps(), scissor,
joshualitt2e3b3e32014-12-09 13:31:14 -0800505 dstCopy, drawType));
bsalomon932f8662014-11-24 06:47:48 -0800506 if (ss->fState.mustSkip()) {
507 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800508 return false;
509 }
bsalomon932f8662014-11-24 06:47:48 -0800510 if (fPrevState && *fPrevState == ss->fState) {
511 fCmdBuffer.pop_back();
512 } else {
513 fPrevState = &ss->fState;
cdalton6819df32014-10-15 13:43:48 -0700514 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700515 }
bsalomonae59b772014-11-19 08:23:49 -0800516 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000517}
518
cdalton6819df32014-10-15 13:43:48 -0700519void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
520 SkASSERT(!fCmdBuffer.empty());
521 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700522 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
523 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700524 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700525 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700526 }
mtklein07894c42014-10-13 14:00:42 -0700527}