SkPixelRef.cpp revision c73dd5c6880739f26216f198c757028fd28df1a4
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 12SK_DEFINE_INST_COUNT(SkPixelRef) 13 14// must be a power-of-2. undef to just use 1 mutex 15#define PIXELREF_MUTEX_RING_COUNT 32 16 17#ifdef PIXELREF_MUTEX_RING_COUNT 18 static int32_t gPixelRefMutexRingIndex; 19 static SK_DECLARE_MUTEX_ARRAY(gPixelRefMutexRing, PIXELREF_MUTEX_RING_COUNT); 20#else 21 SK_DECLARE_STATIC_MUTEX(gPixelRefMutex); 22#endif 23 24static SkBaseMutex* get_default_mutex() { 25#ifdef PIXELREF_MUTEX_RING_COUNT 26 // atomic_inc might be overkill here. It may be fine if once in a while 27 // we hit a race-condition and two subsequent calls get the same index... 28 int index = sk_atomic_inc(&gPixelRefMutexRingIndex); 29 return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)]; 30#else 31 return &gPixelRefMutex; 32#endif 33} 34 35/////////////////////////////////////////////////////////////////////////////// 36 37int32_t SkNextPixelRefGenerationID() { 38 static int32_t gPixelRefGenerationID; 39 // do a loop in case our global wraps around, as we never want to 40 // return a 0 41 int32_t genID; 42 do { 43 genID = sk_atomic_inc(&gPixelRefGenerationID) + 1; 44 } while (0 == genID); 45 return genID; 46} 47 48/////////////////////////////////////////////////////////////////////////////// 49 50void SkPixelRef::setMutex(SkBaseMutex* mutex) { 51 if (NULL == mutex) { 52 mutex = get_default_mutex(); 53 } 54 fMutex = mutex; 55} 56 57// just need a > 0 value, so pick a funny one to aid in debugging 58#define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 59 60SkPixelRef::SkPixelRef(SkBaseMutex* mutex) : fPreLocked(false) { 61 this->setMutex(mutex); 62 fPixels = NULL; 63 fColorTable = NULL; // we do not track ownership of this 64 fLockCount = 0; 65 fGenerationID = 0; // signal to rebuild 66 fIsImmutable = false; 67 fPreLocked = false; 68} 69 70SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex) 71 : INHERITED(buffer) { 72 this->setMutex(mutex); 73 fPixels = NULL; 74 fColorTable = NULL; // we do not track ownership of this 75 fLockCount = 0; 76 fIsImmutable = buffer.readBool(); 77 fGenerationID = buffer.readUInt(); 78 fPreLocked = false; 79} 80 81void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) { 82 // only call me in your constructor, otherwise fLockCount tracking can get 83 // out of sync. 84 fPixels = pixels; 85 fColorTable = ctable; 86 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; 87 fPreLocked = true; 88} 89 90void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { 91 this->INHERITED::flatten(buffer); 92 buffer.writeBool(fIsImmutable); 93 // We write the gen ID into the picture for within-process recording. This 94 // is safe since the same genID will never refer to two different sets of 95 // pixels (barring overflow). However, each process has its own "namespace" 96 // of genIDs. So for cross-process recording we write a zero which will 97 // trigger assignment of a new genID in playback. 98 if (buffer.isCrossProcess()) { 99 buffer.writeUInt(0); 100 } else { 101 buffer.writeUInt(fGenerationID); 102 } 103} 104 105void SkPixelRef::lockPixels() { 106 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 107 108 if (!fPreLocked) { 109 SkAutoMutexAcquire ac(*fMutex); 110 111 if (1 == ++fLockCount) { 112 fPixels = this->onLockPixels(&fColorTable); 113 } 114 } 115} 116 117void SkPixelRef::unlockPixels() { 118 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 119 120 if (!fPreLocked) { 121 SkAutoMutexAcquire ac(*fMutex); 122 123 SkASSERT(fLockCount > 0); 124 if (0 == --fLockCount) { 125 this->onUnlockPixels(); 126 fPixels = NULL; 127 fColorTable = NULL; 128 } 129 } 130} 131 132bool SkPixelRef::lockPixelsAreWritable() const { 133 return this->onLockPixelsAreWritable(); 134} 135 136bool SkPixelRef::onLockPixelsAreWritable() const { 137 return true; 138} 139 140uint32_t SkPixelRef::getGenerationID() const { 141 if (0 == fGenerationID) { 142 fGenerationID = SkNextPixelRefGenerationID(); 143 } 144 return fGenerationID; 145} 146 147void SkPixelRef::notifyPixelsChanged() { 148#ifdef SK_DEBUG 149 if (fIsImmutable) { 150 SkDebugf("========== notifyPixelsChanged called on immutable pixelref"); 151 } 152#endif 153 // this signals us to recompute this next time around 154 fGenerationID = 0; 155} 156 157void SkPixelRef::setImmutable() { 158 fIsImmutable = true; 159} 160 161bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) { 162 return this->onReadPixels(dst, subset); 163} 164 165bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { 166 return false; 167} 168 169/////////////////////////////////////////////////////////////////////////////// 170 171#ifdef SK_BUILD_FOR_ANDROID 172void SkPixelRef::globalRef(void* data) { 173 this->ref(); 174} 175 176void SkPixelRef::globalUnref() { 177 this->unref(); 178} 179#endif 180