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