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

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

Issue 2223203003: Exact Ganesh Gradients for Special Cases (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Move hard stop code into proper #if block Created 4 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
« no previous file with comments | « no previous file | 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 "Sk4fLinearGradient.h" 8 #include "Sk4fLinearGradient.h"
9 #include "SkGradientShaderPriv.h" 9 #include "SkGradientShaderPriv.h"
10 #include "SkLinearGradient.h" 10 #include "SkLinearGradient.h"
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 desc.fPos = fOrigPos; 221 desc.fPos = fOrigPos;
222 desc.fCount = fColorCount; 222 desc.fCount = fColorCount;
223 desc.fTileMode = fTileMode; 223 desc.fTileMode = fTileMode;
224 desc.fGradFlags = fGradFlags; 224 desc.fGradFlags = fGradFlags;
225 225
226 const SkMatrix& m = this->getLocalMatrix(); 226 const SkMatrix& m = this->getLocalMatrix();
227 desc.fLocalMatrix = m.isIdentity() ? nullptr : &m; 227 desc.fLocalMatrix = m.isIdentity() ? nullptr : &m;
228 desc.flatten(buffer); 228 desc.flatten(buffer);
229 } 229 }
230 230
231 SkGradientShaderBase::GpuColorType SkGradientShaderBase::getGpuColorType(SkColor colors[3]) const { 231 static inline bool close_to_one_half(const SkFixed& val) {
bsalomon 2016/08/09 19:46:23 I think we have something like SkScalarNearlyEqual
232 if (fColorCount <= 3) { 232 return SkScalarAbs(SkFixedToScalar(val) - SK_ScalarHalf) < SK_Scalar1 / 1000 ;
233 memcpy(colors, fOrigColors, fColorCount * sizeof(SkColor)); 233 }
234
235 GrGradientEffect::ColorType GrGradientEffect::determineColorTypeAndNumHardStops(
236 const SkGradientShaderBase& shader) {
237 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
238 if (shader.fOrigPos) {
239 if (4 == shader.fColorCount) {
240 if (SkScalarNearlyEqual(shader.fOrigPos[0], 0.0f) &&
241 SkScalarNearlyEqual(shader.fOrigPos[1], 0.5f) &&
242 SkScalarNearlyEqual(shader.fOrigPos[2], 0.5f) &&
243 SkScalarNearlyEqual(shader.fOrigPos[3], 1.0f)) {
244
245 return kHardStopCentered_ColorType;
246 }
247 } else if (3 == shader.fColorCount) {
248 if (SkScalarNearlyEqual(shader.fOrigPos[0], 0.0f) &&
249 SkScalarNearlyEqual(shader.fOrigPos[1], 0.0f) &&
250 SkScalarNearlyEqual(shader.fOrigPos[2], 1.0f)) {
251
252 return kHardStopLeftEdged_ColorType;
253 } else if (SkScalarNearlyEqual(shader.fOrigPos[0], 0.0f) &&
254 SkScalarNearlyEqual(shader.fOrigPos[1], 1.0f) &&
255 SkScalarNearlyEqual(shader.fOrigPos[2], 1.0f)) {
256
257 return kHardStopRightEdged_ColorType;
258 }
259 }
260 }
261 #endif
262
263 if (SkShader::kClamp_TileMode == shader.getTileMode()) {
264 if (2 == shader.fColorCount) {
265 return kTwo_ColorType;
266 } else if (3 == shader.fColorCount &&
267 close_to_one_half(shader.getRecs()[1].fPos)) {
268 return kThree_ColorType;
269 }
234 } 270 }
235 271
236 if (SkShader::kClamp_TileMode == fTileMode) { 272 return kTexture_ColorType;
237 if (2 == fColorCount) {
238 return kTwo_GpuColorType;
239 } else if (3 == fColorCount &&
240 (SkScalarAbs(
241 SkFixedToScalar(fRecs[1].fPos) - SK_ScalarHalf) < SK_Scalar1 / 1000)) {
242 return kThree_GpuColorType;
243 }
244 }
245 return kTexture_GpuColorType;
246 } 273 }
247 274
248 void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst, 275 void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
249 SkColor* colorSrc, Rec* recSrc, 276 SkColor* colorSrc, Rec* recSrc,
250 int count) { 277 int count) {
251 SkAutoSTArray<8, SkColor> colorsTemp(count); 278 SkAutoSTArray<8, SkColor> colorsTemp(count);
252 for (int i = 0; i < count; ++i) { 279 for (int i = 0; i < count; ++i) {
253 int offset = count - i - 1; 280 int offset = count - i - 1;
254 colorsTemp[i] = colorSrc[offset]; 281 colorsTemp[i] = colorSrc[offset];
255 } 282 }
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 931
905 #include "effects/GrTextureStripAtlas.h" 932 #include "effects/GrTextureStripAtlas.h"
906 #include "GrContext.h" 933 #include "GrContext.h"
907 #include "GrInvariantOutput.h" 934 #include "GrInvariantOutput.h"
908 #include "gl/GrGLContext.h" 935 #include "gl/GrGLContext.h"
909 #include "glsl/GrGLSLFragmentShaderBuilder.h" 936 #include "glsl/GrGLSLFragmentShaderBuilder.h"
910 #include "glsl/GrGLSLProgramDataManager.h" 937 #include "glsl/GrGLSLProgramDataManager.h"
911 #include "glsl/GrGLSLUniformHandler.h" 938 #include "glsl/GrGLSLUniformHandler.h"
912 #include "SkGr.h" 939 #include "SkGr.h"
913 940
914 GrGradientEffect::GLSLProcessor::GLSLProcessor()
915 : fCachedYCoord(SK_ScalarMax) {
916 }
917
918 void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniform Handler, 941 void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniform Handler,
919 const GrGradientEffect& ge) { 942 const GrGradientEffect& ge) {
920 943
921 if (SkGradientShaderBase::kTwo_GpuColorType == ge.getColorType()) { // 2 Col or case 944 switch (ge.getColorType()) {
922 fColorStartUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 945 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
923 kVec4f_GrSLType, kDefault_Gr SLPrecision, 946 case GrGradientEffect::kHardStopCentered_ColorType:
bsalomon 2016/08/09 19:46:23 Any reason to now always use a uniform array for c
924 "GradientStartColor"); 947 case GrGradientEffect::kHardStopLeftEdged_ColorType:
925 fColorEndUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 948 case GrGradientEffect::kHardStopRightEdged_ColorType:
926 kVec4f_GrSLType, kDefault_GrSL Precision, 949 fColorsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
927 "GradientEndColor"); 950 kVec4f_GrSLType,
951 kDefault_GrSLPrecision,
952 "Colors",
953 kHardStopCentered_Color Type == ge.getColorType() ? 4 : 3);
928 954
929 } else if (SkGradientShaderBase::kThree_GpuColorType == ge.getColorType()) { // 3 Color Case 955 break;
930 fColorStartUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 956 #endif
931 kVec4f_GrSLType, kDefault_G rSLPrecision, 957 case GrGradientEffect::kTwo_ColorType:
932 "GradientStartColor"); 958 fColorStartUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
933 fColorMidUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 959 kVec4f_GrSLType,
934 kVec4f_GrSLType, kDefault_GrSL Precision, 960 kDefault_GrSLPrecision,
935 "GradientMidColor"); 961 "GradientStartColor");
936 fColorEndUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 962 fColorEndUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
937 kVec4f_GrSLType, kDefault_GrSL Precision, 963 kVec4f_GrSLType,
938 "GradientEndColor"); 964 kDefault_GrSLPrecision,
965 "GradientEndColor");
939 966
940 } else { // if not a fast case 967 break;
941 fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 968
942 kFloat_GrSLType, kDefault_GrSLPreci sion, 969 case GrGradientEffect::kThree_ColorType:
943 "GradientYCoordFS"); 970 fColorStartUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
971 kVec4f_GrSLType,
972 kDefault_GrSLPrecision,
973 "GradientStartColor");
974 fColorMidUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
975 kVec4f_GrSLType,
976 kDefault_GrSLPrecision,
977 "GradientMidColor");
978 fColorEndUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
979 kVec4f_GrSLType,
980 kDefault_GrSLPrecision,
981 "GradientEndColor");
982
983 break;
984
985 case GrGradientEffect::kTexture_ColorType:
986 fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
987 kFloat_GrSLType, kDefault_GrSLP recision,
988 "GradientYCoordFS");
989
990 break;
944 } 991 }
945 } 992 }
946 993
947 static inline void set_color_uni(const GrGLSLProgramDataManager& pdman, 994 static inline void set_after_interp_color_uni(const GrGLSLProgramDataManager& pd man,
948 const GrGLSLProgramDataManager::UniformHandle u ni, 995 const GrGLSLProgramDataManager::UniformHandle u ni,
949 const SkColor* color) { 996 const SkColor* color) {
950 pdman.set4f(uni, 997 pdman.set4f(uni,
951 SkColorGetR(*color) / 255.f, 998 SkColorGetR(*color) / 255.f,
952 SkColorGetG(*color) / 255.f, 999 SkColorGetG(*color) / 255.f,
953 SkColorGetB(*color) / 255.f, 1000 SkColorGetB(*color) / 255.f,
954 SkColorGetA(*color) / 255.f); 1001 SkColorGetA(*color) / 255.f);
955 } 1002 }
956 1003
957 static inline void set_mul_color_uni(const GrGLSLProgramDataManager& pdman, 1004 static inline void set_before_interp_color_uni(const GrGLSLProgramDataManager& p dman,
958 const GrGLSLProgramDataManager::UniformHand le uni, 1005 const GrGLSLProgramDataManager::UniformH andle uni,
959 const SkColor* color){ 1006 const SkColor* color){
960 float a = SkColorGetA(*color) / 255.f; 1007 float a = SkColorGetA(*color) / 255.f;
961 float aDiv255 = a / 255.f; 1008 float aDiv255 = a / 255.f;
962 pdman.set4f(uni, 1009 pdman.set4f(uni,
963 SkColorGetR(*color) * aDiv255, 1010 SkColorGetR(*color) * aDiv255,
964 SkColorGetG(*color) * aDiv255, 1011 SkColorGetG(*color) * aDiv255,
965 SkColorGetB(*color) * aDiv255, 1012 SkColorGetB(*color) * aDiv255,
966 a); 1013 a);
967 } 1014 }
968 1015
1016 static inline void set_after_interp_color_uni_array(const GrGLSLProgramDataManag er& pdman,
1017 const GrGLSLProgramDataManager::UniformHa ndle uni,
1018 const SkTDArray<SkColor>& colors) {
1019 int count = colors.count();
1020 constexpr int kSmallCount = 10;
1021
1022 SkAutoSTArray<4*kSmallCount, float> vals(4*count);
1023
1024 for (int i = 0; i < colors.count(); i++) {
1025 // RGBA
1026 vals[4*i + 0] = SkColorGetR(colors[i]) / 255.f;
1027 vals[4*i + 1] = SkColorGetG(colors[i]) / 255.f;
1028 vals[4*i + 2] = SkColorGetB(colors[i]) / 255.f;
1029 vals[4*i + 3] = SkColorGetA(colors[i]) / 255.f;
1030 }
1031
1032 pdman.set4fv(uni, colors.count(), vals.get());
1033 }
1034
1035 static inline void set_before_interp_color_uni_array(const GrGLSLProgramDataMana ger& pdman,
1036 const GrGLSLProgramDataManager::Un iformHandle uni,
1037 const SkTDArray<SkColor>& colors) {
1038 int count = colors.count();
1039 constexpr int kSmallCount = 10;
1040
1041 SkAutoSTArray<4*kSmallCount, float> vals(4*count);
1042
1043 for (int i = 0; i < count; i++) {
1044 float a = SkColorGetA(colors[i]) / 255.f;
1045 float aDiv255 = a / 255.f;
1046
1047 // RGBA
1048 vals[4*i + 0] = SkColorGetR(colors[i]) * aDiv255;
1049 vals[4*i + 1] = SkColorGetG(colors[i]) * aDiv255;
1050 vals[4*i + 2] = SkColorGetB(colors[i]) * aDiv255;
1051 vals[4*i + 3] = a;
1052 }
1053
1054 pdman.set4fv(uni, count, vals.get());
1055 }
1056
969 void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman, 1057 void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman,
970 const GrProcessor& processor) { 1058 const GrProcessor& processor) {
971
972 const GrGradientEffect& e = processor.cast<GrGradientEffect>(); 1059 const GrGradientEffect& e = processor.cast<GrGradientEffect>();
973 1060
1061 switch (e.getColorType()) {
1062 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
1063 case GrGradientEffect::kHardStopCentered_ColorType:
1064 case GrGradientEffect::kHardStopLeftEdged_ColorType:
1065 case GrGradientEffect::kHardStopRightEdged_ColorType: {
1066 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
1067 set_before_interp_color_uni_array(pdman, fColorsUni, e.fAllColor s);
1068 } else {
1069 set_after_interp_color_uni_array(pdman, fColorsUni, e.fAllColors );
1070 }
974 1071
975 if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()){ 1072 break;
976 1073 }
977 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { 1074 #endif
978 set_mul_color_uni(pdman, fColorStartUni, e.getColors(0)); 1075 case GrGradientEffect::kTwo_ColorType: {
979 set_mul_color_uni(pdman, fColorEndUni, e.getColors(1)); 1076 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
980 } else { 1077 set_before_interp_color_uni(pdman, fColorStartUni, e.getColors(0 ));
981 set_color_uni(pdman, fColorStartUni, e.getColors(0)); 1078 set_before_interp_color_uni(pdman, fColorEndUni, e.getColors(1)) ;
982 set_color_uni(pdman, fColorEndUni, e.getColors(1)); 1079 } else {
1080 set_after_interp_color_uni(pdman, fColorStartUni, e.getColors(0) );
1081 set_after_interp_color_uni(pdman, fColorEndUni, e.getColors(1));
1082 }
1083 break;
983 } 1084 }
984 1085
985 } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){ 1086 case GrGradientEffect::kThree_ColorType: {
1087 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
1088 set_before_interp_color_uni(pdman, fColorStartUni, e.getColors(0 ));
1089 set_before_interp_color_uni(pdman, fColorMidUni, e.getColors(1)) ;
1090 set_before_interp_color_uni(pdman, fColorEndUni, e.getColors(2)) ;
1091 } else {
1092 set_after_interp_color_uni(pdman, fColorStartUni, e.getColors(0) );
1093 set_after_interp_color_uni(pdman, fColorMidUni, e.getColors(1));
1094 set_after_interp_color_uni(pdman, fColorEndUni, e.getColors(2));
1095 }
1096 break;
1097 }
986 1098
987 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { 1099 case GrGradientEffect::kTexture_ColorType: {
988 set_mul_color_uni(pdman, fColorStartUni, e.getColors(0)); 1100 SkScalar yCoord = e.getYCoord();
989 set_mul_color_uni(pdman, fColorMidUni, e.getColors(1)); 1101 if (yCoord != fCachedYCoord) {
990 set_mul_color_uni(pdman, fColorEndUni, e.getColors(2)); 1102 pdman.set1f(fFSYUni, yCoord);
991 } else { 1103 fCachedYCoord = yCoord;
992 set_color_uni(pdman, fColorStartUni, e.getColors(0)); 1104 }
993 set_color_uni(pdman, fColorMidUni, e.getColors(1)); 1105 break;
994 set_color_uni(pdman, fColorEndUni, e.getColors(2));
995 }
996 } else {
997
998 SkScalar yCoord = e.getYCoord();
999 if (yCoord != fCachedYCoord) {
1000 pdman.set1f(fFSYUni, yCoord);
1001 fCachedYCoord = yCoord;
1002 } 1106 }
1003 } 1107 }
1004 } 1108 }
1005 1109
1006
1007 uint32_t GrGradientEffect::GLSLProcessor::GenBaseGradientKey(const GrProcessor& processor) { 1110 uint32_t GrGradientEffect::GLSLProcessor::GenBaseGradientKey(const GrProcessor& processor) {
1008 const GrGradientEffect& e = processor.cast<GrGradientEffect>(); 1111 const GrGradientEffect& e = processor.cast<GrGradientEffect>();
1009 1112
1010 uint32_t key = 0; 1113 uint32_t key = 0;
1011 1114
1012 if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()) {
1013 key |= kTwoColorKey;
1014 } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()) {
1015 key |= kThreeColorKey;
1016 }
1017
1018 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { 1115 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
1019 key |= kPremulBeforeInterpKey; 1116 key |= kPremulBeforeInterpKey;
1020 } 1117 }
1021 1118
1119 if (GrGradientEffect::kTwo_ColorType == e.getColorType()) {
1120 key |= kTwoColorKey;
1121 } else if (GrGradientEffect::kThree_ColorType == e.getColorType()) {
1122 key |= kThreeColorKey;
1123 }
1124 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
1125 else if (GrGradientEffect::kHardStopCentered_ColorType == e.getColorType()) {
1126 key |= kHardStopCenteredKey;
1127 } else if (GrGradientEffect::kHardStopLeftEdged_ColorType == e.getColorType( )) {
1128 key |= kHardStopZeroZeroOneKey;
1129 } else if (GrGradientEffect::kHardStopRightEdged_ColorType == e.getColorType ()) {
1130 key |= kHardStopZeroOneOneKey;
1131 }
1132
1133 if (SkShader::TileMode::kClamp_TileMode == e.fTileMode) {
1134 key |= kClampTileMode;
1135 } else if (SkShader::TileMode::kRepeat_TileMode == e.fTileMode) {
1136 key |= kRepeatTileMode;
1137 } else {
1138 key |= kMirrorTileMode;
1139 }
1140 #endif
1141
1022 return key; 1142 return key;
1023 } 1143 }
1024 1144
1025 void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBui lder, 1145 void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBui lder,
1026 GrGLSLUniformHandler* uniformHan dler, 1146 GrGLSLUniformHandler* uniformHan dler,
1027 const GrGLSLCaps* glslCaps, 1147 const GrGLSLCaps* glslCaps,
1028 const GrGradientEffect& ge, 1148 const GrGradientEffect& ge,
1029 const char* gradientTValue, 1149 const char* gradientTValue,
1030 const char* outputColor, 1150 const char* outputColor,
1031 const char* inputColor, 1151 const char* inputColor,
1032 const SamplerHandle* texSamplers ) { 1152 const SamplerHandle* texSamplers ) {
1033 if (SkGradientShaderBase::kTwo_GpuColorType == ge.getColorType()){ 1153 switch (ge.getColorType()) {
1034 fragBuilder->codeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n", 1154 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
1035 uniformHandler->getUniformVariable(fColorStartU ni).c_str(), 1155 case kHardStopCentered_ColorType: {
1036 uniformHandler->getUniformVariable(fColorEndUni ).c_str(), 1156 const char* t = gradientTValue;
1037 gradientTValue); 1157 const char* colors = uniformHandler->getUniformCStr(fColorsUni);
1038 // Note that we could skip this step if both colors are known to be opaq ue. Two 1158
1039 // considerations: 1159 fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
1040 // The gradient SkShader reporting opaque is more restrictive than neces sary in the two pt 1160
1041 // case. Make sure the key reflects this optimization (and note that it can use the same 1161 // Account for tile mode
1042 // shader as thekBeforeIterp case). This same optimization applies to th e 3 color case 1162 if (SkShader::kRepeat_TileMode == ge.fTileMode) {
1043 // below. 1163 fragBuilder->codeAppendf("clamp_t = fract(%s);", t);
1044 if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) { 1164 } else if (SkShader::kMirror_TileMode == ge.fTileMode) {
1045 fragBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n"); 1165 fragBuilder->codeAppendf("if (%s < 0.0 || %s > 1.0) {", t, t);
1166 fragBuilder->codeAppendf(" if (mod(floor(%s), 2.0) == 0.0) {" , t);
1167 fragBuilder->codeAppendf(" clamp_t = fract(%s);", t);
1168 fragBuilder->codeAppendf(" } else {");
1169 fragBuilder->codeAppendf(" clamp_t = 1.0 - fract(%s);", t );
1170 fragBuilder->codeAppendf(" }");
1171 fragBuilder->codeAppendf("}");
1172 }
1173
1174 // Calculate color
1175 fragBuilder->codeAppendf("float relative_t = fract(2.0 * clamp_t);") ;
1176 if (SkShader::kClamp_TileMode == ge.fTileMode) {
1177 fragBuilder->codeAppendf("relative_t += step(1.0, %s);", t);
1178 }
1179 fragBuilder->codeAppendf("vec4 colorTemp = mix(%s[0], %s[1], relativ e_t);", colors, colors);
1180 fragBuilder->codeAppendf("if (clamp_t >= 0.5) {");
1181 fragBuilder->codeAppendf(" colorTemp = mix(%s[2], %s[3], relative _t);", colors, colors);
1182 fragBuilder->codeAppendf("}");
1183
1184 if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
1185 fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
1186 }
1187 fragBuilder->codeAppendf("%s = %s;", outputColor, (GrGLSLExpr4(input Color) * GrGLSLExpr4("colorTemp")).c_str());
1188
1189 break;
1046 } 1190 }
1047 1191
1048 fragBuilder->codeAppendf("\t%s = %s;\n", outputColor, 1192 case kHardStopLeftEdged_ColorType: {
1049 (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTe mp")).c_str()); 1193 const char* t = gradientTValue;
1050 } else if (SkGradientShaderBase::kThree_GpuColorType == ge.getColorType()) { 1194 const char* colors = uniformHandler->getUniformCStr(fColorsUni);
1051 fragBuilder->codeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n", 1195
1052 gradientTValue); 1196 fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
1053 fragBuilder->codeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n", 1197
1054 uniformHandler->getUniformVariable(fColorStartU ni).c_str()); 1198 // Account for tile mode
1055 if (!glslCaps->canUseMinAndAbsTogether()) { 1199 if (SkShader::kRepeat_TileMode == ge.fTileMode) {
1056 // The Tegra3 compiler will sometimes never return if we have 1200 fragBuilder->codeAppendf("clamp_t = fract(%s);", t);
1057 // min(abs(oneMinus2t), 1.0), or do the abs first in a separate expr ession. 1201 } else if (SkShader::kMirror_TileMode == ge.fTileMode) {
1058 fragBuilder->codeAppend("\tfloat minAbs = abs(oneMinus2t);\n"); 1202 fragBuilder->codeAppendf("if (%s < 0.0 || %s > 1.0) {", t, t);
1059 fragBuilder->codeAppend("\tminAbs = minAbs > 1.0 ? 1.0 : minAbs;\n") ; 1203 fragBuilder->codeAppendf(" if (mod(floor(%s), 2.0) == 0.0) {" , t);
1060 fragBuilder->codeAppendf("\tcolorTemp += (1.0 - minAbs) * %s;\n", 1204 fragBuilder->codeAppendf(" clamp_t = fract(%s);", t);
1061 uniformHandler->getUniformVariable(fColorMi dUni).c_str()); 1205 fragBuilder->codeAppendf(" } else {");
1062 } else { 1206 fragBuilder->codeAppendf(" clamp_t = 1.0 - fract(%s);", t );
1063 fragBuilder->codeAppendf("\tcolorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s;\n", 1207 fragBuilder->codeAppendf(" }");
1064 uniformHandler->getUniformVariable(fColorMi dUni).c_str()); 1208 fragBuilder->codeAppendf("}");
1065 } 1209 }
1066 fragBuilder->codeAppendf("\tcolorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;\n", 1210
1067 uniformHandler->getUniformVariable(fColorEndUni ).c_str()); 1211 fragBuilder->codeAppendf("vec4 colorTemp = mix(%s[1], %s[2], clamp_t );", colors, colors);
1068 if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) { 1212 if (SkShader::kClamp_TileMode == ge.fTileMode) {
1069 fragBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n"); 1213 fragBuilder->codeAppendf("if (%s < 0.0) {", t);
1214 fragBuilder->codeAppendf(" colorTemp = %s[0];", colors);
1215 fragBuilder->codeAppendf("}");
1216 }
1217
1218 if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
1219 fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
1220 }
1221 fragBuilder->codeAppendf("%s = %s;", outputColor, (GrGLSLExpr4(input Color) * GrGLSLExpr4("colorTemp")).c_str());
1222
1223 break;
1070 } 1224 }
1071 1225
1072 fragBuilder->codeAppendf("\t%s = %s;\n", outputColor, 1226 case kHardStopRightEdged_ColorType: {
1073 (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTe mp")).c_str()); 1227 const char* t = gradientTValue;
1074 } else { 1228 const char* colors = uniformHandler->getUniformCStr(fColorsUni);
1075 fragBuilder->codeAppendf("\tvec2 coord = vec2(%s, %s);\n", 1229
1076 gradientTValue, 1230 fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
1077 uniformHandler->getUniformVariable(fFSYUni).c_s tr()); 1231
1078 fragBuilder->codeAppendf("\t%s = ", outputColor); 1232 // Account for tile mode
1079 fragBuilder->appendTextureLookupAndModulate(inputColor, 1233 if (SkShader::kRepeat_TileMode == ge.fTileMode) {
1080 texSamplers[0], 1234 fragBuilder->codeAppendf("clamp_t = fract(%s);", t);
1081 "coord"); 1235 } else if (SkShader::kMirror_TileMode == ge.fTileMode) {
1082 fragBuilder->codeAppend(";\n"); 1236 fragBuilder->codeAppendf("if (%s < 0.0 || %s > 1.0) {", t, t);
1237 fragBuilder->codeAppendf(" if (mod(floor(%s), 2.0) == 0.0) {" , t);
1238 fragBuilder->codeAppendf(" clamp_t = fract(%s);", t);
1239 fragBuilder->codeAppendf(" } else {");
1240 fragBuilder->codeAppendf(" clamp_t = 1.0 - fract(%s);", t );
1241 fragBuilder->codeAppendf(" }");
1242 fragBuilder->codeAppendf("}");
1243 }
1244
1245 fragBuilder->codeAppendf("vec4 colorTemp = mix(%s[0], %s[1], clamp_t );", colors, colors);
1246 if (SkShader::kClamp_TileMode == ge.fTileMode) {
1247 fragBuilder->codeAppendf("if (%s > 1.0) {", t);
1248 fragBuilder->codeAppendf(" colorTemp = %s[2];", colors);
1249 fragBuilder->codeAppendf("}");
1250 }
1251
1252 if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
1253 fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
1254 }
1255 fragBuilder->codeAppendf("%s = %s;", outputColor, (GrGLSLExpr4(input Color) * GrGLSLExpr4("colorTemp")).c_str());
1256
1257 break;
1258 }
1259 #endif
1260
1261 case kTwo_ColorType: {
1262 const char* t = gradientTValue;
1263 const char* start = uniformHandler->getUniformCStr(fColorStartUni);
1264 const char* end = uniformHandler->getUniformCStr(fColorEndUni);
1265
1266 fragBuilder->codeAppendf("vec4 colorTemp = mix(%s, %s, clamp(%s, 0.0 , 1.0));", start, end, t);
1267
1268 // We could skip this step if both colors are known to be opaque. Tw o
1269 // considerations:
1270 // The gradient SkShader reporting opaque is more restrictive than n ecessary in the two pt
1271 // case. Make sure the key reflects this optimization (and note that it can use the same
1272 // shader as thekBeforeIterp case). This same optimization applies t o the 3 color case
1273 // below.
1274 if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
1275 fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
1276 }
1277
1278 fragBuilder->codeAppendf("%s = %s;", outputColor, (GrGLSLExpr4(input Color) * GrGLSLExpr4("colorTemp")).c_str());
1279
1280 break;
1281 }
1282
1283 case kThree_ColorType: {
1284 const char* t = gradientTValue;
1285 const char* start = uniformHandler->getUniformCStr(fColorStartUni);
1286 const char* mid = uniformHandler->getUniformCStr(fColorMidUni);
1287 const char* end = uniformHandler->getUniformCStr(fColorEndUni);
1288
1289 fragBuilder->codeAppendf("float oneMinus2t = 1.0 - (2.0 * %s);", t);
1290 fragBuilder->codeAppendf("vec4 colorTemp = clamp(oneMinus2t, 0.0, 1. 0) * %s;", start);
1291 if (!glslCaps->canUseMinAndAbsTogether()) {
1292 // The Tegra3 compiler will sometimes never return if we have
1293 // min(abs(oneMinus2t), 1.0), or do the abs first in a separate expression.
1294 fragBuilder->codeAppendf("float minAbs = abs(oneMinus2t);");
1295 fragBuilder->codeAppendf("minAbs = minAbs > 1.0 ? 1.0 : minAbs;" );
1296 fragBuilder->codeAppendf("colorTemp += (1.0 - minAbs) * %s;", mi d);
1297 } else {
1298 fragBuilder->codeAppendf("colorTemp += (1.0 - min(abs(oneMinus2t ), 1.0)) * %s;", mid);
1299 }
1300 fragBuilder->codeAppendf("colorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;", end);
1301
1302 if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
1303 fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
1304 }
1305
1306 fragBuilder->codeAppendf("%s = %s;", outputColor, (GrGLSLExpr4(input Color) * GrGLSLExpr4("colorTemp")).c_str());
1307
1308 break;
1309 }
1310
1311 case kTexture_ColorType: {
1312 const char* fsyuni = uniformHandler->getUniformCStr(fFSYUni);
1313
1314 fragBuilder->codeAppendf("vec2 coord = vec2(%s, %s);", gradientTValu e, fsyuni);
1315 fragBuilder->codeAppendf("%s = ", outputColor);
1316 fragBuilder->appendTextureLookupAndModulate(inputColor, texSamplers[ 0], "coord");
1317 fragBuilder->codeAppend(";");
1318
1319 break;
1320 }
1083 } 1321 }
1084 } 1322 }
1085 1323
1086 ///////////////////////////////////////////////////////////////////// 1324 /////////////////////////////////////////////////////////////////////
1087 1325
1088 GrGradientEffect::GrGradientEffect(GrContext* ctx, 1326 GrGradientEffect::GrGradientEffect(GrContext* ctx,
1089 const SkGradientShaderBase& shader, 1327 const SkGradientShaderBase& shader,
1090 const SkMatrix& matrix, 1328 const SkMatrix& matrix,
1091 SkShader::TileMode tileMode) { 1329 SkShader::TileMode tileMode) {
1092 1330
1093 fIsOpaque = shader.isOpaque(); 1331 fIsOpaque = shader.isOpaque();
1094 1332
1095 fColorType = shader.getGpuColorType(&fColors[0]); 1333 fColorType = this->determineColorTypeAndNumHardStops(shader);
1096 1334
1097 // The two and three color specializations do not currently support tiling. 1335 if (kTexture_ColorType != fColorType) {
1098 if (SkGradientShaderBase::kTwo_GpuColorType == fColorType || 1336 if (shader.fOrigColors) {
1099 SkGradientShaderBase::kThree_GpuColorType == fColorType) { 1337 fAllColors.setReserve(shader.fColorCount);
bsalomon 2016/08/09 19:46:23 Maybe just call this fColors?
1100 fRow = -1; 1338 fAllColors = SkTDArray<SkColor>(shader.fOrigColors, shader.fColorCou nt);
bsalomon 2016/08/09 19:46:23 Does this do a move?
fmenozzi 2016/08/09 20:45:49 I don't think so; the ctor for SkTDArray that take
bsalomon 2016/08/10 13:18:35 It looks like this will call SkTDArray<T>& operato
1339 }
1101 1340
1102 if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFl ags()) { 1341 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
1342 if (shader.fOrigPos) {
1343 fPositions.setReserve(shader.fColorCount);
1344 fPositions = SkTDArray<SkScalar>(shader.fOrigPos, shader.fColorCount );
1345 }
1346
1347 fTileMode = tileMode;
1348 #endif
1349 }
1350
1351 switch (fColorType) {
1352 // The two and three color specializations do not currently support tili ng.
1353 case kTwo_ColorType:
1354 case kThree_ColorType:
1355 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
1356 case kHardStopLeftEdged_ColorType:
1357 case kHardStopRightEdged_ColorType:
1358 case kHardStopCentered_ColorType:
1359 #endif
1360 fRow = -1;
1361
1362 if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGr adFlags()) {
1363 fPremulType = kBeforeInterp_PremulType;
1364 } else {
1365 fPremulType = kAfterInterp_PremulType;
1366 }
1367
1368 fCoordTransform.reset(kCoordSet, matrix);
1369
1370 break;
1371 case kTexture_ColorType:
1372 // doesn't matter how this is set, just be consistent because it is part of the effect key.
1103 fPremulType = kBeforeInterp_PremulType; 1373 fPremulType = kBeforeInterp_PremulType;
1104 } else {
1105 fPremulType = kAfterInterp_PremulType;
1106 }
1107 fCoordTransform.reset(kCoordSet, matrix);
1108 } else {
1109 // doesn't matter how this is set, just be consistent because it is part of the effect key.
1110 fPremulType = kBeforeInterp_PremulType;
1111 SkBitmap bitmap;
1112 shader.getGradientTableBitmap(&bitmap);
1113 1374
1114 GrTextureStripAtlas::Desc desc; 1375 SkBitmap bitmap;
1115 desc.fWidth = bitmap.width(); 1376 shader.getGradientTableBitmap(&bitmap);
1116 desc.fHeight = 32;
1117 desc.fRowHeight = bitmap.height();
1118 desc.fContext = ctx;
1119 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info(), *ctx->caps());
1120 fAtlas = GrTextureStripAtlas::GetAtlas(desc);
1121 SkASSERT(fAtlas);
1122 1377
1123 // We always filter the gradient table. Each table is one row of a textu re, always y-clamp. 1378 GrTextureStripAtlas::Desc desc;
1124 GrTextureParams params; 1379 desc.fWidth = bitmap.width();
1125 params.setFilterMode(GrTextureParams::kBilerp_FilterMode); 1380 desc.fHeight = 32;
1126 params.setTileModeX(tileMode); 1381 desc.fRowHeight = bitmap.height();
1382 desc.fContext = ctx;
1383 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info(), *ctx->caps() );
1384 fAtlas = GrTextureStripAtlas::GetAtlas(desc);
1385 SkASSERT(fAtlas);
1127 1386
1128 fRow = fAtlas->lockRow(bitmap); 1387 // We always filter the gradient table. Each table is one row of a t exture, always y-clamp.
1129 if (-1 != fRow) { 1388 GrTextureParams params;
1130 fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf * fAtlas->getNorm alizedTexelHeight(); 1389 params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
1131 fCoordTransform.reset(kCoordSet, matrix, fAtlas->getTexture(), param s.filterMode()); 1390 params.setTileModeX(tileMode);
1132 fTextureAccess.reset(fAtlas->getTexture(), params); 1391
1133 } else { 1392 fRow = fAtlas->lockRow(bitmap);
1134 SkAutoTUnref<GrTexture> texture( 1393 if (-1 != fRow) {
1135 GrRefCachedBitmapTexture(ctx, bitmap, params, SkSourceGammaTreat ment::kRespect)); 1394 fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf * fAtlas->get NormalizedTexelHeight();
1136 if (!texture) { 1395 fCoordTransform.reset(kCoordSet, matrix, fAtlas->getTexture(), p arams.filterMode());
1137 return; 1396 fTextureAccess.reset(fAtlas->getTexture(), params);
1397 } else {
1398 SkAutoTUnref<GrTexture> texture(
1399 GrRefCachedBitmapTexture(ctx, bitmap, params, SkSourceGammaT reatment::kRespect));
1400 if (!texture) {
1401 return;
1402 }
1403 fCoordTransform.reset(kCoordSet, matrix, texture, params.filterM ode());
1404 fTextureAccess.reset(texture, params);
1405 fYCoord = SK_ScalarHalf;
1138 } 1406 }
1139 fCoordTransform.reset(kCoordSet, matrix, texture, params.filterMode( )); 1407
1140 fTextureAccess.reset(texture, params); 1408 this->addTextureAccess(&fTextureAccess);
1141 fYCoord = SK_ScalarHalf; 1409
1142 } 1410 break;
1143 this->addTextureAccess(&fTextureAccess);
1144 } 1411 }
1412
1145 this->addCoordTransform(&fCoordTransform); 1413 this->addCoordTransform(&fCoordTransform);
1146 } 1414 }
1147 1415
1148 GrGradientEffect::~GrGradientEffect() { 1416 GrGradientEffect::~GrGradientEffect() {
1149 if (this->useAtlas()) { 1417 if (this->useAtlas()) {
1150 fAtlas->unlockRow(fRow); 1418 fAtlas->unlockRow(fRow);
1151 } 1419 }
1152 } 1420 }
1153 1421
1154 bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const { 1422 bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
1155 const GrGradientEffect& s = processor.cast<GrGradientEffect>(); 1423 const GrGradientEffect& ge = processor.cast<GrGradientEffect>();
1156 1424
1157 if (this->fColorType == s.getColorType()){ 1425 if (this->fColorType == ge.getColorType()) {
1158 1426 if (kTexture_ColorType == fColorType) {
1159 if (SkGradientShaderBase::kTwo_GpuColorType == fColorType) { 1427 if (fYCoord != ge.getYCoord()) {
1160 if (this->getPremulType() != s.getPremulType() ||
1161 *this->getColors(0) != *s.getColors(0) ||
1162 *this->getColors(1) != *s.getColors(1)) {
1163 return false;
1164 }
1165 } else if (SkGradientShaderBase::kThree_GpuColorType == fColorType) {
1166 if (this->getPremulType() != s.getPremulType() ||
1167 *this->getColors(0) != *s.getColors(0) ||
1168 *this->getColors(1) != *s.getColors(1) ||
1169 *this->getColors(2) != *s.getColors(2)) {
1170 return false; 1428 return false;
1171 } 1429 }
1172 } else { 1430 } else {
1173 if (fYCoord != s.getYCoord()) { 1431 if (this->getPremulType() != ge.getPremulType() ||
1432 this->fAllColors.count() != ge.fAllColors.count()) {
1174 return false; 1433 return false;
1175 } 1434 }
1435
1436 for (int i = 0; i < this->fAllColors.count(); i++) {
1437 if (*this->getColors(i) != *ge.getColors(i)) {
1438 return false;
1439 }
1440 }
1176 } 1441 }
1177 1442
1178 SkASSERT(this->useAtlas() == s.useAtlas()); 1443 SkASSERT(this->useAtlas() == ge.useAtlas());
1179 return true; 1444 return true;
1180 } 1445 }
1181 1446
1182 return false; 1447 return false;
1183 } 1448 }
1184 1449
1185 void GrGradientEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 1450 void GrGradientEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
1186 if (fIsOpaque) { 1451 if (fIsOpaque) {
1187 inout->mulByUnknownOpaqueFourComponents(); 1452 inout->mulByUnknownOpaqueFourComponents();
1188 } else { 1453 } else {
(...skipping 19 matching lines...) Expand all
1208 (*stops)[i] = stop; 1473 (*stops)[i] = stop;
1209 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; 1474 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f;
1210 } 1475 }
1211 } 1476 }
1212 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); 1477 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount));
1213 1478
1214 return outColors; 1479 return outColors;
1215 } 1480 }
1216 1481
1217 #endif 1482 #endif
OLDNEW
« no previous file with comments | « no previous file | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698