SkPixelRef.cpp revision 4daa6f613cb7d8a3c07369af3e919ea65405ec55
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkPixelRef.h"
9#include "SkThread.h"
10
11#ifdef SK_BUILD_FOR_WIN32
12    // We don't have SK_BASE_MUTEX_INIT on Windows.
13
14    // must be a power-of-2. undef to just use 1 mutex
15    #define PIXELREF_MUTEX_RING_COUNT       32
16    static SkBaseMutex gPixelRefMutexRing[PIXELREF_MUTEX_RING_COUNT];
17
18#else
19    static SkBaseMutex gPixelRefMutexRing[] = {
20        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
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
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    // must be a power-of-2. undef to just use 1 mutex
41    #define PIXELREF_MUTEX_RING_COUNT SK_ARRAY_COUNT(gPixelRefMutexRing)
42
43#endif
44
45static SkBaseMutex* get_default_mutex() {
46    static int32_t gPixelRefMutexRingIndex;
47
48    SkASSERT(SkIsPow2(PIXELREF_MUTEX_RING_COUNT));
49
50    // atomic_inc might be overkill here. It may be fine if once in a while
51    // we hit a race-condition and two subsequent calls get the same index...
52    int index = sk_atomic_inc(&gPixelRefMutexRingIndex);
53    return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)];
54}
55
56///////////////////////////////////////////////////////////////////////////////
57
58int32_t SkNextPixelRefGenerationID();
59
60int32_t SkNextPixelRefGenerationID() {
61    static int32_t  gPixelRefGenerationID;
62    // do a loop in case our global wraps around, as we never want to
63    // return a 0
64    int32_t genID;
65    do {
66        genID = sk_atomic_inc(&gPixelRefGenerationID) + 1;
67    } while (0 == genID);
68    return genID;
69}
70
71///////////////////////////////////////////////////////////////////////////////
72
73void SkPixelRef::setMutex(SkBaseMutex* mutex) {
74    if (NULL == mutex) {
75        mutex = get_default_mutex();
76    }
77    fMutex = mutex;
78}
79
80// just need a > 0 value, so pick a funny one to aid in debugging
81#define SKPIXELREF_PRELOCKED_LOCKCOUNT     123456789
82
83static SkImageInfo validate_info(const SkImageInfo& info) {
84    SkAlphaType newAlphaType = info.alphaType();
85    SkAssertResult(SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAlphaType));
86    return info.makeAlphaType(newAlphaType);
87}
88
89SkPixelRef::SkPixelRef(const SkImageInfo& info)
90    : fInfo(validate_info(info))
91#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
92    , fStableID(SkNextPixelRefGenerationID())
93#endif
94
95{
96    this->setMutex(NULL);
97    fRec.zero();
98    fLockCount = 0;
99    this->needsNewGenID();
100    fIsImmutable = false;
101    fPreLocked = false;
102}
103
104
105SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex)
106    : fInfo(validate_info(info))
107#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
108    , fStableID(SkNextPixelRefGenerationID())
109#endif
110{
111    this->setMutex(mutex);
112    fRec.zero();
113    fLockCount = 0;
114    this->needsNewGenID();
115    fIsImmutable = false;
116    fPreLocked = false;
117}
118
119SkPixelRef::~SkPixelRef() {
120    this->callGenIDChangeListeners();
121}
122
123void SkPixelRef::needsNewGenID() {
124    fGenerationID = 0;
125    fUniqueGenerationID = false;
126}
127
128void SkPixelRef::cloneGenID(const SkPixelRef& that) {
129    // This is subtle.  We must call that.getGenerationID() to make sure its genID isn't 0.
130    this->fGenerationID = that.getGenerationID();
131    this->fUniqueGenerationID = false;
132    that.fUniqueGenerationID = false;
133}
134
135void SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) {
136#ifndef SK_IGNORE_PIXELREF_SETPRELOCKED
137    // only call me in your constructor, otherwise fLockCount tracking can get
138    // out of sync.
139    fRec.fPixels = pixels;
140    fRec.fColorTable = ctable;
141    fRec.fRowBytes = rowBytes;
142    fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
143    fPreLocked = true;
144#endif
145}
146
147bool SkPixelRef::lockPixels(LockRec* rec) {
148    SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
149
150    if (!fPreLocked) {
151        SkAutoMutexAcquire  ac(*fMutex);
152
153        if (1 == ++fLockCount) {
154            SkASSERT(fRec.isZero());
155
156            LockRec rec;
157            if (!this->onNewLockPixels(&rec)) {
158                return false;
159            }
160            SkASSERT(!rec.isZero());    // else why did onNewLock return true?
161            fRec = rec;
162        }
163    }
164    *rec = fRec;
165    return true;
166}
167
168bool SkPixelRef::lockPixels() {
169    LockRec rec;
170    return this->lockPixels(&rec);
171}
172
173void SkPixelRef::unlockPixels() {
174    SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
175
176    if (!fPreLocked) {
177        SkAutoMutexAcquire  ac(*fMutex);
178
179        SkASSERT(fLockCount > 0);
180        if (0 == --fLockCount) {
181            // don't call onUnlockPixels unless onLockPixels succeeded
182            if (fRec.fPixels) {
183                this->onUnlockPixels();
184                fRec.zero();
185            } else {
186                SkASSERT(fRec.isZero());
187            }
188        }
189    }
190}
191
192bool SkPixelRef::lockPixelsAreWritable() const {
193    return this->onLockPixelsAreWritable();
194}
195
196bool SkPixelRef::onLockPixelsAreWritable() const {
197    return true;
198}
199
200bool SkPixelRef::onImplementsDecodeInto() {
201    return false;
202}
203
204bool SkPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) {
205    return false;
206}
207
208uint32_t SkPixelRef::getGenerationID() const {
209    if (0 == fGenerationID) {
210        fGenerationID = SkNextPixelRefGenerationID();
211        fUniqueGenerationID = true;  // The only time we can be sure of this!
212    }
213    return fGenerationID;
214}
215
216void SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) {
217    if (NULL == listener || !fUniqueGenerationID) {
218        // No point in tracking this if we're not going to call it.
219        SkDELETE(listener);
220        return;
221    }
222    *fGenIDChangeListeners.append() = listener;
223}
224
225void SkPixelRef::callGenIDChangeListeners() {
226    // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID.
227    if (fUniqueGenerationID) {
228        for (int i = 0; i < fGenIDChangeListeners.count(); i++) {
229            fGenIDChangeListeners[i]->onChange();
230        }
231    }
232    // Listeners get at most one shot, so whether these triggered or not, blow them away.
233    fGenIDChangeListeners.deleteAll();
234}
235
236void SkPixelRef::notifyPixelsChanged() {
237#ifdef SK_DEBUG
238    if (fIsImmutable) {
239        SkDebugf("========== notifyPixelsChanged called on immutable pixelref");
240    }
241#endif
242    this->callGenIDChangeListeners();
243    this->needsNewGenID();
244}
245
246void SkPixelRef::changeAlphaType(SkAlphaType at) {
247    *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeAlphaType(at);
248}
249
250void SkPixelRef::setImmutable() {
251    fIsImmutable = true;
252}
253
254bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
255    return this->onReadPixels(dst, subset);
256}
257
258bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
259    return false;
260}
261
262SkData* SkPixelRef::onRefEncodedData() {
263    return NULL;
264}
265
266bool SkPixelRef::onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
267                                 SkYUVColorSpace* colorSpace) {
268    return false;
269}
270
271size_t SkPixelRef::getAllocatedSizeInBytes() const {
272    return 0;
273}
274
275///////////////////////////////////////////////////////////////////////////////
276
277#ifdef SK_BUILD_FOR_ANDROID
278void SkPixelRef::globalRef(void* data) {
279    this->ref();
280}
281
282void SkPixelRef::globalUnref() {
283    this->unref();
284}
285#endif
286