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

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

Issue 924533004: Revert of AA stroke rects batch (Closed) Base URL: https://skia.googlesource.com/skia.git@oval
Patch Set: 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 fBatch.fColorIgnored = init.fColorIgnored; 102 fBatch.fColorIgnored = init.fColorIgnored;
103 fBatch.fColor = fGeoData[0].fColor; 103 fBatch.fColor = fGeoData[0].fColor;
104 fBatch.fUsesLocalCoords = init.fUsesLocalCoords; 104 fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
105 fBatch.fCoverageIgnored = init.fCoverageIgnored; 105 fBatch.fCoverageIgnored = init.fCoverageIgnored;
106 } 106 }
107 107
108 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE { 108 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE {
109 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); 109 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
110 110
111 SkMatrix localMatrix; 111 SkMatrix localMatrix;
112 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) { 112 if (!this->viewMatrix().invert(&localMatrix)) {
113 SkDebugf("Cannot invert\n"); 113 SkDebugf("Cannot invert\n");
114 return; 114 return;
115 } 115 }
116 116
117 SkAutoTUnref<const GrGeometryProcessor> gp(create_fill_rect_gp(canTweakA lphaForCoverage, 117 const GrGeometryProcessor* gp = create_fill_rect_gp(canTweakAlphaForCove rage,
118 localMatr ix)); 118 localMatrix);
119 119
120 batchTarget->initDraw(gp, pipeline); 120 batchTarget->initDraw(gp, pipeline);
121 gp->unref();
121 122
122 // TODO this is hacky, but the only way we have to initialize the GP is to use the 123 // TODO this is hacky, but the only way we have to initialize the GP is to use the
123 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch 124 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch
124 // everywhere we can remove this nastiness 125 // everywhere we can remove this nastiness
125 GrPipelineInfo init; 126 GrPipelineInfo init;
126 init.fColorIgnored = fBatch.fColorIgnored; 127 init.fColorIgnored = fBatch.fColorIgnored;
127 init.fOverrideColor = GrColor_ILLEGAL; 128 init.fOverrideColor = GrColor_ILLEGAL;
128 init.fCoverageIgnored = fBatch.fCoverageIgnored; 129 init.fCoverageIgnored = fBatch.fCoverageIgnored;
129 init.fUsesLocalCoords = this->usesLocalCoords(); 130 init.fUsesLocalCoords = this->usesLocalCoords();
130 gp->initBatchTracker(batchTarget->currentBatchTracker(), init); 131 gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
131 132
132 size_t vertexStride = gp->getVertexStride(); 133 size_t vertexStride = gp->getVertexStride();
133 134
134 SkASSERT(canTweakAlphaForCoverage ? 135 SkASSERT(canTweakAlphaForCoverage ?
135 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : 136 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) :
136 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr)); 137 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr));
137 138
138 int instanceCount = fGeoData.count(); 139 int instanceCount = fGeoData.count();
139 int vertexCount = kVertsPerAAFillRect * instanceCount; 140 int vertexCount = kVertsPerAAFillRect * instanceCount;
140 141
141 const GrVertexBuffer* vertexBuffer; 142 const GrVertexBuffer* vertexBuffer;
142 int firstVertex; 143 int firstVertex;
143 144
144 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, 145 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
145 vertexCount, 146 vertexCount,
146 &vertexBuffer, 147 &vertexBuffer,
147 &firstVertex); 148 &firstVertex);
148 149
149 for (int i = 0; i < instanceCount; i++) { 150 for (int i = 0; i < instanceCount; i++) {
150 const Geometry& args = fGeoData[i]; 151 const Geometry& args = fGeoData[i];
151 this->generateAAFillRectGeometry(vertices, 152 this->generateAAFillRectGeometry(vertices,
152 i * kVertsPerAAFillRect * vertexStr ide, 153 i * kVertsPerAAFillRect * vertexStride,
153 vertexStride, 154 vertexStride,
154 args.fColor, 155 args.fColor,
155 args.fViewMatrix, 156 args.fViewMatrix,
156 args.fRect, 157 args.fRect,
157 args.fDevRect, 158 args.fDevRect,
158 canTweakAlphaForCoverage); 159 canTweakAlphaForCoverage);
159 } 160 }
160 161
161 GrDrawTarget::DrawInfo drawInfo; 162 GrDrawTarget::DrawInfo drawInfo;
162 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType); 163 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
163 drawInfo.setStartVertex(0); 164 drawInfo.setStartVertex(0);
164 drawInfo.setStartIndex(0); 165 drawInfo.setStartIndex(0);
165 drawInfo.setVerticesPerInstance(kVertsPerAAFillRect); 166 drawInfo.setVerticesPerInstance(kVertsPerAAFillRect);
166 drawInfo.setIndicesPerInstance(kIndicesPerAAFillRect); 167 drawInfo.setIndicesPerInstance(kIndicesPerAAFillRect);
167 drawInfo.adjustStartVertex(firstVertex); 168 drawInfo.adjustStartVertex(firstVertex);
168 drawInfo.setVertexBuffer(vertexBuffer); 169 drawInfo.setVertexBuffer(vertexBuffer);
(...skipping 23 matching lines...) Expand all
192 } 193 }
193 194
194 GrColor color() const { return fBatch.fColor; } 195 GrColor color() const { return fBatch.fColor; }
195 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } 196 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
196 bool canTweakAlphaForCoverage() const { return fBatchOpt.fCanTweakAlphaForCo verage; } 197 bool canTweakAlphaForCoverage() const { return fBatchOpt.fCanTweakAlphaForCo verage; }
197 bool colorIgnored() const { return fBatch.fColorIgnored; } 198 bool colorIgnored() const { return fBatch.fColorIgnored; }
198 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } 199 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
199 200
200 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { 201 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
201 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); 202 AAFillRectBatch* that = t->cast<AAFillRectBatch>();
203 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) {
204 return false;
205 }
202 206
203 SkASSERT(this->canTweakAlphaForCoverage() == that->canTweakAlphaForCover age() && 207 if (this->colorIgnored() != that->colorIgnored()) {
204 this->usesLocalCoords() == that->usesLocalCoords() && 208 return false;
205 this->colorIgnored() == that->colorIgnored()); 209 }
210
211 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
206 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses 212 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses
207 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix 213 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix
208 // using vertex attributes in these cases, but haven't investigated that 214 // using vertex attributes in these cases, but haven't investigated that
209 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) { 215 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
210 return false; 216 return false;
211 } 217 }
212 218
213 if (this->color() != that->color()) { 219 if (this->color() != that->color()) {
214 fBatch.fColor = GrColor_ILLEGAL; 220 fBatch.fColor = GrColor_ILLEGAL;
215 } 221 }
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 // edge, while vertex number of inner edge is 4, the same as miter-stroke. 539 // edge, while vertex number of inner edge is 4, the same as miter-stroke.
534 if (!miterStroke) { 540 if (!miterStroke) {
535 devOutside.inset(0, ry); 541 devOutside.inset(0, ry);
536 devOutsideAssist.outset(0, ry); 542 devOutsideAssist.outset(0, ry);
537 } 543 }
538 544
539 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside, 545 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside,
540 devOutsideAssist, devInside, miterStroke); 546 devOutsideAssist, devInside, miterStroke);
541 } 547 }
542 548
543 class AAStrokeRectBatch : public GrBatch { 549 static const GrGeometryProcessor* create_rect_gp(const GrPipelineBuilder& pipeln eBuilder,
544 public: 550 GrColor color,
545 // TODO support AA rotated stroke rects by copying around view matrices 551 CoverageAttribType* type,
546 struct Geometry { 552 const SkMatrix& localMatrix) {
547 GrColor fColor; 553 uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType;
548 SkRect fDevOutside; 554 const GrGeometryProcessor* gp;
549 SkRect fDevOutsideAssist; 555 if (pipelneBuilder.canTweakAlphaForCoverage()) {
550 SkRect fDevInside; 556 gp = GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), localM atrix);
551 bool fMiterStroke; 557 SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::Positi onColorAttr));
552 }; 558 *type = kUseColor_CoverageAttribType;
553 559 } else {
554 static GrBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix, 560 flags |= GrDefaultGeoProcFactory::kCoverage_GPType;
555 const GrIndexBuffer* indexBuffer) { 561 gp = GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), localM atrix,
556 return SkNEW_ARGS(AAStrokeRectBatch, (geometry, viewMatrix, indexBuffer) ); 562 GrColorIsOpaque(color));
563 SkASSERT(gp->getVertexStride()==sizeof(GrDefaultGeoProcFactory::Position ColorCoverageAttr));
564 *type = kUseCoverage_CoverageAttribType;
557 } 565 }
558 566 return gp;
559 const char* name() const SK_OVERRIDE { return "AAStrokeRect"; } 567 }
560
561 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE {
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 // Local matrix is ignored if we don't have local coords. If we have lo calcoords we only
603 // batch with identical view matrices
604 SkMatrix localMatrix;
605 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) {
606 SkDebugf("Cannot invert\n");
607 return;
608 }
609
610 SkAutoTUnref<const GrGeometryProcessor>gp(create_fill_rect_gp(canTweakAl phaForCoverage,
611 localMatri x));
612
613 batchTarget->initDraw(gp, pipeline);
614
615 // TODO this is hacky, but the only way we have to initialize the GP is to use the
616 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch
617 // everywhere we can remove this nastiness
618 GrPipelineInfo init;
619 init.fColorIgnored = fBatch.fColorIgnored;
620 init.fOverrideColor = GrColor_ILLEGAL;
621 init.fCoverageIgnored = fBatch.fCoverageIgnored;
622 init.fUsesLocalCoords = this->usesLocalCoords();
623 gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
624
625 size_t vertexStride = gp->getVertexStride();
626
627 SkASSERT(canTweakAlphaForCoverage ?
628 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) :
629 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr));
630
631 int innerVertexNum = 4;
632 int outerVertexNum = this->miterStroke() ? 4 : 8;
633 int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
634
635 int instanceCount = fGeoData.count();
636 int vertexCount = totalVertexNum * instanceCount;
637
638 const GrVertexBuffer* vertexBuffer;
639 int firstVertex;
640
641 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
642 vertexCount,
643 &vertexBuffer,
644 &firstVertex);
645
646 for (int i = 0; i < instanceCount; i++) {
647 const Geometry& args = fGeoData[i];
648 this->generateAAStrokeRectGeometry(vertices,
649 i * totalVertexNum * vertexStride ,
650 vertexStride,
651 outerVertexNum,
652 innerVertexNum,
653 args.fColor,
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
685 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
686
687 private:
688 AAStrokeRectBatch(const Geometry& geometry, const SkMatrix& viewMatrix,
689 const GrIndexBuffer* indexBuffer)
690 : fIndexBuffer(indexBuffer) {
691 this->initClassID<AAStrokeRectBatch>();
692 fBatch.fViewMatrix = viewMatrix;
693 fGeoData.push_back(geometry);
694 }
695
696 GrColor color() const { return fBatch.fColor; }
697 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
698 bool canTweakAlphaForCoverage() const { return fBatchOpt.fCanTweakAlphaForCo verage; }
699 bool colorIgnored() const { return fBatch.fColorIgnored; }
700 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
701 bool miterStroke() const { return fBatch.fMiterStroke; }
702
703 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
704 AAStrokeRectBatch* that = t->cast<AAStrokeRectBatch>();
705
706 // TODO batch across miterstroke changes
707 if (this->miterStroke() != that->miterStroke()) {
708 return false;
709 }
710
711 SkASSERT(this->canTweakAlphaForCoverage() == that->canTweakAlphaForCover age() &&
712 this->usesLocalCoords() == that->usesLocalCoords() &&
713 this->colorIgnored() == that->colorIgnored());
714 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses
715 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix
716 // using vertex attributes in these cases, but haven't investigated that
717 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
718 return false;
719 }
720
721 if (this->color() != that->color()) {
722 fBatch.fColor = GrColor_ILLEGAL;
723 }
724 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
725 return true;
726 }
727
728 void generateAAStrokeRectGeometry(void* vertices,
729 size_t offset,
730 size_t vertexStride,
731 int outerVertexNum,
732 int innerVertexNum,
733 GrColor color,
734 const SkRect& devOutside,
735 const SkRect& devOutsideAssist,
736 const SkRect& devInside,
737 bool miterStroke,
738 bool tweakAlphaForCoverage) const {
739 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset;
740
741 // We create vertices for four nested rectangles. There are two ramps fr om 0 to full
742 // coverage, one on the exterior of the stroke and the other on the inte rior.
743 // The following pointers refer to the four rects, from outermost to inn ermost.
744 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
745 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * v ertexStride);
746 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vertexStride);
747 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts +
748 (2 * outerVertexNum + inne rVertexNum) *
749 vertexStride);
750
751 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
752 // TODO: this only really works if the X & Y margins are the same all ar ound
753 // the rect (or if they are all >= 1.0).
754 SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.f Right);
755 inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft);
756 inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop);
757 if (miterStroke) {
758 inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devI nside.fBottom);
759 } else {
760 inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom -
761 devInside.fBottom);
762 }
763 SkASSERT(inset >= 0);
764 #else
765 SkScalar inset = SK_ScalarHalf;
766 #endif
767
768 if (miterStroke) {
769 // outermost
770 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK _ScalarHalf);
771 // inner two
772 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset);
773 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset);
774 // innermost
775 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf);
776 } else {
777 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vert exStride);
778 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts +
779 (outerVertexNum + 4) *
780 vertexStride);
781 // outermost
782 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK _ScalarHalf);
783 set_inset_fan(fan0AssistPos, vertexStride, devOutsideAssist, -SK_Sca larHalf,
784 -SK_ScalarHalf);
785 // outer one of the inner two
786 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset);
787 set_inset_fan(fan1AssistPos, vertexStride, devOutsideAssist, inset, inset);
788 // inner one of the inner two
789 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset);
790 // innermost
791 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf);
792 }
793
794 // Make verts point to vertex color and then set all the color and cover age vertex attrs
795 // values. The outermost rect has 0 coverage
796 verts += sizeof(SkPoint);
797 for (int i = 0; i < outerVertexNum; ++i) {
798 if (tweakAlphaForCoverage) {
799 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
800 } else {
801 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
802 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = 0;
803 }
804 }
805
806 // scale is the coverage for the the inner two rects.
807 int scale;
808 if (inset < SK_ScalarHalf) {
809 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)) ;
810 SkASSERT(scale >= 0 && scale <= 255);
811 } else {
812 scale = 0xff;
813 }
814
815 float innerCoverage = GrNormalizeByteToFloat(scale);
816 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale );
817
818 verts += outerVertexNum * vertexStride;
819 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
820 if (tweakAlphaForCoverage) {
821 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo lor;
822 } else {
823 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
824 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) =
825 innerCoverage;
826 }
827 }
828
829 // The innermost rect has 0 coverage
830 verts += (outerVertexNum + innerVertexNum) * vertexStride;
831 for (int i = 0; i < innerVertexNum; ++i) {
832 if (tweakAlphaForCoverage) {
833 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
834 } else {
835 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
836 *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(Gr Color)) = 0;
837 }
838 }
839 }
840
841 struct BatchTracker {
842 SkMatrix fViewMatrix;
843 GrColor fColor;
844 bool fUsesLocalCoords;
845 bool fColorIgnored;
846 bool fCoverageIgnored;
847 bool fMiterStroke;
848 };
849
850 GrBatchOpt fBatchOpt;
851 BatchTracker fBatch;
852 const GrIndexBuffer* fIndexBuffer;
853 SkSTArray<1, Geometry, true> fGeoData;
854 };
855 568
856 569
857 void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target, 570 void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target,
858 GrPipelineBuilder* pipelineBuilder, 571 GrPipelineBuilder* pipelineBuilder,
859 GrColor color, 572 GrColor color,
860 const SkMatrix& viewMatrix, 573 const SkMatrix& viewMatrix,
861 const SkRect& devOutside, 574 const SkRect& devOutside,
862 const SkRect& devOutsideAssist, 575 const SkRect& devOutsideAssist,
863 const SkRect& devInside, 576 const SkRect& devInside,
864 bool miterStroke) { 577 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 }
865 GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(miterStroke); 598 GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(miterStroke);
866 if (NULL == indexBuffer) { 599 if (NULL == indexBuffer) {
867 SkDebugf("Failed to create index buffer!\n"); 600 SkDebugf("Failed to create index buffer!\n");
868 return; 601 return;
869 } 602 }
870 603
871 AAStrokeRectBatch::Geometry geometry; 604 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
872 geometry.fColor = color;
873 geometry.fDevOutside = devOutside;
874 geometry.fDevOutsideAssist = devOutsideAssist;
875 geometry.fDevInside = devInside;
876 geometry.fMiterStroke = miterStroke;
877 605
878 SkAutoTUnref<GrBatch> batch(AAStrokeRectBatch::Create(geometry, viewMatrix, indexBuffer)); 606 // We create vertices for four nested rectangles. There are two ramps from 0 to full
879 target->drawBatch(pipelineBuilder, batch); 607 // coverage, one on the exterior of the stroke and the other on the interior .
608 // The following pointers refer to the four rects, from outermost to innermo st.
609 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
610 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vstri de);
611 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * v stride);
612 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vstride);
613
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();
880 } 706 }
881 707
882 void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target, 708 void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target,
883 GrPipelineBuilder* pipelineBuilder, 709 GrPipelineBuilder* pipelineBuilder,
884 GrColor color, 710 GrColor color,
885 const SkMatrix& viewMatrix, 711 const SkMatrix& viewMatrix,
886 const SkRect rects[2]) { 712 const SkRect rects[2]) {
887 SkASSERT(viewMatrix.rectStaysRect()); 713 SkASSERT(viewMatrix.rectStaysRect());
888 SkASSERT(!rects[1].isEmpty()); 714 SkASSERT(!rects[1].isEmpty());
889 715
890 SkRect devOutside, devOutsideAssist, devInside; 716 SkRect devOutside, devOutsideAssist, devInside;
891 viewMatrix.mapRect(&devOutside, rects[0]); 717 viewMatrix.mapRect(&devOutside, rects[0]);
892 // can't call mapRect for devInside since it calls sort 718 // can't call mapRect for devInside since it calls sort
893 viewMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2); 719 viewMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);
894 720
895 if (devInside.isEmpty()) { 721 if (devInside.isEmpty()) {
896 this->fillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, 722 this->fillAARect(target, pipelineBuilder, color, viewMatrix, devOutside,
897 devOutside); 723 devOutside);
898 return; 724 return;
899 } 725 }
900 726
901 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside, 727 this->geometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOu tside,
902 devOutsideAssist, devInside, true); 728 devOutsideAssist, devInside, true);
903 } 729 }
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