GrRRectEffect.cpp revision cd0749144383d78a10a5df00e2e96e76456b412b
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 102a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org#include "GrConvexPolyEffect.h" 11eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrFragmentProcessor.h" 12605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h" 133eedb801e35001df4b7e154edf4fd8da942296a0commit-bot@chromium.org#include "GrOvalEffect.h" 14e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org#include "SkRRect.h" 157ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "SkTLazy.h" 1664c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h" 172d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h" 18018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h" 197ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h" 20c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 212a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org// The effects defined here only handle rrect radii >= kRadiusMin. 222a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.orgstatic const SkScalar kRadiusMin = SK_ScalarHalf; 232a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org 242a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////// 252a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org 26b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass CircularRRectEffect : public GrFragmentProcessor { 27e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgpublic: 28f1f66c0c8623805fdb88f09c0d87cbdd1745e12bskia.committer@gmail.com 29dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org enum CornerFlags { 30dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kTopLeft_CornerFlag = (1 << SkRRect::kUpperLeft_Corner), 31dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kTopRight_CornerFlag = (1 << SkRRect::kUpperRight_Corner), 32dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kBottomRight_CornerFlag = (1 << SkRRect::kLowerRight_Corner), 33dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kBottomLeft_CornerFlag = (1 << SkRRect::kLowerLeft_Corner), 34dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org 35dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kLeft_CornerFlags = kTopLeft_CornerFlag | kBottomLeft_CornerFlag, 36dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kTop_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag, 37dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kRight_CornerFlags = kTopRight_CornerFlag | kBottomRight_CornerFlag, 38dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kBottom_CornerFlags = kBottomLeft_CornerFlag | kBottomRight_CornerFlag, 39dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org 40dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kAll_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag | 41dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org kBottomLeft_CornerFlag | kBottomRight_CornerFlag, 42dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org 432a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org kNone_CornerFlags = 0 44cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org }; 45cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org 46dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org // The flags are used to indicate which corners are circluar (unflagged corners are assumed to 47dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org // be square). 48b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static GrFragmentProcessor* Create(GrPrimitiveEdgeType, uint32_t circularCornerFlags, 49b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkRRect&); 50e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 514355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org virtual ~CircularRRectEffect() {}; 52eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 5336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "CircularRRect"; } 54eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 55e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org const SkRRect& getRRect() const { return fRRect; } 56e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 57dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org uint32_t getCircularCornerFlags() const { return fCircularCornerFlags; } 5806acb58074778d8eb40f14ae72b000d5120a8111skia.committer@gmail.com 59b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } 60cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org 61e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.orgprivate: 62b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt CircularRRectEffect(GrPrimitiveEdgeType, uint32_t circularCornerFlags, const SkRRect&); 63e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 6457d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 65b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix 6657d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override; 674b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix 6836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onIsEqual(const GrFragmentProcessor& other) const override; 69e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 7036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onComputeInvariantOutput(GrInvariantOutput* inout) const override; 711a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel 72b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkRRect fRRect; 73b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrPrimitiveEdgeType fEdgeType; 74b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t fCircularCornerFlags; 75e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 76b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 77e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 78b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrFragmentProcessor INHERITED; 79e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org}; 80e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 81b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* CircularRRectEffect::Create(GrPrimitiveEdgeType edgeType, 82b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t circularCornerFlags, 83b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkRRect& rrect) { 84b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (kFillAA_GrProcessorEdgeType != edgeType && kInverseFillAA_GrProcessorEdgeType != edgeType) { 8596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 863eedb801e35001df4b7e154edf4fd8da942296a0commit-bot@chromium.org } 87385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new CircularRRectEffect(edgeType, circularCornerFlags, rrect); 88e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org} 89e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 90605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielvoid CircularRRectEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 9156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt inout->mulByUnknownSingleComponent(); 92e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org} 93e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 94b0a8a377f832c59cee939ad721e1f87d378b7142joshualittCircularRRectEffect::CircularRRectEffect(GrPrimitiveEdgeType edgeType, uint32_t circularCornerFlags, 95b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkRRect& rrect) 96cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org : fRRect(rrect) 97fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org , fEdgeType(edgeType) 98dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org , fCircularCornerFlags(circularCornerFlags) { 99eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt this->initClassID<CircularRRectEffect>(); 100e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org this->setWillReadFragmentPosition(); 101e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org} 102e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 1030e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool CircularRRectEffect::onIsEqual(const GrFragmentProcessor& other) const { 10449586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const CircularRRectEffect& crre = other.cast<CircularRRectEffect>(); 1054355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // The corner flags are derived from fRRect, so no need to check them. 1064355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org return fEdgeType == crre.fEdgeType && fRRect == crre.fRRect; 107e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org} 108e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 109e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////// 110e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 111b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircularRRectEffect); 112e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 113c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrFragmentProcessor* CircularRRectEffect::TestCreate(GrProcessorTestData* d) { 1140067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt SkScalar w = d->fRandom->nextRangeScalar(20.f, 1000.f); 1150067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt SkScalar h = d->fRandom->nextRangeScalar(20.f, 1000.f); 1160067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt SkScalar r = d->fRandom->nextRangeF(kRadiusMin, 9.f); 117e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org SkRRect rrect; 118e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org rrect.setRectXY(SkRect::MakeWH(w, h), r, r); 119b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor* fp; 120cabf4b2f3664b98c1084fbb94a999af15ddfb52dcommit-bot@chromium.org do { 121b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrPrimitiveEdgeType et = 1220067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt); 123b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fp = GrRRectEffect::Create(et, rrect); 12496fcdcc219d2a0d3579719b84b28bede76efba64halcanary } while (nullptr == fp); 125b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return fp; 126e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org} 127c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 128c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////// 129e5280893f8f9f6b6149572a4c8fe513f9c2b3888commit-bot@chromium.org 13064c4728c70001ed074fecf5c4e083781987b12e9egdanielclass GLCircularRRectEffect : public GrGLSLFragmentProcessor { 131c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.orgpublic: 132eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GLCircularRRectEffect(const GrProcessor&); 133c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 1347c157a988845fb00f9024d6db6dda142c3458033wangyix virtual void emitCode(EmitArgs&) override; 135c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 136cfc18867d982119d9dc2888bf09f1093012daaddjvanverth static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*); 137c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 138b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected: 139018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override; 140c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 141c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.orgprivate: 142018fb62d12d1febf121fe265da5b6117b86a6541egdaniel GrGLSLProgramDataManager::UniformHandle fInnerRectUniform; 143018fb62d12d1febf121fe265da5b6117b86a6541egdaniel GrGLSLProgramDataManager::UniformHandle fRadiusPlusHalfUniform; 1447510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen SkRRect fPrevRRect; 14564c4728c70001ed074fecf5c4e083781987b12e9egdaniel typedef GrGLSLFragmentProcessor INHERITED; 146c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org}; 147c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 148eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittGLCircularRRectEffect::GLCircularRRectEffect(const GrProcessor& ) { 149c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org fPrevRRect.setEmpty(); 150c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org} 151c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 1527c157a988845fb00f9024d6db6dda142c3458033wangyixvoid GLCircularRRectEffect::emitCode(EmitArgs& args) { 1537c157a988845fb00f9024d6db6dda142c3458033wangyix const CircularRRectEffect& crre = args.fFp.cast<CircularRRectEffect>(); 1547ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 155c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org const char *rectName; 156c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org const char *radiusPlusHalfName; 157c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org // The inner rect is the rrect bounds inset by the radius. Its left, top, right, and bottom 158c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has 159c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org // only rectangular corners, that side's value corresponds to the rect edge's value outset by 160c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org // half a pixel. 1617ea439b2203855db97330b25945b87dd4b170b8begdaniel fInnerRectUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility, 1627ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec4f_GrSLType, kDefault_GrSLPrecision, 1637ea439b2203855db97330b25945b87dd4b170b8begdaniel "innerRect", 1647ea439b2203855db97330b25945b87dd4b170b8begdaniel &rectName); 165cd0749144383d78a10a5df00e2e96e76456b412bbsalomon // x is (r + .5) and y is 1/(r + .5) 1667ea439b2203855db97330b25945b87dd4b170b8begdaniel fRadiusPlusHalfUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility, 167cd0749144383d78a10a5df00e2e96e76456b412bbsalomon kVec2f_GrSLType, kDefault_GrSLPrecision, 1687ea439b2203855db97330b25945b87dd4b170b8begdaniel "radiusPlusHalf", 1697ea439b2203855db97330b25945b87dd4b170b8begdaniel &radiusPlusHalfName); 1702d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel 171cd0749144383d78a10a5df00e2e96e76456b412bbsalomon // If we're on a device with a "real" mediump then the length calculation could overflow. 172cd0749144383d78a10a5df00e2e96e76456b412bbsalomon SkString clampedCircleDistance; 173cd0749144383d78a10a5df00e2e96e76456b412bbsalomon if (args.fGLSLCaps->floatPrecisionVaries()) { 174cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.printf("clamp(%s.x * (1.0 - length(dxy * %s.y)), 0.0, 1.0);", 175cd0749144383d78a10a5df00e2e96e76456b412bbsalomon radiusPlusHalfName, radiusPlusHalfName); 176cd0749144383d78a10a5df00e2e96e76456b412bbsalomon } else { 177cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.printf("clamp(%s.x - length(dxy), 0.0, 1.0);", radiusPlusHalfName); 178cd0749144383d78a10a5df00e2e96e76456b412bbsalomon } 179cd0749144383d78a10a5df00e2e96e76456b412bbsalomon 1804ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; 1814ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel const char* fragmentPos = fragBuilder->fragmentPosition(); 182c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // At each quarter-circle corner we compute a vector that is the offset of the fragment position 183c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant 184c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // to that corner. This means that points near the interior near the rrect top edge will have 185c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // a vector that points straight up for both the TL left and TR corners. Computing an 186c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // alpha from this vector at either the TR or TL corner will give the correct result. Similarly, 187c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // fragments near the other three edges will get the correct AA. Fragments in the interior of 188c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // the rrect will have a (0,0) vector at all four corners. So long as the radius > 0.5 they will 189c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // correctly produce an alpha value of 1 at all four corners. We take the min of all the alphas. 190c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // The code below is a simplified version of the above that performs maxs on the vector 191c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // components before computing distances and alpha values so that only one distance computation 192c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org // need be computed to determine the min alpha. 193cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org // 194cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org // For the cases where one half of the rrect is rectangular we drop one of the x or y 195cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org // computations, compute a separate rect edge alpha for the rect side, and mul the two computed 196cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org // alphas together. 1974355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org switch (crre.getCircularCornerFlags()) { 1984355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kAll_CornerFlags: 199cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos); 200cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName); 201cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppend("vec2 dxy = max(max(dxy0, dxy1), 0.0);"); 202cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float alpha = %s;", clampedCircleDistance.c_str()); 203cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 2044355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kTopLeft_CornerFlag: 205cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - %s.xy, 0.0);", 2064ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel rectName, fragmentPos); 207cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);", 2084ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel rectName, fragmentPos); 209cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);", 2104ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel rectName, fragmentPos); 211cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float alpha = bottomAlpha * rightAlpha * %s;", 212cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.c_str()); 213c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org break; 2144355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kTopRight_CornerFlag: 215cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);", 2164ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragmentPos, rectName, rectName, fragmentPos); 217cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);", 2184ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragmentPos, rectName); 219cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);", 2204ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel rectName, fragmentPos); 221cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float alpha = bottomAlpha * leftAlpha * %s;", 222cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.c_str()); 223c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org break; 2244355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kBottomRight_CornerFlag: 225cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - %s.zw, 0.0);", 2264ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragmentPos, rectName); 227cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);", 2284ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragmentPos, rectName); 229cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);", 2304ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragmentPos, rectName); 231cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float alpha = topAlpha * leftAlpha * %s;", 232cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.c_str()); 233c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org break; 2344355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kBottomLeft_CornerFlag: 235cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);", 2364ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel rectName, fragmentPos, fragmentPos, rectName); 237cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);", 2384ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel rectName, fragmentPos); 239cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);", 2404ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragmentPos, rectName); 241cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float alpha = topAlpha * rightAlpha * %s;", 242cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.c_str()); 243c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org break; 2444355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kLeft_CornerFlags: 245cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos); 246cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float dy1 = %s.y - %s.w;", fragmentPos, rectName); 247cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppend("vec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);"); 248cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);", 2494ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel rectName, fragmentPos); 250cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float alpha = rightAlpha * %s;", 251cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.c_str()); 252cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 2534355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kTop_CornerFlags: 254cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos); 255cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float dx1 = %s.x - %s.z;", fragmentPos, rectName); 256cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppend("vec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0.y), 0.0);"); 257cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);", 2584ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel rectName, fragmentPos); 259cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float alpha = bottomAlpha * %s;", 260cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.c_str()); 261cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 2624355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kRight_CornerFlags: 263cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float dy0 = %s.y - %s.y;", rectName, fragmentPos); 264cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName); 265cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppend("vec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y)), 0.0);"); 266cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);", 2674ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragmentPos, rectName); 268cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float alpha = leftAlpha * %s;", 269cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.c_str()); 270cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 2714355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kBottom_CornerFlags: 272cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float dx0 = %s.x - %s.x;", rectName, fragmentPos); 273cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName); 274cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppend("vec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1.y), 0.0);"); 275cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);", 2764ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragmentPos, rectName); 277cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("float alpha = topAlpha * %s;", 278cd0749144383d78a10a5df00e2e96e76456b412bbsalomon clampedCircleDistance.c_str()); 279cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 280cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } 28106acb58074778d8eb40f14ae72b000d5120a8111skia.committer@gmail.com 282b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (kInverseFillAA_GrProcessorEdgeType == crre.getEdgeType()) { 283cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppend("alpha = 1.0 - alpha;"); 284fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org } 285c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 286cd0749144383d78a10a5df00e2e96e76456b412bbsalomon fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, 2874ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str()); 288c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org} 289c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 290cfc18867d982119d9dc2888bf09f1093012daaddjvanverthvoid GLCircularRRectEffect::GenKey(const GrProcessor& processor, const GrGLSLCaps&, 291b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 292b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const CircularRRectEffect& crre = processor.cast<CircularRRectEffect>(); 293b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8); 29463e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon b->add32((crre.getCircularCornerFlags() << 3) | crre.getEdgeType()); 295cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org} 296cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org 297018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GLCircularRRectEffect::onSetData(const GrGLSLProgramDataManager& pdman, 298018fb62d12d1febf121fe265da5b6117b86a6541egdaniel const GrProcessor& processor) { 299b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const CircularRRectEffect& crre = processor.cast<CircularRRectEffect>(); 3004355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org const SkRRect& rrect = crre.getRRect(); 301c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org if (rrect != fPrevRRect) { 302c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org SkRect rect = rrect.getBounds(); 303cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org SkScalar radius = 0; 3044355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org switch (crre.getCircularCornerFlags()) { 3054355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kAll_CornerFlags: 306cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org SkASSERT(rrect.isSimpleCircular()); 307cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org radius = rrect.getSimpleRadii().fX; 3082a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkASSERT(radius >= kRadiusMin); 309cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.inset(radius, radius); 310cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 3114355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kTopLeft_CornerFlag: 312c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; 313c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fLeft += radius; 314c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fTop += radius; 315c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fRight += 0.5f; 316c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fBottom += 0.5f; 317c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org break; 3184355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kTopRight_CornerFlag: 319c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; 320de9f251427ccb35fa4d55b5efc97c1b31721cf78bsalomon@google.com rect.fLeft -= 0.5f; 321c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fTop += radius; 322c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fRight -= radius; 323c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fBottom += 0.5f; 324c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org break; 3254355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kBottomRight_CornerFlag: 326c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org radius = rrect.radii(SkRRect::kLowerRight_Corner).fX; 327de9f251427ccb35fa4d55b5efc97c1b31721cf78bsalomon@google.com rect.fLeft -= 0.5f; 328de9f251427ccb35fa4d55b5efc97c1b31721cf78bsalomon@google.com rect.fTop -= 0.5f; 329c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fRight -= radius; 330c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fBottom -= radius; 331c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org break; 3324355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kBottomLeft_CornerFlag: 333c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; 334c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fLeft += radius; 335de9f251427ccb35fa4d55b5efc97c1b31721cf78bsalomon@google.com rect.fTop -= 0.5f; 336de9f251427ccb35fa4d55b5efc97c1b31721cf78bsalomon@google.com rect.fRight += 0.5f; 337c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org rect.fBottom -= radius; 338c5c748c14797ae49ba73999a63e3b07315c888e1commit-bot@chromium.org break; 3394355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kLeft_CornerFlags: 340cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; 341cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fLeft += radius; 342cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fTop += radius; 343cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fRight += 0.5f; 344cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fBottom -= radius; 345cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 3464355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kTop_CornerFlags: 347cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; 348cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fLeft += radius; 349cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fTop += radius; 350cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fRight -= radius; 351cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fBottom += 0.5f; 352cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 3534355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kRight_CornerFlags: 354cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; 355cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fLeft -= 0.5f; 356cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fTop += radius; 357cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fRight -= radius; 358cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fBottom -= radius; 359cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 3604355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kBottom_CornerFlags: 361cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; 362cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fLeft += radius; 363cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fTop -= 0.5f; 364cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fRight -= radius; 365cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org rect.fBottom -= radius; 366cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org break; 367dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org default: 36888cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org SkFAIL("Should have been one of the above cases."); 369cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } 3707510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); 371cd0749144383d78a10a5df00e2e96e76456b412bbsalomon radius += 0.5f; 372cd0749144383d78a10a5df00e2e96e76456b412bbsalomon pdman.set2f(fRadiusPlusHalfUniform, radius, 1.f / radius); 373c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org fPrevRRect = rrect; 374c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org } 375c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org} 376c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 377eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt//////////////////////////////////////////////////////////////////////////////////////////////////// 378c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org 37957d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielvoid CircularRRectEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, 38057d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 381eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GLCircularRRectEffect::GenKey(*this, caps, b); 382eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 383eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 38457d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* CircularRRectEffect::onCreateGLSLInstance() const { 385385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new GLCircularRRectEffect(*this); 386eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 387eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 388eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt////////////////////////////////////////////////////////////////////////////// 3894355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 390b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass EllipticalRRectEffect : public GrFragmentProcessor { 3914355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.orgpublic: 392b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static GrFragmentProcessor* Create(GrPrimitiveEdgeType, const SkRRect&); 3934355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 3944355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org virtual ~EllipticalRRectEffect() {}; 3954355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 39636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "EllipticalRRect"; } 3974355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 398eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt const SkRRect& getRRect() const { return fRRect; } 3994355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 400eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } 4014355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 4024355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.orgprivate: 403b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt EllipticalRRectEffect(GrPrimitiveEdgeType, const SkRRect&); 4044355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 40557d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 406b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix 40757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override; 4084b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix 40936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onIsEqual(const GrFragmentProcessor& other) const override; 4104355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 41136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onComputeInvariantOutput(GrInvariantOutput* inout) const override; 4121a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel 4134355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org SkRRect fRRect; 414b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrPrimitiveEdgeType fEdgeType; 4154355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 416b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 4174355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 418b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrFragmentProcessor INHERITED; 4194355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org}; 4204355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 421b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* 422b0a8a377f832c59cee939ad721e1f87d378b7142joshualittEllipticalRRectEffect::Create(GrPrimitiveEdgeType edgeType, const SkRRect& rrect) { 423b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (kFillAA_GrProcessorEdgeType != edgeType && kInverseFillAA_GrProcessorEdgeType != edgeType) { 42496fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 4253eedb801e35001df4b7e154edf4fd8da942296a0commit-bot@chromium.org } 426385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new EllipticalRRectEffect(edgeType, rrect); 4274355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org} 4284355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 429605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielvoid EllipticalRRectEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 43056995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt inout->mulByUnknownSingleComponent(); 4314355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org} 4324355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 433b0a8a377f832c59cee939ad721e1f87d378b7142joshualittEllipticalRRectEffect::EllipticalRRectEffect(GrPrimitiveEdgeType edgeType, const SkRRect& rrect) 4344355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org : fRRect(rrect) 435eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt , fEdgeType(edgeType) { 436eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt this->initClassID<EllipticalRRectEffect>(); 4374355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org this->setWillReadFragmentPosition(); 4384355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org} 4394355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 4400e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool EllipticalRRectEffect::onIsEqual(const GrFragmentProcessor& other) const { 44149586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const EllipticalRRectEffect& erre = other.cast<EllipticalRRectEffect>(); 4424355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org return fEdgeType == erre.fEdgeType && fRRect == erre.fRRect; 4434355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org} 4444355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 4454355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org////////////////////////////////////////////////////////////////////////////// 4464355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 447b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(EllipticalRRectEffect); 4484355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 449c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrFragmentProcessor* EllipticalRRectEffect::TestCreate(GrProcessorTestData* d) { 4500067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt SkScalar w = d->fRandom->nextRangeScalar(20.f, 1000.f); 4510067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt SkScalar h = d->fRandom->nextRangeScalar(20.f, 1000.f); 452fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org SkVector r[4]; 4530067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt r[SkRRect::kUpperLeft_Corner].fX = d->fRandom->nextRangeF(kRadiusMin, 9.f); 454fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org // ensure at least one corner really is elliptical 455fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org do { 4560067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt r[SkRRect::kUpperLeft_Corner].fY = d->fRandom->nextRangeF(kRadiusMin, 9.f); 457fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org } while (r[SkRRect::kUpperLeft_Corner].fY == r[SkRRect::kUpperLeft_Corner].fX); 458fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org 4594355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org SkRRect rrect; 4600067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt if (d->fRandom->nextBool()) { 461fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org // half the time create a four-radii rrect. 4620067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt r[SkRRect::kLowerRight_Corner].fX = d->fRandom->nextRangeF(kRadiusMin, 9.f); 4630067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt r[SkRRect::kLowerRight_Corner].fY = d->fRandom->nextRangeF(kRadiusMin, 9.f); 464fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org 465fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org r[SkRRect::kUpperRight_Corner].fX = r[SkRRect::kLowerRight_Corner].fX; 466fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org r[SkRRect::kUpperRight_Corner].fY = r[SkRRect::kUpperLeft_Corner].fY; 467fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org 468fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org r[SkRRect::kLowerLeft_Corner].fX = r[SkRRect::kUpperLeft_Corner].fX; 469fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org r[SkRRect::kLowerLeft_Corner].fY = r[SkRRect::kLowerRight_Corner].fY; 470fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org 471fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org rrect.setRectRadii(SkRect::MakeWH(w, h), r); 472fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org } else { 473fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org rrect.setRectXY(SkRect::MakeWH(w, h), r[SkRRect::kUpperLeft_Corner].fX, 474fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org r[SkRRect::kUpperLeft_Corner].fY); 475fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org } 476b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor* fp; 4774355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org do { 4780067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrPrimitiveEdgeType et = 4790067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt); 480b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fp = GrRRectEffect::Create(et, rrect); 48196fcdcc219d2a0d3579719b84b28bede76efba64halcanary } while (nullptr == fp); 482b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return fp; 4834355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org} 4844355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 4854355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org////////////////////////////////////////////////////////////////////////////// 4864355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 48764c4728c70001ed074fecf5c4e083781987b12e9egdanielclass GLEllipticalRRectEffect : public GrGLSLFragmentProcessor { 4884355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.orgpublic: 489eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GLEllipticalRRectEffect(const GrProcessor&); 4904355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 4917c157a988845fb00f9024d6db6dda142c3458033wangyix virtual void emitCode(EmitArgs&) override; 4924355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 493cfc18867d982119d9dc2888bf09f1093012daaddjvanverth static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*); 4944355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 495b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected: 496018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override; 4974355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 4984355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.orgprivate: 499018fb62d12d1febf121fe265da5b6117b86a6541egdaniel GrGLSLProgramDataManager::UniformHandle fInnerRectUniform; 500018fb62d12d1febf121fe265da5b6117b86a6541egdaniel GrGLSLProgramDataManager::UniformHandle fInvRadiiSqdUniform; 5017510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen SkRRect fPrevRRect; 50264c4728c70001ed074fecf5c4e083781987b12e9egdaniel typedef GrGLSLFragmentProcessor INHERITED; 5034355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org}; 5044355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 505eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittGLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrProcessor& effect) { 5064355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org fPrevRRect.setEmpty(); 5074355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org} 5084355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 5097c157a988845fb00f9024d6db6dda142c3458033wangyixvoid GLEllipticalRRectEffect::emitCode(EmitArgs& args) { 5107c157a988845fb00f9024d6db6dda142c3458033wangyix const EllipticalRRectEffect& erre = args.fFp.cast<EllipticalRRectEffect>(); 5117ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 5124355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org const char *rectName; 5134355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // The inner rect is the rrect bounds inset by the x/y radii 5147ea439b2203855db97330b25945b87dd4b170b8begdaniel fInnerRectUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility, 5157ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec4f_GrSLType, kDefault_GrSLPrecision, 5167ea439b2203855db97330b25945b87dd4b170b8begdaniel "innerRect", 5177ea439b2203855db97330b25945b87dd4b170b8begdaniel &rectName); 51830ba436f04e61d4505fb854d5fc56079636e0788joshualitt 5194ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; 5204ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel const char* fragmentPos = fragBuilder->fragmentPosition(); 5214355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos 5224355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // to the ellipse center. The vector is pinned in x and y to be in the quarter-plane relevant 5234355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // to that corner. This means that points near the interior near the rrect top edge will have 5244355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // a vector that points straight up for both the TL left and TR corners. Computing an 5254355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // alpha from this vector at either the TR or TL corner will give the correct result. Similarly, 5264355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // fragments near the other three edges will get the correct AA. Fragments in the interior of 5274355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // the rrect will have a (0,0) vector at all four corners. So long as the radii > 0.5 they will 5284355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // correctly produce an alpha value of 1 at all four corners. We take the min of all the alphas. 529c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon // 5304355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // The code below is a simplified version of the above that performs maxs on the vector 5314355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // components before computing distances and alpha values so that only one distance computation 5324355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // need be computed to determine the min alpha. 5334ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); 5344ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName); 535c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon // The uniforms with the inv squared radii are highp to prevent underflow. 5369615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org switch (erre.getRRect().getType()) { 5379615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org case SkRRect::kSimple_Type: { 538fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org const char *invRadiiXYSqdName; 5397ea439b2203855db97330b25945b87dd4b170b8begdaniel fInvRadiiSqdUniform = uniformHandler->addUniform( 5407ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler::kFragment_Visibility, 5412d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel kVec2f_GrSLType, kHigh_GrSLPrecision, 5422d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel "invRadiiXY", 5432d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel &invRadiiXYSqdName); 5444ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); 545fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org // Z is the x/y offsets divided by squared radii. 5464ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName); 547fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org break; 548fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org } 5499615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org case SkRRect::kNinePatch_Type: { 550fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org const char *invRadiiLTRBSqdName; 5517ea439b2203855db97330b25945b87dd4b170b8begdaniel fInvRadiiSqdUniform = uniformHandler->addUniform( 5527ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler::kFragment_Visibility, 5532d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel kVec4f_GrSLType, kHigh_GrSLPrecision, 5542d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel "invRadiiLTRB", 5552d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel &invRadiiLTRBSqdName); 5564ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); 557fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org // Z is the x/y offsets divided by squared radii. We only care about the (at most) one 558fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org // corner where both the x and y offsets are positive, hence the maxes. (The inverse 559fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org // squared radii will always be positive.) 5604ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);\n", 5614ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel invRadiiLTRBSqdName, invRadiiLTRBSqdName); 562fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org break; 5639615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org } 5649615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org default: 56588cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org SkFAIL("RRect should always be simple or nine-patch."); 566fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org } 5674355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. 5684ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); 5694355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org // grad_dot is the squared length of the gradient of the implicit. 5704ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); 5711b035d82d2b8b50ae334463edd06e4c5e0639311commit-bot@chromium.org // avoid calling inversesqrt on zero. 5724ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); 5734ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n"); 5744355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 575b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) { 5764ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n"); 5774355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org } else { 5784ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n"); 5794355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org } 5804355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 5814ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor, 5824ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str()); 5834355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org} 5844355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 585cfc18867d982119d9dc2888bf09f1093012daaddjvanverthvoid GLEllipticalRRectEffect::GenKey(const GrProcessor& effect, const GrGLSLCaps&, 586b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 58749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>(); 588b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_STATIC_ASSERT(kLast_GrProcessorEdgeType < (1 << 3)); 58963e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon b->add32(erre.getRRect().getType() | erre.getEdgeType() << 3); 5904355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org} 5914355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 592018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GLEllipticalRRectEffect::onSetData(const GrGLSLProgramDataManager& pdman, 593018fb62d12d1febf121fe265da5b6117b86a6541egdaniel const GrProcessor& effect) { 59449586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>(); 5954355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org const SkRRect& rrect = erre.getRRect(); 5964355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org if (rrect != fPrevRRect) { 5974355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org SkRect rect = rrect.getBounds(); 598fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org const SkVector& r0 = rrect.radii(SkRRect::kUpperLeft_Corner); 5992a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkASSERT(r0.fX >= kRadiusMin); 6002a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkASSERT(r0.fY >= kRadiusMin); 6019615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org switch (erre.getRRect().getType()) { 6029615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org case SkRRect::kSimple_Type: 603fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org rect.inset(r0.fX, r0.fY); 6047510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX), 605fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org 1.f / (r0.fY * r0.fY)); 606fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org break; 6079615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org case SkRRect::kNinePatch_Type: { 608fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org const SkVector& r1 = rrect.radii(SkRRect::kLowerRight_Corner); 6092a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkASSERT(r1.fX >= kRadiusMin); 6102a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkASSERT(r1.fY >= kRadiusMin); 611fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org rect.fLeft += r0.fX; 612fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org rect.fTop += r0.fY; 613fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org rect.fRight -= r1.fX; 614fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org rect.fBottom -= r1.fY; 6157510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set4f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX), 616fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org 1.f / (r0.fY * r0.fY), 617fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org 1.f / (r1.fX * r1.fX), 618fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org 1.f / (r1.fY * r1.fY)); 619fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org break; 620fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org } 6219615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org default: 62288cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org SkFAIL("RRect should always be simple or nine-patch."); 623fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org } 6247510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); 6254355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org fPrevRRect = rrect; 6264355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org } 6274355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org} 6284355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 629eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt//////////////////////////////////////////////////////////////////////////////////////////////////// 630eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 63157d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielvoid EllipticalRRectEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, 63257d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 633eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GLEllipticalRRectEffect::GenKey(*this, caps, b); 634eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 635eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 63657d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* EllipticalRRectEffect::onCreateGLSLInstance() const { 637385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new GLEllipticalRRectEffect(*this); 638eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 639eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 6404355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org////////////////////////////////////////////////////////////////////////////// 6414355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org 642b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrRRectEffect::Create(GrPrimitiveEdgeType edgeType, const SkRRect& rrect) { 6432a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org if (rrect.isRect()) { 6442a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org return GrConvexPolyEffect::Create(edgeType, rrect.getBounds()); 6452a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org } 6462a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org 6473eedb801e35001df4b7e154edf4fd8da942296a0commit-bot@chromium.org if (rrect.isOval()) { 6483eedb801e35001df4b7e154edf4fd8da942296a0commit-bot@chromium.org return GrOvalEffect::Create(edgeType, rrect.getBounds()); 6493eedb801e35001df4b7e154edf4fd8da942296a0commit-bot@chromium.org } 6503eedb801e35001df4b7e154edf4fd8da942296a0commit-bot@chromium.org 6514355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org if (rrect.isSimple()) { 6522a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org if (rrect.getSimpleRadii().fX < kRadiusMin || rrect.getSimpleRadii().fY < kRadiusMin) { 6532a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org // In this case the corners are extremely close to rectangular and we collapse the 6542a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org // clip to a rectangular clip. 6552a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org return GrConvexPolyEffect::Create(edgeType, rrect.getBounds()); 6562a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org } 6574355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org if (rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY) { 6586e4eb21d9c4cf10585b705d1a0ded8cafef29adcskia.committer@gmail.com return CircularRRectEffect::Create(edgeType, CircularRRectEffect::kAll_CornerFlags, 6592a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org rrect); 6604355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org } else { 6619615d5fc040e7302ce870639ab221233f56fff7ccommit-bot@chromium.org return EllipticalRRectEffect::Create(edgeType, rrect); 662cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } 6632a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org } 6642a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org 6652a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org if (rrect.isComplex() || rrect.isNinePatch()) { 666cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org // Check for the "tab" cases - two adjacent circular corners and two square corners. 6672a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkScalar circularRadius = 0; 6682a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org uint32_t cornerFlags = 0; 6692a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org 6702a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkVector radii[4]; 6712a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org bool squashedRadii = false; 672cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org for (int c = 0; c < 4; ++c) { 6732a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org radii[c] = rrect.radii((SkRRect::Corner)c); 6742a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkASSERT((0 == radii[c].fX) == (0 == radii[c].fY)); 6752a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org if (0 == radii[c].fX) { 6762a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org // The corner is square, so no need to squash or flag as circular. 6772a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org continue; 6782a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org } 6792a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org if (radii[c].fX < kRadiusMin || radii[c].fY < kRadiusMin) { 6802a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org radii[c].set(0, 0); 6812a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org squashedRadii = true; 682cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org continue; 683cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } 6842a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org if (radii[c].fX != radii[c].fY) { 68544a435bc1ac84748d5bec420c7c5fe09171fd971bsalomon@google.com cornerFlags = ~0U; 686fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org break; 687cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } 688dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org if (!cornerFlags) { 6892a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org circularRadius = radii[c].fX; 690dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org cornerFlags = 1 << c; 691cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } else { 6922a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org if (radii[c].fX != circularRadius) { 69344a435bc1ac84748d5bec420c7c5fe09171fd971bsalomon@google.com cornerFlags = ~0U; 694fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org break; 695cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } 696dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org cornerFlags |= 1 << c; 697cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } 698cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } 699cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org 700dd58422b4b2bffb0f7b5bdc047d0f93bd93813b4commit-bot@chromium.org switch (cornerFlags) { 7012a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org case CircularRRectEffect::kAll_CornerFlags: 7022a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org // This rrect should have been caught in the simple case above. Though, it would 7032a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org // be correctly handled in the fallthrough code. 7042a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkASSERT(false); 7054355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kTopLeft_CornerFlag: 7064355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kTopRight_CornerFlag: 7074355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kBottomRight_CornerFlag: 7084355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kBottomLeft_CornerFlag: 7094355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kLeft_CornerFlags: 7104355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kTop_CornerFlags: 7114355f21dbc29bcb479a3806444dd22916e22771ecommit-bot@chromium.org case CircularRRectEffect::kRight_CornerFlags: 7122a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org case CircularRRectEffect::kBottom_CornerFlags: { 7132a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org SkTCopyOnFirstWrite<SkRRect> rr(rrect); 7142a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org if (squashedRadii) { 7152a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org rr.writable()->setRectRadii(rrect.getBounds(), radii); 7162a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org } 7172a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org return CircularRRectEffect::Create(edgeType, cornerFlags, *rr); 7182a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org } 7192a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org case CircularRRectEffect::kNone_CornerFlags: 7202a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org return GrConvexPolyEffect::Create(edgeType, rrect.getBounds()); 7212a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org default: { 7222a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org if (squashedRadii) { 7232a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org // If we got here then we squashed some but not all the radii to zero. (If all 7242a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org // had been squashed cornerFlags would be 0.) The elliptical effect doesn't 7252a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org // support some rounded and some square corners. 72696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 7272a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org } 728fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org if (rrect.isNinePatch()) { 7292a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org return EllipticalRRectEffect::Create(edgeType, rrect); 730fa5edbe5750632b4590ed951c594dd2766ccc4cfcommit-bot@chromium.org } 73196fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 7322a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org } 733cb3672ed7fb9a5d54849e3265e8399bc5224bacecommit-bot@chromium.org } 734c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org } 7352a8be900db664bb26dca1adcb3a524a1bb1f45e6commit-bot@chromium.org 73696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 737c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org} 738