| 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 "SkRRectsGaussianEdgeShader.h" | 8 #include "SkRRectsGaussianEdgeShader.h" |
| 9 #include "SkReadBuffer.h" | 9 #include "SkReadBuffer.h" |
| 10 #include "SkWriteBuffer.h" | 10 #include "SkWriteBuffer.h" |
| 11 | 11 |
| 12 /** \class SkRRectsGaussianEdgeShaderImpl | 12 /** \class SkRRectsGaussianEdgeShaderImpl |
| 13 * This shader applies a gaussian edge to the intersection of two round rects. | 13 * This shader applies a gaussian edge to the intersection of two round rects. |
| 14 * The round rects must have the same radii at each corner and the x&y radii | 14 * The round rects must have the same radii at each corner and the x&y radii |
| 15 * must also be equal. | 15 * must also be equal. |
| 16 */ | 16 */ |
| 17 class SkRRectsGaussianEdgeShaderImpl : public SkShader { | 17 class SkRRectsGaussianEdgeShaderImpl : public SkShader { |
| 18 public: | 18 public: |
| 19 SkRRectsGaussianEdgeShaderImpl(const SkRRect& first, const SkRRect& second, | 19 SkRRectsGaussianEdgeShaderImpl(const SkRRect& first, const SkRRect& second,
SkScalar radius) |
| 20 SkScalar radius, SkScalar pad) | |
| 21 : fFirst(first) | 20 : fFirst(first) |
| 22 , fSecond(second) | 21 , fSecond(second) |
| 23 , fRadius(radius) | 22 , fRadius(radius) { |
| 24 , fPad(pad) { | |
| 25 } | 23 } |
| 26 | 24 |
| 27 bool isOpaque() const override { return false; } | 25 bool isOpaque() const override { return false; } |
| 28 | 26 |
| 29 #if SK_SUPPORT_GPU | 27 #if SK_SUPPORT_GPU |
| 30 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const overri
de; | 28 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const overri
de; |
| 31 #endif | 29 #endif |
| 32 | 30 |
| 33 class GaussianEdgeShaderContext : public SkShader::Context { | 31 class GaussianEdgeShaderContext : public SkShader::Context { |
| 34 public: | 32 public: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 51 | 49 |
| 52 protected: | 50 protected: |
| 53 void flatten(SkWriteBuffer&) const override; | 51 void flatten(SkWriteBuffer&) const override; |
| 54 size_t onContextSize(const ContextRec&) const override; | 52 size_t onContextSize(const ContextRec&) const override; |
| 55 Context* onCreateContext(const ContextRec&, void*) const override; | 53 Context* onCreateContext(const ContextRec&, void*) const override; |
| 56 | 54 |
| 57 private: | 55 private: |
| 58 SkRRect fFirst; | 56 SkRRect fFirst; |
| 59 SkRRect fSecond; | 57 SkRRect fSecond; |
| 60 SkScalar fRadius; | 58 SkScalar fRadius; |
| 61 SkScalar fPad; | |
| 62 | 59 |
| 63 friend class SkRRectsGaussianEdgeShader; // for serialization registration s
ystem | 60 friend class SkRRectsGaussianEdgeShader; // for serialization registration s
ystem |
| 64 | 61 |
| 65 typedef SkShader INHERITED; | 62 typedef SkShader INHERITED; |
| 66 }; | 63 }; |
| 67 | 64 |
| 68 //////////////////////////////////////////////////////////////////////////// | 65 //////////////////////////////////////////////////////////////////////////// |
| 69 | 66 |
| 70 #if SK_SUPPORT_GPU | 67 #if SK_SUPPORT_GPU |
| 71 | 68 |
| 72 #include "GrCoordTransform.h" | 69 #include "GrCoordTransform.h" |
| 73 #include "GrFragmentProcessor.h" | 70 #include "GrFragmentProcessor.h" |
| 74 #include "GrInvariantOutput.h" | 71 #include "GrInvariantOutput.h" |
| 75 #include "glsl/GrGLSLFragmentProcessor.h" | 72 #include "glsl/GrGLSLFragmentProcessor.h" |
| 76 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 73 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| 77 #include "glsl/GrGLSLProgramDataManager.h" | 74 #include "glsl/GrGLSLProgramDataManager.h" |
| 78 #include "glsl/GrGLSLUniformHandler.h" | 75 #include "glsl/GrGLSLUniformHandler.h" |
| 79 #include "SkGr.h" | 76 #include "SkGr.h" |
| 80 #include "SkGrPriv.h" | 77 #include "SkGrPriv.h" |
| 81 | 78 |
| 82 class RRectsGaussianEdgeFP : public GrFragmentProcessor { | 79 class RRectsGaussianEdgeFP : public GrFragmentProcessor { |
| 83 public: | 80 public: |
| 84 enum Mode { | 81 enum Mode { |
| 85 kCircle_Mode, | 82 kCircle_Mode, |
| 86 kRect_Mode, | 83 kRect_Mode, |
| 87 kSimpleCircular_Mode, | 84 kSimpleCircular_Mode, |
| 88 }; | 85 }; |
| 89 | 86 |
| 90 RRectsGaussianEdgeFP(const SkRRect& first, const SkRRect& second, | 87 RRectsGaussianEdgeFP(const SkRRect& first, const SkRRect& second, SkScalar r
adius) |
| 91 SkScalar radius, SkScalar pad) | |
| 92 : fFirst(first) | 88 : fFirst(first) |
| 93 , fSecond(second) | 89 , fSecond(second) |
| 94 , fRadius(radius) | 90 , fRadius(radius) { |
| 95 , fPad(pad) { | |
| 96 this->initClassID<RRectsGaussianEdgeFP>(); | 91 this->initClassID<RRectsGaussianEdgeFP>(); |
| 97 this->setWillReadFragmentPosition(); | 92 this->setWillReadFragmentPosition(); |
| 98 | 93 |
| 99 fFirstMode = ComputeMode(fFirst); | 94 fFirstMode = ComputeMode(fFirst); |
| 100 fSecondMode = ComputeMode(fSecond); | 95 fSecondMode = ComputeMode(fSecond); |
| 101 } | 96 } |
| 102 | 97 |
| 103 class GLSLRRectsGaussianEdgeFP : public GrGLSLFragmentProcessor { | 98 class GLSLRRectsGaussianEdgeFP : public GrGLSLFragmentProcessor { |
| 104 public: | 99 public: |
| 105 GLSLRRectsGaussianEdgeFP() { } | 100 GLSLRRectsGaussianEdgeFP() { } |
| 106 | 101 |
| 107 // This method emits code so that, for each shape, the distance from the
edge is returned | 102 // This method emits code so that, for each shape, the distance from the
edge is returned |
| 108 // in 'outputName' clamped to 0..1 with positive distance being towards
the center of the | 103 // in 'outputName' clamped to 0..1 with positive distance being towards
the center of the |
| 109 // shape. The distance will have been normalized by the radius. | 104 // shape. The distance will have been normalized by the radius. |
| 110 void emitModeCode(Mode mode, | 105 void emitModeCode(Mode mode, |
| 111 GrGLSLFPFragmentBuilder* fragBuilder, | 106 GrGLSLFPFragmentBuilder* fragBuilder, |
| 112 const char* posName, | 107 const char* posName, |
| 113 const char* sizesName, | 108 const char* sizesName, |
| 114 const char* radiiName, | 109 const char* radiiName, |
| 115 const char* padRadName, | 110 const char* radName, |
| 116 const char* outputName, | 111 const char* outputName, |
| 117 const char indices[2]) { // how to access the params
for the 2 rrects | 112 const char indices[2]) { // how to access the params
for the 2 rrects |
| 118 | 113 |
| 119 // positive distance is towards the center of the circle | 114 // positive distance is towards the center of the circle |
| 120 fragBuilder->codeAppendf("vec2 delta = %s.xy - %s.%s;", | 115 fragBuilder->codeAppendf("vec2 delta = %s.xy - %s.%s;", |
| 121 fragBuilder->fragmentPosition(), posName, i
ndices); | 116 fragBuilder->fragmentPosition(), posName, i
ndices); |
| 122 | 117 |
| 123 switch (mode) { | 118 switch (mode) { |
| 124 case kCircle_Mode: | 119 case kCircle_Mode: |
| 125 fragBuilder->codeAppendf("%s = clamp((%s.%c - length(delta))/%s.
y, 0.0, 1.0);", | 120 fragBuilder->codeAppendf("%s = clamp((%s.%c - length(delta))/%s,
0.0, 1.0);", |
| 126 outputName, sizesName, indices[0], padR
adName); | 121 outputName, sizesName, indices[0], radN
ame); |
| 127 break; | 122 break; |
| 128 case kRect_Mode: | 123 case kRect_Mode: |
| 129 fragBuilder->codeAppendf( | 124 fragBuilder->codeAppendf( |
| 130 "vec2 rectDist = vec2(1.0 - clamp((%s.%c - abs(delta.x))/%s.
y, 0.0, 1.0)," | 125 "vec2 rectDist = vec2(1.0 - clamp((%s.%c - abs(delta.x))/%s,
0.0, 1.0)," |
| 131 "1.0 - clamp((%s.%c - abs(delta.y))/%s.
y, 0.0, 1.0));", | 126 "1.0 - clamp((%s.%c - abs(delta.y))/%s,
0.0, 1.0));", |
| 132 sizesName, indices[0], padRadName, | 127 sizesName, indices[0], radName, |
| 133 sizesName, indices[1], padRadName); | 128 sizesName, indices[1], radName); |
| 134 fragBuilder->codeAppendf("%s = 1.0 - length(rectDist);", outputN
ame); | 129 fragBuilder->codeAppendf("%s = 1.0 - length(rectDist);", outputN
ame); |
| 135 break; | 130 break; |
| 136 case kSimpleCircular_Mode: | 131 case kSimpleCircular_Mode: |
| 137 // For the circular round rect we first compute the distance | 132 // For the circular round rect we first compute the distance |
| 138 // to the rect. Then we compute a multiplier that is 1 if the | 133 // to the rect. Then we compute a multiplier that is 1 if the |
| 139 // point is in one of the circular corners. We then compute the | 134 // point is in one of the circular corners. We then compute the |
| 140 // distance from the corner and then use the multiplier to mask | 135 // distance from the corner and then use the multiplier to mask |
| 141 // between the two distances. | 136 // between the two distances. |
| 142 fragBuilder->codeAppendf("float xDist = clamp((%s.%c - abs(delta
.x))/%s.y," | 137 fragBuilder->codeAppendf("float xDist = clamp((%s.%c - abs(delta
.x))/%s," |
| 143 " 0.0, 1.0);", | 138 " 0.0, 1.0);", |
| 144 sizesName, indices[0], padRadName); | 139 sizesName, indices[0], radName); |
| 145 fragBuilder->codeAppendf("float yDist = clamp((%s.%c - abs(delta
.y))/%s.y," | 140 fragBuilder->codeAppendf("float yDist = clamp((%s.%c - abs(delta
.y))/%s," |
| 146 "0.0, 1.0);", | 141 "0.0, 1.0);", |
| 147 sizesName, indices[1], padRadName); | 142 sizesName, indices[1], radName); |
| 148 fragBuilder->codeAppend("float rectDist = min(xDist, yDist);"); | 143 fragBuilder->codeAppend("float rectDist = min(xDist, yDist);"); |
| 149 | 144 |
| 150 fragBuilder->codeAppendf("vec2 cornerCenter = %s.%s - %s.%s;", | 145 fragBuilder->codeAppendf("vec2 cornerCenter = %s.%s - %s.%s;", |
| 151 sizesName, indices, radiiName, indices)
; | 146 sizesName, indices, radiiName, indices)
; |
| 152 fragBuilder->codeAppend("delta = vec2(abs(delta.x) - cornerCente
r.x," | 147 fragBuilder->codeAppend("delta = vec2(abs(delta.x) - cornerCente
r.x," |
| 153 "abs(delta.y) - cornerCente
r.y);"); | 148 "abs(delta.y) - cornerCente
r.y);"); |
| 154 fragBuilder->codeAppendf("xDist = %s.%c - abs(delta.x);", radiiN
ame, indices[0]); | 149 fragBuilder->codeAppendf("xDist = %s.%c - abs(delta.x);", radiiN
ame, indices[0]); |
| 155 fragBuilder->codeAppendf("yDist = %s.%c - abs(delta.y);", radiiN
ame, indices[1]); | 150 fragBuilder->codeAppendf("yDist = %s.%c - abs(delta.y);", radiiN
ame, indices[1]); |
| 156 fragBuilder->codeAppend("float cornerDist = min(xDist, yDist);")
; | 151 fragBuilder->codeAppend("float cornerDist = min(xDist, yDist);")
; |
| 157 fragBuilder->codeAppend("float multiplier = step(0.0, cornerDist
);"); | 152 fragBuilder->codeAppend("float multiplier = step(0.0, cornerDist
);"); |
| 158 | 153 |
| 159 fragBuilder->codeAppendf("delta += %s.%s;", radiiName, indices); | 154 fragBuilder->codeAppendf("delta += %s.%s;", radiiName, indices); |
| 160 | 155 |
| 161 fragBuilder->codeAppendf("cornerDist = clamp((2.0 * %s.%c - leng
th(delta))/%s.y," | 156 fragBuilder->codeAppendf("cornerDist = clamp((2.0 * %s.%c - leng
th(delta))/%s," |
| 162 "0.0, 1.0);", | 157 "0.0, 1.0);", |
| 163 radiiName, indices[0], padRadName); | 158 radiiName, indices[0], radName); |
| 164 | 159 |
| 165 fragBuilder->codeAppendf("%s = (multiplier * cornerDist) +" | 160 fragBuilder->codeAppendf("%s = (multiplier * cornerDist) +" |
| 166 "((1.0-multiplier) * rectDist);", | 161 "((1.0-multiplier) * rectDist);", |
| 167 outputName); | 162 outputName); |
| 168 break; | 163 break; |
| 169 } | 164 } |
| 170 } | 165 } |
| 171 | 166 |
| 172 void emitCode(EmitArgs& args) override { | 167 void emitCode(EmitArgs& args) override { |
| 173 const RRectsGaussianEdgeFP& fp = args.fFp.cast<RRectsGaussianEdgeFP>
(); | 168 const RRectsGaussianEdgeFP& fp = args.fFp.cast<RRectsGaussianEdgeFP>
(); |
| 174 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; | 169 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; |
| 175 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | 170 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
| 176 | 171 |
| 177 const char* positionsUniName = nullptr; | 172 const char* positionsUniName = nullptr; |
| 178 fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 173 fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| 179 kVec4f_GrSLType, kDefault
_GrSLPrecision, | 174 kVec4f_GrSLType, kDefault
_GrSLPrecision, |
| 180 "Positions", &positionsUn
iName); | 175 "Positions", &positionsUn
iName); |
| 181 const char* sizesUniName = nullptr; | 176 const char* sizesUniName = nullptr; |
| 182 fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 177 fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| 183 kVec4f_GrSLType, kDefault_GrS
LPrecision, | 178 kVec4f_GrSLType, kDefault_GrS
LPrecision, |
| 184 "Sizes", &sizesUniName); | 179 "Sizes", &sizesUniName); |
| 185 const char* radiiUniName = nullptr; | 180 const char* radiiUniName = nullptr; |
| 186 if (fp.fFirstMode == kSimpleCircular_Mode || fp.fSecondMode == kSimp
leCircular_Mode) { | 181 if (fp.fFirstMode == kSimpleCircular_Mode || fp.fSecondMode == kSimp
leCircular_Mode) { |
| 187 fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 182 fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| 188 kVec4f_GrSLType, kDefault
_GrSLPrecision, | 183 kVec4f_GrSLType, kDefault
_GrSLPrecision, |
| 189 "Radii", &radiiUniName); | 184 "Radii", &radiiUniName); |
| 190 } | 185 } |
| 191 const char* padRadUniName = nullptr; | 186 const char* radUniName = nullptr; |
| 192 fPadRadUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 187 fRadiusUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| 193 kVec2f_GrSLType, kDefault_Gr
SLPrecision, | 188 kFloat_GrSLType, kDefault_Gr
SLPrecision, |
| 194 "PadRad", &padRadUniName); | 189 "Radius", &radUniName); |
| 195 | 190 |
| 196 fragBuilder->codeAppend("float firstDist;"); | 191 fragBuilder->codeAppend("float firstDist;"); |
| 197 fragBuilder->codeAppend("{"); | 192 fragBuilder->codeAppend("{"); |
| 198 this->emitModeCode(fp.firstMode(), fragBuilder, | 193 this->emitModeCode(fp.firstMode(), fragBuilder, |
| 199 positionsUniName, sizesUniName, radiiUniName, | 194 positionsUniName, sizesUniName, radiiUniName, |
| 200 padRadUniName, "firstDist", "xy"); | 195 radUniName, "firstDist", "xy"); |
| 201 fragBuilder->codeAppend("}"); | 196 fragBuilder->codeAppend("}"); |
| 202 | 197 |
| 203 fragBuilder->codeAppend("float secondDist;"); | 198 fragBuilder->codeAppend("float secondDist;"); |
| 204 fragBuilder->codeAppend("{"); | 199 fragBuilder->codeAppend("{"); |
| 205 this->emitModeCode(fp.secondMode(), fragBuilder, | 200 this->emitModeCode(fp.secondMode(), fragBuilder, |
| 206 positionsUniName, sizesUniName, radiiUniName, | 201 positionsUniName, sizesUniName, radiiUniName, |
| 207 padRadUniName, "secondDist", "zw"); | 202 radUniName, "secondDist", "zw"); |
| 208 fragBuilder->codeAppend("}"); | 203 fragBuilder->codeAppend("}"); |
| 209 | 204 |
| 210 fragBuilder->codeAppendf("float dist = %s.y * firstDist * secondDist
;", | 205 fragBuilder->codeAppendf("float dist = %s * firstDist * secondDist;"
, radUniName); |
| 211 padRadUniName); | |
| 212 | 206 |
| 213 // Finally use the distance to apply the Gaussian edge | 207 // Finally use the distance to apply the Gaussian edge |
| 214 // TODO: we undo the multiply by the radius here - we should just sk
ip both | 208 // TODO: we undo the multiply by the radius here - we should just sk
ip both |
| 215 fragBuilder->codeAppendf("float factor = 1.0 - clamp((dist - %s.x)/%
s.y, 0.0, 1.0);", | 209 fragBuilder->codeAppendf("float factor = 1.0 - clamp(dist/%s, 0.0, 1
.0);", radUniName); |
| 216 padRadUniName, padRadUniName); | |
| 217 fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.01
8;"); | 210 fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.01
8;"); |
| 218 fragBuilder->codeAppendf("%s = vec4(%s.rgb, factor);", | 211 fragBuilder->codeAppendf("%s = factor*%s;", |
| 219 args.fOutputColor, args.fInputColor); | 212 args.fOutputColor, args.fInputColor); |
| 220 } | 213 } |
| 221 | 214 |
| 222 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 215 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
| 223 GrProcessorKeyBuilder* b) { | 216 GrProcessorKeyBuilder* b) { |
| 224 const RRectsGaussianEdgeFP& fp = proc.cast<RRectsGaussianEdgeFP>(); | 217 const RRectsGaussianEdgeFP& fp = proc.cast<RRectsGaussianEdgeFP>(); |
| 225 | 218 |
| 226 b->add32(fp.firstMode() | (fp.secondMode() << 4)); | 219 b->add32(fp.firstMode() | (fp.secondMode() << 4)); |
| 227 } | 220 } |
| 228 | 221 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 249 edgeFP.secondMode() == kSimpleCircular_Mode) { | 242 edgeFP.secondMode() == kSimpleCircular_Mode) { |
| 250 // This is a bit of overkill since fX should equal fY for both r
ound rects but it | 243 // This is a bit of overkill since fX should equal fY for both r
ound rects but it |
| 251 // makes the shader code simpler. | 244 // makes the shader code simpler. |
| 252 pdman.set4f(fRadiiUni, | 245 pdman.set4f(fRadiiUni, |
| 253 0.5f * first.getSimpleRadii().fX, | 246 0.5f * first.getSimpleRadii().fX, |
| 254 0.5f * first.getSimpleRadii().fY, | 247 0.5f * first.getSimpleRadii().fY, |
| 255 0.5f * second.getSimpleRadii().fX, | 248 0.5f * second.getSimpleRadii().fX, |
| 256 0.5f * second.getSimpleRadii().fY); | 249 0.5f * second.getSimpleRadii().fY); |
| 257 } | 250 } |
| 258 | 251 |
| 259 pdman.set2f(fPadRadUni, edgeFP.pad(), edgeFP.radius()); | 252 pdman.set1f(fRadiusUni, edgeFP.radius()); |
| 260 } | 253 } |
| 261 | 254 |
| 262 private: | 255 private: |
| 263 // The centers of the two round rects (x1, y1, x2, y2) | 256 // The centers of the two round rects (x1, y1, x2, y2) |
| 264 GrGLSLProgramDataManager::UniformHandle fPositionsUni; | 257 GrGLSLProgramDataManager::UniformHandle fPositionsUni; |
| 265 | 258 |
| 266 // The half widths and half heights of the two round rects (w1/2, h1/2,
w2/2, h2/2) | 259 // The half widths and half heights of the two round rects (w1/2, h1/2,
w2/2, h2/2) |
| 267 // For circles we still upload both width & height to simplify things | 260 // For circles we still upload both width & height to simplify things |
| 268 GrGLSLProgramDataManager::UniformHandle fSizesUni; | 261 GrGLSLProgramDataManager::UniformHandle fSizesUni; |
| 269 | 262 |
| 270 // The half corner radii of the two round rects (rx1/2, ry1/2, rx2/2, ry
2/2) | 263 // The half corner radii of the two round rects (rx1/2, ry1/2, rx2/2, ry
2/2) |
| 271 // We upload both the x&y radii (although they are currently always the
same) to make | 264 // We upload both the x&y radii (although they are currently always the
same) to make |
| 272 // the indexing in the shader code simpler. In some future world we coul
d also support | 265 // the indexing in the shader code simpler. In some future world we coul
d also support |
| 273 // non-circular corner round rects & ellipses. | 266 // non-circular corner round rects & ellipses. |
| 274 GrGLSLProgramDataManager::UniformHandle fRadiiUni; | 267 GrGLSLProgramDataManager::UniformHandle fRadiiUni; |
| 275 | 268 |
| 276 // The pad and radius parameters (padding, radius) | 269 // The radius parameters (radius) |
| 277 GrGLSLProgramDataManager::UniformHandle fPadRadUni; | 270 GrGLSLProgramDataManager::UniformHandle fRadiusUni; |
| 278 | 271 |
| 279 typedef GrGLSLFragmentProcessor INHERITED; | 272 typedef GrGLSLFragmentProcessor INHERITED; |
| 280 }; | 273 }; |
| 281 | 274 |
| 282 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { | 275 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { |
| 283 GLSLRRectsGaussianEdgeFP::GenKey(*this, caps, b); | 276 GLSLRRectsGaussianEdgeFP::GenKey(*this, caps, b); |
| 284 } | 277 } |
| 285 | 278 |
| 286 const char* name() const override { return "RRectsGaussianEdgeFP"; } | 279 const char* name() const override { return "RRectsGaussianEdgeFP"; } |
| 287 | 280 |
| 288 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 281 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
| 289 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | 282 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
| 290 } | 283 } |
| 291 | 284 |
| 292 const SkRRect& first() const { return fFirst; } | 285 const SkRRect& first() const { return fFirst; } |
| 293 Mode firstMode() const { return fFirstMode; } | 286 Mode firstMode() const { return fFirstMode; } |
| 294 const SkRRect& second() const { return fSecond; } | 287 const SkRRect& second() const { return fSecond; } |
| 295 Mode secondMode() const { return fSecondMode; } | 288 Mode secondMode() const { return fSecondMode; } |
| 296 SkScalar radius() const { return fRadius; } | 289 SkScalar radius() const { return fRadius; } |
| 297 SkScalar pad() const { return fPad; } | |
| 298 | 290 |
| 299 private: | 291 private: |
| 300 static Mode ComputeMode(const SkRRect& rr) { | 292 static Mode ComputeMode(const SkRRect& rr) { |
| 301 if (rr.isCircle()) { | 293 if (rr.isCircle()) { |
| 302 return kCircle_Mode; | 294 return kCircle_Mode; |
| 303 } else if (rr.isRect()) { | 295 } else if (rr.isRect()) { |
| 304 return kRect_Mode; | 296 return kRect_Mode; |
| 305 } else { | 297 } else { |
| 306 SkASSERT(rr.isSimpleCircular()); | 298 SkASSERT(rr.isSimpleCircular()); |
| 307 return kSimpleCircular_Mode; | 299 return kSimpleCircular_Mode; |
| 308 } | 300 } |
| 309 } | 301 } |
| 310 | 302 |
| 311 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { | 303 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { |
| 312 return new GLSLRRectsGaussianEdgeFP; | 304 return new GLSLRRectsGaussianEdgeFP; |
| 313 } | 305 } |
| 314 | 306 |
| 315 bool onIsEqual(const GrFragmentProcessor& proc) const override { | 307 bool onIsEqual(const GrFragmentProcessor& proc) const override { |
| 316 const RRectsGaussianEdgeFP& edgeFP = proc.cast<RRectsGaussianEdgeFP>(); | 308 const RRectsGaussianEdgeFP& edgeFP = proc.cast<RRectsGaussianEdgeFP>(); |
| 317 return fFirst == edgeFP.fFirst && fSecond == edgeFP.fSecond && | 309 return fFirst == edgeFP.fFirst && |
| 318 fRadius == edgeFP.fRadius && fPad == edgeFP.fPad; | 310 fSecond == edgeFP.fSecond && |
| 311 fRadius == edgeFP.fRadius; |
| 319 } | 312 } |
| 320 | 313 |
| 321 SkRRect fFirst; | 314 SkRRect fFirst; |
| 322 Mode fFirstMode; | 315 Mode fFirstMode; |
| 323 SkRRect fSecond; | 316 SkRRect fSecond; |
| 324 Mode fSecondMode; | 317 Mode fSecondMode; |
| 325 SkScalar fRadius; | 318 SkScalar fRadius; |
| 326 SkScalar fPad; | |
| 327 | 319 |
| 328 typedef GrFragmentProcessor INHERITED; | 320 typedef GrFragmentProcessor INHERITED; |
| 329 }; | 321 }; |
| 330 | 322 |
| 331 //////////////////////////////////////////////////////////////////////////// | 323 //////////////////////////////////////////////////////////////////////////// |
| 332 | 324 |
| 333 sk_sp<GrFragmentProcessor> SkRRectsGaussianEdgeShaderImpl::asFragmentProcessor( | 325 sk_sp<GrFragmentProcessor> SkRRectsGaussianEdgeShaderImpl::asFragmentProcessor( |
| 334 const AsFPAr
gs& args) const { | 326 const AsFPAr
gs& args) const { |
| 335 return sk_make_sp<RRectsGaussianEdgeFP>(fFirst, fSecond, fRadius, fPad); | 327 return sk_make_sp<RRectsGaussianEdgeFP>(fFirst, fSecond, fRadius); |
| 336 } | 328 } |
| 337 | 329 |
| 338 #endif | 330 #endif |
| 339 | 331 |
| 340 //////////////////////////////////////////////////////////////////////////// | 332 //////////////////////////////////////////////////////////////////////////// |
| 341 | 333 |
| 342 SkRRectsGaussianEdgeShaderImpl::GaussianEdgeShaderContext::GaussianEdgeShaderCon
text( | 334 SkRRectsGaussianEdgeShaderImpl::GaussianEdgeShaderContext::GaussianEdgeShaderCon
text( |
| 343 const SkRRectsGaussianEdgeSh
aderImpl& shader, | 335 const SkRRectsGaussianEdgeSh
aderImpl& shader, |
| 344 const ContextRec& rec) | 336 const ContextRec& rec) |
| 345 : INHERITED(shader, rec) { | 337 : INHERITED(shader, rec) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 373 | 365 |
| 374 buf.readRect(&rect1); | 366 buf.readRect(&rect1); |
| 375 SkScalar xRad1 = buf.readScalar(); | 367 SkScalar xRad1 = buf.readScalar(); |
| 376 SkScalar yRad1 = buf.readScalar(); | 368 SkScalar yRad1 = buf.readScalar(); |
| 377 | 369 |
| 378 buf.readRect(&rect2); | 370 buf.readRect(&rect2); |
| 379 SkScalar xRad2 = buf.readScalar(); | 371 SkScalar xRad2 = buf.readScalar(); |
| 380 SkScalar yRad2 = buf.readScalar(); | 372 SkScalar yRad2 = buf.readScalar(); |
| 381 | 373 |
| 382 SkScalar radius = buf.readScalar(); | 374 SkScalar radius = buf.readScalar(); |
| 383 SkScalar pad = buf.readScalar(); | |
| 384 | 375 |
| 385 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(SkRRect::MakeRectXY(rect1,
xRad1, yRad1), | 376 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(SkRRect::MakeRectXY(rect1,
xRad1, yRad1), |
| 386 SkRRect::MakeRectXY(rect2,
xRad2, yRad2), | 377 SkRRect::MakeRectXY(rect2,
xRad2, yRad2), |
| 387 radius, pad); | 378 radius); |
| 388 } | 379 } |
| 389 | 380 |
| 390 void SkRRectsGaussianEdgeShaderImpl::flatten(SkWriteBuffer& buf) const { | 381 void SkRRectsGaussianEdgeShaderImpl::flatten(SkWriteBuffer& buf) const { |
| 391 INHERITED::flatten(buf); | 382 INHERITED::flatten(buf); |
| 392 | 383 |
| 393 SkASSERT(fFirst.isRect() || fFirst.isCircle() || fFirst.isSimpleCircular()); | 384 SkASSERT(fFirst.isRect() || fFirst.isCircle() || fFirst.isSimpleCircular()); |
| 394 buf.writeRect(fFirst.rect()); | 385 buf.writeRect(fFirst.rect()); |
| 395 const SkVector& radii1 = fFirst.getSimpleRadii(); | 386 const SkVector& radii1 = fFirst.getSimpleRadii(); |
| 396 buf.writeScalar(radii1.fX); | 387 buf.writeScalar(radii1.fX); |
| 397 buf.writeScalar(radii1.fY); | 388 buf.writeScalar(radii1.fY); |
| 398 | 389 |
| 399 SkASSERT(fSecond.isRect() || fSecond.isCircle() || fSecond.isSimpleCircular(
)); | 390 SkASSERT(fSecond.isRect() || fSecond.isCircle() || fSecond.isSimpleCircular(
)); |
| 400 buf.writeRect(fSecond.rect()); | 391 buf.writeRect(fSecond.rect()); |
| 401 const SkVector& radii2 = fSecond.getSimpleRadii(); | 392 const SkVector& radii2 = fSecond.getSimpleRadii(); |
| 402 buf.writeScalar(radii2.fX); | 393 buf.writeScalar(radii2.fX); |
| 403 buf.writeScalar(radii2.fY); | 394 buf.writeScalar(radii2.fY); |
| 404 | 395 |
| 405 buf.writeScalar(fRadius); | 396 buf.writeScalar(fRadius); |
| 406 buf.writeScalar(fPad); | |
| 407 } | 397 } |
| 408 | 398 |
| 409 size_t SkRRectsGaussianEdgeShaderImpl::onContextSize(const ContextRec& rec) cons
t { | 399 size_t SkRRectsGaussianEdgeShaderImpl::onContextSize(const ContextRec& rec) cons
t { |
| 410 return sizeof(GaussianEdgeShaderContext); | 400 return sizeof(GaussianEdgeShaderContext); |
| 411 } | 401 } |
| 412 | 402 |
| 413 SkShader::Context* SkRRectsGaussianEdgeShaderImpl::onCreateContext(const Context
Rec& rec, | 403 SkShader::Context* SkRRectsGaussianEdgeShaderImpl::onCreateContext(const Context
Rec& rec, |
| 414 void* storage
) const { | 404 void* storage
) const { |
| 415 return new (storage) GaussianEdgeShaderContext(*this, rec); | 405 return new (storage) GaussianEdgeShaderContext(*this, rec); |
| 416 } | 406 } |
| 417 | 407 |
| 418 /////////////////////////////////////////////////////////////////////////////// | 408 /////////////////////////////////////////////////////////////////////////////// |
| 419 | 409 |
| 420 sk_sp<SkShader> SkRRectsGaussianEdgeShader::Make(const SkRRect& first, | 410 sk_sp<SkShader> SkRRectsGaussianEdgeShader::Make(const SkRRect& first, |
| 421 const SkRRect& second, | 411 const SkRRect& second, |
| 422 SkScalar radius, | 412 SkScalar radius) { |
| 423 SkScalar pad) { | |
| 424 if ((!first.isRect() && !first.isCircle() && !first.isSimpleCircular()) ||
| 413 if ((!first.isRect() && !first.isCircle() && !first.isSimpleCircular()) ||
|
| 425 (!second.isRect() && !second.isCircle() && !second.isSimpleCircular()))
{ | 414 (!second.isRect() && !second.isCircle() && !second.isSimpleCircular()))
{ |
| 426 // we only deal with the shapes where the x & y radii are equal | 415 // we only deal with the shapes where the x & y radii are equal |
| 427 // and the same for all four corners | 416 // and the same for all four corners |
| 428 return nullptr; | 417 return nullptr; |
| 429 } | 418 } |
| 430 | 419 |
| 431 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(first, second, radius, pad
); | 420 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(first, second, radius); |
| 432 } | 421 } |
| 433 | 422 |
| 434 /////////////////////////////////////////////////////////////////////////////// | 423 /////////////////////////////////////////////////////////////////////////////// |
| 435 | 424 |
| 436 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkRRectsGaussianEdgeShader) | 425 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkRRectsGaussianEdgeShader) |
| 437 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRRectsGaussianEdgeShaderImpl) | 426 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRRectsGaussianEdgeShaderImpl) |
| 438 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 427 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| 439 | 428 |
| 440 /////////////////////////////////////////////////////////////////////////////// | 429 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |