aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkPixelRef.cpp
blob: e096d634b190b6917dcf2ca063d68fecf95b5fa8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "SkPixelRef.h"
#include "SkFlattenable.h"
#include "SkThread.h"

static SkMutex  gPixelRefMutex;
static int32_t  gPixelRefGenerationID;

SkPixelRef::SkPixelRef(SkMutex* mutex) {
    if (NULL == mutex) {
        mutex = &gPixelRefMutex;
    }
    fMutex = mutex;
    fPixels = NULL;
    fColorTable = NULL; // we do not track ownership of this
    fLockCount = 0;
    fGenerationID = 0;  // signal to rebuild
    fIsImmutable = false;
}

SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkMutex* mutex) {
    if (NULL == mutex) {
        mutex = &gPixelRefMutex;
    }
    fMutex = mutex;
    fPixels = NULL;
    fColorTable = NULL; // we do not track ownership of this
    fLockCount = 0;
    fGenerationID = 0;  // signal to rebuild
    fIsImmutable = buffer.readBool();
}

void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
    buffer.writeBool(fIsImmutable);
}

void SkPixelRef::lockPixels() {
    SkAutoMutexAcquire  ac(*fMutex);
    
    if (1 == ++fLockCount) {
        fPixels = this->onLockPixels(&fColorTable);
    }
}

void SkPixelRef::unlockPixels() {
    SkAutoMutexAcquire  ac(*fMutex);
    
    SkASSERT(fLockCount > 0);
    if (0 == --fLockCount) {
        this->onUnlockPixels();
        fPixels = NULL;
        fColorTable = NULL;
    }
}

uint32_t SkPixelRef::getGenerationID() const {
    uint32_t genID = fGenerationID;
    if (0 == genID) {
        // do a loop in case our global wraps around, as we never want to
        // return a 0
        do {
            genID = sk_atomic_inc(&gPixelRefGenerationID) + 1;
        } while (0 == genID);
        fGenerationID = genID;
    }
    return genID;
}

void SkPixelRef::notifyPixelsChanged() {
#ifdef SK_DEBUG
    if (fIsImmutable) {
        SkDebugf("========== notifyPixelsChanged called on immutable pixelref");
    }
#endif
    // this signals us to recompute this next time around
    fGenerationID = 0;
}

void SkPixelRef::setImmutable() {
    fIsImmutable = true;
}

///////////////////////////////////////////////////////////////////////////////

#define MAX_PAIR_COUNT  16

struct Pair {
    const char*          fName;
    SkPixelRef::Factory  fFactory;
};

static int gCount;
static Pair gPairs[MAX_PAIR_COUNT];

void SkPixelRef::Register(const char name[], Factory factory) {
    SkASSERT(name);
    SkASSERT(factory);
    
    static bool gOnce;
    if (!gOnce) {
        gCount = 0;
        gOnce = true;
    }
    
    SkASSERT(gCount < MAX_PAIR_COUNT);
    
    gPairs[gCount].fName = name;
    gPairs[gCount].fFactory = factory;
    gCount += 1;
}

SkPixelRef::Factory SkPixelRef::NameToFactory(const char name[]) {
    const Pair* pairs = gPairs;
    for (int i = gCount - 1; i >= 0; --i) {
        if (strcmp(pairs[i].fName, name) == 0) {
            return pairs[i].fFactory;
        }
    }
    return NULL;
}

const char* SkPixelRef::FactoryToName(Factory fact) {
    const Pair* pairs = gPairs;
    for (int i = gCount - 1; i >= 0; --i) {
        if (pairs[i].fFactory == fact) {
            return pairs[i].fName;
        }
    }
    return NULL;
}