Chromium Code Reviews| 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(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(U8CPU alpha) { | |
| 238 // Only initialize the cache in getCache16/32. | |
| 239 fCache16 = NULL; | |
| 240 fCache32 = NULL; | |
| 241 fCache16Storage = NULL; | |
| 242 fCache32PixelRef = NULL; | |
| 243 fCacheAlpha = alpha; | |
| 244 } | |
| 245 | |
| 246 SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() { | |
| 247 sk_free(fCache16Storage); | |
| 248 SkSafeUnref(fCache32PixelRef); | |
| 249 } | |
| 250 | |
| 272 #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) | 251 #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) |
| 273 | 252 |
| 274 /** We take the original colors, not our premultiplied PMColors, since we can | 253 /** 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 | 254 build a 16bit table as long as the original colors are opaque, even if the |
| 276 paint specifies a non-opaque alpha. | 255 paint specifies a non-opaque alpha. |
| 277 */ | 256 */ |
| 278 void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1, | 257 void SkGradientShaderBase::GradientShaderCache::Build16bitCache( |
| 279 int count) { | 258 uint16_t cache[], SkColor c0, SkColor c1, int count) { |
| 280 SkASSERT(count > 1); | 259 SkASSERT(count > 1); |
| 281 SkASSERT(SkColorGetA(c0) == 0xFF); | 260 SkASSERT(SkColorGetA(c0) == 0xFF); |
| 282 SkASSERT(SkColorGetA(c1) == 0xFF); | 261 SkASSERT(SkColorGetA(c1) == 0xFF); |
| 283 | 262 |
| 284 SkFixed r = SkColorGetR(c0); | 263 SkFixed r = SkColorGetR(c0); |
| 285 SkFixed g = SkColorGetG(c0); | 264 SkFixed g = SkColorGetG(c0); |
| 286 SkFixed b = SkColorGetB(c0); | 265 SkFixed b = SkColorGetB(c0); |
| 287 | 266 |
| 288 SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); | 267 SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); |
| 289 SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); | 268 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 | 296 * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead |
| 318 * of using | | 297 * of using | |
| 319 * | 298 * |
| 320 * We chose #1 just because it was more localized. | 299 * We chose #1 just because it was more localized. |
| 321 * See http://code.google.com/p/skia/issues/detail?id=1113 | 300 * See http://code.google.com/p/skia/issues/detail?id=1113 |
| 322 * | 301 * |
| 323 * The type SkUFixed encapsulate this need for unsigned, but logically Fixed. | 302 * The type SkUFixed encapsulate this need for unsigned, but logically Fixed. |
| 324 */ | 303 */ |
| 325 typedef uint32_t SkUFixed; | 304 typedef uint32_t SkUFixed; |
| 326 | 305 |
| 327 void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColo r c1, | 306 void SkGradientShaderBase::GradientShaderCache::Build32bitCache( |
| 328 int count, U8CPU paintAlpha, uint32_t grad Flags) { | 307 SkPMColor cache[], SkColor c0, SkColor c1, |
| 308 int count, U8CPU paintAlpha, uint32_t gradFlags) { | |
| 329 SkASSERT(count > 1); | 309 SkASSERT(count > 1); |
| 330 | 310 |
| 331 // need to apply paintAlpha to our two endpoints | 311 // need to apply paintAlpha to our two endpoints |
| 332 uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha); | 312 uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha); |
| 333 uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha); | 313 uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha); |
| 334 | 314 |
| 335 | 315 |
| 336 const bool interpInPremul = SkToBool(gradFlags & | 316 const bool interpInPremul = SkToBool(gradFlags & |
| 337 SkGradientShader::kInterpolateColorsInPremul_Flag); | 317 SkGradientShader::kInterpolateColorsInPremul_Flag); |
| 338 | 318 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 if (6 == bits) { | 441 if (6 == bits) { |
| 462 return (x << 10) | (x << 4) | (x >> 2); | 442 return (x << 10) | (x << 4) | (x >> 2); |
| 463 } | 443 } |
| 464 if (8 == bits) { | 444 if (8 == bits) { |
| 465 return (x << 8) | x; | 445 return (x << 8) | x; |
| 466 } | 446 } |
| 467 sk_throw(); | 447 sk_throw(); |
| 468 return 0; | 448 return 0; |
| 469 } | 449 } |
| 470 | 450 |
| 471 const uint16_t* SkGradientShaderBase::getCache16() const { | 451 const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16( |
| 452 const SkGradientShaderBase& shader) { | |
| 472 if (fCache16 == NULL) { | 453 if (fCache16 == NULL) { |
| 473 // double the count for dither entries | 454 // double the count for dither entries |
| 474 const int entryCount = kCache16Count * 2; | 455 const int entryCount = kCache16Count * 2; |
| 475 const size_t allocSize = sizeof(uint16_t) * entryCount; | 456 const size_t allocSize = sizeof(uint16_t) * entryCount; |
| 476 | 457 |
| 477 if (fCache16Storage == NULL) { // set the storage and our working ptr | 458 if (fCache16Storage == NULL) { // set the storage and our working ptr |
| 478 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); | 459 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
| 479 } | 460 } |
| 480 fCache16 = fCache16Storage; | 461 fCache16 = fCache16Storage; |
| 481 if (fColorCount == 2) { | 462 if (shader.fColorCount == 2) { |
| 482 Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], | 463 Build16bitCache(fCache16, shader.fOrigColors[0], shader.fOrigColors[ 1], |
| 483 kCache16Count); | 464 kCache16Count); |
| 484 } else { | 465 } else { |
| 485 Rec* rec = fRecs; | 466 Rec* rec = shader.fRecs; |
| 486 int prevIndex = 0; | 467 int prevIndex = 0; |
| 487 for (int i = 1; i < fColorCount; i++) { | 468 for (int i = 1; i < shader.fColorCount; i++) { |
| 488 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; | 469 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; |
| 489 SkASSERT(nextIndex < kCache16Count); | 470 SkASSERT(nextIndex < kCache16Count); |
| 490 | 471 |
| 491 if (nextIndex > prevIndex) | 472 if (nextIndex > prevIndex) |
| 492 Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOri gColors[i], nextIndex - prevIndex + 1); | 473 Build16bitCache(fCache16 + prevIndex, shader.fOrigColors[i-1 ], |
| 474 shader.fOrigColors[i], nextIndex - prevIndex + 1); | |
| 493 prevIndex = nextIndex; | 475 prevIndex = nextIndex; |
| 494 } | 476 } |
| 495 } | 477 } |
| 496 | 478 |
| 497 if (fMapper) { | 479 if (shader.fMapper) { |
| 498 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); | 480 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
| 499 uint16_t* linear = fCache16; // just computed linear data | 481 uint16_t* linear = fCache16; // just computed linear data |
| 500 uint16_t* mapped = fCache16Storage; // storage for mapped data | 482 uint16_t* mapped = fCache16Storage; // storage for mapped data |
| 501 SkUnitMapper* map = fMapper; | 483 SkUnitMapper* map = shader.fMapper; |
| 502 for (int i = 0; i < kCache16Count; i++) { | 484 for (int i = 0; i < kCache16Count; i++) { |
| 503 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache1 6Shift; | 485 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache1 6Shift; |
| 504 mapped[i] = linear[index]; | 486 mapped[i] = linear[index]; |
| 505 mapped[i + kCache16Count] = linear[index + kCache16Count]; | 487 mapped[i + kCache16Count] = linear[index + kCache16Count]; |
| 506 } | 488 } |
| 507 sk_free(fCache16); | 489 sk_free(fCache16); |
| 508 fCache16 = fCache16Storage; | 490 fCache16 = fCache16Storage; |
| 509 } | 491 } |
| 510 } | 492 } |
| 511 return fCache16; | 493 return fCache16; |
| 512 } | 494 } |
| 513 | 495 |
| 514 const SkPMColor* SkGradientShaderBase::getCache32() const { | 496 const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32( |
| 497 const SkGradientShaderBase& shader) { | |
| 515 if (fCache32 == NULL) { | 498 if (fCache32 == NULL) { |
| 516 SkImageInfo info; | 499 SkImageInfo info; |
| 517 info.fWidth = kCache32Count; | 500 info.fWidth = kCache32Count; |
| 518 info.fHeight = 4; // for our 4 dither rows | 501 info.fHeight = 4; // for our 4 dither rows |
| 519 info.fAlphaType = kPremul_SkAlphaType; | 502 info.fAlphaType = kPremul_SkAlphaType; |
| 520 info.fColorType = kPMColor_SkColorType; | 503 info.fColorType = kPMColor_SkColorType; |
| 521 | 504 |
| 522 if (NULL == fCache32PixelRef) { | 505 if (NULL == fCache32PixelRef) { |
| 523 fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); | 506 fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); |
| 524 } | 507 } |
| 525 fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); | 508 fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); |
| 526 if (fColorCount == 2) { | 509 if (shader.fColorCount == 2) { |
| 527 Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1], | 510 Build32bitCache(fCache32, shader.fOrigColors[0], shader.fOrigColors[ 1], |
| 528 kCache32Count, fCacheAlpha, fGradFlags); | 511 kCache32Count, fCacheAlpha, shader.fGradFlags); |
| 529 } else { | 512 } else { |
| 530 Rec* rec = fRecs; | 513 Rec* rec = shader.fRecs; |
| 531 int prevIndex = 0; | 514 int prevIndex = 0; |
| 532 for (int i = 1; i < fColorCount; i++) { | 515 for (int i = 1; i < shader.fColorCount; i++) { |
| 533 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; | 516 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; |
| 534 SkASSERT(nextIndex < kCache32Count); | 517 SkASSERT(nextIndex < kCache32Count); |
| 535 | 518 |
| 536 if (nextIndex > prevIndex) | 519 if (nextIndex > prevIndex) |
| 537 Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1], | 520 Build32bitCache(fCache32 + prevIndex, shader.fOrigColors[i-1 ], |
| 538 fOrigColors[i], nextIndex - prevIndex + 1, | 521 shader.fOrigColors[i], nextIndex - prevIndex + 1, |
| 539 fCacheAlpha, fGradFlags); | 522 fCacheAlpha, shader.fGradFlags); |
| 540 prevIndex = nextIndex; | 523 prevIndex = nextIndex; |
| 541 } | 524 } |
| 542 } | 525 } |
| 543 | 526 |
| 544 if (fMapper) { | 527 if (shader.fMapper) { |
| 545 SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NUL L); | 528 SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NUL L); |
| 546 SkPMColor* linear = fCache32; // just computed linear data | 529 SkPMColor* linear = fCache32; // just computed linear data |
| 547 SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data | 530 SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data |
| 548 SkUnitMapper* map = fMapper; | 531 SkUnitMapper* map = shader.fMapper; |
| 549 for (int i = 0; i < kCache32Count; i++) { | 532 for (int i = 0; i < kCache32Count; i++) { |
| 550 int index = map->mapUnit16((i << 8) | i) >> 8; | 533 int index = map->mapUnit16((i << 8) | i) >> 8; |
| 551 mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; | 534 mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; |
| 552 mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; | 535 mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; |
| 553 mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; | 536 mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; |
| 554 mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; | 537 mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; |
| 555 } | 538 } |
| 556 fCache32PixelRef->unref(); | 539 fCache32PixelRef->unref(); |
| 557 fCache32PixelRef = newPR; | 540 fCache32PixelRef = newPR; |
| 558 fCache32 = (SkPMColor*)newPR->getAddr(); | 541 fCache32 = (SkPMColor*)newPR->getAddr(); |
| 559 } | 542 } |
| 560 } | 543 } |
| 561 return fCache32; | 544 return fCache32; |
| 562 } | 545 } |
| 563 | 546 |
| 564 /* | 547 /* |
| 565 * Because our caller might rebuild the same (logically the same) gradient | 548 * 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, | 549 * over and over, we'd like to return exactly the same "bitmap" if possible, |
|
scroggo
2014/04/03 15:35:54
Now that the cache is not on the SkGradientShader,
Dominik Grewe
2014/04/04 10:59:41
I think the comment is referring to the SkBitmapCa
| |
| 567 * allowing the client to utilize a cache of our bitmap (e.g. with a GPU). | 550 * 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 | 551 * 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 | 552 * colors and positions. Note: we don't try to flatten the fMapper, so if one |
| 570 * is present, we skip the cache for now. | 553 * is present, we skip the cache for now. |
| 571 */ | 554 */ |
| 572 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { | 555 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { |
| 573 // our caller assumes no external alpha, so we ensure that our cache is | 556 // our caller assumes no external alpha, so we ensure that our cache is |
| 574 // built with 0xFF | 557 // built with 0xFF |
| 575 this->setCacheAlpha(0xFF); | 558 GradientShaderCache cache(0xFF); |
| 576 | 559 |
| 577 // don't have a way to put the mapper into our cache-key yet | 560 // don't have a way to put the mapper into our cache-key yet |
| 578 if (fMapper) { | 561 if (fMapper) { |
| 579 // force our cahce32pixelref to be built | 562 // force our cahce32pixelref to be built |
| 580 (void)this->getCache32(); | 563 (void)cache.getCache32(*this); |
| 581 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); | 564 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
| 582 bitmap->setPixelRef(fCache32PixelRef); | 565 bitmap->setPixelRef(cache.getCache32PixelRef()); |
| 583 return; | 566 return; |
| 584 } | 567 } |
| 585 | 568 |
| 586 // build our key: [numColors + colors[] + {positions[]} + flags ] | 569 // build our key: [numColors + colors[] + {positions[]} + flags ] |
| 587 int count = 1 + fColorCount + 1; | 570 int count = 1 + fColorCount + 1; |
| 588 if (fColorCount > 2) { | 571 if (fColorCount > 2) { |
| 589 count += fColorCount - 1; // fRecs[].fPos | 572 count += fColorCount - 1; // fRecs[].fPos |
| 590 } | 573 } |
| 591 | 574 |
| 592 SkAutoSTMalloc<16, int32_t> storage(count); | 575 SkAutoSTMalloc<16, int32_t> storage(count); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 611 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; | 594 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; |
| 612 SkAutoMutexAcquire ama(gMutex); | 595 SkAutoMutexAcquire ama(gMutex); |
| 613 | 596 |
| 614 if (NULL == gCache) { | 597 if (NULL == gCache) { |
| 615 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); | 598 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); |
| 616 } | 599 } |
| 617 size_t size = count * sizeof(int32_t); | 600 size_t size = count * sizeof(int32_t); |
| 618 | 601 |
| 619 if (!gCache->find(storage.get(), size, bitmap)) { | 602 if (!gCache->find(storage.get(), size, bitmap)) { |
| 620 // force our cahce32pixelref to be built | 603 // force our cahce32pixelref to be built |
| 621 (void)this->getCache32(); | 604 (void)cache.getCache32(*this); |
| 622 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); | 605 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
| 623 bitmap->setPixelRef(fCache32PixelRef); | 606 bitmap->setPixelRef(cache.getCache32PixelRef()); |
| 624 | 607 |
| 625 gCache->add(storage.get(), size, *bitmap); | 608 gCache->add(storage.get(), size, *bitmap); |
| 626 } | 609 } |
| 627 } | 610 } |
| 628 | 611 |
| 629 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { | 612 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { |
| 630 if (info) { | 613 if (info) { |
| 631 if (info->fColorCount >= fColorCount) { | 614 if (info->fColorCount >= fColorCount) { |
| 632 if (info->fColors) { | 615 if (info->fColors) { |
| 633 memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor) ); | 616 memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor) ); |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1133 (*stops)[i] = stop; | 1116 (*stops)[i] = stop; |
| 1134 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; | 1117 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; |
| 1135 } | 1118 } |
| 1136 } | 1119 } |
| 1137 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); | 1120 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); |
| 1138 | 1121 |
| 1139 return outColors; | 1122 return outColors; |
| 1140 } | 1123 } |
| 1141 | 1124 |
| 1142 #endif | 1125 #endif |
| OLD | NEW |