SkPixelRef.cpp revision ed458688e284508f17a0408a093d89a8b5966e32
1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8#include "SkPixelRef.h" 9#include "SkReadBuffer.h" 10#include "SkWriteBuffer.h" 11#include "SkThread.h" 12 13#ifdef SK_USE_POSIX_THREADS 14 15 static SkBaseMutex gPixelRefMutexRing[] = { 16 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 17 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 18 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 19 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, 20 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 37 // must be a power-of-2. undef to just use 1 mutex 38 #define PIXELREF_MUTEX_RING_COUNT SK_ARRAY_COUNT(gPixelRefMutexRing) 39 40#else // not pthreads 41 42 // must be a power-of-2. undef to just use 1 mutex 43 #define PIXELREF_MUTEX_RING_COUNT 32 44 static SkBaseMutex gPixelRefMutexRing[PIXELREF_MUTEX_RING_COUNT]; 45 46#endif 47 48static SkBaseMutex* get_default_mutex() { 49 static int32_t gPixelRefMutexRingIndex; 50 51 SkASSERT(SkIsPow2(PIXELREF_MUTEX_RING_COUNT)); 52 53 // atomic_inc might be overkill here. It may be fine if once in a while 54 // we hit a race-condition and two subsequent calls get the same index... 55 int index = sk_atomic_inc(&gPixelRefMutexRingIndex); 56 return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)]; 57} 58 59/////////////////////////////////////////////////////////////////////////////// 60 61int32_t SkNextPixelRefGenerationID(); 62 63int32_t SkNextPixelRefGenerationID() { 64 static int32_t gPixelRefGenerationID; 65 // do a loop in case our global wraps around, as we never want to 66 // return a 0 67 int32_t genID; 68 do { 69 genID = sk_atomic_inc(&gPixelRefGenerationID) + 1; 70 } while (0 == genID); 71 return genID; 72} 73 74/////////////////////////////////////////////////////////////////////////////// 75 76void 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 84#define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 85 86SkPixelRef::SkPixelRef(const SkImageInfo& info) : fInfo(info) { 87 SkAssertResult(SkColorTypeValidateAlphaType(fInfo.colorType(), fInfo.alphaType(), 88 const_cast<SkAlphaType*>(&fInfo.fAlphaType))); 89 90 this->setMutex(NULL); 91 fRec.zero(); 92 fLockCount = 0; 93 this->needsNewGenID(); 94 fIsImmutable = false; 95 fPreLocked = false; 96} 97 98 99SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) : fInfo(info) { 100 SkAssertResult(SkColorTypeValidateAlphaType(fInfo.colorType(), fInfo.alphaType(), 101 const_cast<SkAlphaType*>(&fInfo.fAlphaType))); 102 103 this->setMutex(mutex); 104 fRec.zero(); 105 fLockCount = 0; 106 this->needsNewGenID(); 107 fIsImmutable = false; 108 fPreLocked = false; 109} 110 111SkPixelRef::~SkPixelRef() { 112 this->callGenIDChangeListeners(); 113} 114 115void SkPixelRef::needsNewGenID() { 116 fGenerationID = 0; 117 fUniqueGenerationID = false; 118} 119 120void SkPixelRef::cloneGenID(const SkPixelRef& that) { 121 // This is subtle. We must call that.getGenerationID() to make sure its genID isn't 0. 122 this->fGenerationID = that.getGenerationID(); 123 this->fUniqueGenerationID = false; 124 that.fUniqueGenerationID = false; 125} 126 127void SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) { 128#ifndef SK_IGNORE_PIXELREF_SETPRELOCKED 129 // only call me in your constructor, otherwise fLockCount tracking can get 130 // out of sync. 131 fRec.fPixels = pixels; 132 fRec.fColorTable = ctable; 133 fRec.fRowBytes = rowBytes; 134 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; 135 fPreLocked = true; 136#endif 137} 138 139bool SkPixelRef::lockPixels(LockRec* rec) { 140 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 141 142 if (!fPreLocked) { 143 SkAutoMutexAcquire ac(*fMutex); 144 145 if (1 == ++fLockCount) { 146 SkASSERT(fRec.isZero()); 147 148 LockRec rec; 149 if (!this->onNewLockPixels(&rec)) { 150 return false; 151 } 152 SkASSERT(!rec.isZero()); // else why did onNewLock return true? 153 fRec = rec; 154 } 155 } 156 *rec = fRec; 157 return true; 158} 159 160bool SkPixelRef::lockPixels() { 161 LockRec rec; 162 return this->lockPixels(&rec); 163} 164 165void SkPixelRef::unlockPixels() { 166 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 167 168 if (!fPreLocked) { 169 SkAutoMutexAcquire ac(*fMutex); 170 171 SkASSERT(fLockCount > 0); 172 if (0 == --fLockCount) { 173 // don't call onUnlockPixels unless onLockPixels succeeded 174 if (fRec.fPixels) { 175 this->onUnlockPixels(); 176 fRec.zero(); 177 } else { 178 SkASSERT(fRec.isZero()); 179 } 180 } 181 } 182} 183 184bool SkPixelRef::lockPixelsAreWritable() const { 185 return this->onLockPixelsAreWritable(); 186} 187 188bool SkPixelRef::onLockPixelsAreWritable() const { 189 return true; 190} 191 192bool SkPixelRef::onImplementsDecodeInto() { 193 return false; 194} 195 196bool SkPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) { 197 return false; 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<SkAlphaType*>(&fInfo.fAlphaType) = 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 258size_t SkPixelRef::getAllocatedSizeInBytes() const { 259 return 0; 260} 261 262/////////////////////////////////////////////////////////////////////////////// 263 264#ifdef SK_BUILD_FOR_ANDROID 265void SkPixelRef::globalRef(void* data) { 266 this->ref(); 267} 268 269void SkPixelRef::globalUnref() { 270 this->unref(); 271} 272#endif 273