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.fFlags); | 22 fGradFlags = SkToU8(desc.fFlags); |
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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 | 137 |
132 static SkShader::TileMode unpack_mode(uint32_t packed) { | 138 static SkShader::TileMode unpack_mode(uint32_t packed) { |
133 return (SkShader::TileMode)(packed & 0xF); | 139 return (SkShader::TileMode)(packed & 0xF); |
134 } | 140 } |
135 | 141 |
136 static uint32_t unpack_flags(uint32_t packed) { | 142 static uint32_t unpack_flags(uint32_t packed) { |
137 return packed >> 4; | 143 return packed >> 4; |
138 } | 144 } |
139 | 145 |
140 SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buf
fer) { | 146 SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buf
fer) { |
| 147 fCacheAlpha = 256; |
| 148 |
141 fMapper = buffer.readUnitMapper(); | 149 fMapper = buffer.readUnitMapper(); |
142 | 150 |
| 151 fCache16 = fCache16Storage = NULL; |
| 152 fCache32 = NULL; |
| 153 fCache32PixelRef = NULL; |
| 154 |
143 int colorCount = fColorCount = buffer.getArrayCount(); | 155 int colorCount = fColorCount = buffer.getArrayCount(); |
144 if (colorCount > kColorStorageCount) { | 156 if (colorCount > kColorStorageCount) { |
145 size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) *
colorCount; | 157 size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) *
colorCount; |
146 if (buffer.validateAvailable(allocSize)) { | 158 if (buffer.validateAvailable(allocSize)) { |
147 fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize))
; | 159 fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize))
; |
148 } else { | 160 } else { |
149 fOrigColors = NULL; | 161 fOrigColors = NULL; |
150 colorCount = fColorCount = 0; | 162 colorCount = fColorCount = 0; |
151 } | 163 } |
152 } else { | 164 } else { |
(...skipping 14 matching lines...) Expand all Loading... |
167 for (int i = 1; i < colorCount; i++) { | 179 for (int i = 1; i < colorCount; i++) { |
168 recs[i].fPos = buffer.readInt(); | 180 recs[i].fPos = buffer.readInt(); |
169 recs[i].fScale = buffer.readUInt(); | 181 recs[i].fScale = buffer.readUInt(); |
170 } | 182 } |
171 } | 183 } |
172 buffer.readMatrix(&fPtsToUnit); | 184 buffer.readMatrix(&fPtsToUnit); |
173 this->initCommon(); | 185 this->initCommon(); |
174 } | 186 } |
175 | 187 |
176 SkGradientShaderBase::~SkGradientShaderBase() { | 188 SkGradientShaderBase::~SkGradientShaderBase() { |
| 189 if (fCache16Storage) { |
| 190 sk_free(fCache16Storage); |
| 191 } |
| 192 SkSafeUnref(fCache32PixelRef); |
177 if (fOrigColors != fStorage) { | 193 if (fOrigColors != fStorage) { |
178 sk_free(fOrigColors); | 194 sk_free(fOrigColors); |
179 } | 195 } |
180 SkSafeUnref(fMapper); | 196 SkSafeUnref(fMapper); |
181 } | 197 } |
182 | 198 |
183 void SkGradientShaderBase::initCommon() { | 199 void SkGradientShaderBase::initCommon() { |
| 200 fFlags = 0; |
184 unsigned colorAlpha = 0xFF; | 201 unsigned colorAlpha = 0xFF; |
185 for (int i = 0; i < fColorCount; i++) { | 202 for (int i = 0; i < fColorCount; i++) { |
186 colorAlpha &= SkColorGetA(fOrigColors[i]); | 203 colorAlpha &= SkColorGetA(fOrigColors[i]); |
187 } | 204 } |
188 fColorsAreOpaque = colorAlpha == 0xFF; | 205 fColorsAreOpaque = colorAlpha == 0xFF; |
189 } | 206 } |
190 | 207 |
191 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { | 208 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { |
192 this->INHERITED::flatten(buffer); | 209 this->INHERITED::flatten(buffer); |
193 buffer.writeFlattenable(fMapper); | 210 buffer.writeFlattenable(fMapper); |
194 buffer.writeColorArray(fOrigColors, fColorCount); | 211 buffer.writeColorArray(fOrigColors, fColorCount); |
195 buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags)); | 212 buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags)); |
196 if (fColorCount > 2) { | 213 if (fColorCount > 2) { |
197 Rec* recs = fRecs; | 214 Rec* recs = fRecs; |
198 for (int i = 1; i < fColorCount; i++) { | 215 for (int i = 1; i < fColorCount; i++) { |
199 buffer.writeInt(recs[i].fPos); | 216 buffer.writeInt(recs[i].fPos); |
200 buffer.writeUInt(recs[i].fScale); | 217 buffer.writeUInt(recs[i].fScale); |
201 } | 218 } |
202 } | 219 } |
203 buffer.writeMatrix(fPtsToUnit); | 220 buffer.writeMatrix(fPtsToUnit); |
204 } | 221 } |
205 | 222 |
206 bool SkGradientShaderBase::isOpaque() const { | 223 bool SkGradientShaderBase::isOpaque() const { |
207 return fColorsAreOpaque; | 224 return fColorsAreOpaque; |
208 } | 225 } |
209 | 226 |
210 SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext( | 227 bool SkGradientShaderBase::setContext(const SkBitmap& device, |
211 const SkGradientShaderBase& shader, const SkBitmap& device, | 228 const SkPaint& paint, |
212 const SkPaint& paint, const SkMatrix& matrix) | 229 const SkMatrix& matrix) { |
213 : INHERITED(shader, device, paint, matrix) | 230 if (!this->INHERITED::setContext(device, paint, matrix)) { |
214 , fCache(shader.getCache(getPaintAlpha())) | 231 return false; |
215 { | 232 } |
| 233 |
216 const SkMatrix& inverse = this->getTotalInverse(); | 234 const SkMatrix& inverse = this->getTotalInverse(); |
217 | 235 |
218 fDstToIndex.setConcat(shader.fPtsToUnit, inverse); | 236 fDstToIndex.setConcat(fPtsToUnit, inverse); |
219 | |
220 fDstToIndexProc = fDstToIndex.getMapXYProc(); | 237 fDstToIndexProc = fDstToIndex.getMapXYProc(); |
221 fDstToIndexClass = (uint8_t)SkShader::Context::ComputeMatrixClass(fDstToInde
x); | 238 fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex); |
222 | 239 |
223 // now convert our colors in to PMColors | 240 // now convert our colors in to PMColors |
224 unsigned paintAlpha = this->getPaintAlpha(); | 241 unsigned paintAlpha = this->getPaintAlpha(); |
225 | 242 |
226 fFlags = this->INHERITED::getFlags(); | 243 fFlags = this->INHERITED::getFlags(); |
227 if (shader.fColorsAreOpaque && paintAlpha == 0xFF) { | 244 if (fColorsAreOpaque && paintAlpha == 0xFF) { |
228 fFlags |= kOpaqueAlpha_Flag; | 245 fFlags |= kOpaqueAlpha_Flag; |
229 } | 246 } |
230 // we can do span16 as long as our individual colors are opaque, | 247 // we can do span16 as long as our individual colors are opaque, |
231 // regardless of the paint's alpha | 248 // regardless of the paint's alpha |
232 if (shader.fColorsAreOpaque) { | 249 if (fColorsAreOpaque) { |
233 fFlags |= kHasSpan16_Flag; | 250 fFlags |= kHasSpan16_Flag; |
234 } | 251 } |
| 252 |
| 253 this->setCacheAlpha(paintAlpha); |
| 254 return true; |
| 255 } |
| 256 |
| 257 void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const { |
| 258 // if the new alpha differs from the previous time we were called, inval our
cache |
| 259 // this will trigger the cache to be rebuilt. |
| 260 // we don't care about the first time, since the cache ptrs will already be
NULL |
| 261 if (fCacheAlpha != alpha) { |
| 262 fCache16 = NULL; // inval the cache |
| 263 fCache32 = NULL; // inval the cache |
| 264 fCacheAlpha = alpha; // record the new alpha |
| 265 // inform our subclasses |
| 266 if (fCache32PixelRef) { |
| 267 fCache32PixelRef->notifyPixelsChanged(); |
| 268 } |
| 269 } |
235 } | 270 } |
236 | 271 |
237 SkGradientShaderBase::GradientShaderCache::GradientShaderCache( | |
238 U8CPU alpha, const SkGradientShaderBase& shader) | |
239 : fCacheAlpha(alpha) | |
240 , fShader(shader) | |
241 , fCache16Inited(false) | |
242 , fCache32Inited(false) | |
243 { | |
244 // Only initialize the cache in getCache16/32. | |
245 fCache16 = NULL; | |
246 fCache32 = NULL; | |
247 fCache16Storage = NULL; | |
248 fCache32PixelRef = NULL; | |
249 } | |
250 | |
251 SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() { | |
252 sk_free(fCache16Storage); | |
253 SkSafeUnref(fCache32PixelRef); | |
254 } | |
255 | |
256 #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) | 272 #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) |
257 | 273 |
258 /** We take the original colors, not our premultiplied PMColors, since we can | 274 /** We take the original colors, not our premultiplied PMColors, since we can |
259 build a 16bit table as long as the original colors are opaque, even if the | 275 build a 16bit table as long as the original colors are opaque, even if the |
260 paint specifies a non-opaque alpha. | 276 paint specifies a non-opaque alpha. |
261 */ | 277 */ |
262 void SkGradientShaderBase::GradientShaderCache::Build16bitCache( | 278 void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor
c1, |
263 uint16_t cache[], SkColor c0, SkColor c1, int count) { | 279 int count) { |
264 SkASSERT(count > 1); | 280 SkASSERT(count > 1); |
265 SkASSERT(SkColorGetA(c0) == 0xFF); | 281 SkASSERT(SkColorGetA(c0) == 0xFF); |
266 SkASSERT(SkColorGetA(c1) == 0xFF); | 282 SkASSERT(SkColorGetA(c1) == 0xFF); |
267 | 283 |
268 SkFixed r = SkColorGetR(c0); | 284 SkFixed r = SkColorGetR(c0); |
269 SkFixed g = SkColorGetG(c0); | 285 SkFixed g = SkColorGetG(c0); |
270 SkFixed b = SkColorGetB(c0); | 286 SkFixed b = SkColorGetB(c0); |
271 | 287 |
272 SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); | 288 SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); |
273 SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); | 289 SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); |
(...skipping 27 matching lines...) Expand all Loading... |
301 * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead | 317 * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead |
302 * of using | | 318 * of using | |
303 * | 319 * |
304 * We chose #1 just because it was more localized. | 320 * We chose #1 just because it was more localized. |
305 * See http://code.google.com/p/skia/issues/detail?id=1113 | 321 * See http://code.google.com/p/skia/issues/detail?id=1113 |
306 * | 322 * |
307 * The type SkUFixed encapsulate this need for unsigned, but logically Fixed. | 323 * The type SkUFixed encapsulate this need for unsigned, but logically Fixed. |
308 */ | 324 */ |
309 typedef uint32_t SkUFixed; | 325 typedef uint32_t SkUFixed; |
310 | 326 |
311 void SkGradientShaderBase::GradientShaderCache::Build32bitCache( | 327 void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColo
r c1, |
312 SkPMColor cache[], SkColor c0, SkColor c1, | 328 int count, U8CPU paintAlpha, uint32_t grad
Flags) { |
313 int count, U8CPU paintAlpha, uint32_t gradFlags) { | |
314 SkASSERT(count > 1); | 329 SkASSERT(count > 1); |
315 | 330 |
316 // need to apply paintAlpha to our two endpoints | 331 // need to apply paintAlpha to our two endpoints |
317 uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha); | 332 uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha); |
318 uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha); | 333 uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha); |
319 | 334 |
320 | 335 |
321 const bool interpInPremul = SkToBool(gradFlags & | 336 const bool interpInPremul = SkToBool(gradFlags & |
322 SkGradientShader::kInterpolateColorsInPremul_Flag); | 337 SkGradientShader::kInterpolateColorsInPremul_Flag); |
323 | 338 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 if (6 == bits) { | 461 if (6 == bits) { |
447 return (x << 10) | (x << 4) | (x >> 2); | 462 return (x << 10) | (x << 4) | (x >> 2); |
448 } | 463 } |
449 if (8 == bits) { | 464 if (8 == bits) { |
450 return (x << 8) | x; | 465 return (x << 8) | x; |
451 } | 466 } |
452 sk_throw(); | 467 sk_throw(); |
453 return 0; | 468 return 0; |
454 } | 469 } |
455 | 470 |
456 const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16() { | 471 const uint16_t* SkGradientShaderBase::getCache16() const { |
457 SkOnce(&fCache16Inited, &fCache16Mutex, SkGradientShaderBase::GradientShader
Cache::initCache16, | 472 if (fCache16 == NULL) { |
458 this); | 473 // double the count for dither entries |
459 SkASSERT(fCache16); | 474 const int entryCount = kCache16Count * 2; |
| 475 const size_t allocSize = sizeof(uint16_t) * entryCount; |
| 476 |
| 477 if (fCache16Storage == NULL) { // set the storage and our working ptr |
| 478 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
| 479 } |
| 480 fCache16 = fCache16Storage; |
| 481 if (fColorCount == 2) { |
| 482 Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], |
| 483 kCache16Count); |
| 484 } else { |
| 485 Rec* rec = fRecs; |
| 486 int prevIndex = 0; |
| 487 for (int i = 1; i < fColorCount; i++) { |
| 488 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; |
| 489 SkASSERT(nextIndex < kCache16Count); |
| 490 |
| 491 if (nextIndex > prevIndex) |
| 492 Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOri
gColors[i], nextIndex - prevIndex + 1); |
| 493 prevIndex = nextIndex; |
| 494 } |
| 495 } |
| 496 |
| 497 if (fMapper) { |
| 498 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
| 499 uint16_t* linear = fCache16; // just computed linear data |
| 500 uint16_t* mapped = fCache16Storage; // storage for mapped data |
| 501 SkUnitMapper* map = fMapper; |
| 502 for (int i = 0; i < kCache16Count; i++) { |
| 503 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache1
6Shift; |
| 504 mapped[i] = linear[index]; |
| 505 mapped[i + kCache16Count] = linear[index + kCache16Count]; |
| 506 } |
| 507 sk_free(fCache16); |
| 508 fCache16 = fCache16Storage; |
| 509 } |
| 510 } |
460 return fCache16; | 511 return fCache16; |
461 } | 512 } |
462 | 513 |
463 void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache*
cache) { | 514 const SkPMColor* SkGradientShaderBase::getCache32() const { |
464 // double the count for dither entries | 515 if (fCache32 == NULL) { |
465 const int entryCount = kCache16Count * 2; | 516 SkImageInfo info; |
466 const size_t allocSize = sizeof(uint16_t) * entryCount; | 517 info.fWidth = kCache32Count; |
| 518 info.fHeight = 4; // for our 4 dither rows |
| 519 info.fAlphaType = kPremul_SkAlphaType; |
| 520 info.fColorType = kN32_SkColorType; |
467 | 521 |
468 SkASSERT(NULL == cache->fCache16Storage); | 522 if (NULL == fCache32PixelRef) { |
469 cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); | 523 fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); |
470 cache->fCache16 = cache->fCache16Storage; | 524 } |
471 if (cache->fShader.fColorCount == 2) { | 525 fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); |
472 Build16bitCache(cache->fCache16, cache->fShader.fOrigColors[0], | 526 if (fColorCount == 2) { |
473 cache->fShader.fOrigColors[1], kCache16Count); | 527 Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1], |
474 } else { | 528 kCache32Count, fCacheAlpha, fGradFlags); |
475 Rec* rec = cache->fShader.fRecs; | 529 } else { |
476 int prevIndex = 0; | 530 Rec* rec = fRecs; |
477 for (int i = 1; i < cache->fShader.fColorCount; i++) { | 531 int prevIndex = 0; |
478 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; | 532 for (int i = 1; i < fColorCount; i++) { |
479 SkASSERT(nextIndex < kCache16Count); | 533 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; |
| 534 SkASSERT(nextIndex < kCache32Count); |
480 | 535 |
481 if (nextIndex > prevIndex) | 536 if (nextIndex > prevIndex) |
482 Build16bitCache(cache->fCache16 + prevIndex, cache->fShader.fOri
gColors[i-1], | 537 Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1], |
483 cache->fShader.fOrigColors[i], nextIndex - prevI
ndex + 1); | 538 fOrigColors[i], nextIndex - prevIndex + 1, |
484 prevIndex = nextIndex; | 539 fCacheAlpha, fGradFlags); |
| 540 prevIndex = nextIndex; |
| 541 } |
| 542 } |
| 543 |
| 544 if (fMapper) { |
| 545 SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NUL
L); |
| 546 SkPMColor* linear = fCache32; // just computed linear data |
| 547 SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for
mapped data |
| 548 SkUnitMapper* map = fMapper; |
| 549 for (int i = 0; i < kCache32Count; i++) { |
| 550 int index = map->mapUnit16((i << 8) | i) >> 8; |
| 551 mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; |
| 552 mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; |
| 553 mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; |
| 554 mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; |
| 555 } |
| 556 fCache32PixelRef->unref(); |
| 557 fCache32PixelRef = newPR; |
| 558 fCache32 = (SkPMColor*)newPR->getAddr(); |
485 } | 559 } |
486 } | 560 } |
487 | |
488 if (cache->fShader.fMapper) { | |
489 cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); | |
490 uint16_t* linear = cache->fCache16; // just computed linear data | |
491 uint16_t* mapped = cache->fCache16Storage; // storage for mapped data | |
492 SkUnitMapper* map = cache->fShader.fMapper; | |
493 for (int i = 0; i < kCache16Count; i++) { | |
494 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shi
ft; | |
495 mapped[i] = linear[index]; | |
496 mapped[i + kCache16Count] = linear[index + kCache16Count]; | |
497 } | |
498 sk_free(cache->fCache16); | |
499 cache->fCache16 = cache->fCache16Storage; | |
500 } | |
501 } | |
502 | |
503 const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32() { | |
504 SkOnce(&fCache32Inited, &fCache32Mutex, SkGradientShaderBase::GradientShader
Cache::initCache32, | |
505 this); | |
506 SkASSERT(fCache32); | |
507 return fCache32; | 561 return fCache32; |
508 } | 562 } |
509 | 563 |
510 void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache*
cache) { | |
511 SkImageInfo info; | |
512 info.fWidth = kCache32Count; | |
513 info.fHeight = 4; // for our 4 dither rows | |
514 info.fAlphaType = kPremul_SkAlphaType; | |
515 info.fColorType = kN32_SkColorType; | |
516 | |
517 SkASSERT(NULL == cache->fCache32PixelRef); | |
518 cache->fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); | |
519 cache->fCache32 = (SkPMColor*)cache->fCache32PixelRef->getAddr(); | |
520 if (cache->fShader.fColorCount == 2) { | |
521 Build32bitCache(cache->fCache32, cache->fShader.fOrigColors[0], | |
522 cache->fShader.fOrigColors[1], kCache32Count, cache->fCa
cheAlpha, | |
523 cache->fShader.fGradFlags); | |
524 } else { | |
525 Rec* rec = cache->fShader.fRecs; | |
526 int prevIndex = 0; | |
527 for (int i = 1; i < cache->fShader.fColorCount; i++) { | |
528 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; | |
529 SkASSERT(nextIndex < kCache32Count); | |
530 | |
531 if (nextIndex > prevIndex) | |
532 Build32bitCache(cache->fCache32 + prevIndex, cache->fShader.fOri
gColors[i-1], | |
533 cache->fShader.fOrigColors[i], nextIndex - prevI
ndex + 1, | |
534 cache->fCacheAlpha, cache->fShader.fGradFlags); | |
535 prevIndex = nextIndex; | |
536 } | |
537 } | |
538 | |
539 if (cache->fShader.fMapper) { | |
540 SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL); | |
541 SkPMColor* linear = cache->fCache32; // just computed linear d
ata | |
542 SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapp
ed data | |
543 SkUnitMapper* map = cache->fShader.fMapper; | |
544 for (int i = 0; i < kCache32Count; i++) { | |
545 int index = map->mapUnit16((i << 8) | i) >> 8; | |
546 mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; | |
547 mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; | |
548 mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; | |
549 mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; | |
550 } | |
551 cache->fCache32PixelRef->unref(); | |
552 cache->fCache32PixelRef = newPR; | |
553 cache->fCache32 = (SkPMColor*)newPR->getAddr(); | |
554 } | |
555 } | |
556 | |
557 /* | 564 /* |
558 * The gradient holds a cache for the most recent value of alpha. Successive | |
559 * callers with the same alpha value will share the same cache. | |
560 */ | |
561 SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::getCache(U8CPU
alpha) const { | |
562 SkAutoMutexAcquire ama(fCacheMutex); | |
563 if (!fCache || fCache->getAlpha() != alpha) { | |
564 fCache.reset(SkNEW_ARGS(GradientShaderCache, (alpha, *this))); | |
565 } | |
566 // Increment the ref counter inside the mutex to ensure the returned pointer
is still valid. | |
567 // Otherwise, the pointer may have been overwritten on a different thread be
fore the object's | |
568 // ref count was incremented. | |
569 fCache.get()->ref(); | |
570 return fCache; | |
571 } | |
572 | |
573 /* | |
574 * Because our caller might rebuild the same (logically the same) gradient | 565 * Because our caller might rebuild the same (logically the same) gradient |
575 * over and over, we'd like to return exactly the same "bitmap" if possible, | 566 * over and over, we'd like to return exactly the same "bitmap" if possible, |
576 * allowing the client to utilize a cache of our bitmap (e.g. with a GPU). | 567 * allowing the client to utilize a cache of our bitmap (e.g. with a GPU). |
577 * To do that, we maintain a private cache of built-bitmaps, based on our | 568 * To do that, we maintain a private cache of built-bitmaps, based on our |
578 * colors and positions. Note: we don't try to flatten the fMapper, so if one | 569 * colors and positions. Note: we don't try to flatten the fMapper, so if one |
579 * is present, we skip the cache for now. | 570 * is present, we skip the cache for now. |
580 */ | 571 */ |
581 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { | 572 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { |
582 // our caller assumes no external alpha, so we ensure that our cache is | 573 // our caller assumes no external alpha, so we ensure that our cache is |
583 // built with 0xFF | 574 // built with 0xFF |
584 GradientShaderCache* cache = this->getCache(0xFF); | 575 this->setCacheAlpha(0xFF); |
585 | 576 |
586 // don't have a way to put the mapper into our cache-key yet | 577 // don't have a way to put the mapper into our cache-key yet |
587 if (fMapper) { | 578 if (fMapper) { |
588 // force our cache32pixelref to be built | 579 // force our cahce32pixelref to be built |
589 (void)cache->getCache32(); | 580 (void)this->getCache32(); |
590 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); | 581 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
591 bitmap->setPixelRef(cache->getCache32PixelRef()); | 582 bitmap->setPixelRef(fCache32PixelRef); |
592 return; | 583 return; |
593 } | 584 } |
594 | 585 |
595 // build our key: [numColors + colors[] + {positions[]} + flags ] | 586 // build our key: [numColors + colors[] + {positions[]} + flags ] |
596 int count = 1 + fColorCount + 1; | 587 int count = 1 + fColorCount + 1; |
597 if (fColorCount > 2) { | 588 if (fColorCount > 2) { |
598 count += fColorCount - 1; // fRecs[].fPos | 589 count += fColorCount - 1; // fRecs[].fPos |
599 } | 590 } |
600 | 591 |
601 SkAutoSTMalloc<16, int32_t> storage(count); | 592 SkAutoSTMalloc<16, int32_t> storage(count); |
(...skipping 18 matching lines...) Expand all Loading... |
620 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; | 611 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; |
621 SkAutoMutexAcquire ama(gMutex); | 612 SkAutoMutexAcquire ama(gMutex); |
622 | 613 |
623 if (NULL == gCache) { | 614 if (NULL == gCache) { |
624 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); | 615 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); |
625 } | 616 } |
626 size_t size = count * sizeof(int32_t); | 617 size_t size = count * sizeof(int32_t); |
627 | 618 |
628 if (!gCache->find(storage.get(), size, bitmap)) { | 619 if (!gCache->find(storage.get(), size, bitmap)) { |
629 // force our cahce32pixelref to be built | 620 // force our cahce32pixelref to be built |
630 (void)cache->getCache32(); | 621 (void)this->getCache32(); |
631 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); | 622 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
632 bitmap->setPixelRef(cache->getCache32PixelRef()); | 623 bitmap->setPixelRef(fCache32PixelRef); |
633 | 624 |
634 gCache->add(storage.get(), size, *bitmap); | 625 gCache->add(storage.get(), size, *bitmap); |
635 } | 626 } |
636 } | 627 } |
637 | 628 |
638 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { | 629 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { |
639 if (info) { | 630 if (info) { |
640 if (info->fColorCount >= fColorCount) { | 631 if (info->fColorCount >= fColorCount) { |
641 if (info->fColors) { | 632 if (info->fColors) { |
642 memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor)
); | 633 memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor)
); |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1142 (*stops)[i] = stop; | 1133 (*stops)[i] = stop; |
1143 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; | 1134 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; |
1144 } | 1135 } |
1145 } | 1136 } |
1146 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); | 1137 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); |
1147 | 1138 |
1148 return outColors; | 1139 return outColors; |
1149 } | 1140 } |
1150 | 1141 |
1151 #endif | 1142 #endif |
OLD | NEW |