Chromium Code Reviews| 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 |