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

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

Issue 241283003: Revert of 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: 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
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
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
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
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
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
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
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
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