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

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: fCachedLocalMatrix 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
« no previous file with comments | « src/effects/SkTransparentShader.cpp ('k') | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(this->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 = kPMColor_SkColorType;
521 467
522 if (NULL == fCache32PixelRef) { 468 if (cache->fCache16Storage == NULL) { // set the storage and our working ptr
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 = kPMColor_SkColorType;
517
518 if (NULL == cache->fCache32PixelRef) {
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 SK_DECLARE_STATIC_MUTEX(cacheMutex);
scroggo 2014/04/14 21:11:13 Does this need to be static?
Dominik Grewe 2014/04/15 11:46:32 No. Made it a class member.
565 SkAutoMutexAcquire ama(cacheMutex);
566 if (!fCache || fCache->getAlpha() != alpha) {
scroggo 2014/04/14 21:11:13 Does "!fCache" do the right thing here? Or do you
Dominik Grewe 2014/04/15 11:46:32 It seems to be doing the right thing. Stepping thr
567 fCache.reset(SkNEW_ARGS(GradientShaderCache, (alpha, *this)));
568 }
569 fCache.get()->ref();
scroggo 2014/04/14 21:11:13 As in the picture shader, it would be nice to add
Dominik Grewe 2014/04/15 11:46:32 Done.
570 return fCache;
571 }
572
573 /*
565 * Because our caller might rebuild the same (logically the same) gradient 574 * 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, 575 * 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). 576 * 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 577 * 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 578 * colors and positions. Note: we don't try to flatten the fMapper, so if one
570 * is present, we skip the cache for now. 579 * is present, we skip the cache for now.
571 */ 580 */
572 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { 581 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
573 // our caller assumes no external alpha, so we ensure that our cache is 582 // our caller assumes no external alpha, so we ensure that our cache is
574 // built with 0xFF 583 // built with 0xFF
575 this->setCacheAlpha(0xFF); 584 GradientShaderCache* cache = this->getCache(0xFF);
576 585
577 // don't have a way to put the mapper into our cache-key yet 586 // don't have a way to put the mapper into our cache-key yet
578 if (fMapper) { 587 if (fMapper) {
579 // force our cahce32pixelref to be built 588 // force our cache32pixelref to be built
580 (void)this->getCache32(); 589 (void)cache->getCache32();
581 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); 590 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1));
582 bitmap->setPixelRef(fCache32PixelRef); 591 bitmap->setPixelRef(cache->getCache32PixelRef());
583 return; 592 return;
584 } 593 }
585 594
586 // build our key: [numColors + colors[] + {positions[]} + flags ] 595 // build our key: [numColors + colors[] + {positions[]} + flags ]
587 int count = 1 + fColorCount + 1; 596 int count = 1 + fColorCount + 1;
588 if (fColorCount > 2) { 597 if (fColorCount > 2) {
589 count += fColorCount - 1; // fRecs[].fPos 598 count += fColorCount - 1; // fRecs[].fPos
590 } 599 }
591 600
592 SkAutoSTMalloc<16, int32_t> storage(count); 601 SkAutoSTMalloc<16, int32_t> storage(count);
(...skipping 18 matching lines...) Expand all
611 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; 620 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32;
612 SkAutoMutexAcquire ama(gMutex); 621 SkAutoMutexAcquire ama(gMutex);
613 622
614 if (NULL == gCache) { 623 if (NULL == gCache) {
615 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); 624 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS));
616 } 625 }
617 size_t size = count * sizeof(int32_t); 626 size_t size = count * sizeof(int32_t);
618 627
619 if (!gCache->find(storage.get(), size, bitmap)) { 628 if (!gCache->find(storage.get(), size, bitmap)) {
620 // force our cahce32pixelref to be built 629 // force our cahce32pixelref to be built
621 (void)this->getCache32(); 630 (void)cache->getCache32();
622 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); 631 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1));
623 bitmap->setPixelRef(fCache32PixelRef); 632 bitmap->setPixelRef(cache->getCache32PixelRef());
624 633
625 gCache->add(storage.get(), size, *bitmap); 634 gCache->add(storage.get(), size, *bitmap);
626 } 635 }
627 } 636 }
628 637
629 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { 638 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
630 if (info) { 639 if (info) {
631 if (info->fColorCount >= fColorCount) { 640 if (info->fColorCount >= fColorCount) {
632 if (info->fColors) { 641 if (info->fColors) {
633 memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor) ); 642 memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor) );
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 (*stops)[i] = stop; 1142 (*stops)[i] = stop;
1134 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; 1143 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f;
1135 } 1144 }
1136 } 1145 }
1137 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); 1146 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount));
1138 1147
1139 return outColors; 1148 return outColors;
1140 } 1149 }
1141 1150
1142 #endif 1151 #endif
OLDNEW
« no previous file with comments | « src/effects/SkTransparentShader.cpp ('k') | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698