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