• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_default_mutex()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();
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 
setMutex(SkBaseMutex * mutex)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 
SkPixelRef(SkBaseMutex * mutex)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 
SkPixelRef(SkFlattenableReadBuffer & buffer,SkBaseMutex * mutex)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 
setPreLocked(void * pixels,SkColorTable * ctable)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 
flatten(SkFlattenableWriteBuffer & buffer) const88 void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
89     buffer.writeBool(fIsImmutable);
90 }
91 
lockPixels()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 
unlockPixels()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 
lockPixelsAreWritable() const119 bool SkPixelRef::lockPixelsAreWritable() const {
120     return this->onLockPixelsAreWritable();
121 }
122 
onLockPixelsAreWritable() const123 bool SkPixelRef::onLockPixelsAreWritable() const {
124     return true;
125 }
126 
getGenerationID() const127 uint32_t SkPixelRef::getGenerationID() const {
128     if (0 == fGenerationID) {
129         fGenerationID = SkNextPixelRefGenerationID();
130     }
131     return fGenerationID;
132 }
133 
notifyPixelsChanged()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 
setImmutable()144 void SkPixelRef::setImmutable() {
145     fIsImmutable = true;
146 }
147 
readPixels(SkBitmap * dst,const SkIRect * subset)148 bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
149     return this->onReadPixels(dst, subset);
150 }
151 
onReadPixels(SkBitmap * dst,const SkIRect * subset)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 
Register(const char name[],Factory factory)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)
report_no_entries(const char * functionName)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 
NameToFactory(const char name[])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 
FactoryToName(Factory fact)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
globalRef(void * data)224 void SkPixelRef::globalRef(void* data) {
225     this->ref();
226 }
227 
globalUnref()228 void SkPixelRef::globalUnref() {
229     this->unref();
230 }
231 #endif
232