Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: src/effects/gradients/SkGradientShader.cpp

Issue 207683004: Extract most of the mutable state of SkShader into a separate Context object. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase & Leon's comments Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698