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

Side by Side Diff: src/core/SkNormalBevelSource.cpp

Issue 2151653002: Added math for SkNormalBevelSource to create bevels on GPU side (Closed) Base URL: https://skia.googlesource.com/skia@dvonbeck-bevel-impl-0
Patch Set: Consistency fix 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 | no next file » | 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 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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698