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