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