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

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

Issue 23004010: Pull out Effect Shaders in GPU Path Renderer (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 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 "GrAAHairLinePathRenderer.h" 8 #include "GrAAHairLinePathRenderer.h"
9 9
10 #include "GrContext.h" 10 #include "GrContext.h"
11 #include "GrDrawState.h" 11 #include "GrDrawState.h"
12 #include "GrDrawTargetCaps.h" 12 #include "GrDrawTargetCaps.h"
13 #include "GrEffect.h" 13 #include "GrEffect.h"
14 #include "GrGpu.h" 14 #include "GrGpu.h"
15 #include "GrIndexBuffer.h" 15 #include "GrIndexBuffer.h"
16 #include "GrPathUtils.h" 16 #include "GrPathUtils.h"
17 #include "GrTBackendEffectFactory.h" 17 #include "GrTBackendEffectFactory.h"
18 #include "SkGeometry.h" 18 #include "SkGeometry.h"
19 #include "SkStroke.h" 19 #include "SkStroke.h"
20 #include "SkTemplates.h" 20 #include "SkTemplates.h"
21 21
22 #include "gl/GrGLEffect.h" 22 #include "effects/GrBezierEffect.h"
23 #include "gl/GrGLSL.h"
24 23
25 namespace { 24 namespace {
26 // quadratics are rendered as 5-sided polys in order to bound the 25 // quadratics are rendered as 5-sided polys in order to bound the
27 // AA stroke around the center-curve. See comments in push_quad_index_buffer and 26 // AA stroke around the center-curve. See comments in push_quad_index_buffer and
28 // bloat_quad. Quadratics and conics share an index buffer 27 // bloat_quad. Quadratics and conics share an index buffer
29 static const int kVertsPerQuad = 5; 28 static const int kVertsPerQuad = 5;
30 static const int kIdxsPerQuad = 9; 29 static const int kIdxsPerQuad = 9;
31 30
32 static const int kVertsPerLineSeg = 6; 31 static const int kVertsPerLineSeg = 6;
33 static const int kIdxsPerLineSeg = 12; 32 static const int kIdxsPerLineSeg = 12;
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 for (int i = 0; i < kVertsPerLineSeg; ++i) { 686 for (int i = 0; i < kVertsPerLineSeg; ++i) {
688 (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax); 687 (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax);
689 } 688 }
690 } 689 }
691 690
692 *vert += kVertsPerLineSeg; 691 *vert += kVertsPerLineSeg;
693 } 692 }
694 693
695 } 694 }
696 695
697 /**
698 * Shader is based off of "Resolution Independent Curve Rendering using
699 * Programmable Graphics Hardware" by Loop and Blinn.
700 * The output of this effect is a hairline edge for non rational cubics.
701 * Cubics are specified by implicit equation K^3 - LM.
702 * K, L, and M, are the first three values of the vertex attribute,
703 * the fourth value is not used. Distance is calculated using a
704 * first order approximation from the taylor series.
705 * Coverage is max(0, 1-distance).
706 */
707 class HairCubicEdgeEffect : public GrEffect {
708 public:
709 static GrEffectRef* Create() {
710 GR_CREATE_STATIC_EFFECT(gHairCubicEdgeEffect, HairCubicEdgeEffect, ());
711 gHairCubicEdgeEffect->ref();
712 return gHairCubicEdgeEffect;
713 }
714
715 virtual ~HairCubicEdgeEffect() {}
716
717 static const char* Name() { return "HairCubicEdge"; }
718
719 virtual void getConstantColorComponents(GrColor* color,
720 uint32_t* validFlags) const SK_OVERR IDE {
721 *validFlags = 0;
722 }
723
724 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
725 return GrTBackendEffectFactory<HairCubicEdgeEffect>::getInstance();
726 }
727
728 class GLEffect : public GrGLEffect {
729 public:
730 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
731 : INHERITED (factory) {}
732
733 virtual void emitCode(GrGLShaderBuilder* builder,
734 const GrDrawEffect& drawEffect,
735 EffectKey key,
736 const char* outputColor,
737 const char* inputColor,
738 const TextureSamplerArray& samplers) SK_OVERRIDE {
739 const char *vsName, *fsName;
740
741 SkAssertResult(builder->enableFeature(
742 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
743 builder->addVarying(kVec4f_GrSLType, "CubicCoeffs",
744 &vsName, &fsName);
745 const SkString* attr0Name =
746 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]);
747 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
748
749 builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
750
751 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
752 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
753 builder->fsCodeAppendf("\t\tfloat dfdx =\n"
754 "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
755 fsName, fsName, fsName, fsName);
756 builder->fsCodeAppendf("\t\tfloat dfdy =\n"
757 "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
758 fsName, fsName, fsName, fsName);
759 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
760 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
761 builder->fsCodeAppendf("\t\tfloat func = abs(%s.x*%s.x*%s.x - %s.y*% s.z);\n",
762 fsName, fsName, fsName, fsName, fsName);
763 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
764 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n" );
765 // Add line below for smooth cubic ramp
766 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2 .0*edgeAlpha);\n");
767
768 SkString modulate;
769 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
770 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() );
771 }
772
773 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
774 return 0x0;
775 }
776
777 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {}
778
779 private:
780 typedef GrGLEffect INHERITED;
781 };
782 private:
783 HairCubicEdgeEffect() {
784 this->addVertexAttrib(kVec4f_GrSLType);
785 }
786
787 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
788 return true;
789 }
790
791 GR_DECLARE_EFFECT_TEST;
792
793 typedef GrEffect INHERITED;
794 };
795
796 /**
797 * Shader is based off of Loop-Blinn Quadratic GPU Rendering
798 * The output of this effect is a hairline edge for conics.
799 * Conics specified by implicit equation K^2 - LM.
800 * K, L, and M, are the first three values of the vertex attribute,
801 * the fourth value is not used. Distance is calculated using a
802 * first order approximation from the taylor series.
803 * Coverage is max(0, 1-distance).
804 */
805
806 /**
807 * Test were also run using a second order distance approximation.
808 * There were two versions of the second order approx. The first version
809 * is of roughly the form:
810 * f(q) = |f(p)| - ||f'(p)||*||q-p|| - ||f''(p)||*||q-p||^2.
811 * The second is similar:
812 * f(q) = |f(p)| + ||f'(p)||*||q-p|| + ||f''(p)||*||q-p||^2.
813 * The exact version of the equations can be found in the paper
814 * "Distance Approximations for Rasterizing Implicit Curves" by Gabriel Taubin
815 *
816 * In both versions we solve the quadratic for ||q-p||.
817 * Version 1:
818 * gFM is magnitude of first partials and gFM2 is magnitude of 2nd partials (as derived from paper)
819 * builder->fsCodeAppend("\t\tedgeAlpha = (sqrt(gFM*gFM+4.0*func*gF2M) - gFM)/(2 .0*gF2M);\n");
820 * Version 2:
821 * builder->fsCodeAppend("\t\tedgeAlpha = (gFM - sqrt(gFM*gFM-4.0*func*gF2M))/(2 .0*gF2M);\n");
822 *
823 * Also note that 2nd partials of k,l,m are zero
824 *
825 * When comparing the two second order approximations to the first order approxi mations,
826 * the following results were found. Version 1 tends to underestimate the distan ces, thus it
827 * basically increases all the error that we were already seeing in the first or der
828 * approx. So this version is not the one to use. Version 2 has the opposite eff ect
829 * and tends to overestimate the distances. This is much closer to what we are
830 * looking for. It is able to render ellipses (even thin ones) without the need to chop.
831 * However, it can not handle thin hyperbolas well and thus would still rely on
832 * chopping to tighten the clipping. Another side effect of the overestimating i s
833 * that the curves become much thinner and "ropey". If all that was ever rendere d
834 * were "not too thin" curves and ellipses then 2nd order may have an advantage since
835 * only one geometry would need to be rendered. However no benches were run comp aring
836 * chopped first order and non chopped 2nd order.
837 */
838 class HairConicEdgeEffect : public GrEffect {
839 public:
840 static GrEffectRef* Create() {
841 GR_CREATE_STATIC_EFFECT(gHairConicEdgeEffect, HairConicEdgeEffect, ());
842 gHairConicEdgeEffect->ref();
843 return gHairConicEdgeEffect;
844 }
845
846 virtual ~HairConicEdgeEffect() {}
847
848 static const char* Name() { return "HairConicEdge"; }
849
850 virtual void getConstantColorComponents(GrColor* color,
851 uint32_t* validFlags) const SK_OVERR IDE {
852 *validFlags = 0;
853 }
854
855 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
856 return GrTBackendEffectFactory<HairConicEdgeEffect>::getInstance();
857 }
858
859 class GLEffect : public GrGLEffect {
860 public:
861 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
862 : INHERITED (factory) {}
863
864 virtual void emitCode(GrGLShaderBuilder* builder,
865 const GrDrawEffect& drawEffect,
866 EffectKey key,
867 const char* outputColor,
868 const char* inputColor,
869 const TextureSamplerArray& samplers) SK_OVERRIDE {
870 const char *vsName, *fsName;
871
872 SkAssertResult(builder->enableFeature(
873 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
874 builder->addVarying(kVec4f_GrSLType, "ConicCoeffs",
875 &vsName, &fsName);
876 const SkString* attr0Name =
877 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]);
878 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
879
880 builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
881
882 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
883 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
884 builder->fsCodeAppendf("\t\tfloat dfdx =\n"
885 "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s .z*dklmdx.y;\n",
886 fsName, fsName, fsName);
887 builder->fsCodeAppendf("\t\tfloat dfdy =\n"
888 "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s .z*dklmdy.y;\n",
889 fsName, fsName, fsName);
890 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
891 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
892 builder->fsCodeAppendf("\t\tfloat func = abs(%s.x*%s.x - %s.y*%s.z); \n", fsName, fsName,
893 fsName, fsName);
894 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
895 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n" );
896 // Add line below for smooth cubic ramp
897 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2 .0*edgeAlpha);\n");
898
899 SkString modulate;
900 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
901 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() );
902 }
903
904 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
905 return 0x0;
906 }
907
908 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {}
909
910 private:
911 typedef GrGLEffect INHERITED;
912 };
913
914 private:
915 HairConicEdgeEffect() {
916 this->addVertexAttrib(kVec4f_GrSLType);
917 }
918
919 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
920 return true;
921 }
922
923 GR_DECLARE_EFFECT_TEST;
924
925 typedef GrEffect INHERITED;
926 };
927
928 GR_DEFINE_EFFECT_TEST(HairConicEdgeEffect);
929
930 GrEffectRef* HairConicEdgeEffect::TestCreate(SkMWCRandom* random,
931 GrContext*,
932 const GrDrawTargetCaps& caps,
933 GrTexture*[]) {
934 return caps.shaderDerivativeSupport() ? HairConicEdgeEffect::Create() : NULL ;
935 }
936
937 /**
938 * The output of this effect is a hairline edge for quadratics.
939 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
940 * two components of the vertex attribute. Uses unsigned distance.
941 * Coverage is min(0, 1-distance). 3rd & 4th component unused.
942 * Requires shader derivative instruction support.
943 */
944 class HairQuadEdgeEffect : public GrEffect {
945 public:
946
947 static GrEffectRef* Create() {
948 GR_CREATE_STATIC_EFFECT(gHairQuadEdgeEffect, HairQuadEdgeEffect, ());
949 gHairQuadEdgeEffect->ref();
950 return gHairQuadEdgeEffect;
951 }
952
953 virtual ~HairQuadEdgeEffect() {}
954
955 static const char* Name() { return "HairQuadEdge"; }
956
957 virtual void getConstantColorComponents(GrColor* color,
958 uint32_t* validFlags) const SK_OVERR IDE {
959 *validFlags = 0;
960 }
961
962 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
963 return GrTBackendEffectFactory<HairQuadEdgeEffect>::getInstance();
964 }
965
966 class GLEffect : public GrGLEffect {
967 public:
968 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
969 : INHERITED (factory) {}
970
971 virtual void emitCode(GrGLShaderBuilder* builder,
972 const GrDrawEffect& drawEffect,
973 EffectKey key,
974 const char* outputColor,
975 const char* inputColor,
976 const TextureSamplerArray& samplers) SK_OVERRIDE {
977 const char *vsName, *fsName;
978 const SkString* attrName =
979 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]);
980 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
981
982 SkAssertResult(builder->enableFeature(
983 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
984 builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsNam e);
985
986 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
987 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
988 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx. y,\n"
989 "\t\t 2.0*%s.x*duvdy.x - duvdy. y);\n",
990 fsName, fsName);
991 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsNa me, fsName,
992 fsName);
993 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / do t(gF, gF));\n");
994 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n" );
995
996 SkString modulate;
997 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
998 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() );
999
1000 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
1001 }
1002
1003 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
1004 return 0x0;
1005 }
1006
1007 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {}
1008
1009 private:
1010 typedef GrGLEffect INHERITED;
1011 };
1012
1013 private:
1014 HairQuadEdgeEffect() {
1015 this->addVertexAttrib(kVec4f_GrSLType);
1016 }
1017
1018 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
1019 return true;
1020 }
1021
1022 GR_DECLARE_EFFECT_TEST;
1023
1024 typedef GrEffect INHERITED;
1025 };
1026
1027 GR_DEFINE_EFFECT_TEST(HairQuadEdgeEffect);
1028
1029 GrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random,
1030 GrContext*,
1031 const GrDrawTargetCaps& caps,
1032 GrTexture*[]) {
1033 // Doesn't work without derivative instructions.
1034 return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL;
1035 }
1036
1037 /////////////////////////////////////////////////////////////////////////////// 696 ///////////////////////////////////////////////////////////////////////////////
1038 697
1039 namespace { 698 namespace {
1040 699
1041 // position + edge 700 // position + edge
1042 extern const GrVertexAttrib gHairlineBezierAttribs[] = { 701 extern const GrVertexAttrib gHairlineBezierAttribs[] = {
1043 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind ing}, 702 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind ing},
1044 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g} 703 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g}
1045 }; 704 };
1046 705
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1290 // perspective. 949 // perspective.
1291 if (target->getDrawState().getViewMatrix().hasPerspective()) { 950 if (target->getDrawState().getViewMatrix().hasPerspective()) {
1292 asr.set(target, GrDrawTarget::kPreserve_ASRInit); 951 asr.set(target, GrDrawTarget::kPreserve_ASRInit);
1293 } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { 952 } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
1294 return false; 953 return false;
1295 } 954 }
1296 GrDrawState* drawState = target->drawState(); 955 GrDrawState* drawState = target->drawState();
1297 956
1298 static const int kEdgeAttrIndex = 1; 957 static const int kEdgeAttrIndex = 1;
1299 958
1300 GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); 959 GrEffectRef* hairQuadEffect = GrQuadEffect::Create(kHairAA_BezierEffectT ype);
1301 GrEffectRef* hairConicEffect = HairConicEdgeEffect::Create(); 960 GrEffectRef* hairConicEffect = GrConicEffect::Create(kHairAA_BezierEffec tType);
1302 961
1303 // Check devBounds 962 // Check devBounds
1304 SkASSERT(check_bounds<BezierVertex>(drawState, devBounds, arg.vertices() , 963 SkASSERT(check_bounds<BezierVertex>(drawState, devBounds, arg.vertices() ,
1305 kVertsPerQuad * quadCnt + kVertsPerQ uad * conicCnt)); 964 kVertsPerQuad * quadCnt + kVertsPerQ uad * conicCnt));
1306 965
1307 { 966 {
1308 GrDrawState::AutoRestoreEffects are(drawState); 967 GrDrawState::AutoRestoreEffects are(drawState);
1309 target->setIndexSourceToBuffer(fQuadsIndexBuffer); 968 target->setIndexSourceToBuffer(fQuadsIndexBuffer);
1310 int quads = 0; 969 int quads = 0;
1311 drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref( ); 970 drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref( );
(...skipping 23 matching lines...) Expand all
1335 &devBounds); 994 &devBounds);
1336 conics += n; 995 conics += n;
1337 } 996 }
1338 } 997 }
1339 } 998 }
1340 999
1341 target->resetIndexSource(); 1000 target->resetIndexSource();
1342 1001
1343 return true; 1002 return true;
1344 } 1003 }
OLDNEW
« no previous file with comments | « gyp/gpu.gypi ('k') | src/gpu/effects/GrBezierEffect.h » ('j') | src/gpu/effects/GrBezierEffect.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698