blob: 3c7b14677ba9523fca69d5dc483a643810eeb57b [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 */
65static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
joshualitt5478d422014-11-14 16:00:38 -080066 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType |
67 GrDefaultGeoProcFactory::kColor_GPType;
68 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0;
joshualitt2dd1ae02014-12-03 06:24:10 -080069 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(flags))->unref();
bsalomon62c447d2014-08-08 08:08:50 -070070 if (0xFF == GrColorUnpackA(color)) {
71 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
72 }
73}
robertphillips@google.com42903302013-04-20 12:26:07 +000074
cdalton3fc6a2f2014-11-13 11:54:20 -080075static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
76 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
77 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
78 if (isWinding) {
79 // Double check that it is in fact winding.
80 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
81 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
82 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
83 SkASSERT(!pathStencilSettings.isTwoSided());
84 }
85 return isWinding;
86}
87
88template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
89 // Assume the next time this buffer fills up it will use approximately the same amount
90 // of space as last time. Only resize if we're using less than a third of the
91 // allocated space, and leave enough for 50% growth over last time.
92 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
93 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
94 buffer->reset();
95 buffer->setReserve(reserve);
96 } else {
97 buffer->rewind();
98 }
99}
100
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000101enum {
102 kTraceCmdBit = 0x80,
103 kCmdMask = 0x7f,
104};
105
bsalomon62c447d2014-08-08 08:08:50 -0700106static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000107
bsalomon62c447d2014-08-08 08:08:50 -0700108static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000109
bsalomon62c447d2014-08-08 08:08:50 -0700110static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000111
joshualitt9853cce2014-11-17 14:22:48 -0800112void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
113 const SkRect& rect,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000114 const SkRect* localRect,
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000115 const SkMatrix* localMatrix) {
joshualitt9853cce2014-11-17 14:22:48 -0800116 GrDrawState::AutoRestoreEffects are(ds);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000117
joshualitt9853cce2014-11-17 14:22:48 -0800118 GrColor color = ds->getColor();
119 set_vertex_attributes(ds, SkToBool(localRect), color);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000120
joshualitt2dd1ae02014-12-03 06:24:10 -0800121 size_t vstride = ds->getGeometryProcessor()->getVertexStride();
122 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
123 0));
124 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000125 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700126 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000127 return;
128 }
129
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000130 // Go to device coords to allow batching across matrix changes
joshualitt9853cce2014-11-17 14:22:48 -0800131 SkMatrix matrix = ds->getViewMatrix();
bsalomon01c8da12014-08-04 09:21:30 -0700132
jvanverth@google.com39768252013-02-14 15:25:44 +0000133 // 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 +0000134 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
135 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000136 GrDrawState::AutoViewMatrixRestore avmr;
joshualitt9853cce2014-11-17 14:22:48 -0800137 if (!avmr.setIdentity(ds)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000138 return;
139 }
140
egdaniel7b3d5ee2014-08-28 05:41:14 -0700141 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
142 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000143
144 SkRect devBounds;
145 // since we already computed the dev verts, set the bounds hint. This will help us avoid
146 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700147 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000148
bsalomon49f085d2014-09-05 13:34:00 -0700149 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700150 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
151 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000152 coords->setRectFan(localRect->fLeft, localRect->fTop,
153 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700154 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700155 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700156 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000157 }
158 }
159
bsalomon62c447d2014-08-08 08:08:50 -0700160 static const int kColorOffset = sizeof(SkPoint);
161 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
162 for (int i = 0; i < 4; ++i) {
163 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700164 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000165 }
166
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000167 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualitt9853cce2014-11-17 14:22:48 -0800168 this->drawIndexedInstances(ds, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000169}
170
joshualitt54e0c122014-11-19 09:38:51 -0800171int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700172 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000173 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000174
bsalomon@google.com934c5702012-03-20 21:17:58 +0000175 const GeometrySrcState& geomSrc = this->getGeomSrc();
176
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000177 // we only attempt to concat the case when reserved verts are used with a client-specified index
178 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
179 // between draws.
180 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
181 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
182 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000183 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000184 // Check if there is a draw info that is compatible that uses the same VB from the pool and
185 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700186 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000187 return 0;
188 }
189
cdalton6819df32014-10-15 13:43:48 -0700190 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000191
cdalton6819df32014-10-15 13:43:48 -0700192 if (!draw->fInfo.isInstanced() ||
193 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
194 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800195 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800196 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000197 return 0;
198 }
bsalomon371bcbc2014-12-01 08:19:34 -0800199 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000200 return 0;
201 }
202
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000203 // how many instances can be concat'ed onto draw given the size of the index buffer
204 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700205 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000206 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000207
cdalton6819df32014-10-15 13:43:48 -0700208 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000209
210 // update last fGpuCmdMarkers to include any additional trace markers that have been added
211 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700212 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000213 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
214 } else {
215 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700216 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000217 }
218 }
219
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000220 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000221}
222
joshualitt9853cce2014-11-17 14:22:48 -0800223void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
224 const DrawInfo& info,
joshualitt9176e2c2014-11-20 07:28:52 -0800225 const ScissorState& scissorState,
226 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800227 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
228
bsalomonae59b772014-11-19 08:23:49 -0800229 if (!this->recordStateAndShouldDraw(ds, GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualitt9176e2c2014-11-20 07:28:52 -0800230 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800231 return;
232 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000233
bsalomonb3e3a952014-09-19 11:10:40 -0700234 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000235 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800236 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000237 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800238 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700239 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000240 } else {
241 return;
242 }
243 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800244 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000245 }
cdalton6819df32014-10-15 13:43:48 -0700246 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000247}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000248
joshualitt9853cce2014-11-17 14:22:48 -0800249void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
250 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800251 const GrClipMaskManager::ScissorState& scissorState,
252 const GrStencilSettings& stencilSettings) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000253 // Only compare the subset of GrDrawState relevant to path stenciling?
joshualitt54e0c122014-11-19 09:38:51 -0800254 if (!this->recordStateAndShouldDraw(ds, GrGpu::kStencilPath_DrawType, scissorState, NULL)) {
bsalomonae59b772014-11-19 08:23:49 -0800255 return;
256 }
cdalton6819df32014-10-15 13:43:48 -0700257 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800258 sp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700259 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000260}
261
joshualitt9853cce2014-11-17 14:22:48 -0800262void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
263 const GrPath* path,
joshualitt2c93efe2014-11-06 12:57:13 -0800264 const GrClipMaskManager::ScissorState& scissorState,
265 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700266 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000267 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt54e0c122014-11-19 09:38:51 -0800268 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800269 return;
270 }
cdalton6819df32014-10-15 13:43:48 -0700271 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800272 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700273 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000274}
275
joshualitt9853cce2014-11-17 14:22:48 -0800276void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
277 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800278 const void* indices,
279 PathIndexType indexType,
280 const float transformValues[],
281 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800282 int count,
joshualitt2c93efe2014-11-06 12:57:13 -0800283 const GrClipMaskManager::ScissorState& scissorState,
284 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700285 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700286 SkASSERT(pathRange);
287 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800288 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000289
joshualitt54e0c122014-11-19 09:38:51 -0800290 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800291 return;
292 }
cdalton6819df32014-10-15 13:43:48 -0700293
cdalton55b24af2014-11-25 11:00:56 -0800294 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
295 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
296 // Add padding to the index buffer so the indices are aligned properly.
297 fPathIndexBuffer.append(indexBytes - misalign);
298 }
299
300 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
301 reinterpret_cast<const char*>(indices));
302 float* savedTransforms = fPathTransformBuffer.append(
303 count * GrPathRendering::PathTransformSize(transformType),
304 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700305
cdalton3fc6a2f2014-11-13 11:54:20 -0800306 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
307 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800308 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800309 // equivalent to two separate draw calls if there is overlap. Blending won't work,
310 // and the combined calls may also cancel each other's winding numbers in some
311 // places. For now the winding numbers are only an issue if the fill is even/odd,
312 // because DrawPaths is currently only used for glyphs, and glyphs in the same
313 // font tend to all wind in the same direction.
314 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
315 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800316 indexType == previous->fIndexType &&
317 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800318 stencilSettings == previous->fStencilSettings &&
319 path_fill_type_is_winding(stencilSettings) &&
joshualitt9853cce2014-11-17 14:22:48 -0800320 !ds.willBlendWithDst()) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800321 // Fold this DrawPaths call into the one previous.
322 previous->fCount += count;
323 return;
324 }
325 }
326
327 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
328 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800329 dp->fIndexType = indexType;
cdalton3fc6a2f2014-11-13 11:54:20 -0800330 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
cdalton55b24af2014-11-25 11:00:56 -0800331 dp->fTransformType = transformType;
332 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800333 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700334
335 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000336}
337
bsalomon63b21962014-11-05 07:05:34 -0800338void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
339 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800340 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000341 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000342 if (NULL == rect) {
343 // We could do something smart and remove previous draws and clears to
344 // the current render target. If we get that smart we have to make sure
345 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000346 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000347 rect = &r;
348 }
cdalton6819df32014-10-15 13:43:48 -0700349 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000350 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000351 clr->fColor = color;
352 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000353 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700354 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000355}
356
joshualitt6db519c2014-10-29 08:48:18 -0700357void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
358 bool insideClip,
359 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800360 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700361 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
362 clr->fRect = rect;
363 clr->fInsideClip = insideClip;
364 this->recordTraceMarkersIfNecessary();
365}
366
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000367void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800368 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000369 if (!this->caps()->discardRenderTargetSupport()) {
370 return;
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 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700374 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000375}
376
bsalomon371bcbc2014-12-01 08:19:34 -0800377void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700378 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800379 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800380 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
381 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000382 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000383}
384
bsalomon371bcbc2014-12-01 08:19:34 -0800385void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700386 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000387 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000388 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000389
reed@google.comac10a2d2010-12-22 21:39:39 +0000390
cdalton6819df32014-10-15 13:43:48 -0700391 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000392
cdalton6819df32014-10-15 13:43:48 -0700393 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700394
bsalomonae59b772014-11-19 08:23:49 -0800395 // Updated every time we find a set state cmd to reflect the current state in the playback
396 // stream.
joshualittdafa4d02014-12-04 08:59:10 -0800397 GrOptDrawState* currentOptState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800398
cdalton6819df32014-10-15 13:43:48 -0700399 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000400 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700401 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700402 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700403 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000404 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800405 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000406 ++currCmdMarker;
407 }
cdalton6819df32014-10-15 13:43:48 -0700408
joshualittd53a8272014-11-10 16:03:14 -0800409 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800410 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomon932f8662014-11-24 06:47:48 -0800411 currentOptState = &ss->fState;
joshualittdafa4d02014-12-04 08:59:10 -0800412 currentOptState->finalize(this->getGpu());
joshualittd53a8272014-11-10 16:03:14 -0800413 } else {
bsalomon932f8662014-11-24 06:47:48 -0800414 iter->execute(this, currentOptState);
joshualittd53a8272014-11-10 16:03:14 -0800415 }
cdalton6819df32014-10-15 13:43:48 -0700416
417 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800418 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000419 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000420 }
mtkleinf439c772014-10-14 14:29:30 -0700421
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000422 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000423 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000424}
425
cdalton3fc6a2f2014-11-13 11:54:20 -0800426void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800427 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800428 buf->getGpu()->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700429}
430
cdalton3fc6a2f2014-11-13 11:54:20 -0800431void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
432 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800433 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800434 buf->getGpu()->stencilPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700435}
436
cdalton3fc6a2f2014-11-13 11:54:20 -0800437void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
438 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800439 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800440 buf->getGpu()->drawPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700441}
442
cdalton3fc6a2f2014-11-13 11:54:20 -0800443void GrInOrderDrawBuffer::DrawPaths::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()->drawPaths(*optState, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800447 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
448 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
449 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700450}
451
bsalomon932f8662014-11-24 06:47:48 -0800452void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {}
cdalton6819df32014-10-15 13:43:48 -0700453
cdalton3fc6a2f2014-11-13 11:54:20 -0800454void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700455 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800456 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700457 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800458 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700459 }
460}
461
cdalton3fc6a2f2014-11-13 11:54:20 -0800462void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
463 const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800464 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700465}
466
cdalton3fc6a2f2014-11-13 11:54:20 -0800467void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800468 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700469}
470
bsalomonf90a02b2014-11-26 12:28:00 -0800471bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
472 GrSurface* src,
473 const SkIRect& srcRect,
474 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800475 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700476 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000477 cs->fSrcRect = srcRect;
478 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700479 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000480 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000481 }
bsalomonf90a02b2014-11-26 12:28:00 -0800482 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000483}
484
bsalomonae59b772014-11-19 08:23:49 -0800485bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
486 GrGpu::DrawType drawType,
joshualitt54e0c122014-11-19 09:38:51 -0800487 const GrClipMaskManager::ScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800488 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800489 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
joshualittdafa4d02014-12-04 08:59:10 -0800490 (ds, *this->getGpu()->caps(), scissor, dstCopy,
491 drawType));
bsalomon932f8662014-11-24 06:47:48 -0800492 if (ss->fState.mustSkip()) {
493 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800494 return false;
495 }
bsalomon932f8662014-11-24 06:47:48 -0800496 if (fPrevState && *fPrevState == ss->fState) {
497 fCmdBuffer.pop_back();
498 } else {
499 fPrevState = &ss->fState;
cdalton6819df32014-10-15 13:43:48 -0700500 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700501 }
bsalomonae59b772014-11-19 08:23:49 -0800502 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000503}
504
cdalton6819df32014-10-15 13:43:48 -0700505void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
506 SkASSERT(!fCmdBuffer.empty());
507 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700508 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
509 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700510 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700511 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700512 }
mtklein07894c42014-10-13 14:00:42 -0700513}