Home | History | Annotate | Download | only in gradients
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "Sk4fLinearGradient.h"
      9 #include "SkGradientShaderPriv.h"
     10 #include "SkLinearGradient.h"
     11 #include "SkRadialGradient.h"
     12 #include "SkTwoPointConicalGradient.h"
     13 #include "SkSweepGradient.h"
     14 
     15 void SkGradientShaderBase::Descriptor::flatten(SkWriteBuffer& buffer) const {
     16     buffer.writeColorArray(fColors, fCount);
     17     if (fPos) {
     18         buffer.writeBool(true);
     19         buffer.writeScalarArray(fPos, fCount);
     20     } else {
     21         buffer.writeBool(false);
     22     }
     23     buffer.write32(fTileMode);
     24     buffer.write32(fGradFlags);
     25     if (fLocalMatrix) {
     26         buffer.writeBool(true);
     27         buffer.writeMatrix(*fLocalMatrix);
     28     } else {
     29         buffer.writeBool(false);
     30     }
     31 }
     32 
     33 bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) {
     34     fCount = buffer.getArrayCount();
     35     if (fCount > kStorageCount) {
     36         size_t allocSize = (sizeof(SkColor) + sizeof(SkScalar)) * fCount;
     37         fDynamicStorage.reset(allocSize);
     38         fColors = (SkColor*)fDynamicStorage.get();
     39         fPos = (SkScalar*)(fColors + fCount);
     40     } else {
     41         fColors = fColorStorage;
     42         fPos = fPosStorage;
     43     }
     44 
     45     if (!buffer.readColorArray(const_cast<SkColor*>(fColors), fCount)) {
     46         return false;
     47     }
     48     if (buffer.readBool()) {
     49         if (!buffer.readScalarArray(const_cast<SkScalar*>(fPos), fCount)) {
     50             return false;
     51         }
     52     } else {
     53         fPos = nullptr;
     54     }
     55 
     56     fTileMode = (SkShader::TileMode)buffer.read32();
     57     fGradFlags = buffer.read32();
     58 
     59     if (buffer.readBool()) {
     60         fLocalMatrix = &fLocalMatrixStorage;
     61         buffer.readMatrix(&fLocalMatrixStorage);
     62     } else {
     63         fLocalMatrix = nullptr;
     64     }
     65     return buffer.isValid();
     66 }
     67 
     68 ////////////////////////////////////////////////////////////////////////////////////////////
     69 
     70 SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit)
     71     : INHERITED(desc.fLocalMatrix)
     72     , fPtsToUnit(ptsToUnit)
     73 {
     74     fPtsToUnit.getType();  // Precache so reads are threadsafe.
     75     SkASSERT(desc.fCount > 1);
     76 
     77     fGradFlags = SkToU8(desc.fGradFlags);
     78 
     79     SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount);
     80     SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs));
     81     fTileMode = desc.fTileMode;
     82     fTileProc = gTileProcs[desc.fTileMode];
     83 
     84     /*  Note: we let the caller skip the first and/or last position.
     85         i.e. pos[0] = 0.3, pos[1] = 0.7
     86         In these cases, we insert dummy entries to ensure that the final data
     87         will be bracketed by [0, 1].
     88         i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1
     89 
     90         Thus colorCount (the caller's value, and fColorCount (our value) may
     91         differ by up to 2. In the above example:
     92             colorCount = 2
     93             fColorCount = 4
     94      */
     95     fColorCount = desc.fCount;
     96     // check if we need to add in dummy start and/or end position/colors
     97     bool dummyFirst = false;
     98     bool dummyLast = false;
     99     if (desc.fPos) {
    100         dummyFirst = desc.fPos[0] != 0;
    101         dummyLast = desc.fPos[desc.fCount - 1] != SK_Scalar1;
    102         fColorCount += dummyFirst + dummyLast;
    103     }
    104 
    105     if (fColorCount > kColorStorageCount) {
    106         size_t size = sizeof(SkColor) + sizeof(Rec);
    107         if (desc.fPos) {
    108             size += sizeof(SkScalar);
    109         }
    110         fOrigColors = reinterpret_cast<SkColor*>(
    111                                         sk_malloc_throw(size * fColorCount));
    112     }
    113     else {
    114         fOrigColors = fStorage;
    115     }
    116 
    117     // Now copy over the colors, adding the dummies as needed
    118     {
    119         SkColor* origColors = fOrigColors;
    120         if (dummyFirst) {
    121             *origColors++ = desc.fColors[0];
    122         }
    123         memcpy(origColors, desc.fColors, desc.fCount * sizeof(SkColor));
    124         if (dummyLast) {
    125             origColors += desc.fCount;
    126             *origColors = desc.fColors[desc.fCount - 1];
    127         }
    128     }
    129 
    130     if (desc.fPos && fColorCount) {
    131         fOrigPos = (SkScalar*)(fOrigColors + fColorCount);
    132         fRecs = (Rec*)(fOrigPos + fColorCount);
    133     } else {
    134         fOrigPos = nullptr;
    135         fRecs = (Rec*)(fOrigColors + fColorCount);
    136     }
    137 
    138     if (fColorCount > 2) {
    139         Rec* recs = fRecs;
    140         recs->fPos = 0;
    141         //  recs->fScale = 0; // unused;
    142         recs += 1;
    143         if (desc.fPos) {
    144             SkScalar* origPosPtr = fOrigPos;
    145             *origPosPtr++ = 0;
    146 
    147             /*  We need to convert the user's array of relative positions into
    148                 fixed-point positions and scale factors. We need these results
    149                 to be strictly monotonic (no two values equal or out of order).
    150                 Hence this complex loop that just jams a zero for the scale
    151                 value if it sees a segment out of order, and it assures that
    152                 we start at 0 and end at 1.0
    153             */
    154             SkScalar prev = 0;
    155             int startIndex = dummyFirst ? 0 : 1;
    156             int count = desc.fCount + dummyLast;
    157             for (int i = startIndex; i < count; i++) {
    158                 // force the last value to be 1.0
    159                 SkScalar curr;
    160                 if (i == desc.fCount) {  // we're really at the dummyLast
    161                     curr = 1;
    162                 } else {
    163                     curr = SkScalarPin(desc.fPos[i], 0, 1);
    164                 }
    165                 *origPosPtr++ = curr;
    166 
    167                 recs->fPos = SkScalarToFixed(curr);
    168                 SkFixed diff = SkScalarToFixed(curr - prev);
    169                 if (diff > 0) {
    170                     recs->fScale = (1 << 24) / diff;
    171                 } else {
    172                     recs->fScale = 0; // ignore this segment
    173                 }
    174                 // get ready for the next value
    175                 prev = curr;
    176                 recs += 1;
    177             }
    178         } else {    // assume even distribution
    179             fOrigPos = nullptr;
    180 
    181             SkFixed dp = SK_Fixed1 / (desc.fCount - 1);
    182             SkFixed p = dp;
    183             SkFixed scale = (desc.fCount - 1) << 8;  // (1 << 24) / dp
    184             for (int i = 1; i < desc.fCount - 1; i++) {
    185                 recs->fPos   = p;
    186                 recs->fScale = scale;
    187                 recs += 1;
    188                 p += dp;
    189             }
    190             recs->fPos = SK_Fixed1;
    191             recs->fScale = scale;
    192         }
    193     } else if (desc.fPos) {
    194         SkASSERT(2 == fColorCount);
    195         fOrigPos[0] = SkScalarPin(desc.fPos[0], 0, 1);
    196         fOrigPos[1] = SkScalarPin(desc.fPos[1], fOrigPos[0], 1);
    197         if (0 == fOrigPos[0] && 1 == fOrigPos[1]) {
    198             fOrigPos = nullptr;
    199         }
    200     }
    201     this->initCommon();
    202 }
    203 
    204 SkGradientShaderBase::~SkGradientShaderBase() {
    205     if (fOrigColors != fStorage) {
    206         sk_free(fOrigColors);
    207     }
    208 }
    209 
    210 void SkGradientShaderBase::initCommon() {
    211     unsigned colorAlpha = 0xFF;
    212     for (int i = 0; i < fColorCount; i++) {
    213         colorAlpha &= SkColorGetA(fOrigColors[i]);
    214     }
    215     fColorsAreOpaque = colorAlpha == 0xFF;
    216 }
    217 
    218 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
    219     Descriptor desc;
    220     desc.fColors = fOrigColors;
    221     desc.fPos = fOrigPos;
    222     desc.fCount = fColorCount;
    223     desc.fTileMode = fTileMode;
    224     desc.fGradFlags = fGradFlags;
    225 
    226     const SkMatrix& m = this->getLocalMatrix();
    227     desc.fLocalMatrix = m.isIdentity() ? nullptr : &m;
    228     desc.flatten(buffer);
    229 }
    230 
    231 SkGradientShaderBase::GpuColorType SkGradientShaderBase::getGpuColorType(SkColor colors[3]) const {
    232     if (fColorCount <= 3) {
    233         memcpy(colors, fOrigColors, fColorCount * sizeof(SkColor));
    234     }
    235 
    236     if (SkShader::kClamp_TileMode == fTileMode) {
    237         if (2 == fColorCount) {
    238             return kTwo_GpuColorType;
    239         } else if (3 == fColorCount &&
    240                    (SkScalarAbs(
    241                     SkFixedToScalar(fRecs[1].fPos) - SK_ScalarHalf) < SK_Scalar1 / 1000)) {
    242             return kThree_GpuColorType;
    243         }
    244     }
    245     return kTexture_GpuColorType;
    246 }
    247 
    248 void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
    249                                               SkColor* colorSrc, Rec* recSrc,
    250                                               int count) {
    251     SkAutoSTArray<8, SkColor> colorsTemp(count);
    252     for (int i = 0; i < count; ++i) {
    253         int offset = count - i - 1;
    254         colorsTemp[i] = colorSrc[offset];
    255     }
    256     if (count > 2) {
    257         SkAutoSTArray<8, Rec> recsTemp(count);
    258         for (int i = 0; i < count; ++i) {
    259             int offset = count - i - 1;
    260             recsTemp[i].fPos = SK_Fixed1 - recSrc[offset].fPos;
    261             recsTemp[i].fScale = recSrc[offset].fScale;
    262         }
    263         memcpy(recDst, recsTemp.get(), count * sizeof(Rec));
    264     }
    265     memcpy(colorDst, colorsTemp.get(), count * sizeof(SkColor));
    266 }
    267 
    268 bool SkGradientShaderBase::isOpaque() const {
    269     return fColorsAreOpaque;
    270 }
    271 
    272 static unsigned rounded_divide(unsigned numer, unsigned denom) {
    273     return (numer + (denom >> 1)) / denom;
    274 }
    275 
    276 bool SkGradientShaderBase::onAsLuminanceColor(SkColor* lum) const {
    277     // we just compute an average color.
    278     // possibly we could weight this based on the proportional width for each color
    279     //   assuming they are not evenly distributed in the fPos array.
    280     int r = 0;
    281     int g = 0;
    282     int b = 0;
    283     const int n = fColorCount;
    284     for (int i = 0; i < n; ++i) {
    285         SkColor c = fOrigColors[i];
    286         r += SkColorGetR(c);
    287         g += SkColorGetG(c);
    288         b += SkColorGetB(c);
    289     }
    290     *lum = SkColorSetRGB(rounded_divide(r, n), rounded_divide(g, n), rounded_divide(b, n));
    291     return true;
    292 }
    293 
    294 SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext(
    295         const SkGradientShaderBase& shader, const ContextRec& rec)
    296     : INHERITED(shader, rec)
    297 #ifdef SK_SUPPORT_LEGACY_GRADIENT_DITHERING
    298     , fDither(true)
    299 #else
    300     , fDither(rec.fPaint->isDither())
    301 #endif
    302     , fCache(shader.refCache(getPaintAlpha(), fDither))
    303 {
    304     const SkMatrix& inverse = this->getTotalInverse();
    305 
    306     fDstToIndex.setConcat(shader.fPtsToUnit, inverse);
    307 
    308     fDstToIndexProc = fDstToIndex.getMapXYProc();
    309     fDstToIndexClass = (uint8_t)SkShader::Context::ComputeMatrixClass(fDstToIndex);
    310 
    311     // now convert our colors in to PMColors
    312     unsigned paintAlpha = this->getPaintAlpha();
    313 
    314     fFlags = this->INHERITED::getFlags();
    315     if (shader.fColorsAreOpaque && paintAlpha == 0xFF) {
    316         fFlags |= kOpaqueAlpha_Flag;
    317     }
    318 }
    319 
    320 SkGradientShaderBase::GradientShaderCache::GradientShaderCache(
    321         U8CPU alpha, bool dither, const SkGradientShaderBase& shader)
    322     : fCacheAlpha(alpha)
    323     , fCacheDither(dither)
    324     , fShader(shader)
    325     , fCache16Inited(false)
    326     , fCache32Inited(false)
    327 {
    328     // Only initialize the cache in getCache16/32.
    329     fCache16 = nullptr;
    330     fCache32 = nullptr;
    331     fCache16Storage = nullptr;
    332     fCache32PixelRef = nullptr;
    333 }
    334 
    335 SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() {
    336     sk_free(fCache16Storage);
    337     SkSafeUnref(fCache32PixelRef);
    338 }
    339 
    340 #define Fixed_To_Dot8(x)        (((x) + 0x80) >> 8)
    341 
    342 /** We take the original colors, not our premultiplied PMColors, since we can
    343     build a 16bit table as long as the original colors are opaque, even if the
    344     paint specifies a non-opaque alpha.
    345 */
    346 void SkGradientShaderBase::GradientShaderCache::Build16bitCache(
    347         uint16_t cache[], SkColor c0, SkColor c1, int count, bool dither) {
    348     SkASSERT(count > 1);
    349     SkASSERT(SkColorGetA(c0) == 0xFF);
    350     SkASSERT(SkColorGetA(c1) == 0xFF);
    351 
    352     SkFixed r = SkColorGetR(c0);
    353     SkFixed g = SkColorGetG(c0);
    354     SkFixed b = SkColorGetB(c0);
    355 
    356     SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
    357     SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
    358     SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);
    359 
    360     r = SkIntToFixed(r) + 0x8000;
    361     g = SkIntToFixed(g) + 0x8000;
    362     b = SkIntToFixed(b) + 0x8000;
    363 
    364     if (dither) {
    365         do {
    366             unsigned rr = r >> 16;
    367             unsigned gg = g >> 16;
    368             unsigned bb = b >> 16;
    369             cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb));
    370             cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb);
    371             cache += 1;
    372             r += dr;
    373             g += dg;
    374             b += db;
    375         } while (--count != 0);
    376     } else {
    377         do {
    378             unsigned rr = r >> 16;
    379             unsigned gg = g >> 16;
    380             unsigned bb = b >> 16;
    381             cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb));
    382             cache[kCache16Count] = cache[0];
    383             cache += 1;
    384             r += dr;
    385             g += dg;
    386             b += db;
    387         } while (--count != 0);
    388     }
    389 }
    390 
    391 /*
    392  *  r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in
    393  *  release builds, we saw a compiler error where the 0xFF parameter in
    394  *  SkPackARGB32() was being totally ignored whenever it was called with
    395  *  a non-zero add (e.g. 0x8000).
    396  *
    397  *  We found two work-arounds:
    398  *      1. change r,g,b to unsigned (or just one of them)
    399  *      2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead
    400  *         of using |
    401  *
    402  *  We chose #1 just because it was more localized.
    403  *  See http://code.google.com/p/skia/issues/detail?id=1113
    404  *
    405  *  The type SkUFixed encapsulate this need for unsigned, but logically Fixed.
    406  */
    407 typedef uint32_t SkUFixed;
    408 
    409 void SkGradientShaderBase::GradientShaderCache::Build32bitCache(
    410         SkPMColor cache[], SkColor c0, SkColor c1,
    411         int count, U8CPU paintAlpha, uint32_t gradFlags, bool dither) {
    412     SkASSERT(count > 1);
    413 
    414     // need to apply paintAlpha to our two endpoints
    415     uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
    416     uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);
    417 
    418 
    419     const bool interpInPremul = SkToBool(gradFlags &
    420                            SkGradientShader::kInterpolateColorsInPremul_Flag);
    421 
    422     uint32_t r0 = SkColorGetR(c0);
    423     uint32_t g0 = SkColorGetG(c0);
    424     uint32_t b0 = SkColorGetB(c0);
    425 
    426     uint32_t r1 = SkColorGetR(c1);
    427     uint32_t g1 = SkColorGetG(c1);
    428     uint32_t b1 = SkColorGetB(c1);
    429 
    430     if (interpInPremul) {
    431         r0 = SkMulDiv255Round(r0, a0);
    432         g0 = SkMulDiv255Round(g0, a0);
    433         b0 = SkMulDiv255Round(b0, a0);
    434 
    435         r1 = SkMulDiv255Round(r1, a1);
    436         g1 = SkMulDiv255Round(g1, a1);
    437         b1 = SkMulDiv255Round(b1, a1);
    438     }
    439 
    440     SkFixed da = SkIntToFixed(a1 - a0) / (count - 1);
    441     SkFixed dr = SkIntToFixed(r1 - r0) / (count - 1);
    442     SkFixed dg = SkIntToFixed(g1 - g0) / (count - 1);
    443     SkFixed db = SkIntToFixed(b1 - b0) / (count - 1);
    444 
    445     /*  We pre-add 1/8 to avoid having to add this to our [0] value each time
    446         in the loop. Without this, the bias for each would be
    447             0x2000  0xA000  0xE000  0x6000
    448         With this trick, we can add 0 for the first (no-op) and just adjust the
    449         others.
    450      */
    451     const SkUFixed bias0 = dither ? 0x2000 : 0x8000;
    452     const SkUFixed bias1 = dither ? 0x8000 : 0;
    453     const SkUFixed bias2 = dither ? 0xC000 : 0;
    454     const SkUFixed bias3 = dither ? 0x4000 : 0;
    455 
    456     SkUFixed a = SkIntToFixed(a0) + bias0;
    457     SkUFixed r = SkIntToFixed(r0) + bias0;
    458     SkUFixed g = SkIntToFixed(g0) + bias0;
    459     SkUFixed b = SkIntToFixed(b0) + bias0;
    460 
    461     /*
    462      *  Our dither-cell (spatially) is
    463      *      0 2
    464      *      3 1
    465      *  Where
    466      *      [0] -> [-1/8 ... 1/8 ) values near 0
    467      *      [1] -> [ 1/8 ... 3/8 ) values near 1/4
    468      *      [2] -> [ 3/8 ... 5/8 ) values near 1/2
    469      *      [3] -> [ 5/8 ... 7/8 ) values near 3/4
    470      */
    471 
    472     if (0xFF == a0 && 0 == da) {
    473         do {
    474             cache[kCache32Count*0] = SkPackARGB32(0xFF, (r + 0    ) >> 16,
    475                                                         (g + 0    ) >> 16,
    476                                                         (b + 0    ) >> 16);
    477             cache[kCache32Count*1] = SkPackARGB32(0xFF, (r + bias1) >> 16,
    478                                                         (g + bias1) >> 16,
    479                                                         (b + bias1) >> 16);
    480             cache[kCache32Count*2] = SkPackARGB32(0xFF, (r + bias2) >> 16,
    481                                                         (g + bias2) >> 16,
    482                                                         (b + bias2) >> 16);
    483             cache[kCache32Count*3] = SkPackARGB32(0xFF, (r + bias3) >> 16,
    484                                                         (g + bias3) >> 16,
    485                                                         (b + bias3) >> 16);
    486             cache += 1;
    487             r += dr;
    488             g += dg;
    489             b += db;
    490         } while (--count != 0);
    491     } else if (interpInPremul) {
    492         do {
    493             cache[kCache32Count*0] = SkPackARGB32((a + 0    ) >> 16,
    494                                                   (r + 0    ) >> 16,
    495                                                   (g + 0    ) >> 16,
    496                                                   (b + 0    ) >> 16);
    497             cache[kCache32Count*1] = SkPackARGB32((a + bias1) >> 16,
    498                                                   (r + bias1) >> 16,
    499                                                   (g + bias1) >> 16,
    500                                                   (b + bias1) >> 16);
    501             cache[kCache32Count*2] = SkPackARGB32((a + bias2) >> 16,
    502                                                   (r + bias2) >> 16,
    503                                                   (g + bias2) >> 16,
    504                                                   (b + bias2) >> 16);
    505             cache[kCache32Count*3] = SkPackARGB32((a + bias3) >> 16,
    506                                                   (r + bias3) >> 16,
    507                                                   (g + bias3) >> 16,
    508                                                   (b + bias3) >> 16);
    509             cache += 1;
    510             a += da;
    511             r += dr;
    512             g += dg;
    513             b += db;
    514         } while (--count != 0);
    515     } else {    // interpolate in unpreml space
    516         do {
    517             cache[kCache32Count*0] = SkPremultiplyARGBInline((a + 0     ) >> 16,
    518                                                              (r + 0     ) >> 16,
    519                                                              (g + 0     ) >> 16,
    520                                                              (b + 0     ) >> 16);
    521             cache[kCache32Count*1] = SkPremultiplyARGBInline((a + bias1) >> 16,
    522                                                              (r + bias1) >> 16,
    523                                                              (g + bias1) >> 16,
    524                                                              (b + bias1) >> 16);
    525             cache[kCache32Count*2] = SkPremultiplyARGBInline((a + bias2) >> 16,
    526                                                              (r + bias2) >> 16,
    527                                                              (g + bias2) >> 16,
    528                                                              (b + bias2) >> 16);
    529             cache[kCache32Count*3] = SkPremultiplyARGBInline((a + bias3) >> 16,
    530                                                              (r + bias3) >> 16,
    531                                                              (g + bias3) >> 16,
    532                                                              (b + bias3) >> 16);
    533             cache += 1;
    534             a += da;
    535             r += dr;
    536             g += dg;
    537             b += db;
    538         } while (--count != 0);
    539     }
    540 }
    541 
    542 static inline int SkFixedToFFFF(SkFixed x) {
    543     SkASSERT((unsigned)x <= SK_Fixed1);
    544     return x - (x >> 16);
    545 }
    546 
    547 const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16() {
    548     SkOnce(&fCache16Inited, &fCache16Mutex, SkGradientShaderBase::GradientShaderCache::initCache16,
    549            this);
    550     SkASSERT(fCache16);
    551     return fCache16;
    552 }
    553 
    554 void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache* cache) {
    555     // double the count for dither entries
    556     const int entryCount = kCache16Count * 2;
    557     const size_t allocSize = sizeof(uint16_t) * entryCount;
    558 
    559     SkASSERT(nullptr == cache->fCache16Storage);
    560     cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
    561     cache->fCache16 = cache->fCache16Storage;
    562     if (cache->fShader.fColorCount == 2) {
    563         Build16bitCache(cache->fCache16, cache->fShader.fOrigColors[0],
    564                         cache->fShader.fOrigColors[1], kCache16Count, cache->fCacheDither);
    565     } else {
    566         Rec* rec = cache->fShader.fRecs;
    567         int prevIndex = 0;
    568         for (int i = 1; i < cache->fShader.fColorCount; i++) {
    569             int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift;
    570             SkASSERT(nextIndex < kCache16Count);
    571 
    572             if (nextIndex > prevIndex)
    573                 Build16bitCache(cache->fCache16 + prevIndex, cache->fShader.fOrigColors[i-1],
    574                                 cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1,
    575                                 cache->fCacheDither);
    576             prevIndex = nextIndex;
    577         }
    578     }
    579 }
    580 
    581 const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32() {
    582     SkOnce(&fCache32Inited, &fCache32Mutex, SkGradientShaderBase::GradientShaderCache::initCache32,
    583            this);
    584     SkASSERT(fCache32);
    585     return fCache32;
    586 }
    587 
    588 void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache* cache) {
    589     const int kNumberOfDitherRows = 4;
    590     const SkImageInfo info = SkImageInfo::MakeN32Premul(kCache32Count, kNumberOfDitherRows);
    591 
    592     SkASSERT(nullptr == cache->fCache32PixelRef);
    593     cache->fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, nullptr);
    594     cache->fCache32 = (SkPMColor*)cache->fCache32PixelRef->getAddr();
    595     if (cache->fShader.fColorCount == 2) {
    596         Build32bitCache(cache->fCache32, cache->fShader.fOrigColors[0],
    597                         cache->fShader.fOrigColors[1], kCache32Count, cache->fCacheAlpha,
    598                         cache->fShader.fGradFlags, cache->fCacheDither);
    599     } else {
    600         Rec* rec = cache->fShader.fRecs;
    601         int prevIndex = 0;
    602         for (int i = 1; i < cache->fShader.fColorCount; i++) {
    603             int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift;
    604             SkASSERT(nextIndex < kCache32Count);
    605 
    606             if (nextIndex > prevIndex)
    607                 Build32bitCache(cache->fCache32 + prevIndex, cache->fShader.fOrigColors[i-1],
    608                                 cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1,
    609                                 cache->fCacheAlpha, cache->fShader.fGradFlags, cache->fCacheDither);
    610             prevIndex = nextIndex;
    611         }
    612     }
    613 }
    614 
    615 /*
    616  *  The gradient holds a cache for the most recent value of alpha. Successive
    617  *  callers with the same alpha value will share the same cache.
    618  */
    619 SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::refCache(U8CPU alpha,
    620                                                                           bool dither) const {
    621     SkAutoMutexAcquire ama(fCacheMutex);
    622     if (!fCache || fCache->getAlpha() != alpha || fCache->getDither() != dither) {
    623         fCache.reset(new GradientShaderCache(alpha, dither, *this));
    624     }
    625     // Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
    626     // Otherwise, the pointer may have been overwritten on a different thread before the object's
    627     // ref count was incremented.
    628     fCache.get()->ref();
    629     return fCache;
    630 }
    631 
    632 SK_DECLARE_STATIC_MUTEX(gGradientCacheMutex);
    633 /*
    634  *  Because our caller might rebuild the same (logically the same) gradient
    635  *  over and over, we'd like to return exactly the same "bitmap" if possible,
    636  *  allowing the client to utilize a cache of our bitmap (e.g. with a GPU).
    637  *  To do that, we maintain a private cache of built-bitmaps, based on our
    638  *  colors and positions. Note: we don't try to flatten the fMapper, so if one
    639  *  is present, we skip the cache for now.
    640  */
    641 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
    642     // our caller assumes no external alpha, so we ensure that our cache is
    643     // built with 0xFF
    644     SkAutoTUnref<GradientShaderCache> cache(this->refCache(0xFF, true));
    645 
    646     // build our key: [numColors + colors[] + {positions[]} + flags ]
    647     int count = 1 + fColorCount + 1;
    648     if (fColorCount > 2) {
    649         count += fColorCount - 1;    // fRecs[].fPos
    650     }
    651 
    652     SkAutoSTMalloc<16, int32_t> storage(count);
    653     int32_t* buffer = storage.get();
    654 
    655     *buffer++ = fColorCount;
    656     memcpy(buffer, fOrigColors, fColorCount * sizeof(SkColor));
    657     buffer += fColorCount;
    658     if (fColorCount > 2) {
    659         for (int i = 1; i < fColorCount; i++) {
    660             *buffer++ = fRecs[i].fPos;
    661         }
    662     }
    663     *buffer++ = fGradFlags;
    664     SkASSERT(buffer - storage.get() == count);
    665 
    666     ///////////////////////////////////
    667 
    668     static SkGradientBitmapCache* gCache;
    669     // each cache cost 1K of RAM, since each bitmap will be 1x256 at 32bpp
    670     static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32;
    671     SkAutoMutexAcquire ama(gGradientCacheMutex);
    672 
    673     if (nullptr == gCache) {
    674         gCache = new SkGradientBitmapCache(MAX_NUM_CACHED_GRADIENT_BITMAPS);
    675     }
    676     size_t size = count * sizeof(int32_t);
    677 
    678     if (!gCache->find(storage.get(), size, bitmap)) {
    679         // force our cahce32pixelref to be built
    680         (void)cache->getCache32();
    681         bitmap->setInfo(SkImageInfo::MakeN32Premul(kCache32Count, 1));
    682         bitmap->setPixelRef(cache->getCache32PixelRef());
    683 
    684         gCache->add(storage.get(), size, *bitmap);
    685     }
    686 }
    687 
    688 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info, bool flipGrad) const {
    689     if (info) {
    690         if (info->fColorCount >= fColorCount) {
    691             SkColor* colorLoc;
    692             Rec*     recLoc;
    693             if (flipGrad && (info->fColors || info->fColorOffsets)) {
    694                 SkAutoSTArray<8, SkColor> colorStorage(fColorCount);
    695                 SkAutoSTArray<8, Rec> recStorage(fColorCount);
    696                 colorLoc = colorStorage.get();
    697                 recLoc = recStorage.get();
    698                 FlipGradientColors(colorLoc, recLoc, fOrigColors, fRecs, fColorCount);
    699             } else {
    700                 colorLoc = fOrigColors;
    701                 recLoc = fRecs;
    702             }
    703             if (info->fColors) {
    704                 memcpy(info->fColors, colorLoc, fColorCount * sizeof(SkColor));
    705             }
    706             if (info->fColorOffsets) {
    707                 if (fColorCount == 2) {
    708                     info->fColorOffsets[0] = 0;
    709                     info->fColorOffsets[1] = SK_Scalar1;
    710                 } else if (fColorCount > 2) {
    711                     for (int i = 0; i < fColorCount; ++i) {
    712                         info->fColorOffsets[i] = SkFixedToScalar(recLoc[i].fPos);
    713                     }
    714                 }
    715             }
    716         }
    717         info->fColorCount = fColorCount;
    718         info->fTileMode = fTileMode;
    719         info->fGradientFlags = fGradFlags;
    720     }
    721 }
    722 
    723 #ifndef SK_IGNORE_TO_STRING
    724 void SkGradientShaderBase::toString(SkString* str) const {
    725 
    726     str->appendf("%d colors: ", fColorCount);
    727 
    728     for (int i = 0; i < fColorCount; ++i) {
    729         str->appendHex(fOrigColors[i], 8);
    730         if (i < fColorCount-1) {
    731             str->append(", ");
    732         }
    733     }
    734 
    735     if (fColorCount > 2) {
    736         str->append(" points: (");
    737         for (int i = 0; i < fColorCount; ++i) {
    738             str->appendScalar(SkFixedToScalar(fRecs[i].fPos));
    739             if (i < fColorCount-1) {
    740                 str->append(", ");
    741             }
    742         }
    743         str->append(")");
    744     }
    745 
    746     static const char* gTileModeName[SkShader::kTileModeCount] = {
    747         "clamp", "repeat", "mirror"
    748     };
    749 
    750     str->append(" ");
    751     str->append(gTileModeName[fTileMode]);
    752 
    753     this->INHERITED::toString(str);
    754 }
    755 #endif
    756 
    757 ///////////////////////////////////////////////////////////////////////////////
    758 ///////////////////////////////////////////////////////////////////////////////
    759 
    760 // Return true if these parameters are valid/legal/safe to construct a gradient
    761 //
    762 static bool valid_grad(const SkColor colors[], const SkScalar pos[], int count, unsigned tileMode) {
    763     return nullptr != colors && count >= 1 && tileMode < (unsigned)SkShader::kTileModeCount;
    764 }
    765 
    766 // assumes colors is SkColor* and pos is SkScalar*
    767 #define EXPAND_1_COLOR(count)               \
    768     SkColor tmp[2];                         \
    769     do {                                    \
    770         if (1 == count) {                   \
    771             tmp[0] = tmp[1] = colors[0];    \
    772             colors = tmp;                   \
    773             pos = nullptr;                     \
    774             count = 2;                      \
    775         }                                   \
    776     } while (0)
    777 
    778 static void desc_init(SkGradientShaderBase::Descriptor* desc,
    779                       const SkColor colors[], const SkScalar pos[], int colorCount,
    780                       SkShader::TileMode mode, uint32_t flags, const SkMatrix* localMatrix) {
    781     desc->fColors       = colors;
    782     desc->fPos          = pos;
    783     desc->fCount        = colorCount;
    784     desc->fTileMode     = mode;
    785     desc->fGradFlags    = flags;
    786     desc->fLocalMatrix  = localMatrix;
    787 }
    788 
    789 SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2],
    790                                          const SkColor colors[],
    791                                          const SkScalar pos[], int colorCount,
    792                                          SkShader::TileMode mode,
    793                                          uint32_t flags,
    794                                          const SkMatrix* localMatrix) {
    795     if (!pts) {
    796         return nullptr;
    797     }
    798     if (!valid_grad(colors, pos, colorCount, mode)) {
    799         return nullptr;
    800     }
    801     EXPAND_1_COLOR(colorCount);
    802 
    803     SkGradientShaderBase::Descriptor desc;
    804     desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix);
    805     return new SkLinearGradient(pts, desc);
    806 }
    807 
    808 SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius,
    809                                          const SkColor colors[],
    810                                          const SkScalar pos[], int colorCount,
    811                                          SkShader::TileMode mode,
    812                                          uint32_t flags,
    813                                          const SkMatrix* localMatrix) {
    814     if (radius <= 0) {
    815         return nullptr;
    816     }
    817     if (!valid_grad(colors, pos, colorCount, mode)) {
    818         return nullptr;
    819     }
    820     EXPAND_1_COLOR(colorCount);
    821 
    822     SkGradientShaderBase::Descriptor desc;
    823     desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix);
    824     return new SkRadialGradient(center, radius, desc);
    825 }
    826 
    827 SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
    828                                                   SkScalar startRadius,
    829                                                   const SkPoint& end,
    830                                                   SkScalar endRadius,
    831                                                   const SkColor colors[],
    832                                                   const SkScalar pos[],
    833                                                   int colorCount,
    834                                                   SkShader::TileMode mode,
    835                                                   uint32_t flags,
    836                                                   const SkMatrix* localMatrix) {
    837     if (startRadius < 0 || endRadius < 0) {
    838         return nullptr;
    839     }
    840     if (!valid_grad(colors, pos, colorCount, mode)) {
    841         return nullptr;
    842     }
    843     if (start == end && startRadius == endRadius) {
    844         return SkShader::CreateEmptyShader();
    845     }
    846 
    847     EXPAND_1_COLOR(colorCount);
    848 
    849     bool flipGradient = startRadius > endRadius;
    850 
    851     SkGradientShaderBase::Descriptor desc;
    852 
    853     if (!flipGradient) {
    854         desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix);
    855         return new SkTwoPointConicalGradient(start, startRadius, end, endRadius, flipGradient,
    856                                              desc);
    857     } else {
    858         SkAutoSTArray<8, SkColor> colorsNew(colorCount);
    859         SkAutoSTArray<8, SkScalar> posNew(colorCount);
    860         for (int i = 0; i < colorCount; ++i) {
    861             colorsNew[i] = colors[colorCount - i - 1];
    862         }
    863 
    864         if (pos) {
    865             for (int i = 0; i < colorCount; ++i) {
    866                 posNew[i] = 1 - pos[colorCount - i - 1];
    867             }
    868             desc_init(&desc, colorsNew.get(), posNew.get(), colorCount, mode, flags, localMatrix);
    869         } else {
    870             desc_init(&desc, colorsNew.get(), nullptr, colorCount, mode, flags, localMatrix);
    871         }
    872 
    873         return new SkTwoPointConicalGradient(end, endRadius, start, startRadius, flipGradient,
    874                                              desc);
    875     }
    876 }
    877 
    878 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
    879                                         const SkColor colors[],
    880                                         const SkScalar pos[],
    881                                         int colorCount,
    882                                         uint32_t flags,
    883                                         const SkMatrix* localMatrix) {
    884     if (!valid_grad(colors, pos, colorCount, SkShader::kClamp_TileMode)) {
    885         return nullptr;
    886     }
    887     EXPAND_1_COLOR(colorCount);
    888 
    889     SkGradientShaderBase::Descriptor desc;
    890     desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, flags, localMatrix);
    891     return new SkSweepGradient(cx, cy, desc);
    892 }
    893 
    894 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader)
    895     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLinearGradient)
    896     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialGradient)
    897     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient)
    898     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient)
    899 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
    900 
    901 ///////////////////////////////////////////////////////////////////////////////
    902 
    903 #if SK_SUPPORT_GPU
    904 
    905 #include "effects/GrTextureStripAtlas.h"
    906 #include "GrInvariantOutput.h"
    907 #include "gl/GrGLContext.h"
    908 #include "glsl/GrGLSLFragmentShaderBuilder.h"
    909 #include "glsl/GrGLSLProgramDataManager.h"
    910 #include "glsl/GrGLSLUniformHandler.h"
    911 #include "SkGr.h"
    912 
    913 GrGLGradientEffect::GrGLGradientEffect()
    914     : fCachedYCoord(SK_ScalarMax) {
    915 }
    916 
    917 void GrGLGradientEffect::emitUniforms(GrGLSLUniformHandler* uniformHandler,
    918                                       const GrGradientEffect& ge) {
    919 
    920     if (SkGradientShaderBase::kTwo_GpuColorType == ge.getColorType()) { // 2 Color case
    921         fColorStartUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
    922                                                     kVec4f_GrSLType, kDefault_GrSLPrecision,
    923                                                     "GradientStartColor");
    924         fColorEndUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
    925                                                   kVec4f_GrSLType, kDefault_GrSLPrecision,
    926                                                   "GradientEndColor");
    927 
    928     } else if (SkGradientShaderBase::kThree_GpuColorType == ge.getColorType()) { // 3 Color Case
    929         fColorStartUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
    930                                                     kVec4f_GrSLType,  kDefault_GrSLPrecision,
    931                                                     "GradientStartColor");
    932         fColorMidUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
    933                                                   kVec4f_GrSLType, kDefault_GrSLPrecision,
    934                                                   "GradientMidColor");
    935         fColorEndUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
    936                                                   kVec4f_GrSLType, kDefault_GrSLPrecision,
    937                                                   "GradientEndColor");
    938 
    939     } else { // if not a fast case
    940         fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
    941                                              kFloat_GrSLType, kDefault_GrSLPrecision,
    942                                              "GradientYCoordFS");
    943     }
    944 }
    945 
    946 static inline void set_color_uni(const GrGLSLProgramDataManager& pdman,
    947                                  const GrGLSLProgramDataManager::UniformHandle uni,
    948                                  const SkColor* color) {
    949        pdman.set4f(uni,
    950                    SkColorGetR(*color) / 255.f,
    951                    SkColorGetG(*color) / 255.f,
    952                    SkColorGetB(*color) / 255.f,
    953                    SkColorGetA(*color) / 255.f);
    954 }
    955 
    956 static inline void set_mul_color_uni(const GrGLSLProgramDataManager& pdman,
    957                                      const GrGLSLProgramDataManager::UniformHandle uni,
    958                                      const SkColor* color){
    959        float a = SkColorGetA(*color) / 255.f;
    960        float aDiv255 = a / 255.f;
    961        pdman.set4f(uni,
    962                    SkColorGetR(*color) * aDiv255,
    963                    SkColorGetG(*color) * aDiv255,
    964                    SkColorGetB(*color) * aDiv255,
    965                    a);
    966 }
    967 
    968 void GrGLGradientEffect::onSetData(const GrGLSLProgramDataManager& pdman,
    969                                    const GrProcessor& processor) {
    970 
    971     const GrGradientEffect& e = processor.cast<GrGradientEffect>();
    972 
    973 
    974     if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()){
    975 
    976         if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
    977             set_mul_color_uni(pdman, fColorStartUni, e.getColors(0));
    978             set_mul_color_uni(pdman, fColorEndUni,   e.getColors(1));
    979         } else {
    980             set_color_uni(pdman, fColorStartUni, e.getColors(0));
    981             set_color_uni(pdman, fColorEndUni,   e.getColors(1));
    982         }
    983 
    984     } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){
    985 
    986         if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
    987             set_mul_color_uni(pdman, fColorStartUni, e.getColors(0));
    988             set_mul_color_uni(pdman, fColorMidUni,   e.getColors(1));
    989             set_mul_color_uni(pdman, fColorEndUni,   e.getColors(2));
    990         } else {
    991             set_color_uni(pdman, fColorStartUni, e.getColors(0));
    992             set_color_uni(pdman, fColorMidUni,   e.getColors(1));
    993             set_color_uni(pdman, fColorEndUni,   e.getColors(2));
    994         }
    995     } else {
    996 
    997         SkScalar yCoord = e.getYCoord();
    998         if (yCoord != fCachedYCoord) {
    999             pdman.set1f(fFSYUni, yCoord);
   1000             fCachedYCoord = yCoord;
   1001         }
   1002     }
   1003 }
   1004 
   1005 
   1006 uint32_t GrGLGradientEffect::GenBaseGradientKey(const GrProcessor& processor) {
   1007     const GrGradientEffect& e = processor.cast<GrGradientEffect>();
   1008 
   1009     uint32_t key = 0;
   1010 
   1011     if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()) {
   1012         key |= kTwoColorKey;
   1013     } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()) {
   1014         key |= kThreeColorKey;
   1015     }
   1016 
   1017     if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
   1018         key |= kPremulBeforeInterpKey;
   1019     }
   1020 
   1021     return key;
   1022 }
   1023 
   1024 void GrGLGradientEffect::emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
   1025                                    GrGLSLUniformHandler* uniformHandler,
   1026                                    const GrGLSLCaps* glslCaps,
   1027                                    const GrGradientEffect& ge,
   1028                                    const char* gradientTValue,
   1029                                    const char* outputColor,
   1030                                    const char* inputColor,
   1031                                    const TextureSamplerArray& samplers) {
   1032     if (SkGradientShaderBase::kTwo_GpuColorType == ge.getColorType()){
   1033         fragBuilder->codeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n",
   1034                                  uniformHandler->getUniformVariable(fColorStartUni).c_str(),
   1035                                  uniformHandler->getUniformVariable(fColorEndUni).c_str(),
   1036                                  gradientTValue);
   1037         // Note that we could skip this step if both colors are known to be opaque. Two
   1038         // considerations:
   1039         // The gradient SkShader reporting opaque is more restrictive than necessary in the two pt
   1040         // case. Make sure the key reflects this optimization (and note that it can use the same
   1041         // shader as thekBeforeIterp case). This same optimization applies to the 3 color case
   1042         // below.
   1043         if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
   1044             fragBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
   1045         }
   1046 
   1047         fragBuilder->codeAppendf("\t%s = %s;\n", outputColor,
   1048                                  (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
   1049     } else if (SkGradientShaderBase::kThree_GpuColorType == ge.getColorType()) {
   1050         fragBuilder->codeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
   1051                                  gradientTValue);
   1052         fragBuilder->codeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n",
   1053                                  uniformHandler->getUniformVariable(fColorStartUni).c_str());
   1054         if (!glslCaps->canUseMinAndAbsTogether()) {
   1055             // The Tegra3 compiler will sometimes never return if we have
   1056             // min(abs(oneMinus2t), 1.0), or do the abs first in a separate expression.
   1057             fragBuilder->codeAppend("\tfloat minAbs = abs(oneMinus2t);\n");
   1058             fragBuilder->codeAppend("\tminAbs = minAbs > 1.0 ? 1.0 : minAbs;\n");
   1059             fragBuilder->codeAppendf("\tcolorTemp += (1.0 - minAbs) * %s;\n",
   1060                                      uniformHandler->getUniformVariable(fColorMidUni).c_str());
   1061         } else {
   1062             fragBuilder->codeAppendf("\tcolorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s;\n",
   1063                                      uniformHandler->getUniformVariable(fColorMidUni).c_str());
   1064         }
   1065         fragBuilder->codeAppendf("\tcolorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;\n",
   1066                                  uniformHandler->getUniformVariable(fColorEndUni).c_str());
   1067         if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
   1068             fragBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
   1069         }
   1070 
   1071         fragBuilder->codeAppendf("\t%s = %s;\n", outputColor,
   1072                                  (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
   1073     } else {
   1074         fragBuilder->codeAppendf("\tvec2 coord = vec2(%s, %s);\n",
   1075                                  gradientTValue,
   1076                                  uniformHandler->getUniformVariable(fFSYUni).c_str());
   1077         fragBuilder->codeAppendf("\t%s = ", outputColor);
   1078         fragBuilder->appendTextureLookupAndModulate(inputColor,
   1079                                                     samplers[0],
   1080                                                     "coord");
   1081         fragBuilder->codeAppend(";\n");
   1082     }
   1083 }
   1084 
   1085 /////////////////////////////////////////////////////////////////////
   1086 
   1087 GrGradientEffect::GrGradientEffect(GrContext* ctx,
   1088                                    const SkGradientShaderBase& shader,
   1089                                    const SkMatrix& matrix,
   1090                                    SkShader::TileMode tileMode) {
   1091 
   1092     fIsOpaque = shader.isOpaque();
   1093 
   1094     fColorType = shader.getGpuColorType(&fColors[0]);
   1095 
   1096     // The two and three color specializations do not currently support tiling.
   1097     if (SkGradientShaderBase::kTwo_GpuColorType == fColorType ||
   1098         SkGradientShaderBase::kThree_GpuColorType == fColorType) {
   1099         fRow = -1;
   1100 
   1101         if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFlags()) {
   1102             fPremulType = kBeforeInterp_PremulType;
   1103         } else {
   1104             fPremulType = kAfterInterp_PremulType;
   1105         }
   1106         fCoordTransform.reset(kCoordSet, matrix);
   1107     } else {
   1108         // doesn't matter how this is set, just be consistent because it is part of the effect key.
   1109         fPremulType = kBeforeInterp_PremulType;
   1110         SkBitmap bitmap;
   1111         shader.getGradientTableBitmap(&bitmap);
   1112 
   1113         GrTextureStripAtlas::Desc desc;
   1114         desc.fWidth  = bitmap.width();
   1115         desc.fHeight = 32;
   1116         desc.fRowHeight = bitmap.height();
   1117         desc.fContext = ctx;
   1118         desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info());
   1119         fAtlas = GrTextureStripAtlas::GetAtlas(desc);
   1120         SkASSERT(fAtlas);
   1121 
   1122         // We always filter the gradient table. Each table is one row of a texture, always y-clamp.
   1123         GrTextureParams params;
   1124         params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
   1125         params.setTileModeX(tileMode);
   1126 
   1127         fRow = fAtlas->lockRow(bitmap);
   1128         if (-1 != fRow) {
   1129             fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf * fAtlas->getNormalizedTexelHeight();
   1130             fCoordTransform.reset(kCoordSet, matrix, fAtlas->getTexture(), params.filterMode());
   1131             fTextureAccess.reset(fAtlas->getTexture(), params);
   1132         } else {
   1133             SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(ctx, bitmap, params));
   1134             if (!texture) {
   1135                 return;
   1136             }
   1137             fCoordTransform.reset(kCoordSet, matrix, texture, params.filterMode());
   1138             fTextureAccess.reset(texture, params);
   1139             fYCoord = SK_ScalarHalf;
   1140         }
   1141         this->addTextureAccess(&fTextureAccess);
   1142     }
   1143     this->addCoordTransform(&fCoordTransform);
   1144 }
   1145 
   1146 GrGradientEffect::~GrGradientEffect() {
   1147     if (this->useAtlas()) {
   1148         fAtlas->unlockRow(fRow);
   1149     }
   1150 }
   1151 
   1152 bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
   1153     const GrGradientEffect& s = processor.cast<GrGradientEffect>();
   1154 
   1155     if (this->fColorType == s.getColorType()){
   1156 
   1157         if (SkGradientShaderBase::kTwo_GpuColorType == fColorType) {
   1158             if (*this->getColors(0) != *s.getColors(0) ||
   1159                 *this->getColors(1) != *s.getColors(1)) {
   1160                 return false;
   1161             }
   1162         } else if (SkGradientShaderBase::kThree_GpuColorType == fColorType) {
   1163             if (*this->getColors(0) != *s.getColors(0) ||
   1164                 *this->getColors(1) != *s.getColors(1) ||
   1165                 *this->getColors(2) != *s.getColors(2)) {
   1166                 return false;
   1167             }
   1168         } else {
   1169             if (fYCoord != s.getYCoord()) {
   1170                 return false;
   1171             }
   1172         }
   1173 
   1174         SkASSERT(this->useAtlas() == s.useAtlas());
   1175         return true;
   1176     }
   1177 
   1178     return false;
   1179 }
   1180 
   1181 void GrGradientEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
   1182     if (fIsOpaque) {
   1183         inout->mulByUnknownOpaqueFourComponents();
   1184     } else {
   1185         inout->mulByUnknownFourComponents();
   1186     }
   1187 }
   1188 
   1189 int GrGradientEffect::RandomGradientParams(SkRandom* random,
   1190                                            SkColor colors[],
   1191                                            SkScalar** stops,
   1192                                            SkShader::TileMode* tm) {
   1193     int outColors = random->nextRangeU(1, kMaxRandomGradientColors);
   1194 
   1195     // if one color, omit stops, otherwise randomly decide whether or not to
   1196     if (outColors == 1 || (outColors >= 2 && random->nextBool())) {
   1197         *stops = nullptr;
   1198     }
   1199 
   1200     SkScalar stop = 0.f;
   1201     for (int i = 0; i < outColors; ++i) {
   1202         colors[i] = random->nextU();
   1203         if (*stops) {
   1204             (*stops)[i] = stop;
   1205             stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - stop) : 1.f;
   1206         }
   1207     }
   1208     *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileModeCount));
   1209 
   1210     return outColors;
   1211 }
   1212 
   1213 #endif
   1214