OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "GrPLSPathRenderer.h" | 8 #include "GrPLSPathRenderer.h" |
9 | 9 |
10 #include "SkChunkAlloc.h" | 10 #include "SkChunkAlloc.h" |
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
780 SkPath path; | 780 SkPath path; |
781 args.fShape->asPath(&path); | 781 args.fShape->asPath(&path); |
782 return args.fShaderCaps->shaderDerivativeSupport() && args.fAntiAlias && | 782 return args.fShaderCaps->shaderDerivativeSupport() && args.fAntiAlias && |
783 args.fShape->style().isSimpleFill() && !path.isInverseFillType() && | 783 args.fShape->style().isSimpleFill() && !path.isInverseFillType() && |
784 path.getFillType() == SkPath::FillType::kWinding_FillType; | 784 path.getFillType() == SkPath::FillType::kWinding_FillType; |
785 } | 785 } |
786 | 786 |
787 class PLSPathBatch : public GrVertexBatch { | 787 class PLSPathBatch : public GrVertexBatch { |
788 public: | 788 public: |
789 DEFINE_BATCH_CLASS_ID | 789 DEFINE_BATCH_CLASS_ID |
790 struct Geometry { | 790 PLSPathBatch(GrColor color, const SkPath& path, const SkMatrix& viewMatrix) |
791 GrColor fColor; | 791 : INHERITED(ClassID()) |
792 SkMatrix fViewMatrix; | 792 , fColor(color) |
793 SkPath fPath; | 793 , fPath(path) |
794 }; | 794 , fViewMatrix(viewMatrix) { |
795 | 795 // compute bounds |
796 static GrDrawBatch* Create(const Geometry& geometry) { | 796 fBounds = path.getBounds(); |
797 return new PLSPathBatch(geometry); | 797 fViewMatrix.mapRect(&fBounds); |
798 } | 798 } |
799 | 799 |
800 const char* name() const override { return "PLSBatch"; } | 800 const char* name() const override { return "PLSBatch"; } |
801 | 801 |
802 void computePipelineOptimizations(GrInitInvariantOutput* color, | 802 void computePipelineOptimizations(GrInitInvariantOutput* color, |
803 GrInitInvariantOutput* coverage, | 803 GrInitInvariantOutput* coverage, |
804 GrBatchToXPOverrides* overrides) const ove rride { | 804 GrBatchToXPOverrides* overrides) const ove rride { |
805 // When this is called on a batch, there is only one geometry bundle | 805 // When this is called on a batch, there is only one geometry bundle |
806 color->setKnownFourComponents(fGeoData[0].fColor); | 806 color->setKnownFourComponents(fColor); |
807 coverage->setUnknownSingleComponent(); | 807 coverage->setUnknownSingleComponent(); |
808 overrides->fUsePLSDstRead = true; | 808 overrides->fUsePLSDstRead = true; |
809 } | 809 } |
810 | 810 |
811 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | 811 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
812 // Handle any color overrides | 812 // Handle any color overrides |
813 if (!overrides.readsColor()) { | 813 if (!overrides.readsColor()) { |
814 fGeoData[0].fColor = GrColor_ILLEGAL; | 814 fColor = GrColor_ILLEGAL; |
815 } | 815 } |
816 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | 816 overrides.getOverrideColorIfSet(&fColor); |
817 | 817 |
818 // setup batch properties | 818 // setup batch properties |
819 fBatch.fColorIgnored = !overrides.readsColor(); | 819 fUsesLocalCoords = overrides.readsLocalCoords(); |
820 fBatch.fColor = fGeoData[0].fColor; | |
821 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); | |
822 fBatch.fCoverageIgnored = !overrides.readsCoverage(); | |
823 fBatch.fCanTweakAlphaForCoverage = overrides.canTweakAlphaForCoverage(); | |
824 } | 820 } |
825 | 821 |
826 void onPrepareDraws(Target* target) const override { | 822 void onPrepareDraws(Target* target) const override { |
827 int instanceCount = fGeoData.count(); | |
828 | 823 |
829 SkMatrix invert; | 824 SkMatrix invert; |
830 if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) { | 825 if (fUsesLocalCoords && !fViewMatrix.invert(&invert)) { |
831 SkDebugf("Could not invert viewmatrix\n"); | 826 SkDebugf("Could not invert viewmatrix\n"); |
832 return; | 827 return; |
833 } | 828 } |
834 | 829 |
835 // Setup GrGeometryProcessors | 830 // Setup GrGeometryProcessors |
836 SkAutoTUnref<GrPLSGeometryProcessor> triangleProcessor( | 831 SkAutoTUnref<GrPLSGeometryProcessor> triangleProcessor( |
837 PLSAATriangleEffect::Create(invert, this->usesLocalCoords())); | 832 PLSAATriangleEffect::Create(invert, fUsesLocalCoords)); |
838 SkAutoTUnref<GrPLSGeometryProcessor> quadProcessor( | 833 SkAutoTUnref<GrPLSGeometryProcessor> quadProcessor( |
839 PLSQuadEdgeEffect::Create(invert, this->usesLocalCoords())); | 834 PLSQuadEdgeEffect::Create(invert, fUsesLocalCoords)); |
840 | 835 |
841 GrResourceProvider* rp = target->resourceProvider(); | 836 GrResourceProvider* rp = target->resourceProvider(); |
robertphillips
2016/06/30 16:58:27
SkRect bounds;
this->bounds()->roundOut(&bounds);
bsalomon
2016/06/30 17:33:58
Done.
| |
842 for (int i = 0; i < instanceCount; ++i) { | 837 SkRect bounds = this->bounds(); |
843 const Geometry& args = fGeoData[i]; | 838 bounds.fLeft = SkScalarFloorToScalar(bounds.fLeft); |
844 SkRect bounds = args.fPath.getBounds(); | 839 bounds.fTop = SkScalarFloorToScalar(bounds.fTop); |
845 args.fViewMatrix.mapRect(&bounds); | 840 bounds.fRight = SkScalarCeilToScalar(bounds.fRight); |
846 bounds.fLeft = SkScalarFloorToScalar(bounds.fLeft); | 841 bounds.fBottom = SkScalarCeilToScalar(bounds.fBottom); |
847 bounds.fTop = SkScalarFloorToScalar(bounds.fTop); | 842 triangleProcessor->setBounds(bounds); |
848 bounds.fRight = SkScalarCeilToScalar(bounds.fRight); | 843 quadProcessor->setBounds(bounds); |
849 bounds.fBottom = SkScalarCeilToScalar(bounds.fBottom); | |
850 triangleProcessor->setBounds(bounds); | |
851 quadProcessor->setBounds(bounds); | |
852 | 844 |
853 // We use the fact that SkPath::transform path does subdivision base d on | 845 // We use the fact that SkPath::transform path does subdivision based on |
854 // perspective. Otherwise, we apply the view matrix when copying to the | 846 // perspective. Otherwise, we apply the view matrix when copying to the |
855 // segment representation. | 847 // segment representation. |
856 const SkMatrix* viewMatrix = &args.fViewMatrix; | 848 const SkMatrix* viewMatrix = &fViewMatrix; |
857 | 849 |
858 // We avoid initializing the path unless we have to | 850 // We avoid initializing the path unless we have to |
859 const SkPath* pathPtr = &args.fPath; | 851 const SkPath* pathPtr = &fPath; |
860 SkTLazy<SkPath> tmpPath; | 852 SkTLazy<SkPath> tmpPath; |
861 if (viewMatrix->hasPerspective()) { | 853 if (viewMatrix->hasPerspective()) { |
862 SkPath* tmpPathPtr = tmpPath.init(*pathPtr); | 854 SkPath* tmpPathPtr = tmpPath.init(*pathPtr); |
863 tmpPathPtr->setIsVolatile(true); | 855 tmpPathPtr->setIsVolatile(true); |
864 tmpPathPtr->transform(*viewMatrix); | 856 tmpPathPtr->transform(*viewMatrix); |
865 viewMatrix = &SkMatrix::I(); | 857 viewMatrix = &SkMatrix::I(); |
866 pathPtr = tmpPathPtr; | 858 pathPtr = tmpPathPtr; |
867 } | 859 } |
868 | 860 |
869 GrMesh mesh; | 861 GrMesh mesh; |
870 | 862 |
871 PLSVertices triVertices; | 863 PLSVertices triVertices; |
872 PLSVertices quadVertices; | 864 PLSVertices quadVertices; |
873 if (!get_geometry(*pathPtr, *viewMatrix, triVertices, quadVertices, rp, bounds)) { | 865 if (!get_geometry(*pathPtr, *viewMatrix, triVertices, quadVertices, rp, bounds)) { |
874 continue; | 866 return; |
875 } | 867 } |
876 | 868 |
877 if (triVertices.count()) { | 869 if (triVertices.count()) { |
878 const GrBuffer* triVertexBuffer; | 870 const GrBuffer* triVertexBuffer; |
879 int firstTriVertex; | 871 int firstTriVertex; |
880 size_t triStride = triangleProcessor->getVertexStride(); | 872 size_t triStride = triangleProcessor->getVertexStride(); |
881 PLSVertex* triVerts = reinterpret_cast<PLSVertex*>(target->makeV ertexSpace( | 873 PLSVertex* triVerts = reinterpret_cast<PLSVertex*>(target->makeVerte xSpace( |
882 triStride, triVertices.count(), &triVertexBuffer, &first TriVertex)); | 874 triStride, triVertices.count(), &triVertexBuffer, &firstTriV ertex)); |
883 if (!triVerts) { | 875 if (!triVerts) { |
884 SkDebugf("Could not allocate vertices\n"); | |
885 return; | |
886 } | |
887 for (int i = 0; i < triVertices.count(); ++i) { | |
888 triVerts[i] = triVertices[i]; | |
889 } | |
890 mesh.init(kTriangles_GrPrimitiveType, triVertexBuffer, firstTriV ertex, | |
891 triVertices.count()); | |
892 target->draw(triangleProcessor, mesh); | |
893 } | |
894 | |
895 if (quadVertices.count()) { | |
896 const GrBuffer* quadVertexBuffer; | |
897 int firstQuadVertex; | |
898 size_t quadStride = quadProcessor->getVertexStride(); | |
899 PLSVertex* quadVerts = reinterpret_cast<PLSVertex*>(target->make VertexSpace( | |
900 quadStride, quadVertices.count(), &quadVertexBuffer, &fi rstQuadVertex)); | |
901 if (!quadVerts) { | |
902 SkDebugf("Could not allocate vertices\n"); | |
903 return; | |
904 } | |
905 for (int i = 0; i < quadVertices.count(); ++i) { | |
906 quadVerts[i] = quadVertices[i]; | |
907 } | |
908 mesh.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQua dVertex, | |
909 quadVertices.count()); | |
910 target->draw(quadProcessor, mesh); | |
911 } | |
912 | |
913 SkAutoTUnref<GrGeometryProcessor> finishProcessor( | |
914 PLSFinishEffect::Create(this->color(), | |
915 pathPtr->getFillType() == | |
916 SkPath::FillType ::kEvenOdd_FillType, | |
917 invert, | |
918 this->usesLocalCoords())); | |
919 const GrBuffer* rectVertexBuffer; | |
920 size_t finishStride = finishProcessor->getVertexStride(); | |
921 int firstRectVertex; | |
922 static const int kRectVertexCount = 6; | |
923 SkPoint* rectVerts = reinterpret_cast<SkPoint*>(target->makeVertexSp ace( | |
924 finishStride, kRectVertexCount, &rectVertexBuffer, &firstRec tVertex)); | |
925 if (!rectVerts) { | |
926 SkDebugf("Could not allocate vertices\n"); | 876 SkDebugf("Could not allocate vertices\n"); |
927 return; | 877 return; |
928 } | 878 } |
929 rectVerts[0] = { bounds.fLeft, bounds.fTop }; | 879 for (int i = 0; i < triVertices.count(); ++i) { |
930 rectVerts[1] = { bounds.fLeft, bounds.fBottom }; | 880 triVerts[i] = triVertices[i]; |
931 rectVerts[2] = { bounds.fRight, bounds.fBottom }; | 881 } |
932 rectVerts[3] = { bounds.fLeft, bounds.fTop }; | 882 mesh.init(kTriangles_GrPrimitiveType, triVertexBuffer, firstTriVerte x, |
933 rectVerts[4] = { bounds.fRight, bounds.fTop }; | 883 triVertices.count()); |
934 rectVerts[5] = { bounds.fRight, bounds.fBottom }; | 884 target->draw(triangleProcessor, mesh); |
885 } | |
935 | 886 |
936 mesh.init(kTriangles_GrPrimitiveType, rectVertexBuffer, firstRectVer tex, | 887 if (quadVertices.count()) { |
937 kRectVertexCount); | 888 const GrBuffer* quadVertexBuffer; |
938 target->draw(finishProcessor, mesh); | 889 int firstQuadVertex; |
890 size_t quadStride = quadProcessor->getVertexStride(); | |
891 PLSVertex* quadVerts = reinterpret_cast<PLSVertex*>(target->makeVert exSpace( | |
892 quadStride, quadVertices.count(), &quadVertexBuffer, &firstQ uadVertex)); | |
893 if (!quadVerts) { | |
894 SkDebugf("Could not allocate vertices\n"); | |
895 return; | |
896 } | |
897 for (int i = 0; i < quadVertices.count(); ++i) { | |
898 quadVerts[i] = quadVertices[i]; | |
899 } | |
900 mesh.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVer tex, | |
901 quadVertices.count()); | |
902 target->draw(quadProcessor, mesh); | |
939 } | 903 } |
904 | |
905 SkAutoTUnref<GrGeometryProcessor> finishProcessor( | |
906 PLSFinishEffect::Create(fColor, | |
907 pathPtr->getFillType() == | |
908 SkPath::FillType::kE venOdd_FillType, | |
909 invert, | |
910 fUsesLocalCoords)); | |
911 const GrBuffer* rectVertexBuffer; | |
912 size_t finishStride = finishProcessor->getVertexStride(); | |
913 int firstRectVertex; | |
914 static const int kRectVertexCount = 6; | |
915 SkPoint* rectVerts = reinterpret_cast<SkPoint*>(target->makeVertexSpace( | |
916 finishStride, kRectVertexCount, &rectVertexBuffer, &firstRectVer tex)); | |
917 if (!rectVerts) { | |
918 SkDebugf("Could not allocate vertices\n"); | |
919 return; | |
920 } | |
921 rectVerts[0] = { bounds.fLeft, bounds.fTop }; | |
922 rectVerts[1] = { bounds.fLeft, bounds.fBottom }; | |
923 rectVerts[2] = { bounds.fRight, bounds.fBottom }; | |
924 rectVerts[3] = { bounds.fLeft, bounds.fTop }; | |
925 rectVerts[4] = { bounds.fRight, bounds.fTop }; | |
926 rectVerts[5] = { bounds.fRight, bounds.fBottom }; | |
927 | |
928 mesh.init(kTriangles_GrPrimitiveType, rectVertexBuffer, firstRectVertex, | |
929 kRectVertexCount); | |
930 target->draw(finishProcessor, mesh); | |
940 } | 931 } |
941 | 932 |
942 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
943 | |
944 private: | 933 private: |
945 PLSPathBatch(const Geometry& geometry) : INHERITED(ClassID()) { | |
946 fGeoData.push_back(geometry); | |
947 | |
948 // compute bounds | |
949 fBounds = geometry.fPath.getBounds(); | |
950 geometry.fViewMatrix.mapRect(&fBounds); | |
951 } | |
952 | |
953 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 934 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
954 return false; | 935 return false; |
955 } | 936 } |
956 | 937 |
957 GrColor color() const { return fBatch.fColor; } | 938 bool fUsesLocalCoords; |
958 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | |
959 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover age; } | |
960 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
961 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } | |
962 | 939 |
963 struct BatchTracker { | 940 GrColor fColor; |
964 GrColor fColor; | 941 SkPath fPath; |
965 bool fUsesLocalCoords; | 942 SkMatrix fViewMatrix; |
966 bool fColorIgnored; | |
967 bool fCoverageIgnored; | |
968 bool fCanTweakAlphaForCoverage; | |
969 }; | |
970 | |
971 BatchTracker fBatch; | |
972 SkSTArray<1, Geometry, true> fGeoData; | |
973 | |
974 typedef GrVertexBatch INHERITED; | 943 typedef GrVertexBatch INHERITED; |
975 }; | 944 }; |
976 | 945 |
977 SkDEBUGCODE(bool inPLSDraw = false;) | 946 SkDEBUGCODE(bool inPLSDraw = false;) |
978 bool GrPLSPathRenderer::onDrawPath(const DrawPathArgs& args) { | 947 bool GrPLSPathRenderer::onDrawPath(const DrawPathArgs& args) { |
979 SkASSERT(!args.fShape->isEmpty()) | 948 SkASSERT(!args.fShape->isEmpty()) |
980 SkASSERT(!inPLSDraw); | 949 SkASSERT(!inPLSDraw); |
981 SkDEBUGCODE(inPLSDraw = true;) | 950 SkDEBUGCODE(inPLSDraw = true;) |
982 PLSPathBatch::Geometry geometry; | 951 SkPath path; |
983 geometry.fColor = args.fColor; | 952 args.fShape->asPath(&path); |
984 geometry.fViewMatrix = *args.fViewMatrix; | |
985 args.fShape->asPath(&geometry.fPath); | |
986 | 953 |
987 SkAutoTUnref<GrDrawBatch> batch(PLSPathBatch::Create(geometry)); | 954 SkAutoTUnref<GrDrawBatch> batch(new PLSPathBatch(args.fColor, path, *args.fV iewMatrix)); |
988 | 955 |
989 GrPipelineBuilder pipelineBuilder(*args.fPaint, args.fDrawContext->mustUseHW AA(*args.fPaint)); | 956 GrPipelineBuilder pipelineBuilder(*args.fPaint, args.fDrawContext->mustUseHW AA(*args.fPaint)); |
990 pipelineBuilder.setUserStencil(args.fUserStencilSettings); | 957 pipelineBuilder.setUserStencil(args.fUserStencilSettings); |
991 | 958 |
992 args.fDrawContext->drawBatch(pipelineBuilder, *args.fClip, batch); | 959 args.fDrawContext->drawBatch(pipelineBuilder, *args.fClip, batch); |
993 | 960 |
994 SkDEBUGCODE(inPLSDraw = false;) | 961 SkDEBUGCODE(inPLSDraw = false;) |
995 return true; | 962 return true; |
996 | 963 |
997 } | 964 } |
998 | 965 |
999 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 966 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
1000 | 967 |
1001 #ifdef GR_TEST_UTILS | 968 #ifdef GR_TEST_UTILS |
1002 | 969 |
1003 DRAW_BATCH_TEST_DEFINE(PLSPathBatch) { | 970 DRAW_BATCH_TEST_DEFINE(PLSPathBatch) { |
1004 PLSPathBatch::Geometry geometry; | 971 GrColor color = GrRandomColor(random); |
1005 geometry.fColor = GrRandomColor(random); | 972 SkMatrix vm = GrTest::TestMatrixInvertible(random); |
1006 geometry.fViewMatrix = GrTest::TestMatrixInvertible(random); | 973 SkPath path = GrTest::TestPathConvex(random); |
1007 geometry.fPath = GrTest::TestPathConvex(random); | |
1008 | 974 |
1009 return PLSPathBatch::Create(geometry); | 975 return new PLSPathBatch(color, path, vm); |
1010 } | 976 } |
1011 | 977 |
1012 #endif | 978 #endif |
OLD | NEW |