Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(396)

Side by Side Diff: src/gpu/GrAARectRenderer.cpp

Issue 912483004: AA stroke rects batch (Closed) Base URL: https://skia.googlesource.com/skia.git@oval
Patch Set: one cl and rebase Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 fBatch.fColor = fGeoData[0].fColor; 90 fBatch.fColor = fGeoData[0].fColor;
91 fBatch.fUsesLocalCoords = init.fUsesLocalCoords; 91 fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
92 fBatch.fCoverageIgnored = init.fCoverageIgnored; 92 fBatch.fCoverageIgnored = init.fCoverageIgnored;
93 fBatch.fCanTweakAlphaForCoverage = init.fCanTweakAlphaForCoverage; 93 fBatch.fCanTweakAlphaForCoverage = init.fCanTweakAlphaForCoverage;
94 } 94 }
95 95
96 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE { 96 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE {
97 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); 97 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
98 98
99 SkMatrix localMatrix; 99 SkMatrix localMatrix;
100 if (!this->viewMatrix().invert(&localMatrix)) { 100 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) {
101 SkDebugf("Cannot invert\n"); 101 SkDebugf("Cannot invert\n");
102 return; 102 return;
103 } 103 }
104 104
105 const GrGeometryProcessor* gp = create_fill_rect_gp(canTweakAlphaForCove rage, 105 SkAutoTUnref<const GrGeometryProcessor> gp(create_fill_rect_gp(canTweakA lphaForCoverage,
106 localMatrix); 106 localMatr ix));
107 107
108 batchTarget->initDraw(gp, pipeline); 108 batchTarget->initDraw(gp, pipeline);
109 gp->unref();
110 109
111 // TODO this is hacky, but the only way we have to initialize the GP is to use the 110 // TODO this is hacky, but the only way we have to initialize the GP is to use the
112 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch 111 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch
113 // everywhere we can remove this nastiness 112 // everywhere we can remove this nastiness
114 GrPipelineInfo init; 113 GrPipelineInfo init;
115 init.fColorIgnored = fBatch.fColorIgnored; 114 init.fColorIgnored = fBatch.fColorIgnored;
116 init.fOverrideColor = GrColor_ILLEGAL; 115 init.fOverrideColor = GrColor_ILLEGAL;
117 init.fCoverageIgnored = fBatch.fCoverageIgnored; 116 init.fCoverageIgnored = fBatch.fCoverageIgnored;
118 init.fUsesLocalCoords = this->usesLocalCoords(); 117 init.fUsesLocalCoords = this->usesLocalCoords();
119 gp->initBatchTracker(batchTarget->currentBatchTracker(), init); 118 gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
120 119
121 size_t vertexStride = gp->getVertexStride(); 120 size_t vertexStride = gp->getVertexStride();
122 121
123 SkASSERT(canTweakAlphaForCoverage ? 122 SkASSERT(canTweakAlphaForCoverage ?
124 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : 123 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) :
125 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr)); 124 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr));
126 125
127 int instanceCount = fGeoData.count(); 126 int instanceCount = fGeoData.count();
128 int vertexCount = kVertsPerAAFillRect * instanceCount; 127 int vertexCount = kVertsPerAAFillRect * instanceCount;
129 128
130 const GrVertexBuffer* vertexBuffer; 129 const GrVertexBuffer* vertexBuffer;
131 int firstVertex; 130 int firstVertex;
132 131
133 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride, 132 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
134 vertexCount, 133 vertexCount,
135 &vertexBuffer, 134 &vertexBuffer,
136 &firstVertex); 135 &firstVertex);
137 136
138 for (int i = 0; i < instanceCount; i++) { 137 for (int i = 0; i < instanceCount; i++) {
139 const Geometry& args = fGeoData[i]; 138 const Geometry& args = fGeoData[i];
140 this->generateAAFillRectGeometry(vertices, 139 this->generateAAFillRectGeometry(vertices,
141 i * kVertsPerAAFillRect * vertexStride, 140 i * kVertsPerAAFillRect * vertexStr ide,
142 vertexStride, 141 vertexStride,
143 args.fColor, 142 args.fColor,
144 args.fViewMatrix, 143 args.fViewMatrix,
145 args.fRect, 144 args.fRect,
146 args.fDevRect, 145 args.fDevRect,
147 canTweakAlphaForCoverage); 146 canTweakAlphaForCoverage);
148 } 147 }
149 148
150 GrDrawTarget::DrawInfo drawInfo; 149 GrDrawTarget::DrawInfo drawInfo;
151 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType); 150 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
152 drawInfo.setStartVertex(0); 151 drawInfo.setStartVertex(0);
153 drawInfo.setStartIndex(0); 152 drawInfo.setStartIndex(0);
154 drawInfo.setVerticesPerInstance(kVertsPerAAFillRect); 153 drawInfo.setVerticesPerInstance(kVertsPerAAFillRect);
155 drawInfo.setIndicesPerInstance(kIndicesPerAAFillRect); 154 drawInfo.setIndicesPerInstance(kIndicesPerAAFillRect);
156 drawInfo.adjustStartVertex(firstVertex); 155 drawInfo.adjustStartVertex(firstVertex);
157 drawInfo.setVertexBuffer(vertexBuffer); 156 drawInfo.setVertexBuffer(vertexBuffer);
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 // edge, while vertex number of inner edge is 4, the same as miter-stroke. 526 // edge, while vertex number of inner edge is 4, the same as miter-stroke.
528 if (!miterStroke) { 527 if (!miterStroke) {
529 devOutside.inset(0, ry); 528 devOutside.inset(0, ry);
530 devOutsideAssist.outset(0, ry); 529 devOutsideAssist.outset(0, ry);
531 } 530 }
532 531
533 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside, 532 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside,
534 devOutsideAssist, devInside, miterStroke); 533 devOutsideAssist, devInside, miterStroke);
535 } 534 }
536 535
537 static const GrGeometryProcessor* create_rect_gp(const GrPipelineBuilder& pipeln eBuilder, 536 class AAStrokeRectBatch : public GrBatch {
538 GrColor color, 537 public:
539 CoverageAttribType* type, 538 // TODO support AA rotated stroke rects by copying around view matrices
540 const SkMatrix& localMatrix) { 539 struct Geometry {
541 uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType; 540 GrColor fColor;
542 const GrGeometryProcessor* gp; 541 SkRect fDevOutside;
543 if (pipelneBuilder.canTweakAlphaForCoverage()) { 542 SkRect fDevOutsideAssist;
544 gp = GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), localM atrix); 543 SkRect fDevInside;
545 SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::Positi onColorAttr)); 544 bool fMiterStroke;
546 *type = kUseColor_CoverageAttribType; 545 };
547 } else { 546
548 flags |= GrDefaultGeoProcFactory::kCoverage_GPType; 547 static GrBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix,
549 gp = GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), localM atrix, 548 const GrIndexBuffer* indexBuffer) {
550 GrColorIsOpaque(color)); 549 return SkNEW_ARGS(AAStrokeRectBatch, (geometry, viewMatrix, indexBuffer) );
551 SkASSERT(gp->getVertexStride()==sizeof(GrDefaultGeoProcFactory::Position ColorCoverageAttr)); 550 }
552 *type = kUseCoverage_CoverageAttribType; 551
553 } 552 const char* name() const SK_OVERRIDE { return "AAStrokeRect"; }
554 return gp; 553
555 } 554 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE {
555 // When this is called on a batch, there is only one geometry bundle
556 out->setKnownFourComponents(fGeoData[0].fColor);
557 }
558
559 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID E {
560 out->setUnknownSingleComponent();
561 }
562
563 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE {
564 // Handle any color overrides
565 if (init.fColorIgnored) {
566 fGeoData[0].fColor = GrColor_ILLEGAL;
567 } else if (GrColor_ILLEGAL != init.fOverrideColor) {
568 fGeoData[0].fColor = init.fOverrideColor;
569 }
570
571 // setup batch properties
572 fBatch.fColorIgnored = init.fColorIgnored;
573 fBatch.fColor = fGeoData[0].fColor;
574 fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
575 fBatch.fCoverageIgnored = init.fCoverageIgnored;
576 fBatch.fMiterStroke = fGeoData[0].fMiterStroke;
577 fBatch.fCanTweakAlphaForCoverage = init.fCanTweakAlphaForCoverage;
578 }
579
580 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE {
581 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
582
583 // Local matrix is ignored if we don't have local coords. If we have lo calcoords we only
584 // batch with identical view matrices
585 SkMatrix localMatrix;
586 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) {
587 SkDebugf("Cannot invert\n");
588 return;
589 }
590
591 SkAutoTUnref<const GrGeometryProcessor>gp(create_fill_rect_gp(canTweakAl phaForCoverage,
592 localMatri x));
593
594 batchTarget->initDraw(gp, pipeline);
595
596 // TODO this is hacky, but the only way we have to initialize the GP is to use the
597 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch
598 // everywhere we can remove this nastiness
599 GrPipelineInfo init;
600 init.fColorIgnored = fBatch.fColorIgnored;
601 init.fOverrideColor = GrColor_ILLEGAL;
602 init.fCoverageIgnored = fBatch.fCoverageIgnored;
603 init.fUsesLocalCoords = this->usesLocalCoords();
604 gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
605
606 size_t vertexStride = gp->getVertexStride();
607
608 SkASSERT(canTweakAlphaForCoverage ?
609 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) :
610 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr));
611
612 int innerVertexNum = 4;
613 int outerVertexNum = this->miterStroke() ? 4 : 8;
614 int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
615
616 int instanceCount = fGeoData.count();
617 int vertexCount = totalVertexNum * instanceCount;
618
619 const GrVertexBuffer* vertexBuffer;
620 int firstVertex;
621
622 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
623 vertexCount,
624 &vertexBuffer,
625 &firstVertex);
626
627 for (int i = 0; i < instanceCount; i++) {
628 const Geometry& args = fGeoData[i];
629 this->generateAAStrokeRectGeometry(vertices,
630 i * totalVertexNum * vertexStride ,
631 vertexStride,
632 outerVertexNum,
633 innerVertexNum,
634 args.fColor,
635 args.fDevOutside,
636 args.fDevOutsideAssist,
637 args.fDevInside,
638 args.fMiterStroke,
639 canTweakAlphaForCoverage);
640 }
641
642 GrDrawTarget::DrawInfo drawInfo;
643 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
644 drawInfo.setStartVertex(0);
645 drawInfo.setStartIndex(0);
646 drawInfo.setVerticesPerInstance(totalVertexNum);
647 drawInfo.setIndicesPerInstance(aa_stroke_rect_index_count(this->miterStr oke()));
648 drawInfo.adjustStartVertex(firstVertex);
649 drawInfo.setVertexBuffer(vertexBuffer);
650 drawInfo.setIndexBuffer(fIndexBuffer);
651
652 int maxInstancesPerDraw = kNumBevelStrokeRectsInIndexBuffer;
653
654 while (instanceCount) {
655 drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw) );
656 drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.vertices PerInstance());
657 drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPe rInstance());
658
659 batchTarget->draw(drawInfo);
660
661 drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCoun t());
662 instanceCount -= drawInfo.instanceCount();
663 }
664 }
665
666 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
667
668 private:
669 AAStrokeRectBatch(const Geometry& geometry, const SkMatrix& viewMatrix,
670 const GrIndexBuffer* indexBuffer)
671 : fIndexBuffer(indexBuffer) {
672 this->initClassID<AAStrokeRectBatch>();
673 fBatch.fViewMatrix = viewMatrix;
674 fGeoData.push_back(geometry);
675 }
676
677 GrColor color() const { return fBatch.fColor; }
678 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
679 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover age; }
680 bool colorIgnored() const { return fBatch.fColorIgnored; }
681 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
682 bool miterStroke() const { return fBatch.fMiterStroke; }
683
684 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
685 AAStrokeRectBatch* that = t->cast<AAStrokeRectBatch>();
686
687 // TODO batch across miterstroke changes
688 if (this->miterStroke() != that->miterStroke()) {
689 return false;
690 }
691
692 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses
693 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix
694 // using vertex attributes in these cases, but haven't investigated that
695 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
696 return false;
697 }
698
699 // In the event of two batches, one who can tweak, one who cannot, we ju st fall back to
700 // not tweaking
701 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) {
702 fBatch.fCanTweakAlphaForCoverage = false;
703 }
704
705 if (this->color() != that->color()) {
706 fBatch.fColor = GrColor_ILLEGAL;
707 }
708 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
709 return true;
710 }
711
712 void generateAAStrokeRectGeometry(void* vertices,
713 size_t offset,
714 size_t vertexStride,
715 int outerVertexNum,
716 int innerVertexNum,
717 GrColor color,
718 const SkRect& devOutside,
719 const SkRect& devOutsideAssist,
720 const SkRect& devInside,
721 bool miterStroke,
722 bool tweakAlphaForCoverage) const {
723 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset;
724
725 // We create vertices for four nested rectangles. There are two ramps fr om 0 to full
726 // coverage, one on the exterior of the stroke and the other on the inte rior.
727 // The following pointers refer to the four rects, from outermost to inn ermost.
728 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
729 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * v ertexStride);
730 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vertexStride);
731 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts +
732 (2 * outerVertexNum + inne rVertexNum) *
733 vertexStride);
734
735 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
736 // TODO: this only really works if the X & Y margins are the same all ar ound
737 // the rect (or if they are all >= 1.0).
738 SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.f Right);
739 inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft);
740 inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop);
741 if (miterStroke) {
742 inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devI nside.fBottom);
743 } else {
744 inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom -
745 devInside.fBottom);
746 }
747 SkASSERT(inset >= 0);
748 #else
749 SkScalar inset = SK_ScalarHalf;
750 #endif
751
752 if (miterStroke) {
753 // outermost
754 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK _ScalarHalf);
755 // inner two
756 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset);
757 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset);
758 // innermost
759 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf);
760 } else {
761 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vert exStride);
762 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts +
763 (outerVertexNum + 4) *
764 vertexStride);
765 // outermost
766 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK _ScalarHalf);
767 set_inset_fan(fan0AssistPos, vertexStride, devOutsideAssist, -SK_Sca larHalf,
768 -SK_ScalarHalf);
769 // outer one of the inner two
770 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset);
771 set_inset_fan(fan1AssistPos, vertexStride, devOutsideAssist, inset, inset);
772 // inner one of the inner two
773 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset);
774 // innermost
775 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf);
776 }
777
778 // Make verts point to vertex color and then set all the color and cover age vertex attrs
779 // values. The outermost rect has 0 coverage
780 verts += sizeof(SkPoint);
781 for (int i = 0; i < outerVertexNum; ++i) {
782 if (tweakAlphaForCoverage) {
783 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
784 } else {
785 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
786 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = 0;
787 }
788 }
789
790 // scale is the coverage for the the inner two rects.
791 int scale;
792 if (inset < SK_ScalarHalf) {
793 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)) ;
794 SkASSERT(scale >= 0 && scale <= 255);
795 } else {
796 scale = 0xff;
797 }
798
799 float innerCoverage = GrNormalizeByteToFloat(scale);
800 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale );
801
802 verts += outerVertexNum * vertexStride;
803 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
804 if (tweakAlphaForCoverage) {
805 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo lor;
806 } else {
807 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
808 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) =
809 innerCoverage;
810 }
811 }
812
813 // The innermost rect has 0 coverage
814 verts += (outerVertexNum + innerVertexNum) * vertexStride;
815 for (int i = 0; i < innerVertexNum; ++i) {
816 if (tweakAlphaForCoverage) {
817 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
818 } else {
819 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
820 *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(Gr Color)) = 0;
821 }
822 }
823 }
824
825 struct BatchTracker {
826 SkMatrix fViewMatrix;
827 GrColor fColor;
828 bool fUsesLocalCoords;
829 bool fColorIgnored;
830 bool fCoverageIgnored;
831 bool fMiterStroke;
832 bool fCanTweakAlphaForCoverage;
833 };
834
835 BatchTracker fBatch;
836 const GrIndexBuffer* fIndexBuffer;
837 SkSTArray<1, Geometry, true> fGeoData;
838 };
556 839
557 840
558 void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target, 841 void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target,
559 GrPipelineBuilder* pipelineBuilder, 842 GrPipelineBuilder* pipelineBuilder,
560 GrColor color, 843 GrColor color,
561 const SkMatrix& viewMatrix, 844 const SkMatrix& viewMatrix,
562 const SkRect& devOutside, 845 const SkRect& devOutside,
563 const SkRect& devOutsideAssist, 846 const SkRect& devOutsideAssist,
564 const SkRect& devInside, 847 const SkRect& devInside,
565 bool miterStroke) { 848 bool miterStroke) {
566 SkMatrix localMatrix;
567 if (!viewMatrix.invert(&localMatrix)) {
568 SkDebugf("Cannot invert\n");
569 return;
570 }
571
572 CoverageAttribType type;
573 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(*pipelineBuilder, color, &type,
574 localMatrix));
575
576 int innerVertexNum = 4;
577 int outerVertexNum = miterStroke ? 4 : 8;
578 int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
579
580 size_t vstride = gp->getVertexStride();
581 GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, vstride, 0);
582 if (!geo.succeeded()) {
583 SkDebugf("Failed to get space for vertices!\n");
584 return;
585 }
586 GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(miterStroke); 849 GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(miterStroke);
587 if (NULL == indexBuffer) { 850 if (NULL == indexBuffer) {
588 SkDebugf("Failed to create index buffer!\n"); 851 SkDebugf("Failed to create index buffer!\n");
589 return; 852 return;
590 } 853 }
591 854
592 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); 855 AAStrokeRectBatch::Geometry geometry;
593 856 geometry.fColor = color;
594 // We create vertices for four nested rectangles. There are two ramps from 0 to full 857 geometry.fDevOutside = devOutside;
595 // coverage, one on the exterior of the stroke and the other on the interior . 858 geometry.fDevOutsideAssist = devOutsideAssist;
596 // The following pointers refer to the four rects, from outermost to innermo st. 859 geometry.fDevInside = devInside;
597 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); 860 geometry.fMiterStroke = miterStroke;
598 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vstri de); 861
599 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * v stride); 862 SkAutoTUnref<GrBatch> batch(AAStrokeRectBatch::Create(geometry, viewMatrix, indexBuffer));
600 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vstride); 863 target->drawBatch(pipelineBuilder, batch);
601
602 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
603 // TODO: this only really works if the X & Y margins are the same all around
604 // the rect (or if they are all >= 1.0).
605 SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRigh t);
606 inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft);
607 inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop);
608 if (miterStroke) {
609 inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInsid e.fBottom);
610 } else {
611 inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - de vInside.fBottom);
612 }
613 SkASSERT(inset >= 0);
614 #else
615 SkScalar inset = SK_ScalarHalf;
616 #endif
617
618 if (miterStroke) {
619 // outermost
620 set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHa lf);
621 // inner two
622 set_inset_fan(fan1Pos, vstride, devOutside, inset, inset);
623 set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset);
624 // innermost
625 set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHa lf);
626 } else {
627 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vstride) ;
628 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertex Num + 4) * vstride);
629 // outermost
630 set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHa lf);
631 set_inset_fan(fan0AssistPos, vstride, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf);
632 // outer one of the inner two
633 set_inset_fan(fan1Pos, vstride, devOutside, inset, inset);
634 set_inset_fan(fan1AssistPos, vstride, devOutsideAssist, inset, inset);
635 // inner one of the inner two
636 set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset);
637 // innermost
638 set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHa lf);
639 }
640
641 // Make verts point to vertex color and then set all the color and coverage vertex attrs values.
642 // The outermost rect has 0 coverage
643 verts += sizeof(SkPoint);
644 for (int i = 0; i < outerVertexNum; ++i) {
645 if (kUseCoverage_CoverageAttribType == type) {
646 *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
647 *reinterpret_cast<float*>(verts + i * vstride + sizeof(GrColor)) = 0 ;
648 } else {
649 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0;
650 }
651 }
652
653 // scale is the coverage for the the inner two rects.
654 int scale;
655 if (inset < SK_ScalarHalf) {
656 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
657 SkASSERT(scale >= 0 && scale <= 255);
658 } else {
659 scale = 0xff;
660 }
661
662 float innerCoverage = GrNormalizeByteToFloat(scale);
663 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
664
665 verts += outerVertexNum * vstride;
666 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
667 if (kUseCoverage_CoverageAttribType == type) {
668 *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
669 *reinterpret_cast<float*>(verts + i * vstride + sizeof(GrColor)) = i nnerCoverage;
670 } else {
671 *reinterpret_cast<GrColor*>(verts + i * vstride) = scaledColor;
672 }
673 }
674
675 // The innermost rect has 0 coverage
676 verts += (outerVertexNum + innerVertexNum) * vstride;
677 for (int i = 0; i < innerVertexNum; ++i) {
678 if (kUseCoverage_CoverageAttribType == type) {
679 *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
680 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0;
681 } else {
682 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0;
683 }
684 }
685
686 target->setIndexSourceToBuffer(indexBuffer);
687 target->drawIndexedInstances(pipelineBuilder,
688 gp,
689 kTriangles_GrPrimitiveType,
690 1,
691 totalVertexNum,
692 aa_stroke_rect_index_count(miterStroke));
693 target->resetIndexSource();
694 } 864 }
695 865
696 void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target, 866 void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target,
697 GrPipelineBuilder* pipelineBuilder, 867 GrPipelineBuilder* pipelineBuilder,
698 GrColor color, 868 GrColor color,
699 const SkMatrix& viewMatrix, 869 const SkMatrix& viewMatrix,
700 const SkRect rects[2]) { 870 const SkRect rects[2]) {
701 SkASSERT(viewMatrix.rectStaysRect()); 871 SkASSERT(viewMatrix.rectStaysRect());
702 SkASSERT(!rects[1].isEmpty()); 872 SkASSERT(!rects[1].isEmpty());
703 873
704 SkRect devOutside, devOutsideAssist, devInside; 874 SkRect devOutside, devOutsideAssist, devInside;
705 viewMatrix.mapRect(&devOutside, rects[0]); 875 viewMatrix.mapRect(&devOutside, rects[0]);
706 // can't call mapRect for devInside since it calls sort 876 // can't call mapRect for devInside since it calls sort
707 viewMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2); 877 viewMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);
708 878
709 if (devInside.isEmpty()) { 879 if (devInside.isEmpty()) {
710 this->fillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, 880 this->fillAARect(target, pipelineBuilder, color, viewMatrix, devOutside,
711 devOutside); 881 devOutside);
712 return; 882 return;
713 } 883 }
714 884
715 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside, 885 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside,
716 devOutsideAssist, devInside, true); 886 devOutsideAssist, devInside, true);
717 } 887 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698