Home | History | Annotate | Download | only in core
      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 "SkFlattenable.h"
     10 #include "SkThread.h"
     11 
     12 // must be a power-of-2. undef to just use 1 mutex
     13 #define PIXELREF_MUTEX_RING_COUNT       32
     14 
     15 #ifdef PIXELREF_MUTEX_RING_COUNT
     16     static int32_t gPixelRefMutexRingIndex;
     17     static SK_DECLARE_MUTEX_ARRAY(gPixelRefMutexRing, PIXELREF_MUTEX_RING_COUNT);
     18 #else
     19     SK_DECLARE_STATIC_MUTEX(gPixelRefMutex);
     20 #endif
     21 
     22 SkBaseMutex* get_default_mutex() {
     23 #ifdef PIXELREF_MUTEX_RING_COUNT
     24     // atomic_inc might be overkill here. It may be fine if once in a while
     25     // we hit a race-condition and two subsequent calls get the same index...
     26     int index = sk_atomic_inc(&gPixelRefMutexRingIndex);
     27     return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)];
     28 #else
     29     return &gPixelRefMutex;
     30 #endif
     31 }
     32 
     33 ///////////////////////////////////////////////////////////////////////////////
     34 
     35 extern int32_t SkNextPixelRefGenerationID();
     36 int32_t SkNextPixelRefGenerationID() {
     37     static int32_t  gPixelRefGenerationID;
     38     // do a loop in case our global wraps around, as we never want to
     39     // return a 0
     40     int32_t genID;
     41     do {
     42         genID = sk_atomic_inc(&gPixelRefGenerationID) + 1;
     43     } while (0 == genID);
     44     return genID;
     45 }
     46 
     47 ///////////////////////////////////////////////////////////////////////////////
     48 
     49 void SkPixelRef::setMutex(SkBaseMutex* mutex) {
     50     if (NULL == mutex) {
     51         mutex = get_default_mutex();
     52     }
     53     fMutex = mutex;
     54 }
     55 
     56 // just need a > 0 value, so pick a funny one to aid in debugging
     57 #define SKPIXELREF_PRELOCKED_LOCKCOUNT     123456789
     58 
     59 SkPixelRef::SkPixelRef(SkBaseMutex* mutex) : fPreLocked(false) {
     60     this->setMutex(mutex);
     61     fPixels = NULL;
     62     fColorTable = NULL; // we do not track ownership of this
     63     fLockCount = 0;
     64     fGenerationID = 0;  // signal to rebuild
     65     fIsImmutable = false;
     66     fPreLocked = false;
     67 }
     68 
     69 SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex) {
     70     this->setMutex(mutex);
     71     fPixels = NULL;
     72     fColorTable = NULL; // we do not track ownership of this
     73     fLockCount = 0;
     74     fGenerationID = 0;  // signal to rebuild
     75     fIsImmutable = buffer.readBool();
     76     fPreLocked = false;
     77 }
     78 
     79 void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) {
     80     // only call me in your constructor, otherwise fLockCount tracking can get
     81     // out of sync.
     82     fPixels = pixels;
     83     fColorTable = ctable;
     84     fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
     85     fPreLocked = true;
     86 }
     87 
     88 void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
     89     buffer.writeBool(fIsImmutable);
     90 }
     91 
     92 void SkPixelRef::lockPixels() {
     93     SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
     94 
     95     if (!fPreLocked) {
     96         SkAutoMutexAcquire  ac(*fMutex);
     97 
     98         if (1 == ++fLockCount) {
     99             fPixels = this->onLockPixels(&fColorTable);
    100         }
    101     }
    102 }
    103 
    104 void SkPixelRef::unlockPixels() {
    105     SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
    106 
    107     if (!fPreLocked) {
    108         SkAutoMutexAcquire  ac(*fMutex);
    109 
    110         SkASSERT(fLockCount > 0);
    111         if (0 == --fLockCount) {
    112             this->onUnlockPixels();
    113             fPixels = NULL;
    114             fColorTable = NULL;
    115         }
    116     }
    117 }
    118 
    119 bool SkPixelRef::lockPixelsAreWritable() const {
    120     return this->onLockPixelsAreWritable();
    121 }
    122 
    123 bool SkPixelRef::onLockPixelsAreWritable() const {
    124     return true;
    125 }
    126 
    127 uint32_t SkPixelRef::getGenerationID() const {
    128     if (0 == fGenerationID) {
    129         fGenerationID = SkNextPixelRefGenerationID();
    130     }
    131     return fGenerationID;
    132 }
    133 
    134 void SkPixelRef::notifyPixelsChanged() {
    135 #ifdef SK_DEBUG
    136     if (fIsImmutable) {
    137         SkDebugf("========== notifyPixelsChanged called on immutable pixelref");
    138     }
    139 #endif
    140     // this signals us to recompute this next time around
    141     fGenerationID = 0;
    142 }
    143 
    144 void SkPixelRef::setImmutable() {
    145     fIsImmutable = true;
    146 }
    147 
    148 bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
    149     return this->onReadPixels(dst, subset);
    150 }
    151 
    152 bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
    153     return false;
    154 }
    155 
    156 ///////////////////////////////////////////////////////////////////////////////
    157 
    158 #define MAX_PAIR_COUNT  16
    159 
    160 struct Pair {
    161     const char*          fName;
    162     SkPixelRef::Factory  fFactory;
    163 };
    164 
    165 static int gCount;
    166 static Pair gPairs[MAX_PAIR_COUNT];
    167 
    168 void SkPixelRef::Register(const char name[], Factory factory) {
    169     SkASSERT(name);
    170     SkASSERT(factory);
    171 
    172     static bool gOnce;
    173     if (!gOnce) {
    174         gCount = 0;
    175         gOnce = true;
    176     }
    177 
    178     SkASSERT(gCount < MAX_PAIR_COUNT);
    179 
    180     gPairs[gCount].fName = name;
    181     gPairs[gCount].fFactory = factory;
    182     gCount += 1;
    183 }
    184 
    185 #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    186 static void report_no_entries(const char* functionName) {
    187     if (!gCount) {
    188         SkDebugf("%s has no registered name/factory pairs."
    189                  " Call SkGraphics::Init() at process initialization time.",
    190                  functionName);
    191     }
    192 }
    193 #endif
    194 
    195 SkPixelRef::Factory SkPixelRef::NameToFactory(const char name[]) {
    196 #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    197     report_no_entries(__FUNCTION__);
    198 #endif
    199     const Pair* pairs = gPairs;
    200     for (int i = gCount - 1; i >= 0; --i) {
    201         if (strcmp(pairs[i].fName, name) == 0) {
    202             return pairs[i].fFactory;
    203         }
    204     }
    205     return NULL;
    206 }
    207 
    208 const char* SkPixelRef::FactoryToName(Factory fact) {
    209 #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    210     report_no_entries(__FUNCTION__);
    211 #endif
    212     const Pair* pairs = gPairs;
    213     for (int i = gCount - 1; i >= 0; --i) {
    214         if (pairs[i].fFactory == fact) {
    215             return pairs[i].fName;
    216         }
    217     }
    218     return NULL;
    219 }
    220 
    221 ///////////////////////////////////////////////////////////////////////////////
    222 
    223 #ifdef SK_BUILD_FOR_ANDROID
    224 void SkPixelRef::globalRef(void* data) {
    225     this->ref();
    226 }
    227 
    228 void SkPixelRef::globalUnref() {
    229     this->unref();
    230 }
    231 #endif
    232