blob: 6e5c1fe778d7b19d140a277c746e62868a52ad7e [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
joshualitt8fc6c2d2014-12-22 15:27:05 -0800123 bool hasExplicitLocalCoords = SkToBool(localRect);
124 SkAutoTUnref<const GrGeometryProcessor> gp(
125 create_rect_gp(hasExplicitLocalCoords,
126 color,
127 hasExplicitLocalCoords ? NULL : localMatrix));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000128
joshualitt56995b52014-12-11 15:44:02 -0800129 size_t vstride = gp->getVertexStride();
joshualitt2dd1ae02014-12-03 06:24:10 -0800130 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
131 0));
132 AutoReleaseGeometry geo(this, 4, vstride, 0);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000133 if (!geo.succeeded()) {
tfarina38406c82014-10-31 07:11:12 -0700134 SkDebugf("Failed to get space for vertices!\n");
bsalomon@google.com934c5702012-03-20 21:17:58 +0000135 return;
136 }
137
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000138 // Go to device coords to allow batching across matrix changes
joshualitt9853cce2014-11-17 14:22:48 -0800139 SkMatrix matrix = ds->getViewMatrix();
bsalomon01c8da12014-08-04 09:21:30 -0700140
jvanverth@google.com39768252013-02-14 15:25:44 +0000141 // 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 +0000142 // modify that stage's matrix. Otherwise if the effect is generating its source rect from
143 // the vertex positions then we have to account for the view matrix change.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000144 GrDrawState::AutoViewMatrixRestore avmr;
joshualitt9853cce2014-11-17 14:22:48 -0800145 if (!avmr.setIdentity(ds)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000146 return;
147 }
148
egdaniel7b3d5ee2014-08-28 05:41:14 -0700149 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
150 matrix.mapPointsWithStride(geo.positions(), vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000151
152 SkRect devBounds;
153 // since we already computed the dev verts, set the bounds hint. This will help us avoid
154 // unnecessary clipping in our onDraw().
egdaniel7b3d5ee2014-08-28 05:41:14 -0700155 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000156
bsalomon49f085d2014-09-05 13:34:00 -0700157 if (localRect) {
bsalomon62c447d2014-08-08 08:08:50 -0700158 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
159 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000160 coords->setRectFan(localRect->fLeft, localRect->fTop,
161 localRect->fRight, localRect->fBottom,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700162 vstride);
bsalomon49f085d2014-09-05 13:34:00 -0700163 if (localMatrix) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700164 localMatrix->mapPointsWithStride(coords, vstride, 4);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000165 }
166 }
167
bsalomon62c447d2014-08-08 08:08:50 -0700168 static const int kColorOffset = sizeof(SkPoint);
169 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
170 for (int i = 0; i < 4; ++i) {
171 *vertColor = color;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700172 vertColor = (GrColor*) ((intptr_t) vertColor + vstride);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000173 }
174
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000175 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
joshualitt56995b52014-12-11 15:44:02 -0800176 this->drawIndexedInstances(ds, gp, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000177}
178
joshualitt54e0c122014-11-19 09:38:51 -0800179int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawInfo& info) {
cdalton6819df32014-10-15 13:43:48 -0700180 SkASSERT(!fCmdBuffer.empty());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000181 SkASSERT(info.isInstanced());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000182
bsalomon@google.com934c5702012-03-20 21:17:58 +0000183 const GeometrySrcState& geomSrc = this->getGeomSrc();
184
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000185 // we only attempt to concat the case when reserved verts are used with a client-specified index
186 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
187 // between draws.
188 if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
189 kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
190 return 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000191 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000192 // Check if there is a draw info that is compatible that uses the same VB from the pool and
193 // the same IB
cdalton6819df32014-10-15 13:43:48 -0700194 if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000195 return 0;
196 }
197
cdalton6819df32014-10-15 13:43:48 -0700198 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000199
cdalton6819df32014-10-15 13:43:48 -0700200 if (!draw->fInfo.isInstanced() ||
201 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
202 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
bsalomon371bcbc2014-12-01 08:19:34 -0800203 draw->fInfo.vertexBuffer() != info.vertexBuffer() ||
joshualitt54e0c122014-11-19 09:38:51 -0800204 draw->fInfo.indexBuffer() != geomSrc.fIndexBuffer) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000205 return 0;
206 }
bsalomon371bcbc2014-12-01 08:19:34 -0800207 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVertex()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000208 return 0;
209 }
210
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000211 // how many instances can be concat'ed onto draw given the size of the index buffer
212 int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
cdalton6819df32014-10-15 13:43:48 -0700213 instancesToConcat -= draw->fInfo.instanceCount();
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000214 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000215
cdalton6819df32014-10-15 13:43:48 -0700216 draw->fInfo.adjustInstanceCount(instancesToConcat);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000217
218 // update last fGpuCmdMarkers to include any additional trace markers that have been added
219 if (this->getActiveTraceMarkers().count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700220 if (cmd_has_trace_marker(draw->fType)) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000221 fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
222 } else {
223 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
cdalton6819df32014-10-15 13:43:48 -0700224 draw->fType = add_trace_bit(draw->fType);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000225 }
226 }
227
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000228 return instancesToConcat;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000229}
230
joshualitt9853cce2014-11-17 14:22:48 -0800231void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800232 const GrGeometryProcessor* gp,
joshualitt9853cce2014-11-17 14:22:48 -0800233 const DrawInfo& info,
bsalomon3e791242014-12-17 13:43:13 -0800234 const GrScissorState& scissorState,
joshualitt9176e2c2014-11-20 07:28:52 -0800235 const GrDeviceCoordTexture* dstCopy) {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800236 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
237
joshualitt56995b52014-12-11 15:44:02 -0800238 if (!this->recordStateAndShouldDraw(ds, gp, NULL,
joshualitt2e3b3e32014-12-09 13:31:14 -0800239 GrGpu::PrimTypeToDrawType(info.primitiveType()),
joshualitt9176e2c2014-11-20 07:28:52 -0800240 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800241 return;
242 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000243
bsalomonb3e3a952014-09-19 11:10:40 -0700244 Draw* draw;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000245 if (info.isInstanced()) {
joshualitt54e0c122014-11-19 09:38:51 -0800246 int instancesConcated = this->concatInstancedDraw(ds, info);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000247 if (info.instanceCount() > instancesConcated) {
joshualitt54e0c122014-11-19 09:38:51 -0800248 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
cdalton6819df32014-10-15 13:43:48 -0700249 draw->fInfo.adjustInstanceCount(-instancesConcated);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000250 } else {
251 return;
252 }
253 } else {
joshualitt54e0c122014-11-19 09:38:51 -0800254 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000255 }
cdalton6819df32014-10-15 13:43:48 -0700256 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000257}
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000258
joshualitt9853cce2014-11-17 14:22:48 -0800259void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800260 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800261 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800262 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800263 const GrStencilSettings& stencilSettings) {
bsalomon3e791242014-12-17 13:43:13 -0800264 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
265 (path, ds.getRenderTarget()));
266 sp->fScissor = scissorState;
267 sp->fUseHWAA = ds.isHWAntialias();
268 sp->fViewMatrix = ds.getViewMatrix();
269 sp->fStencil = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700270 this->recordTraceMarkersIfNecessary();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000271}
272
joshualitt9853cce2014-11-17 14:22:48 -0800273void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800274 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800275 const GrPath* path,
bsalomon3e791242014-12-17 13:43:13 -0800276 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800277 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700278 const GrDeviceCoordTexture* dstCopy) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000279 // TODO: Only compare the subset of GrDrawState relevant to path covering?
joshualitt56995b52014-12-11 15:44:02 -0800280 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType,
281 scissorState, dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800282 return;
283 }
cdalton6819df32014-10-15 13:43:48 -0700284 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
joshualitt2c93efe2014-11-06 12:57:13 -0800285 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700286 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000287}
288
joshualitt9853cce2014-11-17 14:22:48 -0800289void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800290 const GrPathProcessor* pathProc,
joshualitt9853cce2014-11-17 14:22:48 -0800291 const GrPathRange* pathRange,
cdalton55b24af2014-11-25 11:00:56 -0800292 const void* indices,
293 PathIndexType indexType,
294 const float transformValues[],
295 PathTransformType transformType,
joshualitt2c93efe2014-11-06 12:57:13 -0800296 int count,
bsalomon3e791242014-12-17 13:43:13 -0800297 const GrScissorState& scissorState,
joshualitt2c93efe2014-11-06 12:57:13 -0800298 const GrStencilSettings& stencilSettings,
joshualitt92e496f2014-10-31 13:56:50 -0700299 const GrDeviceCoordTexture* dstCopy) {
bsalomon49f085d2014-09-05 13:34:00 -0700300 SkASSERT(pathRange);
301 SkASSERT(indices);
cdalton55b24af2014-11-25 11:00:56 -0800302 SkASSERT(transformValues);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000303
joshualitt56995b52014-12-11 15:44:02 -0800304 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_DrawType, scissorState,
joshualitt2e3b3e32014-12-09 13:31:14 -0800305 dstCopy)) {
bsalomonae59b772014-11-19 08:23:49 -0800306 return;
307 }
cdalton6819df32014-10-15 13:43:48 -0700308
cdalton55b24af2014-11-25 11:00:56 -0800309 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
310 if (int misalign = fPathIndexBuffer.count() % indexBytes) {
311 // Add padding to the index buffer so the indices are aligned properly.
312 fPathIndexBuffer.append(indexBytes - misalign);
313 }
314
315 char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
316 reinterpret_cast<const char*>(indices));
317 float* savedTransforms = fPathTransformBuffer.append(
318 count * GrPathRendering::PathTransformSize(transformType),
319 transformValues);
cdalton6819df32014-10-15 13:43:48 -0700320
cdalton3fc6a2f2014-11-13 11:54:20 -0800321 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
322 // The previous command was also DrawPaths. Try to collapse this call into the one
bsalomon371bcbc2014-12-01 08:19:34 -0800323 // before. Note that stenciling all the paths at once, then covering, may not be
cdalton3fc6a2f2014-11-13 11:54:20 -0800324 // equivalent to two separate draw calls if there is overlap. Blending won't work,
325 // and the combined calls may also cancel each other's winding numbers in some
326 // places. For now the winding numbers are only an issue if the fill is even/odd,
327 // because DrawPaths is currently only used for glyphs, and glyphs in the same
328 // font tend to all wind in the same direction.
329 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
330 if (pathRange == previous->pathRange() &&
cdalton55b24af2014-11-25 11:00:56 -0800331 indexType == previous->fIndexType &&
332 transformType == previous->fTransformType &&
cdalton3fc6a2f2014-11-13 11:54:20 -0800333 stencilSettings == previous->fStencilSettings &&
334 path_fill_type_is_winding(stencilSettings) &&
joshualitt56995b52014-12-11 15:44:02 -0800335 !ds.willBlendWithDst(pathProc)) {
cdalton3fc6a2f2014-11-13 11:54:20 -0800336 // Fold this DrawPaths call into the one previous.
337 previous->fCount += count;
338 return;
339 }
340 }
341
342 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
bsalomonef3fcd82014-12-12 08:51:38 -0800343 dp->fIndicesLocation = SkToU32(savedIndices - fPathIndexBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800344 dp->fIndexType = indexType;
bsalomonef3fcd82014-12-12 08:51:38 -0800345 dp->fTransformsLocation = SkToU32(savedTransforms - fPathTransformBuffer.begin());
cdalton55b24af2014-11-25 11:00:56 -0800346 dp->fTransformType = transformType;
347 dp->fCount = count;
joshualitt2c93efe2014-11-06 12:57:13 -0800348 dp->fStencilSettings = stencilSettings;
cdalton6819df32014-10-15 13:43:48 -0700349
350 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000351}
352
bsalomon63b21962014-11-05 07:05:34 -0800353void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
354 bool canIgnoreRect, GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800355 SkASSERT(renderTarget);
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000356 SkIRect r;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000357 if (NULL == rect) {
358 // We could do something smart and remove previous draws and clears to
359 // the current render target. If we get that smart we have to make sure
360 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000361 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000362 rect = &r;
363 }
cdalton6819df32014-10-15 13:43:48 -0700364 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000365 GrColorIsPMAssert(color);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000366 clr->fColor = color;
367 clr->fRect = *rect;
robertphillips@google.com56ce48a2013-10-31 21:44:25 +0000368 clr->fCanIgnoreRect = canIgnoreRect;
cdalton6819df32014-10-15 13:43:48 -0700369 this->recordTraceMarkersIfNecessary();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000370}
371
joshualitt6db519c2014-10-29 08:48:18 -0700372void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
373 bool insideClip,
374 GrRenderTarget* renderTarget) {
joshualitt9853cce2014-11-17 14:22:48 -0800375 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700376 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
377 clr->fRect = rect;
378 clr->fInsideClip = insideClip;
379 this->recordTraceMarkersIfNecessary();
380}
381
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000382void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800383 SkASSERT(renderTarget);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000384 if (!this->caps()->discardRenderTargetSupport()) {
385 return;
386 }
cdalton6819df32014-10-15 13:43:48 -0700387 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000388 clr->fColor = GrColor_ILLEGAL;
cdalton6819df32014-10-15 13:43:48 -0700389 this->recordTraceMarkersIfNecessary();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000390}
391
bsalomon371bcbc2014-12-01 08:19:34 -0800392void GrInOrderDrawBuffer::onReset() {
cdalton6819df32014-10-15 13:43:48 -0700393 fCmdBuffer.reset();
bsalomon932f8662014-11-24 06:47:48 -0800394 fPrevState = NULL;
cdalton3fc6a2f2014-11-13 11:54:20 -0800395 reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
396 reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000397 fGpuCmdMarkers.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000398}
399
bsalomon371bcbc2014-12-01 08:19:34 -0800400void GrInOrderDrawBuffer::onFlush() {
cdalton6819df32014-10-15 13:43:48 -0700401 if (fCmdBuffer.empty()) {
robertphillips@google.com1267fbd2013-07-03 18:37:27 +0000402 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000403 }
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000404
reed@google.comac10a2d2010-12-22 21:39:39 +0000405
cdalton6819df32014-10-15 13:43:48 -0700406 CmdBuffer::Iter iter(fCmdBuffer);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000407
cdalton6819df32014-10-15 13:43:48 -0700408 int currCmdMarker = 0;
cdalton6819df32014-10-15 13:43:48 -0700409
bsalomonae59b772014-11-19 08:23:49 -0800410 // Updated every time we find a set state cmd to reflect the current state in the playback
411 // stream.
joshualittdafa4d02014-12-04 08:59:10 -0800412 GrOptDrawState* currentOptState = NULL;
joshualittd53a8272014-11-10 16:03:14 -0800413
cdalton6819df32014-10-15 13:43:48 -0700414 while (iter.next()) {
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000415 GrGpuTraceMarker newMarker("", -1);
egdanield78a1682014-07-09 10:41:26 -0700416 SkString traceString;
cdalton6819df32014-10-15 13:43:48 -0700417 if (cmd_has_trace_marker(iter->fType)) {
egdanield78a1682014-07-09 10:41:26 -0700418 traceString = fGpuCmdMarkers[currCmdMarker].toString();
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000419 newMarker.fMarker = traceString.c_str();
bsalomon371bcbc2014-12-01 08:19:34 -0800420 this->getGpu()->addGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000421 ++currCmdMarker;
422 }
cdalton6819df32014-10-15 13:43:48 -0700423
joshualittd53a8272014-11-10 16:03:14 -0800424 if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
joshualitt9853cce2014-11-17 14:22:48 -0800425 SetState* ss = reinterpret_cast<SetState*>(iter.get());
bsalomon932f8662014-11-24 06:47:48 -0800426 currentOptState = &ss->fState;
joshualittdafa4d02014-12-04 08:59:10 -0800427 currentOptState->finalize(this->getGpu());
joshualittd53a8272014-11-10 16:03:14 -0800428 } else {
bsalomon932f8662014-11-24 06:47:48 -0800429 iter->execute(this, currentOptState);
joshualittd53a8272014-11-10 16:03:14 -0800430 }
cdalton6819df32014-10-15 13:43:48 -0700431
432 if (cmd_has_trace_marker(iter->fType)) {
bsalomon371bcbc2014-12-01 08:19:34 -0800433 this->getGpu()->removeGpuTraceMarker(&newMarker);
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000434 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000435 }
mtkleinf439c772014-10-14 14:29:30 -0700436
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +0000437 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
commit-bot@chromium.orga8916ff2013-08-16 15:53:46 +0000438 ++fDrawID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000439}
440
cdalton3fc6a2f2014-11-13 11:54:20 -0800441void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800442 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800443 buf->getGpu()->draw(*optState, fInfo);
cdalton6819df32014-10-15 13:43:48 -0700444}
445
bsalomon3e791242014-12-17 13:43:13 -0800446void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
447 GrGpu::StencilPathState state;
448 state.fRenderTarget = fRenderTarget.get();
449 state.fScissor = &fScissor;
450 state.fStencil = &fStencil;
451 state.fUseHWAA = fUseHWAA;
452 state.fViewMatrix = &fViewMatrix;
453
454 buf->getGpu()->stencilPath(this->path(), state);
cdalton6819df32014-10-15 13:43:48 -0700455}
456
cdalton3fc6a2f2014-11-13 11:54:20 -0800457void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
458 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800459 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800460 buf->getGpu()->drawPath(*optState, this->path(), fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700461}
462
cdalton3fc6a2f2014-11-13 11:54:20 -0800463void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
464 const GrOptDrawState* optState) {
bsalomon932f8662014-11-24 06:47:48 -0800465 SkASSERT(optState);
bsalomon371bcbc2014-12-01 08:19:34 -0800466 buf->getGpu()->drawPaths(*optState, this->pathRange(),
cdalton55b24af2014-11-25 11:00:56 -0800467 &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
468 &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
469 fCount, fStencilSettings);
cdalton6819df32014-10-15 13:43:48 -0700470}
471
bsalomon932f8662014-11-24 06:47:48 -0800472void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {}
cdalton6819df32014-10-15 13:43:48 -0700473
cdalton3fc6a2f2014-11-13 11:54:20 -0800474void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
cdalton6819df32014-10-15 13:43:48 -0700475 if (GrColor_ILLEGAL == fColor) {
bsalomon371bcbc2014-12-01 08:19:34 -0800476 buf->getGpu()->discard(this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700477 } else {
bsalomon371bcbc2014-12-01 08:19:34 -0800478 buf->getGpu()->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
cdalton6819df32014-10-15 13:43:48 -0700479 }
480}
481
cdalton3fc6a2f2014-11-13 11:54:20 -0800482void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
483 const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800484 buf->getGpu()->clearStencilClip(fRect, fInsideClip, this->renderTarget());
joshualitt6db519c2014-10-29 08:48:18 -0700485}
486
cdalton3fc6a2f2014-11-13 11:54:20 -0800487void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
bsalomon371bcbc2014-12-01 08:19:34 -0800488 buf->getGpu()->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
cdalton6819df32014-10-15 13:43:48 -0700489}
490
bsalomonf90a02b2014-11-26 12:28:00 -0800491bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
492 GrSurface* src,
493 const SkIRect& srcRect,
494 const SkIPoint& dstPoint) {
bsalomon371bcbc2014-12-01 08:19:34 -0800495 if (getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) {
cdalton6819df32014-10-15 13:43:48 -0700496 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
bsalomon@google.com116ad842013-04-09 15:38:19 +0000497 cs->fSrcRect = srcRect;
498 cs->fDstPoint = dstPoint;
cdalton6819df32014-10-15 13:43:48 -0700499 this->recordTraceMarkersIfNecessary();
bsalomon@google.com116ad842013-04-09 15:38:19 +0000500 return true;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000501 }
bsalomonf90a02b2014-11-26 12:28:00 -0800502 return false;
bsalomon@google.com116ad842013-04-09 15:38:19 +0000503}
504
bsalomonae59b772014-11-19 08:23:49 -0800505bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
joshualitt56995b52014-12-11 15:44:02 -0800506 const GrGeometryProcessor* gp,
507 const GrPathProcessor* pathProc,
bsalomonae59b772014-11-19 08:23:49 -0800508 GrGpu::DrawType drawType,
bsalomon3e791242014-12-17 13:43:13 -0800509 const GrScissorState& scissor,
bsalomonae59b772014-11-19 08:23:49 -0800510 const GrDeviceCoordTexture* dstCopy) {
bsalomon932f8662014-11-24 06:47:48 -0800511 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
joshualitt56995b52014-12-11 15:44:02 -0800512 (ds, gp, pathProc, *this->getGpu()->caps(), scissor,
joshualitt2e3b3e32014-12-09 13:31:14 -0800513 dstCopy, drawType));
bsalomon932f8662014-11-24 06:47:48 -0800514 if (ss->fState.mustSkip()) {
515 fCmdBuffer.pop_back();
bsalomonae59b772014-11-19 08:23:49 -0800516 return false;
517 }
joshualitt9b989322014-12-15 14:16:27 -0800518 if (fPrevState && fPrevState->combineIfPossible(ss->fState)) {
bsalomon932f8662014-11-24 06:47:48 -0800519 fCmdBuffer.pop_back();
520 } else {
521 fPrevState = &ss->fState;
cdalton6819df32014-10-15 13:43:48 -0700522 this->recordTraceMarkersIfNecessary();
bsalomon838f62d2014-08-05 07:15:57 -0700523 }
bsalomonae59b772014-11-19 08:23:49 -0800524 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000525}
526
cdalton6819df32014-10-15 13:43:48 -0700527void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
528 SkASSERT(!fCmdBuffer.empty());
529 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
mtkleinf439c772014-10-14 14:29:30 -0700530 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
531 if (activeTraceMarkers.count() > 0) {
cdalton6819df32014-10-15 13:43:48 -0700532 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
mtkleinf439c772014-10-14 14:29:30 -0700533 fGpuCmdMarkers.push_back(activeTraceMarkers);
mtklein07894c42014-10-13 14:00:42 -0700534 }
mtklein07894c42014-10-13 14:00:42 -0700535}