Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "GrRRectEffect.h" | 8 #include "GrRRectEffect.h" |
| 9 | 9 |
| 10 #include "gl/GrGLEffect.h" | 10 #include "gl/GrGLEffect.h" |
| 11 #include "gl/GrGLSL.h" | 11 #include "gl/GrGLSL.h" |
| 12 #include "GrTBackendEffectFactory.h" | 12 #include "GrTBackendEffectFactory.h" |
| 13 | 13 |
| 14 #include "SkRRect.h" | 14 #include "SkRRect.h" |
| 15 | 15 |
| 16 using namespace GrRRectEffect; | 16 class GLCircularRRectEffect; |
| 17 | 17 |
| 18 class GLRRectEffect; | 18 class CircularRRectEffect : public GrEffect { |
| 19 | |
| 20 class RRectEffect : public GrEffect { | |
| 21 public: | 19 public: |
| 22 // This effect only supports circular corner rrects where the radius is >= k RadiusMin. | 20 // This effect only supports circular corner rrects where the radius is >= k RadiusMin. |
| 23 static const SkScalar kRadiusMin; | 21 static const SkScalar kRadiusMin; |
| 24 | 22 |
| 25 enum CornerFlags { | 23 enum CornerFlags { |
| 26 kTopLeft_CornerFlag = (1 << SkRRect::kUpperLeft_Corner), | 24 kTopLeft_CornerFlag = (1 << SkRRect::kUpperLeft_Corner), |
| 27 kTopRight_CornerFlag = (1 << SkRRect::kUpperRight_Corner), | 25 kTopRight_CornerFlag = (1 << SkRRect::kUpperRight_Corner), |
| 28 kBottomRight_CornerFlag = (1 << SkRRect::kLowerRight_Corner), | 26 kBottomRight_CornerFlag = (1 << SkRRect::kLowerRight_Corner), |
| 29 kBottomLeft_CornerFlag = (1 << SkRRect::kLowerLeft_Corner), | 27 kBottomLeft_CornerFlag = (1 << SkRRect::kLowerLeft_Corner), |
| 30 | 28 |
| 31 kLeft_CornerFlags = kTopLeft_CornerFlag | kBottomLeft_CornerFlag, | 29 kLeft_CornerFlags = kTopLeft_CornerFlag | kBottomLeft_CornerFlag, |
| 32 kTop_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag, | 30 kTop_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag, |
| 33 kRight_CornerFlags = kTopRight_CornerFlag | kBottomRight_CornerFlag, | 31 kRight_CornerFlags = kTopRight_CornerFlag | kBottomRight_CornerFlag, |
| 34 kBottom_CornerFlags = kBottomLeft_CornerFlag | kBottomRight_CornerFlag, | 32 kBottom_CornerFlags = kBottomLeft_CornerFlag | kBottomRight_CornerFlag, |
| 35 | 33 |
| 36 kAll_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag | | 34 kAll_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag | |
| 37 kBottomLeft_CornerFlag | kBottomRight_CornerFlag, | 35 kBottomLeft_CornerFlag | kBottomRight_CornerFlag, |
| 38 | 36 |
| 39 }; | 37 }; |
| 40 | 38 |
| 41 // The flags are used to indicate which corners are circluar (unflagged corn ers are assumed to | 39 // The flags are used to indicate which corners are circluar (unflagged corn ers are assumed to |
| 42 // be square). | 40 // be square). |
| 43 static GrEffectRef* Create(GrEffectEdgeType, uint32_t circularCornerFlags, c onst SkRRect&); | 41 static GrEffectRef* Create(GrEffectEdgeType, uint32_t circularCornerFlags, c onst SkRRect&); |
| 44 | 42 |
| 45 virtual ~RRectEffect() {}; | 43 virtual ~CircularRRectEffect() {}; |
| 46 static const char* Name() { return "RRect"; } | 44 static const char* Name() { return "CircularRRect"; } |
| 47 | 45 |
| 48 const SkRRect& getRRect() const { return fRRect; } | 46 const SkRRect& getRRect() const { return fRRect; } |
| 49 | 47 |
| 50 uint32_t getCircularCornerFlags() const { return fCircularCornerFlags; } | 48 uint32_t getCircularCornerFlags() const { return fCircularCornerFlags; } |
| 51 | 49 |
| 52 GrEffectEdgeType getEdgeType() const { return fEdgeType; } | 50 GrEffectEdgeType getEdgeType() const { return fEdgeType; } |
| 53 | 51 |
| 54 typedef GLRRectEffect GLEffect; | 52 typedef GLCircularRRectEffect GLEffect; |
| 55 | 53 |
| 56 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; | 54 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; |
| 57 | 55 |
| 58 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | 56 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
| 59 | 57 |
| 60 private: | 58 private: |
| 61 RRectEffect(GrEffectEdgeType, uint32_t circularCornerFlags, const SkRRect&); | 59 CircularRRectEffect(GrEffectEdgeType, uint32_t circularCornerFlags, const Sk RRect&); |
| 62 | 60 |
| 63 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; | 61 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; |
| 64 | 62 |
| 65 SkRRect fRRect; | 63 SkRRect fRRect; |
| 66 GrEffectEdgeType fEdgeType; | 64 GrEffectEdgeType fEdgeType; |
| 67 uint32_t fCircularCornerFlags; | 65 uint32_t fCircularCornerFlags; |
| 68 | 66 |
| 69 GR_DECLARE_EFFECT_TEST; | 67 GR_DECLARE_EFFECT_TEST; |
| 70 | 68 |
| 71 typedef GrEffect INHERITED; | 69 typedef GrEffect INHERITED; |
| 72 }; | 70 }; |
| 73 | 71 |
| 74 const SkScalar RRectEffect::kRadiusMin = 0.5f; | 72 const SkScalar CircularRRectEffect::kRadiusMin = 0.5f; |
| 75 | 73 |
| 76 GrEffectRef* RRectEffect::Create(GrEffectEdgeType edgeType, | 74 GrEffectRef* CircularRRectEffect::Create(GrEffectEdgeType edgeType, |
| 77 uint32_t circularCornerFlags, | 75 uint32_t circularCornerFlags, |
| 78 const SkRRect& rrect) { | 76 const SkRRect& rrect) { |
| 79 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge Type == edgeType); | 77 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge Type == edgeType); |
| 80 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, | 78 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircularRRectEffect, |
| 81 (edgeType, circularCornerF lags, rrect)))); | 79 (edgeType, circularCornerF lags, rrect)))); |
| 82 } | 80 } |
| 83 | 81 |
| 84 void RRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlag s) const { | 82 void CircularRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* v alidFlags) const { |
| 85 *validFlags = 0; | 83 *validFlags = 0; |
| 86 } | 84 } |
| 87 | 85 |
| 88 const GrBackendEffectFactory& RRectEffect::getFactory() const { | 86 const GrBackendEffectFactory& CircularRRectEffect::getFactory() const { |
| 89 return GrTBackendEffectFactory<RRectEffect>::getInstance(); | 87 return GrTBackendEffectFactory<CircularRRectEffect>::getInstance(); |
| 90 } | 88 } |
| 91 | 89 |
| 92 RRectEffect::RRectEffect(GrEffectEdgeType edgeType, uint32_t circularCornerFlags , | 90 CircularRRectEffect::CircularRRectEffect(GrEffectEdgeType edgeType, uint32_t cir cularCornerFlags, |
| 93 const SkRRect& rrect) | 91 const SkRRect& rrect) |
| 94 : fRRect(rrect) | 92 : fRRect(rrect) |
| 95 , fEdgeType(edgeType) | 93 , fEdgeType(edgeType) |
| 96 , fCircularCornerFlags(circularCornerFlags) { | 94 , fCircularCornerFlags(circularCornerFlags) { |
| 97 this->setWillReadFragmentPosition(); | 95 this->setWillReadFragmentPosition(); |
| 98 } | 96 } |
| 99 | 97 |
| 100 bool RRectEffect::onIsEqual(const GrEffect& other) const { | 98 bool CircularRRectEffect::onIsEqual(const GrEffect& other) const { |
| 101 const RRectEffect& rre = CastEffect<RRectEffect>(other); | 99 const CircularRRectEffect& crre = CastEffect<CircularRRectEffect>(other); |
| 102 // type is derived from fRRect, so no need to check it. | 100 // The corner flags are derived from fRRect, so no need to check them. |
| 103 return fEdgeType == rre.fEdgeType && fRRect == rre.fRRect; | 101 return fEdgeType == crre.fEdgeType && fRRect == crre.fRRect; |
| 104 } | 102 } |
| 105 | 103 |
| 106 ////////////////////////////////////////////////////////////////////////////// | 104 ////////////////////////////////////////////////////////////////////////////// |
| 107 | 105 |
| 108 GR_DEFINE_EFFECT_TEST(RRectEffect); | 106 GR_DEFINE_EFFECT_TEST(CircularRRectEffect); |
| 109 | 107 |
| 110 GrEffectRef* RRectEffect::TestCreate(SkRandom* random, | 108 GrEffectRef* CircularRRectEffect::TestCreate(SkRandom* random, |
| 111 GrContext*, | 109 GrContext*, |
| 112 const GrDrawTargetCaps& caps, | 110 const GrDrawTargetCaps& caps, |
| 113 GrTexture*[]) { | 111 GrTexture*[]) { |
| 114 SkScalar w = random->nextRangeScalar(20.f, 1000.f); | 112 SkScalar w = random->nextRangeScalar(20.f, 1000.f); |
| 115 SkScalar h = random->nextRangeScalar(20.f, 1000.f); | 113 SkScalar h = random->nextRangeScalar(20.f, 1000.f); |
| 116 SkScalar r = random->nextRangeF(kRadiusMin, 9.f); | 114 SkScalar r = random->nextRangeF(kRadiusMin, 9.f); |
| 117 SkRRect rrect; | 115 SkRRect rrect; |
| 118 rrect.setRectXY(SkRect::MakeWH(w, h), r, r); | 116 rrect.setRectXY(SkRect::MakeWH(w, h), r, r); |
| 119 GrEffectRef* effect; | 117 GrEffectRef* effect; |
| 120 do { | 118 do { |
| 121 GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectE dgeTypeCnt); | 119 GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectE dgeTypeCnt); |
| 122 effect = GrRRectEffect::Create(et, rrect); | 120 effect = GrRRectEffect::Create(et, rrect); |
| 123 } while (NULL == effect); | 121 } while (NULL == effect); |
| 124 return effect; | 122 return effect; |
| 125 } | 123 } |
| 126 | 124 |
| 127 ////////////////////////////////////////////////////////////////////////////// | 125 ////////////////////////////////////////////////////////////////////////////// |
| 128 | 126 |
| 129 class GLRRectEffect : public GrGLEffect { | 127 class GLCircularRRectEffect : public GrGLEffect { |
| 130 public: | 128 public: |
| 131 GLRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | 129 GLCircularRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
| 132 | 130 |
| 133 virtual void emitCode(GrGLShaderBuilder* builder, | 131 virtual void emitCode(GrGLShaderBuilder* builder, |
| 134 const GrDrawEffect& drawEffect, | 132 const GrDrawEffect& drawEffect, |
| 135 EffectKey key, | 133 EffectKey key, |
| 136 const char* outputColor, | 134 const char* outputColor, |
| 137 const char* inputColor, | 135 const char* inputColor, |
| 138 const TransformedCoordsArray&, | 136 const TransformedCoordsArray&, |
| 139 const TextureSamplerArray&) SK_OVERRIDE; | 137 const TextureSamplerArray&) SK_OVERRIDE; |
| 140 | 138 |
| 141 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); | 139 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); |
| 142 | 140 |
| 143 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; | 141 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; |
| 144 | 142 |
| 145 private: | 143 private: |
| 146 GrGLUniformManager::UniformHandle fInnerRectUniform; | 144 GrGLUniformManager::UniformHandle fInnerRectUniform; |
| 147 GrGLUniformManager::UniformHandle fRadiusPlusHalfUniform; | 145 GrGLUniformManager::UniformHandle fRadiusPlusHalfUniform; |
| 148 SkRRect fPrevRRect; | 146 SkRRect fPrevRRect; |
| 149 typedef GrGLEffect INHERITED; | 147 typedef GrGLEffect INHERITED; |
| 150 }; | 148 }; |
| 151 | 149 |
| 152 GLRRectEffect::GLRRectEffect(const GrBackendEffectFactory& factory, | 150 GLCircularRRectEffect::GLCircularRRectEffect(const GrBackendEffectFactory& facto ry, |
| 153 const GrDrawEffect& drawEffect) | 151 const GrDrawEffect& drawEffect) |
| 154 : INHERITED (factory) { | 152 : INHERITED (factory) { |
| 155 fPrevRRect.setEmpty(); | 153 fPrevRRect.setEmpty(); |
| 156 } | 154 } |
| 157 | 155 |
| 158 void GLRRectEffect::emitCode(GrGLShaderBuilder* builder, | 156 void GLCircularRRectEffect::emitCode(GrGLShaderBuilder* builder, |
| 159 const GrDrawEffect& drawEffect, | 157 const GrDrawEffect& drawEffect, |
| 160 EffectKey key, | 158 EffectKey key, |
| 161 const char* outputColor, | 159 const char* outputColor, |
| 162 const char* inputColor, | 160 const char* inputColor, |
| 163 const TransformedCoordsArray&, | 161 const TransformedCoordsArray&, |
| 164 const TextureSamplerArray& samplers) { | 162 const TextureSamplerArray& samplers) { |
| 165 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | 163 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect> (); |
| 166 const char *rectName; | 164 const char *rectName; |
| 167 const char *radiusPlusHalfName; | 165 const char *radiusPlusHalfName; |
| 168 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom | 166 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom |
| 169 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has | 167 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has |
| 170 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by | 168 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by |
| 171 // half a pixel. | 169 // half a pixel. |
| 172 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity, | 170 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity, |
| 173 kVec4f_GrSLType, | 171 kVec4f_GrSLType, |
| 174 "innerRect", | 172 "innerRect", |
| 175 &rectName); | 173 &rectName); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 186 // fragments near the other three edges will get the correct AA. Fragments i n the interior of | 184 // fragments near the other three edges will get the correct AA. Fragments i n the interior of |
| 187 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will | 185 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will |
| 188 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. | 186 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. |
| 189 // The code below is a simplified version of the above that performs maxs on the vector | 187 // The code below is a simplified version of the above that performs maxs on the vector |
| 190 // components before computing distances and alpha values so that only one d istance computation | 188 // components before computing distances and alpha values so that only one d istance computation |
| 191 // need be computed to determine the min alpha. | 189 // need be computed to determine the min alpha. |
| 192 // | 190 // |
| 193 // For the cases where one half of the rrect is rectangular we drop one of t he x or y | 191 // For the cases where one half of the rrect is rectangular we drop one of t he x or y |
| 194 // computations, compute a separate rect edge alpha for the rect side, and m ul the two computed | 192 // computations, compute a separate rect edge alpha for the rect side, and m ul the two computed |
| 195 // alphas together. | 193 // alphas together. |
| 196 switch (rre.getCircularCornerFlags()) { | 194 switch (crre.getCircularCornerFlags()) { |
| 197 case RRectEffect::kAll_CornerFlags: | 195 case CircularRRectEffect::kAll_CornerFlags: |
| 198 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); | 196 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); |
| 199 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); | 197 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); |
| 200 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; | 198 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; |
| 201 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0. 0, 1.0);\n", | 199 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0. 0, 1.0);\n", |
| 202 radiusPlusHalfName); | 200 radiusPlusHalfName); |
| 203 break; | 201 break; |
| 204 case RRectEffect::kTopLeft_CornerFlag: | 202 case CircularRRectEffect::kTopLeft_CornerFlag: |
| 205 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n", rectName, fragmentPos); | 203 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n", |
| 204 rectName, fragmentPos); | |
| 206 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", | 205 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", |
| 207 rectName, fragmentPos); | 206 rectName, fragmentPos); |
| 208 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", | 207 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", |
| 209 rectName, fragmentPos); | 208 rectName, fragmentPos); |
| 210 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", | 209 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", |
| 211 radiusPlusHalfName); | 210 radiusPlusHalfName); |
| 212 break; | 211 break; |
| 213 case RRectEffect::kTopRight_CornerFlag: | 212 case CircularRRectEffect::kTopRight_CornerFlag: |
| 214 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n", | 213 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n", |
| 215 fragmentPos, rectName, rectName, fragmentPos) ; | 214 fragmentPos, rectName, rectName, fragmentPos) ; |
| 216 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", | 215 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", |
| 217 fragmentPos, rectName); | 216 fragmentPos, rectName); |
| 218 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", | 217 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", |
| 219 rectName, fragmentPos); | 218 rectName, fragmentPos); |
| 220 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", | 219 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", |
| 221 radiusPlusHalfName); | 220 radiusPlusHalfName); |
| 222 break; | 221 break; |
| 223 case RRectEffect::kBottomRight_CornerFlag: | 222 case CircularRRectEffect::kBottomRight_CornerFlag: |
| 224 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n", | 223 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n", |
| 225 fragmentPos, rectName); | 224 fragmentPos, rectName); |
| 226 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", | 225 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", |
| 227 fragmentPos, rectName); | 226 fragmentPos, rectName); |
| 228 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", | 227 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", |
| 229 fragmentPos, rectName); | 228 fragmentPos, rectName); |
| 230 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * cla mp(%s - length(dxy), 0.0, 1.0);\n", | 229 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * cla mp(%s - length(dxy), 0.0, 1.0);\n", |
| 231 radiusPlusHalfName); | 230 radiusPlusHalfName); |
| 232 break; | 231 break; |
| 233 case RRectEffect::kBottomLeft_CornerFlag: | 232 case CircularRRectEffect::kBottomLeft_CornerFlag: |
| 234 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n", | 233 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n", |
| 235 rectName, fragmentPos, fragmentPos, rectName) ; | 234 rectName, fragmentPos, fragmentPos, rectName) ; |
| 236 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", | 235 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", |
| 237 rectName, fragmentPos); | 236 rectName, fragmentPos); |
| 238 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", | 237 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", |
| 239 fragmentPos, rectName); | 238 fragmentPos, rectName); |
| 240 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * cl amp(%s - length(dxy), 0.0, 1.0);\n", | 239 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * cl amp(%s - length(dxy), 0.0, 1.0);\n", |
| 241 radiusPlusHalfName); | 240 radiusPlusHalfName); |
| 242 break; | 241 break; |
| 243 case RRectEffect::kLeft_CornerFlags: | 242 case CircularRRectEffect::kLeft_CornerFlags: |
| 244 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); | 243 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); |
| 245 builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos , rectName); | 244 builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos , rectName); |
| 246 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d y1)), 0.0);\n"); | 245 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d y1)), 0.0);\n"); |
| 247 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", | 246 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", |
| 248 rectName, fragmentPos); | 247 rectName, fragmentPos); |
| 249 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le ngth(dxy), 0.0, 1.0);\n", | 248 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le ngth(dxy), 0.0, 1.0);\n", |
| 250 radiusPlusHalfName); | 249 radiusPlusHalfName); |
| 251 break; | 250 break; |
| 252 case RRectEffect::kTop_CornerFlags: | 251 case CircularRRectEffect::kTop_CornerFlags: |
| 253 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); | 252 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); |
| 254 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos , rectName); | 253 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos , rectName); |
| 255 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy 0.y), 0.0);\n"); | 254 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy 0.y), 0.0);\n"); |
| 256 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", | 255 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", |
| 257 rectName, fragmentPos); | 256 rectName, fragmentPos); |
| 258 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l ength(dxy), 0.0, 1.0);\n", | 257 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l ength(dxy), 0.0, 1.0);\n", |
| 259 radiusPlusHalfName); | 258 radiusPlusHalfName); |
| 260 break; | 259 break; |
| 261 case RRectEffect::kRight_CornerFlags: | 260 case CircularRRectEffect::kRight_CornerFlags: |
| 262 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f ragmentPos); | 261 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f ragmentPos); |
| 263 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); | 262 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); |
| 264 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1 .y)), 0.0);\n"); | 263 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1 .y)), 0.0);\n"); |
| 265 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", | 264 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", |
| 266 fragmentPos, rectName); | 265 fragmentPos, rectName); |
| 267 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len gth(dxy), 0.0, 1.0);\n", | 266 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len gth(dxy), 0.0, 1.0);\n", |
| 268 radiusPlusHalfName); | 267 radiusPlusHalfName); |
| 269 break; | 268 break; |
| 270 case RRectEffect::kBottom_CornerFlags: | 269 case CircularRRectEffect::kBottom_CornerFlags: |
| 271 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f ragmentPos); | 270 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f ragmentPos); |
| 272 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); | 271 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); |
| 273 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy 1.y), 0.0);\n"); | 272 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy 1.y), 0.0);\n"); |
| 274 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", | 273 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", |
| 275 fragmentPos, rectName); | 274 fragmentPos, rectName); |
| 276 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng th(dxy), 0.0, 1.0);\n", | 275 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng th(dxy), 0.0, 1.0);\n", |
| 277 radiusPlusHalfName); | 276 radiusPlusHalfName); |
| 278 break; | 277 break; |
| 279 } | 278 } |
| 280 | 279 |
| 281 if (kInverseFillAA_GrEffectEdgeType == rre.getEdgeType()) { | 280 if (kInverseFillAA_GrEffectEdgeType == crre.getEdgeType()) { |
| 282 builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); | 281 builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); |
| 283 } | 282 } |
| 284 | 283 |
| 285 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, | 284 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, |
| 286 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); | 285 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); |
| 287 } | 286 } |
| 288 | 287 |
| 289 GrGLEffect::EffectKey GLRRectEffect::GenKey(const GrDrawEffect& drawEffect, cons t GrGLCaps&) { | 288 GrGLEffect::EffectKey GLCircularRRectEffect::GenKey(const GrDrawEffect& drawEffe ct, |
| 290 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | 289 const GrGLCaps&) { |
| 290 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect> (); | |
| 291 GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8); | 291 GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8); |
| 292 return (rre.getCircularCornerFlags() << 3) | rre.getEdgeType(); | 292 return (crre.getCircularCornerFlags() << 3) | crre.getEdgeType(); |
| 293 } | 293 } |
| 294 | 294 |
| 295 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) { | 295 void GLCircularRRectEffect::setData(const GrGLUniformManager& uman, |
| 296 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | 296 const GrDrawEffect& drawEffect) { |
| 297 const SkRRect& rrect = rre.getRRect(); | 297 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect> (); |
| 298 const SkRRect& rrect = crre.getRRect(); | |
| 298 if (rrect != fPrevRRect) { | 299 if (rrect != fPrevRRect) { |
| 299 SkRect rect = rrect.getBounds(); | 300 SkRect rect = rrect.getBounds(); |
| 300 SkScalar radius = 0; | 301 SkScalar radius = 0; |
| 301 switch (rre.getCircularCornerFlags()) { | 302 switch (crre.getCircularCornerFlags()) { |
| 302 case RRectEffect::kAll_CornerFlags: | 303 case CircularRRectEffect::kAll_CornerFlags: |
| 303 SkASSERT(rrect.isSimpleCircular()); | 304 SkASSERT(rrect.isSimpleCircular()); |
| 304 radius = rrect.getSimpleRadii().fX; | 305 radius = rrect.getSimpleRadii().fX; |
| 305 SkASSERT(radius >= RRectEffect::kRadiusMin); | 306 SkASSERT(radius >= CircularRRectEffect::kRadiusMin); |
| 306 rect.inset(radius, radius); | 307 rect.inset(radius, radius); |
| 307 break; | 308 break; |
| 308 case RRectEffect::kTopLeft_CornerFlag: | 309 case CircularRRectEffect::kTopLeft_CornerFlag: |
| 309 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; | 310 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; |
| 310 rect.fLeft += radius; | 311 rect.fLeft += radius; |
| 311 rect.fTop += radius; | 312 rect.fTop += radius; |
| 312 rect.fRight += 0.5f; | 313 rect.fRight += 0.5f; |
| 313 rect.fBottom += 0.5f; | 314 rect.fBottom += 0.5f; |
| 314 break; | 315 break; |
| 315 case RRectEffect::kTopRight_CornerFlag: | 316 case CircularRRectEffect::kTopRight_CornerFlag: |
| 316 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; | 317 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; |
| 317 rect.fLeft -= 0.5; | 318 rect.fLeft -= 0.5; |
| 318 rect.fTop += radius; | 319 rect.fTop += radius; |
| 319 rect.fRight -= radius; | 320 rect.fRight -= radius; |
| 320 rect.fBottom += 0.5f; | 321 rect.fBottom += 0.5f; |
| 321 break; | 322 break; |
| 322 case RRectEffect::kBottomRight_CornerFlag: | 323 case CircularRRectEffect::kBottomRight_CornerFlag: |
| 323 radius = rrect.radii(SkRRect::kLowerRight_Corner).fX; | 324 radius = rrect.radii(SkRRect::kLowerRight_Corner).fX; |
| 324 rect.fLeft -= 0.5; | 325 rect.fLeft -= 0.5; |
| 325 rect.fTop -= 0.5; | 326 rect.fTop -= 0.5; |
| 326 rect.fRight -= radius; | 327 rect.fRight -= radius; |
| 327 rect.fBottom -= radius; | 328 rect.fBottom -= radius; |
| 328 break; | 329 break; |
| 329 case RRectEffect::kBottomLeft_CornerFlag: | 330 case CircularRRectEffect::kBottomLeft_CornerFlag: |
| 330 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; | 331 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; |
| 331 rect.fLeft += radius; | 332 rect.fLeft += radius; |
| 332 rect.fTop -= 0.5; | 333 rect.fTop -= 0.5; |
| 333 rect.fRight += 0.5; | 334 rect.fRight += 0.5; |
| 334 rect.fBottom -= radius; | 335 rect.fBottom -= radius; |
| 335 break; | 336 break; |
| 336 case RRectEffect::kLeft_CornerFlags: | 337 case CircularRRectEffect::kLeft_CornerFlags: |
| 337 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; | 338 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; |
| 338 rect.fLeft += radius; | 339 rect.fLeft += radius; |
| 339 rect.fTop += radius; | 340 rect.fTop += radius; |
| 340 rect.fRight += 0.5f; | 341 rect.fRight += 0.5f; |
| 341 rect.fBottom -= radius; | 342 rect.fBottom -= radius; |
| 342 break; | 343 break; |
| 343 case RRectEffect::kTop_CornerFlags: | 344 case CircularRRectEffect::kTop_CornerFlags: |
| 344 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; | 345 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; |
| 345 rect.fLeft += radius; | 346 rect.fLeft += radius; |
| 346 rect.fTop += radius; | 347 rect.fTop += radius; |
| 347 rect.fRight -= radius; | 348 rect.fRight -= radius; |
| 348 rect.fBottom += 0.5f; | 349 rect.fBottom += 0.5f; |
| 349 break; | 350 break; |
| 350 case RRectEffect::kRight_CornerFlags: | 351 case CircularRRectEffect::kRight_CornerFlags: |
| 351 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; | 352 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; |
| 352 rect.fLeft -= 0.5f; | 353 rect.fLeft -= 0.5f; |
| 353 rect.fTop += radius; | 354 rect.fTop += radius; |
| 354 rect.fRight -= radius; | 355 rect.fRight -= radius; |
| 355 rect.fBottom -= radius; | 356 rect.fBottom -= radius; |
| 356 break; | 357 break; |
| 357 case RRectEffect::kBottom_CornerFlags: | 358 case CircularRRectEffect::kBottom_CornerFlags: |
| 358 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; | 359 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; |
| 359 rect.fLeft += radius; | 360 rect.fLeft += radius; |
| 360 rect.fTop -= 0.5f; | 361 rect.fTop -= 0.5f; |
| 361 rect.fRight -= radius; | 362 rect.fRight -= radius; |
| 362 rect.fBottom -= radius; | 363 rect.fBottom -= radius; |
| 363 break; | 364 break; |
| 364 default: | 365 default: |
| 365 GrCrash("Should have been one of the above cases."); | 366 GrCrash("Should have been one of the above cases."); |
| 366 } | 367 } |
| 367 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom); | 368 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom); |
| 368 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); | 369 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); |
| 369 fPrevRRect = rrect; | 370 fPrevRRect = rrect; |
| 370 } | 371 } |
| 371 } | 372 } |
| 372 | 373 |
| 373 ////////////////////////////////////////////////////////////////////////////// | 374 ////////////////////////////////////////////////////////////////////////////// |
| 374 | 375 |
| 376 class GLEllipticalRRectEffect; | |
| 377 | |
| 378 class EllipticalRRectEffect : public GrEffect { | |
| 379 public: | |
| 380 // This effect only supports circular corner rrects where the radius is >= k RadiusMin. | |
|
jvanverth1
2014/03/12 13:44:28
Fix comment? It might also be worth mentioning tha
bsalomon
2014/03/12 14:20:15
Done.
| |
| 381 static const SkScalar kRadiusMin; | |
| 382 | |
| 383 static GrEffectRef* Create(GrEffectEdgeType, const SkRRect&); | |
| 384 | |
| 385 virtual ~EllipticalRRectEffect() {}; | |
| 386 static const char* Name() { return "EllipticalRRect"; } | |
| 387 | |
| 388 const SkRRect& getRRect() const { return fRRect; } | |
| 389 | |
| 390 GrEffectEdgeType getEdgeType() const { return fEdgeType; } | |
| 391 | |
| 392 typedef GLEllipticalRRectEffect GLEffect; | |
| 393 | |
| 394 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; | |
| 395 | |
| 396 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | |
| 397 | |
| 398 private: | |
| 399 EllipticalRRectEffect(GrEffectEdgeType, const SkRRect&); | |
| 400 | |
| 401 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; | |
| 402 | |
| 403 SkRRect fRRect; | |
| 404 GrEffectEdgeType fEdgeType; | |
| 405 | |
| 406 GR_DECLARE_EFFECT_TEST; | |
| 407 | |
| 408 typedef GrEffect INHERITED; | |
| 409 }; | |
| 410 | |
| 411 const SkScalar EllipticalRRectEffect::kRadiusMin = 0.5f; | |
| 412 | |
| 413 GrEffectRef* EllipticalRRectEffect::Create(GrEffectEdgeType edgeType, | |
| 414 const SkRRect& rrect) { | |
| 415 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge Type == edgeType); | |
| 416 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipticalRRectEffect, (ed geType, rrect)))); | |
| 417 } | |
| 418 | |
| 419 void EllipticalRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { | |
| 420 *validFlags = 0; | |
| 421 } | |
| 422 | |
| 423 const GrBackendEffectFactory& EllipticalRRectEffect::getFactory() const { | |
| 424 return GrTBackendEffectFactory<EllipticalRRectEffect>::getInstance(); | |
| 425 } | |
| 426 | |
| 427 EllipticalRRectEffect::EllipticalRRectEffect(GrEffectEdgeType edgeType, const Sk RRect& rrect) | |
| 428 : fRRect(rrect) | |
| 429 , fEdgeType(edgeType){ | |
| 430 this->setWillReadFragmentPosition(); | |
| 431 } | |
| 432 | |
| 433 bool EllipticalRRectEffect::onIsEqual(const GrEffect& other) const { | |
| 434 const EllipticalRRectEffect& erre = CastEffect<EllipticalRRectEffect>(other) ; | |
| 435 return fEdgeType == erre.fEdgeType && fRRect == erre.fRRect; | |
| 436 } | |
| 437 | |
| 438 ////////////////////////////////////////////////////////////////////////////// | |
| 439 | |
| 440 GR_DEFINE_EFFECT_TEST(EllipticalRRectEffect); | |
| 441 | |
| 442 GrEffectRef* EllipticalRRectEffect::TestCreate(SkRandom* random, | |
| 443 GrContext*, | |
| 444 const GrDrawTargetCaps& caps, | |
| 445 GrTexture*[]) { | |
| 446 SkScalar w = random->nextRangeScalar(20.f, 1000.f); | |
| 447 SkScalar h = random->nextRangeScalar(20.f, 1000.f); | |
| 448 SkScalar rx = random->nextRangeF(kRadiusMin, 9.f); | |
| 449 SkScalar ry = random->nextRangeF(kRadiusMin, 9.f); | |
| 450 SkRRect rrect; | |
| 451 rrect.setRectXY(SkRect::MakeWH(w, h), rx, ry); | |
| 452 GrEffectRef* effect; | |
| 453 do { | |
| 454 GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectE dgeTypeCnt); | |
| 455 effect = EllipticalRRectEffect::Create(et, rrect); | |
| 456 } while (NULL == effect); | |
| 457 return effect; | |
| 458 } | |
| 459 | |
| 460 ////////////////////////////////////////////////////////////////////////////// | |
| 461 | |
| 462 class GLEllipticalRRectEffect : public GrGLEffect { | |
| 463 public: | |
| 464 GLEllipticalRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | |
| 465 | |
| 466 virtual void emitCode(GrGLShaderBuilder* builder, | |
| 467 const GrDrawEffect& drawEffect, | |
| 468 EffectKey key, | |
| 469 const char* outputColor, | |
| 470 const char* inputColor, | |
| 471 const TransformedCoordsArray&, | |
| 472 const TextureSamplerArray&) SK_OVERRIDE; | |
| 473 | |
| 474 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); | |
| 475 | |
| 476 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; | |
| 477 | |
| 478 private: | |
| 479 GrGLUniformManager::UniformHandle fInnerRectUniform; | |
| 480 GrGLUniformManager::UniformHandle fInvRadiusXYSqdUniform; | |
| 481 SkRRect fPrevRRect; | |
| 482 typedef GrGLEffect INHERITED; | |
| 483 }; | |
| 484 | |
| 485 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrBackendEffectFactory& f actory, | |
| 486 const GrDrawEffect& drawEffect) | |
| 487 : INHERITED (factory) { | |
| 488 fPrevRRect.setEmpty(); | |
| 489 } | |
| 490 | |
| 491 void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder, | |
| 492 const GrDrawEffect& drawEffect, | |
| 493 EffectKey key, | |
| 494 const char* outputColor, | |
| 495 const char* inputColor, | |
| 496 const TransformedCoordsArray&, | |
| 497 const TextureSamplerArray& samplers) { | |
| 498 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>(); | |
| 499 const char *rectName; | |
| 500 const char *invRadiusXYSqdName; | |
| 501 // The inner rect is the rrect bounds inset by the x/y radii | |
| 502 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity, | |
| 503 kVec4f_GrSLType, | |
| 504 "innerRect", | |
| 505 &rectName); | |
| 506 fInvRadiusXYSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Vi sibility, | |
| 507 kVec2f_GrSLType, | |
| 508 "invRadiusXY", | |
| 509 &invRadiusXYSqdName); | |
| 510 const char* fragmentPos = builder->fragmentPosition(); | |
| 511 // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos | |
| 512 // to the ellipse center. The vector is pinned in x and y to be in the quart er-plane relevant | |
| 513 // to that corner. This means that points near the interior near the rrect t op edge will have | |
| 514 // a vector that points straight up for both the TL left and TR corners. Com puting an | |
| 515 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, | |
| 516 // fragments near the other three edges will get the correct AA. Fragments i n the interior of | |
| 517 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will | |
| 518 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. | |
| 519 // The code below is a simplified version of the above that performs maxs on the vector | |
| 520 // components before computing distances and alpha values so that only one d istance computation | |
| 521 // need be computed to determine the min alpha. | |
| 522 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen tPos); | |
| 523 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect Name); | |
| 524 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); | |
| 525 // Z is the x/y offsets divided by squared radii. | |
| 526 builder->fsCodeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiusXYSqdName); | |
| 527 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. | |
| 528 builder->fsCodeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); | |
| 529 // grad_dot is the squared length of the gradient of the implicit. | |
| 530 builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n", fragmentPo s); | |
| 531 builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); | |
| 532 builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_ dot);\n", | |
| 533 fragmentPos); | |
| 534 | |
| 535 if (kFillAA_GrEffectEdgeType == erre.getEdgeType()) { | |
| 536 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1 .0);\n"); | |
| 537 } else { | |
| 538 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1 .0);\n"); | |
| 539 } | |
| 540 | |
| 541 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, | |
| 542 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); | |
| 543 } | |
| 544 | |
| 545 GrGLEffect::EffectKey GLEllipticalRRectEffect::GenKey(const GrDrawEffect& drawEf fect, | |
| 546 const GrGLCaps&) { | |
| 547 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>(); | |
| 548 return erre.getEdgeType(); | |
| 549 } | |
| 550 | |
| 551 void GLEllipticalRRectEffect::setData(const GrGLUniformManager& uman, | |
| 552 const GrDrawEffect& drawEffect) { | |
| 553 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>(); | |
| 554 const SkRRect& rrect = erre.getRRect(); | |
| 555 if (rrect != fPrevRRect) { | |
| 556 SkRect rect = rrect.getBounds(); | |
| 557 SkASSERT(rrect.isSimple()); | |
| 558 const SkVector& radius = rrect.getSimpleRadii(); | |
| 559 SkASSERT(radius.fX >= EllipticalRRectEffect::kRadiusMin); | |
| 560 SkASSERT(radius.fY >= EllipticalRRectEffect::kRadiusMin); | |
| 561 rect.inset(radius.fX, radius.fY); | |
| 562 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom); | |
| 563 uman.set2f(fInvRadiusXYSqdUniform, 1.f / (radius.fX * radius.fX), | |
| 564 1.f / (radius.fY * radius.fY)); | |
| 565 fPrevRRect = rrect; | |
| 566 } | |
| 567 } | |
| 568 | |
| 569 ////////////////////////////////////////////////////////////////////////////// | |
| 570 | |
| 375 GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre ct) { | 571 GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre ct) { |
| 376 if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) { | 572 if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) { |
| 377 return NULL; | 573 return NULL; |
| 378 } | 574 } |
| 379 uint32_t cornerFlags; | 575 uint32_t cornerFlags; |
| 380 if (rrect.isSimpleCircular()) { | 576 if (rrect.isSimple()) { |
| 381 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { | 577 if (rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY) { |
| 382 return NULL; | 578 if (rrect.getSimpleRadii().fX < CircularRRectEffect::kRadiusMin) { |
| 579 return NULL; | |
| 580 } | |
| 581 cornerFlags = CircularRRectEffect::kAll_CornerFlags; | |
| 582 } else { | |
| 583 if (rrect.getSimpleRadii().fX < EllipticalRRectEffect::kRadiusMin || | |
| 584 rrect.getSimpleRadii().fY < EllipticalRRectEffect::kRadiusMin) { | |
| 585 return NULL; | |
| 586 } | |
| 587 return EllipticalRRectEffect::Create(edgeType, rrect); | |
| 383 } | 588 } |
| 384 cornerFlags = RRectEffect::kAll_CornerFlags; | |
| 385 } else if (rrect.isComplex()) { | 589 } else if (rrect.isComplex()) { |
| 386 // Check for the "tab" cases - two adjacent circular corners and two squ are corners. | 590 // Check for the "tab" cases - two adjacent circular corners and two squ are corners. |
| 387 SkScalar radius = 0; | 591 SkScalar radius = 0; |
| 388 cornerFlags = 0; | 592 cornerFlags = 0; |
| 389 for (int c = 0; c < 4; ++c) { | 593 for (int c = 0; c < 4; ++c) { |
| 390 const SkVector& r = rrect.radii((SkRRect::Corner)c); | 594 const SkVector& r = rrect.radii((SkRRect::Corner)c); |
| 391 SkASSERT((0 == r.fX) == (0 == r.fY)); | 595 SkASSERT((0 == r.fX) == (0 == r.fY)); |
| 392 if (0 == r.fX) { | 596 if (0 == r.fX) { |
| 393 continue; | 597 continue; |
| 394 } | 598 } |
| 395 if (r.fX != r.fY) { | 599 if (r.fX != r.fY) { |
| 396 return NULL; | 600 return NULL; |
| 397 } | 601 } |
| 398 if (!cornerFlags) { | 602 if (!cornerFlags) { |
| 399 radius = r.fX; | 603 radius = r.fX; |
| 400 if (radius < RRectEffect::kRadiusMin) { | 604 if (radius < CircularRRectEffect::kRadiusMin) { |
| 401 return NULL; | 605 return NULL; |
| 402 } | 606 } |
| 403 cornerFlags = 1 << c; | 607 cornerFlags = 1 << c; |
| 404 } else { | 608 } else { |
| 405 if (r.fX != radius) { | 609 if (r.fX != radius) { |
| 406 return NULL; | 610 return NULL; |
| 407 } | 611 } |
| 408 cornerFlags |= 1 << c; | 612 cornerFlags |= 1 << c; |
| 409 } | 613 } |
| 410 } | 614 } |
| 411 | 615 |
| 412 switch (cornerFlags) { | 616 switch (cornerFlags) { |
| 413 case RRectEffect::kTopLeft_CornerFlag: | 617 case CircularRRectEffect::kTopLeft_CornerFlag: |
| 414 case RRectEffect::kTopRight_CornerFlag: | 618 case CircularRRectEffect::kTopRight_CornerFlag: |
| 415 case RRectEffect::kBottomRight_CornerFlag: | 619 case CircularRRectEffect::kBottomRight_CornerFlag: |
| 416 case RRectEffect::kBottomLeft_CornerFlag: | 620 case CircularRRectEffect::kBottomLeft_CornerFlag: |
| 417 case RRectEffect::kLeft_CornerFlags: | 621 case CircularRRectEffect::kLeft_CornerFlags: |
| 418 case RRectEffect::kTop_CornerFlags: | 622 case CircularRRectEffect::kTop_CornerFlags: |
| 419 case RRectEffect::kRight_CornerFlags: | 623 case CircularRRectEffect::kRight_CornerFlags: |
| 420 case RRectEffect::kBottom_CornerFlags: | 624 case CircularRRectEffect::kBottom_CornerFlags: |
| 421 case RRectEffect::kAll_CornerFlags: | 625 case CircularRRectEffect::kAll_CornerFlags: |
| 422 break; | 626 break; |
| 423 default: | 627 default: |
| 424 return NULL; | 628 return NULL; |
| 425 } | 629 } |
| 426 } else { | 630 } else { |
| 427 return NULL; | 631 return NULL; |
| 428 } | 632 } |
| 429 return RRectEffect::Create(edgeType, cornerFlags, rrect); | 633 return CircularRRectEffect::Create(edgeType, cornerFlags, rrect); |
| 430 } | 634 } |
| OLD | NEW |