SkPixelRef.cpp revision 9c49bc3e643c435677727c1c0904c4a7cb7a6907
1#include "SkPixelRef.h"
2#include "SkFlattenable.h"
3#include "SkThread.h"
4
5static SkMutex  gPixelRefMutex;
6
7extern int32_t SkNextPixelRefGenerationID();
8int32_t SkNextPixelRefGenerationID() {
9    static int32_t  gPixelRefGenerationID;
10    // do a loop in case our global wraps around, as we never want to
11    // return a 0
12    int32_t genID;
13    do {
14        genID = sk_atomic_inc(&gPixelRefGenerationID) + 1;
15    } while (0 == genID);
16    return genID;
17}
18
19
20SkPixelRef::SkPixelRef(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 = false;
30}
31
32SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkMutex* mutex) {
33    if (NULL == mutex) {
34        mutex = &gPixelRefMutex;
35    }
36    fMutex = mutex;
37    fPixels = NULL;
38    fColorTable = NULL; // we do not track ownership of this
39    fLockCount = 0;
40    fGenerationID = 0;  // signal to rebuild
41    fIsImmutable = buffer.readBool();
42}
43
44void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
45    buffer.writeBool(fIsImmutable);
46}
47
48void SkPixelRef::lockPixels() {
49    SkAutoMutexAcquire  ac(*fMutex);
50
51    if (1 == ++fLockCount) {
52        fPixels = this->onLockPixels(&fColorTable);
53    }
54}
55
56void SkPixelRef::unlockPixels() {
57    SkAutoMutexAcquire  ac(*fMutex);
58
59    SkASSERT(fLockCount > 0);
60    if (0 == --fLockCount) {
61        this->onUnlockPixels();
62        fPixels = NULL;
63        fColorTable = NULL;
64    }
65}
66
67bool SkPixelRef::lockPixelsAreWritable() const {
68    return this->onLockPixelsAreWritable();
69}
70
71bool SkPixelRef::onLockPixelsAreWritable() const {
72    return true;
73}
74
75uint32_t SkPixelRef::getGenerationID() const {
76    if (0 == fGenerationID) {
77        fGenerationID = SkNextPixelRefGenerationID();
78    }
79    return fGenerationID;
80}
81
82void SkPixelRef::notifyPixelsChanged() {
83#ifdef SK_DEBUG
84    if (fIsImmutable) {
85        SkDebugf("========== notifyPixelsChanged called on immutable pixelref");
86    }
87#endif
88    // this signals us to recompute this next time around
89    fGenerationID = 0;
90}
91
92void SkPixelRef::setImmutable() {
93    fIsImmutable = true;
94}
95
96bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
97    return this->onReadPixels(dst, subset);
98}
99
100bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
101    return false;
102}
103
104///////////////////////////////////////////////////////////////////////////////
105
106#define MAX_PAIR_COUNT  16
107
108struct Pair {
109    const char*          fName;
110    SkPixelRef::Factory  fFactory;
111};
112
113static int gCount;
114static Pair gPairs[MAX_PAIR_COUNT];
115
116void SkPixelRef::Register(const char name[], Factory factory) {
117    SkASSERT(name);
118    SkASSERT(factory);
119
120    static bool gOnce;
121    if (!gOnce) {
122        gCount = 0;
123        gOnce = true;
124    }
125
126    SkASSERT(gCount < MAX_PAIR_COUNT);
127
128    gPairs[gCount].fName = name;
129    gPairs[gCount].fFactory = factory;
130    gCount += 1;
131}
132
133SkPixelRef::Factory SkPixelRef::NameToFactory(const char name[]) {
134    const Pair* pairs = gPairs;
135    for (int i = gCount - 1; i >= 0; --i) {
136        if (strcmp(pairs[i].fName, name) == 0) {
137            return pairs[i].fFactory;
138        }
139    }
140    return NULL;
141}
142
143const char* SkPixelRef::FactoryToName(Factory fact) {
144    const Pair* pairs = gPairs;
145    for (int i = gCount - 1; i >= 0; --i) {
146        if (pairs[i].fFactory == fact) {
147            return pairs[i].fName;
148        }
149    }
150    return NULL;
151}
152
153///////////////////////////////////////////////////////////////////////////////
154
155#ifdef ANDROID
156void SkPixelRef::globalRef(void* data) {
157    this->ref();
158}
159
160void SkPixelRef::globalUnref() {
161    this->unref();
162}
163#endif
164