blob: 1f4903591924b1e4dee4be321c4e7ab6f5bfb819 [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 */
joshualitt8fc6c2d2014-12-22 15:27:05 -080065static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords,
66 GrColor color,
67 const SkMatrix* localMatrix) {
joshualitt5478d422014-11-14 16:00:38 -080068 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
69 GrDefaultGeoProcFactory::kColor_GPType;
joshualitt8fc6c2d2014-12-22 15:27:05 -080070 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
71 if (localMatrix) {
72 return GrDefaultGeoProcFactory::Create(color, flags, GrColorIsOpaque(color), 0xff,
73 *localMatrix);
74 } else {
75 return GrDefaultGeoProcFactory::Create(color, flags, GrColorIsOpaque(color));
76 }
bsalomon62c447d2014-08-08 08:08:50 -070077}
robertphillips@google.com42903302013-04-20 12:26:07 +000078
cdalton3fc6a2f2014-11-13 11:54:20 -080079static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
80 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
81 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
82 if (isWinding) {
83 // Double check that it is in fact winding.
84 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
85 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
86 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
87 SkASSERT(!pathStencilSettings.isTwoSided());
88 }
89 return isWinding;
90}
91
92template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
93 // Assume the next time this buffer fills up it will use approximately the same amount
94 // of space as last time. Only resize if we're using less than a third of the
95 // allocated space, and leave enough for 50% growth over last time.
96 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
97 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
98 buffer->reset();
99 buffer->setReserve(reserve);
100 } else {
101 buffer->rewind();
102 }
103}
104
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000105enum {
106 kTraceCmdBit = 0x80,
107 kCmdMask = 0x7f,
108};
109
bsalomon62c447d2014-08-08 08:08:50 -0700110static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000111
bsalomon62c447d2014-08-08 08:08:50 -0700112static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000113
bsalomon62c447d2014-08-08 08:08:50 -0700114static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000115
joshualitt9853cce2014-11-17 14:22:48 -0800116void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
joshualitt2e3b3e32014-12-09 13:31:14 -0800117 GrColor color,
joshualitt9853cce2014-11-17 14:22:48 -0800118 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000119 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000120 const SkMatrix* localMatrix) {
joshualitt9853cce2014-11-17 14:22:48 -0800121 GrDrawState::AutoRestoreEffects are(ds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000122
joshualittd27f73e2014-12-29 07:43:36 -0800123 // Go to device coords to allow batching across matrix changes
124 SkMatrix matrix = ds->getViewMatrix();
125 SkMatrix invert = SkMatrix::I();
126
127 // if we have a local rect, then we apply the localMatrix directly to the localRect to generate
128 // vertex local coords
joshualitt8fc6c2d2014-12-22 15:27:05 -0800129 bool hasExplicitLocalCoords = SkToBool(localRect);
joshualittd27f73e2014-12-29 07:43:36 -0800130 if (!hasExplicitLocalCoords) {
131 if (!matrix.isIdentity() && !matrix.invert(&invert)) {
132 SkDebugf("Could not invert\n");
133 return;
134 }
135
136 if (localMatrix) {
137 invert.preConcat(*localMatrix);
138 }
139 }
140
141 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCoords,
142 color,
143 &invert));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000144
joshualitt56995b52014-12-11 15:44:02 -0800145 size_t vstride = gp->getVertexStride();
joshualitt2dd1ae02014-12-03 06:24:10 -0800146 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
147 0));
148 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000149 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700150 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000151 return;
152 }
153
jvanverth@google.com39768252013-02-14 15:25:44 +0000154 // 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 +0000155 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
156 // the vertex positions then we have to account for the view matrix change.
joshualittd27f73e2014-12-29 07:43:36 -0800157 GrDrawState::AutoViewMatrixRestore avmr(ds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000158
egdaniel7b3d5ee2014-08-28 05:41:14 -0700159 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
160 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000161
162 SkRect devBounds;
163 // since we already computed the dev verts, set the bounds hint. This will help us avoid
164 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700165 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000166
bsalomon49f085d2014-09-05 13:34:00 -0700167 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700168 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
169 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000170 coords->setRectFan(localRect->fLeft, localRect->fTop,
171 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700172 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700173 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700174 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000175 }
176 }
177
bsalomon62c447d2014-08-08 08:08:50 -0700178 static const int kColorOffset = sizeof(SkPoint);
179 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
180 for (int i = 0; i < 4; ++i) {
181 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700182 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000183 }
184
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000185 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualitt56995b52014-12-11 15:44:02 -0800186 this->drawIndexedInstances(ds, gp, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000187}
188
joshualitt54e0c122014-11-19 09:38:51 -0800189int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700190 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000191 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000192
bsalomon@google.com934c5702012-03-20 21:17:58 +0000193 const GeometrySrcState& geomSrc = this->getGeomSrc();
194
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000195 // we only attempt to concat the case when reserved verts are used with a client-specified index
196 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
197 // between draws.
198 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
199 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
200 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000201 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000202 // Check if there is a draw info that is compatible that uses the same VB from the pool and
203 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700204 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000205 return 0;
206 }
207
cdalton6819df32014-10-15 13:43:48 -0700208 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000209
cdalton6819df32014-10-15 13:43:48 -0700210 if (!draw->fInfo.isInstanced() ||
211 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
212 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800213 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800214 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000215 return 0;
216 }
bsalomon371bcbc2014-12-01 08:19:34 -0800217 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000218 return 0;
219 }
220
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000221 // how many instances can be concat'ed onto draw given the size of the index buffer
222 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700223 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000224 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000225
cdalton6819df32014-10-15 13:43:48 -0700226 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000227
228 // update last fGpuCmdMarkers to include any additional trace markers that have been added
229 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700230 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000231 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
232 } else {
233 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700234 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000235 }
236 }
237
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000238 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000239}
240
joshualitt9853cce2014-11-17 14:22:48 -0800241void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800242 const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800243 const DrawInfo& info,
bsalomon3e791242014-12-17 13:43:13 -0800244 const GrScissorState& scissorState,
joshualitt9176e2c2014-11-20 07:28:52 -0800245 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800246 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
247
joshualitt56995b52014-12-11 15:44:02 -0800248 if (!this->recordStateAndShouldDraw(ds, gp, NULL,
joshualitt2e3b3e32014-12-09 13:31:14 -0800249 GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualitt9176e2c2014-11-20 07:28:52 -0800250 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800251 return;
252 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000253
bsalomonb3e3a952014-09-19 11:10:40 -0700254 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000255 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800256 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000257 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800258 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700259 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000260 } else {
261 return;
262 }
263 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800264 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000265 }
cdalton6819df32014-10-15 13:43:48 -0700266 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000267}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000268
joshualitt9853cce2014-11-17 14:22:48 -0800269void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800270 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800271 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800272 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800273 const GrStencilSettings& stencilSettings) {
bsalomon3e791242014-12-17 13:43:13 -0800274 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
275 (path, ds.getRenderTarget()));
276 sp->fScissor = scissorState;
277 sp->fUseHWAA = ds.isHWAntialias();
278 sp->fViewMatrix = ds.getViewMatrix();
279 sp->fStencil = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700280 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000281}
282
joshualitt9853cce2014-11-17 14:22:48 -0800283void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800284 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800285 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800286 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800287 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700288 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000289 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt56995b52014-12-11 15:44:02 -0800290 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType,
291 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800292 return;
293 }
cdalton6819df32014-10-15 13:43:48 -0700294 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800295 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700296 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000297}
298
joshualitt9853cce2014-11-17 14:22:48 -0800299void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800300 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800301 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800302 const void* indices,
303 PathIndexType indexType,
304 const float transformValues[],
305 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800306 int count,
bsalomon3e791242014-12-17 13:43:13 -0800307 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800308 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700309 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700310 SkASSERT(pathRange);
311 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800312 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000313
joshualitt56995b52014-12-11 15:44:02 -0800314 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType, scissorState,
joshualitt2e3b3e32014-12-09 13:31:14 -0800315 dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800316 return;
317 }
cdalton6819df32014-10-15 13:43:48 -0700318
cdalton55b24af2014-11-25 11:00:56 -0800319 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
320 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
321 // Add padding to the index buffer so the indices are aligned properly.
322 fPathIndexBuffer.append(indexBytes - misalign);
323 }
324
325 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
326 reinterpret_cast<const char*>(indices));
327 float* savedTransforms = fPathTransformBuffer.append(
328 count * GrPathRendering::PathTransformSize(transformType),
329 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700330
cdalton3fc6a2f2014-11-13 11:54:20 -0800331 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
332 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800333 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800334 // equivalent to two separate draw calls if there is overlap. Blending won't work,
335 // and the combined calls may also cancel each other's winding numbers in some
336 // places. For now the winding numbers are only an issue if the fill is even/odd,
337 // because DrawPaths is currently only used for glyphs, and glyphs in the same
338 // font tend to all wind in the same direction.
339 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
340 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800341 indexType == previous->fIndexType &&
342 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800343 stencilSettings == previous->fStencilSettings &&
344 path_fill_type_is_winding(stencilSettings) &&
joshualitt56995b52014-12-11 15:44:02 -0800345 !ds.willBlendWithDst(pathProc)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800346 // Fold this DrawPaths call into the one previous.
347 previous->fCount += count;
348 return;
349 }
350 }
351
352 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
bsalomonef3fcd82014-12-12 08:51:38 -0800353 dp->fIndicesLocation = SkToU32(savedIndices - fPathIndexBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800354 dp->fIndexType = indexType;
bsalomonef3fcd82014-12-12 08:51:38 -0800355 dp->fTransformsLocation = SkToU32(savedTransforms - fPathTransformBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800356 dp->fTransformType = transformType;
357 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800358 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700359
360 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000361}
362
bsalomon63b21962014-11-05 07:05:34 -0800363void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
364 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800365 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000366 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000367 if (NULL == rect) {
368 // We could do something smart and remove previous draws and clears to
369 // the current render target. If we get that smart we have to make sure
370 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000371 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000372 rect = &r;
373 }
cdalton6819df32014-10-15 13:43:48 -0700374 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000375 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000376 clr->fColor = color;
377 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000378 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700379 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000380}
381
joshualitt6db519c2014-10-29 08:48:18 -0700382void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
383 bool insideClip,
384 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800385 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700386 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
387 clr->fRect = rect;
388 clr->fInsideClip = insideClip;
389 this->recordTraceMarkersIfNecessary();
390}
391
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000392void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800393 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000394 if (!this->caps()->discardRenderTargetSupport()) {
395 return;
396 }
cdalton6819df32014-10-15 13:43:48 -0700397 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000398 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700399 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000400}
401
bsalomon371bcbc2014-12-01 08:19:34 -0800402void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700403 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800404 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800405 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
406 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000407 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000408}
409
bsalomon371bcbc2014-12-01 08:19:34 -0800410void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700411 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000412 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000413 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000414
reed@google.comac10a2d2010-12-22 21:39:39 +0000415
cdalton6819df32014-10-15 13:43:48 -0700416 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000417
cdalton6819df32014-10-15 13:43:48 -0700418 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700419
bsalomonae59b772014-11-19 08:23:49 -0800420 // Updated every time we find a set state cmd to reflect the current state in the playback
421 // stream.
joshualittdafa4d02014-12-04 08:59:10 -0800422 GrOptDrawState* currentOptState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800423
cdalton6819df32014-10-15 13:43:48 -0700424 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000425 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700426 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700427 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700428 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000429 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800430 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000431 ++currCmdMarker;
432 }
cdalton6819df32014-10-15 13:43:48 -0700433
joshualittd53a8272014-11-10 16:03:14 -0800434 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800435 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomon932f8662014-11-24 06:47:48 -0800436 currentOptState = &ss->fState;
joshualittdafa4d02014-12-04 08:59:10 -0800437 currentOptState->finalize(this->getGpu());
joshualittd53a8272014-11-10 16:03:14 -0800438 } else {
bsalomon932f8662014-11-24 06:47:48 -0800439 iter->execute(this, currentOptState);
joshualittd53a8272014-11-10 16:03:14 -0800440 }
cdalton6819df32014-10-15 13:43:48 -0700441
442 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800443 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000444 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000445 }
mtkleinf439c772014-10-14 14:29:30 -0700446
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000447 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000448 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000449}
450
cdalton3fc6a2f2014-11-13 11:54:20 -0800451void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800452 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800453 buf->getGpu()->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700454}
455
bsalomon3e791242014-12-17 13:43:13 -0800456void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
457 GrGpu::StencilPathState state;
458 state.fRenderTarget = fRenderTarget.get();
459 state.fScissor = &fScissor;
460 state.fStencil = &fStencil;
461 state.fUseHWAA = fUseHWAA;
462 state.fViewMatrix = &fViewMatrix;
463
464 buf->getGpu()->stencilPath(this->path(), state);
cdalton6819df32014-10-15 13:43:48 -0700465}
466
cdalton3fc6a2f2014-11-13 11:54:20 -0800467void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
468 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800469 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800470 buf->getGpu()->drawPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700471}
472
cdalton3fc6a2f2014-11-13 11:54:20 -0800473void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
474 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800475 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800476 buf->getGpu()->drawPaths(*optState, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800477 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
478 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
479 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700480}
481
bsalomon932f8662014-11-24 06:47:48 -0800482void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {}
cdalton6819df32014-10-15 13:43:48 -0700483
cdalton3fc6a2f2014-11-13 11:54:20 -0800484void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700485 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800486 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700487 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800488 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700489 }
490}
491
cdalton3fc6a2f2014-11-13 11:54:20 -0800492void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
493 const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800494 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700495}
496
cdalton3fc6a2f2014-11-13 11:54:20 -0800497void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800498 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700499}
500
bsalomonf90a02b2014-11-26 12:28:00 -0800501bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
502 GrSurface* src,
503 const SkIRect& srcRect,
504 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800505 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700506 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000507 cs->fSrcRect = srcRect;
508 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700509 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000510 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000511 }
bsalomonf90a02b2014-11-26 12:28:00 -0800512 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000513}
514
bsalomonae59b772014-11-19 08:23:49 -0800515bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800516 const GrGeometryProcessor* gp,
517 const GrPathProcessor* pathProc,
bsalomonae59b772014-11-19 08:23:49 -0800518 GrGpu::DrawType drawType,
bsalomon3e791242014-12-17 13:43:13 -0800519 const GrScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800520 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800521 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
joshualitt56995b52014-12-11 15:44:02 -0800522 (ds, gp, pathProc, *this->getGpu()->caps(), scissor,
joshualitt2e3b3e32014-12-09 13:31:14 -0800523 dstCopy, drawType));
bsalomon932f8662014-11-24 06:47:48 -0800524 if (ss->fState.mustSkip()) {
525 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800526 return false;
527 }
joshualitt9b989322014-12-15 14:16:27 -0800528 if (fPrevState && fPrevState->combineIfPossible(ss->fState)) {
bsalomon932f8662014-11-24 06:47:48 -0800529 fCmdBuffer.pop_back();
530 } else {
531 fPrevState = &ss->fState;
cdalton6819df32014-10-15 13:43:48 -0700532 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700533 }
bsalomonae59b772014-11-19 08:23:49 -0800534 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000535}
536
cdalton6819df32014-10-15 13:43:48 -0700537void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
538 SkASSERT(!fCmdBuffer.empty());
539 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700540 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
541 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700542 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700543 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700544 }
mtklein07894c42014-10-13 14:00:42 -0700545}