SkPixelRef.cpp revision f1715706f761e7e254f601abf33581702fa8fe17
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 "SkFlattenableBuffers.h" 10#include "SkThread.h" 11 12#ifdef SK_USE_POSIX_THREADS 13 14 static SkBaseMutex gPixelRefMutexRing[] = { 15 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 16 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 17 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 18 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 19 20 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 21 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 22 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 23 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 24 25 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 26 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 27 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 28 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 29 30 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 31 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 32 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 33 { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, 34 }; 35 36 // must be a power-of-2. undef to just use 1 mutex 37 #define PIXELREF_MUTEX_RING_COUNT SK_ARRAY_COUNT(gPixelRefMutexRing) 38 39#else // not pthreads 40 41 // must be a power-of-2. undef to just use 1 mutex 42 #define PIXELREF_MUTEX_RING_COUNT 32 43 static SkBaseMutex gPixelRefMutexRing[PIXELREF_MUTEX_RING_COUNT]; 44 45#endif 46 47static 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 60int32_t SkNextPixelRefGenerationID(); 61 62int32_t SkNextPixelRefGenerationID() { 63 static int32_t gPixelRefGenerationID; 64 // do a loop in case our global wraps around, as we never want to 65 // return a 0 66 int32_t genID; 67 do { 68 genID = sk_atomic_inc(&gPixelRefGenerationID) + 1; 69 } while (0 == genID); 70 return genID; 71} 72 73/////////////////////////////////////////////////////////////////////////////// 74 75void SkPixelRef::setMutex(SkBaseMutex* mutex) { 76 if (NULL == mutex) { 77 mutex = get_default_mutex(); 78 } 79 fMutex = mutex; 80} 81 82// just need a > 0 value, so pick a funny one to aid in debugging 83#define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 84 85SkPixelRef::SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex) { 86 this->setMutex(mutex); 87 fPixels = NULL; 88 fColorTable = NULL; // we do not track ownership of this 89 fLockCount = 0; 90 this->needsNewGenID(); 91 fIsImmutable = false; 92 fPreLocked = false; 93} 94 95SkPixelRef::SkPixelRef(const SkImageInfo&) { 96 this->setMutex(NULL); 97 fPixels = NULL; 98 fColorTable = NULL; // we do not track ownership of this 99 fLockCount = 0; 100 this->needsNewGenID(); 101 fIsImmutable = false; 102 fPreLocked = false; 103} 104 105#ifdef SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR 106// THIS GUY IS DEPRECATED -- don't use me! 107SkPixelRef::SkPixelRef(SkBaseMutex* mutex) { 108 this->setMutex(mutex); 109 fPixels = NULL; 110 fColorTable = NULL; // we do not track ownership of this 111 fLockCount = 0; 112 this->needsNewGenID(); 113 fIsImmutable = false; 114 fPreLocked = false; 115} 116#endif 117 118SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex) 119 : INHERITED(buffer) { 120 this->setMutex(mutex); 121 fPixels = NULL; 122 fColorTable = NULL; // we do not track ownership of this 123 fLockCount = 0; 124 fIsImmutable = buffer.readBool(); 125 fGenerationID = buffer.readUInt(); 126 fUniqueGenerationID = false; // Conservatively assuming the original still exists. 127 fPreLocked = false; 128} 129 130SkPixelRef::~SkPixelRef() { 131 this->callGenIDChangeListeners(); 132} 133 134void SkPixelRef::needsNewGenID() { 135 fGenerationID = 0; 136 fUniqueGenerationID = false; 137} 138 139void SkPixelRef::cloneGenID(const SkPixelRef& that) { 140 // This is subtle. We must call that.getGenerationID() to make sure its genID isn't 0. 141 this->fGenerationID = that.getGenerationID(); 142 this->fUniqueGenerationID = false; 143 that.fUniqueGenerationID = false; 144} 145 146void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) { 147#ifndef SK_IGNORE_PIXELREF_SETPRELOCKED 148 // only call me in your constructor, otherwise fLockCount tracking can get 149 // out of sync. 150 fPixels = pixels; 151 fColorTable = ctable; 152 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; 153 fPreLocked = true; 154#endif 155} 156 157void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { 158 this->INHERITED::flatten(buffer); 159 buffer.writeBool(fIsImmutable); 160 // We write the gen ID into the picture for within-process recording. This 161 // is safe since the same genID will never refer to two different sets of 162 // pixels (barring overflow). However, each process has its own "namespace" 163 // of genIDs. So for cross-process recording we write a zero which will 164 // trigger assignment of a new genID in playback. 165 if (buffer.isCrossProcess()) { 166 buffer.writeUInt(0); 167 } else { 168 buffer.writeUInt(fGenerationID); 169 fUniqueGenerationID = false; // Conservative, a copy is probably about to exist. 170 } 171} 172 173void SkPixelRef::lockPixels() { 174 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 175 176 if (!fPreLocked) { 177 SkAutoMutexAcquire ac(*fMutex); 178 179 if (1 == ++fLockCount) { 180 fPixels = this->onLockPixels(&fColorTable); 181 } 182 } 183} 184 185void SkPixelRef::unlockPixels() { 186 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 187 188 if (!fPreLocked) { 189 SkAutoMutexAcquire ac(*fMutex); 190 191 SkASSERT(fLockCount > 0); 192 if (0 == --fLockCount) { 193 this->onUnlockPixels(); 194 fPixels = NULL; 195 fColorTable = NULL; 196 } 197 } 198} 199 200bool SkPixelRef::lockPixelsAreWritable() const { 201 return this->onLockPixelsAreWritable(); 202} 203 204bool SkPixelRef::onLockPixelsAreWritable() const { 205 return true; 206} 207 208bool SkPixelRef::onImplementsDecodeInto() { 209 return false; 210} 211 212bool SkPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) { 213 return false; 214} 215 216uint32_t SkPixelRef::getGenerationID() const { 217 if (0 == fGenerationID) { 218 fGenerationID = SkNextPixelRefGenerationID(); 219 fUniqueGenerationID = true; // The only time we can be sure of this! 220 } 221 return fGenerationID; 222} 223 224void SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) { 225 if (NULL == listener || !fUniqueGenerationID) { 226 // No point in tracking this if we're not going to call it. 227 SkDELETE(listener); 228 return; 229 } 230 *fGenIDChangeListeners.append() = listener; 231} 232 233void SkPixelRef::callGenIDChangeListeners() { 234 // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID. 235 if (fUniqueGenerationID) { 236 for (int i = 0; i < fGenIDChangeListeners.count(); i++) { 237 fGenIDChangeListeners[i]->onChange(); 238 } 239 } 240 // Listeners get at most one shot, so whether these triggered or not, blow them away. 241 fGenIDChangeListeners.deleteAll(); 242} 243 244void SkPixelRef::notifyPixelsChanged() { 245#ifdef SK_DEBUG 246 if (fIsImmutable) { 247 SkDebugf("========== notifyPixelsChanged called on immutable pixelref"); 248 } 249#endif 250 this->callGenIDChangeListeners(); 251 this->needsNewGenID(); 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 270size_t SkPixelRef::getAllocatedSizeInBytes() const { 271 return 0; 272} 273 274/////////////////////////////////////////////////////////////////////////////// 275 276#ifdef SK_BUILD_FOR_ANDROID 277void SkPixelRef::globalRef(void* data) { 278 this->ref(); 279} 280 281void SkPixelRef::globalUnref() { 282 this->unref(); 283} 284#endif 285