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 bool needWidth = true; |
45 fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloa t_GrSLType, | 54 bool needHeight = (fp.fBevelType == SkNormalSource::BevelType::kRoun dedOut || |
46 kDefault_GrSLPrecision, "Width", &widthUniName); | 55 fp.fBevelType == SkNormalSource::BevelType::kRoun dedIn); |
56 bool needNormalized = (fp.fBevelType == SkNormalSource::BevelType::k Linear); | |
57 | |
58 const char *widthUniName = nullptr; | |
59 if (needWidth) { | |
60 fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, k Float_GrSLType, | |
61 kDefault_GrSLPrecision, " Width", | |
62 &widthUniName); | |
63 } | |
47 | 64 |
48 const char* heightUniName = nullptr; | 65 const char* heightUniName = nullptr; |
49 fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFlo at_GrSLType, | 66 if (needHeight) { |
50 kDefault_GrSLPrecision, "Height", &heightUniName); | 67 fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType, |
68 kDefault_GrSLPrecision, "Height", | |
69 &heightUniName); | |
70 } | |
51 | 71 |
52 fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 1.0, 0.0);", args.fOut putColor); | 72 const char* normalizedWidthUniName = nullptr; |
73 const char* normalizedHeightUniName = nullptr; | |
74 if (needNormalized) { | |
75 fNormalizedWidthUni = uniformHandler->addUniform(kFragment_GrSha derFlag, | |
76 kFloat_GrSLType , | |
77 kDefault_GrSLPr ecision, | |
78 "NormalizedWidt h", | |
79 &normalizedWidt hUniName); | |
80 fNormalizedHeightUni = uniformHandler->addUniform(kFragment_GrSh aderFlag, | |
81 kFloat_GrSLTyp e, | |
82 kDefault_GrSLP recision, | |
83 "NormalizedHei ght", | |
84 &normalizedHei ghtUniName); | |
85 } | |
86 | |
87 // Here we are splitting the distance vector into length and normali zed direction | |
88 // TODO: Output these values from the geometry processor frag code i nstead of the vector | |
89 fragBuilder->codeAppendf("float dv_length = length(%s);", | |
90 fragBuilder->distanceVectorName()); | |
91 fragBuilder->codeAppendf("vec2 dv_norm = normalize(%s);", | |
92 fragBuilder->distanceVectorName()); | |
93 | |
94 fragBuilder->codeAppend( "vec3 normal;"); | |
95 fragBuilder->codeAppendf("if (dv_length >= %s) {", widthUniName); | |
96 fragBuilder->codeAppend( " normal = vec3(0.0, 0.0, 1.0);"); | |
97 fragBuilder->codeAppend( "} else {"); | |
98 this->emitMath(fragBuilder, fp.fBevelType, widthUniName, heightUniNa me, | |
99 normalizedWidthUniName, normalizedHeightUniName); | |
100 fragBuilder->codeAppend( "}"); | |
101 fragBuilder->codeAppendf("%s = vec4(normal, 0.0);", args.fOutputColo r); | |
53 } | 102 } |
54 | 103 |
55 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 104 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
56 GrProcessorKeyBuilder* b) { | 105 GrProcessorKeyBuilder* b) { |
57 const NormalBevelFP& fp = proc.cast<NormalBevelFP>(); | 106 const NormalBevelFP& fp = proc.cast<NormalBevelFP>(); |
58 b->add32(static_cast<int>(fp.fType)); | 107 b->add32(static_cast<int>(fp.fBevelType)); |
59 } | 108 } |
60 | 109 |
61 protected: | 110 protected: |
62 void setNormalData(const GrGLSLProgramDataManager& pdman, | 111 void setNormalData(const GrGLSLProgramDataManager& pdman, |
63 const GrProcessor& proc) override { | 112 const GrProcessor& proc) override { |
64 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); | 113 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); |
65 | 114 |
66 if (fPrevWidth != normalBevelFP.fWidth) { | 115 // Updating uniform if bevel type requires it and data has changed |
67 pdman.set1f(fWidthUni, normalBevelFP.fWidth); | 116 |
68 fPrevWidth = normalBevelFP.fWidth; | 117 bool needWidth = true; |
118 bool needHeight = (normalBevelFP.fBevelType == SkNormalSource::Bevel Type::kRoundedOut || | |
119 normalBevelFP.fBevelType == SkNormalSource::Bevel Type::kRoundedIn); | |
120 bool needNormalized = (normalBevelFP.fBevelType == SkNormalSource::B evelType::kLinear); | |
121 | |
122 bool dirtyWidth = (fPrevWidth != normalBevelFP.fBevelWidth); | |
123 bool dirtyHeight = (fPrevHeight != normalBevelFP.fBevelHeight); | |
124 bool dirtyNormalized = (dirtyHeight || dirtyWidth); | |
125 | |
126 | |
127 if (needWidth && dirtyWidth) { | |
128 pdman.set1f(fWidthUni, normalBevelFP.fBevelWidth); | |
129 fPrevWidth = normalBevelFP.fBevelWidth; | |
69 } | 130 } |
70 if (fPrevHeight != normalBevelFP.fHeight) { | 131 if (needHeight && dirtyHeight) { |
71 pdman.set1f(fHeightUni, normalBevelFP.fHeight); | 132 pdman.set1f(fHeightUni, normalBevelFP.fBevelHeight); |
72 fPrevHeight = normalBevelFP.fHeight; | 133 fPrevHeight = normalBevelFP.fBevelHeight; |
134 } | |
135 if (needNormalized && dirtyNormalized) { | |
136 SkScalar height = normalBevelFP.fBevelHeight; | |
137 SkScalar width = normalBevelFP.fBevelWidth; | |
138 | |
139 SkScalar length = SkScalarSqrt(SkScalarSquare(height) + SkScalar Square(width)); | |
140 pdman.set1f(fNormalizedHeightUni, height/length); | |
141 pdman.set1f(fNormalizedWidthUni, width/length); | |
73 } | 142 } |
74 } | 143 } |
75 | 144 |
145 // This method emits the code that calculates the normal orthgonal to th e simulated beveled | |
146 // surface. In the comments inside the function, the math involved is de scribed. For this | |
147 // purpose, the d-axis is defined to be the axis co-linear to the distan ce vector, where the | |
148 // origin is the end of the bevel inside the shape. | |
149 void emitMath(GrGLSLFPFragmentBuilder* fb, SkNormalSource::BevelType typ e, | |
150 const char* width, const char* height, const char* normali zedWidth, | |
151 const char* normalizedHeight) { | |
152 switch (type) { | |
153 case SkNormalSource::BevelType::kLinear: | |
154 // Because the slope of the bevel is -height/width, the vect or | |
155 // normalized(vec2(height, width)) is the d- and z-component s of the normal | |
156 // vector that is orthogonal to the linear bevel. Multiplyin g the d-component | |
157 // to the normalized distance vector splits it into x- and y -components. | |
158 fb->codeAppendf("normal = vec3(%s * dv_norm, %s);", | |
egdaniel
2016/08/04 18:36:19
for sanity lets assert normailizedHeight and norma
| |
159 normalizedHeight, normalizedWidth); | |
160 break; | |
161 case SkNormalSource::BevelType::kRoundedOut: | |
162 // Fall through | |
163 case SkNormalSource::BevelType::kRoundedIn: | |
egdaniel
2016/08/04 18:36:20
assert the height in here
| |
164 // Setting the current position in the d-axis to the distanc e from the end of | |
165 // the bevel as opposed to the beginning if the bevel is rou nded in, essentially | |
166 // flipping the bevel calculations. | |
167 if ( type == SkNormalSource::BevelType::kRoundedIn ) { | |
168 fb->codeAppendf("float currentPos_d = %s - dv_length;", width); | |
169 } else if (type == SkNormalSource::BevelType::kRoundedOut) { | |
170 fb->codeAppendf("float currentPos_d = dv_length;"); | |
171 } | |
172 | |
173 fb->codeAppendf("float rootTOverW = sqrt(t/%s);", width); | |
174 | |
175 // Calculating the d- and z-components of the normal, where 'd' is the axis | |
176 // co-linear to the distance vector. Equation was derived fr om the formula for | |
177 // a bezier curve by solving the parametric equation for d(t ) and z(t), then | |
178 // with those, calculate d'(t), z'(t) and t(d), and from the se, d'(d) and z'(d). | |
179 // z'(d)/d'(d) results in the slope of the bevel at d, so we construct an | |
180 // orthogonal vector of slope -d'(d)/z'(d) and length 1. | |
181 fb->codeAppendf("vec2 unnormalizedNormal_dz = vec2(%s*(1.0-r ootTOverW), " | |
182 "%s*rootT OverW);", | |
183 height, width); | |
184 fb->codeAppendf("vec2 normal_dz = normalize(unnormalizedNorm al_dz);"); | |
185 | |
186 // Multiplying the d-component to the normalized distance ve ctor splits it into | |
187 // x- and y-components. | |
188 fb->codeAppendf("normal = vec3(normal_dz.x*dv_norm, normal_d z.y);"); | |
189 | |
190 break; | |
191 default: | |
192 SkDEBUGFAIL("Invalid bevel type passed to emitMath"); | |
193 } | |
194 } | |
195 | |
76 private: | 196 private: |
77 SkScalar fPrevWidth; | 197 SkScalar fPrevWidth; |
78 GrGLSLProgramDataManager::UniformHandle fWidthUni; | 198 GrGLSLProgramDataManager::UniformHandle fWidthUni; |
79 | 199 |
80 SkScalar fPrevHeight; | 200 SkScalar fPrevHeight; |
81 GrGLSLProgramDataManager::UniformHandle fHeightUni; | 201 GrGLSLProgramDataManager::UniformHandle fHeightUni; |
202 | |
203 // width / length(<width,height>) | |
204 GrGLSLProgramDataManager::UniformHandle fNormalizedWidthUni; | |
205 // height / length(<width,height>) | |
206 GrGLSLProgramDataManager::UniformHandle fNormalizedHeightUni; | |
82 }; | 207 }; |
83 | 208 |
84 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { | 209 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { |
85 GLSLNormalBevelFP::GenKey(*this, caps, b); | 210 GLSLNormalBevelFP::GenKey(*this, caps, b); |
86 } | 211 } |
87 | 212 |
88 const char* name() const override { return "NormalBevelFP"; } | 213 const char* name() const override { return "NormalBevelFP"; } |
89 | 214 |
90 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 215 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
91 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput); | 216 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput); |
92 } | 217 } |
93 | 218 |
94 private: | 219 private: |
95 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalBevelFP; } | 220 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalBevelFP; } |
96 | 221 |
97 bool onIsEqual(const GrFragmentProcessor& proc) const override { | 222 bool onIsEqual(const GrFragmentProcessor& proc) const override { |
98 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); | 223 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); |
99 return fType == normalBevelFP.fType && | 224 return fBevelType == normalBevelFP.fBevelType && |
100 fWidth == normalBevelFP.fWidth && | 225 fBevelWidth == normalBevelFP.fBevelWidth && |
101 fHeight == normalBevelFP.fHeight; | 226 fBevelHeight == normalBevelFP.fBevelHeight; |
102 } | 227 } |
103 | 228 |
104 SkNormalSource::BevelType fType; | 229 SkNormalSource::BevelType fBevelType; |
105 SkScalar fWidth; | 230 SkScalar fBevelWidth; |
106 SkScalar fHeight; | 231 SkScalar fBevelHeight; |
107 }; | 232 }; |
108 | 233 |
109 sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor( | 234 sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor( |
110 const SkShader::AsFPArgs&) const { | 235 const SkShader::AsFPArgs& args) const { |
111 | 236 |
112 return sk_make_sp<NormalBevelFP>(fType, fWidth, fHeight); | 237 SkScalar maxScale = args.fViewMatrix->getMaxScale(); |
238 | |
239 // Providing device-space width and height | |
240 return sk_make_sp<NormalBevelFP>(fType, maxScale * fWidth, maxScale * fHeigh t); | |
113 } | 241 } |
114 | 242 |
115 #endif // SK_SUPPORT_GPU | 243 #endif // SK_SUPPORT_GPU |
116 | 244 |
117 //////////////////////////////////////////////////////////////////////////// | 245 //////////////////////////////////////////////////////////////////////////// |
118 | 246 |
119 SkNormalBevelSourceImpl::Provider::Provider() {} | 247 SkNormalBevelSourceImpl::Provider::Provider() {} |
120 | 248 |
121 SkNormalBevelSourceImpl::Provider::~Provider() {} | 249 SkNormalBevelSourceImpl::Provider::~Provider() {} |
122 | 250 |
(...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) { | 288 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 | 289 /* 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.*/ | 290 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)); | 291 SkASSERT(width > 0.0f && !SkScalarNearlyZero(width)); |
164 if (SkScalarNearlyZero(height)) { | 292 if (SkScalarNearlyZero(height)) { |
165 return SkNormalSource::MakeFlat(); | 293 return SkNormalSource::MakeFlat(); |
166 } | 294 } |
167 | 295 |
168 return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height); | 296 return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height); |
169 } | 297 } |
OLD | NEW |