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