OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBitmapCache.h" | 8 #include "SkBitmapCache.h" |
9 #include "SkMutex.h" | 9 #include "SkMutex.h" |
10 #include "SkPixelRef.h" | 10 #include "SkPixelRef.h" |
11 #include "SkTraceEvent.h" | 11 #include "SkTraceEvent.h" |
12 | 12 |
13 //#define SK_SUPPORT_LEGACY_UNBALANCED_PIXELREF_LOCKCOUNT | 13 //#define SK_SUPPORT_LEGACY_UNBALANCED_PIXELREF_LOCKCOUNT |
14 //#define SK_TRACE_PIXELREF_LIFETIME | 14 //#define SK_TRACE_PIXELREF_LIFETIME |
15 | 15 |
16 #ifdef SK_BUILD_FOR_WIN32 | |
17 // We don't have SK_BASE_MUTEX_INIT on Windows. | |
18 | |
19 // must be a power-of-2. undef to just use 1 mutex | |
20 #define PIXELREF_MUTEX_RING_COUNT 32 | |
21 static SkBaseMutex gPixelRefMutexRing[PIXELREF_MUTEX_RING_COUNT]; | |
22 | |
23 #else | |
24 static SkBaseMutex gPixelRefMutexRing[] = { | |
25 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
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 | |
30 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
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 | |
35 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
36 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
37 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
38 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
39 | |
40 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
41 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
42 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
43 SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT, | |
44 }; | |
45 // must be a power-of-2. undef to just use 1 mutex | |
46 #define PIXELREF_MUTEX_RING_COUNT SK_ARRAY_COUNT(gPixelRefMutexRing) | |
47 | |
48 #endif | |
49 | |
50 static SkBaseMutex* get_default_mutex() { | |
51 static int32_t gPixelRefMutexRingIndex; | |
52 | |
53 SkASSERT(SkIsPow2(PIXELREF_MUTEX_RING_COUNT)); | |
54 | |
55 // atomic_inc might be overkill here. It may be fine if once in a while | |
56 // we hit a race-condition and two subsequent calls get the same index... | |
57 int index = sk_atomic_inc(&gPixelRefMutexRingIndex); | |
58 return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)]; | |
59 } | |
60 | |
61 /////////////////////////////////////////////////////////////////////////////// | |
62 #include "SkNextID.h" | 16 #include "SkNextID.h" |
63 | 17 |
64 uint32_t SkNextID::ImageID() { | 18 uint32_t SkNextID::ImageID() { |
65 static uint32_t gID = 0; | 19 static uint32_t gID = 0; |
66 uint32_t id; | 20 uint32_t id; |
67 // Loop in case our global wraps around, as we never want to return a 0. | 21 // Loop in case our global wraps around, as we never want to return a 0. |
68 do { | 22 do { |
69 id = sk_atomic_fetch_add(&gID, 2u) + 2; // Never set the low bit. | 23 id = sk_atomic_fetch_add(&gID, 2u) + 2; // Never set the low bit. |
70 } while (0 == id); | 24 } while (0 == id); |
71 return id; | 25 return id; |
72 } | 26 } |
73 | 27 |
74 /////////////////////////////////////////////////////////////////////////////// | 28 /////////////////////////////////////////////////////////////////////////////// |
75 | 29 |
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 | 30 // just need a > 0 value, so pick a funny one to aid in debugging |
84 #define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 | 31 #define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 |
85 | 32 |
86 static SkImageInfo validate_info(const SkImageInfo& info) { | 33 static SkImageInfo validate_info(const SkImageInfo& info) { |
87 SkAlphaType newAlphaType = info.alphaType(); | 34 SkAlphaType newAlphaType = info.alphaType(); |
88 SkAssertResult(SkColorTypeValidateAlphaType(info.colorType(), info.alphaType
(), &newAlphaType)); | 35 SkAssertResult(SkColorTypeValidateAlphaType(info.colorType(), info.alphaType
(), &newAlphaType)); |
89 return info.makeAlphaType(newAlphaType); | 36 return info.makeAlphaType(newAlphaType); |
90 } | 37 } |
91 | 38 |
92 #ifdef SK_TRACE_PIXELREF_LIFETIME | 39 #ifdef SK_TRACE_PIXELREF_LIFETIME |
93 static int32_t gInstCounter; | 40 static int32_t gInstCounter; |
94 #endif | 41 #endif |
95 | 42 |
96 SkPixelRef::SkPixelRef(const SkImageInfo& info) | 43 SkPixelRef::SkPixelRef(const SkImageInfo& info) |
97 : fInfo(validate_info(info)) | 44 : fInfo(validate_info(info)) |
98 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 45 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
99 , fStableID(SkNextID::ImageID()) | 46 , fStableID(SkNextID::ImageID()) |
100 #endif | 47 #endif |
101 | 48 |
102 { | 49 { |
103 #ifdef SK_TRACE_PIXELREF_LIFETIME | 50 #ifdef SK_TRACE_PIXELREF_LIFETIME |
104 SkDebugf(" pixelref %d\n", sk_atomic_inc(&gInstCounter)); | 51 SkDebugf(" pixelref %d\n", sk_atomic_inc(&gInstCounter)); |
105 #endif | 52 #endif |
106 this->setMutex(NULL); | |
107 fRec.zero(); | 53 fRec.zero(); |
108 fLockCount = 0; | 54 fLockCount = 0; |
109 this->needsNewGenID(); | 55 this->needsNewGenID(); |
110 fMutability = kMutable; | |
111 fPreLocked = false; | |
112 fAddedToCache.store(false); | |
113 } | |
114 | |
115 | |
116 SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) | |
117 : fInfo(validate_info(info)) | |
118 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | |
119 , fStableID(SkNextID::ImageID()) | |
120 #endif | |
121 { | |
122 #ifdef SK_TRACE_PIXELREF_LIFETIME | |
123 SkDebugf(" pixelref %d\n", sk_atomic_inc(&gInstCounter)); | |
124 #endif | |
125 this->setMutex(mutex); | |
126 fRec.zero(); | |
127 fLockCount = 0; | |
128 this->needsNewGenID(); | |
129 fMutability = kMutable; | 56 fMutability = kMutable; |
130 fPreLocked = false; | 57 fPreLocked = false; |
131 fAddedToCache.store(false); | 58 fAddedToCache.store(false); |
132 } | 59 } |
133 | 60 |
134 SkPixelRef::~SkPixelRef() { | 61 SkPixelRef::~SkPixelRef() { |
135 #ifndef SK_SUPPORT_LEGACY_UNBALANCED_PIXELREF_LOCKCOUNT | 62 #ifndef SK_SUPPORT_LEGACY_UNBALANCED_PIXELREF_LOCKCOUNT |
136 SkASSERT(SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount || 0 == fLockCount); | 63 SkASSERT(SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount || 0 == fLockCount); |
137 #endif | 64 #endif |
138 | 65 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 // out of sync. | 106 // out of sync. |
180 fRec.fPixels = pixels; | 107 fRec.fPixels = pixels; |
181 fRec.fColorTable = ctable; | 108 fRec.fColorTable = ctable; |
182 fRec.fRowBytes = rowBytes; | 109 fRec.fRowBytes = rowBytes; |
183 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; | 110 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; |
184 fPreLocked = true; | 111 fPreLocked = true; |
185 } | 112 } |
186 | 113 |
187 // Increments fLockCount only on success | 114 // Increments fLockCount only on success |
188 bool SkPixelRef::lockPixelsInsideMutex() { | 115 bool SkPixelRef::lockPixelsInsideMutex() { |
189 fMutex->assertHeld(); | 116 fMutex.assertHeld(); |
190 | 117 |
191 if (1 == ++fLockCount) { | 118 if (1 == ++fLockCount) { |
192 SkASSERT(fRec.isZero()); | 119 SkASSERT(fRec.isZero()); |
193 if (!this->onNewLockPixels(&fRec)) { | 120 if (!this->onNewLockPixels(&fRec)) { |
194 fRec.zero(); | 121 fRec.zero(); |
195 fLockCount -= 1; // we return fLockCount unchanged if we fail. | 122 fLockCount -= 1; // we return fLockCount unchanged if we fail. |
196 return false; | 123 return false; |
197 } | 124 } |
198 } | 125 } |
199 if (fRec.fPixels) { | 126 if (fRec.fPixels) { |
200 validate_pixels_ctable(fInfo, fRec.fColorTable); | 127 validate_pixels_ctable(fInfo, fRec.fColorTable); |
201 return true; | 128 return true; |
202 } | 129 } |
203 // no pixels, so we failed (somehow) | 130 // no pixels, so we failed (somehow) |
204 --fLockCount; | 131 --fLockCount; |
205 return false; | 132 return false; |
206 } | 133 } |
207 | 134 |
208 // For historical reasons, we always inc fLockCount, even if we return false. | 135 // For historical reasons, we always inc fLockCount, even if we return false. |
209 // It would be nice to change this (it seems), and only inc if we actually succe
ed... | 136 // It would be nice to change this (it seems), and only inc if we actually succe
ed... |
210 bool SkPixelRef::lockPixels() { | 137 bool SkPixelRef::lockPixels() { |
211 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); | 138 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); |
212 | 139 |
213 if (!fPreLocked) { | 140 if (!fPreLocked) { |
214 TRACE_EVENT_BEGIN0("skia", "SkPixelRef::lockPixelsMutex"); | 141 TRACE_EVENT_BEGIN0("skia", "SkPixelRef::lockPixelsMutex"); |
215 SkAutoMutexAcquire ac(*fMutex); | 142 SkAutoMutexAcquire ac(fMutex); |
216 TRACE_EVENT_END0("skia", "SkPixelRef::lockPixelsMutex"); | 143 TRACE_EVENT_END0("skia", "SkPixelRef::lockPixelsMutex"); |
217 SkDEBUGCODE(int oldCount = fLockCount;) | 144 SkDEBUGCODE(int oldCount = fLockCount;) |
218 bool success = this->lockPixelsInsideMutex(); | 145 bool success = this->lockPixelsInsideMutex(); |
219 // lockPixelsInsideMutex only increments the count if it succeeds. | 146 // lockPixelsInsideMutex only increments the count if it succeeds. |
220 SkASSERT(oldCount + (int)success == fLockCount); | 147 SkASSERT(oldCount + (int)success == fLockCount); |
221 | 148 |
222 if (!success) { | 149 if (!success) { |
223 // For compatibility with SkBitmap calling lockPixels, we still want
to increment | 150 // For compatibility with SkBitmap calling lockPixels, we still want
to increment |
224 // fLockCount even if we failed. If we updated SkBitmap we could rem
ove this oddity. | 151 // fLockCount even if we failed. If we updated SkBitmap we could rem
ove this oddity. |
225 fLockCount += 1; | 152 fLockCount += 1; |
(...skipping 12 matching lines...) Expand all Loading... |
238 *rec = fRec; | 165 *rec = fRec; |
239 return true; | 166 return true; |
240 } | 167 } |
241 return false; | 168 return false; |
242 } | 169 } |
243 | 170 |
244 void SkPixelRef::unlockPixels() { | 171 void SkPixelRef::unlockPixels() { |
245 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); | 172 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); |
246 | 173 |
247 if (!fPreLocked) { | 174 if (!fPreLocked) { |
248 SkAutoMutexAcquire ac(*fMutex); | 175 SkAutoMutexAcquire ac(fMutex); |
249 | 176 |
250 SkASSERT(fLockCount > 0); | 177 SkASSERT(fLockCount > 0); |
251 if (0 == --fLockCount) { | 178 if (0 == --fLockCount) { |
252 // don't call onUnlockPixels unless onLockPixels succeeded | 179 // don't call onUnlockPixels unless onLockPixels succeeded |
253 if (fRec.fPixels) { | 180 if (fRec.fPixels) { |
254 this->onUnlockPixels(); | 181 this->onUnlockPixels(); |
255 fRec.zero(); | 182 fRec.zero(); |
256 } else { | 183 } else { |
257 SkASSERT(fRec.isZero()); | 184 SkASSERT(fRec.isZero()); |
258 } | 185 } |
(...skipping 12 matching lines...) Expand all Loading... |
271 } | 198 } |
272 | 199 |
273 if (fPreLocked) { | 200 if (fPreLocked) { |
274 result->fUnlockProc = NULL; | 201 result->fUnlockProc = NULL; |
275 result->fUnlockContext = NULL; | 202 result->fUnlockContext = NULL; |
276 result->fCTable = fRec.fColorTable; | 203 result->fCTable = fRec.fColorTable; |
277 result->fPixels = fRec.fPixels; | 204 result->fPixels = fRec.fPixels; |
278 result->fRowBytes = fRec.fRowBytes; | 205 result->fRowBytes = fRec.fRowBytes; |
279 result->fSize.set(fInfo.width(), fInfo.height()); | 206 result->fSize.set(fInfo.width(), fInfo.height()); |
280 } else { | 207 } else { |
281 SkAutoMutexAcquire ac(*fMutex); | 208 SkAutoMutexAcquire ac(fMutex); |
282 if (!this->onRequestLock(request, result)) { | 209 if (!this->onRequestLock(request, result)) { |
283 return false; | 210 return false; |
284 } | 211 } |
285 } | 212 } |
286 if (result->fPixels) { | 213 if (result->fPixels) { |
287 validate_pixels_ctable(fInfo, result->fCTable); | 214 validate_pixels_ctable(fInfo, result->fCTable); |
288 return true; | 215 return true; |
289 } | 216 } |
290 return false; | 217 return false; |
291 } | 218 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 } | 344 } |
418 | 345 |
419 result->fUnlockProc = unlock_legacy_result; | 346 result->fUnlockProc = unlock_legacy_result; |
420 result->fUnlockContext = SkRef(this); // this is balanced in our fUnlockPr
oc | 347 result->fUnlockContext = SkRef(this); // this is balanced in our fUnlockPr
oc |
421 result->fCTable = fRec.fColorTable; | 348 result->fCTable = fRec.fColorTable; |
422 result->fPixels = fRec.fPixels; | 349 result->fPixels = fRec.fPixels; |
423 result->fRowBytes = fRec.fRowBytes; | 350 result->fRowBytes = fRec.fRowBytes; |
424 result->fSize.set(fInfo.width(), fInfo.height()); | 351 result->fSize.set(fInfo.width(), fInfo.height()); |
425 return true; | 352 return true; |
426 } | 353 } |
OLD | NEW |