1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkBitmapCache.h" 9 #include "SkPixelRef.h" 10 #include "SkThread.h" 11 #include "SkTraceEvent.h" 12 13 #ifdef SK_BUILD_FOR_WIN32 14 // We don't have SK_BASE_MUTEX_INIT on Windows. 15 16 // must be a power-of-2. undef to just use 1 mutex 17 #define PIXELREF_MUTEX_RING_COUNT 32 18 static SkBaseMutex gPixelRefMutexRing[PIXELREF_MUTEX_RING_COUNT]; 19 20 #else 21 static SkBaseMutex gPixelRefMutexRing[] = { 22 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 23 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 24 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 25 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 26 27 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 28 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 29 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 30 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 31 32 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 33 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 34 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 35 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 36 37 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 38 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 39 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 40 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 41 }; 42 // must be a power-of-2. undef to just use 1 mutex 43 #define PIXELREF_MUTEX_RING_COUNT SK_ARRAY_COUNT(gPixelRefMutexRing) 44 45 #endif 46 47 static SkBaseMutex* get_default_mutex() { 48 static int32_t gPixelRefMutexRingIndex; 49 50 SkASSERT(SkIsPow2(PIXELREF_MUTEX_RING_COUNT)); 51 52 // atomic_inc might be overkill here. It may be fine if once in a while 53 // we hit a race-condition and two subsequent calls get the same index... 54 int index = sk_atomic_inc(&gPixelRefMutexRingIndex); 55 return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)]; 56 } 57 58 /////////////////////////////////////////////////////////////////////////////// 59 60 static uint32_t next_gen_id() { 61 static uint32_t gNextGenID = 0; 62 uint32_t genID; 63 // Loop in case our global wraps around, as we never want to return a 0. 64 do { 65 genID = sk_atomic_fetch_add(&gNextGenID, 2u) + 2; // Never set the low bit. 66 } while (0 == genID); 67 return genID; 68 } 69 70 /////////////////////////////////////////////////////////////////////////////// 71 72 void SkPixelRef::setMutex(SkBaseMutex* mutex) { 73 if (NULL == mutex) { 74 mutex = get_default_mutex(); 75 } 76 fMutex = mutex; 77 } 78 79 // just need a > 0 value, so pick a funny one to aid in debugging 80 #define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 81 82 static SkImageInfo validate_info(const SkImageInfo& info) { 83 SkAlphaType newAlphaType = info.alphaType(); 84 SkAssertResult(SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAlphaType)); 85 return info.makeAlphaType(newAlphaType); 86 } 87 88 SkPixelRef::SkPixelRef(const SkImageInfo& info) 89 : fInfo(validate_info(info)) 90 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 91 , fStableID(next_gen_id()) 92 #endif 93 94 { 95 this->setMutex(NULL); 96 fRec.zero(); 97 fLockCount = 0; 98 this->needsNewGenID(); 99 fIsImmutable = false; 100 fPreLocked = false; 101 fAddedToCache.store(false); 102 } 103 104 105 SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) 106 : fInfo(validate_info(info)) 107 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 108 , fStableID(next_gen_id()) 109 #endif 110 { 111 this->setMutex(mutex); 112 fRec.zero(); 113 fLockCount = 0; 114 this->needsNewGenID(); 115 fIsImmutable = false; 116 fPreLocked = false; 117 fAddedToCache.store(false); 118 } 119 120 SkPixelRef::~SkPixelRef() { 121 this->callGenIDChangeListeners(); 122 } 123 124 void SkPixelRef::needsNewGenID() { 125 fTaggedGenID.store(0); 126 SkASSERT(!this->genIDIsUnique()); // This method isn't threadsafe, so the assert should be fine. 127 } 128 129 void SkPixelRef::cloneGenID(const SkPixelRef& that) { 130 // This is subtle. We must call that.getGenerationID() to make sure its genID isn't 0. 131 uint32_t genID = that.getGenerationID(); 132 133 // Neither ID is unique any more. 134 // (These & ~1u are actually redundant. that.getGenerationID() just did it for us.) 135 this->fTaggedGenID.store(genID & ~1u); 136 that. fTaggedGenID.store(genID & ~1u); 137 138 // This method isn't threadsafe, so these asserts should be fine. 139 SkASSERT(!this->genIDIsUnique()); 140 SkASSERT(!that. genIDIsUnique()); 141 } 142 143 void SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) { 144 #ifndef SK_IGNORE_PIXELREF_SETPRELOCKED 145 // only call me in your constructor, otherwise fLockCount tracking can get 146 // out of sync. 147 fRec.fPixels = pixels; 148 fRec.fColorTable = ctable; 149 fRec.fRowBytes = rowBytes; 150 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; 151 fPreLocked = true; 152 #endif 153 } 154 155 bool SkPixelRef::lockPixels(LockRec* rec) { 156 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 157 158 if (!fPreLocked) { 159 TRACE_EVENT_BEGIN0("skia", "SkPixelRef::lockPixelsMutex"); 160 SkAutoMutexAcquire ac(*fMutex); 161 TRACE_EVENT_END0("skia", "SkPixelRef::lockPixelsMutex"); 162 163 if (1 == ++fLockCount) { 164 SkASSERT(fRec.isZero()); 165 166 LockRec rec; 167 if (!this->onNewLockPixels(&rec)) { 168 return false; 169 } 170 SkASSERT(!rec.isZero()); // else why did onNewLock return true? 171 fRec = rec; 172 } 173 } 174 *rec = fRec; 175 return true; 176 } 177 178 bool SkPixelRef::lockPixels() { 179 LockRec rec; 180 return this->lockPixels(&rec); 181 } 182 183 void SkPixelRef::unlockPixels() { 184 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 185 186 if (!fPreLocked) { 187 SkAutoMutexAcquire ac(*fMutex); 188 189 SkASSERT(fLockCount > 0); 190 if (0 == --fLockCount) { 191 // don't call onUnlockPixels unless onLockPixels succeeded 192 if (fRec.fPixels) { 193 this->onUnlockPixels(); 194 fRec.zero(); 195 } else { 196 SkASSERT(fRec.isZero()); 197 } 198 } 199 } 200 } 201 202 bool SkPixelRef::lockPixelsAreWritable() const { 203 return this->onLockPixelsAreWritable(); 204 } 205 206 bool SkPixelRef::onLockPixelsAreWritable() const { 207 return true; 208 } 209 210 uint32_t SkPixelRef::getGenerationID() const { 211 uint32_t id = fTaggedGenID.load(); 212 if (0 == id) { 213 uint32_t next = next_gen_id() | 1u; 214 if (fTaggedGenID.compare_exchange(&id, next)) { 215 id = next; // There was no race or we won the race. fTaggedGenID is next now. 216 } else { 217 // We lost a race to set fTaggedGenID. compare_exchange() filled id with the winner. 218 } 219 // We can't quite SkASSERT(this->genIDIsUnique()). It could be non-unique 220 // if we got here via the else path (pretty unlikely, but possible). 221 } 222 return id & ~1u; // Mask off bottom unique bit. 223 } 224 225 void SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) { 226 if (NULL == listener || !this->genIDIsUnique()) { 227 // No point in tracking this if we're not going to call it. 228 SkDELETE(listener); 229 return; 230 } 231 *fGenIDChangeListeners.append() = listener; 232 } 233 234 // we need to be called *before* the genID gets changed or zerod 235 void SkPixelRef::callGenIDChangeListeners() { 236 // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID. 237 if (this->genIDIsUnique()) { 238 for (int i = 0; i < fGenIDChangeListeners.count(); i++) { 239 fGenIDChangeListeners[i]->onChange(); 240 } 241 242 // TODO: SkAtomic could add "old_value = atomic.xchg(new_value)" to make this clearer. 243 if (fAddedToCache.load()) { 244 SkNotifyBitmapGenIDIsStale(this->getGenerationID()); 245 fAddedToCache.store(false); 246 } 247 } 248 // Listeners get at most one shot, so whether these triggered or not, blow them away. 249 fGenIDChangeListeners.deleteAll(); 250 } 251 252 void SkPixelRef::notifyPixelsChanged() { 253 #ifdef SK_DEBUG 254 if (fIsImmutable) { 255 SkDebugf("========== notifyPixelsChanged called on immutable pixelref"); 256 } 257 #endif 258 this->callGenIDChangeListeners(); 259 this->needsNewGenID(); 260 } 261 262 void SkPixelRef::changeAlphaType(SkAlphaType at) { 263 *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeAlphaType(at); 264 } 265 266 void SkPixelRef::setImmutable() { 267 fIsImmutable = true; 268 } 269 270 bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) { 271 return this->onReadPixels(dst, subset); 272 } 273 274 bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { 275 return false; 276 } 277 278 SkData* SkPixelRef::onRefEncodedData() { 279 return NULL; 280 } 281 282 bool SkPixelRef::onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], 283 SkYUVColorSpace* colorSpace) { 284 return false; 285 } 286 287 size_t SkPixelRef::getAllocatedSizeInBytes() const { 288 return 0; 289 } 290 291