Chromium Code Reviews| 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" | 10 #include "GrBufferAllocPool.h" |
| 11 #include "GrDrawTargetCaps.h" | 11 #include "GrDrawTargetCaps.h" |
| 12 #include "GrTextStrike.h" | 12 #include "GrTextStrike.h" |
| 13 #include "GrGpu.h" | 13 #include "GrGpu.h" |
| 14 #include "GrTemplates.h" | 14 #include "GrTemplates.h" |
| 15 #include "GrTexture.h" | 15 #include "GrTexture.h" |
| 16 | 16 |
| 17 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu, | 17 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu, |
| 18 GrVertexBufferAllocPool* vertexPool, | 18 GrVertexBufferAllocPool* vertexPool, |
| 19 GrIndexBufferAllocPool* indexPool) | 19 GrIndexBufferAllocPool* indexPool) |
| 20 : INHERITED(gpu->getContext()) | 20 : INHERITED(gpu->getContext()) |
| 21 , fCmdBuffer(kCmdBufferInitialSizeInBytes) | 21 , fCmdBuffer(kCmdBufferInitialSizeInBytes) |
| 22 , fLastState(NULL) | 22 , fLastState(NULL) |
| 23 , fDstGpu(gpu) | 23 , fDstGpu(gpu) |
| 24 , fVertexPool(*vertexPool) | 24 , fVertexPool(*vertexPool) |
| 25 , fIndexPool(*indexPool) | 25 , fIndexPool(*indexPool) |
| 26 , fPathIndexBuffer(kPathIdxBufferMinAllocCnt) | |
| 27 , fPathTransformBuffer(kPathXformBufferMinAllocCnt) | |
| 26 , fFlushing(false) | 28 , fFlushing(false) |
| 27 , fDrawID(0) { | 29 , fDrawID(0) { |
| 28 | 30 |
| 29 fDstGpu->ref(); | 31 fDstGpu->ref(); |
| 30 fCaps.reset(SkRef(fDstGpu->caps())); | 32 fCaps.reset(SkRef(fDstGpu->caps())); |
| 31 | 33 |
| 32 SkASSERT(vertexPool); | 34 SkASSERT(vertexPool); |
| 33 SkASSERT(indexPool); | 35 SkASSERT(indexPool); |
| 34 | 36 |
| 35 GeometryPoolState& poolState = fGeoPoolStateStack.push_back(); | 37 GeometryPoolState& poolState = fGeoPoolStateStack.push_back(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 if (hasLocalCoords) { | 96 if (hasLocalCoords) { |
| 95 drawState->setVertexAttribs<kRectAttribs>(3, 2 * sizeof(SkPoint) + sizeo f(SkColor)); | 97 drawState->setVertexAttribs<kRectAttribs>(3, 2 * sizeof(SkPoint) + sizeo f(SkColor)); |
| 96 } else { | 98 } else { |
| 97 drawState->setVertexAttribs<kRectAttribs>(2, sizeof(SkPoint) + sizeof(Sk Color)); | 99 drawState->setVertexAttribs<kRectAttribs>(2, sizeof(SkPoint) + sizeof(Sk Color)); |
| 98 } | 100 } |
| 99 if (0xFF == GrColorUnpackA(color)) { | 101 if (0xFF == GrColorUnpackA(color)) { |
| 100 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); | 102 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); |
| 101 } | 103 } |
| 102 } | 104 } |
| 103 | 105 |
| 106 static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin gs) { | |
| 107 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Fa ce; | |
| 108 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); | |
| 109 if (isWinding) { | |
| 110 // Double check that it is in fact winding. | |
| 111 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace)); | |
| 112 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace)); | |
| 113 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace)); | |
| 114 SkASSERT(!pathStencilSettings.isTwoSided()); | |
| 115 } | |
| 116 return isWinding; | |
| 117 } | |
| 118 | |
| 119 static bool draw_state_is_opaque(const GrDrawState& drawState) { | |
|
egdaniel
2014/11/11 18:39:07
I don't believe this function fully captures what
Chris Dalton
2014/11/11 19:29:15
Ok, so while we wait for isUnblended can I capture
| |
| 120 GrBlendCoeff dstBlendCoeff = drawState.getDstBlendCoeff(); | |
| 121 return (kZero_GrBlendCoeff == dstBlendCoeff || | |
| 122 (kISA_GrBlendCoeff == dstBlendCoeff && drawState.srcAlphaWillBeOne() )); | |
| 123 } | |
| 124 | |
| 104 enum { | 125 enum { |
| 105 kTraceCmdBit = 0x80, | 126 kTraceCmdBit = 0x80, |
| 106 kCmdMask = 0x7f, | 127 kCmdMask = 0x7f, |
| 107 }; | 128 }; |
| 108 | 129 |
| 109 static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; } | 130 static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; } |
| 110 | 131 |
| 111 static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; } | 132 static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; } |
| 112 | 133 |
| 113 static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTr aceCmdBit); } | 134 static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTr aceCmdBit); } |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 326 PathTransformType transformsType, | 347 PathTransformType transformsType, |
| 327 const GrClipMaskManager::ScissorState& sci ssorState, | 348 const GrClipMaskManager::ScissorState& sci ssorState, |
| 328 const GrStencilSettings& stencilSettings, | 349 const GrStencilSettings& stencilSettings, |
| 329 const GrDeviceCoordTexture* dstCopy) { | 350 const GrDeviceCoordTexture* dstCopy) { |
| 330 SkASSERT(pathRange); | 351 SkASSERT(pathRange); |
| 331 SkASSERT(indices); | 352 SkASSERT(indices); |
| 332 SkASSERT(transforms); | 353 SkASSERT(transforms); |
| 333 | 354 |
| 334 this->recordStateIfNecessary(); | 355 this->recordStateIfNecessary(); |
| 335 | 356 |
| 336 int sizeOfIndices = sizeof(uint32_t) * count; | 357 int indicesLocation = fPathIndexBuffer.append(indices, count); |
| 337 int sizeOfTransforms = sizeof(float) * count * | 358 int transformsLocation = fPathTransformBuffer.append(transforms, |
| 338 GrPathRendering::PathTransformSize(transformsType); | 359 GrPathRendering::PathTransformSize(transformsTy pe) * count); |
| 339 | 360 |
| 340 DrawPaths* dp = GrNEW_APPEND_WITH_DATA_TO_RECORDER(fCmdBuffer, DrawPaths, (p athRange), | 361 if (kDrawPaths_Cmd == fCmdBuffer.back().fType) { |
| 341 sizeOfIndices + sizeOfTra nsforms); | 362 // The previous command was also DrawPaths. Try to collapse this call in to the one |
| 342 memcpy(dp->indices(), indices, sizeOfIndices); | 363 // before. Note that stencilling all the paths at once, then covering, m ay not be |
| 364 // equivalent to two separate draw calls if there is overlap. Blending w on't work, | |
| 365 // and the combined calls may also cancel each other's winding numbers i n some | |
| 366 // places. For now the winding numbers are only an issue if the fill is even/odd, | |
| 367 // because DrawPaths is currently only used for glyphs, and glyphs in th e same | |
| 368 // font tend to all wind in the same direction. | |
| 369 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back()); | |
| 370 if (pathRange == previous->pathRange() && | |
| 371 transformsType == previous->fTransformsType && | |
| 372 scissorState == previous->fScissorState && | |
| 373 stencilSettings == previous->fStencilSettings && | |
| 374 path_fill_type_is_winding(stencilSettings) && | |
| 375 draw_state_is_opaque(this->getDrawState())) { | |
|
bsalomon
2014/11/11 14:41:25
Could/should you check that the b.boxes don't over
Chris Dalton
2014/11/11 17:49:07
In theory, yes. But right now there isn't a way of
| |
| 376 // Fold this DrawPaths call into the one previous. | |
| 377 SkASSERT(!dstCopy || !dstCopy->texture()); | |
| 378 previous->fCount += count; | |
| 379 return; | |
| 380 } | |
| 381 } | |
| 382 | |
| 383 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange)) ; | |
| 384 dp->fIndicesLocation = indicesLocation; | |
| 343 dp->fCount = count; | 385 dp->fCount = count; |
| 344 memcpy(dp->transforms(), transforms, sizeOfTransforms); | 386 dp->fTransformsLocation = transformsLocation; |
| 345 dp->fTransformsType = transformsType; | 387 dp->fTransformsType = transformsType; |
| 346 dp->fScissorState = scissorState; | 388 dp->fScissorState = scissorState; |
| 347 dp->fStencilSettings = stencilSettings; | 389 dp->fStencilSettings = stencilSettings; |
| 348 if (dstCopy) { | 390 if (dstCopy) { |
| 349 dp->fDstCopy = *dstCopy; | 391 dp->fDstCopy = *dstCopy; |
| 350 } | 392 } |
| 351 | 393 |
| 352 this->recordTraceMarkersIfNecessary(); | 394 this->recordTraceMarkersIfNecessary(); |
| 353 } | 395 } |
| 354 | 396 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 clr->fColor = GrColor_ILLEGAL; | 438 clr->fColor = GrColor_ILLEGAL; |
| 397 this->recordTraceMarkersIfNecessary(); | 439 this->recordTraceMarkersIfNecessary(); |
| 398 } | 440 } |
| 399 | 441 |
| 400 void GrInOrderDrawBuffer::reset() { | 442 void GrInOrderDrawBuffer::reset() { |
| 401 SkASSERT(1 == fGeoPoolStateStack.count()); | 443 SkASSERT(1 == fGeoPoolStateStack.count()); |
| 402 this->resetVertexSource(); | 444 this->resetVertexSource(); |
| 403 this->resetIndexSource(); | 445 this->resetIndexSource(); |
| 404 | 446 |
| 405 fCmdBuffer.reset(); | 447 fCmdBuffer.reset(); |
| 448 fPathIndexBuffer.reset(); | |
| 449 fPathTransformBuffer.reset(); | |
| 406 fLastState = NULL; | 450 fLastState = NULL; |
| 407 fVertexPool.reset(); | 451 fVertexPool.reset(); |
| 408 fIndexPool.reset(); | 452 fIndexPool.reset(); |
| 409 fGpuCmdMarkers.reset(); | 453 fGpuCmdMarkers.reset(); |
| 410 } | 454 } |
| 411 | 455 |
| 412 void GrInOrderDrawBuffer::flush() { | 456 void GrInOrderDrawBuffer::flush() { |
| 413 if (fFlushing) { | 457 if (fFlushing) { |
| 414 return; | 458 return; |
| 415 } | 459 } |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 445 fDstGpu->addGpuTraceMarker(&newMarker); | 489 fDstGpu->addGpuTraceMarker(&newMarker); |
| 446 ++currCmdMarker; | 490 ++currCmdMarker; |
| 447 } | 491 } |
| 448 | 492 |
| 449 SkDEBUGCODE(bool isDraw = kDraw_Cmd == strip_trace_bit(iter->fType) || | 493 SkDEBUGCODE(bool isDraw = kDraw_Cmd == strip_trace_bit(iter->fType) || |
| 450 kStencilPath_Cmd == strip_trace_bit(iter->fTyp e) || | 494 kStencilPath_Cmd == strip_trace_bit(iter->fTyp e) || |
| 451 kDrawPath_Cmd == strip_trace_bit(iter->fType) || | 495 kDrawPath_Cmd == strip_trace_bit(iter->fType) || |
| 452 kDrawPaths_Cmd == strip_trace_bit(iter->fType) ); | 496 kDrawPaths_Cmd == strip_trace_bit(iter->fType) ); |
| 453 SkASSERT(!isDraw || fDstGpu->drawState() != prevDrawState); | 497 SkASSERT(!isDraw || fDstGpu->drawState() != prevDrawState); |
| 454 | 498 |
| 455 iter->execute(fDstGpu); | 499 iter->execute(this); |
| 456 | 500 |
| 457 if (cmd_has_trace_marker(iter->fType)) { | 501 if (cmd_has_trace_marker(iter->fType)) { |
| 458 fDstGpu->removeGpuTraceMarker(&newMarker); | 502 fDstGpu->removeGpuTraceMarker(&newMarker); |
| 459 } | 503 } |
| 460 } | 504 } |
| 461 | 505 |
| 462 fDstGpu->restoreActiveTraceMarkers(); | 506 fDstGpu->restoreActiveTraceMarkers(); |
| 463 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker); | 507 SkASSERT(fGpuCmdMarkers.count() == currCmdMarker); |
| 464 | 508 |
| 465 fDstGpu->setDrawState(prevDrawState); | 509 fDstGpu->setDrawState(prevDrawState); |
| 466 prevDrawState->unref(); | 510 prevDrawState->unref(); |
| 467 this->reset(); | 511 this->reset(); |
| 468 ++fDrawID; | 512 ++fDrawID; |
| 469 } | 513 } |
| 470 | 514 |
| 471 void GrInOrderDrawBuffer::Draw::execute(GrGpu* gpu) { | 515 void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf) { |
| 516 GrGpu* gpu = buf->dstGpu(); | |
| 472 gpu->setVertexSourceToBuffer(this->vertexBuffer()); | 517 gpu->setVertexSourceToBuffer(this->vertexBuffer()); |
| 473 if (fInfo.isIndexed()) { | 518 if (fInfo.isIndexed()) { |
| 474 gpu->setIndexSourceToBuffer(this->indexBuffer()); | 519 gpu->setIndexSourceToBuffer(this->indexBuffer()); |
| 475 } | 520 } |
| 476 gpu->draw(fInfo, fScissorState); | 521 gpu->draw(fInfo, fScissorState); |
| 477 } | 522 } |
| 478 | 523 |
| 479 void GrInOrderDrawBuffer::StencilPath::execute(GrGpu* gpu) { | 524 void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf) { |
| 525 GrGpu* gpu = buf->dstGpu(); | |
| 480 gpu->stencilPath(this->path(), fScissorState, fStencilSettings); | 526 gpu->stencilPath(this->path(), fScissorState, fStencilSettings); |
| 481 } | 527 } |
| 482 | 528 |
| 483 void GrInOrderDrawBuffer::DrawPath::execute(GrGpu* gpu) { | 529 void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf) { |
| 530 GrGpu* gpu = buf->dstGpu(); | |
| 484 gpu->drawPath(this->path(), fScissorState, fStencilSettings, | 531 gpu->drawPath(this->path(), fScissorState, fStencilSettings, |
| 485 fDstCopy.texture() ? &fDstCopy : NULL); | 532 fDstCopy.texture() ? &fDstCopy : NULL); |
| 486 } | 533 } |
| 487 | 534 |
| 488 void GrInOrderDrawBuffer::DrawPaths::execute(GrGpu* gpu) { | 535 void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf) { |
| 489 gpu->drawPaths(this->pathRange(), this->indices(), fCount, this->transforms( ), | 536 GrGpu* gpu = buf->dstGpu(); |
| 490 fTransformsType, fScissorState, fStencilSettings, | 537 gpu->drawPaths(this->pathRange(), buf->pathIndexBuffer() + fIndicesLocation, fCount, |
| 491 fDstCopy.texture() ? &fDstCopy : NULL); | 538 buf->pathTransformBuffer() + fTransformsLocation, fTransforms Type, |
| 539 fScissorState, fStencilSettings, fDstCopy.texture() ? &fDstCo py : NULL); | |
| 492 } | 540 } |
| 493 | 541 |
| 494 void GrInOrderDrawBuffer::SetState::execute(GrGpu* gpu) { | 542 void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer* buf) { |
| 543 GrGpu* gpu = buf->dstGpu(); | |
| 495 gpu->setDrawState(&fState); | 544 gpu->setDrawState(&fState); |
| 496 } | 545 } |
| 497 | 546 |
| 498 void GrInOrderDrawBuffer::Clear::execute(GrGpu* gpu) { | 547 void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf) { |
| 548 GrGpu* gpu = buf->dstGpu(); | |
| 499 if (GrColor_ILLEGAL == fColor) { | 549 if (GrColor_ILLEGAL == fColor) { |
| 500 gpu->discard(this->renderTarget()); | 550 gpu->discard(this->renderTarget()); |
| 501 } else { | 551 } else { |
| 502 gpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget()); | 552 gpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget()); |
| 503 } | 553 } |
| 504 } | 554 } |
| 505 | 555 |
| 506 void GrInOrderDrawBuffer::ClearStencilClip::execute(GrGpu* gpu) { | 556 void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf) { |
| 507 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget()); | 557 GrGpu* gpu = buf->dstGpu(); |
| 558 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget()); | |
| 508 } | 559 } |
| 509 | 560 |
| 510 void GrInOrderDrawBuffer::CopySurface::execute(GrGpu* gpu) { | 561 void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf) { |
| 562 GrGpu* gpu = buf->dstGpu(); | |
| 511 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint); | 563 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint); |
| 512 } | 564 } |
| 513 | 565 |
| 514 bool GrInOrderDrawBuffer::copySurface(GrSurface* dst, | 566 bool GrInOrderDrawBuffer::copySurface(GrSurface* dst, |
| 515 GrSurface* src, | 567 GrSurface* src, |
| 516 const SkIRect& srcRect, | 568 const SkIRect& srcRect, |
| 517 const SkIPoint& dstPoint) { | 569 const SkIPoint& dstPoint) { |
| 518 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) { | 570 if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) { |
| 519 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst , src)); | 571 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst , src)); |
| 520 cs->fSrcRect = srcRect; | 572 cs->fSrcRect = srcRect; |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 724 | 776 |
| 725 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() { | 777 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() { |
| 726 SkASSERT(!fCmdBuffer.empty()); | 778 SkASSERT(!fCmdBuffer.empty()); |
| 727 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType)); | 779 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType)); |
| 728 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); | 780 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); |
| 729 if (activeTraceMarkers.count() > 0) { | 781 if (activeTraceMarkers.count() > 0) { |
| 730 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType); | 782 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType); |
| 731 fGpuCmdMarkers.push_back(activeTraceMarkers); | 783 fGpuCmdMarkers.push_back(activeTraceMarkers); |
| 732 } | 784 } |
| 733 } | 785 } |
| 786 | |
| 787 template<typename T> int GrInOrderDrawBuffer::DataBuffer<T>::append(const T* arr ay, int count) { | |
| 788 if (fCount + count > fAllocCnt) { | |
| 789 fAllocCnt = SkTMax(2 * fAllocCnt, (fCount + count) * 3 / 2); | |
| 790 fBuffer.realloc(fAllocCnt); | |
| 791 } | |
| 792 int location = fCount; | |
| 793 memcpy(fBuffer + location, array, sizeof(T) * count); | |
| 794 fCount += count; | |
| 795 return location; | |
| 796 } | |
| 797 | |
| 798 template<typename T> void GrInOrderDrawBuffer::DataBuffer<T>::reset() { | |
| 799 // Assume the next time this buffer fills up it will use approximately the s ame amount | |
| 800 // of space as last time. Only resize if we're using less than a third of th e | |
| 801 // allocated space, and leave enough for 50% growth over last time. | |
| 802 if (3 * fCount < fAllocCnt && fAllocCnt > fMinAllocCnt) { | |
| 803 fAllocCnt = SkTMax(fMinAllocCnt, fCount * 3 / 2); | |
| 804 fBuffer.reset(fAllocCnt); | |
| 805 } | |
| 806 fCount = 0; | |
| 807 } | |
| OLD | NEW |