Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkPixelRef.cpp
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         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
17         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
18         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
19         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
20
21         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
22         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
23         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
24         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
25
26         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
27         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
28         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
29         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
30
31         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
32         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
33         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
34         { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
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
48 static 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
61 int32_t SkNextPixelRefGenerationID();
62
63 int32_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
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
84 #define SKPIXELREF_PRELOCKED_LOCKCOUNT     123456789
85
86 SkPixelRef::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
96 SkPixelRef::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
105 static SkImageInfo read_info(SkReadBuffer& buffer) {
106     SkImageInfo info;
107     info.unflatten(buffer);
108     return info;
109 }
110
111 SkPixelRef::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
124 SkPixelRef::~SkPixelRef() {
125     this->callGenIDChangeListeners();
126 }
127
128 void SkPixelRef::needsNewGenID() {
129     fGenerationID = 0;
130     fUniqueGenerationID = false;
131 }
132
133 void 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
140 void 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
152 void 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
169 bool 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
190 bool SkPixelRef::lockPixels() {
191     LockRec rec;
192     return this->lockPixels(&rec);
193 }
194
195 void 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
214 bool SkPixelRef::lockPixelsAreWritable() const {
215     return this->onLockPixelsAreWritable();
216 }
217
218 bool SkPixelRef::onLockPixelsAreWritable() const {
219     return true;
220 }
221
222 bool SkPixelRef::onImplementsDecodeInto() {
223     return false;
224 }
225
226 bool SkPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) {
227     return false;
228 }
229
230 uint32_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
238 void 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
247 void 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
258 void 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
268 void SkPixelRef::changeAlphaType(SkAlphaType at) {
269     *const_cast<SkAlphaType*>(&fInfo.fAlphaType) = at;
270 }
271
272 void SkPixelRef::setImmutable() {
273     fIsImmutable = true;
274 }
275
276 bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
277     return this->onReadPixels(dst, subset);
278 }
279
280 bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
281     return false;
282 }
283
284 SkData* SkPixelRef::onRefEncodedData() {
285     return NULL;
286 }
287
288 size_t SkPixelRef::getAllocatedSizeInBytes() const {
289     return 0;
290 }
291
292 ///////////////////////////////////////////////////////////////////////////////
293
294 #ifdef SK_BUILD_FOR_ANDROID
295 void SkPixelRef::globalRef(void* data) {
296     this->ref();
297 }
298
299 void SkPixelRef::globalUnref() {
300     this->unref();
301 }
302 #endif