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 "SkFlattenable.h" 10 #include "SkThread.h" 11 12 // must be a power-of-2. undef to just use 1 mutex 13 #define PIXELREF_MUTEX_RING_COUNT 32 14 15 #ifdef PIXELREF_MUTEX_RING_COUNT 16 static int32_t gPixelRefMutexRingIndex; 17 static SK_DECLARE_MUTEX_ARRAY(gPixelRefMutexRing, PIXELREF_MUTEX_RING_COUNT); 18 #else 19 SK_DECLARE_STATIC_MUTEX(gPixelRefMutex); 20 #endif 21 22 SkBaseMutex* get_default_mutex() { 23 #ifdef PIXELREF_MUTEX_RING_COUNT 24 // atomic_inc might be overkill here. It may be fine if once in a while 25 // we hit a race-condition and two subsequent calls get the same index... 26 int index = sk_atomic_inc(&gPixelRefMutexRingIndex); 27 return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)]; 28 #else 29 return &gPixelRefMutex; 30 #endif 31 } 32 33 /////////////////////////////////////////////////////////////////////////////// 34 35 extern int32_t SkNextPixelRefGenerationID(); 36 int32_t SkNextPixelRefGenerationID() { 37 static int32_t gPixelRefGenerationID; 38 // do a loop in case our global wraps around, as we never want to 39 // return a 0 40 int32_t genID; 41 do { 42 genID = sk_atomic_inc(&gPixelRefGenerationID) + 1; 43 } while (0 == genID); 44 return genID; 45 } 46 47 /////////////////////////////////////////////////////////////////////////////// 48 49 void SkPixelRef::setMutex(SkBaseMutex* mutex) { 50 if (NULL == mutex) { 51 mutex = get_default_mutex(); 52 } 53 fMutex = mutex; 54 } 55 56 // just need a > 0 value, so pick a funny one to aid in debugging 57 #define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 58 59 SkPixelRef::SkPixelRef(SkBaseMutex* mutex) : fPreLocked(false) { 60 this->setMutex(mutex); 61 fPixels = NULL; 62 fColorTable = NULL; // we do not track ownership of this 63 fLockCount = 0; 64 fGenerationID = 0; // signal to rebuild 65 fIsImmutable = false; 66 fPreLocked = false; 67 } 68 69 SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex) { 70 this->setMutex(mutex); 71 fPixels = NULL; 72 fColorTable = NULL; // we do not track ownership of this 73 fLockCount = 0; 74 fGenerationID = 0; // signal to rebuild 75 fIsImmutable = buffer.readBool(); 76 fPreLocked = false; 77 } 78 79 void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) { 80 // only call me in your constructor, otherwise fLockCount tracking can get 81 // out of sync. 82 fPixels = pixels; 83 fColorTable = ctable; 84 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; 85 fPreLocked = true; 86 } 87 88 void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { 89 buffer.writeBool(fIsImmutable); 90 } 91 92 void SkPixelRef::lockPixels() { 93 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 94 95 if (!fPreLocked) { 96 SkAutoMutexAcquire ac(*fMutex); 97 98 if (1 == ++fLockCount) { 99 fPixels = this->onLockPixels(&fColorTable); 100 } 101 } 102 } 103 104 void SkPixelRef::unlockPixels() { 105 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); 106 107 if (!fPreLocked) { 108 SkAutoMutexAcquire ac(*fMutex); 109 110 SkASSERT(fLockCount > 0); 111 if (0 == --fLockCount) { 112 this->onUnlockPixels(); 113 fPixels = NULL; 114 fColorTable = NULL; 115 } 116 } 117 } 118 119 bool SkPixelRef::lockPixelsAreWritable() const { 120 return this->onLockPixelsAreWritable(); 121 } 122 123 bool SkPixelRef::onLockPixelsAreWritable() const { 124 return true; 125 } 126 127 uint32_t SkPixelRef::getGenerationID() const { 128 if (0 == fGenerationID) { 129 fGenerationID = SkNextPixelRefGenerationID(); 130 } 131 return fGenerationID; 132 } 133 134 void SkPixelRef::notifyPixelsChanged() { 135 #ifdef SK_DEBUG 136 if (fIsImmutable) { 137 SkDebugf("========== notifyPixelsChanged called on immutable pixelref"); 138 } 139 #endif 140 // this signals us to recompute this next time around 141 fGenerationID = 0; 142 } 143 144 void SkPixelRef::setImmutable() { 145 fIsImmutable = true; 146 } 147 148 bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) { 149 return this->onReadPixels(dst, subset); 150 } 151 152 bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { 153 return false; 154 } 155 156 /////////////////////////////////////////////////////////////////////////////// 157 158 #define MAX_PAIR_COUNT 16 159 160 struct Pair { 161 const char* fName; 162 SkPixelRef::Factory fFactory; 163 }; 164 165 static int gCount; 166 static Pair gPairs[MAX_PAIR_COUNT]; 167 168 void SkPixelRef::Register(const char name[], Factory factory) { 169 SkASSERT(name); 170 SkASSERT(factory); 171 172 static bool gOnce; 173 if (!gOnce) { 174 gCount = 0; 175 gOnce = true; 176 } 177 178 SkASSERT(gCount < MAX_PAIR_COUNT); 179 180 gPairs[gCount].fName = name; 181 gPairs[gCount].fFactory = factory; 182 gCount += 1; 183 } 184 185 #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG) 186 static void report_no_entries(const char* functionName) { 187 if (!gCount) { 188 SkDebugf("%s has no registered name/factory pairs." 189 " Call SkGraphics::Init() at process initialization time.", 190 functionName); 191 } 192 } 193 #endif 194 195 SkPixelRef::Factory SkPixelRef::NameToFactory(const char name[]) { 196 #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG) 197 report_no_entries(__FUNCTION__); 198 #endif 199 const Pair* pairs = gPairs; 200 for (int i = gCount - 1; i >= 0; --i) { 201 if (strcmp(pairs[i].fName, name) == 0) { 202 return pairs[i].fFactory; 203 } 204 } 205 return NULL; 206 } 207 208 const char* SkPixelRef::FactoryToName(Factory fact) { 209 #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG) 210 report_no_entries(__FUNCTION__); 211 #endif 212 const Pair* pairs = gPairs; 213 for (int i = gCount - 1; i >= 0; --i) { 214 if (pairs[i].fFactory == fact) { 215 return pairs[i].fName; 216 } 217 } 218 return NULL; 219 } 220 221 /////////////////////////////////////////////////////////////////////////////// 222 223 #ifdef SK_BUILD_FOR_ANDROID 224 void SkPixelRef::globalRef(void* data) { 225 this->ref(); 226 } 227 228 void SkPixelRef::globalUnref() { 229 this->unref(); 230 } 231 #endif 232