| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrTargetCommands.h" |
| 9 |
| 10 #include "GrColor.h" |
| 11 #include "GrDefaultGeoProcFactory.h" |
| 8 #include "GrInOrderDrawBuffer.h" | 12 #include "GrInOrderDrawBuffer.h" |
| 9 | |
| 10 #include "GrBufferAllocPool.h" | |
| 11 #include "GrDefaultGeoProcFactory.h" | |
| 12 #include "GrDrawTargetCaps.h" | |
| 13 #include "GrGpu.h" | |
| 14 #include "GrTemplates.h" | 13 #include "GrTemplates.h" |
| 15 #include "GrFontCache.h" | 14 #include "SkPoint.h" |
| 16 #include "GrTexture.h" | |
| 17 | |
| 18 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu, | |
| 19 GrVertexBufferAllocPool* vertexPool, | |
| 20 GrIndexBufferAllocPool* indexPool) | |
| 21 : INHERITED(gpu, vertexPool, indexPool) | |
| 22 , fCommands(gpu, vertexPool, indexPool) | |
| 23 , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4) | |
| 24 , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4) | |
| 25 , fDrawID(0) { | |
| 26 | |
| 27 SkASSERT(vertexPool); | |
| 28 SkASSERT(indexPool); | |
| 29 } | |
| 30 | |
| 31 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { | |
| 32 this->reset(); | |
| 33 } | |
| 34 | 15 |
| 35 void GrTargetCommands::closeBatch() { | 16 void GrTargetCommands::closeBatch() { |
| 36 if (fDrawBatch) { | 17 if (fDrawBatch) { |
| 37 fBatchTarget.resetNumberOfDraws(); | 18 fBatchTarget.resetNumberOfDraws(); |
| 38 fDrawBatch->execute(NULL, fPrevState); | 19 fDrawBatch->execute(NULL, fPrevState); |
| 39 fDrawBatch->fBatch->setNumberOfDraws(fBatchTarget.numberOfDraws()); | 20 fDrawBatch->fBatch->setNumberOfDraws(fBatchTarget.numberOfDraws()); |
| 40 fDrawBatch = NULL; | 21 fDrawBatch = NULL; |
| 41 } | 22 } |
| 42 } | 23 } |
| 43 | 24 |
| 44 //////////////////////////////////////////////////////////////////////////////// | |
| 45 | |
| 46 /** We always use per-vertex colors so that rects can be batched across color ch
anges. Sometimes we | |
| 47 have explicit local coords and sometimes not. We *could* always provide expl
icit local coords | |
| 48 and just duplicate the positions when the caller hasn't provided a local coo
rd rect, but we | |
| 49 haven't seen a use case which frequently switches between local rect and no
local rect draws. | |
| 50 | |
| 51 The color param is used to determine whether the opaque hint can be set on t
he draw state. | |
| 52 The caller must populate the vertex colors itself. | |
| 53 | |
| 54 The vertex attrib order is always pos, color, [local coords]. | |
| 55 */ | |
| 56 static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords, | |
| 57 GrColor color, | |
| 58 const SkMatrix* localMatrix) { | |
| 59 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | | |
| 60 GrDefaultGeoProcFactory::kColor_GPType; | |
| 61 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPTyp
e : 0; | |
| 62 if (localMatrix) { | |
| 63 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *loc
alMatrix, | |
| 64 GrColorIsOpaque(color)); | |
| 65 } else { | |
| 66 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMa
trix::I(), | |
| 67 GrColorIsOpaque(color)); | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin
gs) { | 25 static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin
gs) { |
| 72 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Fa
ce; | 26 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Fa
ce; |
| 73 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); | 27 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); |
| 74 if (isWinding) { | 28 if (isWinding) { |
| 75 // Double check that it is in fact winding. | 29 // Double check that it is in fact winding. |
| 76 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace)); | 30 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace)); |
| 77 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace)); | 31 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace)); |
| 78 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace)); | 32 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace)); |
| 79 SkASSERT(!pathStencilSettings.isTwoSided()); | 33 SkASSERT(!pathStencilSettings.isTwoSided()); |
| 80 } | 34 } |
| 81 return isWinding; | 35 return isWinding; |
| 82 } | 36 } |
| 83 | 37 |
| 84 class RectBatch : public GrBatch { | |
| 85 public: | |
| 86 struct Geometry { | |
| 87 GrColor fColor; | |
| 88 SkMatrix fViewMatrix; | |
| 89 SkRect fRect; | |
| 90 bool fHasLocalRect; | |
| 91 bool fHasLocalMatrix; | |
| 92 SkRect fLocalRect; | |
| 93 SkMatrix fLocalMatrix; | |
| 94 }; | |
| 95 | |
| 96 static GrBatch* Create(const Geometry& geometry) { | |
| 97 return SkNEW_ARGS(RectBatch, (geometry)); | |
| 98 } | |
| 99 | |
| 100 const char* name() const SK_OVERRIDE { return "RectBatch"; } | |
| 101 | |
| 102 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { | |
| 103 // When this is called on a batch, there is only one geometry bundle | |
| 104 out->setKnownFourComponents(fGeoData[0].fColor); | |
| 105 } | |
| 106 | |
| 107 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID
E { | |
| 108 out->setKnownSingleComponent(0xff); | |
| 109 } | |
| 110 | |
| 111 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { | |
| 112 // Handle any color overrides | |
| 113 if (init.fColorIgnored) { | |
| 114 fGeoData[0].fColor = GrColor_ILLEGAL; | |
| 115 } else if (GrColor_ILLEGAL != init.fOverrideColor) { | |
| 116 fGeoData[0].fColor = init.fOverrideColor; | |
| 117 } | |
| 118 | |
| 119 // setup batch properties | |
| 120 fBatch.fColorIgnored = init.fColorIgnored; | |
| 121 fBatch.fColor = fGeoData[0].fColor; | |
| 122 fBatch.fUsesLocalCoords = init.fUsesLocalCoords; | |
| 123 fBatch.fCoverageIgnored = init.fCoverageIgnored; | |
| 124 } | |
| 125 | |
| 126 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
) SK_OVERRIDE { | |
| 127 // Go to device coords to allow batching across matrix changes | |
| 128 SkMatrix invert = SkMatrix::I(); | |
| 129 | |
| 130 // if we have a local rect, then we apply the localMatrix directly to th
e localRect to | |
| 131 // generate vertex local coords | |
| 132 bool hasExplicitLocalCoords = this->hasLocalRect(); | |
| 133 if (!hasExplicitLocalCoords) { | |
| 134 if (!this->viewMatrix().isIdentity() && !this->viewMatrix().invert(&
invert)) { | |
| 135 SkDebugf("Could not invert\n"); | |
| 136 return; | |
| 137 } | |
| 138 | |
| 139 if (this->hasLocalMatrix()) { | |
| 140 invert.preConcat(this->localMatrix()); | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLoc
alCoords, | |
| 145 this->color(), | |
| 146 &invert)); | |
| 147 | |
| 148 batchTarget->initDraw(gp, pipeline); | |
| 149 | |
| 150 // TODO this is hacky, but the only way we have to initialize the GP is
to use the | |
| 151 // GrPipelineInfo struct so we can generate the correct shader. Once we
have GrBatch | |
| 152 // everywhere we can remove this nastiness | |
| 153 GrPipelineInfo init; | |
| 154 init.fColorIgnored = fBatch.fColorIgnored; | |
| 155 init.fOverrideColor = GrColor_ILLEGAL; | |
| 156 init.fCoverageIgnored = fBatch.fCoverageIgnored; | |
| 157 init.fUsesLocalCoords = this->usesLocalCoords(); | |
| 158 gp->initBatchTracker(batchTarget->currentBatchTracker(), init); | |
| 159 | |
| 160 size_t vertexStride = gp->getVertexStride(); | |
| 161 | |
| 162 SkASSERT(hasExplicitLocalCoords ? | |
| 163 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo
calCoordAttr) : | |
| 164 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt
tr)); | |
| 165 | |
| 166 int instanceCount = fGeoData.count(); | |
| 167 int vertexCount = kVertsPerRect * instanceCount; | |
| 168 | |
| 169 const GrVertexBuffer* vertexBuffer; | |
| 170 int firstVertex; | |
| 171 | |
| 172 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, | |
| 173 vertexCount, | |
| 174 &vertexBuffer, | |
| 175 &firstVertex); | |
| 176 | |
| 177 for (int i = 0; i < instanceCount; i++) { | |
| 178 const Geometry& args = fGeoData[i]; | |
| 179 | |
| 180 intptr_t offset = GrTCast<intptr_t>(vertices) + kVertsPerRect * i *
vertexStride; | |
| 181 SkPoint* positions = GrTCast<SkPoint*>(offset); | |
| 182 | |
| 183 positions->setRectFan(args.fRect.fLeft, args.fRect.fTop, | |
| 184 args.fRect.fRight, args.fRect.fBottom, vertexS
tride); | |
| 185 args.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVerts
PerRect); | |
| 186 | |
| 187 if (args.fHasLocalRect) { | |
| 188 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor
); | |
| 189 SkPoint* coords = GrTCast<SkPoint*>(offset + kLocalOffset); | |
| 190 coords->setRectFan(args.fLocalRect.fLeft, args.fLocalRect.fTop, | |
| 191 args.fLocalRect.fRight, args.fLocalRect.fBott
om, | |
| 192 vertexStride); | |
| 193 if (args.fHasLocalMatrix) { | |
| 194 args.fLocalMatrix.mapPointsWithStride(coords, vertexStride,
kVertsPerRect); | |
| 195 } | |
| 196 } | |
| 197 | |
| 198 static const int kColorOffset = sizeof(SkPoint); | |
| 199 GrColor* vertColor = GrTCast<GrColor*>(offset + kColorOffset); | |
| 200 for (int j = 0; j < 4; ++j) { | |
| 201 *vertColor = args.fColor; | |
| 202 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer(); | |
| 207 | |
| 208 GrDrawTarget::DrawInfo drawInfo; | |
| 209 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType); | |
| 210 drawInfo.setStartVertex(0); | |
| 211 drawInfo.setStartIndex(0); | |
| 212 drawInfo.setVerticesPerInstance(kVertsPerRect); | |
| 213 drawInfo.setIndicesPerInstance(kIndicesPerRect); | |
| 214 drawInfo.adjustStartVertex(firstVertex); | |
| 215 drawInfo.setVertexBuffer(vertexBuffer); | |
| 216 drawInfo.setIndexBuffer(quadIndexBuffer); | |
| 217 | |
| 218 int maxInstancesPerDraw = quadIndexBuffer->maxQuads(); | |
| 219 while (instanceCount) { | |
| 220 drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw)
); | |
| 221 drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.vertices
PerInstance()); | |
| 222 drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPe
rInstance()); | |
| 223 | |
| 224 batchTarget->draw(drawInfo); | |
| 225 | |
| 226 drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCoun
t()); | |
| 227 instanceCount -= drawInfo.instanceCount(); | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 232 | |
| 233 private: | |
| 234 RectBatch(const Geometry& geometry) { | |
| 235 this->initClassID<RectBatch>(); | |
| 236 fGeoData.push_back(geometry); | |
| 237 } | |
| 238 | |
| 239 GrColor color() const { return fBatch.fColor; } | |
| 240 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | |
| 241 bool colorIgnored() const { return fBatch.fColorIgnored; } | |
| 242 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
| 243 const SkMatrix& localMatrix() const { return fGeoData[0].fLocalMatrix; } | |
| 244 bool hasLocalRect() const { return fGeoData[0].fHasLocalRect; } | |
| 245 bool hasLocalMatrix() const { return fGeoData[0].fHasLocalMatrix; } | |
| 246 | |
| 247 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { | |
| 248 RectBatch* that = t->cast<RectBatch>(); | |
| 249 | |
| 250 if (this->hasLocalRect() != that->hasLocalRect()) { | |
| 251 return false; | |
| 252 } | |
| 253 | |
| 254 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | |
| 255 if (!this->hasLocalRect() && this->usesLocalCoords()) { | |
| 256 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { | |
| 257 return false; | |
| 258 } | |
| 259 | |
| 260 if (this->hasLocalMatrix() != that->hasLocalMatrix()) { | |
| 261 return false; | |
| 262 } | |
| 263 | |
| 264 if (this->hasLocalMatrix() && !this->localMatrix().cheapEqualTo(that
->localMatrix())) { | |
| 265 return false; | |
| 266 } | |
| 267 } | |
| 268 | |
| 269 if (this->color() != that->color()) { | |
| 270 fBatch.fColor = GrColor_ILLEGAL; | |
| 271 } | |
| 272 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | |
| 273 return true; | |
| 274 } | |
| 275 | |
| 276 struct BatchTracker { | |
| 277 GrColor fColor; | |
| 278 bool fUsesLocalCoords; | |
| 279 bool fColorIgnored; | |
| 280 bool fCoverageIgnored; | |
| 281 }; | |
| 282 | |
| 283 const static int kVertsPerRect = 4; | |
| 284 const static int kIndicesPerRect = 6; | |
| 285 | |
| 286 BatchTracker fBatch; | |
| 287 SkSTArray<1, Geometry, true> fGeoData; | |
| 288 }; | |
| 289 | |
| 290 void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder, | |
| 291 GrColor color, | |
| 292 const SkMatrix& viewMatrix, | |
| 293 const SkRect& rect, | |
| 294 const SkRect* localRect, | |
| 295 const SkMatrix* localMatrix) { | |
| 296 RectBatch::Geometry geometry; | |
| 297 geometry.fColor = color; | |
| 298 geometry.fViewMatrix = viewMatrix; | |
| 299 geometry.fRect = rect; | |
| 300 | |
| 301 if (localRect) { | |
| 302 geometry.fHasLocalRect = true; | |
| 303 geometry.fLocalRect = *localRect; | |
| 304 } else { | |
| 305 geometry.fHasLocalRect = false; | |
| 306 } | |
| 307 | |
| 308 if (localMatrix) { | |
| 309 geometry.fHasLocalMatrix = true; | |
| 310 geometry.fLocalMatrix = *localMatrix; | |
| 311 } else { | |
| 312 geometry.fHasLocalMatrix = false; | |
| 313 } | |
| 314 | |
| 315 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry)); | |
| 316 | |
| 317 SkRect bounds = rect; | |
| 318 viewMatrix.mapRect(&bounds); | |
| 319 this->drawBatch(pipelineBuilder, batch, &bounds); | |
| 320 } | |
| 321 | |
| 322 int GrTargetCommands::concatInstancedDraw(GrInOrderDrawBuffer* iodb, | 38 int GrTargetCommands::concatInstancedDraw(GrInOrderDrawBuffer* iodb, |
| 323 const GrDrawTarget::DrawInfo& info) { | 39 const GrDrawTarget::DrawInfo& info) { |
| 324 SkASSERT(!fCmdBuffer.empty()); | 40 SkASSERT(!fCmdBuffer.empty()); |
| 325 SkASSERT(info.isInstanced()); | 41 SkASSERT(info.isInstanced()); |
| 326 | 42 |
| 327 const GrIndexBuffer* ib; | 43 const GrIndexBuffer* ib; |
| 328 if (!iodb->canConcatToIndexBuffer(&ib)) { | 44 if (!iodb->canConcatToIndexBuffer(&ib)) { |
| 329 return 0; | 45 return 0; |
| 330 } | 46 } |
| 331 | 47 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 354 instancesToConcat -= draw->fInfo.instanceCount(); | 70 instancesToConcat -= draw->fInfo.instanceCount(); |
| 355 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount()); | 71 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount()); |
| 356 | 72 |
| 357 draw->fInfo.adjustInstanceCount(instancesToConcat); | 73 draw->fInfo.adjustInstanceCount(instancesToConcat); |
| 358 | 74 |
| 359 // update last fGpuCmdMarkers to include any additional trace markers that h
ave been added | 75 // update last fGpuCmdMarkers to include any additional trace markers that h
ave been added |
| 360 iodb->recordTraceMarkersIfNecessary(draw); | 76 iodb->recordTraceMarkersIfNecessary(draw); |
| 361 return instancesToConcat; | 77 return instancesToConcat; |
| 362 } | 78 } |
| 363 | 79 |
| 364 void GrInOrderDrawBuffer::onDraw(const GrGeometryProcessor* gp, | |
| 365 const DrawInfo& info, | |
| 366 const PipelineInfo& pipelineInfo) { | |
| 367 GrTargetCommands::Cmd* cmd = fCommands.recordDraw(this, gp, info, pipelineIn
fo); | |
| 368 this->recordTraceMarkersIfNecessary(cmd); | |
| 369 } | |
| 370 | |
| 371 GrTargetCommands::Cmd* GrTargetCommands::recordDraw( | 80 GrTargetCommands::Cmd* GrTargetCommands::recordDraw( |
| 372 GrInOrderDrawBuffer* iodb, | 81 GrInOrderDrawBuffer* iodb, |
| 373 const GrGeometryProcessor* gp, | 82 const GrGeometryProcessor* gp, |
| 374 const GrDrawTarget::DrawInfo&
info, | 83 const GrDrawTarget::DrawInfo&
info, |
| 375 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | 84 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { |
| 376 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer())); | 85 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer())); |
| 377 this->closeBatch(); | 86 this->closeBatch(); |
| 378 | 87 |
| 379 if (!this->setupPipelineAndShouldDraw(iodb, gp, pipelineInfo)) { | 88 if (!this->setupPipelineAndShouldDraw(iodb, gp, pipelineInfo)) { |
| 380 return NULL; | 89 return NULL; |
| 381 } | 90 } |
| 382 | 91 |
| 383 Draw* draw; | 92 Draw* draw; |
| 384 if (info.isInstanced()) { | 93 if (info.isInstanced()) { |
| 385 int instancesConcated = this->concatInstancedDraw(iodb, info); | 94 int instancesConcated = this->concatInstancedDraw(iodb, info); |
| 386 if (info.instanceCount() > instancesConcated) { | 95 if (info.instanceCount() > instancesConcated) { |
| 387 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | 96 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); |
| 388 draw->fInfo.adjustInstanceCount(-instancesConcated); | 97 draw->fInfo.adjustInstanceCount(-instancesConcated); |
| 389 } else { | 98 } else { |
| 390 return NULL; | 99 return NULL; |
| 391 } | 100 } |
| 392 } else { | 101 } else { |
| 393 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | 102 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); |
| 394 } | 103 } |
| 395 | 104 |
| 396 return draw; | 105 return draw; |
| 397 } | 106 } |
| 398 | 107 |
| 399 void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch, | |
| 400 const PipelineInfo& pipelineInfo) { | |
| 401 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipeline
Info); | |
| 402 this->recordTraceMarkersIfNecessary(cmd); | |
| 403 } | |
| 404 | |
| 405 GrTargetCommands::Cmd* GrTargetCommands::recordDrawBatch( | 108 GrTargetCommands::Cmd* GrTargetCommands::recordDrawBatch( |
| 406 GrInOrderDrawBuffer* iodb, | 109 GrInOrderDrawBuffer* iodb, |
| 407 GrBatch* batch, | 110 GrBatch* batch, |
| 408 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | 111 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { |
| 409 if (!this->setupPipelineAndShouldDraw(iodb, batch, pipelineInfo)) { | 112 if (!this->setupPipelineAndShouldDraw(iodb, batch, pipelineInfo)) { |
| 410 return NULL; | 113 return NULL; |
| 411 } | 114 } |
| 412 | 115 |
| 413 // Check if there is a Batch Draw we can batch with | 116 // Check if there is a Batch Draw we can batch with |
| 414 if (Cmd::kDrawBatch_Cmd != fCmdBuffer.back().type() || !fDrawBatch) { | 117 if (Cmd::kDrawBatch_Cmd != fCmdBuffer.back().type() || !fDrawBatch) { |
| 415 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch, &fB
atchTarget)); | 118 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch, &fB
atchTarget)); |
| 416 return fDrawBatch; | 119 return fDrawBatch; |
| 417 } | 120 } |
| 418 | 121 |
| 419 SkASSERT(&fCmdBuffer.back() == fDrawBatch); | 122 SkASSERT(&fCmdBuffer.back() == fDrawBatch); |
| 420 if (!fDrawBatch->fBatch->combineIfPossible(batch)) { | 123 if (!fDrawBatch->fBatch->combineIfPossible(batch)) { |
| 421 this->closeBatch(); | 124 this->closeBatch(); |
| 422 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch, &fB
atchTarget)); | 125 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch, &fB
atchTarget)); |
| 423 } | 126 } |
| 424 | 127 |
| 425 return fDrawBatch; | 128 return fDrawBatch; |
| 426 } | 129 } |
| 427 | 130 |
| 428 void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder
, | |
| 429 const GrPathProcessor* pathProc, | |
| 430 const GrPath* path, | |
| 431 const GrScissorState& scissorState, | |
| 432 const GrStencilSettings& stencilSettings
) { | |
| 433 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuild
er, | |
| 434 pathProc, path, sci
ssorState, | |
| 435 stencilSettings); | |
| 436 this->recordTraceMarkersIfNecessary(cmd); | |
| 437 } | |
| 438 | |
| 439 GrTargetCommands::Cmd* GrTargetCommands::recordStencilPath( | 131 GrTargetCommands::Cmd* GrTargetCommands::recordStencilPath( |
| 440 GrInOrderDrawBuffer* iod
b, | 132 GrInOrderDrawBuffer* iod
b, |
| 441 const GrPipelineBuilder&
pipelineBuilder, | 133 const GrPipelineBuilder&
pipelineBuilder, |
| 442 const GrPathProcessor* p
athProc, | 134 const GrPathProcessor* p
athProc, |
| 443 const GrPath* path, | 135 const GrPath* path, |
| 444 const GrScissorState& sc
issorState, | 136 const GrScissorState& sc
issorState, |
| 445 const GrStencilSettings&
stencilSettings) { | 137 const GrStencilSettings&
stencilSettings) { |
| 446 this->closeBatch(); | 138 this->closeBatch(); |
| 447 | 139 |
| 448 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, | 140 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, |
| 449 (path, pipelineBuilder.getRenderT
arget())); | 141 (path, pipelineBuilder.getRenderT
arget())); |
| 450 | 142 |
| 451 sp->fScissor = scissorState; | 143 sp->fScissor = scissorState; |
| 452 sp->fUseHWAA = pipelineBuilder.isHWAntialias(); | 144 sp->fUseHWAA = pipelineBuilder.isHWAntialias(); |
| 453 sp->fViewMatrix = pathProc->viewMatrix(); | 145 sp->fViewMatrix = pathProc->viewMatrix(); |
| 454 sp->fStencil = stencilSettings; | 146 sp->fStencil = stencilSettings; |
| 455 return sp; | 147 return sp; |
| 456 } | 148 } |
| 457 | 149 |
| 458 void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc, | |
| 459 const GrPath* path, | |
| 460 const GrStencilSettings& stencilSettings, | |
| 461 const PipelineInfo& pipelineInfo) { | |
| 462 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc, | |
| 463 path, stencilSettings, | |
| 464 pipelineInfo); | |
| 465 this->recordTraceMarkersIfNecessary(cmd); | |
| 466 } | |
| 467 | |
| 468 GrTargetCommands::Cmd* GrTargetCommands::recordDrawPath( | 150 GrTargetCommands::Cmd* GrTargetCommands::recordDrawPath( |
| 469 GrInOrderDrawBuffer* iodb, | 151 GrInOrderDrawBuffer* iodb, |
| 470 const GrPathProcessor* pathPro
c, | 152 const GrPathProcessor* pathPro
c, |
| 471 const GrPath* path, | 153 const GrPath* path, |
| 472 const GrStencilSettings& stenc
ilSettings, | 154 const GrStencilSettings& stenc
ilSettings, |
| 473 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | 155 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { |
| 474 this->closeBatch(); | 156 this->closeBatch(); |
| 475 | 157 |
| 476 // TODO: Only compare the subset of GrPipelineBuilder relevant to path cover
ing? | 158 // TODO: Only compare the subset of GrPipelineBuilder relevant to path cover
ing? |
| 477 if (!this->setupPipelineAndShouldDraw(iodb, pathProc, pipelineInfo)) { | 159 if (!this->setupPipelineAndShouldDraw(iodb, pathProc, pipelineInfo)) { |
| 478 return NULL; | 160 return NULL; |
| 479 } | 161 } |
| 480 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path)); | 162 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path)); |
| 481 dp->fStencilSettings = stencilSettings; | 163 dp->fStencilSettings = stencilSettings; |
| 482 return dp; | 164 return dp; |
| 483 } | 165 } |
| 484 | 166 |
| 485 void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc, | |
| 486 const GrPathRange* pathRange, | |
| 487 const void* indices, | |
| 488 PathIndexType indexType, | |
| 489 const float transformValues[], | |
| 490 PathTransformType transformType, | |
| 491 int count, | |
| 492 const GrStencilSettings& stencilSettings, | |
| 493 const PipelineInfo& pipelineInfo) { | |
| 494 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathR
ange, | |
| 495 indices, indexType, t
ransformValues, | |
| 496 transformType, count, | |
| 497 stencilSettings, pipe
lineInfo); | |
| 498 this->recordTraceMarkersIfNecessary(cmd); | |
| 499 } | |
| 500 | |
| 501 GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths( | 167 GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths( |
| 502 GrInOrderDrawBuffer* iodb, | 168 GrInOrderDrawBuffer* iodb, |
| 503 const GrPathProcessor* pathPro
c, | 169 const GrPathProcessor* pathPro
c, |
| 504 const GrPathRange* pathRange, | 170 const GrPathRange* pathRange, |
| 505 const void* indexValues, | 171 const void* indexValues, |
| 506 GrDrawTarget::PathIndexType in
dexType, | 172 GrDrawTarget::PathIndexType in
dexType, |
| 507 const float transformValues[], | 173 const float transformValues[], |
| 508 GrDrawTarget::PathTransformTyp
e transformType, | 174 GrDrawTarget::PathTransformTyp
e transformType, |
| 509 int count, | 175 int count, |
| 510 const GrStencilSettings& stenc
ilSettings, | 176 const GrStencilSettings& stenc
ilSettings, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; | 221 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; |
| 556 dp->fIndices = savedIndices; | 222 dp->fIndices = savedIndices; |
| 557 dp->fIndexType = indexType; | 223 dp->fIndexType = indexType; |
| 558 dp->fTransforms = savedTransforms; | 224 dp->fTransforms = savedTransforms; |
| 559 dp->fTransformType = transformType; | 225 dp->fTransformType = transformType; |
| 560 dp->fCount = count; | 226 dp->fCount = count; |
| 561 dp->fStencilSettings = stencilSettings; | 227 dp->fStencilSettings = stencilSettings; |
| 562 return dp; | 228 return dp; |
| 563 } | 229 } |
| 564 | 230 |
| 565 void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color, | |
| 566 bool canIgnoreRect, GrRenderTarget* renderTarg
et) { | |
| 567 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color, | |
| 568 canIgnoreRect, renderTarg
et); | |
| 569 this->recordTraceMarkersIfNecessary(cmd); | |
| 570 } | |
| 571 | |
| 572 GrTargetCommands::Cmd* GrTargetCommands::recordClear(GrInOrderDrawBuffer* iodb, | 231 GrTargetCommands::Cmd* GrTargetCommands::recordClear(GrInOrderDrawBuffer* iodb, |
| 573 const SkIRect* rect, | 232 const SkIRect* rect, |
| 574 GrColor color, | 233 GrColor color, |
| 575 bool canIgnoreRect, | 234 bool canIgnoreRect, |
| 576 GrRenderTarget* renderTarge
t) { | 235 GrRenderTarget* renderTarge
t) { |
| 577 SkASSERT(renderTarget); | 236 SkASSERT(renderTarget); |
| 578 this->closeBatch(); | 237 this->closeBatch(); |
| 579 | 238 |
| 580 SkIRect r; | 239 SkIRect r; |
| 581 if (NULL == rect) { | 240 if (NULL == rect) { |
| 582 // We could do something smart and remove previous draws and clears to | 241 // We could do something smart and remove previous draws and clears to |
| 583 // the current render target. If we get that smart we have to make sure | 242 // the current render target. If we get that smart we have to make sure |
| 584 // those draws aren't read before this clear (render-to-texture). | 243 // those draws aren't read before this clear (render-to-texture). |
| 585 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height()); | 244 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height()); |
| 586 rect = &r; | 245 rect = &r; |
| 587 } | 246 } |
| 588 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); | 247 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); |
| 589 GrColorIsPMAssert(color); | 248 GrColorIsPMAssert(color); |
| 590 clr->fColor = color; | 249 clr->fColor = color; |
| 591 clr->fRect = *rect; | 250 clr->fRect = *rect; |
| 592 clr->fCanIgnoreRect = canIgnoreRect; | 251 clr->fCanIgnoreRect = canIgnoreRect; |
| 593 return clr; | 252 return clr; |
| 594 } | 253 } |
| 595 | 254 |
| 596 void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect, | |
| 597 bool insideClip, | |
| 598 GrRenderTarget* renderTarget) { | |
| 599 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect, | |
| 600 insideClip, re
nderTarget); | |
| 601 this->recordTraceMarkersIfNecessary(cmd); | |
| 602 } | |
| 603 | |
| 604 GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(GrInOrderDrawBuf
fer* iodb, | 255 GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(GrInOrderDrawBuf
fer* iodb, |
| 605 const SkIRect& r
ect, | 256 const SkIRect& r
ect, |
| 606 bool insideClip, | 257 bool insideClip, |
| 607 GrRenderTarget*
renderTarget) { | 258 GrRenderTarget*
renderTarget) { |
| 608 SkASSERT(renderTarget); | 259 SkASSERT(renderTarget); |
| 609 this->closeBatch(); | 260 this->closeBatch(); |
| 610 | 261 |
| 611 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilCli
p, (renderTarget)); | 262 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilCli
p, (renderTarget)); |
| 612 clr->fRect = rect; | 263 clr->fRect = rect; |
| 613 clr->fInsideClip = insideClip; | 264 clr->fInsideClip = insideClip; |
| 614 return clr; | 265 return clr; |
| 615 } | 266 } |
| 616 | 267 |
| 617 void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) { | |
| 618 if (!this->caps()->discardRenderTargetSupport()) { | |
| 619 return; | |
| 620 } | |
| 621 | |
| 622 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget); | |
| 623 this->recordTraceMarkersIfNecessary(cmd); | |
| 624 } | |
| 625 | |
| 626 GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrInOrderDrawBuffer* iodb
, | 268 GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrInOrderDrawBuffer* iodb
, |
| 627 GrRenderTarget* renderTar
get) { | 269 GrRenderTarget* renderTar
get) { |
| 628 SkASSERT(renderTarget); | 270 SkASSERT(renderTarget); |
| 629 this->closeBatch(); | 271 this->closeBatch(); |
| 630 | 272 |
| 631 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); | 273 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); |
| 632 clr->fColor = GrColor_ILLEGAL; | 274 clr->fColor = GrColor_ILLEGAL; |
| 633 return clr; | 275 return clr; |
| 634 } | 276 } |
| 635 | 277 |
| 636 void GrInOrderDrawBuffer::onReset() { | |
| 637 fCommands.reset(); | |
| 638 fPathIndexBuffer.rewind(); | |
| 639 fPathTransformBuffer.rewind(); | |
| 640 fGpuCmdMarkers.reset(); | |
| 641 } | |
| 642 | |
| 643 void GrTargetCommands::reset() { | 278 void GrTargetCommands::reset() { |
| 644 fCmdBuffer.reset(); | 279 fCmdBuffer.reset(); |
| 645 fPrevState = NULL; | 280 fPrevState = NULL; |
| 646 fDrawBatch = NULL; | 281 fDrawBatch = NULL; |
| 647 } | 282 } |
| 648 | 283 |
| 649 void GrInOrderDrawBuffer::onFlush() { | |
| 650 fCommands.flush(this); | |
| 651 ++fDrawID; | |
| 652 } | |
| 653 | |
| 654 void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) { | 284 void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) { |
| 655 if (fCmdBuffer.empty()) { | 285 if (fCmdBuffer.empty()) { |
| 656 return; | 286 return; |
| 657 } | 287 } |
| 658 | 288 |
| 659 // Updated every time we find a set state cmd to reflect the current state i
n the playback | 289 // Updated every time we find a set state cmd to reflect the current state i
n the playback |
| 660 // stream. | 290 // stream. |
| 661 SetState* currentState = NULL; | 291 SetState* currentState = NULL; |
| 662 | 292 |
| 663 // TODO this is temporary while batch is being rolled out | 293 // TODO this is temporary while batch is being rolled out |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 } | 397 } |
| 768 | 398 |
| 769 void GrTargetCommands::ClearStencilClip::execute(GrGpu* gpu, const SetState*) { | 399 void GrTargetCommands::ClearStencilClip::execute(GrGpu* gpu, const SetState*) { |
| 770 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget()); | 400 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget()); |
| 771 } | 401 } |
| 772 | 402 |
| 773 void GrTargetCommands::CopySurface::execute(GrGpu* gpu, const SetState*) { | 403 void GrTargetCommands::CopySurface::execute(GrGpu* gpu, const SetState*) { |
| 774 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint); | 404 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint); |
| 775 } | 405 } |
| 776 | 406 |
| 777 bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst, | |
| 778 GrSurface* src, | |
| 779 const SkIRect& srcRect, | |
| 780 const SkIPoint& dstPoint) { | |
| 781 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(this, dst, src, | |
| 782 srcRect, dstPoint); | |
| 783 this->recordTraceMarkersIfNecessary(cmd); | |
| 784 return SkToBool(cmd); | |
| 785 } | |
| 786 | |
| 787 GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrInOrderDrawBuffer*
iodb, | 407 GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrInOrderDrawBuffer*
iodb, |
| 788 GrSurface* dst, | 408 GrSurface* dst, |
| 789 GrSurface* src, | 409 GrSurface* src, |
| 790 const SkIRect& srcRec
t, | 410 const SkIRect& srcRec
t, |
| 791 const SkIPoint& dstPo
int) { | 411 const SkIPoint& dstPo
int) { |
| 792 if (iodb->getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) { | 412 if (iodb->getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) { |
| 793 this->closeBatch(); | 413 this->closeBatch(); |
| 794 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst
, src)); | 414 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst
, src)); |
| 795 cs->fSrcRect = srcRect; | 415 cs->fSrcRect = srcRect; |
| 796 cs->fDstPoint = dstPoint; | 416 cs->fDstPoint = dstPoint; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 fPrevState->getPipeline()->isEqual(*ss->getPipeline())) { | 463 fPrevState->getPipeline()->isEqual(*ss->getPipeline())) { |
| 844 fCmdBuffer.pop_back(); | 464 fCmdBuffer.pop_back(); |
| 845 } else { | 465 } else { |
| 846 this->closeBatch(); | 466 this->closeBatch(); |
| 847 fPrevState = ss; | 467 fPrevState = ss; |
| 848 iodb->recordTraceMarkersIfNecessary(ss); | 468 iodb->recordTraceMarkersIfNecessary(ss); |
| 849 } | 469 } |
| 850 return true; | 470 return true; |
| 851 } | 471 } |
| 852 | 472 |
| 853 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* c
md) { | |
| 854 if (!cmd) { | |
| 855 return; | |
| 856 } | |
| 857 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); | |
| 858 if (activeTraceMarkers.count() > 0) { | |
| 859 if (cmd->isTraced()) { | |
| 860 fGpuCmdMarkers.back().addSet(activeTraceMarkers); | |
| 861 } else { | |
| 862 cmd->makeTraced(); | |
| 863 fGpuCmdMarkers.push_back(activeTraceMarkers); | |
| 864 } | |
| 865 } | |
| 866 } | |
| 867 | |
| 868 void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount, | |
| 869 size_t vertexStride, | |
| 870 int indexCount) { | |
| 871 fCommands.closeBatch(); | |
| 872 | |
| 873 this->INHERITED::willReserveVertexAndIndexSpace(vertexCount, vertexStride, i
ndexCount); | |
| 874 } | |
| OLD | NEW |