| 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 | 
|---|