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
get_default_mutex()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();
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
setMutex(SkBaseMutex * mutex)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
SkPixelRef(SkBaseMutex * mutex)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
SkPixelRef(SkFlattenableReadBuffer & buffer,SkBaseMutex * mutex)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
setPreLocked(void * pixels,SkColorTable * ctable)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
flatten(SkFlattenableWriteBuffer & buffer) const88 void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
89 buffer.writeBool(fIsImmutable);
90 }
91
lockPixels()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
unlockPixels()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
lockPixelsAreWritable() const119 bool SkPixelRef::lockPixelsAreWritable() const {
120 return this->onLockPixelsAreWritable();
121 }
122
onLockPixelsAreWritable() const123 bool SkPixelRef::onLockPixelsAreWritable() const {
124 return true;
125 }
126
getGenerationID() const127 uint32_t SkPixelRef::getGenerationID() const {
128 if (0 == fGenerationID) {
129 fGenerationID = SkNextPixelRefGenerationID();
130 }
131 return fGenerationID;
132 }
133
notifyPixelsChanged()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
setImmutable()144 void SkPixelRef::setImmutable() {
145 fIsImmutable = true;
146 }
147
readPixels(SkBitmap * dst,const SkIRect * subset)148 bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
149 return this->onReadPixels(dst, subset);
150 }
151
onReadPixels(SkBitmap * dst,const SkIRect * subset)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
Register(const char name[],Factory factory)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)
report_no_entries(const char * functionName)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
NameToFactory(const char name[])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
FactoryToName(Factory fact)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
globalRef(void * data)224 void SkPixelRef::globalRef(void* data) {
225 this->ref();
226 }
227
globalUnref()228 void SkPixelRef::globalUnref() {
229 this->unref();
230 }
231 #endif
232