GrRRectEffect.cpp revision cb3672ed7fb9a5d54849e3265e8399bc5224bace
1c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org/*
2c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org * Copyright 2014 Google Inc.
3c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org *
4c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
5c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org * found in the LICENSE file.
6c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org */
7c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
8c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org#include "GrRRectEffect.h"
9c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
10c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org#include "gl/GrGLEffect.h"
11c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org#include "gl/GrGLSL.h"
12c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org#include "GrTBackendEffectFactory.h"
13c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
14e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org#include "SkRRect.h"
15c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
16e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgclass GLRRectEffect;
17e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
18e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgclass RRectEffect : public GrEffect {
19e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgpublic:
20cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    // This effect only supports circular corner rrects where the radius is >= kRadiusMin.
21e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    static const SkScalar kRadiusMin;
22e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
23cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    /// The types of circular corner rrects supported
24cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    enum Type {
25cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        kCircleCorner_Type,     //<! All four corners have the same circular radius.
26cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        kLeftCircleTab_Type,    //<! The left side has circular corners and the right is a rect.
27cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        kTopCircleTab_Type,     //<! etc
28cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        kRightCircleTab_Type,
29cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        kBottomCircleTab_Type,
30cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    };
31cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org
32cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    static GrEffectRef* Create(const SkRRect&, Type);
33e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
34e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    virtual ~RRectEffect() {};
35e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    static const char* Name() { return "RRect"; }
36e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
37e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    const SkRRect& getRRect() const { return fRRect; }
38e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
39cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    Type getType() const { return fType; }
40cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org
41e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    typedef GLRRectEffect GLEffect;
42e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
43e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
44e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
45e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
46e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
47e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgprivate:
48cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    RRectEffect(const SkRRect&, Type);
49e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
50e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
51e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
52e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    SkRRect fRRect;
53cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    Type    fType;
54e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
55e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    GR_DECLARE_EFFECT_TEST;
56e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
57e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    typedef GrEffect INHERITED;
58e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org};
59e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
60e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgconst SkScalar RRectEffect::kRadiusMin = 0.5f;
61e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
62cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.orgGrEffectRef* RRectEffect::Create(const SkRRect& rrect, Type type) {
63cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, (rrect, type))));
64e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org}
65e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
66e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgvoid RRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
67e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    *validFlags = 0;
68e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org}
69e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
70e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgconst GrBackendEffectFactory& RRectEffect::getFactory() const {
71e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    return GrTBackendEffectFactory<RRectEffect>::getInstance();
72e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org}
73e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
74cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.orgRRectEffect::RRectEffect(const SkRRect& rrect, Type type)
75cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    : fRRect(rrect)
76cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    , fType(type) {
77e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    this->setWillReadFragmentPosition();
78e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org}
79e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
80e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgbool RRectEffect::onIsEqual(const GrEffect& other) const {
81e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    const RRectEffect& rre = CastEffect<RRectEffect>(other);
82cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    // type is derived from fRRect, so no need to check it.
83e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    return fRRect == rre.fRRect;
84e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org}
85e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
86e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
87e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
88e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(RRectEffect);
89e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
90e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgGrEffectRef* RRectEffect::TestCreate(SkRandom* random,
91e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                                     GrContext*,
92e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                                     const GrDrawTargetCaps& caps,
93e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                                     GrTexture*[]) {
94e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    SkScalar w = random->nextRangeScalar(20.f, 1000.f);
95e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    SkScalar h = random->nextRangeScalar(20.f, 1000.f);
96e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    SkScalar r = random->nextRangeF(kRadiusMin, 9.f);
97e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    SkRRect rrect;
98e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    rrect.setRectXY(SkRect::MakeWH(w, h), r, r);
99e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
100e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    return GrRRectEffect::Create(rrect);
101e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org}
102c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
103c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
104e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org
105e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgclass GLRRectEffect : public GrGLEffect {
106c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.orgpublic:
107e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    GLRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
108c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
109c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    virtual void emitCode(GrGLShaderBuilder* builder,
110c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                          const GrDrawEffect& drawEffect,
111c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                          EffectKey key,
112c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                          const char* outputColor,
113c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                          const char* inputColor,
114c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                          const TransformedCoordsArray&,
115c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                          const TextureSamplerArray&) SK_OVERRIDE;
116c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
117cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
118c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
119c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
120c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
121c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.orgprivate:
122c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    GrGLUniformManager::UniformHandle   fInnerRectUniform;
123c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    GrGLUniformManager::UniformHandle   fRadiusPlusHalfUniform;
124c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    SkRRect                             fPrevRRect;
125c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    typedef GrGLEffect INHERITED;
126c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org};
127c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
128e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgGLRRectEffect::GLRRectEffect(const GrBackendEffectFactory& factory,
129e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                             const GrDrawEffect& drawEffect)
130c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    : INHERITED (factory) {
131c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    fPrevRRect.setEmpty();
132c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org}
133c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
134e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgvoid GLRRectEffect::emitCode(GrGLShaderBuilder* builder,
135e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                             const GrDrawEffect& drawEffect,
136e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                             EffectKey key,
137e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                             const char* outputColor,
138e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                             const char* inputColor,
139e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                             const TransformedCoordsArray&,
140e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org                             const TextureSamplerArray& samplers) {
141cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    const RRectEffect& rre = drawEffect.castEffect<RRectEffect>();
142c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    const char *rectName;
143c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    const char *radiusPlusHalfName;
144c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // The inner rect is the rrect bounds inset by the radius. Its top, left, right, and bottom
145cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    // edges correspond to components x, y, z, and w, respectively. When one side of the rrect has
146cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    // rectangular corners, that side's value corresponds to the rect edge's value outset by half a
147cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    // pixel.
148c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
149c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                                            kVec4f_GrSLType,
150c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                                            "innerRect",
151c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                                            &rectName);
152c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    fRadiusPlusHalfUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
153c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                                                 kFloat_GrSLType,
154c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                                                 "radiusPlusHalf",
155c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                                                 &radiusPlusHalfName);
156c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    const char* fragmentPos = builder->fragmentPosition();
157c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // At each quarter-circle corner we compute a vector that is the offset of the fragment position
158c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant
159c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // to that corner. This means that points near the interior near the rrect top edge will have
160c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // a vector that points straight up for both the TL left and TR corners. Computing an
161c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // alpha from this vector at either the TR or TL corner will give the correct result. Similarly,
162c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // fragments near the other three edges will get the correct AA. Fragments in the interior of
163c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // the rrect will have a (0,0) vector at all four corners. So long as the radius > 0.5 they will
164c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // correctly produce an alpha value of 1 at all four corners. We take the min of all the alphas.
165c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // The code below is a simplified version of the above that performs maxs on the vector
166c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // components before computing distances and alpha values so that only one distance computation
167c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    // need be computed to determine the min alpha.
168cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    //
169cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    // For the cases where one half of the rrect is rectangular we drop one of the x or y
170cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    // computations, compute a separate rect edge alpha for the rect side, and mul the two computed
171cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    // alphas together.
172cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    switch (rre.getType()) {
173cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        case RRectEffect::kCircleCorner_Type:
174cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
175cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
176cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
177cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0);\n",
178cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                                   radiusPlusHalfName);
179cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            break;
180cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        case RRectEffect::kLeftCircleTab_Type:
181cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
182cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos, rectName);
183cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);\n");
184cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
185cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                                    rectName, fragmentPos);
186cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
187cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                                   radiusPlusHalfName);
188cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            break;
189cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        case RRectEffect::kTopCircleTab_Type:
190cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
191cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos, rectName);
192cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0.y), 0.0);\n");
193cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
194cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                                   rectName, fragmentPos);
195cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
196cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                                   radiusPlusHalfName);
197cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            break;
198cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        case RRectEffect::kRightCircleTab_Type:
199cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, fragmentPos);
200cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
201cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y)), 0.0);\n");
202cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
203cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                                   fragmentPos, rectName);
204cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
205cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                                   radiusPlusHalfName);
206cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            break;
207cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        case RRectEffect::kBottomCircleTab_Type:
208cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, fragmentPos);
209cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
210cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1.y), 0.0);\n");
211cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
212cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                                   fragmentPos, rectName);
213cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
214cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                                   radiusPlusHalfName);
215cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            break;
216cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    }
217c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
218c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
219c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
220c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org}
221c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
222cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.orgGrGLEffect::EffectKey GLRRectEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
223cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    const RRectEffect& rre = drawEffect.castEffect<RRectEffect>();
224cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    return rre.getType();
225cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org}
226cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org
227e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgvoid GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
228e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org    const RRectEffect& rre = drawEffect.castEffect<RRectEffect>();
229c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    const SkRRect& rrect = rre.getRRect();
230c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    if (rrect != fPrevRRect) {
231c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org        SkRect rect = rrect.getBounds();
232cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        SkScalar radius = 0;
233cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        switch (rre.getType()) {
234cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            case RRectEffect::kCircleCorner_Type:
235cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                SkASSERT(rrect.isSimpleCircular());
236cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                radius = rrect.getSimpleRadii().fX;
237cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                SkASSERT(radius >= RRectEffect::kRadiusMin);
238cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.inset(radius, radius);
239cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                break;
240cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            case RRectEffect::kLeftCircleTab_Type:
241cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
242cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fLeft += radius;
243cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fTop += radius;
244cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fRight += 0.5f;
245cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fBottom -= radius;
246cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                break;
247cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            case RRectEffect::kTopCircleTab_Type:
248cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
249cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fLeft += radius;
250cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fTop += radius;
251cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fRight -= radius;
252cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fBottom += 0.5f;
253cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                break;
254cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            case RRectEffect::kRightCircleTab_Type:
255cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                radius = rrect.radii(SkRRect::kUpperRight_Corner).fX;
256cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fLeft -= 0.5f;
257cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fTop += radius;
258cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fRight -= radius;
259cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fBottom -= radius;
260cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                break;
261cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            case RRectEffect::kBottomCircleTab_Type:
262cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
263cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fLeft += radius;
264cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fTop -= 0.5f;
265cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fRight -= radius;
266cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                rect.fBottom -= radius;
267cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                break;
268cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        }
269c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org        uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
270c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org        uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f);
271c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org        fPrevRRect = rrect;
272c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    }
273c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org}
274c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
275c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
276c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org
277c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.orgGrEffectRef* GrRRectEffect::Create(const SkRRect& rrect) {
278cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    RRectEffect::Type type;
279cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    if (rrect.isSimpleCircular()) {
280cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) {
281cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            return NULL;
282cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        }
283cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        type = RRectEffect::kCircleCorner_Type;
284cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    } else if (rrect.isComplex()) {
285cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        // Check for the "tab" cases - two adjacent circular corners and two square corners.
286cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        SkScalar radius = 0;
287cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        int circleCornerBitfield = 0;
288cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        for (int c = 0; c < 4; ++c) {
289cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            const SkVector& r = rrect.radii((SkRRect::Corner)c);
290cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            SkASSERT((0 == r.fX) == (0 == r.fY));
291cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            if (0 == r.fX) {
292cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                continue;
293cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            }
294cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            if (r.fX != r.fY) {
295cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                return NULL;
296cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            }
297cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            if (!circleCornerBitfield) {
298cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                radius = r.fX;
299cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                if (radius < RRectEffect::kRadiusMin) {
300cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                    return NULL;
301cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                }
302cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                circleCornerBitfield = 1 << c;
303cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            } else {
304cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                if (r.fX != radius) {
305cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                    return NULL;
306cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                }
307cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                circleCornerBitfield |= 1 << c;
308cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            }
309cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        }
310cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org
311cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        GR_STATIC_ASSERT(SkRRect::kUpperLeft_Corner  == 0);
312cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        GR_STATIC_ASSERT(SkRRect::kUpperRight_Corner == 1);
313cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        GR_STATIC_ASSERT(SkRRect::kLowerRight_Corner == 2);
314cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        GR_STATIC_ASSERT(SkRRect::kLowerLeft_Corner  == 3);
315cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        switch (circleCornerBitfield) {
316cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            case 3:
317cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                type = RRectEffect::kTopCircleTab_Type;
318cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                break;
319cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            case 6:
320cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                type = RRectEffect::kRightCircleTab_Type;
321cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                break;
322cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            case 9:
323cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                type = RRectEffect::kLeftCircleTab_Type;
324cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                break;
325cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            case 12:
326cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                type = RRectEffect::kBottomCircleTab_Type;
327cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                break;
328cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org            default:
329cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org                return NULL;
330cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org        }
331cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    } else {
332c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org        return NULL;
333c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    }
334cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org    return RRectEffect::Create(rrect, type);
335c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org}
336