| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "GrInOrderDrawBuffer.h" | 8 #include "GrInOrderDrawBuffer.h" |
| 9 | 9 |
| 10 #include "GrBufferAllocPool.h" | |
| 11 #include "GrDefaultGeoProcFactory.h" | 10 #include "GrDefaultGeoProcFactory.h" |
| 12 #include "GrDrawTargetCaps.h" | |
| 13 #include "GrGpu.h" | |
| 14 #include "GrTemplates.h" | 11 #include "GrTemplates.h" |
| 15 #include "GrFontCache.h" | |
| 16 #include "GrTexture.h" | |
| 17 | 12 |
| 18 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu, | 13 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu, |
| 19 GrVertexBufferAllocPool* vertexPool, | 14 GrVertexBufferAllocPool* vertexPool, |
| 20 GrIndexBufferAllocPool* indexPool) | 15 GrIndexBufferAllocPool* indexPool) |
| 21 : INHERITED(gpu, vertexPool, indexPool) | 16 : INHERITED(gpu, vertexPool, indexPool) |
| 22 , fCommands(gpu, vertexPool, indexPool) | 17 , fCommands(gpu, vertexPool, indexPool) |
| 23 , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4) | 18 , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4) |
| 24 , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4) | 19 , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4) |
| 25 , fDrawID(0) { | 20 , fDrawID(0) { |
| 26 | 21 |
| 27 SkASSERT(vertexPool); | 22 SkASSERT(vertexPool); |
| 28 SkASSERT(indexPool); | 23 SkASSERT(indexPool); |
| 29 } | 24 } |
| 30 | 25 |
| 31 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { | 26 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { |
| 32 this->reset(); | 27 this->reset(); |
| 33 } | 28 } |
| 34 | 29 |
| 35 void GrTargetCommands::closeBatch() { | |
| 36 if (fDrawBatch) { | |
| 37 fBatchTarget.resetNumberOfDraws(); | |
| 38 fDrawBatch->execute(NULL, fPrevState); | |
| 39 fDrawBatch->fBatch->setNumberOfDraws(fBatchTarget.numberOfDraws()); | |
| 40 fDrawBatch = NULL; | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 //////////////////////////////////////////////////////////////////////////////// | 30 //////////////////////////////////////////////////////////////////////////////// |
| 45 | 31 |
| 46 /** We always use per-vertex colors so that rects can be batched across color ch
anges. Sometimes we | 32 /** 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 | 33 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 | 34 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. | 35 haven't seen a use case which frequently switches between local rect and no
local rect draws. |
| 50 | 36 |
| 51 The color param is used to determine whether the opaque hint can be set on t
he draw state. | 37 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. | 38 The caller must populate the vertex colors itself. |
| 53 | 39 |
| 54 The vertex attrib order is always pos, color, [local coords]. | 40 The vertex attrib order is always pos, color, [local coords]. |
| 55 */ | 41 */ |
| 56 static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords, | 42 static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords, |
| 57 GrColor color, | 43 GrColor color, |
| 58 const SkMatrix* localMatrix) { | 44 const SkMatrix* localMatrix) { |
| 59 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | | 45 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | |
| 60 GrDefaultGeoProcFactory::kColor_GPType; | 46 GrDefaultGeoProcFactory::kColor_GPType; |
| 61 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPTyp
e : 0; | 47 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPTyp
e : 0; |
| 62 if (localMatrix) { | 48 if (localMatrix) { |
| 63 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *loc
alMatrix, | 49 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *loc
alMatrix, |
| 64 GrColorIsOpaque(color)); | 50 GrColorIsOpaque(color)); |
| 65 } else { | 51 } else { |
| 66 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMa
trix::I(), | 52 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMa
trix::I(), |
| 67 GrColorIsOpaque(color)); | 53 GrColorIsOpaque(color)); |
| 68 } | 54 } |
| 69 } | 55 } |
| 70 | 56 |
| 71 static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin
gs) { | |
| 72 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Fa
ce; | |
| 73 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); | |
| 74 if (isWinding) { | |
| 75 // Double check that it is in fact winding. | |
| 76 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace)); | |
| 77 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace)); | |
| 78 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace)); | |
| 79 SkASSERT(!pathStencilSettings.isTwoSided()); | |
| 80 } | |
| 81 return isWinding; | |
| 82 } | |
| 83 | |
| 84 class RectBatch : public GrBatch { | 57 class RectBatch : public GrBatch { |
| 85 public: | 58 public: |
| 86 struct Geometry { | 59 struct Geometry { |
| 87 GrColor fColor; | 60 GrColor fColor; |
| 88 SkMatrix fViewMatrix; | 61 SkMatrix fViewMatrix; |
| 89 SkRect fRect; | 62 SkRect fRect; |
| 90 bool fHasLocalRect; | 63 bool fHasLocalRect; |
| 91 bool fHasLocalMatrix; | 64 bool fHasLocalMatrix; |
| 92 SkRect fLocalRect; | 65 SkRect fLocalRect; |
| 93 SkMatrix fLocalMatrix; | 66 SkMatrix fLocalMatrix; |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 geometry.fHasLocalMatrix = false; | 285 geometry.fHasLocalMatrix = false; |
| 313 } | 286 } |
| 314 | 287 |
| 315 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry)); | 288 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry)); |
| 316 | 289 |
| 317 SkRect bounds = rect; | 290 SkRect bounds = rect; |
| 318 viewMatrix.mapRect(&bounds); | 291 viewMatrix.mapRect(&bounds); |
| 319 this->drawBatch(pipelineBuilder, batch, &bounds); | 292 this->drawBatch(pipelineBuilder, batch, &bounds); |
| 320 } | 293 } |
| 321 | 294 |
| 322 int GrTargetCommands::concatInstancedDraw(GrInOrderDrawBuffer* iodb, | |
| 323 const GrDrawTarget::DrawInfo& info) { | |
| 324 SkASSERT(!fCmdBuffer.empty()); | |
| 325 SkASSERT(info.isInstanced()); | |
| 326 | |
| 327 const GrIndexBuffer* ib; | |
| 328 if (!iodb->canConcatToIndexBuffer(&ib)) { | |
| 329 return 0; | |
| 330 } | |
| 331 | |
| 332 // Check if there is a draw info that is compatible that uses the same VB fr
om the pool and | |
| 333 // the same IB | |
| 334 if (Cmd::kDraw_Cmd != fCmdBuffer.back().type()) { | |
| 335 return 0; | |
| 336 } | |
| 337 | |
| 338 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back()); | |
| 339 | |
| 340 if (!draw->fInfo.isInstanced() || | |
| 341 draw->fInfo.primitiveType() != info.primitiveType() || | |
| 342 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() || | |
| 343 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() || | |
| 344 draw->fInfo.vertexBuffer() != info.vertexBuffer() || | |
| 345 draw->fInfo.indexBuffer() != ib) { | |
| 346 return 0; | |
| 347 } | |
| 348 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVerte
x()) { | |
| 349 return 0; | |
| 350 } | |
| 351 | |
| 352 // how many instances can be concat'ed onto draw given the size of the index
buffer | |
| 353 int instancesToConcat = iodb->indexCountInCurrentSource() / info.indicesPerI
nstance(); | |
| 354 instancesToConcat -= draw->fInfo.instanceCount(); | |
| 355 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount()); | |
| 356 | |
| 357 draw->fInfo.adjustInstanceCount(instancesToConcat); | |
| 358 | |
| 359 // update last fGpuCmdMarkers to include any additional trace markers that h
ave been added | |
| 360 iodb->recordTraceMarkersIfNecessary(draw); | |
| 361 return instancesToConcat; | |
| 362 } | |
| 363 | |
| 364 void GrInOrderDrawBuffer::onDraw(const GrGeometryProcessor* gp, | 295 void GrInOrderDrawBuffer::onDraw(const GrGeometryProcessor* gp, |
| 365 const DrawInfo& info, | 296 const DrawInfo& info, |
| 366 const PipelineInfo& pipelineInfo) { | 297 const PipelineInfo& pipelineInfo) { |
| 367 GrTargetCommands::Cmd* cmd = fCommands.recordDraw(this, gp, info, pipelineIn
fo); | 298 GrTargetCommands::Cmd* cmd = fCommands.recordDraw(this, gp, info, pipelineIn
fo); |
| 368 this->recordTraceMarkersIfNecessary(cmd); | 299 this->recordTraceMarkersIfNecessary(cmd); |
| 369 } | 300 } |
| 370 | 301 |
| 371 GrTargetCommands::Cmd* GrTargetCommands::recordDraw( | |
| 372 GrInOrderDrawBuffer* iodb, | |
| 373 const GrGeometryProcessor* gp, | |
| 374 const GrDrawTarget::DrawInfo&
info, | |
| 375 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
| 376 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer())); | |
| 377 this->closeBatch(); | |
| 378 | |
| 379 if (!this->setupPipelineAndShouldDraw(iodb, gp, pipelineInfo)) { | |
| 380 return NULL; | |
| 381 } | |
| 382 | |
| 383 Draw* draw; | |
| 384 if (info.isInstanced()) { | |
| 385 int instancesConcated = this->concatInstancedDraw(iodb, info); | |
| 386 if (info.instanceCount() > instancesConcated) { | |
| 387 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | |
| 388 draw->fInfo.adjustInstanceCount(-instancesConcated); | |
| 389 } else { | |
| 390 return NULL; | |
| 391 } | |
| 392 } else { | |
| 393 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | |
| 394 } | |
| 395 | |
| 396 return draw; | |
| 397 } | |
| 398 | |
| 399 void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch, | 302 void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch, |
| 400 const PipelineInfo& pipelineInfo) { | 303 const PipelineInfo& pipelineInfo) { |
| 401 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipeline
Info); | 304 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipeline
Info); |
| 402 this->recordTraceMarkersIfNecessary(cmd); | 305 this->recordTraceMarkersIfNecessary(cmd); |
| 403 } | 306 } |
| 404 | 307 |
| 405 GrTargetCommands::Cmd* GrTargetCommands::recordDrawBatch( | |
| 406 GrInOrderDrawBuffer* iodb, | |
| 407 GrBatch* batch, | |
| 408 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
| 409 if (!this->setupPipelineAndShouldDraw(iodb, batch, pipelineInfo)) { | |
| 410 return NULL; | |
| 411 } | |
| 412 | |
| 413 // Check if there is a Batch Draw we can batch with | |
| 414 if (Cmd::kDrawBatch_Cmd != fCmdBuffer.back().type() || !fDrawBatch) { | |
| 415 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch, &fB
atchTarget)); | |
| 416 return fDrawBatch; | |
| 417 } | |
| 418 | |
| 419 SkASSERT(&fCmdBuffer.back() == fDrawBatch); | |
| 420 if (!fDrawBatch->fBatch->combineIfPossible(batch)) { | |
| 421 this->closeBatch(); | |
| 422 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch, &fB
atchTarget)); | |
| 423 } | |
| 424 | |
| 425 return fDrawBatch; | |
| 426 } | |
| 427 | |
| 428 void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder
, | 308 void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder
, |
| 429 const GrPathProcessor* pathProc, | 309 const GrPathProcessor* pathProc, |
| 430 const GrPath* path, | 310 const GrPath* path, |
| 431 const GrScissorState& scissorState, | 311 const GrScissorState& scissorState, |
| 432 const GrStencilSettings& stencilSettings
) { | 312 const GrStencilSettings& stencilSettings
) { |
| 433 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuild
er, | 313 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuild
er, |
| 434 pathProc, path, sci
ssorState, | 314 pathProc, path, sci
ssorState, |
| 435 stencilSettings); | 315 stencilSettings); |
| 436 this->recordTraceMarkersIfNecessary(cmd); | 316 this->recordTraceMarkersIfNecessary(cmd); |
| 437 } | 317 } |
| 438 | 318 |
| 439 GrTargetCommands::Cmd* GrTargetCommands::recordStencilPath( | |
| 440 GrInOrderDrawBuffer* iod
b, | |
| 441 const GrPipelineBuilder&
pipelineBuilder, | |
| 442 const GrPathProcessor* p
athProc, | |
| 443 const GrPath* path, | |
| 444 const GrScissorState& sc
issorState, | |
| 445 const GrStencilSettings&
stencilSettings) { | |
| 446 this->closeBatch(); | |
| 447 | |
| 448 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, | |
| 449 (path, pipelineBuilder.getRenderT
arget())); | |
| 450 | |
| 451 sp->fScissor = scissorState; | |
| 452 sp->fUseHWAA = pipelineBuilder.isHWAntialias(); | |
| 453 sp->fViewMatrix = pathProc->viewMatrix(); | |
| 454 sp->fStencil = stencilSettings; | |
| 455 return sp; | |
| 456 } | |
| 457 | |
| 458 void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc, | 319 void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc, |
| 459 const GrPath* path, | 320 const GrPath* path, |
| 460 const GrStencilSettings& stencilSettings, | 321 const GrStencilSettings& stencilSettings, |
| 461 const PipelineInfo& pipelineInfo) { | 322 const PipelineInfo& pipelineInfo) { |
| 462 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc, | 323 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc, |
| 463 path, stencilSettings, | 324 path, stencilSettings, |
| 464 pipelineInfo); | 325 pipelineInfo); |
| 465 this->recordTraceMarkersIfNecessary(cmd); | 326 this->recordTraceMarkersIfNecessary(cmd); |
| 466 } | 327 } |
| 467 | 328 |
| 468 GrTargetCommands::Cmd* GrTargetCommands::recordDrawPath( | |
| 469 GrInOrderDrawBuffer* iodb, | |
| 470 const GrPathProcessor* pathPro
c, | |
| 471 const GrPath* path, | |
| 472 const GrStencilSettings& stenc
ilSettings, | |
| 473 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
| 474 this->closeBatch(); | |
| 475 | |
| 476 // TODO: Only compare the subset of GrPipelineBuilder relevant to path cover
ing? | |
| 477 if (!this->setupPipelineAndShouldDraw(iodb, pathProc, pipelineInfo)) { | |
| 478 return NULL; | |
| 479 } | |
| 480 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path)); | |
| 481 dp->fStencilSettings = stencilSettings; | |
| 482 return dp; | |
| 483 } | |
| 484 | |
| 485 void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc, | 329 void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc, |
| 486 const GrPathRange* pathRange, | 330 const GrPathRange* pathRange, |
| 487 const void* indices, | 331 const void* indices, |
| 488 PathIndexType indexType, | 332 PathIndexType indexType, |
| 489 const float transformValues[], | 333 const float transformValues[], |
| 490 PathTransformType transformType, | 334 PathTransformType transformType, |
| 491 int count, | 335 int count, |
| 492 const GrStencilSettings& stencilSettings, | 336 const GrStencilSettings& stencilSettings, |
| 493 const PipelineInfo& pipelineInfo) { | 337 const PipelineInfo& pipelineInfo) { |
| 494 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathR
ange, | 338 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathR
ange, |
| 495 indices, indexType, t
ransformValues, | 339 indices, indexType, t
ransformValues, |
| 496 transformType, count, | 340 transformType, count, |
| 497 stencilSettings, pipe
lineInfo); | 341 stencilSettings, pipe
lineInfo); |
| 498 this->recordTraceMarkersIfNecessary(cmd); | 342 this->recordTraceMarkersIfNecessary(cmd); |
| 499 } | 343 } |
| 500 | 344 |
| 501 GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths( | |
| 502 GrInOrderDrawBuffer* iodb, | |
| 503 const GrPathProcessor* pathPro
c, | |
| 504 const GrPathRange* pathRange, | |
| 505 const void* indexValues, | |
| 506 GrDrawTarget::PathIndexType in
dexType, | |
| 507 const float transformValues[], | |
| 508 GrDrawTarget::PathTransformTyp
e transformType, | |
| 509 int count, | |
| 510 const GrStencilSettings& stenc
ilSettings, | |
| 511 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
| 512 SkASSERT(pathRange); | |
| 513 SkASSERT(indexValues); | |
| 514 SkASSERT(transformValues); | |
| 515 this->closeBatch(); | |
| 516 | |
| 517 if (!this->setupPipelineAndShouldDraw(iodb, pathProc, pipelineInfo)) { | |
| 518 return NULL; | |
| 519 } | |
| 520 | |
| 521 char* savedIndices; | |
| 522 float* savedTransforms; | |
| 523 | |
| 524 iodb->appendIndicesAndTransforms(indexValues, indexType, | |
| 525 transformValues, transformType, | |
| 526 count, &savedIndices, &savedTransforms); | |
| 527 | |
| 528 if (Cmd::kDrawPaths_Cmd == fCmdBuffer.back().type()) { | |
| 529 // The previous command was also DrawPaths. Try to collapse this call in
to the one | |
| 530 // before. Note that stenciling all the paths at once, then covering, ma
y not be | |
| 531 // equivalent to two separate draw calls if there is overlap. Blending w
on't work, | |
| 532 // and the combined calls may also cancel each other's winding numbers i
n some | |
| 533 // places. For now the winding numbers are only an issue if the fill is
even/odd, | |
| 534 // because DrawPaths is currently only used for glyphs, and glyphs in th
e same | |
| 535 // font tend to all wind in the same direction. | |
| 536 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back()); | |
| 537 if (pathRange == previous->pathRange() && | |
| 538 indexType == previous->fIndexType && | |
| 539 transformType == previous->fTransformType && | |
| 540 stencilSettings == previous->fStencilSettings && | |
| 541 path_fill_type_is_winding(stencilSettings) && | |
| 542 !pipelineInfo.willBlendWithDst(pathProc)) { | |
| 543 const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexTy
pe); | |
| 544 const int xformSize = GrPathRendering::PathTransformSize(transfo
rmType); | |
| 545 if (&previous->fIndices[previous->fCount*indexBytes] == savedInd
ices && | |
| 546 (0 == xformSize || | |
| 547 &previous->fTransforms[previous->fCount*xformSize] == saved
Transforms)) { | |
| 548 // Fold this DrawPaths call into the one previous. | |
| 549 previous->fCount += count; | |
| 550 return NULL; | |
| 551 } | |
| 552 } | |
| 553 } | |
| 554 | |
| 555 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; | |
| 556 dp->fIndices = savedIndices; | |
| 557 dp->fIndexType = indexType; | |
| 558 dp->fTransforms = savedTransforms; | |
| 559 dp->fTransformType = transformType; | |
| 560 dp->fCount = count; | |
| 561 dp->fStencilSettings = stencilSettings; | |
| 562 return dp; | |
| 563 } | |
| 564 | |
| 565 void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color, | 345 void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color, |
| 566 bool canIgnoreRect, GrRenderTarget* renderTarg
et) { | 346 bool canIgnoreRect, GrRenderTarget* renderTarg
et) { |
| 567 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color, | 347 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color, |
| 568 canIgnoreRect, renderTarg
et); | 348 canIgnoreRect, renderTarg
et); |
| 569 this->recordTraceMarkersIfNecessary(cmd); | 349 this->recordTraceMarkersIfNecessary(cmd); |
| 570 } | 350 } |
| 571 | 351 |
| 572 GrTargetCommands::Cmd* GrTargetCommands::recordClear(GrInOrderDrawBuffer* iodb, | |
| 573 const SkIRect* rect, | |
| 574 GrColor color, | |
| 575 bool canIgnoreRect, | |
| 576 GrRenderTarget* renderTarge
t) { | |
| 577 SkASSERT(renderTarget); | |
| 578 this->closeBatch(); | |
| 579 | |
| 580 SkIRect r; | |
| 581 if (NULL == rect) { | |
| 582 // 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 | |
| 584 // those draws aren't read before this clear (render-to-texture). | |
| 585 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height()); | |
| 586 rect = &r; | |
| 587 } | |
| 588 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); | |
| 589 GrColorIsPMAssert(color); | |
| 590 clr->fColor = color; | |
| 591 clr->fRect = *rect; | |
| 592 clr->fCanIgnoreRect = canIgnoreRect; | |
| 593 return clr; | |
| 594 } | |
| 595 | |
| 596 void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect, | 352 void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect, |
| 597 bool insideClip, | 353 bool insideClip, |
| 598 GrRenderTarget* renderTarget) { | 354 GrRenderTarget* renderTarget) { |
| 599 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect, | 355 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect, |
| 600 insideClip, re
nderTarget); | 356 insideClip, re
nderTarget); |
| 601 this->recordTraceMarkersIfNecessary(cmd); | 357 this->recordTraceMarkersIfNecessary(cmd); |
| 602 } | 358 } |
| 603 | 359 |
| 604 GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(GrInOrderDrawBuf
fer* iodb, | |
| 605 const SkIRect& r
ect, | |
| 606 bool insideClip, | |
| 607 GrRenderTarget*
renderTarget) { | |
| 608 SkASSERT(renderTarget); | |
| 609 this->closeBatch(); | |
| 610 | |
| 611 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilCli
p, (renderTarget)); | |
| 612 clr->fRect = rect; | |
| 613 clr->fInsideClip = insideClip; | |
| 614 return clr; | |
| 615 } | |
| 616 | |
| 617 void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) { | 360 void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) { |
| 618 if (!this->caps()->discardRenderTargetSupport()) { | 361 if (!this->caps()->discardRenderTargetSupport()) { |
| 619 return; | 362 return; |
| 620 } | 363 } |
| 621 | 364 |
| 622 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget); | 365 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget); |
| 623 this->recordTraceMarkersIfNecessary(cmd); | 366 this->recordTraceMarkersIfNecessary(cmd); |
| 624 } | 367 } |
| 625 | 368 |
| 626 GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrInOrderDrawBuffer* iodb
, | |
| 627 GrRenderTarget* renderTar
get) { | |
| 628 SkASSERT(renderTarget); | |
| 629 this->closeBatch(); | |
| 630 | |
| 631 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); | |
| 632 clr->fColor = GrColor_ILLEGAL; | |
| 633 return clr; | |
| 634 } | |
| 635 | |
| 636 void GrInOrderDrawBuffer::onReset() { | 369 void GrInOrderDrawBuffer::onReset() { |
| 637 fCommands.reset(); | 370 fCommands.reset(); |
| 638 fPathIndexBuffer.rewind(); | 371 fPathIndexBuffer.rewind(); |
| 639 fPathTransformBuffer.rewind(); | 372 fPathTransformBuffer.rewind(); |
| 640 fGpuCmdMarkers.reset(); | 373 fGpuCmdMarkers.reset(); |
| 641 } | 374 } |
| 642 | 375 |
| 643 void GrTargetCommands::reset() { | |
| 644 fCmdBuffer.reset(); | |
| 645 fPrevState = NULL; | |
| 646 fDrawBatch = NULL; | |
| 647 } | |
| 648 | |
| 649 void GrInOrderDrawBuffer::onFlush() { | 376 void GrInOrderDrawBuffer::onFlush() { |
| 650 fCommands.flush(this); | 377 fCommands.flush(this); |
| 651 ++fDrawID; | 378 ++fDrawID; |
| 652 } | 379 } |
| 653 | 380 |
| 654 void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) { | |
| 655 if (fCmdBuffer.empty()) { | |
| 656 return; | |
| 657 } | |
| 658 | |
| 659 // Updated every time we find a set state cmd to reflect the current state i
n the playback | |
| 660 // stream. | |
| 661 SetState* currentState = NULL; | |
| 662 | |
| 663 // TODO this is temporary while batch is being rolled out | |
| 664 this->closeBatch(); | |
| 665 iodb->getVertexAllocPool()->unmap(); | |
| 666 iodb->getIndexAllocPool()->unmap(); | |
| 667 fBatchTarget.preFlush(); | |
| 668 | |
| 669 currentState = NULL; | |
| 670 CmdBuffer::Iter iter(fCmdBuffer); | |
| 671 | |
| 672 int currCmdMarker = 0; | |
| 673 | |
| 674 GrGpu* gpu = iodb->getGpu(); | |
| 675 | |
| 676 int i = 0; | |
| 677 while (iter.next()) { | |
| 678 i++; | |
| 679 GrGpuTraceMarker newMarker("", -1); | |
| 680 SkString traceString; | |
| 681 if (iter->isTraced()) { | |
| 682 traceString = iodb->getCmdString(currCmdMarker); | |
| 683 newMarker.fMarker = traceString.c_str(); | |
| 684 gpu->addGpuTraceMarker(&newMarker); | |
| 685 ++currCmdMarker; | |
| 686 } | |
| 687 | |
| 688 // TODO temporary hack | |
| 689 if (Cmd::kDrawBatch_Cmd == iter->type()) { | |
| 690 DrawBatch* db = reinterpret_cast<DrawBatch*>(iter.get()); | |
| 691 fBatchTarget.flushNext(db->fBatch->numberOfDraws()); | |
| 692 continue; | |
| 693 } | |
| 694 | |
| 695 if (Cmd::kSetState_Cmd == iter->type()) { | |
| 696 SetState* ss = reinterpret_cast<SetState*>(iter.get()); | |
| 697 | |
| 698 // TODO sometimes we have a prim proc, othertimes we have a GrBatch.
Eventually we | |
| 699 // will only have GrBatch and we can delete this | |
| 700 if (ss->fPrimitiveProcessor) { | |
| 701 gpu->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor, | |
| 702 *ss->getPipeline(), | |
| 703 ss->fBatchTracker); | |
| 704 } | |
| 705 currentState = ss; | |
| 706 } else { | |
| 707 iter->execute(gpu, currentState); | |
| 708 } | |
| 709 | |
| 710 if (iter->isTraced()) { | |
| 711 gpu->removeGpuTraceMarker(&newMarker); | |
| 712 } | |
| 713 } | |
| 714 | |
| 715 // TODO see copious notes about hack | |
| 716 fBatchTarget.postFlush(); | |
| 717 } | |
| 718 | |
| 719 void GrTargetCommands::Draw::execute(GrGpu* gpu, const SetState* state) { | |
| 720 SkASSERT(state); | |
| 721 DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state
->fDesc, | |
| 722 &state->fBatchTracker); | |
| 723 gpu->draw(args, fInfo); | |
| 724 } | |
| 725 | |
| 726 void GrTargetCommands::StencilPath::execute(GrGpu* gpu, const SetState*) { | |
| 727 GrGpu::StencilPathState state; | |
| 728 state.fRenderTarget = fRenderTarget.get(); | |
| 729 state.fScissor = &fScissor; | |
| 730 state.fStencil = &fStencil; | |
| 731 state.fUseHWAA = fUseHWAA; | |
| 732 state.fViewMatrix = &fViewMatrix; | |
| 733 | |
| 734 gpu->stencilPath(this->path(), state); | |
| 735 } | |
| 736 | |
| 737 void GrTargetCommands::DrawPath::execute(GrGpu* gpu, const SetState* state) { | |
| 738 SkASSERT(state); | |
| 739 DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state
->fDesc, | |
| 740 &state->fBatchTracker); | |
| 741 gpu->drawPath(args, this->path(), fStencilSettings); | |
| 742 } | |
| 743 | |
| 744 void GrTargetCommands::DrawPaths::execute(GrGpu* gpu, const SetState* state) { | |
| 745 SkASSERT(state); | |
| 746 DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state
->fDesc, | |
| 747 &state->fBatchTracker); | |
| 748 gpu->drawPaths(args, this->pathRange(), | |
| 749 fIndices, fIndexType, | |
| 750 fTransforms, fTransformType, | |
| 751 fCount, fStencilSettings); | |
| 752 } | |
| 753 | |
| 754 void GrTargetCommands::DrawBatch::execute(GrGpu*, const SetState* state) { | |
| 755 SkASSERT(state); | |
| 756 fBatch->generateGeometry(fBatchTarget, state->getPipeline()); | |
| 757 } | |
| 758 | |
| 759 void GrTargetCommands::SetState::execute(GrGpu*, const SetState*) {} | |
| 760 | |
| 761 void GrTargetCommands::Clear::execute(GrGpu* gpu, const SetState*) { | |
| 762 if (GrColor_ILLEGAL == fColor) { | |
| 763 gpu->discard(this->renderTarget()); | |
| 764 } else { | |
| 765 gpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget()); | |
| 766 } | |
| 767 } | |
| 768 | |
| 769 void GrTargetCommands::ClearStencilClip::execute(GrGpu* gpu, const SetState*) { | |
| 770 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget()); | |
| 771 } | |
| 772 | |
| 773 void GrTargetCommands::CopySurface::execute(GrGpu* gpu, const SetState*) { | |
| 774 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint); | |
| 775 } | |
| 776 | |
| 777 bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst, | 381 bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst, |
| 778 GrSurface* src, | 382 GrSurface* src, |
| 779 const SkIRect& srcRect, | 383 const SkIRect& srcRect, |
| 780 const SkIPoint& dstPoint) { | 384 const SkIPoint& dstPoint) { |
| 781 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(this, dst, src, | 385 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(this, dst, src, |
| 782 srcRect, dstPoint); | 386 srcRect, dstPoint); |
| 783 this->recordTraceMarkersIfNecessary(cmd); | 387 this->recordTraceMarkersIfNecessary(cmd); |
| 784 return SkToBool(cmd); | 388 return SkToBool(cmd); |
| 785 } | 389 } |
| 786 | 390 |
| 787 GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrInOrderDrawBuffer*
iodb, | |
| 788 GrSurface* dst, | |
| 789 GrSurface* src, | |
| 790 const SkIRect& srcRec
t, | |
| 791 const SkIPoint& dstPo
int) { | |
| 792 if (iodb->getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) { | |
| 793 this->closeBatch(); | |
| 794 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst
, src)); | |
| 795 cs->fSrcRect = srcRect; | |
| 796 cs->fDstPoint = dstPoint; | |
| 797 return cs; | |
| 798 } | |
| 799 return NULL; | |
| 800 } | |
| 801 | |
| 802 bool GrTargetCommands::setupPipelineAndShouldDraw(GrInOrderDrawBuffer* iodb, | |
| 803 const GrPrimitiveProcessor* pr
imProc, | |
| 804 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
| 805 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (primProc)); | |
| 806 iodb->setupPipeline(pipelineInfo, ss->pipelineLocation()); | |
| 807 | |
| 808 if (ss->getPipeline()->mustSkip()) { | |
| 809 fCmdBuffer.pop_back(); | |
| 810 return false; | |
| 811 } | |
| 812 | |
| 813 ss->fPrimitiveProcessor->initBatchTracker(&ss->fBatchTracker, | |
| 814 ss->getPipeline()->getInitBatchTra
cker()); | |
| 815 | |
| 816 if (fPrevState && fPrevState->fPrimitiveProcessor.get() && | |
| 817 fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker, | |
| 818 *ss->fPrimitiveProcessor, | |
| 819 ss->fBatchTracker) && | |
| 820 fPrevState->getPipeline()->isEqual(*ss->getPipeline())) { | |
| 821 fCmdBuffer.pop_back(); | |
| 822 } else { | |
| 823 fPrevState = ss; | |
| 824 iodb->recordTraceMarkersIfNecessary(ss); | |
| 825 } | |
| 826 return true; | |
| 827 } | |
| 828 | |
| 829 bool GrTargetCommands::setupPipelineAndShouldDraw(GrInOrderDrawBuffer* iodb, | |
| 830 GrBatch* batch, | |
| 831 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
| 832 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, ()); | |
| 833 iodb->setupPipeline(pipelineInfo, ss->pipelineLocation()); | |
| 834 | |
| 835 if (ss->getPipeline()->mustSkip()) { | |
| 836 fCmdBuffer.pop_back(); | |
| 837 return false; | |
| 838 } | |
| 839 | |
| 840 batch->initBatchTracker(ss->getPipeline()->getInitBatchTracker()); | |
| 841 | |
| 842 if (fPrevState && !fPrevState->fPrimitiveProcessor.get() && | |
| 843 fPrevState->getPipeline()->isEqual(*ss->getPipeline())) { | |
| 844 fCmdBuffer.pop_back(); | |
| 845 } else { | |
| 846 this->closeBatch(); | |
| 847 fPrevState = ss; | |
| 848 iodb->recordTraceMarkersIfNecessary(ss); | |
| 849 } | |
| 850 return true; | |
| 851 } | |
| 852 | |
| 853 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* c
md) { | 391 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* c
md) { |
| 854 if (!cmd) { | 392 if (!cmd) { |
| 855 return; | 393 return; |
| 856 } | 394 } |
| 857 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); | 395 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); |
| 858 if (activeTraceMarkers.count() > 0) { | 396 if (activeTraceMarkers.count() > 0) { |
| 859 if (cmd->isTraced()) { | 397 if (cmd->isTraced()) { |
| 860 fGpuCmdMarkers.back().addSet(activeTraceMarkers); | 398 fGpuCmdMarkers.back().addSet(activeTraceMarkers); |
| 861 } else { | 399 } else { |
| 862 cmd->makeTraced(); | 400 cmd->makeTraced(); |
| 863 fGpuCmdMarkers.push_back(activeTraceMarkers); | 401 fGpuCmdMarkers.push_back(activeTraceMarkers); |
| 864 } | 402 } |
| 865 } | 403 } |
| 866 } | 404 } |
| 867 | 405 |
| 868 void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount, | 406 void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount, |
| 869 size_t vertexStride, | 407 size_t vertexStride, |
| 870 int indexCount) { | 408 int indexCount) { |
| 871 fCommands.closeBatch(); | 409 fCommands.closeBatch(); |
| 872 | 410 |
| 873 this->INHERITED::willReserveVertexAndIndexSpace(vertexCount, vertexStride, i
ndexCount); | 411 this->INHERITED::willReserveVertexAndIndexSpace(vertexCount, vertexStride, i
ndexCount); |
| 874 } | 412 } |
| OLD | NEW |