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