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 "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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |