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 |