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, ¶ms); 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