1 /*
2  * Copyright 2008 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkPixelRef_DEFINED
9 #define SkPixelRef_DEFINED
10 
11 #include "../private/SkAtomics.h"
12 #include "../private/SkMutex.h"
13 #include "../private/SkTDArray.h"
14 #include "SkBitmap.h"
15 #include "SkFilterQuality.h"
16 #include "SkImageInfo.h"
17 #include "SkPixmap.h"
18 #include "SkRefCnt.h"
19 #include "SkSize.h"
20 #include "SkString.h"
21 
22 class SkColorTable;
23 struct SkIRect;
24 
25 class GrTexture;
26 class SkDiscardableMemory;
27 
28 /** \class SkPixelRef
29 
30     This class is the smart container for pixel memory, and is used with
31     SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
32     access the actual pixel memory by calling lockPixels/unlockPixels.
33 
34     This class can be shared/accessed between multiple threads.
35 */
36 class SK_API SkPixelRef : public SkRefCnt {
37 public:
38     explicit SkPixelRef(const SkImageInfo&);
39     virtual ~SkPixelRef();
40 
info()41     const SkImageInfo& info() const {
42         return fInfo;
43     }
44 
45     /** Return the pixel memory returned from lockPixels, or null if the
46         lockCount is 0.
47     */
pixels()48     void* pixels() const { return fRec.fPixels; }
49 
50     /** Return the current colorTable (if any) if pixels are locked, or null.
51     */
colorTable()52     SkColorTable* colorTable() const { return fRec.fColorTable; }
53 
rowBytes()54     size_t rowBytes() const { return fRec.fRowBytes; }
55 
56     /**
57      *  To access the actual pixels of a pixelref, it must be "locked".
58      *  Calling lockPixels returns a LockRec struct (on success).
59      */
60     struct LockRec {
LockRecLockRec61         LockRec() : fPixels(NULL), fColorTable(NULL) {}
62 
63         void*           fPixels;
64         SkColorTable*   fColorTable;
65         size_t          fRowBytes;
66 
zeroLockRec67         void zero() { sk_bzero(this, sizeof(*this)); }
68 
isZeroLockRec69         bool isZero() const {
70             return NULL == fPixels && NULL == fColorTable && 0 == fRowBytes;
71         }
72     };
73 
74     SkDEBUGCODE(bool isLocked() const { return fLockCount > 0; })
75     SkDEBUGCODE(int getLockCount() const { return fLockCount; })
76 
77     /**
78      *  Call to access the pixel memory. Return true on success. Balance this
79      *  with a call to unlockPixels().
80      */
81     bool lockPixels();
82 
83     /**
84      *  Call to access the pixel memory. On success, return true and fill out
85      *  the specified rec. On failure, return false and ignore the rec parameter.
86      *  Balance this with a call to unlockPixels().
87      */
88     bool lockPixels(LockRec* rec);
89 
90     /** Call to balanace a previous call to lockPixels(). Returns the pixels
91         (or null) after the unlock. NOTE: lock calls can be nested, but the
92         matching number of unlock calls must be made in order to free the
93         memory (if the subclass implements caching/deferred-decoding.)
94     */
95     void unlockPixels();
96 
97     /**
98      *  Some bitmaps can return a copy of their pixels for lockPixels(), but
99      *  that copy, if modified, will not be pushed back. These bitmaps should
100      *  not be used as targets for a raster device/canvas (since all pixels
101      *  modifications will be lost when unlockPixels() is called.)
102      */
103     bool lockPixelsAreWritable() const;
104 
105     /** Returns a non-zero, unique value corresponding to the pixels in this
106         pixelref. Each time the pixels are changed (and notifyPixelsChanged is
107         called), a different generation ID will be returned.
108     */
109     uint32_t getGenerationID() const;
110 
111 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
112     /** Returns a non-zero, unique value corresponding to this SkPixelRef.
113         Unlike the generation ID, this ID remains the same even when the pixels
114         are changed. IDs are not reused (until uint32_t wraps), so it is safe
115         to consider this ID unique even after this SkPixelRef is deleted.
116 
117         Can be used as a key which uniquely identifies this SkPixelRef
118         regardless of changes to its pixels or deletion of this object.
119      */
getStableID()120     uint32_t getStableID() const { return fStableID; }
121 #endif
122 
123     /**
124      *  Call this if you have changed the contents of the pixels. This will in-
125      *  turn cause a different generation ID value to be returned from
126      *  getGenerationID().
127      */
128     void notifyPixelsChanged();
129 
130     /**
131      *  Change the info's AlphaType. Note that this does not automatically
132      *  invalidate the generation ID. If the pixel values themselves have
133      *  changed, then you must explicitly call notifyPixelsChanged() as well.
134      */
135     void changeAlphaType(SkAlphaType at);
136 
137     /** Returns true if this pixelref is marked as immutable, meaning that the
138         contents of its pixels will not change for the lifetime of the pixelref.
139     */
isImmutable()140     bool isImmutable() const { return fMutability != kMutable; }
141 
142     /** Marks this pixelref is immutable, meaning that the contents of its
143         pixels will not change for the lifetime of the pixelref. This state can
144         be set on a pixelref, but it cannot be cleared once it is set.
145     */
146     void setImmutable();
147 
148     /** Return the optional URI string associated with this pixelref. May be
149         null.
150     */
getURI()151     const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
152 
153     /** Copy a URI string to this pixelref, or clear the URI if the uri is null
154      */
setURI(const char uri[])155     void setURI(const char uri[]) {
156         fURI.set(uri);
157     }
158 
159     /** Copy a URI string to this pixelref
160      */
setURI(const char uri[],size_t len)161     void setURI(const char uri[], size_t len) {
162         fURI.set(uri, len);
163     }
164 
165     /** Assign a URI string to this pixelref.
166     */
setURI(const SkString & uri)167     void setURI(const SkString& uri) { fURI = uri; }
168 
169     struct LockRequest {
170         SkISize         fSize;
171         SkFilterQuality fQuality;
172     };
173 
174     struct LockResult {
LockResultLockResult175         LockResult() : fPixels(NULL), fCTable(NULL) {}
176 
177         void        (*fUnlockProc)(void* ctx);
178         void*       fUnlockContext;
179 
180         const void* fPixels;
181         SkColorTable* fCTable;  // should be NULL unless colortype is kIndex8
182         size_t      fRowBytes;
183         SkISize     fSize;
184 
unlockLockResult185         void unlock() {
186             if (fUnlockProc) {
187                 fUnlockProc(fUnlockContext);
188                 fUnlockProc = NULL; // can't unlock twice!
189             }
190         }
191     };
192 
193     bool requestLock(const LockRequest&, LockResult*);
194 
195     // Register a listener that may be called the next time our generation ID changes.
196     //
197     // We'll only call the listener if we're confident that we are the only SkPixelRef with this
198     // generation ID.  If our generation ID changes and we decide not to call the listener, we'll
199     // never call it: you must add a new listener for each generation ID change.  We also won't call
200     // the listener when we're certain no one knows what our generation ID is.
201     //
202     // This can be used to invalidate caches keyed by SkPixelRef generation ID.
203     struct GenIDChangeListener {
~GenIDChangeListenerGenIDChangeListener204         virtual ~GenIDChangeListener() {}
205         virtual void onChange() = 0;
206     };
207 
208     // Takes ownership of listener.
209     void addGenIDChangeListener(GenIDChangeListener* listener);
210 
211     // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache
212     // to know automatically those entries can be purged when this pixelref is changed or deleted.
notifyAddedToCache()213     void notifyAddedToCache() {
214         fAddedToCache.store(true);
215     }
216 
diagnostic_only_getDiscardable()217     virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return NULL; }
218 
219     /**
220      *  Returns true if the pixels are generated on-the-fly (when required).
221      */
isLazyGenerated()222     bool isLazyGenerated() const { return this->onIsLazyGenerated(); }
223 
224 protected:
225     /**
226      *  On success, returns true and fills out the LockRec for the pixels. On
227      *  failure returns false and ignores the LockRec parameter.
228      *
229      *  The caller will have already acquired a mutex for thread safety, so this
230      *  method need not do that.
231      */
232     virtual bool onNewLockPixels(LockRec*) = 0;
233 
234     /**
235      *  Balancing the previous successful call to onNewLockPixels. The locked
236      *  pixel address will no longer be referenced, so the subclass is free to
237      *  move or discard that memory.
238      *
239      *  The caller will have already acquired a mutex for thread safety, so this
240      *  method need not do that.
241      */
242     virtual void onUnlockPixels() = 0;
243 
244     /** Default impl returns true */
245     virtual bool onLockPixelsAreWritable() const;
246 
247     // default impl does nothing.
248     virtual void onNotifyPixelsChanged();
249 
250     /**
251      *  Returns the size (in bytes) of the internally allocated memory.
252      *  This should be implemented in all serializable SkPixelRef derived classes.
253      *  SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value,
254      *  otherwise the rendering code may attempt to read memory out of bounds.
255      *
256      *  @return default impl returns 0.
257      */
258     virtual size_t getAllocatedSizeInBytes() const;
259 
260     virtual bool onRequestLock(const LockRequest&, LockResult*);
261 
onIsLazyGenerated()262     virtual bool onIsLazyGenerated() const { return false; }
263 
264     /** Return the mutex associated with this pixelref. This value is assigned
265         in the constructor, and cannot change during the lifetime of the object.
266     */
mutex()267     SkBaseMutex* mutex() const { return &fMutex; }
268 
269     // only call from constructor. Flags this to always be locked, removing
270     // the need to grab the mutex and call onLockPixels/onUnlockPixels.
271     // Performance tweak to avoid those calls (esp. in multi-thread use case).
272     void setPreLocked(void*, size_t rowBytes, SkColorTable*);
273 
274 private:
275     mutable SkMutex fMutex;
276 
277     // mostly const. fInfo.fAlpahType can be changed at runtime.
278     const SkImageInfo fInfo;
279 
280     // LockRec is only valid if we're in a locked state (isLocked())
281     LockRec         fRec;
282     int             fLockCount;
283 
284     bool lockPixelsInsideMutex();
285 
286     // Bottom bit indicates the Gen ID is unique.
genIDIsUnique()287     bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }
288     mutable SkAtomic<uint32_t> fTaggedGenID;
289 
290 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
291     const uint32_t fStableID;
292 #endif
293 
294     SkTDArray<GenIDChangeListener*> fGenIDChangeListeners;  // pointers are owned
295 
296     SkString    fURI;
297 
298     // Set true by caches when they cache content that's derived from the current pixels.
299     SkAtomic<bool> fAddedToCache;
300 
301     enum {
302         kMutable,               // PixelRefs begin mutable.
303         kTemporarilyImmutable,  // Considered immutable, but can revert to mutable.
304         kImmutable,             // Once set to this state, it never leaves.
305     } fMutability : 8;          // easily fits inside a byte
306 
307     // only ever set in constructor, const after that
308     bool fPreLocked;
309 
310     void needsNewGenID();
311     void callGenIDChangeListeners();
312 
313     void setTemporarilyImmutable();
314     void restoreMutability();
315     friend class SkSurface_Raster;   // For the two methods above.
316 
isPreLocked()317     bool isPreLocked() const { return fPreLocked; }
318     friend class SkImage_Raster;
319     friend class SkSpecialImage_Raster;
320 
321     // When copying a bitmap to another with the same shape and config, we can safely
322     // clone the pixelref generation ID too, which makes them equivalent under caching.
323     friend class SkBitmap;  // only for cloneGenID
324     void cloneGenID(const SkPixelRef&);
325 
326     void setImmutableWithID(uint32_t genID);
327     friend class SkImage_Gpu;
328     friend class SkImageCacherator;
329     friend class SkSpecialImage_Gpu;
330 
331     typedef SkRefCnt INHERITED;
332 };
333 
334 class SkPixelRefFactory : public SkRefCnt {
335 public:
336     /**
337      *  Allocate a new pixelref matching the specified ImageInfo, allocating
338      *  the memory for the pixels. If the ImageInfo requires a ColorTable,
339      *  the pixelref will ref() the colortable.
340      *  On failure return NULL.
341      */
342     virtual SkPixelRef* create(const SkImageInfo&, size_t rowBytes, SkColorTable*) = 0;
343 };
344 
345 #endif
346