| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 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 "SkBitmapCache.h" | 8 #include "SkBitmapCache.h" |
| 9 #include "SkMutex.h" | 9 #include "SkMutex.h" |
| 10 #include "SkPixelRef.h" | 10 #include "SkPixelRef.h" |
| 11 #include "SkTraceEvent.h" | 11 #include "SkTraceEvent.h" |
| 12 | 12 |
| 13 //#define SK_SUPPORT_LEGACY_UNBALANCED_PIXELREF_LOCKCOUNT | 13 //#define SK_SUPPORT_LEGACY_UNBALANCED_PIXELREF_LOCKCOUNT |
| 14 //#define SK_TRACE_PIXELREF_LIFETIME | 14 //#define SK_TRACE_PIXELREF_LIFETIME |
| 15 | 15 |
| 16 #ifdef SK_BUILD_FOR_WIN32 | |
| 17 // We don't have SK_BASE_MUTEX_INIT on Windows. | |
| 18 | |
| 19 // must be a power-of-2. undef to just use 1 mutex | |
| 20 #define PIXELREF_MUTEX_RING_COUNT 32 | |
| 21 static SkBaseMutex gPixelRefMutexRing[PIXELREF_MUTEX_RING_COUNT]; | |
| 22 | |
| 23 #else | |
| 24 static SkBaseMutex gPixelRefMutexRing[] = { | |
| 25 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 26 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 27 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 28 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 29 | |
| 30 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 31 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 32 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 33 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 34 | |
| 35 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 36 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 37 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 38 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 39 | |
| 40 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 41 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 42 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 43 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
| 44 }; | |
| 45 // must be a power-of-2. undef to just use 1 mutex | |
| 46 #define PIXELREF_MUTEX_RING_COUNT SK_ARRAY_COUNT(gPixelRefMutexRing) | |
| 47 | |
| 48 #endif | |
| 49 | |
| 50 static SkBaseMutex* get_default_mutex() { | |
| 51 static int32_t gPixelRefMutexRingIndex; | |
| 52 | |
| 53 SkASSERT(SkIsPow2(PIXELREF_MUTEX_RING_COUNT)); | |
| 54 | |
| 55 // atomic_inc might be overkill here. It may be fine if once in a while | |
| 56 // we hit a race-condition and two subsequent calls get the same index... | |
| 57 int index = sk_atomic_inc(&gPixelRefMutexRingIndex); | |
| 58 return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)]; | |
| 59 } | |
| 60 | |
| 61 /////////////////////////////////////////////////////////////////////////////// | |
| 62 #include "SkNextID.h" | 16 #include "SkNextID.h" |
| 63 | 17 |
| 64 uint32_t SkNextID::ImageID() { | 18 uint32_t SkNextID::ImageID() { |
| 65 static uint32_t gID = 0; | 19 static uint32_t gID = 0; |
| 66 uint32_t id; | 20 uint32_t id; |
| 67 // Loop in case our global wraps around, as we never want to return a 0. | 21 // Loop in case our global wraps around, as we never want to return a 0. |
| 68 do { | 22 do { |
| 69 id = sk_atomic_fetch_add(&gID, 2u) + 2; // Never set the low bit. | 23 id = sk_atomic_fetch_add(&gID, 2u) + 2; // Never set the low bit. |
| 70 } while (0 == id); | 24 } while (0 == id); |
| 71 return id; | 25 return id; |
| 72 } | 26 } |
| 73 | 27 |
| 74 /////////////////////////////////////////////////////////////////////////////// | 28 /////////////////////////////////////////////////////////////////////////////// |
| 75 | 29 |
| 76 void SkPixelRef::setMutex(SkBaseMutex* mutex) { | |
| 77 if (NULL == mutex) { | |
| 78 mutex = get_default_mutex(); | |
| 79 } | |
| 80 fMutex = mutex; | |
| 81 } | |
| 82 | |
| 83 // just need a > 0 value, so pick a funny one to aid in debugging | 30 // just need a > 0 value, so pick a funny one to aid in debugging |
| 84 #define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 | 31 #define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 |
| 85 | 32 |
| 86 static SkImageInfo validate_info(const SkImageInfo& info) { | 33 static SkImageInfo validate_info(const SkImageInfo& info) { |
| 87 SkAlphaType newAlphaType = info.alphaType(); | 34 SkAlphaType newAlphaType = info.alphaType(); |
| 88 SkAssertResult(SkColorTypeValidateAlphaType(info.colorType(), info.alphaType
(), &newAlphaType)); | 35 SkAssertResult(SkColorTypeValidateAlphaType(info.colorType(), info.alphaType
(), &newAlphaType)); |
| 89 return info.makeAlphaType(newAlphaType); | 36 return info.makeAlphaType(newAlphaType); |
| 90 } | 37 } |
| 91 | 38 |
| 92 #ifdef SK_TRACE_PIXELREF_LIFETIME | 39 #ifdef SK_TRACE_PIXELREF_LIFETIME |
| 93 static int32_t gInstCounter; | 40 static int32_t gInstCounter; |
| 94 #endif | 41 #endif |
| 95 | 42 |
| 96 SkPixelRef::SkPixelRef(const SkImageInfo& info) | 43 SkPixelRef::SkPixelRef(const SkImageInfo& info) |
| 97 : fInfo(validate_info(info)) | 44 : fInfo(validate_info(info)) |
| 98 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 45 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
| 99 , fStableID(SkNextID::ImageID()) | 46 , fStableID(SkNextID::ImageID()) |
| 100 #endif | 47 #endif |
| 101 | 48 |
| 102 { | 49 { |
| 103 #ifdef SK_TRACE_PIXELREF_LIFETIME | 50 #ifdef SK_TRACE_PIXELREF_LIFETIME |
| 104 SkDebugf(" pixelref %d\n", sk_atomic_inc(&gInstCounter)); | 51 SkDebugf(" pixelref %d\n", sk_atomic_inc(&gInstCounter)); |
| 105 #endif | 52 #endif |
| 106 this->setMutex(NULL); | |
| 107 fRec.zero(); | 53 fRec.zero(); |
| 108 fLockCount = 0; | 54 fLockCount = 0; |
| 109 this->needsNewGenID(); | 55 this->needsNewGenID(); |
| 110 fMutability = kMutable; | |
| 111 fPreLocked = false; | |
| 112 fAddedToCache.store(false); | |
| 113 } | |
| 114 | |
| 115 | |
| 116 SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) | |
| 117 : fInfo(validate_info(info)) | |
| 118 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | |
| 119 , fStableID(SkNextID::ImageID()) | |
| 120 #endif | |
| 121 { | |
| 122 #ifdef SK_TRACE_PIXELREF_LIFETIME | |
| 123 SkDebugf(" pixelref %d\n", sk_atomic_inc(&gInstCounter)); | |
| 124 #endif | |
| 125 this->setMutex(mutex); | |
| 126 fRec.zero(); | |
| 127 fLockCount = 0; | |
| 128 this->needsNewGenID(); | |
| 129 fMutability = kMutable; | 56 fMutability = kMutable; |
| 130 fPreLocked = false; | 57 fPreLocked = false; |
| 131 fAddedToCache.store(false); | 58 fAddedToCache.store(false); |
| 132 } | 59 } |
| 133 | 60 |
| 134 SkPixelRef::~SkPixelRef() { | 61 SkPixelRef::~SkPixelRef() { |
| 135 #ifndef SK_SUPPORT_LEGACY_UNBALANCED_PIXELREF_LOCKCOUNT | 62 #ifndef SK_SUPPORT_LEGACY_UNBALANCED_PIXELREF_LOCKCOUNT |
| 136 SkASSERT(SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount || 0 == fLockCount); | 63 SkASSERT(SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount || 0 == fLockCount); |
| 137 #endif | 64 #endif |
| 138 | 65 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 // out of sync. | 106 // out of sync. |
| 180 fRec.fPixels = pixels; | 107 fRec.fPixels = pixels; |
| 181 fRec.fColorTable = ctable; | 108 fRec.fColorTable = ctable; |
| 182 fRec.fRowBytes = rowBytes; | 109 fRec.fRowBytes = rowBytes; |
| 183 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; | 110 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; |
| 184 fPreLocked = true; | 111 fPreLocked = true; |
| 185 } | 112 } |
| 186 | 113 |
| 187 // Increments fLockCount only on success | 114 // Increments fLockCount only on success |
| 188 bool SkPixelRef::lockPixelsInsideMutex() { | 115 bool SkPixelRef::lockPixelsInsideMutex() { |
| 189 fMutex->assertHeld(); | 116 fMutex.assertHeld(); |
| 190 | 117 |
| 191 if (1 == ++fLockCount) { | 118 if (1 == ++fLockCount) { |
| 192 SkASSERT(fRec.isZero()); | 119 SkASSERT(fRec.isZero()); |
| 193 if (!this->onNewLockPixels(&fRec)) { | 120 if (!this->onNewLockPixels(&fRec)) { |
| 194 fRec.zero(); | 121 fRec.zero(); |
| 195 fLockCount -= 1; // we return fLockCount unchanged if we fail. | 122 fLockCount -= 1; // we return fLockCount unchanged if we fail. |
| 196 return false; | 123 return false; |
| 197 } | 124 } |
| 198 } | 125 } |
| 199 if (fRec.fPixels) { | 126 if (fRec.fPixels) { |
| 200 validate_pixels_ctable(fInfo, fRec.fColorTable); | 127 validate_pixels_ctable(fInfo, fRec.fColorTable); |
| 201 return true; | 128 return true; |
| 202 } | 129 } |
| 203 // no pixels, so we failed (somehow) | 130 // no pixels, so we failed (somehow) |
| 204 --fLockCount; | 131 --fLockCount; |
| 205 return false; | 132 return false; |
| 206 } | 133 } |
| 207 | 134 |
| 208 // For historical reasons, we always inc fLockCount, even if we return false. | 135 // For historical reasons, we always inc fLockCount, even if we return false. |
| 209 // It would be nice to change this (it seems), and only inc if we actually succe
ed... | 136 // It would be nice to change this (it seems), and only inc if we actually succe
ed... |
| 210 bool SkPixelRef::lockPixels() { | 137 bool SkPixelRef::lockPixels() { |
| 211 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); | 138 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); |
| 212 | 139 |
| 213 if (!fPreLocked) { | 140 if (!fPreLocked) { |
| 214 TRACE_EVENT_BEGIN0("skia", "SkPixelRef::lockPixelsMutex"); | 141 TRACE_EVENT_BEGIN0("skia", "SkPixelRef::lockPixelsMutex"); |
| 215 SkAutoMutexAcquire ac(*fMutex); | 142 SkAutoMutexAcquire ac(fMutex); |
| 216 TRACE_EVENT_END0("skia", "SkPixelRef::lockPixelsMutex"); | 143 TRACE_EVENT_END0("skia", "SkPixelRef::lockPixelsMutex"); |
| 217 SkDEBUGCODE(int oldCount = fLockCount;) | 144 SkDEBUGCODE(int oldCount = fLockCount;) |
| 218 bool success = this->lockPixelsInsideMutex(); | 145 bool success = this->lockPixelsInsideMutex(); |
| 219 // lockPixelsInsideMutex only increments the count if it succeeds. | 146 // lockPixelsInsideMutex only increments the count if it succeeds. |
| 220 SkASSERT(oldCount + (int)success == fLockCount); | 147 SkASSERT(oldCount + (int)success == fLockCount); |
| 221 | 148 |
| 222 if (!success) { | 149 if (!success) { |
| 223 // For compatibility with SkBitmap calling lockPixels, we still want
to increment | 150 // For compatibility with SkBitmap calling lockPixels, we still want
to increment |
| 224 // fLockCount even if we failed. If we updated SkBitmap we could rem
ove this oddity. | 151 // fLockCount even if we failed. If we updated SkBitmap we could rem
ove this oddity. |
| 225 fLockCount += 1; | 152 fLockCount += 1; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 238 *rec = fRec; | 165 *rec = fRec; |
| 239 return true; | 166 return true; |
| 240 } | 167 } |
| 241 return false; | 168 return false; |
| 242 } | 169 } |
| 243 | 170 |
| 244 void SkPixelRef::unlockPixels() { | 171 void SkPixelRef::unlockPixels() { |
| 245 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); | 172 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); |
| 246 | 173 |
| 247 if (!fPreLocked) { | 174 if (!fPreLocked) { |
| 248 SkAutoMutexAcquire ac(*fMutex); | 175 SkAutoMutexAcquire ac(fMutex); |
| 249 | 176 |
| 250 SkASSERT(fLockCount > 0); | 177 SkASSERT(fLockCount > 0); |
| 251 if (0 == --fLockCount) { | 178 if (0 == --fLockCount) { |
| 252 // don't call onUnlockPixels unless onLockPixels succeeded | 179 // don't call onUnlockPixels unless onLockPixels succeeded |
| 253 if (fRec.fPixels) { | 180 if (fRec.fPixels) { |
| 254 this->onUnlockPixels(); | 181 this->onUnlockPixels(); |
| 255 fRec.zero(); | 182 fRec.zero(); |
| 256 } else { | 183 } else { |
| 257 SkASSERT(fRec.isZero()); | 184 SkASSERT(fRec.isZero()); |
| 258 } | 185 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 271 } | 198 } |
| 272 | 199 |
| 273 if (fPreLocked) { | 200 if (fPreLocked) { |
| 274 result->fUnlockProc = NULL; | 201 result->fUnlockProc = NULL; |
| 275 result->fUnlockContext = NULL; | 202 result->fUnlockContext = NULL; |
| 276 result->fCTable = fRec.fColorTable; | 203 result->fCTable = fRec.fColorTable; |
| 277 result->fPixels = fRec.fPixels; | 204 result->fPixels = fRec.fPixels; |
| 278 result->fRowBytes = fRec.fRowBytes; | 205 result->fRowBytes = fRec.fRowBytes; |
| 279 result->fSize.set(fInfo.width(), fInfo.height()); | 206 result->fSize.set(fInfo.width(), fInfo.height()); |
| 280 } else { | 207 } else { |
| 281 SkAutoMutexAcquire ac(*fMutex); | 208 SkAutoMutexAcquire ac(fMutex); |
| 282 if (!this->onRequestLock(request, result)) { | 209 if (!this->onRequestLock(request, result)) { |
| 283 return false; | 210 return false; |
| 284 } | 211 } |
| 285 } | 212 } |
| 286 if (result->fPixels) { | 213 if (result->fPixels) { |
| 287 validate_pixels_ctable(fInfo, result->fCTable); | 214 validate_pixels_ctable(fInfo, result->fCTable); |
| 288 return true; | 215 return true; |
| 289 } | 216 } |
| 290 return false; | 217 return false; |
| 291 } | 218 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 } | 344 } |
| 418 | 345 |
| 419 result->fUnlockProc = unlock_legacy_result; | 346 result->fUnlockProc = unlock_legacy_result; |
| 420 result->fUnlockContext = SkRef(this); // this is balanced in our fUnlockPr
oc | 347 result->fUnlockContext = SkRef(this); // this is balanced in our fUnlockPr
oc |
| 421 result->fCTable = fRec.fColorTable; | 348 result->fCTable = fRec.fColorTable; |
| 422 result->fPixels = fRec.fPixels; | 349 result->fPixels = fRec.fPixels; |
| 423 result->fRowBytes = fRec.fRowBytes; | 350 result->fRowBytes = fRec.fRowBytes; |
| 424 result->fSize.set(fInfo.width(), fInfo.height()); | 351 result->fSize.set(fInfo.width(), fInfo.height()); |
| 425 return true; | 352 return true; |
| 426 } | 353 } |
| OLD | NEW |