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