SkPixelRef.cpp revision 50dfa0130b0705414df7ba7da9915139f6320b09
1#include "SkPixelRef.h"
2#include "SkFlattenable.h"
3#include "SkThread.h"
4
5static SkMutex  gPixelRefMutex;
6static int32_t  gPixelRefGenerationID;
7
8SkPixelRef::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
20SkPixelRef::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
32void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
33    buffer.writeBool(fIsImmutable);
34}
35
36void SkPixelRef::lockPixels() {
37    SkAutoMutexAcquire  ac(*fMutex);
38
39    if (1 == ++fLockCount) {
40        fPixels = this->onLockPixels(&fColorTable);
41    }
42}
43
44void 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
55uint32_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
68void SkPixelRef::notifyPixelsChanged() {
69#ifdef SK_DEBUG
70    if (fIsImmutable) {
71        SkDebugf("========== notifyPixelsChanged called on immutable pixelref");
72    }
73#endif
74    // this signals us to recompute this next time around
75    fGenerationID = 0;
76}
77
78void SkPixelRef::setImmutable() {
79    fIsImmutable = true;
80}
81
82bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
83    return this->onReadPixels(dst, subset);
84}
85
86bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
87    return false;
88}
89
90///////////////////////////////////////////////////////////////////////////////
91
92#define MAX_PAIR_COUNT  16
93
94struct Pair {
95    const char*          fName;
96    SkPixelRef::Factory  fFactory;
97};
98
99static int gCount;
100static Pair gPairs[MAX_PAIR_COUNT];
101
102void SkPixelRef::Register(const char name[], Factory factory) {
103    SkASSERT(name);
104    SkASSERT(factory);
105
106    static bool gOnce;
107    if (!gOnce) {
108        gCount = 0;
109        gOnce = true;
110    }
111
112    SkASSERT(gCount < MAX_PAIR_COUNT);
113
114    gPairs[gCount].fName = name;
115    gPairs[gCount].fFactory = factory;
116    gCount += 1;
117}
118
119SkPixelRef::Factory SkPixelRef::NameToFactory(const char name[]) {
120    const Pair* pairs = gPairs;
121    for (int i = gCount - 1; i >= 0; --i) {
122        if (strcmp(pairs[i].fName, name) == 0) {
123            return pairs[i].fFactory;
124        }
125    }
126    return NULL;
127}
128
129const char* SkPixelRef::FactoryToName(Factory fact) {
130    const Pair* pairs = gPairs;
131    for (int i = gCount - 1; i >= 0; --i) {
132        if (pairs[i].fFactory == fact) {
133            return pairs[i].fName;
134        }
135    }
136    return NULL;
137}
138
139///////////////////////////////////////////////////////////////////////////////
140
141#ifdef ANDROID
142void SkPixelRef::globalRef(void* data) {
143    this->ref();
144}
145
146void SkPixelRef::globalUnref() {
147    this->unref();
148}
149#endif
150