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_USE_POSIX_THREADS 12 13 static SkBaseMutex gPixelRefMutexRing[] = { 14 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 15 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 16 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 17 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 18 19 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 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 24 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 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 29 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 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 }; 34 35 // must be a power-of-2. undef to just use 1 mutex 36 #define PIXELREF_MUTEX_RING_COUNT SK_ARRAY_COUNT(gPixelRefMutexRing) 37 38 #else // not pthreads 39 40 // must be a power-of-2. undef to just use 1 mutex 41 #define PIXELREF_MUTEX_RING_COUNT 32 42 static SkBaseMutex gPixelRefMutexRing[PIXELREF_MUTEX_RING_COUNT]; 43 44 #endif 45 46 static 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 59 int32_t SkNextPixelRefGenerationID(); 60 61 int32_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 74 void 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 84 static 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 90 SkPixelRef::SkPixelRef(const SkImageInfo& info) : fInfo(validate_info(info)) { 91 this->setMutex(NULL); 92 fRec.zero(); 93 fLockCount = 0; 94 this->needsNewGenID(); 95 fIsImmutable = false; 96 fPreLocked = false; 97 } 98 99 100 SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) : fInfo(validate_info(info)) { 101 this->setMutex(mutex); 102 fRec.zero(); 103 fLockCount = 0; 104 this->needsNewGenID(); 105 fIsImmutable = false; 106 fPreLocked = false; 107 } 108 109 SkPixelRef::~SkPixelRef() { 110 this->callGenIDChangeListeners(); 111 } 112 113 void SkPixelRef::needsNewGenID() { 114 fGenerationID = 0; 115 fUniqueGenerationID = false; 116 } 117 118 void SkPixelRef::cloneGenID(const SkPixelRef& that) { 119 // This is subtle. We must call that.getGenerationID() to make sure its genID isn't 0. 120 this->fGenerationID = that.getGenerationID(); 121 this->fUniqueGenerationID = false; 122 that.fUniqueGenerationID = false; 123 } 124 125 void SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) { 126 #ifndef SK_IGNORE_PIXELREF_SETPRELOCKED 127 // only call me in your constructor, otherwise fLockCount tracking can get 128 // out of sync. 129 fRec.fPixels = pixels; 130 fRec.fColorTable = ctable; 131 fRec.fRowBytes = rowBytes; 132 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; 133 fPreLocked = true; 134 #endif 135 } 136 137 bool SkPixelRef::lockPixels(LockRec* rec) { 138 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 139 140 if (!fPreLocked) { 141 SkAutoMutexAcquire ac(*fMutex); 142 143 if (1 == ++fLockCount) { 144 SkASSERT(fRec.isZero()); 145 146 LockRec rec; 147 if (!this->onNewLockPixels(&rec)) { 148 return false; 149 } 150 SkASSERT(!rec.isZero()); // else why did onNewLock return true? 151 fRec = rec; 152 } 153 } 154 *rec = fRec; 155 return true; 156 } 157 158 bool SkPixelRef::lockPixels() { 159 LockRec rec; 160 return this->lockPixels(&rec); 161 } 162 163 void SkPixelRef::unlockPixels() { 164 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 165 166 if (!fPreLocked) { 167 SkAutoMutexAcquire ac(*fMutex); 168 169 SkASSERT(fLockCount > 0); 170 if (0 == --fLockCount) { 171 // don't call onUnlockPixels unless onLockPixels succeeded 172 if (fRec.fPixels) { 173 this->onUnlockPixels(); 174 fRec.zero(); 175 } else { 176 SkASSERT(fRec.isZero()); 177 } 178 } 179 } 180 } 181 182 bool SkPixelRef::lockPixelsAreWritable() const { 183 return this->onLockPixelsAreWritable(); 184 } 185 186 bool SkPixelRef::onLockPixelsAreWritable() const { 187 return true; 188 } 189 190 bool SkPixelRef::onImplementsDecodeInto() { 191 return false; 192 } 193 194 bool SkPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) { 195 return false; 196 } 197 198 uint32_t SkPixelRef::getGenerationID() const { 199 if (0 == fGenerationID) { 200 fGenerationID = SkNextPixelRefGenerationID(); 201 fUniqueGenerationID = true; // The only time we can be sure of this! 202 } 203 return fGenerationID; 204 } 205 206 void SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) { 207 if (NULL == listener || !fUniqueGenerationID) { 208 // No point in tracking this if we're not going to call it. 209 SkDELETE(listener); 210 return; 211 } 212 *fGenIDChangeListeners.append() = listener; 213 } 214 215 void SkPixelRef::callGenIDChangeListeners() { 216 // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID. 217 if (fUniqueGenerationID) { 218 for (int i = 0; i < fGenIDChangeListeners.count(); i++) { 219 fGenIDChangeListeners[i]->onChange(); 220 } 221 } 222 // Listeners get at most one shot, so whether these triggered or not, blow them away. 223 fGenIDChangeListeners.deleteAll(); 224 } 225 226 void SkPixelRef::notifyPixelsChanged() { 227 #ifdef SK_DEBUG 228 if (fIsImmutable) { 229 SkDebugf("========== notifyPixelsChanged called on immutable pixelref"); 230 } 231 #endif 232 this->callGenIDChangeListeners(); 233 this->needsNewGenID(); 234 } 235 236 void SkPixelRef::changeAlphaType(SkAlphaType at) { 237 *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeAlphaType(at); 238 } 239 240 void SkPixelRef::setImmutable() { 241 fIsImmutable = true; 242 } 243 244 bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) { 245 return this->onReadPixels(dst, subset); 246 } 247 248 bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { 249 return false; 250 } 251 252 SkData* SkPixelRef::onRefEncodedData() { 253 return NULL; 254 } 255 256 bool SkPixelRef::onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], 257 SkYUVColorSpace* colorSpace) { 258 return false; 259 } 260 261 size_t SkPixelRef::getAllocatedSizeInBytes() const { 262 return 0; 263 } 264 265 /////////////////////////////////////////////////////////////////////////////// 266 267 #ifdef SK_BUILD_FOR_ANDROID 268 void SkPixelRef::globalRef(void* data) { 269 this->ref(); 270 } 271 272 void SkPixelRef::globalUnref() { 273 this->unref(); 274 } 275 #endif 276