OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkGradientShaderPriv.h" | 8 #include "SkGradientShaderPriv.h" |
9 #include "SkLinearGradient.h" | 9 #include "SkLinearGradient.h" |
10 #include "SkRadialGradient.h" | 10 #include "SkRadialGradient.h" |
11 #include "SkTwoPointRadialGradient.h" | 11 #include "SkTwoPointRadialGradient.h" |
12 #include "SkTwoPointConicalGradient.h" | 12 #include "SkTwoPointConicalGradient.h" |
13 #include "SkSweepGradient.h" | 13 #include "SkSweepGradient.h" |
14 | 14 |
15 SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { | 15 SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { |
16 SkASSERT(desc.fCount > 1); | 16 SkASSERT(desc.fCount > 1); |
17 | 17 |
| 18 fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return |
| 19 |
18 fMapper = desc.fMapper; | 20 fMapper = desc.fMapper; |
19 SkSafeRef(fMapper); | 21 SkSafeRef(fMapper); |
20 fGradFlags = SkToU8(desc.fGradFlags); | 22 fGradFlags = SkToU8(desc.fGradFlags); |
21 | 23 |
22 SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); | 24 SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); |
23 SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); | 25 SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); |
24 fTileMode = desc.fTileMode; | 26 fTileMode = desc.fTileMode; |
25 fTileProc = gTileProcs[desc.fTileMode]; | 27 fTileProc = gTileProcs[desc.fTileMode]; |
26 | 28 |
| 29 fCache16 = fCache16Storage = NULL; |
| 30 fCache32 = NULL; |
| 31 fCache32PixelRef = NULL; |
| 32 |
27 /* Note: we let the caller skip the first and/or last position. | 33 /* Note: we let the caller skip the first and/or last position. |
28 i.e. pos[0] = 0.3, pos[1] = 0.7 | 34 i.e. pos[0] = 0.3, pos[1] = 0.7 |
29 In these cases, we insert dummy entries to ensure that the final data | 35 In these cases, we insert dummy entries to ensure that the final data |
30 will be bracketed by [0, 1]. | 36 will be bracketed by [0, 1]. |
31 i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1 | 37 i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1 |
32 | 38 |
33 Thus colorCount (the caller's value, and fColorCount (our value) may | 39 Thus colorCount (the caller's value, and fColorCount (our value) may |
34 differ by up to 2. In the above example: | 40 differ by up to 2. In the above example: |
35 colorCount = 2 | 41 colorCount = 2 |
36 fColorCount = 4 | 42 fColorCount = 4 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 | 139 |
134 static SkShader::TileMode unpack_mode(uint32_t packed) { | 140 static SkShader::TileMode unpack_mode(uint32_t packed) { |
135 return (SkShader::TileMode)(packed & 0xF); | 141 return (SkShader::TileMode)(packed & 0xF); |
136 } | 142 } |
137 | 143 |
138 static uint32_t unpack_flags(uint32_t packed) { | 144 static uint32_t unpack_flags(uint32_t packed) { |
139 return packed >> 4; | 145 return packed >> 4; |
140 } | 146 } |
141 | 147 |
142 SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buf
fer) { | 148 SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buf
fer) { |
| 149 fCacheAlpha = 256; |
| 150 |
143 fMapper = buffer.readUnitMapper(); | 151 fMapper = buffer.readUnitMapper(); |
144 | 152 |
| 153 fCache16 = fCache16Storage = NULL; |
| 154 fCache32 = NULL; |
| 155 fCache32PixelRef = NULL; |
| 156 |
145 int colorCount = fColorCount = buffer.getArrayCount(); | 157 int colorCount = fColorCount = buffer.getArrayCount(); |
146 if (colorCount > kColorStorageCount) { | 158 if (colorCount > kColorStorageCount) { |
147 size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) *
colorCount; | 159 size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) *
colorCount; |
148 if (buffer.validateAvailable(allocSize)) { | 160 if (buffer.validateAvailable(allocSize)) { |
149 fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize))
; | 161 fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize))
; |
150 } else { | 162 } else { |
151 fOrigColors = NULL; | 163 fOrigColors = NULL; |
152 colorCount = fColorCount = 0; | 164 colorCount = fColorCount = 0; |
153 } | 165 } |
154 } else { | 166 } else { |
(...skipping 14 matching lines...) Expand all Loading... |
169 for (int i = 1; i < colorCount; i++) { | 181 for (int i = 1; i < colorCount; i++) { |
170 recs[i].fPos = buffer.readInt(); | 182 recs[i].fPos = buffer.readInt(); |
171 recs[i].fScale = buffer.readUInt(); | 183 recs[i].fScale = buffer.readUInt(); |
172 } | 184 } |
173 } | 185 } |
174 buffer.readMatrix(&fPtsToUnit); | 186 buffer.readMatrix(&fPtsToUnit); |
175 this->initCommon(); | 187 this->initCommon(); |
176 } | 188 } |
177 | 189 |
178 SkGradientShaderBase::~SkGradientShaderBase() { | 190 SkGradientShaderBase::~SkGradientShaderBase() { |
| 191 if (fCache16Storage) { |
| 192 sk_free(fCache16Storage); |
| 193 } |
| 194 SkSafeUnref(fCache32PixelRef); |
179 if (fOrigColors != fStorage) { | 195 if (fOrigColors != fStorage) { |
180 sk_free(fOrigColors); | 196 sk_free(fOrigColors); |
181 } | 197 } |
182 SkSafeUnref(fMapper); | 198 SkSafeUnref(fMapper); |
183 } | 199 } |
184 | 200 |
185 void SkGradientShaderBase::initCommon() { | 201 void SkGradientShaderBase::initCommon() { |
| 202 fFlags = 0; |
186 unsigned colorAlpha = 0xFF; | 203 unsigned colorAlpha = 0xFF; |
187 for (int i = 0; i < fColorCount; i++) { | 204 for (int i = 0; i < fColorCount; i++) { |
188 colorAlpha &= SkColorGetA(fOrigColors[i]); | 205 colorAlpha &= SkColorGetA(fOrigColors[i]); |
189 } | 206 } |
190 fColorsAreOpaque = colorAlpha == 0xFF; | 207 fColorsAreOpaque = colorAlpha == 0xFF; |
191 } | 208 } |
192 | 209 |
193 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { | 210 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { |
194 this->INHERITED::flatten(buffer); | 211 this->INHERITED::flatten(buffer); |
195 buffer.writeFlattenable(fMapper); | 212 buffer.writeFlattenable(fMapper); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 } | 260 } |
244 | 261 |
245 void SkGradientShaderBase::flipGradientColors() { | 262 void SkGradientShaderBase::flipGradientColors() { |
246 FlipGradientColors(fOrigColors, fRecs, fOrigColors, fRecs, fColorCount); | 263 FlipGradientColors(fOrigColors, fRecs, fOrigColors, fRecs, fColorCount); |
247 } | 264 } |
248 | 265 |
249 bool SkGradientShaderBase::isOpaque() const { | 266 bool SkGradientShaderBase::isOpaque() const { |
250 return fColorsAreOpaque; | 267 return fColorsAreOpaque; |
251 } | 268 } |
252 | 269 |
253 SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext( | 270 bool SkGradientShaderBase::setContext(const SkBitmap& device, |
254 const SkGradientShaderBase& shader, const SkBitmap& device, | 271 const SkPaint& paint, |
255 const SkPaint& paint, const SkMatrix& matrix) | 272 const SkMatrix& matrix) { |
256 : INHERITED(shader, device, paint, matrix) | 273 if (!this->INHERITED::setContext(device, paint, matrix)) { |
257 , fCache(shader.refCache(getPaintAlpha())) | 274 return false; |
258 { | 275 } |
| 276 |
259 const SkMatrix& inverse = this->getTotalInverse(); | 277 const SkMatrix& inverse = this->getTotalInverse(); |
260 | 278 |
261 fDstToIndex.setConcat(shader.fPtsToUnit, inverse); | 279 fDstToIndex.setConcat(fPtsToUnit, inverse); |
262 | |
263 fDstToIndexProc = fDstToIndex.getMapXYProc(); | 280 fDstToIndexProc = fDstToIndex.getMapXYProc(); |
264 fDstToIndexClass = (uint8_t)SkShader::Context::ComputeMatrixClass(fDstToInde
x); | 281 fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex); |
265 | 282 |
266 // now convert our colors in to PMColors | 283 // now convert our colors in to PMColors |
267 unsigned paintAlpha = this->getPaintAlpha(); | 284 unsigned paintAlpha = this->getPaintAlpha(); |
268 | 285 |
269 fFlags = this->INHERITED::getFlags(); | 286 fFlags = this->INHERITED::getFlags(); |
270 if (shader.fColorsAreOpaque && paintAlpha == 0xFF) { | 287 if (fColorsAreOpaque && paintAlpha == 0xFF) { |
271 fFlags |= kOpaqueAlpha_Flag; | 288 fFlags |= kOpaqueAlpha_Flag; |
272 } | 289 } |
273 // we can do span16 as long as our individual colors are opaque, | 290 // we can do span16 as long as our individual colors are opaque, |
274 // regardless of the paint's alpha | 291 // regardless of the paint's alpha |
275 if (shader.fColorsAreOpaque) { | 292 if (fColorsAreOpaque) { |
276 fFlags |= kHasSpan16_Flag; | 293 fFlags |= kHasSpan16_Flag; |
277 } | 294 } |
| 295 |
| 296 this->setCacheAlpha(paintAlpha); |
| 297 return true; |
| 298 } |
| 299 |
| 300 void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const { |
| 301 // if the new alpha differs from the previous time we were called, inval our
cache |
| 302 // this will trigger the cache to be rebuilt. |
| 303 // we don't care about the first time, since the cache ptrs will already be
NULL |
| 304 if (fCacheAlpha != alpha) { |
| 305 fCache16 = NULL; // inval the cache |
| 306 fCache32 = NULL; // inval the cache |
| 307 fCacheAlpha = alpha; // record the new alpha |
| 308 // inform our subclasses |
| 309 if (fCache32PixelRef) { |
| 310 fCache32PixelRef->notifyPixelsChanged(); |
| 311 } |
| 312 } |
278 } | 313 } |
279 | 314 |
280 SkGradientShaderBase::GradientShaderCache::GradientShaderCache( | |
281 U8CPU alpha, const SkGradientShaderBase& shader) | |
282 : fCacheAlpha(alpha) | |
283 , fShader(shader) | |
284 , fCache16Inited(false) | |
285 , fCache32Inited(false) | |
286 { | |
287 // Only initialize the cache in getCache16/32. | |
288 fCache16 = NULL; | |
289 fCache32 = NULL; | |
290 fCache16Storage = NULL; | |
291 fCache32PixelRef = NULL; | |
292 } | |
293 | |
294 SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() { | |
295 sk_free(fCache16Storage); | |
296 SkSafeUnref(fCache32PixelRef); | |
297 } | |
298 | |
299 #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) | 315 #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) |
300 | 316 |
301 /** We take the original colors, not our premultiplied PMColors, since we can | 317 /** We take the original colors, not our premultiplied PMColors, since we can |
302 build a 16bit table as long as the original colors are opaque, even if the | 318 build a 16bit table as long as the original colors are opaque, even if the |
303 paint specifies a non-opaque alpha. | 319 paint specifies a non-opaque alpha. |
304 */ | 320 */ |
305 void SkGradientShaderBase::GradientShaderCache::Build16bitCache( | 321 void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor
c1, |
306 uint16_t cache[], SkColor c0, SkColor c1, int count) { | 322 int count) { |
307 SkASSERT(count > 1); | 323 SkASSERT(count > 1); |
308 SkASSERT(SkColorGetA(c0) == 0xFF); | 324 SkASSERT(SkColorGetA(c0) == 0xFF); |
309 SkASSERT(SkColorGetA(c1) == 0xFF); | 325 SkASSERT(SkColorGetA(c1) == 0xFF); |
310 | 326 |
311 SkFixed r = SkColorGetR(c0); | 327 SkFixed r = SkColorGetR(c0); |
312 SkFixed g = SkColorGetG(c0); | 328 SkFixed g = SkColorGetG(c0); |
313 SkFixed b = SkColorGetB(c0); | 329 SkFixed b = SkColorGetB(c0); |
314 | 330 |
315 SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); | 331 SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); |
316 SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); | 332 SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); |
(...skipping 27 matching lines...) Expand all Loading... |
344 * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead | 360 * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead |
345 * of using | | 361 * of using | |
346 * | 362 * |
347 * We chose #1 just because it was more localized. | 363 * We chose #1 just because it was more localized. |
348 * See http://code.google.com/p/skia/issues/detail?id=1113 | 364 * See http://code.google.com/p/skia/issues/detail?id=1113 |
349 * | 365 * |
350 * The type SkUFixed encapsulate this need for unsigned, but logically Fixed. | 366 * The type SkUFixed encapsulate this need for unsigned, but logically Fixed. |
351 */ | 367 */ |
352 typedef uint32_t SkUFixed; | 368 typedef uint32_t SkUFixed; |
353 | 369 |
354 void SkGradientShaderBase::GradientShaderCache::Build32bitCache( | 370 void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColo
r c1, |
355 SkPMColor cache[], SkColor c0, SkColor c1, | 371 int count, U8CPU paintAlpha, uint32_t grad
Flags) { |
356 int count, U8CPU paintAlpha, uint32_t gradFlags) { | |
357 SkASSERT(count > 1); | 372 SkASSERT(count > 1); |
358 | 373 |
359 // need to apply paintAlpha to our two endpoints | 374 // need to apply paintAlpha to our two endpoints |
360 uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha); | 375 uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha); |
361 uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha); | 376 uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha); |
362 | 377 |
363 | 378 |
364 const bool interpInPremul = SkToBool(gradFlags & | 379 const bool interpInPremul = SkToBool(gradFlags & |
365 SkGradientShader::kInterpolateColorsInPremul_Flag); | 380 SkGradientShader::kInterpolateColorsInPremul_Flag); |
366 | 381 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 if (6 == bits) { | 504 if (6 == bits) { |
490 return (x << 10) | (x << 4) | (x >> 2); | 505 return (x << 10) | (x << 4) | (x >> 2); |
491 } | 506 } |
492 if (8 == bits) { | 507 if (8 == bits) { |
493 return (x << 8) | x; | 508 return (x << 8) | x; |
494 } | 509 } |
495 sk_throw(); | 510 sk_throw(); |
496 return 0; | 511 return 0; |
497 } | 512 } |
498 | 513 |
499 const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16() { | 514 const uint16_t* SkGradientShaderBase::getCache16() const { |
500 SkOnce(&fCache16Inited, &fCache16Mutex, SkGradientShaderBase::GradientShader
Cache::initCache16, | 515 if (fCache16 == NULL) { |
501 this); | 516 // double the count for dither entries |
502 SkASSERT(fCache16); | 517 const int entryCount = kCache16Count * 2; |
| 518 const size_t allocSize = sizeof(uint16_t) * entryCount; |
| 519 |
| 520 if (fCache16Storage == NULL) { // set the storage and our working ptr |
| 521 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
| 522 } |
| 523 fCache16 = fCache16Storage; |
| 524 if (fColorCount == 2) { |
| 525 Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], |
| 526 kCache16Count); |
| 527 } else { |
| 528 Rec* rec = fRecs; |
| 529 int prevIndex = 0; |
| 530 for (int i = 1; i < fColorCount; i++) { |
| 531 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; |
| 532 SkASSERT(nextIndex < kCache16Count); |
| 533 |
| 534 if (nextIndex > prevIndex) |
| 535 Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOri
gColors[i], nextIndex - prevIndex + 1); |
| 536 prevIndex = nextIndex; |
| 537 } |
| 538 } |
| 539 |
| 540 if (fMapper) { |
| 541 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
| 542 uint16_t* linear = fCache16; // just computed linear data |
| 543 uint16_t* mapped = fCache16Storage; // storage for mapped data |
| 544 SkUnitMapper* map = fMapper; |
| 545 for (int i = 0; i < kCache16Count; i++) { |
| 546 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache1
6Shift; |
| 547 mapped[i] = linear[index]; |
| 548 mapped[i + kCache16Count] = linear[index + kCache16Count]; |
| 549 } |
| 550 sk_free(fCache16); |
| 551 fCache16 = fCache16Storage; |
| 552 } |
| 553 } |
503 return fCache16; | 554 return fCache16; |
504 } | 555 } |
505 | 556 |
506 void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache*
cache) { | 557 const SkPMColor* SkGradientShaderBase::getCache32() const { |
507 // double the count for dither entries | 558 if (fCache32 == NULL) { |
508 const int entryCount = kCache16Count * 2; | 559 SkImageInfo info; |
509 const size_t allocSize = sizeof(uint16_t) * entryCount; | 560 info.fWidth = kCache32Count; |
| 561 info.fHeight = 4; // for our 4 dither rows |
| 562 info.fAlphaType = kPremul_SkAlphaType; |
| 563 info.fColorType = kN32_SkColorType; |
510 | 564 |
511 SkASSERT(NULL == cache->fCache16Storage); | 565 if (NULL == fCache32PixelRef) { |
512 cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); | 566 fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); |
513 cache->fCache16 = cache->fCache16Storage; | 567 } |
514 if (cache->fShader.fColorCount == 2) { | 568 fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); |
515 Build16bitCache(cache->fCache16, cache->fShader.fOrigColors[0], | 569 if (fColorCount == 2) { |
516 cache->fShader.fOrigColors[1], kCache16Count); | 570 Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1], |
517 } else { | 571 kCache32Count, fCacheAlpha, fGradFlags); |
518 Rec* rec = cache->fShader.fRecs; | 572 } else { |
519 int prevIndex = 0; | 573 Rec* rec = fRecs; |
520 for (int i = 1; i < cache->fShader.fColorCount; i++) { | 574 int prevIndex = 0; |
521 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; | 575 for (int i = 1; i < fColorCount; i++) { |
522 SkASSERT(nextIndex < kCache16Count); | 576 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; |
| 577 SkASSERT(nextIndex < kCache32Count); |
523 | 578 |
524 if (nextIndex > prevIndex) | 579 if (nextIndex > prevIndex) |
525 Build16bitCache(cache->fCache16 + prevIndex, cache->fShader.fOri
gColors[i-1], | 580 Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1], |
526 cache->fShader.fOrigColors[i], nextIndex - prevI
ndex + 1); | 581 fOrigColors[i], nextIndex - prevIndex + 1, |
527 prevIndex = nextIndex; | 582 fCacheAlpha, fGradFlags); |
| 583 prevIndex = nextIndex; |
| 584 } |
| 585 } |
| 586 |
| 587 if (fMapper) { |
| 588 SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NUL
L); |
| 589 SkPMColor* linear = fCache32; // just computed linear data |
| 590 SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for
mapped data |
| 591 SkUnitMapper* map = fMapper; |
| 592 for (int i = 0; i < kCache32Count; i++) { |
| 593 int index = map->mapUnit16((i << 8) | i) >> 8; |
| 594 mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; |
| 595 mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; |
| 596 mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; |
| 597 mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; |
| 598 } |
| 599 fCache32PixelRef->unref(); |
| 600 fCache32PixelRef = newPR; |
| 601 fCache32 = (SkPMColor*)newPR->getAddr(); |
528 } | 602 } |
529 } | 603 } |
530 | |
531 if (cache->fShader.fMapper) { | |
532 cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); | |
533 uint16_t* linear = cache->fCache16; // just computed linear data | |
534 uint16_t* mapped = cache->fCache16Storage; // storage for mapped data | |
535 SkUnitMapper* map = cache->fShader.fMapper; | |
536 for (int i = 0; i < kCache16Count; i++) { | |
537 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shi
ft; | |
538 mapped[i] = linear[index]; | |
539 mapped[i + kCache16Count] = linear[index + kCache16Count]; | |
540 } | |
541 sk_free(cache->fCache16); | |
542 cache->fCache16 = cache->fCache16Storage; | |
543 } | |
544 } | |
545 | |
546 const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32() { | |
547 SkOnce(&fCache32Inited, &fCache32Mutex, SkGradientShaderBase::GradientShader
Cache::initCache32, | |
548 this); | |
549 SkASSERT(fCache32); | |
550 return fCache32; | 604 return fCache32; |
551 } | 605 } |
552 | 606 |
553 void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache*
cache) { | |
554 SkImageInfo info; | |
555 info.fWidth = kCache32Count; | |
556 info.fHeight = 4; // for our 4 dither rows | |
557 info.fAlphaType = kPremul_SkAlphaType; | |
558 info.fColorType = kN32_SkColorType; | |
559 | |
560 SkASSERT(NULL == cache->fCache32PixelRef); | |
561 cache->fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); | |
562 cache->fCache32 = (SkPMColor*)cache->fCache32PixelRef->getAddr(); | |
563 if (cache->fShader.fColorCount == 2) { | |
564 Build32bitCache(cache->fCache32, cache->fShader.fOrigColors[0], | |
565 cache->fShader.fOrigColors[1], kCache32Count, cache->fCa
cheAlpha, | |
566 cache->fShader.fGradFlags); | |
567 } else { | |
568 Rec* rec = cache->fShader.fRecs; | |
569 int prevIndex = 0; | |
570 for (int i = 1; i < cache->fShader.fColorCount; i++) { | |
571 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; | |
572 SkASSERT(nextIndex < kCache32Count); | |
573 | |
574 if (nextIndex > prevIndex) | |
575 Build32bitCache(cache->fCache32 + prevIndex, cache->fShader.fOri
gColors[i-1], | |
576 cache->fShader.fOrigColors[i], nextIndex - prevI
ndex + 1, | |
577 cache->fCacheAlpha, cache->fShader.fGradFlags); | |
578 prevIndex = nextIndex; | |
579 } | |
580 } | |
581 | |
582 if (cache->fShader.fMapper) { | |
583 SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL); | |
584 SkPMColor* linear = cache->fCache32; // just computed linear d
ata | |
585 SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapp
ed data | |
586 SkUnitMapper* map = cache->fShader.fMapper; | |
587 for (int i = 0; i < kCache32Count; i++) { | |
588 int index = map->mapUnit16((i << 8) | i) >> 8; | |
589 mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; | |
590 mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; | |
591 mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; | |
592 mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; | |
593 } | |
594 cache->fCache32PixelRef->unref(); | |
595 cache->fCache32PixelRef = newPR; | |
596 cache->fCache32 = (SkPMColor*)newPR->getAddr(); | |
597 } | |
598 } | |
599 | |
600 /* | 607 /* |
601 * The gradient holds a cache for the most recent value of alpha. Successive | |
602 * callers with the same alpha value will share the same cache. | |
603 */ | |
604 SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::refCache(U8CPU
alpha) const { | |
605 SkAutoMutexAcquire ama(fCacheMutex); | |
606 if (!fCache || fCache->getAlpha() != alpha) { | |
607 fCache.reset(SkNEW_ARGS(GradientShaderCache, (alpha, *this))); | |
608 } | |
609 // Increment the ref counter inside the mutex to ensure the returned pointer
is still valid. | |
610 // Otherwise, the pointer may have been overwritten on a different thread be
fore the object's | |
611 // ref count was incremented. | |
612 fCache.get()->ref(); | |
613 return fCache; | |
614 } | |
615 | |
616 /* | |
617 * Because our caller might rebuild the same (logically the same) gradient | 608 * Because our caller might rebuild the same (logically the same) gradient |
618 * over and over, we'd like to return exactly the same "bitmap" if possible, | 609 * over and over, we'd like to return exactly the same "bitmap" if possible, |
619 * allowing the client to utilize a cache of our bitmap (e.g. with a GPU). | 610 * allowing the client to utilize a cache of our bitmap (e.g. with a GPU). |
620 * To do that, we maintain a private cache of built-bitmaps, based on our | 611 * To do that, we maintain a private cache of built-bitmaps, based on our |
621 * colors and positions. Note: we don't try to flatten the fMapper, so if one | 612 * colors and positions. Note: we don't try to flatten the fMapper, so if one |
622 * is present, we skip the cache for now. | 613 * is present, we skip the cache for now. |
623 */ | 614 */ |
624 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { | 615 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { |
625 // our caller assumes no external alpha, so we ensure that our cache is | 616 // our caller assumes no external alpha, so we ensure that our cache is |
626 // built with 0xFF | 617 // built with 0xFF |
627 SkAutoTUnref<GradientShaderCache> cache(this->refCache(0xFF)); | 618 this->setCacheAlpha(0xFF); |
628 | 619 |
629 // don't have a way to put the mapper into our cache-key yet | 620 // don't have a way to put the mapper into our cache-key yet |
630 if (fMapper) { | 621 if (fMapper) { |
631 // force our cache32pixelref to be built | 622 // force our cahce32pixelref to be built |
632 (void)cache->getCache32(); | 623 (void)this->getCache32(); |
633 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); | 624 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
634 bitmap->setPixelRef(cache->getCache32PixelRef()); | 625 bitmap->setPixelRef(fCache32PixelRef); |
635 return; | 626 return; |
636 } | 627 } |
637 | 628 |
638 // build our key: [numColors + colors[] + {positions[]} + flags ] | 629 // build our key: [numColors + colors[] + {positions[]} + flags ] |
639 int count = 1 + fColorCount + 1; | 630 int count = 1 + fColorCount + 1; |
640 if (fColorCount > 2) { | 631 if (fColorCount > 2) { |
641 count += fColorCount - 1; // fRecs[].fPos | 632 count += fColorCount - 1; // fRecs[].fPos |
642 } | 633 } |
643 | 634 |
644 SkAutoSTMalloc<16, int32_t> storage(count); | 635 SkAutoSTMalloc<16, int32_t> storage(count); |
(...skipping 18 matching lines...) Expand all Loading... |
663 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; | 654 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; |
664 SkAutoMutexAcquire ama(gMutex); | 655 SkAutoMutexAcquire ama(gMutex); |
665 | 656 |
666 if (NULL == gCache) { | 657 if (NULL == gCache) { |
667 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); | 658 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); |
668 } | 659 } |
669 size_t size = count * sizeof(int32_t); | 660 size_t size = count * sizeof(int32_t); |
670 | 661 |
671 if (!gCache->find(storage.get(), size, bitmap)) { | 662 if (!gCache->find(storage.get(), size, bitmap)) { |
672 // force our cahce32pixelref to be built | 663 // force our cahce32pixelref to be built |
673 (void)cache->getCache32(); | 664 (void)this->getCache32(); |
674 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); | 665 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
675 bitmap->setPixelRef(cache->getCache32PixelRef()); | 666 bitmap->setPixelRef(fCache32PixelRef); |
676 | 667 |
677 gCache->add(storage.get(), size, *bitmap); | 668 gCache->add(storage.get(), size, *bitmap); |
678 } | 669 } |
679 } | 670 } |
680 | 671 |
681 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info, bool flipGrad)
const { | 672 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info, bool flipGrad)
const { |
682 if (info) { | 673 if (info) { |
683 if (info->fColorCount >= fColorCount) { | 674 if (info->fColorCount >= fColorCount) { |
684 SkColor* colorLoc; | 675 SkColor* colorLoc; |
685 Rec* recLoc; | 676 Rec* recLoc; |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1204 (*stops)[i] = stop; | 1195 (*stops)[i] = stop; |
1205 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; | 1196 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; |
1206 } | 1197 } |
1207 } | 1198 } |
1208 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); | 1199 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); |
1209 | 1200 |
1210 return outColors; | 1201 return outColors; |
1211 } | 1202 } |
1212 | 1203 |
1213 #endif | 1204 #endif |
OLD | NEW |