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

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: cleanup 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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 }
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