blob: 70d61ecfffba21ef67ab4c8bd1a8fdff53034770 [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) {
joshualitt8059eb92014-12-29 15:10:07 -080072 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *localMatrix,
73 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080074 } else {
joshualitt8059eb92014-12-29 15:10:07 -080075 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMatrix::I(),
76 GrColorIsOpaque(color));
joshualitt8fc6c2d2014-12-22 15:27:05 -080077 }
bsalomon62c447d2014-08-08 08:08:50 -070078}
robertphillips@google.com42903302013-04-20 12:26:07 +000079
cdalton3fc6a2f2014-11-13 11:54:20 -080080static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
81 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
82 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
83 if (isWinding) {
84 // Double check that it is in fact winding.
85 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
86 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
87 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
88 SkASSERT(!pathStencilSettings.isTwoSided());
89 }
90 return isWinding;
91}
92
93template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
94 // Assume the next time this buffer fills up it will use approximately the same amount
95 // of space as last time. Only resize if we're using less than a third of the
96 // allocated space, and leave enough for 50% growth over last time.
97 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
98 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
99 buffer->reset();
100 buffer->setReserve(reserve);
101 } else {
102 buffer->rewind();
103 }
104}
105
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000106enum {
107 kTraceCmdBit = 0x80,
108 kCmdMask = 0x7f,
109};
110
bsalomon62c447d2014-08-08 08:08:50 -0700111static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000112
bsalomon62c447d2014-08-08 08:08:50 -0700113static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000114
bsalomon62c447d2014-08-08 08:08:50 -0700115static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000116
egdaniel8dd688b2015-01-22 10:16:09 -0800117void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -0800118 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800119 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800120 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000121 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000122 const SkMatrix* localMatrix) {
egdaniel8dd688b2015-01-22 10:16:09 -0800123 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000124
joshualittd27f73e2014-12-29 07:43:36 -0800125 // Go to device coords to allow batching across matrix changes
joshualittd27f73e2014-12-29 07:43:36 -0800126 SkMatrix invert = SkMatrix::I();
127
128 // if we have a local rect, then we apply the localMatrix directly to the localRect to generate
129 // vertex local coords
joshualitt8fc6c2d2014-12-22 15:27:05 -0800130 bool hasExplicitLocalCoords = SkToBool(localRect);
joshualittd27f73e2014-12-29 07:43:36 -0800131 if (!hasExplicitLocalCoords) {
joshualitt8059eb92014-12-29 15:10:07 -0800132 if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
joshualittd27f73e2014-12-29 07:43:36 -0800133 SkDebugf("Could not invert\n");
134 return;
135 }
136
137 if (localMatrix) {
138 invert.preConcat(*localMatrix);
139 }
140 }
141
142 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCoords,
143 color,
144 &invert));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000145
joshualitt56995b52014-12-11 15:44:02 -0800146 size_t vstride = gp->getVertexStride();
joshualitt2dd1ae02014-12-03 06:24:10 -0800147 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
148 0));
149 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000150 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700151 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000152 return;
153 }
154
joshualitt8059eb92014-12-29 15:10:07 -0800155 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
156 viewMatrix.mapPointsWithStride(geo.positions(), vstride, 4);
157
jvanverth@google.com39768252013-02-14 15:25:44 +0000158 // 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 +0000159 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
joshualitt8059eb92014-12-29 15:10:07 -0800160 // the vertex positions then we have to account for the view matrix
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000161 SkRect devBounds;
joshualitt8059eb92014-12-29 15:10:07 -0800162
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000163 // 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());
egdaniel8dd688b2015-01-22 10:16:09 -0800186 this->drawIndexedInstances(pipelineBuilder, gp, kTriangles_GrPrimitiveType, 1, 4, 6,
187 &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000188}
189
egdaniel8dd688b2015-01-22 10:16:09 -0800190int GrInOrderDrawBuffer::concatInstancedDraw(const GrPipelineBuilder& pipelineBuilder,
191 const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700192 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000193 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000194
bsalomon@google.com934c5702012-03-20 21:17:58 +0000195 const GeometrySrcState& geomSrc = this->getGeomSrc();
196
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000197 // we only attempt to concat the case when reserved verts are used with a client-specified index
198 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
199 // between draws.
200 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
201 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
202 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000203 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000204 // Check if there is a draw info that is compatible that uses the same VB from the pool and
205 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700206 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000207 return 0;
208 }
209
cdalton6819df32014-10-15 13:43:48 -0700210 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000211
cdalton6819df32014-10-15 13:43:48 -0700212 if (!draw->fInfo.isInstanced() ||
213 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
214 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800215 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800216 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000217 return 0;
218 }
bsalomon371bcbc2014-12-01 08:19:34 -0800219 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000220 return 0;
221 }
222
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000223 // how many instances can be concat'ed onto draw given the size of the index buffer
224 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700225 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000226 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000227
cdalton6819df32014-10-15 13:43:48 -0700228 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000229
230 // update last fGpuCmdMarkers to include any additional trace markers that have been added
231 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700232 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000233 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
234 } else {
235 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700236 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000237 }
238 }
239
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000240 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000241}
242
egdaniel8dd688b2015-01-22 10:16:09 -0800243void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800244 const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800245 const DrawInfo& info,
bsalomon3e791242014-12-17 13:43:13 -0800246 const GrScissorState& scissorState,
joshualitt9176e2c2014-11-20 07:28:52 -0800247 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800248 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
249
egdaniel8dd688b2015-01-22 10:16:09 -0800250 if (!this->recordStateAndShouldDraw(pipelineBuilder, gp, 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()) {
egdaniel8dd688b2015-01-22 10:16:09 -0800256 int instancesConcated = this->concatInstancedDraw(pipelineBuilder, 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
egdaniel8dd688b2015-01-22 10:16:09 -0800269void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
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,
egdaniel8dd688b2015-01-22 10:16:09 -0800275 (path, pipelineBuilder.getRenderTarget()));
bsalomon3e791242014-12-17 13:43:13 -0800276 sp->fScissor = scissorState;
egdaniel8dd688b2015-01-22 10:16:09 -0800277 sp->fUseHWAA = pipelineBuilder.isHWAntialias();
joshualitt8059eb92014-12-29 15:10:07 -0800278 sp->fViewMatrix = pathProc->viewMatrix();
bsalomon3e791242014-12-17 13:43:13 -0800279 sp->fStencil = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700280 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000281}
282
egdaniel8dd688b2015-01-22 10:16:09 -0800283void GrInOrderDrawBuffer::onDrawPath(const GrPipelineBuilder& pipelineBuilder,
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) {
egdaniel8dd688b2015-01-22 10:16:09 -0800289 // TODO: Only compare the subset of GrPipelineBuilder relevant to path covering?
290 if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800291 return;
292 }
cdalton6819df32014-10-15 13:43:48 -0700293 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800294 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700295 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000296}
297
egdaniel8dd688b2015-01-22 10:16:09 -0800298void GrInOrderDrawBuffer::onDrawPaths(const GrPipelineBuilder& pipelineBuilder,
joshualitt56995b52014-12-11 15:44:02 -0800299 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800300 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800301 const void* indices,
302 PathIndexType indexType,
303 const float transformValues[],
304 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800305 int count,
bsalomon3e791242014-12-17 13:43:13 -0800306 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800307 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700308 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700309 SkASSERT(pathRange);
310 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800311 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000312
egdaniel8dd688b2015-01-22 10:16:09 -0800313 if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800314 return;
315 }
cdalton6819df32014-10-15 13:43:48 -0700316
cdalton55b24af2014-11-25 11:00:56 -0800317 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
318 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
319 // Add padding to the index buffer so the indices are aligned properly.
320 fPathIndexBuffer.append(indexBytes - misalign);
321 }
322
323 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
324 reinterpret_cast<const char*>(indices));
325 float* savedTransforms = fPathTransformBuffer.append(
326 count * GrPathRendering::PathTransformSize(transformType),
327 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700328
cdalton3fc6a2f2014-11-13 11:54:20 -0800329 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
330 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800331 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800332 // equivalent to two separate draw calls if there is overlap. Blending won't work,
333 // and the combined calls may also cancel each other's winding numbers in some
334 // places. For now the winding numbers are only an issue if the fill is even/odd,
335 // because DrawPaths is currently only used for glyphs, and glyphs in the same
336 // font tend to all wind in the same direction.
337 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
338 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800339 indexType == previous->fIndexType &&
340 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800341 stencilSettings == previous->fStencilSettings &&
342 path_fill_type_is_winding(stencilSettings) &&
egdaniel8dd688b2015-01-22 10:16:09 -0800343 !pipelineBuilder.willBlendWithDst(pathProc)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800344 // Fold this DrawPaths call into the one previous.
345 previous->fCount += count;
346 return;
347 }
348 }
349
350 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
bsalomonef3fcd82014-12-12 08:51:38 -0800351 dp->fIndicesLocation = SkToU32(savedIndices - fPathIndexBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800352 dp->fIndexType = indexType;
bsalomonef3fcd82014-12-12 08:51:38 -0800353 dp->fTransformsLocation = SkToU32(savedTransforms - fPathTransformBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800354 dp->fTransformType = transformType;
355 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800356 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700357
358 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000359}
360
bsalomon63b21962014-11-05 07:05:34 -0800361void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
362 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800363 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000364 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000365 if (NULL == rect) {
366 // We could do something smart and remove previous draws and clears to
367 // the current render target. If we get that smart we have to make sure
368 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000369 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000370 rect = &r;
371 }
cdalton6819df32014-10-15 13:43:48 -0700372 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000373 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000374 clr->fColor = color;
375 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000376 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700377 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000378}
379
joshualitt6db519c2014-10-29 08:48:18 -0700380void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
381 bool insideClip,
382 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800383 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700384 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
385 clr->fRect = rect;
386 clr->fInsideClip = insideClip;
387 this->recordTraceMarkersIfNecessary();
388}
389
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000390void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800391 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000392 if (!this->caps()->discardRenderTargetSupport()) {
393 return;
394 }
cdalton6819df32014-10-15 13:43:48 -0700395 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000396 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700397 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000398}
399
bsalomon371bcbc2014-12-01 08:19:34 -0800400void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700401 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800402 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800403 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
404 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000405 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000406}
407
bsalomon371bcbc2014-12-01 08:19:34 -0800408void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700409 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000410 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000411 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000412
reed@google.comac10a2d2010-12-22 21:39:39 +0000413
cdalton6819df32014-10-15 13:43:48 -0700414 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000415
cdalton6819df32014-10-15 13:43:48 -0700416 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700417
bsalomonae59b772014-11-19 08:23:49 -0800418 // Updated every time we find a set state cmd to reflect the current state in the playback
419 // stream.
joshualitt873ad0e2015-01-20 09:08:51 -0800420 SetState* currentState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800421
cdalton6819df32014-10-15 13:43:48 -0700422 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000423 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700424 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700425 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700426 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000427 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800428 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000429 ++currCmdMarker;
430 }
cdalton6819df32014-10-15 13:43:48 -0700431
joshualittd53a8272014-11-10 16:03:14 -0800432 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800433 SetState* ss = reinterpret_cast<SetState*>(iter.get());
joshualitt873ad0e2015-01-20 09:08:51 -0800434
egdaniel8dd688b2015-01-22 10:16:09 -0800435 this->getGpu()->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor, ss->fPipeline,
436 ss->fPipeline.descInfo(), ss->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800437 currentState = ss;
438
joshualittd53a8272014-11-10 16:03:14 -0800439 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800440 iter->execute(this, currentState);
joshualittd53a8272014-11-10 16:03:14 -0800441 }
cdalton6819df32014-10-15 13:43:48 -0700442
443 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800444 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000445 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000446 }
mtkleinf439c772014-10-14 14:29:30 -0700447
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000448 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000449 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000450}
451
joshualitt873ad0e2015-01-20 09:08:51 -0800452void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
453 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800454 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800455 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800456 buf->getGpu()->draw(args, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700457}
458
joshualitt873ad0e2015-01-20 09:08:51 -0800459void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon3e791242014-12-17 13:43:13 -0800460 GrGpu::StencilPathState state;
461 state.fRenderTarget = fRenderTarget.get();
462 state.fScissor = &fScissor;
463 state.fStencil = &fStencil;
464 state.fUseHWAA = fUseHWAA;
465 state.fViewMatrix = &fViewMatrix;
466
467 buf->getGpu()->stencilPath(this->path(), state);
cdalton6819df32014-10-15 13:43:48 -0700468}
469
joshualitt873ad0e2015-01-20 09:08:51 -0800470void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
471 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800472 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800473 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800474 buf->getGpu()->drawPath(args, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700475}
476
joshualitt873ad0e2015-01-20 09:08:51 -0800477void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
478 SkASSERT(state);
egdaniel8dd688b2015-01-22 10:16:09 -0800479 DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
joshualitt17e73142015-01-21 11:52:36 -0800480 &state->fBatchTracker);
joshualitt873ad0e2015-01-20 09:08:51 -0800481 buf->getGpu()->drawPaths(args, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800482 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
483 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
484 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700485}
486
joshualitt873ad0e2015-01-20 09:08:51 -0800487void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const SetState*) {}
cdalton6819df32014-10-15 13:43:48 -0700488
joshualitt873ad0e2015-01-20 09:08:51 -0800489void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const SetState*) {
cdalton6819df32014-10-15 13:43:48 -0700490 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800491 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700492 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800493 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700494 }
495}
496
joshualitt873ad0e2015-01-20 09:08:51 -0800497void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800498 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700499}
500
joshualitt873ad0e2015-01-20 09:08:51 -0800501void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const SetState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800502 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700503}
504
bsalomonf90a02b2014-11-26 12:28:00 -0800505bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
506 GrSurface* src,
507 const SkIRect& srcRect,
508 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800509 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700510 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000511 cs->fSrcRect = srcRect;
512 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700513 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000514 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000515 }
bsalomonf90a02b2014-11-26 12:28:00 -0800516 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000517}
518
egdaniel8dd688b2015-01-22 10:16:09 -0800519bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipelineBuilder,
joshualitt71c92602015-01-14 08:12:47 -0800520 const GrPrimitiveProcessor* primProc,
bsalomon3e791242014-12-17 13:43:13 -0800521 const GrScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800522 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800523 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
egdaniel8dd688b2015-01-22 10:16:09 -0800524 (pipelineBuilder, primProc, *this->getGpu()->caps(),
525 scissor, dstCopy));
526 if (ss->fPipeline.mustSkip()) {
bsalomon932f8662014-11-24 06:47:48 -0800527 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800528 return false;
529 }
joshualitt873ad0e2015-01-20 09:08:51 -0800530
531 ss->fPrimitiveProcessor->initBatchTracker(&ss->fBatchTracker,
egdaniel8dd688b2015-01-22 10:16:09 -0800532 ss->fPipeline.getInitBatchTracker());
joshualitt873ad0e2015-01-20 09:08:51 -0800533
534 if (fPrevState &&
535 fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker,
536 *ss->fPrimitiveProcessor,
537 ss->fBatchTracker) &&
egdaniel8dd688b2015-01-22 10:16:09 -0800538 fPrevState->fPipeline.isEqual(ss->fPipeline)) {
bsalomon932f8662014-11-24 06:47:48 -0800539 fCmdBuffer.pop_back();
540 } else {
joshualitt873ad0e2015-01-20 09:08:51 -0800541 fPrevState = ss;
cdalton6819df32014-10-15 13:43:48 -0700542 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700543 }
bsalomonae59b772014-11-19 08:23:49 -0800544 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000545}
546
cdalton6819df32014-10-15 13:43:48 -0700547void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
548 SkASSERT(!fCmdBuffer.empty());
549 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700550 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
551 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700552 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700553 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700554 }
mtklein07894c42014-10-13 14:00:42 -0700555}