OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
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 "SkNormalBevelSource.h" | 8 #include "SkNormalBevelSource.h" |
9 | 9 |
10 #include "SkNormalSource.h" | 10 #include "SkNormalSource.h" |
11 #include "SkNormalSourcePriv.h" | 11 #include "SkNormalSourcePriv.h" |
12 #include "SkPoint3.h" | 12 #include "SkPoint3.h" |
13 #include "SkReadBuffer.h" | 13 #include "SkReadBuffer.h" |
14 #include "SkWriteBuffer.h" | 14 #include "SkWriteBuffer.h" |
15 | 15 |
16 #if SK_SUPPORT_GPU | 16 #if SK_SUPPORT_GPU |
17 #include "GrInvariantOutput.h" | 17 #include "GrInvariantOutput.h" |
18 #include "glsl/GrGLSLFragmentProcessor.h" | 18 #include "glsl/GrGLSLFragmentProcessor.h" |
19 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 19 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
20 #include "SkGr.h" | 20 #include "SkGr.h" |
21 | 21 |
| 22 /** \class NormalBevelFP |
| 23 * |
| 24 * Fragment processor for the SkNormalBevelSource. |
| 25 * |
| 26 * @param bevelType type of the bevel |
| 27 * @param bevelWidth width of the bevel in device space |
| 28 * @param bevelHeight height of the bevel in device space |
| 29 */ |
22 class NormalBevelFP : public GrFragmentProcessor { | 30 class NormalBevelFP : public GrFragmentProcessor { |
23 public: | 31 public: |
24 NormalBevelFP(SkNormalSource::BevelType type, SkScalar width, SkScalar heigh
t) | 32 NormalBevelFP(SkNormalSource::BevelType bevelType, SkScalar bevelWidth, SkSc
alar bevelHeight) |
25 : fType(type) | 33 : fBevelType(bevelType) |
26 , fWidth(width) | 34 , fBevelWidth(bevelWidth) |
27 , fHeight(height) { | 35 , fBevelHeight(bevelHeight) { |
28 this->initClassID<NormalBevelFP>(); | 36 this->initClassID<NormalBevelFP>(); |
29 | 37 |
30 fUsesDistanceVectorField = true; | 38 fUsesDistanceVectorField = true; |
31 } | 39 } |
32 | 40 |
33 class GLSLNormalBevelFP : public GLSLNormalFP { | 41 class GLSLNormalBevelFP : public GLSLNormalFP { |
34 public: | 42 public: |
35 GLSLNormalBevelFP() { | 43 GLSLNormalBevelFP() { |
36 fPrevWidth = SkFloatToScalar(0.0f); | 44 fPrevWidth = SkFloatToScalar(0.0f); |
37 fPrevHeight = SkFloatToScalar(0.0f); | 45 fPrevHeight = SkFloatToScalar(0.0f); |
38 } | 46 } |
39 | 47 |
40 void onEmitCode(EmitArgs& args) override { | 48 void onEmitCode(EmitArgs& args) override { |
41 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; | 49 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; |
| 50 const NormalBevelFP& fp = args.fFp.cast<NormalBevelFP>(); |
42 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | 51 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
43 | 52 |
44 const char* widthUniName = nullptr; | 53 // Determining necessary uniforms and initializing them |
45 fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloa
t_GrSLType, | 54 bool needWidth = true; |
46 kDefault_GrSLPrecision, "Width", &widthUniName); | 55 bool needHeight = (fp.fBevelType == SkNormalSource::BevelType::kRoun
dedOut || |
| 56 fp.fBevelType == SkNormalSource::BevelType::kRoun
dedIn); |
| 57 bool needNormalized = (fp.fBevelType == SkNormalSource::BevelType::k
Linear); |
| 58 |
| 59 const char *widthUniName = nullptr; |
| 60 if (needWidth) { |
| 61 fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, k
Float_GrSLType, |
| 62 kDefault_GrSLPrecision, "
Width", |
| 63 &widthUniName); |
| 64 } |
47 | 65 |
48 const char* heightUniName = nullptr; | 66 const char* heightUniName = nullptr; |
49 fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFlo
at_GrSLType, | 67 if (needHeight) { |
50 kDefault_GrSLPrecision, "Height", &heightUniName); | 68 fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
kFloat_GrSLType, |
| 69 kDefault_GrSLPrecision,
"Height", |
| 70 &heightUniName); |
| 71 } |
51 | 72 |
52 fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 1.0, 0.0);", args.fOut
putColor); | 73 const char* normalizedWidthUniName = nullptr; |
| 74 const char* normalizedHeightUniName = nullptr; |
| 75 if (needNormalized) { |
| 76 fNormalizedWidthUni = uniformHandler->addUniform(kFragment_GrSha
derFlag, |
| 77 kFloat_GrSLType
, |
| 78 kDefault_GrSLPr
ecision, |
| 79 "NormalizedWidt
h", |
| 80 &normalizedWidt
hUniName); |
| 81 fNormalizedHeightUni = uniformHandler->addUniform(kFragment_GrSh
aderFlag, |
| 82 kFloat_GrSLTyp
e, |
| 83 kDefault_GrSLP
recision, |
| 84 "NormalizedHei
ght", |
| 85 &normalizedHei
ghtUniName); |
| 86 } |
| 87 |
| 88 // Here we are splitting the distance vector into length and normali
zed direction |
| 89 // TODO: Output these values from the geometry processor frag code i
nstead of the vector |
| 90 fragBuilder->codeAppendf("float dv_length = length(%s);", |
| 91 fragBuilder->distanceVectorName()); |
| 92 fragBuilder->codeAppendf("vec2 dv_norm = normalize(%s);", |
| 93 fragBuilder->distanceVectorName()); |
| 94 |
| 95 // Asserting presence of necessary uniforms |
| 96 SkASSERT(widthUniName); |
| 97 |
| 98 fragBuilder->codeAppend( "vec3 normal;"); |
| 99 fragBuilder->codeAppendf("if (dv_length >= %s) {", widthUniName); |
| 100 fragBuilder->codeAppend( " normal = vec3(0.0, 0.0, 1.0);"); |
| 101 fragBuilder->codeAppend( "} else {"); |
| 102 this->emitMath(fragBuilder, fp.fBevelType, widthUniName, heightUniNa
me, |
| 103 normalizedWidthUniName, normalizedHeightUniName); |
| 104 fragBuilder->codeAppend( "}"); |
| 105 fragBuilder->codeAppendf("%s = vec4(normal, 0.0);", args.fOutputColo
r); |
53 } | 106 } |
54 | 107 |
55 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 108 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
56 GrProcessorKeyBuilder* b) { | 109 GrProcessorKeyBuilder* b) { |
57 const NormalBevelFP& fp = proc.cast<NormalBevelFP>(); | 110 const NormalBevelFP& fp = proc.cast<NormalBevelFP>(); |
58 b->add32(static_cast<int>(fp.fType)); | 111 b->add32(static_cast<int>(fp.fBevelType)); |
59 } | 112 } |
60 | 113 |
61 protected: | 114 protected: |
62 void setNormalData(const GrGLSLProgramDataManager& pdman, | 115 void setNormalData(const GrGLSLProgramDataManager& pdman, |
63 const GrProcessor& proc) override { | 116 const GrProcessor& proc) override { |
64 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); | 117 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); |
65 | 118 |
66 if (fPrevWidth != normalBevelFP.fWidth) { | 119 // Updating uniform if bevel type requires it and data has changed |
67 pdman.set1f(fWidthUni, normalBevelFP.fWidth); | 120 |
68 fPrevWidth = normalBevelFP.fWidth; | 121 bool needWidth = true; |
| 122 bool needHeight = (normalBevelFP.fBevelType == SkNormalSource::Bevel
Type::kRoundedOut || |
| 123 normalBevelFP.fBevelType == SkNormalSource::Bevel
Type::kRoundedIn); |
| 124 bool needNormalized = (normalBevelFP.fBevelType == SkNormalSource::B
evelType::kLinear); |
| 125 |
| 126 bool dirtyWidth = (fPrevWidth != normalBevelFP.fBevelWidth); |
| 127 bool dirtyHeight = (fPrevHeight != normalBevelFP.fBevelHeight); |
| 128 bool dirtyNormalized = (dirtyHeight || dirtyWidth); |
| 129 |
| 130 |
| 131 if (needWidth && dirtyWidth) { |
| 132 pdman.set1f(fWidthUni, normalBevelFP.fBevelWidth); |
| 133 fPrevWidth = normalBevelFP.fBevelWidth; |
69 } | 134 } |
70 if (fPrevHeight != normalBevelFP.fHeight) { | 135 if (needHeight && dirtyHeight) { |
71 pdman.set1f(fHeightUni, normalBevelFP.fHeight); | 136 pdman.set1f(fHeightUni, normalBevelFP.fBevelHeight); |
72 fPrevHeight = normalBevelFP.fHeight; | 137 fPrevHeight = normalBevelFP.fBevelHeight; |
| 138 } |
| 139 if (needNormalized && dirtyNormalized) { |
| 140 SkScalar height = normalBevelFP.fBevelHeight; |
| 141 SkScalar width = normalBevelFP.fBevelWidth; |
| 142 |
| 143 SkScalar length = SkScalarSqrt(SkScalarSquare(height) + SkScalar
Square(width)); |
| 144 pdman.set1f(fNormalizedHeightUni, height/length); |
| 145 pdman.set1f(fNormalizedWidthUni, width/length); |
73 } | 146 } |
74 } | 147 } |
75 | 148 |
| 149 // This method emits the code that calculates the normal orthgonal to th
e simulated beveled |
| 150 // surface. In the comments inside the function, the math involved is de
scribed. For this |
| 151 // purpose, the d-axis is defined to be the axis co-linear to the distan
ce vector, where the |
| 152 // origin is the end of the bevel inside the shape. |
| 153 void emitMath(GrGLSLFPFragmentBuilder* fb, SkNormalSource::BevelType typ
e, |
| 154 const char* width, const char* height, const char* normali
zedWidth, |
| 155 const char* normalizedHeight) { |
| 156 switch (type) { |
| 157 case SkNormalSource::BevelType::kLinear: |
| 158 // Asserting presence of necessary uniforms |
| 159 SkASSERT(normalizedHeight); |
| 160 SkASSERT(normalizedWidth); |
| 161 |
| 162 // Because the slope of the bevel is -height/width, the vect
or |
| 163 // normalized(vec2(height, width)) is the d- and z-component
s of the normal |
| 164 // vector that is orthogonal to the linear bevel. Multiplyin
g the d-component |
| 165 // to the normalized distance vector splits it into x- and y
-components. |
| 166 fb->codeAppendf("normal = vec3(%s * dv_norm, %s);", |
| 167 normalizedHeight, normalizedWidth); |
| 168 break; |
| 169 case SkNormalSource::BevelType::kRoundedOut: |
| 170 // Fall through |
| 171 case SkNormalSource::BevelType::kRoundedIn: |
| 172 // Asserting presence of necessary uniforms |
| 173 SkASSERT(height); |
| 174 SkASSERT(width); |
| 175 |
| 176 // Setting the current position in the d-axis to the distanc
e from the end of |
| 177 // the bevel as opposed to the beginning if the bevel is rou
nded in, essentially |
| 178 // flipping the bevel calculations. |
| 179 if ( type == SkNormalSource::BevelType::kRoundedIn ) { |
| 180 fb->codeAppendf("float currentPos_d = %s - dv_length;",
width); |
| 181 } else if (type == SkNormalSource::BevelType::kRoundedOut) { |
| 182 fb->codeAppendf("float currentPos_d = dv_length;"); |
| 183 } |
| 184 |
| 185 fb->codeAppendf("float rootDOverW = sqrt(currentPos_d/%s);",
width); |
| 186 |
| 187 // Calculating the d- and z-components of the normal, where
'd' is the axis |
| 188 // co-linear to the distance vector. Equation was derived fr
om the formula for |
| 189 // a bezier curve by solving the parametric equation for d(t
) and z(t), then |
| 190 // with those, calculate d'(t), z'(t) and t(d), and from the
se, d'(d) and z'(d). |
| 191 // z'(d)/d'(d) results in the slope of the bevel at d, so we
construct an |
| 192 // orthogonal vector of slope -d'(d)/z'(d) and length 1. |
| 193 fb->codeAppendf("vec2 unnormalizedNormal_dz = vec2(%s*(1.0-r
ootDOverW), " |
| 194 "%s*rootD
OverW);", |
| 195 height, width); |
| 196 fb->codeAppendf("vec2 normal_dz = normalize(unnormalizedNorm
al_dz);"); |
| 197 |
| 198 // Multiplying the d-component to the normalized distance ve
ctor splits it into |
| 199 // x- and y-components. |
| 200 fb->codeAppendf("normal = vec3(normal_dz.x*dv_norm, normal_d
z.y);"); |
| 201 |
| 202 break; |
| 203 default: |
| 204 SkDEBUGFAIL("Invalid bevel type passed to emitMath"); |
| 205 } |
| 206 } |
| 207 |
76 private: | 208 private: |
77 SkScalar fPrevWidth; | 209 SkScalar fPrevWidth; |
78 GrGLSLProgramDataManager::UniformHandle fWidthUni; | 210 GrGLSLProgramDataManager::UniformHandle fWidthUni; |
79 | 211 |
80 SkScalar fPrevHeight; | 212 SkScalar fPrevHeight; |
81 GrGLSLProgramDataManager::UniformHandle fHeightUni; | 213 GrGLSLProgramDataManager::UniformHandle fHeightUni; |
| 214 |
| 215 // width / length(<width,height>) |
| 216 GrGLSLProgramDataManager::UniformHandle fNormalizedWidthUni; |
| 217 // height / length(<width,height>) |
| 218 GrGLSLProgramDataManager::UniformHandle fNormalizedHeightUni; |
82 }; | 219 }; |
83 | 220 |
84 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { | 221 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { |
85 GLSLNormalBevelFP::GenKey(*this, caps, b); | 222 GLSLNormalBevelFP::GenKey(*this, caps, b); |
86 } | 223 } |
87 | 224 |
88 const char* name() const override { return "NormalBevelFP"; } | 225 const char* name() const override { return "NormalBevelFP"; } |
89 | 226 |
90 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 227 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
91 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput); | 228 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput); |
92 } | 229 } |
93 | 230 |
94 private: | 231 private: |
95 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new
GLSLNormalBevelFP; } | 232 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new
GLSLNormalBevelFP; } |
96 | 233 |
97 bool onIsEqual(const GrFragmentProcessor& proc) const override { | 234 bool onIsEqual(const GrFragmentProcessor& proc) const override { |
98 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); | 235 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); |
99 return fType == normalBevelFP.fType && | 236 return fBevelType == normalBevelFP.fBevelType && |
100 fWidth == normalBevelFP.fWidth && | 237 fBevelWidth == normalBevelFP.fBevelWidth && |
101 fHeight == normalBevelFP.fHeight; | 238 fBevelHeight == normalBevelFP.fBevelHeight; |
102 } | 239 } |
103 | 240 |
104 SkNormalSource::BevelType fType; | 241 SkNormalSource::BevelType fBevelType; |
105 SkScalar fWidth; | 242 SkScalar fBevelWidth; |
106 SkScalar fHeight; | 243 SkScalar fBevelHeight; |
107 }; | 244 }; |
108 | 245 |
109 sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor( | 246 sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor( |
110 const SkShader::AsFPArgs&) const { | 247 const SkShader::AsFPArgs& args) const { |
111 | 248 |
112 return sk_make_sp<NormalBevelFP>(fType, fWidth, fHeight); | 249 SkScalar maxScale = args.fViewMatrix->getMaxScale(); |
| 250 |
| 251 // Providing device-space width and height |
| 252 return sk_make_sp<NormalBevelFP>(fType, maxScale * fWidth, maxScale * fHeigh
t); |
113 } | 253 } |
114 | 254 |
115 #endif // SK_SUPPORT_GPU | 255 #endif // SK_SUPPORT_GPU |
116 | 256 |
117 //////////////////////////////////////////////////////////////////////////// | 257 //////////////////////////////////////////////////////////////////////////// |
118 | 258 |
119 SkNormalBevelSourceImpl::Provider::Provider() {} | 259 SkNormalBevelSourceImpl::Provider::Provider() {} |
120 | 260 |
121 SkNormalBevelSourceImpl::Provider::~Provider() {} | 261 SkNormalBevelSourceImpl::Provider::~Provider() {} |
122 | 262 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 sk_sp<SkNormalSource> SkNormalSource::MakeBevel(BevelType type, SkScalar width,
SkScalar height) { | 300 sk_sp<SkNormalSource> SkNormalSource::MakeBevel(BevelType type, SkScalar width,
SkScalar height) { |
161 /* TODO make sure this checks are tolerant enough to account for loss of con
version when GPUs | 301 /* TODO make sure this checks are tolerant enough to account for loss of con
version when GPUs |
162 use 16-bit float types. We don't want to assume stuff is non-zero on the
GPU and be wrong.*/ | 302 use 16-bit float types. We don't want to assume stuff is non-zero on the
GPU and be wrong.*/ |
163 SkASSERT(width > 0.0f && !SkScalarNearlyZero(width)); | 303 SkASSERT(width > 0.0f && !SkScalarNearlyZero(width)); |
164 if (SkScalarNearlyZero(height)) { | 304 if (SkScalarNearlyZero(height)) { |
165 return SkNormalSource::MakeFlat(); | 305 return SkNormalSource::MakeFlat(); |
166 } | 306 } |
167 | 307 |
168 return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height); | 308 return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height); |
169 } | 309 } |
OLD | NEW |