Chromium Code Reviews| 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 * | |
|
robertphillips
2016/08/03 16:33:15
What do you think about renaming these bevelWidth,
dvonbeck
2016/08/03 21:04:20
Done. Should I do this in the user-facing API too?
| |
| 26 * @param type type of the bevel | |
| 27 * @param width width of the bevel in device space | |
| 28 * @param height 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 type, SkScalar width, SkScalar heigh t) |
| 25 : fType(type) | 33 : fType(type) |
| 26 , fWidth(width) | 34 , fWidth(width) |
| 27 , fHeight(height) { | 35 , fHeight(height) { |
| 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 const char* widthUniName = nullptr; |
| 45 fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloa t_GrSLType, | 54 fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloa t_GrSLType, |
| 46 kDefault_GrSLPrecision, "Width", &widthUniName); | 55 kDefault_GrSLPrecision, "Width", &widthUniName); |
| 47 | 56 |
| 48 const char* heightUniName = nullptr; | 57 const char* heightUniName = nullptr; |
| 49 fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFlo at_GrSLType, | 58 fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFlo at_GrSLType, |
| 50 kDefault_GrSLPrecision, "Height", &heightUniName); | 59 kDefault_GrSLPrecision, "Height", &heightUniName); |
| 51 | 60 |
|
robertphillips
2016/08/03 16:33:14
Do you think the shader compilers are going to be
dvonbeck
2016/08/03 16:39:24
I assume so but I don't know. Do you think I shoul
dvonbeck
2016/08/03 21:04:19
No longer necessary.
| |
| 52 fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 1.0, 0.0);", args.fOut putColor); | 61 fragBuilder->codeAppend( "vec3 normal;"); |
| 62 fragBuilder->codeAppendf("if (length(%s) >= %s) {", | |
| 63 fragBuilder->distanceVectorName(), widthUni Name); | |
| 64 fragBuilder->codeAppend( " normal = vec3(0.0, 0.0, 1.0);"); | |
| 65 fragBuilder->codeAppend( "} else {"); | |
| 66 this->emitMath(fragBuilder, fp.fType, widthUniName, heightUniName); | |
| 67 fragBuilder->codeAppend( "}"); | |
| 68 fragBuilder->codeAppendf("%s = vec4(normal, 0.0);", args.fOutputColo r); | |
| 53 } | 69 } |
| 54 | 70 |
| 55 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 71 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
| 56 GrProcessorKeyBuilder* b) { | 72 GrProcessorKeyBuilder* b) { |
| 57 const NormalBevelFP& fp = proc.cast<NormalBevelFP>(); | 73 const NormalBevelFP& fp = proc.cast<NormalBevelFP>(); |
| 58 b->add32(static_cast<int>(fp.fType)); | 74 b->add32(static_cast<int>(fp.fType)); |
| 59 } | 75 } |
| 60 | 76 |
| 61 protected: | 77 protected: |
| 62 void setNormalData(const GrGLSLProgramDataManager& pdman, | 78 void setNormalData(const GrGLSLProgramDataManager& pdman, |
| 63 const GrProcessor& proc) override { | 79 const GrProcessor& proc) override { |
| 64 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); | 80 const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>(); |
| 65 | 81 |
| 66 if (fPrevWidth != normalBevelFP.fWidth) { | 82 if (fPrevWidth != normalBevelFP.fWidth) { |
| 67 pdman.set1f(fWidthUni, normalBevelFP.fWidth); | 83 pdman.set1f(fWidthUni, normalBevelFP.fWidth); |
| 68 fPrevWidth = normalBevelFP.fWidth; | 84 fPrevWidth = normalBevelFP.fWidth; |
| 69 } | 85 } |
| 70 if (fPrevHeight != normalBevelFP.fHeight) { | 86 if (fPrevHeight != normalBevelFP.fHeight) { |
| 71 pdman.set1f(fHeightUni, normalBevelFP.fHeight); | 87 pdman.set1f(fHeightUni, normalBevelFP.fHeight); |
| 72 fPrevHeight = normalBevelFP.fHeight; | 88 fPrevHeight = normalBevelFP.fHeight; |
| 73 } | 89 } |
| 74 } | 90 } |
| 75 | 91 |
| 92 void emitMath(GrGLSLFPFragmentBuilder* fb, SkNormalSource::BevelType typ e, | |
| 93 const char* width, const char* height) { | |
| 94 const char* distanceVector = fb->distanceVectorName(); | |
| 95 | |
| 96 // Setting t to the distance from the end of the bevel as opposed to the beginning if | |
| 97 // the bevel is rounded out. | |
| 98 if ( type == SkNormalSource::BevelType::kRoundedIn ) { | |
| 99 fb->codeAppendf(" float t = %s - length(%s);", width, distanc eVector); | |
| 100 } else if (type == SkNormalSource::BevelType::kRoundedOut) { | |
| 101 fb->codeAppendf(" float t = length(%s);", distanceVector); | |
| 102 } | |
| 103 | |
| 104 switch (type) { | |
| 105 case SkNormalSource::BevelType::kLinear: | |
| 106 fb->codeAppendf(" normal = normalize(%s*vec3(%s, 0.0) " | |
| 107 "+ vec3(0.0, 0.0, %s) );", | |
| 108 height, distanceVector, width); | |
| 109 break; | |
|
robertphillips
2016/08/03 16:33:15
Add a "// fall through" comment
dvonbeck
2016/08/03 21:04:20
Done.
| |
| 110 case SkNormalSource::BevelType::kRoundedOut: | |
| 111 case SkNormalSource::BevelType::kRoundedIn: | |
| 112 // calculating the slope of the normal with respect to the d istance vector by | |
| 113 // setting it equal to the negative reciprocal of the deriva tive of the bezier | |
|
robertphillips
2016/08/03 16:33:15
cure -> curve
One would hope the shader compilers
dvonbeck
2016/08/03 16:39:24
Do you think they will, or should I make it explic
dvonbeck
2016/08/03 21:04:20
Done.
| |
| 114 // cure | |
| 115 fb->codeAppendf("float slope = %s * sqrt(t) / (%s * (sqrt(%s ) - sqrt(t)));", | |
| 116 width, height, width); | |
| 117 // calculating a value so that when appended to the distance vector and | |
| 118 // normalized, it would result in a normal with the correct slope | |
| 119 fb->codeAppend("float z_prenorm = slope * t;"); | |
| 120 // Multiplying with the height's sign to orient the vector i nwards for bevels of | |
| 121 // negative height | |
|
robertphillips
2016/08/03 16:33:15
Is sign() verboten?
dvonbeck
2016/08/03 21:04:20
No longer necessary.
| |
| 122 fb->codeAppendf("normal = normalize(vec3(%s, z_prenorm)) * n ormalize(%s);", | |
| 123 distanceVector, height); | |
| 124 break; | |
| 125 default: | |
| 126 SkDEBUGFAIL("Invalid bevel type passed to emitMath"); | |
| 127 } | |
| 128 } | |
| 129 | |
| 76 private: | 130 private: |
| 77 SkScalar fPrevWidth; | 131 SkScalar fPrevWidth; |
| 78 GrGLSLProgramDataManager::UniformHandle fWidthUni; | 132 GrGLSLProgramDataManager::UniformHandle fWidthUni; |
| 79 | 133 |
| 80 SkScalar fPrevHeight; | 134 SkScalar fPrevHeight; |
| 81 GrGLSLProgramDataManager::UniformHandle fHeightUni; | 135 GrGLSLProgramDataManager::UniformHandle fHeightUni; |
| 82 }; | 136 }; |
| 83 | 137 |
| 84 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { | 138 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { |
| 85 GLSLNormalBevelFP::GenKey(*this, caps, b); | 139 GLSLNormalBevelFP::GenKey(*this, caps, b); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 100 fWidth == normalBevelFP.fWidth && | 154 fWidth == normalBevelFP.fWidth && |
| 101 fHeight == normalBevelFP.fHeight; | 155 fHeight == normalBevelFP.fHeight; |
| 102 } | 156 } |
| 103 | 157 |
| 104 SkNormalSource::BevelType fType; | 158 SkNormalSource::BevelType fType; |
| 105 SkScalar fWidth; | 159 SkScalar fWidth; |
| 106 SkScalar fHeight; | 160 SkScalar fHeight; |
| 107 }; | 161 }; |
| 108 | 162 |
| 109 sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor( | 163 sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor( |
| 110 const SkShader::AsFPArgs&) const { | 164 const SkShader::AsFPArgs& args) const { |
| 111 | 165 |
| 112 return sk_make_sp<NormalBevelFP>(fType, fWidth, fHeight); | 166 SkScalar maxScale = args.fViewMatrix->getMaxScale(); |
| 167 | |
| 168 // Providing device-space width and height | |
| 169 return sk_make_sp<NormalBevelFP>(fType, maxScale * fWidth, maxScale * fHeigh t); | |
| 113 } | 170 } |
| 114 | 171 |
| 115 #endif // SK_SUPPORT_GPU | 172 #endif // SK_SUPPORT_GPU |
| 116 | 173 |
| 117 //////////////////////////////////////////////////////////////////////////// | 174 //////////////////////////////////////////////////////////////////////////// |
| 118 | 175 |
| 119 SkNormalBevelSourceImpl::Provider::Provider() {} | 176 SkNormalBevelSourceImpl::Provider::Provider() {} |
| 120 | 177 |
| 121 SkNormalBevelSourceImpl::Provider::~Provider() {} | 178 SkNormalBevelSourceImpl::Provider::~Provider() {} |
| 122 | 179 |
| (...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) { | 217 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 | 218 /* 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.*/ | 219 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)); | 220 SkASSERT(width > 0.0f && !SkScalarNearlyZero(width)); |
| 164 if (SkScalarNearlyZero(height)) { | 221 if (SkScalarNearlyZero(height)) { |
| 165 return SkNormalSource::MakeFlat(); | 222 return SkNormalSource::MakeFlat(); |
| 166 } | 223 } |
| 167 | 224 |
| 168 return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height); | 225 return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height); |
| 169 } | 226 } |
| OLD | NEW |