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