| 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(); |
| 842 for (int i = 0; i < instanceCount; ++i) { | 837 SkRect bounds; |
| 843 const Geometry& args = fGeoData[i]; | 838 this->bounds().roundOut(&bounds); |
| 844 SkRect bounds = args.fPath.getBounds(); | 839 triangleProcessor->setBounds(bounds); |
| 845 args.fViewMatrix.mapRect(&bounds); | 840 quadProcessor->setBounds(bounds); |
| 846 bounds.fLeft = SkScalarFloorToScalar(bounds.fLeft); | |
| 847 bounds.fTop = SkScalarFloorToScalar(bounds.fTop); | |
| 848 bounds.fRight = SkScalarCeilToScalar(bounds.fRight); | |
| 849 bounds.fBottom = SkScalarCeilToScalar(bounds.fBottom); | |
| 850 triangleProcessor->setBounds(bounds); | |
| 851 quadProcessor->setBounds(bounds); | |
| 852 | 841 |
| 853 // We use the fact that SkPath::transform path does subdivision base
d on | 842 // We use the fact that SkPath::transform path does subdivision based on |
| 854 // perspective. Otherwise, we apply the view matrix when copying to
the | 843 // perspective. Otherwise, we apply the view matrix when copying to the |
| 855 // segment representation. | 844 // segment representation. |
| 856 const SkMatrix* viewMatrix = &args.fViewMatrix; | 845 const SkMatrix* viewMatrix = &fViewMatrix; |
| 857 | 846 |
| 858 // We avoid initializing the path unless we have to | 847 // We avoid initializing the path unless we have to |
| 859 const SkPath* pathPtr = &args.fPath; | 848 const SkPath* pathPtr = &fPath; |
| 860 SkTLazy<SkPath> tmpPath; | 849 SkTLazy<SkPath> tmpPath; |
| 861 if (viewMatrix->hasPerspective()) { | 850 if (viewMatrix->hasPerspective()) { |
| 862 SkPath* tmpPathPtr = tmpPath.init(*pathPtr); | 851 SkPath* tmpPathPtr = tmpPath.init(*pathPtr); |
| 863 tmpPathPtr->setIsVolatile(true); | 852 tmpPathPtr->setIsVolatile(true); |
| 864 tmpPathPtr->transform(*viewMatrix); | 853 tmpPathPtr->transform(*viewMatrix); |
| 865 viewMatrix = &SkMatrix::I(); | 854 viewMatrix = &SkMatrix::I(); |
| 866 pathPtr = tmpPathPtr; | 855 pathPtr = tmpPathPtr; |
| 867 } | 856 } |
| 868 | 857 |
| 869 GrMesh mesh; | 858 GrMesh mesh; |
| 870 | 859 |
| 871 PLSVertices triVertices; | 860 PLSVertices triVertices; |
| 872 PLSVertices quadVertices; | 861 PLSVertices quadVertices; |
| 873 if (!get_geometry(*pathPtr, *viewMatrix, triVertices, quadVertices,
rp, bounds)) { | 862 if (!get_geometry(*pathPtr, *viewMatrix, triVertices, quadVertices, rp,
bounds)) { |
| 874 continue; | 863 return; |
| 875 } | 864 } |
| 876 | 865 |
| 877 if (triVertices.count()) { | 866 if (triVertices.count()) { |
| 878 const GrBuffer* triVertexBuffer; | 867 const GrBuffer* triVertexBuffer; |
| 879 int firstTriVertex; | 868 int firstTriVertex; |
| 880 size_t triStride = triangleProcessor->getVertexStride(); | 869 size_t triStride = triangleProcessor->getVertexStride(); |
| 881 PLSVertex* triVerts = reinterpret_cast<PLSVertex*>(target->makeV
ertexSpace( | 870 PLSVertex* triVerts = reinterpret_cast<PLSVertex*>(target->makeVerte
xSpace( |
| 882 triStride, triVertices.count(), &triVertexBuffer, &first
TriVertex)); | 871 triStride, triVertices.count(), &triVertexBuffer, &firstTriV
ertex)); |
| 883 if (!triVerts) { | 872 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"); | 873 SkDebugf("Could not allocate vertices\n"); |
| 927 return; | 874 return; |
| 928 } | 875 } |
| 929 rectVerts[0] = { bounds.fLeft, bounds.fTop }; | 876 for (int i = 0; i < triVertices.count(); ++i) { |
| 930 rectVerts[1] = { bounds.fLeft, bounds.fBottom }; | 877 triVerts[i] = triVertices[i]; |
| 931 rectVerts[2] = { bounds.fRight, bounds.fBottom }; | 878 } |
| 932 rectVerts[3] = { bounds.fLeft, bounds.fTop }; | 879 mesh.init(kTriangles_GrPrimitiveType, triVertexBuffer, firstTriVerte
x, |
| 933 rectVerts[4] = { bounds.fRight, bounds.fTop }; | 880 triVertices.count()); |
| 934 rectVerts[5] = { bounds.fRight, bounds.fBottom }; | 881 target->draw(triangleProcessor, mesh); |
| 882 } |
| 935 | 883 |
| 936 mesh.init(kTriangles_GrPrimitiveType, rectVertexBuffer, firstRectVer
tex, | 884 if (quadVertices.count()) { |
| 937 kRectVertexCount); | 885 const GrBuffer* quadVertexBuffer; |
| 938 target->draw(finishProcessor, mesh); | 886 int firstQuadVertex; |
| 887 size_t quadStride = quadProcessor->getVertexStride(); |
| 888 PLSVertex* quadVerts = reinterpret_cast<PLSVertex*>(target->makeVert
exSpace( |
| 889 quadStride, quadVertices.count(), &quadVertexBuffer, &firstQ
uadVertex)); |
| 890 if (!quadVerts) { |
| 891 SkDebugf("Could not allocate vertices\n"); |
| 892 return; |
| 893 } |
| 894 for (int i = 0; i < quadVertices.count(); ++i) { |
| 895 quadVerts[i] = quadVertices[i]; |
| 896 } |
| 897 mesh.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVer
tex, |
| 898 quadVertices.count()); |
| 899 target->draw(quadProcessor, mesh); |
| 939 } | 900 } |
| 901 |
| 902 SkAutoTUnref<GrGeometryProcessor> finishProcessor( |
| 903 PLSFinishEffect::Create(fColor, |
| 904 pathPtr->getFillType() == |
| 905 SkPath::FillType::kE
venOdd_FillType, |
| 906 invert, |
| 907 fUsesLocalCoords)); |
| 908 const GrBuffer* rectVertexBuffer; |
| 909 size_t finishStride = finishProcessor->getVertexStride(); |
| 910 int firstRectVertex; |
| 911 static const int kRectVertexCount = 6; |
| 912 SkPoint* rectVerts = reinterpret_cast<SkPoint*>(target->makeVertexSpace( |
| 913 finishStride, kRectVertexCount, &rectVertexBuffer, &firstRectVer
tex)); |
| 914 if (!rectVerts) { |
| 915 SkDebugf("Could not allocate vertices\n"); |
| 916 return; |
| 917 } |
| 918 rectVerts[0] = { bounds.fLeft, bounds.fTop }; |
| 919 rectVerts[1] = { bounds.fLeft, bounds.fBottom }; |
| 920 rectVerts[2] = { bounds.fRight, bounds.fBottom }; |
| 921 rectVerts[3] = { bounds.fLeft, bounds.fTop }; |
| 922 rectVerts[4] = { bounds.fRight, bounds.fTop }; |
| 923 rectVerts[5] = { bounds.fRight, bounds.fBottom }; |
| 924 |
| 925 mesh.init(kTriangles_GrPrimitiveType, rectVertexBuffer, firstRectVertex, |
| 926 kRectVertexCount); |
| 927 target->draw(finishProcessor, mesh); |
| 940 } | 928 } |
| 941 | 929 |
| 942 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 943 | |
| 944 private: | 930 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 { | 931 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
| 954 return false; | 932 return false; |
| 955 } | 933 } |
| 956 | 934 |
| 957 GrColor color() const { return fBatch.fColor; } | 935 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 | 936 |
| 963 struct BatchTracker { | 937 GrColor fColor; |
| 964 GrColor fColor; | 938 SkPath fPath; |
| 965 bool fUsesLocalCoords; | 939 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; | 940 typedef GrVertexBatch INHERITED; |
| 975 }; | 941 }; |
| 976 | 942 |
| 977 SkDEBUGCODE(bool inPLSDraw = false;) | 943 SkDEBUGCODE(bool inPLSDraw = false;) |
| 978 bool GrPLSPathRenderer::onDrawPath(const DrawPathArgs& args) { | 944 bool GrPLSPathRenderer::onDrawPath(const DrawPathArgs& args) { |
| 979 SkASSERT(!args.fShape->isEmpty()) | 945 SkASSERT(!args.fShape->isEmpty()) |
| 980 SkASSERT(!inPLSDraw); | 946 SkASSERT(!inPLSDraw); |
| 981 SkDEBUGCODE(inPLSDraw = true;) | 947 SkDEBUGCODE(inPLSDraw = true;) |
| 982 PLSPathBatch::Geometry geometry; | 948 SkPath path; |
| 983 geometry.fColor = args.fColor; | 949 args.fShape->asPath(&path); |
| 984 geometry.fViewMatrix = *args.fViewMatrix; | |
| 985 args.fShape->asPath(&geometry.fPath); | |
| 986 | 950 |
| 987 SkAutoTUnref<GrDrawBatch> batch(PLSPathBatch::Create(geometry)); | 951 SkAutoTUnref<GrDrawBatch> batch(new PLSPathBatch(args.fColor, path, *args.fV
iewMatrix)); |
| 988 | 952 |
| 989 GrPipelineBuilder pipelineBuilder(*args.fPaint, args.fDrawContext->mustUseHW
AA(*args.fPaint)); | 953 GrPipelineBuilder pipelineBuilder(*args.fPaint, args.fDrawContext->mustUseHW
AA(*args.fPaint)); |
| 990 pipelineBuilder.setUserStencil(args.fUserStencilSettings); | 954 pipelineBuilder.setUserStencil(args.fUserStencilSettings); |
| 991 | 955 |
| 992 args.fDrawContext->drawBatch(pipelineBuilder, *args.fClip, batch); | 956 args.fDrawContext->drawBatch(pipelineBuilder, *args.fClip, batch); |
| 993 | 957 |
| 994 SkDEBUGCODE(inPLSDraw = false;) | 958 SkDEBUGCODE(inPLSDraw = false;) |
| 995 return true; | 959 return true; |
| 996 | 960 |
| 997 } | 961 } |
| 998 | 962 |
| 999 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 963 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 1000 | 964 |
| 1001 #ifdef GR_TEST_UTILS | 965 #ifdef GR_TEST_UTILS |
| 1002 | 966 |
| 1003 DRAW_BATCH_TEST_DEFINE(PLSPathBatch) { | 967 DRAW_BATCH_TEST_DEFINE(PLSPathBatch) { |
| 1004 PLSPathBatch::Geometry geometry; | 968 GrColor color = GrRandomColor(random); |
| 1005 geometry.fColor = GrRandomColor(random); | 969 SkMatrix vm = GrTest::TestMatrixInvertible(random); |
| 1006 geometry.fViewMatrix = GrTest::TestMatrixInvertible(random); | 970 SkPath path = GrTest::TestPathConvex(random); |
| 1007 geometry.fPath = GrTest::TestPathConvex(random); | |
| 1008 | 971 |
| 1009 return PLSPathBatch::Create(geometry); | 972 return new PLSPathBatch(color, path, vm); |
| 1010 } | 973 } |
| 1011 | 974 |
| 1012 #endif | 975 #endif |
| OLD | NEW |