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 48 static 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 61 int32_t SkNextPixelRefGenerationID(); 62 63 int32_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 76 void 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 86 SkPixelRef::SkPixelRef(const SkImageInfo& info) 87 : fInfo(info) 88 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 89 , fStableID(SkNextPixelRefGenerationID()) 90 #endif 91 { 92 this->setMutex(NULL); 93 fRec.zero(); 94 fLockCount = 0; 95 this->needsNewGenID(); 96 fIsImmutable = false; 97 fPreLocked = false; 98 } 99 100 101 SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) 102 : fInfo(info) 103 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 104 , fStableID(SkNextPixelRefGenerationID()) 105 #endif 106 { 107 this->setMutex(mutex); 108 fRec.zero(); 109 fLockCount = 0; 110 this->needsNewGenID(); 111 fIsImmutable = false; 112 fPreLocked = false; 113 } 114 115 static SkImageInfo read_info(SkReadBuffer& buffer) { 116 SkImageInfo info; 117 info.unflatten(buffer); 118 return info; 119 } 120 121 SkPixelRef::SkPixelRef(SkReadBuffer& buffer, SkBaseMutex* mutex) 122 : INHERITED(buffer) 123 , fInfo(read_info(buffer)) 124 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 125 , fStableID(SkNextPixelRefGenerationID()) 126 #endif 127 { 128 this->setMutex(mutex); 129 fRec.zero(); 130 fLockCount = 0; 131 fIsImmutable = buffer.readBool(); 132 fGenerationID = buffer.readUInt(); 133 fUniqueGenerationID = false; // Conservatively assuming the original still exists. 134 fPreLocked = false; 135 } 136 137 SkPixelRef::~SkPixelRef() { 138 this->callGenIDChangeListeners(); 139 } 140 141 void SkPixelRef::needsNewGenID() { 142 fGenerationID = 0; 143 fUniqueGenerationID = false; 144 } 145 146 void SkPixelRef::cloneGenID(const SkPixelRef& that) { 147 // This is subtle. We must call that.getGenerationID() to make sure its genID isn't 0. 148 this->fGenerationID = that.getGenerationID(); 149 this->fUniqueGenerationID = false; 150 that.fUniqueGenerationID = false; 151 } 152 153 void SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) { 154 #ifndef SK_IGNORE_PIXELREF_SETPRELOCKED 155 // only call me in your constructor, otherwise fLockCount tracking can get 156 // out of sync. 157 fRec.fPixels = pixels; 158 fRec.fColorTable = ctable; 159 fRec.fRowBytes = rowBytes; 160 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; 161 fPreLocked = true; 162 #endif 163 } 164 165 void SkPixelRef::flatten(SkWriteBuffer& buffer) const { 166 this->INHERITED::flatten(buffer); 167 fInfo.flatten(buffer); 168 buffer.writeBool(fIsImmutable); 169 // We write the gen ID into the picture for within-process recording. This 170 // is safe since the same genID will never refer to two different sets of 171 // pixels (barring overflow). However, each process has its own "namespace" 172 // of genIDs. So for cross-process recording we write a zero which will 173 // trigger assignment of a new genID in playback. 174 if (buffer.isCrossProcess()) { 175 buffer.writeUInt(0); 176 } else { 177 buffer.writeUInt(fGenerationID); 178 fUniqueGenerationID = false; // Conservative, a copy is probably about to exist. 179 } 180 } 181 182 bool SkPixelRef::lockPixels(LockRec* rec) { 183 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 184 185 if (!fPreLocked) { 186 SkAutoMutexAcquire ac(*fMutex); 187 188 if (1 == ++fLockCount) { 189 SkASSERT(fRec.isZero()); 190 191 LockRec rec; 192 if (!this->onNewLockPixels(&rec)) { 193 return false; 194 } 195 SkASSERT(!rec.isZero()); // else why did onNewLock return true? 196 fRec = rec; 197 } 198 } 199 *rec = fRec; 200 return true; 201 } 202 203 bool SkPixelRef::lockPixels() { 204 LockRec rec; 205 return this->lockPixels(&rec); 206 } 207 208 void SkPixelRef::unlockPixels() { 209 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 210 211 if (!fPreLocked) { 212 SkAutoMutexAcquire ac(*fMutex); 213 214 SkASSERT(fLockCount > 0); 215 if (0 == --fLockCount) { 216 // don't call onUnlockPixels unless onLockPixels succeeded 217 if (fRec.fPixels) { 218 this->onUnlockPixels(); 219 fRec.zero(); 220 } else { 221 SkASSERT(fRec.isZero()); 222 } 223 } 224 } 225 } 226 227 bool SkPixelRef::lockPixelsAreWritable() const { 228 return this->onLockPixelsAreWritable(); 229 } 230 231 bool SkPixelRef::onLockPixelsAreWritable() const { 232 return true; 233 } 234 235 bool SkPixelRef::onImplementsDecodeInto() { 236 return false; 237 } 238 239 bool SkPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) { 240 return false; 241 } 242 243 uint32_t SkPixelRef::getGenerationID() const { 244 if (0 == fGenerationID) { 245 fGenerationID = SkNextPixelRefGenerationID(); 246 fUniqueGenerationID = true; // The only time we can be sure of this! 247 } 248 return fGenerationID; 249 } 250 251 void SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) { 252 if (NULL == listener || !fUniqueGenerationID) { 253 // No point in tracking this if we're not going to call it. 254 SkDELETE(listener); 255 return; 256 } 257 *fGenIDChangeListeners.append() = listener; 258 } 259 260 void SkPixelRef::callGenIDChangeListeners() { 261 // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID. 262 if (fUniqueGenerationID) { 263 for (int i = 0; i < fGenIDChangeListeners.count(); i++) { 264 fGenIDChangeListeners[i]->onChange(); 265 } 266 } 267 // Listeners get at most one shot, so whether these triggered or not, blow them away. 268 fGenIDChangeListeners.deleteAll(); 269 } 270 271 void SkPixelRef::notifyPixelsChanged() { 272 #ifdef SK_DEBUG 273 if (fIsImmutable) { 274 SkDebugf("========== notifyPixelsChanged called on immutable pixelref"); 275 } 276 #endif 277 this->callGenIDChangeListeners(); 278 this->needsNewGenID(); 279 } 280 281 void SkPixelRef::changeAlphaType(SkAlphaType at) { 282 *const_cast<SkAlphaType*>(&fInfo.fAlphaType) = at; 283 } 284 285 void SkPixelRef::setImmutable() { 286 fIsImmutable = true; 287 } 288 289 bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) { 290 return this->onReadPixels(dst, subset); 291 } 292 293 bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { 294 return false; 295 } 296 297 SkData* SkPixelRef::onRefEncodedData() { 298 return NULL; 299 } 300 301 size_t SkPixelRef::getAllocatedSizeInBytes() const { 302 return 0; 303 } 304 305 /////////////////////////////////////////////////////////////////////////////// 306 307 #ifdef SK_BUILD_FOR_ANDROID 308 void SkPixelRef::globalRef(void* data) { 309 this->ref(); 310 } 311 312 void SkPixelRef::globalUnref() { 313 this->unref(); 314 } 315 #endif 316