reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame^] | 1 | #include "SkPixelRef.h" |
| 2 | #include "SkFlattenable.h" |
| 3 | #include "SkThread.h" |
| 4 | |
| 5 | static SkMutex gPixelRefMutex; |
| 6 | static int32_t gPixelRefGenerationID; |
| 7 | |
| 8 | SkPixelRef::SkPixelRef(SkMutex* mutex) { |
| 9 | if (NULL == mutex) { |
| 10 | mutex = &gPixelRefMutex; |
| 11 | } |
| 12 | fMutex = mutex; |
| 13 | fPixels = NULL; |
| 14 | fColorTable = NULL; // we do not track ownership of this |
| 15 | fLockCount = 0; |
| 16 | fGenerationID = 0; // signal to rebuild |
| 17 | fIsImmutable = false; |
| 18 | } |
| 19 | |
| 20 | SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkMutex* mutex) { |
| 21 | if (NULL == mutex) { |
| 22 | mutex = &gPixelRefMutex; |
| 23 | } |
| 24 | fMutex = mutex; |
| 25 | fPixels = NULL; |
| 26 | fColorTable = NULL; // we do not track ownership of this |
| 27 | fLockCount = 0; |
| 28 | fGenerationID = 0; // signal to rebuild |
| 29 | fIsImmutable = buffer.readBool(); |
| 30 | } |
| 31 | |
| 32 | void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { |
| 33 | buffer.writeBool(fIsImmutable); |
| 34 | } |
| 35 | |
| 36 | void SkPixelRef::lockPixels() { |
| 37 | SkAutoMutexAcquire ac(*fMutex); |
| 38 | |
| 39 | if (1 == ++fLockCount) { |
| 40 | fPixels = this->onLockPixels(&fColorTable); |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | void SkPixelRef::unlockPixels() { |
| 45 | SkAutoMutexAcquire ac(*fMutex); |
| 46 | |
| 47 | SkASSERT(fLockCount > 0); |
| 48 | if (0 == --fLockCount) { |
| 49 | this->onUnlockPixels(); |
| 50 | fPixels = NULL; |
| 51 | fColorTable = NULL; |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | uint32_t SkPixelRef::getGenerationID() const { |
| 56 | uint32_t genID = fGenerationID; |
| 57 | if (0 == genID) { |
| 58 | // do a loop in case our global wraps around, as we never want to |
| 59 | // return a 0 |
| 60 | do { |
| 61 | genID = sk_atomic_inc(&gPixelRefGenerationID) + 1; |
| 62 | } while (0 == genID); |
| 63 | fGenerationID = genID; |
| 64 | } |
| 65 | return genID; |
| 66 | } |
| 67 | |
| 68 | void SkPixelRef::notifyPixelsChanged() { |
| 69 | if (fIsImmutable) { |
| 70 | SkDebugf("========== notifyPixelsChanged called on immutable pixelref"); |
| 71 | sk_throw(); |
| 72 | } |
| 73 | // this signals us to recompute this next time around |
| 74 | fGenerationID = 0; |
| 75 | } |
| 76 | |
| 77 | void SkPixelRef::setImmutable() { |
| 78 | fIsImmutable = true; |
| 79 | } |
| 80 | |
| 81 | /////////////////////////////////////////////////////////////////////////////// |
| 82 | |
| 83 | #define MAX_PAIR_COUNT 16 |
| 84 | |
| 85 | struct Pair { |
| 86 | const char* fName; |
| 87 | SkPixelRef::Factory fFactory; |
| 88 | }; |
| 89 | |
| 90 | static int gCount; |
| 91 | static Pair gPairs[MAX_PAIR_COUNT]; |
| 92 | |
| 93 | void SkPixelRef::Register(const char name[], Factory factory) { |
| 94 | SkASSERT(name); |
| 95 | SkASSERT(factory); |
| 96 | |
| 97 | static bool gOnce; |
| 98 | if (!gOnce) { |
| 99 | gCount = 0; |
| 100 | gOnce = true; |
| 101 | } |
| 102 | |
| 103 | SkASSERT(gCount < MAX_PAIR_COUNT); |
| 104 | |
| 105 | gPairs[gCount].fName = name; |
| 106 | gPairs[gCount].fFactory = factory; |
| 107 | gCount += 1; |
| 108 | } |
| 109 | |
| 110 | SkPixelRef::Factory SkPixelRef::NameToFactory(const char name[]) { |
| 111 | const Pair* pairs = gPairs; |
| 112 | for (int i = gCount - 1; i >= 0; --i) { |
| 113 | if (strcmp(pairs[i].fName, name) == 0) { |
| 114 | return pairs[i].fFactory; |
| 115 | } |
| 116 | } |
| 117 | return NULL; |
| 118 | } |
| 119 | |
| 120 | const char* SkPixelRef::FactoryToName(Factory fact) { |
| 121 | const Pair* pairs = gPairs; |
| 122 | for (int i = gCount - 1; i >= 0; --i) { |
| 123 | if (pairs[i].fFactory == fact) { |
| 124 | return pairs[i].fName; |
| 125 | } |
| 126 | } |
| 127 | return NULL; |
| 128 | } |
| 129 | |