Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 "GrAARectRenderer.h" | 8 #include "GrAARectRenderer.h" |
| 9 #include "GrBatch.h" | 9 #include "GrBatch.h" |
| 10 #include "GrBatchTarget.h" | 10 #include "GrBatchTarget.h" |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 SkASSERT(canTweakAlphaForCoverage ? | 135 SkASSERT(canTweakAlphaForCoverage ? |
| 136 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : | 136 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : |
| 137 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr)); | 137 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr)); |
| 138 | 138 |
| 139 int instanceCount = fGeoData.count(); | 139 int instanceCount = fGeoData.count(); |
| 140 int vertexCount = kVertsPerAAFillRect * instanceCount; | 140 int vertexCount = kVertsPerAAFillRect * instanceCount; |
| 141 | 141 |
| 142 const GrVertexBuffer* vertexBuffer; | 142 const GrVertexBuffer* vertexBuffer; |
| 143 int firstVertex; | 143 int firstVertex; |
| 144 | 144 |
| 145 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride, | 145 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, |
| 146 vertexCount, | 146 vertexCount, |
| 147 &vertexBuffer, | 147 &vertexBuffer, |
| 148 &firstVertex); | 148 &firstVertex); |
| 149 | 149 |
| 150 for (int i = 0; i < instanceCount; i++) { | 150 for (int i = 0; i < instanceCount; i++) { |
| 151 const Geometry& args = fGeoData[i]; | 151 const Geometry& args = fGeoData[i]; |
| 152 this->generateAAFillRectGeometry(vertices, | 152 this->generateAAFillRectGeometry(vertices, |
| 153 i * kVertsPerAAFillRect * vertexStride, | 153 i * kVertsPerAAFillRect * vertexStr ide, |
| 154 vertexStride, | 154 vertexStride, |
| 155 args.fColor, | 155 args.fColor, |
| 156 args.fViewMatrix, | 156 args.fViewMatrix, |
| 157 args.fRect, | 157 args.fRect, |
| 158 args.fDevRect, | 158 args.fDevRect, |
| 159 canTweakAlphaForCoverage); | 159 canTweakAlphaForCoverage); |
| 160 } | 160 } |
| 161 | 161 |
| 162 GrDrawTarget::DrawInfo drawInfo; | 162 GrDrawTarget::DrawInfo drawInfo; |
| 163 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType); | 163 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType); |
| 164 drawInfo.setStartVertex(0); | 164 drawInfo.setStartVertex(0); |
| 165 drawInfo.setStartIndex(0); | 165 drawInfo.setStartIndex(0); |
| 166 drawInfo.setVerticesPerInstance(kVertsPerAAFillRect); | 166 drawInfo.setVerticesPerInstance(kVertsPerAAFillRect); |
| 167 drawInfo.setIndicesPerInstance(kIndicesPerAAFillRect); | 167 drawInfo.setIndicesPerInstance(kIndicesPerAAFillRect); |
| 168 drawInfo.adjustStartVertex(firstVertex); | 168 drawInfo.adjustStartVertex(firstVertex); |
| 169 drawInfo.setVertexBuffer(vertexBuffer); | 169 drawInfo.setVertexBuffer(vertexBuffer); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 193 } | 193 } |
| 194 | 194 |
| 195 GrColor color() const { return fBatch.fColor; } | 195 GrColor color() const { return fBatch.fColor; } |
| 196 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | 196 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
| 197 bool canTweakAlphaForCoverage() const { return fBatchOpt.fCanTweakAlphaForCo verage; } | 197 bool canTweakAlphaForCoverage() const { return fBatchOpt.fCanTweakAlphaForCo verage; } |
| 198 bool colorIgnored() const { return fBatch.fColorIgnored; } | 198 bool colorIgnored() const { return fBatch.fColorIgnored; } |
| 199 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | 199 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } |
| 200 | 200 |
| 201 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { | 201 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { |
| 202 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); | 202 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); |
| 203 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) { | |
| 204 return false; | |
| 205 } | |
| 206 | 203 |
| 207 if (this->colorIgnored() != that->colorIgnored()) { | 204 SkASSERT(this->canTweakAlphaForCoverage() == that->canTweakAlphaForCover age() && |
| 208 return false; | 205 this->usesLocalCoords() == that->usesLocalCoords() && |
| 209 } | 206 this->colorIgnored() == that->colorIgnored()); |
| 210 | |
| 211 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | |
| 212 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses | 207 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses |
| 213 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix | 208 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix |
| 214 // using vertex attributes in these cases, but haven't investigated that | 209 // using vertex attributes in these cases, but haven't investigated that |
| 215 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) { | 210 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) { |
| 216 return false; | 211 return false; |
| 217 } | 212 } |
| 218 | 213 |
| 219 if (this->color() != that->color()) { | 214 if (this->color() != that->color()) { |
| 220 fBatch.fColor = GrColor_ILLEGAL; | 215 fBatch.fColor = GrColor_ILLEGAL; |
| 221 } | 216 } |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 539 // edge, while vertex number of inner edge is 4, the same as miter-stroke. | 534 // edge, while vertex number of inner edge is 4, the same as miter-stroke. |
| 540 if (!miterStroke) { | 535 if (!miterStroke) { |
| 541 devOutside.inset(0, ry); | 536 devOutside.inset(0, ry); |
| 542 devOutsideAssist.outset(0, ry); | 537 devOutsideAssist.outset(0, ry); |
| 543 } | 538 } |
| 544 | 539 |
| 545 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside, | 540 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside, |
| 546 devOutsideAssist, devInside, miterStroke); | 541 devOutsideAssist, devInside, miterStroke); |
| 547 } | 542 } |
| 548 | 543 |
| 549 static const GrGeometryProcessor* create_rect_gp(const GrPipelineBuilder& pipeln eBuilder, | 544 class AAStrokeRectBatch : public GrBatch { |
| 550 GrColor color, | 545 public: |
| 551 CoverageAttribType* type, | 546 struct Geometry { |
|
robertphillips
2015/02/12 14:53:29
Line these guys up?
That's a lot of data for a si
| |
| 552 const SkMatrix& localMatrix) { | 547 GrColor fColor; |
| 553 uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType; | 548 SkMatrix fViewMatrix; |
| 554 const GrGeometryProcessor* gp; | 549 SkRect fDevOutside; |
| 555 if (pipelneBuilder.canTweakAlphaForCoverage()) { | 550 SkRect fDevOutsideAssist; |
| 556 gp = GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), localM atrix); | 551 SkRect fDevInside; |
| 557 SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::Positi onColorAttr)); | 552 bool fMiterStroke; |
| 558 *type = kUseColor_CoverageAttribType; | 553 }; |
| 559 } else { | 554 |
| 560 flags |= GrDefaultGeoProcFactory::kCoverage_GPType; | 555 static GrBatch* Create(const Geometry& geometry, const GrIndexBuffer* indexB uffer) { |
| 561 gp = GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), localM atrix, | 556 return SkNEW_ARGS(AAStrokeRectBatch, (geometry, indexBuffer)); |
| 562 GrColorIsOpaque(color)); | 557 } |
| 563 SkASSERT(gp->getVertexStride()==sizeof(GrDefaultGeoProcFactory::Position ColorCoverageAttr)); | 558 |
| 564 *type = kUseCoverage_CoverageAttribType; | 559 const char* name() const SK_OVERRIDE { return "AAStrokeRect"; } |
| 565 } | 560 |
| 566 return gp; | 561 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { |
| 567 } | 562 // When this is called on a batch, there is only one geometry bundle |
| 563 if (!this->canTweakAlphaForCoverage() && GrColorIsOpaque(fGeoData[0].fCo lor)) { | |
| 564 out->setUnknownOpaqueFourComponents(); | |
| 565 } else { | |
| 566 out->setUnknownFourComponents(); | |
| 567 } | |
| 568 } | |
| 569 | |
| 570 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID E { | |
| 571 if (this->canTweakAlphaForCoverage()) { | |
| 572 // uniform coverage | |
| 573 out->setKnownSingleComponent(0xff); | |
| 574 } else { | |
| 575 out->setUnknownSingleComponent(); | |
| 576 } | |
| 577 } | |
| 578 | |
| 579 void initBatchOpt(const GrBatchOpt& batchOpt) { | |
| 580 fBatchOpt = batchOpt; | |
| 581 } | |
| 582 | |
| 583 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { | |
| 584 // Handle any color overrides | |
| 585 if (init.fColorIgnored) { | |
| 586 fGeoData[0].fColor = GrColor_ILLEGAL; | |
| 587 } else if (GrColor_ILLEGAL != init.fOverrideColor) { | |
| 588 fGeoData[0].fColor = init.fOverrideColor; | |
| 589 } | |
| 590 | |
| 591 // setup batch properties | |
| 592 fBatch.fColorIgnored = init.fColorIgnored; | |
| 593 fBatch.fColor = fGeoData[0].fColor; | |
| 594 fBatch.fUsesLocalCoords = init.fUsesLocalCoords; | |
| 595 fBatch.fCoverageIgnored = init.fCoverageIgnored; | |
| 596 fBatch.fMiterStroke = fGeoData[0].fMiterStroke; | |
| 597 } | |
| 598 | |
| 599 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE { | |
| 600 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); | |
| 601 | |
| 602 SkMatrix localMatrix; | |
| 603 if (!this->viewMatrix().invert(&localMatrix)) { | |
| 604 SkDebugf("Cannot invert\n"); | |
| 605 return; | |
| 606 } | |
| 607 | |
|
robertphillips
2015/02/12 14:53:29
SkAutoTUnref ?
| |
| 608 const GrGeometryProcessor* gp = create_fill_rect_gp(canTweakAlphaForCove rage, | |
| 609 localMatrix); | |
| 610 | |
| 611 batchTarget->initDraw(gp, pipeline); | |
| 612 gp->unref(); | |
| 613 | |
| 614 // TODO this is hacky, but the only way we have to initialize the GP is to use the | |
| 615 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch | |
| 616 // everywhere we can remove this nastiness | |
| 617 GrPipelineInfo init; | |
| 618 init.fColorIgnored = fBatch.fColorIgnored; | |
| 619 init.fOverrideColor = GrColor_ILLEGAL; | |
| 620 init.fCoverageIgnored = fBatch.fCoverageIgnored; | |
| 621 init.fUsesLocalCoords = this->usesLocalCoords(); | |
| 622 gp->initBatchTracker(batchTarget->currentBatchTracker(), init); | |
| 623 | |
| 624 size_t vertexStride = gp->getVertexStride(); | |
| 625 | |
| 626 SkASSERT(canTweakAlphaForCoverage ? | |
| 627 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : | |
| 628 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr)); | |
| 629 | |
| 630 int innerVertexNum = 4; | |
| 631 int outerVertexNum = this->miterStroke() ? 4 : 8; | |
| 632 int totalVertexNum = (outerVertexNum + innerVertexNum) * 2; | |
| 633 | |
| 634 int instanceCount = fGeoData.count(); | |
| 635 int vertexCount = totalVertexNum * instanceCount; | |
| 636 | |
| 637 const GrVertexBuffer* vertexBuffer; | |
| 638 int firstVertex; | |
| 639 | |
| 640 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, | |
| 641 vertexCount, | |
| 642 &vertexBuffer, | |
| 643 &firstVertex); | |
| 644 | |
| 645 for (int i = 0; i < instanceCount; i++) { | |
| 646 const Geometry& args = fGeoData[i]; | |
| 647 this->generateAAStrokeRectGeometry(vertices, | |
| 648 i * totalVertexNum * vertexStride , | |
| 649 vertexStride, | |
| 650 outerVertexNum, | |
| 651 innerVertexNum, | |
| 652 args.fColor, | |
| 653 args.fViewMatrix, | |
| 654 args.fDevOutside, | |
| 655 args.fDevOutsideAssist, | |
| 656 args.fDevInside, | |
| 657 args.fMiterStroke, | |
| 658 canTweakAlphaForCoverage); | |
| 659 } | |
| 660 | |
| 661 GrDrawTarget::DrawInfo drawInfo; | |
| 662 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType); | |
| 663 drawInfo.setStartVertex(0); | |
| 664 drawInfo.setStartIndex(0); | |
| 665 drawInfo.setVerticesPerInstance(totalVertexNum); | |
| 666 drawInfo.setIndicesPerInstance(aa_stroke_rect_index_count(this->miterStr oke())); | |
| 667 drawInfo.adjustStartVertex(firstVertex); | |
| 668 drawInfo.setVertexBuffer(vertexBuffer); | |
| 669 drawInfo.setIndexBuffer(fIndexBuffer); | |
| 670 | |
| 671 int maxInstancesPerDraw = kNumBevelStrokeRectsInIndexBuffer; | |
| 672 | |
| 673 while (instanceCount) { | |
| 674 drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw) ); | |
| 675 drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.vertices PerInstance()); | |
| 676 drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPe rInstance()); | |
| 677 | |
| 678 batchTarget->draw(drawInfo); | |
| 679 | |
| 680 drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCoun t()); | |
| 681 instanceCount -= drawInfo.instanceCount(); | |
| 682 } | |
| 683 } | |
| 684 | |
|
robertphillips
2015/02/12 14:53:29
can this be const?
| |
| 685 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 686 | |
| 687 private: | |
| 688 AAStrokeRectBatch(const Geometry& geometry, const GrIndexBuffer* indexBuffer ) | |
| 689 : fIndexBuffer(indexBuffer) { | |
| 690 this->initClassID<AAStrokeRectBatch>(); | |
| 691 fGeoData.push_back(geometry); | |
| 692 } | |
| 693 | |
| 694 GrColor color() const { return fBatch.fColor; } | |
| 695 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | |
| 696 bool canTweakAlphaForCoverage() const { return fBatchOpt.fCanTweakAlphaForCo verage; } | |
| 697 bool colorIgnored() const { return fBatch.fColorIgnored; } | |
| 698 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
| 699 bool miterStroke() const { return fBatch.fMiterStroke; } | |
| 700 | |
| 701 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { | |
| 702 AAStrokeRectBatch* that = t->cast<AAStrokeRectBatch>(); | |
| 703 | |
| 704 if (this->miterStroke() != that->miterStroke()) { | |
| 705 return false; | |
| 706 } | |
| 707 | |
| 708 SkASSERT(this->canTweakAlphaForCoverage() == that->canTweakAlphaForCover age() && | |
| 709 this->usesLocalCoords() == that->usesLocalCoords() && | |
| 710 this->colorIgnored() == that->colorIgnored()); | |
| 711 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses | |
| 712 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix | |
| 713 // using vertex attributes in these cases, but haven't investigated that | |
| 714 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) { | |
| 715 return false; | |
| 716 } | |
| 717 | |
| 718 if (this->color() != that->color()) { | |
| 719 fBatch.fColor = GrColor_ILLEGAL; | |
| 720 } | |
| 721 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; | |
| 722 return true; | |
| 723 } | |
| 724 | |
| 725 void generateAAStrokeRectGeometry(void* vertices, | |
| 726 uint32_t offset, | |
| 727 uint32_t vertexStride, | |
| 728 int outerVertexNum, | |
| 729 int innerVertexNum, | |
| 730 GrColor color, | |
| 731 const SkMatrix& viewMatrix, | |
| 732 const SkRect& devOutside, | |
| 733 const SkRect& devOutsideAssist, | |
| 734 const SkRect& devInside, | |
| 735 bool miterStroke, | |
| 736 bool tweakAlphaForCoverage) const { | |
| 737 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; | |
| 738 | |
| 739 // We create vertices for four nested rectangles. There are two ramps fr om 0 to full | |
| 740 // coverage, one on the exterior of the stroke and the other on the inte rior. | |
| 741 // The following pointers refer to the four rects, from outermost to inn ermost. | |
| 742 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); | |
| 743 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * v ertexStride); | |
| 744 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vertexStride); | |
| 745 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + | |
| 746 (2 * outerVertexNum + inne rVertexNum) * | |
| 747 vertexStride); | |
| 748 | |
|
robertphillips
2015/02/12 14:53:29
Hmm - do we still need this guard?
| |
| 749 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX | |
| 750 // TODO: this only really works if the X & Y margins are the same all ar ound | |
| 751 // the rect (or if they are all >= 1.0). | |
| 752 SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.f Right); | |
| 753 inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft); | |
| 754 inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop); | |
| 755 if (miterStroke) { | |
| 756 inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devI nside.fBottom); | |
| 757 } else { | |
| 758 inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - | |
| 759 devInside.fBottom); | |
| 760 } | |
| 761 SkASSERT(inset >= 0); | |
| 762 #else | |
| 763 SkScalar inset = SK_ScalarHalf; | |
| 764 #endif | |
| 765 | |
| 766 if (miterStroke) { | |
| 767 // outermost | |
| 768 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK _ScalarHalf); | |
| 769 // inner two | |
| 770 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset); | |
| 771 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset); | |
| 772 // innermost | |
| 773 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf); | |
| 774 } else { | |
| 775 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vert exStride); | |
| 776 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + | |
| 777 (outerVertexNum + 4) * | |
| 778 vertexStride); | |
| 779 // outermost | |
| 780 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK _ScalarHalf); | |
| 781 set_inset_fan(fan0AssistPos, vertexStride, devOutsideAssist, -SK_Sca larHalf, | |
| 782 -SK_ScalarHalf); | |
| 783 // outer one of the inner two | |
| 784 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset); | |
| 785 set_inset_fan(fan1AssistPos, vertexStride, devOutsideAssist, inset, inset); | |
| 786 // inner one of the inner two | |
| 787 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset); | |
| 788 // innermost | |
| 789 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf); | |
| 790 } | |
| 791 | |
| 792 // Make verts point to vertex color and then set all the color and cover age vertex attrs | |
| 793 // values. The outermost rect has 0 coverage | |
| 794 verts += sizeof(SkPoint); | |
| 795 for (int i = 0; i < outerVertexNum; ++i) { | |
| 796 if (tweakAlphaForCoverage) { | |
| 797 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; | |
| 798 } else { | |
| 799 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | |
| 800 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = 0; | |
| 801 } | |
| 802 } | |
| 803 | |
| 804 // scale is the coverage for the the inner two rects. | |
| 805 int scale; | |
| 806 if (inset < SK_ScalarHalf) { | |
| 807 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)) ; | |
| 808 SkASSERT(scale >= 0 && scale <= 255); | |
| 809 } else { | |
| 810 scale = 0xff; | |
| 811 } | |
| 812 | |
| 813 float innerCoverage = GrNormalizeByteToFloat(scale); | |
| 814 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale ); | |
| 815 | |
| 816 verts += outerVertexNum * vertexStride; | |
| 817 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) { | |
| 818 if (tweakAlphaForCoverage) { | |
| 819 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo lor; | |
| 820 } else { | |
| 821 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | |
| 822 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = | |
| 823 innerCoverage; | |
| 824 } | |
| 825 } | |
| 826 | |
| 827 // The innermost rect has 0 coverage | |
| 828 verts += (outerVertexNum + innerVertexNum) * vertexStride; | |
| 829 for (int i = 0; i < innerVertexNum; ++i) { | |
| 830 if (tweakAlphaForCoverage) { | |
| 831 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; | |
| 832 } else { | |
| 833 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | |
| 834 *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(Gr Color)) = 0; | |
| 835 } | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 struct BatchTracker { | |
|
robertphillips
2015/02/12 14:53:29
Line these guys up?
| |
| 840 GrColor fColor; | |
| 841 bool fUsesLocalCoords; | |
| 842 bool fColorIgnored; | |
| 843 bool fCoverageIgnored; | |
| 844 bool fMiterStroke; | |
| 845 }; | |
| 846 | |
| 847 GrBatchOpt fBatchOpt; | |
| 848 BatchTracker fBatch; | |
| 849 const GrIndexBuffer* fIndexBuffer; | |
| 850 SkSTArray<1, Geometry, true> fGeoData; | |
| 851 }; | |
| 568 | 852 |
| 569 | 853 |
| 570 void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target, | 854 void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target, |
| 571 GrPipelineBuilder* pipelineBuilder, | 855 GrPipelineBuilder* pipelineBuilder, |
| 572 GrColor color, | 856 GrColor color, |
| 573 const SkMatrix& viewMatrix, | 857 const SkMatrix& viewMatrix, |
| 574 const SkRect& devOutside, | 858 const SkRect& devOutside, |
| 575 const SkRect& devOutsideAssist, | 859 const SkRect& devOutsideAssist, |
| 576 const SkRect& devInside, | 860 const SkRect& devInside, |
| 577 bool miterStroke) { | 861 bool miterStroke) { |
| 578 SkMatrix localMatrix; | |
| 579 if (!viewMatrix.invert(&localMatrix)) { | |
| 580 SkDebugf("Cannot invert\n"); | |
| 581 return; | |
| 582 } | |
| 583 | |
| 584 CoverageAttribType type; | |
| 585 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(*pipelineBuilder, color, &type, | |
| 586 localMatrix)); | |
| 587 | |
| 588 int innerVertexNum = 4; | |
| 589 int outerVertexNum = miterStroke ? 4 : 8; | |
| 590 int totalVertexNum = (outerVertexNum + innerVertexNum) * 2; | |
| 591 | |
| 592 size_t vstride = gp->getVertexStride(); | |
| 593 GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, vstride, 0); | |
| 594 if (!geo.succeeded()) { | |
| 595 SkDebugf("Failed to get space for vertices!\n"); | |
| 596 return; | |
| 597 } | |
| 598 GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(miterStroke); | 862 GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(miterStroke); |
| 599 if (NULL == indexBuffer) { | 863 if (NULL == indexBuffer) { |
| 600 SkDebugf("Failed to create index buffer!\n"); | 864 SkDebugf("Failed to create index buffer!\n"); |
| 601 return; | 865 return; |
| 602 } | 866 } |
| 603 | 867 |
| 604 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); | 868 AAStrokeRectBatch::Geometry geometry; |
| 605 | 869 geometry.fColor = color; |
| 606 // We create vertices for four nested rectangles. There are two ramps from 0 to full | 870 geometry.fViewMatrix = viewMatrix; |
| 607 // coverage, one on the exterior of the stroke and the other on the interior . | 871 geometry.fDevOutside = devOutside; |
| 608 // The following pointers refer to the four rects, from outermost to innermo st. | 872 geometry.fDevOutsideAssist = devOutsideAssist; |
| 609 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); | 873 geometry.fDevInside = devInside; |
| 610 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vstri de); | 874 geometry.fMiterStroke = miterStroke; |
| 611 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * v stride); | 875 |
| 612 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vstride); | 876 SkAutoTUnref<GrBatch> batch(AAStrokeRectBatch::Create(geometry, indexBuffer) ); |
| 613 | 877 target->drawBatch(pipelineBuilder, batch); |
| 614 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX | |
| 615 // TODO: this only really works if the X & Y margins are the same all around | |
| 616 // the rect (or if they are all >= 1.0). | |
| 617 SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRigh t); | |
| 618 inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft); | |
| 619 inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop); | |
| 620 if (miterStroke) { | |
| 621 inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInsid e.fBottom); | |
| 622 } else { | |
| 623 inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - de vInside.fBottom); | |
| 624 } | |
| 625 SkASSERT(inset >= 0); | |
| 626 #else | |
| 627 SkScalar inset = SK_ScalarHalf; | |
| 628 #endif | |
| 629 | |
| 630 if (miterStroke) { | |
| 631 // outermost | |
| 632 set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHa lf); | |
| 633 // inner two | |
| 634 set_inset_fan(fan1Pos, vstride, devOutside, inset, inset); | |
| 635 set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset); | |
| 636 // innermost | |
| 637 set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHa lf); | |
| 638 } else { | |
| 639 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vstride) ; | |
| 640 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertex Num + 4) * vstride); | |
| 641 // outermost | |
| 642 set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHa lf); | |
| 643 set_inset_fan(fan0AssistPos, vstride, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf); | |
| 644 // outer one of the inner two | |
| 645 set_inset_fan(fan1Pos, vstride, devOutside, inset, inset); | |
| 646 set_inset_fan(fan1AssistPos, vstride, devOutsideAssist, inset, inset); | |
| 647 // inner one of the inner two | |
| 648 set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset); | |
| 649 // innermost | |
| 650 set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHa lf); | |
| 651 } | |
| 652 | |
| 653 // Make verts point to vertex color and then set all the color and coverage vertex attrs values. | |
| 654 // The outermost rect has 0 coverage | |
| 655 verts += sizeof(SkPoint); | |
| 656 for (int i = 0; i < outerVertexNum; ++i) { | |
| 657 if (kUseCoverage_CoverageAttribType == type) { | |
| 658 *reinterpret_cast<GrColor*>(verts + i * vstride) = color; | |
| 659 *reinterpret_cast<float*>(verts + i * vstride + sizeof(GrColor)) = 0 ; | |
| 660 } else { | |
| 661 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0; | |
| 662 } | |
| 663 } | |
| 664 | |
| 665 // scale is the coverage for the the inner two rects. | |
| 666 int scale; | |
| 667 if (inset < SK_ScalarHalf) { | |
| 668 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); | |
| 669 SkASSERT(scale >= 0 && scale <= 255); | |
| 670 } else { | |
| 671 scale = 0xff; | |
| 672 } | |
| 673 | |
| 674 float innerCoverage = GrNormalizeByteToFloat(scale); | |
| 675 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); | |
| 676 | |
| 677 verts += outerVertexNum * vstride; | |
| 678 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) { | |
| 679 if (kUseCoverage_CoverageAttribType == type) { | |
| 680 *reinterpret_cast<GrColor*>(verts + i * vstride) = color; | |
| 681 *reinterpret_cast<float*>(verts + i * vstride + sizeof(GrColor)) = i nnerCoverage; | |
| 682 } else { | |
| 683 *reinterpret_cast<GrColor*>(verts + i * vstride) = scaledColor; | |
| 684 } | |
| 685 } | |
| 686 | |
| 687 // The innermost rect has 0 coverage | |
| 688 verts += (outerVertexNum + innerVertexNum) * vstride; | |
| 689 for (int i = 0; i < innerVertexNum; ++i) { | |
| 690 if (kUseCoverage_CoverageAttribType == type) { | |
| 691 *reinterpret_cast<GrColor*>(verts + i * vstride) = color; | |
| 692 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0; | |
| 693 } else { | |
| 694 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0; | |
| 695 } | |
| 696 } | |
| 697 | |
| 698 target->setIndexSourceToBuffer(indexBuffer); | |
| 699 target->drawIndexedInstances(pipelineBuilder, | |
| 700 gp, | |
| 701 kTriangles_GrPrimitiveType, | |
| 702 1, | |
| 703 totalVertexNum, | |
| 704 aa_stroke_rect_index_count(miterStroke)); | |
| 705 target->resetIndexSource(); | |
| 706 } | 878 } |
| 707 | 879 |
| 708 void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target, | 880 void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target, |
| 709 GrPipelineBuilder* pipelineBuilder, | 881 GrPipelineBuilder* pipelineBuilder, |
| 710 GrColor color, | 882 GrColor color, |
| 711 const SkMatrix& viewMatrix, | 883 const SkMatrix& viewMatrix, |
| 712 const SkRect rects[2]) { | 884 const SkRect rects[2]) { |
| 713 SkASSERT(viewMatrix.rectStaysRect()); | 885 SkASSERT(viewMatrix.rectStaysRect()); |
| 714 SkASSERT(!rects[1].isEmpty()); | 886 SkASSERT(!rects[1].isEmpty()); |
| 715 | 887 |
| 716 SkRect devOutside, devOutsideAssist, devInside; | 888 SkRect devOutside, devOutsideAssist, devInside; |
| 717 viewMatrix.mapRect(&devOutside, rects[0]); | 889 viewMatrix.mapRect(&devOutside, rects[0]); |
| 718 // can't call mapRect for devInside since it calls sort | 890 // can't call mapRect for devInside since it calls sort |
| 719 viewMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2); | 891 viewMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2); |
| 720 | 892 |
| 721 if (devInside.isEmpty()) { | 893 if (devInside.isEmpty()) { |
| 722 this->fillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, | 894 this->fillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, |
| 723 devOutside); | 895 devOutside); |
| 724 return; | 896 return; |
| 725 } | 897 } |
| 726 | 898 |
| 727 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside, | 899 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside, |
| 728 devOutsideAssist, devInside, true); | 900 devOutsideAssist, devInside, true); |
| 729 } | 901 } |
| OLD | NEW |