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