OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
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 "SkGradientShaderPriv.h" | 8 #include "SkGradientShaderPriv.h" |
9 #include "SkLinearGradient.h" | 9 #include "SkLinearGradient.h" |
10 #include "SkRadialGradient.h" | 10 #include "SkRadialGradient.h" |
(...skipping 813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
824 #include "SkGr.h" | 824 #include "SkGr.h" |
825 | 825 |
826 GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory) | 826 GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory) |
827 : INHERITED(factory) | 827 : INHERITED(factory) |
828 , fCachedYCoord(SK_ScalarMax) | 828 , fCachedYCoord(SK_ScalarMax) |
829 , fEffectMatrix(kCoordsType) { | 829 , fEffectMatrix(kCoordsType) { |
830 } | 830 } |
831 | 831 |
832 GrGLGradientEffect::~GrGLGradientEffect() { } | 832 GrGLGradientEffect::~GrGLGradientEffect() { } |
833 | 833 |
834 void GrGLGradientEffect::emitYCoordUniform(GrGLShaderBuilder* builder) { | 834 void GrGLGradientEffect::emitUniforms(GrGLShaderBuilder* builder, EffectKey key) { |
835 fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, | 835 |
836 kFloat_GrSLType, "GradientYCoordFS"); | 836 if (GrGradientEffect::kTwo_ColorType == getColorType(key)) { // 2 Color case |
837 fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Shader Type, | |
838 kVec4f_GrSLType, "GradientStartColo r"); | |
839 fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderTy pe, | |
840 kVec4f_GrSLType, "GradientEndColor"); | |
841 | |
842 } else if (GrGradientEffect::kThree_ColorType == getColorType(key)){ // 3 Co lor Case | |
843 fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Shader Type, | |
844 kVec4f_GrSLType, "GradientStartColo r"); | |
845 fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderTy pe, | |
846 kVec4f_GrSLType, "GradientMidColor"); | |
847 fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderTy pe, | |
848 kVec4f_GrSLType, "GradientEndColor" ); | |
849 | |
850 } else { // if not a fast case | |
851 fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, | |
852 kFloat_GrSLType, "GradientYCoordFS"); | |
853 } | |
854 } | |
855 | |
856 static void setColorUni(const GrGLUniformManager& uman, | |
857 const GrGLUniformManager::UniformHandle uni, | |
858 const SkColor color){ | |
859 uman.set4f(uni, | |
860 SkColorGetR(color)/255.f, | |
861 SkColorGetG(color)/255.f, | |
862 SkColorGetB(color)/255.f, | |
863 SkColorGetA(color)/255.f | |
864 ); | |
837 } | 865 } |
838 | 866 |
839 void GrGLGradientEffect::setData(const GrGLUniformManager& uman, | 867 void GrGLGradientEffect::setData(const GrGLUniformManager& uman, |
840 const GrDrawEffect& drawEffect) { | 868 const GrDrawEffect& drawEffect) { |
869 | |
841 const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>(); | 870 const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>(); |
842 const GrTexture* texture = e.texture(0); | |
843 fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, texture); | |
844 | 871 |
845 SkScalar yCoord = e.getYCoord(); | 872 |
846 if (yCoord != fCachedYCoord) { | 873 if (GrGradientEffect::kTwo_ColorType == e.getColorType()){ |
847 uman.set1f(fFSYUni, yCoord); | 874 |
848 fCachedYCoord = yCoord; | 875 fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, NULL); |
876 const SkColor* colors = e.getColors(); | |
877 setColorUni(uman, fColorStartUni, colors[0]); | |
878 setColorUni(uman, fColorEndUni, colors[1]); | |
879 | |
880 } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){ | |
881 | |
882 fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, NULL); | |
883 const SkColor* colors = e.getColors(); | |
884 setColorUni(uman, fColorStartUni, colors[0]); | |
885 setColorUni(uman, fColorMidUni, colors[1]); | |
886 setColorUni(uman, fColorEndUni, colors[2]); | |
887 | |
888 } else { | |
889 | |
890 const GrTexture* texture = e.texture(0); | |
891 fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, texture); | |
892 | |
893 SkScalar yCoord = e.getYCoord(); | |
894 if (yCoord != fCachedYCoord) { | |
895 uman.set1f(fFSYUni, yCoord); | |
896 fCachedYCoord = yCoord; | |
897 } | |
849 } | 898 } |
850 } | 899 } |
851 | 900 |
852 GrGLEffect::EffectKey GrGLGradientEffect::GenMatrixKey(const GrDrawEffect& drawE ffect) { | 901 |
902 GrGLEffect::EffectKey GrGLGradientEffect::GenBaseGradientKey(const GrDrawEffect& drawEffect) { | |
853 const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>(); | 903 const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>(); |
854 const GrTexture* texture = e.texture(0); | 904 const GrTexture* texture = NULL; |
855 return GrGLEffectMatrix::GenKey(e.getMatrix(), drawEffect, kCoordsType, text ure); | 905 |
906 if (GrGradientEffect::kTexture_ColorType == e.getColorType()){ | |
907 texture = e.texture(0); | |
908 } | |
909 | |
910 EffectKey key = GrGLEffectMatrix::GenKey(e.getMatrix(), drawEffect, kCoordsT ype, texture); | |
911 | |
912 if (GrGradientEffect::kTwo_ColorType == e.getColorType()) { | |
913 key = key | kTwoColorKey; | |
914 } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){ | |
915 key = key | kThreeColorKey; | |
916 } | |
917 | |
918 return key; | |
856 } | 919 } |
857 | 920 |
858 void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder, | 921 void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder, |
859 EffectKey key, | 922 EffectKey key, |
860 const char** fsCoordName, | 923 const char** fsCoordName, |
861 const char** vsVaryingName, | 924 const char** vsVaryingName, |
862 GrSLType* vsVaryingType) { | 925 GrSLType* vsVaryingType) { |
863 fEffectMatrix.emitCodeMakeFSCoords2D(builder, | 926 fEffectMatrix.emitCodeMakeFSCoords2D(builder, |
864 key & kMatrixKeyMask, | 927 key & kMatrixKeyMask, |
865 fsCoordName, | 928 fsCoordName, |
866 vsVaryingName, | 929 vsVaryingName, |
867 vsVaryingType); | 930 vsVaryingType); |
868 } | 931 } |
869 | 932 |
870 void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder, | 933 void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder, |
871 const char* gradientTValue, | 934 const char* gradientTValue, |
872 const char* outputColor, | 935 EffectKey key, |
873 const char* inputColor, | 936 const char* outputColor, |
874 const GrGLShaderBuilder::TextureSampler & sampler) { | 937 const char* inputColor, |
938 const GrGLShaderBuilder::TextureSamplerArray& samplers) { | |
939 if (GrGradientEffect::kTwo_ColorType == getColorType(key)){ | |
875 | 940 |
876 builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n", | 941 builder->fsCodeAppendf("\tvec4 colorTemp = mix(%s, %s, %s);\n", |
877 gradientTValue, | 942 builder->getUniformVariable(fColorStartUni).c_str (), |
878 builder->getUniformVariable(fFSYUni).c_str()); | 943 builder->getUniformVariable(fColorEndUni).c_str() , |
879 builder->fsCodeAppendf("\t%s = ", outputColor); | 944 gradientTValue); |
880 builder->appendTextureLookupAndModulate(GrGLShaderBuilder::kFragment_ShaderT ype, | 945 |
881 inputColor, | 946 SkString output, colorTemp; |
882 sampler, | 947 colorTemp.append("colorTemp"); |
883 "coord"); | 948 builder->fsCodeAppendf("\t%s = ", outputColor); |
884 builder->fsCodeAppend(";\n"); | 949 GrGLSLModulatef<4>(&output, inputColor, colorTemp.c_str()); |
950 builder->fsCodeAppend(output.c_str()); | |
951 builder->fsCodeAppend(";\n"); | |
952 | |
953 | |
954 } else if (GrGradientEffect::kThree_ColorType == getColorType(key)){ | |
955 | |
956 builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n", | |
957 gradientTValue); | |
958 builder->fsCodeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s +(1.0 - min(abs(oneMinus2t), 1.0)) * %s + clamp(-oneMinus2t, 0.0, 1.0) * %s; \n", | |
959 builder->getUniformVariable(fColorStartUni).c_str (), | |
960 builder->getUniformVariable(fColorMidUni).c_str() , | |
961 builder->getUniformVariable(fColorEndUni).c_str() ); | |
962 | |
963 SkString output, colorTemp; | |
964 colorTemp.append("colorTemp"); | |
965 builder->fsCodeAppendf("\t%s = ", outputColor); | |
966 GrGLSLModulatef<4>(&output, inputColor, colorTemp.c_str()); | |
967 builder->fsCodeAppend(output.c_str()); | |
968 builder->fsCodeAppend(";\n"); | |
969 | |
970 } else { | |
971 builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n", | |
972 gradientTValue, | |
973 builder->getUniformVariable(fFSYUni).c_str()); | |
974 builder->fsCodeAppendf("\t%s = ", outputColor); | |
975 builder->appendTextureLookupAndModulate(GrGLShaderBuilder::kFragment_Sha derType, | |
976 inputColor, | |
977 samplers[0], | |
978 "coord"); | |
979 builder->fsCodeAppend(";\n"); | |
980 } | |
885 } | 981 } |
886 | 982 |
887 ///////////////////////////////////////////////////////////////////// | 983 ///////////////////////////////////////////////////////////////////// |
888 | 984 |
889 GrGradientEffect::GrGradientEffect(GrContext* ctx, | 985 GrGradientEffect::GrGradientEffect(GrContext* ctx, |
890 const SkGradientShaderBase& shader, | 986 const SkGradientShaderBase& shader, |
891 const SkMatrix& matrix, | 987 const SkMatrix& matrix, |
892 SkShader::TileMode tileMode) { | 988 SkShader::TileMode tileMode) { |
893 // TODO: check for simple cases where we don't need a texture: | |
894 //GradientInfo info; | |
895 //shader.asAGradient(&info); | |
896 //if (info.fColorCount == 2) { ... | |
897 | 989 |
898 fMatrix = matrix; | |
899 | 990 |
900 SkBitmap bitmap; | 991 SkBitmap bitmap; |
901 shader.getGradientTableBitmap(&bitmap); | 992 shader.getGradientTableBitmap(&bitmap); |
902 | 993 fMatrix = matrix; |
903 fIsOpaque = shader.isOpaque(); | 994 fIsOpaque = shader.isOpaque(); |
904 | 995 |
905 GrTextureStripAtlas::Desc desc; | 996 SkShader::GradientInfo info; |
906 desc.fWidth = bitmap.width(); | 997 SkScalar pos[3] = {0}; |
907 desc.fHeight = 32; | |
908 desc.fRowHeight = bitmap.height(); | |
909 desc.fContext = ctx; | |
910 desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config()); | |
911 fAtlas = GrTextureStripAtlas::GetAtlas(desc); | |
912 SkASSERT(NULL != fAtlas); | |
913 | 998 |
914 // We always filter the gradient table. Each table is one row of a texture, so always y-clamp. | 999 info.fColorCount = 3; |
915 GrTextureParams params; | 1000 info.fColors = &fColors[0]; |
916 params.setFilterMode(GrTextureParams::kBilerp_FilterMode); | 1001 info.fColorOffsets = &pos[0]; |
917 params.setTileModeX(tileMode); | 1002 shader.asAGradient(&info); |
918 | 1003 |
919 fRow = fAtlas->lockRow(bitmap); | 1004 if (2 == info.fColorCount) { // if 2 color |
920 if (-1 != fRow) { | 1005 fRow = -1; // flag for no atlas |
921 fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf * | 1006 fColorType = kTwo_ColorType; |
922 fAtlas->getVerticalScaleFactor(); | 1007 } else if (3 == info.fColorCount && |
923 fTextureAccess.reset(fAtlas->getTexture(), params); | 1008 (SkScalarAbs(pos[1] - 0.5) < 0.01)) { // 3 color symmetric |
1009 fRow = -1; // flag for no atlas | |
1010 fColorType = kThree_ColorType; | |
924 } else { | 1011 } else { |
925 GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, ¶m s); | 1012 fColorType = kTexture_ColorType; |
926 fTextureAccess.reset(texture, params); | 1013 |
927 fYCoord = SK_ScalarHalf; | 1014 GrTextureStripAtlas::Desc desc; |
1015 desc.fWidth = bitmap.width(); | |
1016 desc.fHeight = 32; | |
1017 desc.fRowHeight = bitmap.height(); | |
1018 desc.fContext = ctx; | |
1019 desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config()); | |
1020 fAtlas = GrTextureStripAtlas::GetAtlas(desc); | |
1021 GrAssert(NULL != fAtlas); | |
928 | 1022 |
929 // Unlock immediately, this is not great, but we don't have a way of | 1023 // We always filter the gradient table. Each table is one row of a textu re, always y-clamp. |
930 // knowing when else to unlock it currently, so it may get purged from | 1024 GrTextureParams params; |
931 // the cache, but it'll still be ref'd until it's no longer being used. | 1025 params.setFilterMode(GrTextureParams::kBilerp_FilterMode); |
932 GrUnlockAndUnrefCachedBitmapTexture(texture); | 1026 params.setTileModeX(tileMode); |
1027 | |
1028 fRow = fAtlas->lockRow(bitmap); | |
1029 if (-1 != fRow) { | |
1030 fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf * | |
1031 fAtlas->getVerticalScaleFactor(); | |
1032 fTextureAccess.reset(fAtlas->getTexture(), params); | |
1033 } else { | |
1034 GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, &p arams); | |
1035 fTextureAccess.reset(texture, params); | |
1036 fYCoord = SK_ScalarHalf; | |
1037 | |
1038 // Unlock immediately, this is not great, but we don't have a way of | |
1039 // knowing when else to unlock it currently, so it may get purged fr om | |
1040 // the cache, but it'll still be ref'd until it's no longer being us ed. | |
1041 GrUnlockAndUnrefCachedBitmapTexture(texture); | |
1042 } | |
1043 this->addTextureAccess(&fTextureAccess); | |
933 } | 1044 } |
934 this->addTextureAccess(&fTextureAccess); | |
935 } | 1045 } |
936 | 1046 |
937 GrGradientEffect::~GrGradientEffect() { | 1047 GrGradientEffect::~GrGradientEffect() { |
938 if (this->useAtlas()) { | 1048 if (this->useAtlas()) { |
939 fAtlas->unlockRow(fRow); | 1049 fAtlas->unlockRow(fRow); |
940 } | 1050 } |
941 } | 1051 } |
942 | 1052 |
943 bool GrGradientEffect::onIsEqual(const GrEffect& effect) const { | 1053 bool GrGradientEffect::onIsEqual(const GrEffect& effect) const { |
944 const GrGradientEffect& s = CastEffect<GrGradientEffect>(effect); | 1054 const GrGradientEffect& s = CastEffect<GrGradientEffect>(effect); |
945 return fTextureAccess.getTexture() == s.fTextureAccess.getTexture() && | 1055 |
946 fTextureAccess.getParams().getTileModeX() == | 1056 if (this->fColorType == s.getColorType()){ |
reed1
2013/08/15 21:32:15
nit: Skia doesn't use this-> for fields, but it do
dierk
2013/08/16 16:59:56
Done.
| |
1057 | |
1058 if (kTwo_ColorType == this->fColorType) { | |
1059 if (this->getColors()[0] != s.getColors()[0] || | |
1060 this->getColors()[1] != s.getColors()[1]) { | |
1061 return false; | |
1062 } | |
1063 } else if (kThree_ColorType == this->fColorType) { | |
1064 if (this->getColors()[0] != s.getColors()[0] || | |
1065 this->getColors()[1] != s.getColors()[1] || | |
1066 this->getColors()[2] != s.getColors()[2]) { | |
1067 return false; | |
1068 } | |
1069 } | |
1070 | |
1071 return fTextureAccess.getTexture() == s.fTextureAccess.getTexture() && | |
1072 fTextureAccess.getParams().getTileModeX() == | |
947 s.fTextureAccess.getParams().getTileModeX() && | 1073 s.fTextureAccess.getParams().getTileModeX() && |
948 this->useAtlas() == s.useAtlas() && | 1074 this->useAtlas() == s.useAtlas() && |
949 fYCoord == s.getYCoord() && | 1075 fYCoord == s.getYCoord() && |
950 fMatrix.cheapEqualTo(s.getMatrix()); | 1076 fMatrix.cheapEqualTo(s.getMatrix()); |
1077 } | |
1078 | |
1079 return false; | |
951 } | 1080 } |
952 | 1081 |
953 void GrGradientEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const { | 1082 void GrGradientEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const { |
954 if (fIsOpaque && (kA_GrColorComponentFlag & *validFlags) && 0xff == GrColorU npackA(*color)) { | 1083 if (fIsOpaque && (kA_GrColorComponentFlag & *validFlags) && 0xff == GrColorU npackA(*color)) { |
955 *validFlags = kA_GrColorComponentFlag; | 1084 *validFlags = kA_GrColorComponentFlag; |
956 } else { | 1085 } else { |
957 *validFlags = 0; | 1086 *validFlags = 0; |
958 } | 1087 } |
959 } | 1088 } |
960 | 1089 |
(...skipping 15 matching lines...) Expand all Loading... | |
976 (*stops)[i] = stop; | 1105 (*stops)[i] = stop; |
977 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; | 1106 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; |
978 } | 1107 } |
979 } | 1108 } |
980 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); | 1109 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); |
981 | 1110 |
982 return outColors; | 1111 return outColors; |
983 } | 1112 } |
984 | 1113 |
985 #endif | 1114 #endif |
OLD | NEW |