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

Side by Side Diff: src/effects/gradients/SkGradientShader.cpp

Issue 22854005: GPU Gradients (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: remove dead line of code Created 7 years, 3 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
« no previous file with comments | « src/core/SkShader.cpp ('k') | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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_Visibility, 835
836 kFloat_GrSLType, "GradientYCoordFS"); 836 if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)) { // 2 Color case
837 fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibi lity,
838 kVec4f_GrSLType, "GradientStartColo r");
839 fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili ty,
840 kVec4f_GrSLType, "GradientEndColor");
841
842 } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){ // 3 Color Case
843 fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibi lity,
844 kVec4f_GrSLType, "GradientStartColo r");
845 fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili ty,
846 kVec4f_GrSLType, "GradientMidColor");
847 fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili ty,
848 kVec4f_GrSLType, "GradientEndColor" );
849
850 } else { // if not a fast case
851 fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
852 kFloat_GrSLType, "GradientYCoordFS");
853 }
854 }
855
856 static inline void set_color_uni(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 }
865
866 static inline void set_mul_color_uni(const GrGLUniformManager& uman,
867 const GrGLUniformManager::UniformHandle uni ,
868 const SkColor* color){
869 float a = SkColorGetA(*color) / 255.f;
870 float aDiv255 = a / 255.f;
871 uman.set4f(uni,
872 SkColorGetR(*color) * aDiv255,
873 SkColorGetG(*color) * aDiv255,
874 SkColorGetB(*color) * aDiv255,
875 a);
837 } 876 }
838 877
839 void GrGLGradientEffect::setData(const GrGLUniformManager& uman, 878 void GrGLGradientEffect::setData(const GrGLUniformManager& uman,
840 const GrDrawEffect& drawEffect) { 879 const GrDrawEffect& drawEffect) {
880
841 const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>(); 881 const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>();
842 const GrTexture* texture = e.texture(0);
843 fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, texture);
844 882
845 SkScalar yCoord = e.getYCoord(); 883
846 if (yCoord != fCachedYCoord) { 884 if (GrGradientEffect::kTwo_ColorType == e.getColorType()){
847 uman.set1f(fFSYUni, yCoord); 885
848 fCachedYCoord = yCoord; 886 fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, NULL);
887 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
888 set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
889 set_mul_color_uni(uman, fColorEndUni, e.getColors(1));
890 } else {
891 set_color_uni(uman, fColorStartUni, e.getColors(0));
892 set_color_uni(uman, fColorEndUni, e.getColors(1));
893 }
894
895 } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
896
897 fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, NULL);
898 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
899 set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
900 set_mul_color_uni(uman, fColorMidUni, e.getColors(1));
901 set_mul_color_uni(uman, fColorEndUni, e.getColors(2));
902 } else {
903 set_color_uni(uman, fColorStartUni, e.getColors(0));
904 set_color_uni(uman, fColorMidUni, e.getColors(1));
905 set_color_uni(uman, fColorEndUni, e.getColors(2));
906 }
907 } else {
908 const GrTexture* texture = e.texture(0);
909 fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, texture);
910
911 SkScalar yCoord = e.getYCoord();
912 if (yCoord != fCachedYCoord) {
913 uman.set1f(fFSYUni, yCoord);
914 fCachedYCoord = yCoord;
915 }
849 } 916 }
850 } 917 }
851 918
852 GrGLEffect::EffectKey GrGLGradientEffect::GenMatrixKey(const GrDrawEffect& drawE ffect) { 919
920 GrGLEffect::EffectKey GrGLGradientEffect::GenBaseGradientKey(const GrDrawEffect& drawEffect) {
853 const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>(); 921 const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>();
854 const GrTexture* texture = e.texture(0); 922 const GrTexture* texture = NULL;
855 return GrGLEffectMatrix::GenKey(e.getMatrix(), drawEffect, kCoordsType, text ure); 923
924 if (GrGradientEffect::kTexture_ColorType == e.getColorType()){
925 texture = e.texture(0);
926 }
927
928 EffectKey key = GrGLEffectMatrix::GenKey(e.getMatrix(), drawEffect, kCoordsT ype, texture);
929
930 if (GrGradientEffect::kTwo_ColorType == e.getColorType()) {
931 key |= kTwoColorKey;
932 } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
933 key |= kThreeColorKey;
934 }
935
936 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
937 key |= kPremulBeforeInterpKey;
938 }
939
940 return key;
856 } 941 }
857 942
858 void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder, 943 void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder,
859 EffectKey key, 944 EffectKey key,
860 SkString* fsCoordName, 945 SkString* fsCoordName,
861 SkString* vsVaryingName, 946 SkString* vsVaryingName,
862 GrSLType* vsVaryingType) { 947 GrSLType* vsVaryingType) {
863 fEffectMatrix.emitCodeMakeFSCoords2D(builder, 948 fEffectMatrix.emitCodeMakeFSCoords2D(builder,
864 key & kMatrixKeyMask, 949 key & kMatrixKeyMask,
865 fsCoordName, 950 fsCoordName,
866 vsVaryingName, 951 vsVaryingName,
867 vsVaryingType); 952 vsVaryingType);
868 } 953 }
869 954
870 void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder, 955 void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
871 const char* gradientTValue, 956 const char* gradientTValue,
872 const char* outputColor, 957 EffectKey key,
873 const char* inputColor, 958 const char* outputColor,
874 const GrGLShaderBuilder::TextureSampler & sampler) { 959 const char* inputColor,
960 const GrGLShaderBuilder::TextureSamplerArray& samplers) {
961 if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)){
962 builder->fsCodeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1. 0));\n",
963 builder->getUniformVariable(fColorStartUni).c_str (),
964 builder->getUniformVariable(fColorEndUni).c_str() ,
965 gradientTValue);
966 // Note that we could skip this step if both colors are known to be opaq ue. Two
967 // considerations:
968 // The gradient SkShader reporting opaque is more restrictive than neces sary in the two pt
969 // case. Make sure the key reflects this optimization (and note that it can use the same
970 // shader as thekBeforeIterp case). This same optimization applies to th e 3 color case below.
971 if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(key)) {
972 builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
973 }
875 974
876 builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n", 975 SkString output;
877 gradientTValue, 976 builder->fsCodeAppendf("\t%s = ", outputColor);
878 builder->getUniformVariable(fFSYUni).c_str()); 977 GrGLSLModulatef<4>(&output, inputColor, "colorTemp");
879 builder->fsCodeAppendf("\t%s = ", outputColor); 978 builder->fsCodeAppend(output.c_str());
880 builder->fsAppendTextureLookupAndModulate(inputColor, sampler, "coord"); 979 builder->fsCodeAppend(";\n");
881 builder->fsCodeAppend(";\n"); 980 } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){
981 builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
982 gradientTValue);
983 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",
984 builder->getUniformVariable(fColorStartUni).c_str (),
985 builder->getUniformVariable(fColorMidUni).c_str() ,
986 builder->getUniformVariable(fColorEndUni).c_str() );
987 if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(key)) {
988 builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
989 }
990
991 SkString output;
992 builder->fsCodeAppendf("\t%s = ", outputColor);
993 GrGLSLModulatef<4>(&output, inputColor, "colorTemp");
994 builder->fsCodeAppend(output.c_str());
995 builder->fsCodeAppend(";\n");
996 } else {
997 builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n",
998 gradientTValue,
999 builder->getUniformVariable(fFSYUni).c_str());
1000 builder->fsCodeAppendf("\t%s = ", outputColor);
1001 builder->fsAppendTextureLookupAndModulate(inputColor,
1002 samplers[0],
1003 "coord");
1004 builder->fsCodeAppend(";\n");
1005 }
882 } 1006 }
883 1007
884 ///////////////////////////////////////////////////////////////////// 1008 /////////////////////////////////////////////////////////////////////
885 1009
886 GrGradientEffect::GrGradientEffect(GrContext* ctx, 1010 GrGradientEffect::GrGradientEffect(GrContext* ctx,
887 const SkGradientShaderBase& shader, 1011 const SkGradientShaderBase& shader,
888 const SkMatrix& matrix, 1012 const SkMatrix& matrix,
889 SkShader::TileMode tileMode) { 1013 SkShader::TileMode tileMode) {
890 // TODO: check for simple cases where we don't need a texture: 1014
891 //GradientInfo info;
892 //shader.asAGradient(&info);
893 //if (info.fColorCount == 2) { ...
894 1015
895 fMatrix = matrix; 1016 fMatrix = matrix;
896
897 SkBitmap bitmap;
898 shader.getGradientTableBitmap(&bitmap);
899
900 fIsOpaque = shader.isOpaque(); 1017 fIsOpaque = shader.isOpaque();
901 1018
902 GrTextureStripAtlas::Desc desc; 1019 SkShader::GradientInfo info;
903 desc.fWidth = bitmap.width(); 1020 SkScalar pos[3] = {0};
904 desc.fHeight = 32;
905 desc.fRowHeight = bitmap.height();
906 desc.fContext = ctx;
907 desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config());
908 fAtlas = GrTextureStripAtlas::GetAtlas(desc);
909 SkASSERT(NULL != fAtlas);
910 1021
911 // We always filter the gradient table. Each table is one row of a texture, so always y-clamp. 1022 info.fColorCount = 3;
912 GrTextureParams params; 1023 info.fColors = &fColors[0];
913 params.setFilterMode(GrTextureParams::kBilerp_FilterMode); 1024 info.fColorOffsets = &pos[0];
914 params.setTileModeX(tileMode); 1025 shader.asAGradient(&info);
915 1026
916 fRow = fAtlas->lockRow(bitmap); 1027 // The two and three color specializations do not currently support tiling.
917 if (-1 != fRow) { 1028 bool foundSpecialCase = false;
918 fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf * 1029 if (SkShader::kClamp_TileMode == info.fTileMode) {
919 fAtlas->getVerticalScaleFactor(); 1030 if (2 == info.fColorCount) {
920 fTextureAccess.reset(fAtlas->getTexture(), params); 1031 fRow = -1; // flag for no atlas
1032 fColorType = kTwo_ColorType;
1033 foundSpecialCase = true;
1034 } else if (3 == info.fColorCount &&
1035 (SkScalarAbs(pos[1] - SK_ScalarHalf) < SK_Scalar1 / 1000)) { // 3 color symmetric
1036 fRow = -1; // flag for no atlas
1037 fColorType = kThree_ColorType;
1038 foundSpecialCase = true;
1039 }
1040 }
1041 if (foundSpecialCase) {
1042 if (SkGradientShader::kInterpolateColorsInPremul_Flag & info.fGradientFl ags) {
1043 fPremulType = kBeforeInterp_PremulType;
1044 } else {
1045 fPremulType = kAfterInterp_PremulType;
1046 }
921 } else { 1047 } else {
922 GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, &param s); 1048 // doesn't matter how this is set, just be consistent because it is part of the effect key.
923 fTextureAccess.reset(texture, params); 1049 fPremulType = kBeforeInterp_PremulType;
924 fYCoord = SK_ScalarHalf; 1050 SkBitmap bitmap;
1051 shader.getGradientTableBitmap(&bitmap);
1052 fColorType = kTexture_ColorType;
1053
1054 GrTextureStripAtlas::Desc desc;
1055 desc.fWidth = bitmap.width();
1056 desc.fHeight = 32;
1057 desc.fRowHeight = bitmap.height();
1058 desc.fContext = ctx;
1059 desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config());
1060 fAtlas = GrTextureStripAtlas::GetAtlas(desc);
1061 SkASSERT(NULL != fAtlas);
925 1062
926 // Unlock immediately, this is not great, but we don't have a way of 1063 // We always filter the gradient table. Each table is one row of a textu re, always y-clamp.
927 // knowing when else to unlock it currently, so it may get purged from 1064 GrTextureParams params;
928 // the cache, but it'll still be ref'd until it's no longer being used. 1065 params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
929 GrUnlockAndUnrefCachedBitmapTexture(texture); 1066 params.setTileModeX(tileMode);
1067
1068 fRow = fAtlas->lockRow(bitmap);
1069 if (-1 != fRow) {
1070 fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf *
1071 fAtlas->getVerticalScaleFactor();
1072 fTextureAccess.reset(fAtlas->getTexture(), params);
1073 } else {
1074 GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, &p arams);
1075 fTextureAccess.reset(texture, params);
1076 fYCoord = SK_ScalarHalf;
1077
1078 // Unlock immediately, this is not great, but we don't have a way of
1079 // knowing when else to unlock it currently, so it may get purged fr om
1080 // the cache, but it'll still be ref'd until it's no longer being us ed.
1081 GrUnlockAndUnrefCachedBitmapTexture(texture);
1082 }
1083 this->addTextureAccess(&fTextureAccess);
930 } 1084 }
931 this->addTextureAccess(&fTextureAccess);
932 } 1085 }
933 1086
934 GrGradientEffect::~GrGradientEffect() { 1087 GrGradientEffect::~GrGradientEffect() {
935 if (this->useAtlas()) { 1088 if (this->useAtlas()) {
936 fAtlas->unlockRow(fRow); 1089 fAtlas->unlockRow(fRow);
937 } 1090 }
938 } 1091 }
939 1092
940 bool GrGradientEffect::onIsEqual(const GrEffect& effect) const { 1093 bool GrGradientEffect::onIsEqual(const GrEffect& effect) const {
941 const GrGradientEffect& s = CastEffect<GrGradientEffect>(effect); 1094 const GrGradientEffect& s = CastEffect<GrGradientEffect>(effect);
942 return fTextureAccess.getTexture() == s.fTextureAccess.getTexture() && 1095
943 fTextureAccess.getParams().getTileModeX() == 1096 if (this->fColorType == s.getColorType()){
1097
1098 if (kTwo_ColorType == fColorType) {
1099 if (*this->getColors(0) != *s.getColors(0) ||
1100 *this->getColors(1) != *s.getColors(1)) {
1101 return false;
1102 }
1103 } else if (kThree_ColorType == fColorType) {
1104 if (*this->getColors(0) != *s.getColors(0) ||
1105 *this->getColors(1) != *s.getColors(1) ||
1106 *this->getColors(2) != *s.getColors(2)) {
1107 return false;
1108 }
1109 }
1110
1111 return fTextureAccess.getTexture() == s.fTextureAccess.getTexture() &&
1112 fTextureAccess.getParams().getTileModeX() ==
944 s.fTextureAccess.getParams().getTileModeX() && 1113 s.fTextureAccess.getParams().getTileModeX() &&
945 this->useAtlas() == s.useAtlas() && 1114 this->useAtlas() == s.useAtlas() &&
946 fYCoord == s.getYCoord() && 1115 fYCoord == s.getYCoord() &&
947 fMatrix.cheapEqualTo(s.getMatrix()); 1116 fMatrix.cheapEqualTo(s.getMatrix());
1117 }
1118
1119 return false;
948 } 1120 }
949 1121
950 void GrGradientEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const { 1122 void GrGradientEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const {
951 if (fIsOpaque && (kA_GrColorComponentFlag & *validFlags) && 0xff == GrColorU npackA(*color)) { 1123 if (fIsOpaque && (kA_GrColorComponentFlag & *validFlags) && 0xff == GrColorU npackA(*color)) {
952 *validFlags = kA_GrColorComponentFlag; 1124 *validFlags = kA_GrColorComponentFlag;
953 } else { 1125 } else {
954 *validFlags = 0; 1126 *validFlags = 0;
955 } 1127 }
956 } 1128 }
957 1129
(...skipping 15 matching lines...) Expand all
973 (*stops)[i] = stop; 1145 (*stops)[i] = stop;
974 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; 1146 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f;
975 } 1147 }
976 } 1148 }
977 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); 1149 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount));
978 1150
979 return outColors; 1151 return outColors;
980 } 1152 }
981 1153
982 #endif 1154 #endif
OLDNEW
« no previous file with comments | « src/core/SkShader.cpp ('k') | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698