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