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 |