SkPixelRef.cpp revision ed458688e284508f17a0408a093d89a8b5966e32
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        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
17        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
18        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
19        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
20
21        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
22        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
23        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
24        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
25
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        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
30
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        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
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
48static 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
61int32_t SkNextPixelRefGenerationID();
62
63int32_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
76void 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
86SkPixelRef::SkPixelRef(const SkImageInfo& info) : fInfo(info) {
87    SkAssertResult(SkColorTypeValidateAlphaType(fInfo.colorType(), fInfo.alphaType(),
88                                                const_cast<SkAlphaType*>(&fInfo.fAlphaType)));
89
90    this->setMutex(NULL);
91    fRec.zero();
92    fLockCount = 0;
93    this->needsNewGenID();
94    fIsImmutable = false;
95    fPreLocked = false;
96}
97
98
99SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) : fInfo(info) {
100    SkAssertResult(SkColorTypeValidateAlphaType(fInfo.colorType(), fInfo.alphaType(),
101                                                const_cast<SkAlphaType*>(&fInfo.fAlphaType)));
102
103    this->setMutex(mutex);
104    fRec.zero();
105    fLockCount = 0;
106    this->needsNewGenID();
107    fIsImmutable = false;
108    fPreLocked = false;
109}
110
111SkPixelRef::~SkPixelRef() {
112    this->callGenIDChangeListeners();
113}
114
115void SkPixelRef::needsNewGenID() {
116    fGenerationID = 0;
117    fUniqueGenerationID = false;
118}
119
120void SkPixelRef::cloneGenID(const SkPixelRef& that) {
121    // This is subtle.  We must call that.getGenerationID() to make sure its genID isn't 0.
122    this->fGenerationID = that.getGenerationID();
123    this->fUniqueGenerationID = false;
124    that.fUniqueGenerationID = false;
125}
126
127void SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) {
128#ifndef SK_IGNORE_PIXELREF_SETPRELOCKED
129    // only call me in your constructor, otherwise fLockCount tracking can get
130    // out of sync.
131    fRec.fPixels = pixels;
132    fRec.fColorTable = ctable;
133    fRec.fRowBytes = rowBytes;
134    fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
135    fPreLocked = true;
136#endif
137}
138
139bool SkPixelRef::lockPixels(LockRec* rec) {
140    SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
141
142    if (!fPreLocked) {
143        SkAutoMutexAcquire  ac(*fMutex);
144
145        if (1 == ++fLockCount) {
146            SkASSERT(fRec.isZero());
147
148            LockRec rec;
149            if (!this->onNewLockPixels(&rec)) {
150                return false;
151            }
152            SkASSERT(!rec.isZero());    // else why did onNewLock return true?
153            fRec = rec;
154        }
155    }
156    *rec = fRec;
157    return true;
158}
159
160bool SkPixelRef::lockPixels() {
161    LockRec rec;
162    return this->lockPixels(&rec);
163}
164
165void SkPixelRef::unlockPixels() {
166    SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
167
168    if (!fPreLocked) {
169        SkAutoMutexAcquire  ac(*fMutex);
170
171        SkASSERT(fLockCount > 0);
172        if (0 == --fLockCount) {
173            // don't call onUnlockPixels unless onLockPixels succeeded
174            if (fRec.fPixels) {
175                this->onUnlockPixels();
176                fRec.zero();
177            } else {
178                SkASSERT(fRec.isZero());
179            }
180        }
181    }
182}
183
184bool SkPixelRef::lockPixelsAreWritable() const {
185    return this->onLockPixelsAreWritable();
186}
187
188bool SkPixelRef::onLockPixelsAreWritable() const {
189    return true;
190}
191
192bool SkPixelRef::onImplementsDecodeInto() {
193    return false;
194}
195
196bool SkPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) {
197    return false;
198}
199
200uint32_t SkPixelRef::getGenerationID() const {
201    if (0 == fGenerationID) {
202        fGenerationID = SkNextPixelRefGenerationID();
203        fUniqueGenerationID = true;  // The only time we can be sure of this!
204    }
205    return fGenerationID;
206}
207
208void SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) {
209    if (NULL == listener || !fUniqueGenerationID) {
210        // No point in tracking this if we're not going to call it.
211        SkDELETE(listener);
212        return;
213    }
214    *fGenIDChangeListeners.append() = listener;
215}
216
217void SkPixelRef::callGenIDChangeListeners() {
218    // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID.
219    if (fUniqueGenerationID) {
220        for (int i = 0; i < fGenIDChangeListeners.count(); i++) {
221            fGenIDChangeListeners[i]->onChange();
222        }
223    }
224    // Listeners get at most one shot, so whether these triggered or not, blow them away.
225    fGenIDChangeListeners.deleteAll();
226}
227
228void SkPixelRef::notifyPixelsChanged() {
229#ifdef SK_DEBUG
230    if (fIsImmutable) {
231        SkDebugf("========== notifyPixelsChanged called on immutable pixelref");
232    }
233#endif
234    this->callGenIDChangeListeners();
235    this->needsNewGenID();
236}
237
238void SkPixelRef::changeAlphaType(SkAlphaType at) {
239    *const_cast<SkAlphaType*>(&fInfo.fAlphaType) = at;
240}
241
242void SkPixelRef::setImmutable() {
243    fIsImmutable = true;
244}
245
246bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
247    return this->onReadPixels(dst, subset);
248}
249
250bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
251    return false;
252}
253
254SkData* SkPixelRef::onRefEncodedData() {
255    return NULL;
256}
257
258size_t SkPixelRef::getAllocatedSizeInBytes() const {
259    return 0;
260}
261
262///////////////////////////////////////////////////////////////////////////////
263
264#ifdef SK_BUILD_FOR_ANDROID
265void SkPixelRef::globalRef(void* data) {
266    this->ref();
267}
268
269void SkPixelRef::globalUnref() {
270    this->unref();
271}
272#endif
273