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