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 class SkData;
24 struct SkIRect;
25 
26 class GrTexture;
27 class SkDiscardableMemory;
28 
29 /** \class SkPixelRef
30 
31     This class is the smart container for pixel memory, and is used with
32     SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
33     access the actual pixel memory by calling lockPixels/unlockPixels.
34 
35     This class can be shared/accessed between multiple threads.
36 */
37 class SK_API SkPixelRef : public SkRefCnt {
38 public:
39     explicit SkPixelRef(const SkImageInfo&);
40     virtual ~SkPixelRef();
41 
info()42     const SkImageInfo& info() const {
43         return fInfo;
44     }
45 
46     /** Return the pixel memory returned from lockPixels, or null if the
47         lockCount is 0.
48     */
pixels()49     void* pixels() const { return fRec.fPixels; }
50 
51     /** Return the current colorTable (if any) if pixels are locked, or null.
52     */
colorTable()53     SkColorTable* colorTable() const { return fRec.fColorTable; }
54 
rowBytes()55     size_t rowBytes() const { return fRec.fRowBytes; }
56 
57     /**
58      *  To access the actual pixels of a pixelref, it must be "locked".
59      *  Calling lockPixels returns a LockRec struct (on success).
60      */
61     struct LockRec {
LockRecLockRec62         LockRec() : fPixels(NULL), fColorTable(NULL) {}
63 
64         void*           fPixels;
65         SkColorTable*   fColorTable;
66         size_t          fRowBytes;
67 
zeroLockRec68         void zero() { sk_bzero(this, sizeof(*this)); }
69 
isZeroLockRec70         bool isZero() const {
71             return NULL == fPixels && NULL == fColorTable && 0 == fRowBytes;
72         }
73     };
74 
75     SkDEBUGCODE(bool isLocked() const { return fLockCount > 0; })
76     SkDEBUGCODE(int getLockCount() const { return fLockCount; })
77 
78     /**
79      *  Call to access the pixel memory. Return true on success. Balance this
80      *  with a call to unlockPixels().
81      */
82     bool lockPixels();
83 
84     /**
85      *  Call to access the pixel memory. On success, return true and fill out
86      *  the specified rec. On failure, return false and ignore the rec parameter.
87      *  Balance this with a call to unlockPixels().
88      */
89     bool lockPixels(LockRec* rec);
90 
91     /** Call to balanace a previous call to lockPixels(). Returns the pixels
92         (or null) after the unlock. NOTE: lock calls can be nested, but the
93         matching number of unlock calls must be made in order to free the
94         memory (if the subclass implements caching/deferred-decoding.)
95     */
96     void unlockPixels();
97 
98     /**
99      *  Some bitmaps can return a copy of their pixels for lockPixels(), but
100      *  that copy, if modified, will not be pushed back. These bitmaps should
101      *  not be used as targets for a raster device/canvas (since all pixels
102      *  modifications will be lost when unlockPixels() is called.)
103      */
104     bool lockPixelsAreWritable() const;
105 
106     /** Returns a non-zero, unique value corresponding to the pixels in this
107         pixelref. Each time the pixels are changed (and notifyPixelsChanged is
108         called), a different generation ID will be returned.
109     */
110     uint32_t getGenerationID() const;
111 
112 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
113     /** Returns a non-zero, unique value corresponding to this SkPixelRef.
114         Unlike the generation ID, this ID remains the same even when the pixels
115         are changed. IDs are not reused (until uint32_t wraps), so it is safe
116         to consider this ID unique even after this SkPixelRef is deleted.
117 
118         Can be used as a key which uniquely identifies this SkPixelRef
119         regardless of changes to its pixels or deletion of this object.
120      */
getStableID()121     uint32_t getStableID() const { return fStableID; }
122 #endif
123 
124     /**
125      *  Call this if you have changed the contents of the pixels. This will in-
126      *  turn cause a different generation ID value to be returned from
127      *  getGenerationID().
128      */
129     void notifyPixelsChanged();
130 
131     /**
132      *  Change the info's AlphaType. Note that this does not automatically
133      *  invalidate the generation ID. If the pixel values themselves have
134      *  changed, then you must explicitly call notifyPixelsChanged() as well.
135      */
136     void changeAlphaType(SkAlphaType at);
137 
138     /** Returns true if this pixelref is marked as immutable, meaning that the
139         contents of its pixels will not change for the lifetime of the pixelref.
140     */
isImmutable()141     bool isImmutable() const { return fMutability != kMutable; }
142 
143     /** Marks this pixelref is immutable, meaning that the contents of its
144         pixels will not change for the lifetime of the pixelref. This state can
145         be set on a pixelref, but it cannot be cleared once it is set.
146     */
147     void setImmutable();
148 
149     /** Return the optional URI string associated with this pixelref. May be
150         null.
151     */
getURI()152     const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
153 
154     /** Copy a URI string to this pixelref, or clear the URI if the uri is null
155      */
setURI(const char uri[])156     void setURI(const char uri[]) {
157         fURI.set(uri);
158     }
159 
160     /** Copy a URI string to this pixelref
161      */
setURI(const char uri[],size_t len)162     void setURI(const char uri[], size_t len) {
163         fURI.set(uri, len);
164     }
165 
166     /** Assign a URI string to this pixelref.
167     */
setURI(const SkString & uri)168     void setURI(const SkString& uri) { fURI = uri; }
169 
170     /**
171      *  If the pixelRef has an encoded (i.e. compressed) representation,
172      *  return a ref to its data. If the pixelRef
173      *  is uncompressed or otherwise does not have this form, return NULL.
174      *
175      *  If non-null is returned, the caller is responsible for calling unref()
176      *  on the data when it is finished.
177      */
refEncodedData()178     SkData* refEncodedData() {
179         return this->onRefEncodedData();
180     }
181 
182     struct LockRequest {
183         SkISize         fSize;
184         SkFilterQuality fQuality;
185     };
186 
187     struct LockResult {
LockResultLockResult188         LockResult() : fPixels(NULL), fCTable(NULL) {}
189 
190         void        (*fUnlockProc)(void* ctx);
191         void*       fUnlockContext;
192 
193         const void* fPixels;
194         SkColorTable* fCTable;  // should be NULL unless colortype is kIndex8
195         size_t      fRowBytes;
196         SkISize     fSize;
197 
unlockLockResult198         void unlock() {
199             if (fUnlockProc) {
200                 fUnlockProc(fUnlockContext);
201                 fUnlockProc = NULL; // can't unlock twice!
202             }
203         }
204     };
205 
206     bool requestLock(const LockRequest&, LockResult*);
207 
208     /** Are we really wrapping a texture instead of a bitmap?
209      */
getTexture()210     virtual GrTexture* getTexture() { return NULL; }
211 
212     /**
213      *  If any planes or rowBytes is NULL, this should output the sizes and return true
214      *  if it can efficiently return YUV planar data. If it cannot, it should return false.
215      *
216      *  If all planes and rowBytes are not NULL, then it should copy the associated Y,U,V data
217      *  into those planes of memory supplied by the caller. It should validate that the sizes
218      *  match what it expected. If the sizes do not match, it should return false.
219      *
220      *  If colorSpace is not NULL, the YUV color space of the data should be stored in the address
221      *  it points at.
222      */
getYUV8Planes(SkISize sizes[3],void * planes[3],size_t rowBytes[3],SkYUVColorSpace * colorSpace)223     bool getYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
224                        SkYUVColorSpace* colorSpace) {
225         return this->onGetYUV8Planes(sizes, planes, rowBytes, colorSpace);
226     }
227 
228     /** Populates dst with the pixels of this pixelRef, converting them to colorType. */
229     bool readPixels(SkBitmap* dst, SkColorType colorType, const SkIRect* subset = NULL);
230 
231     /**
232      *  Makes a deep copy of this PixelRef, respecting the requested config.
233      *  @param colorType Desired colortype.
234      *  @param profileType Desired colorprofiletype.
235      *  @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
236      *         of this PixelRef.
237      *  @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
238      *          not be created with the given config), or this PixelRef does not support deep
239      *          copies.
240      */
deepCopy(SkColorType,SkColorProfileType,const SkIRect *)241     virtual SkPixelRef* deepCopy(SkColorType, SkColorProfileType, const SkIRect* /*subset*/) {
242         return NULL;
243     }
244 
245     // Register a listener that may be called the next time our generation ID changes.
246     //
247     // We'll only call the listener if we're confident that we are the only SkPixelRef with this
248     // generation ID.  If our generation ID changes and we decide not to call the listener, we'll
249     // never call it: you must add a new listener for each generation ID change.  We also won't call
250     // the listener when we're certain no one knows what our generation ID is.
251     //
252     // This can be used to invalidate caches keyed by SkPixelRef generation ID.
253     struct GenIDChangeListener {
~GenIDChangeListenerGenIDChangeListener254         virtual ~GenIDChangeListener() {}
255         virtual void onChange() = 0;
256     };
257 
258     // Takes ownership of listener.
259     void addGenIDChangeListener(GenIDChangeListener* listener);
260 
261     // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache
262     // to know automatically those entries can be purged when this pixelref is changed or deleted.
notifyAddedToCache()263     void notifyAddedToCache() {
264         fAddedToCache.store(true);
265     }
266 
diagnostic_only_getDiscardable()267     virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return NULL; }
268 
269     /**
270      *  Returns true if the pixels are generated on-the-fly (when required).
271      */
isLazyGenerated()272     bool isLazyGenerated() const { return this->onIsLazyGenerated(); }
273 
274 protected:
275     /**
276      *  On success, returns true and fills out the LockRec for the pixels. On
277      *  failure returns false and ignores the LockRec parameter.
278      *
279      *  The caller will have already acquired a mutex for thread safety, so this
280      *  method need not do that.
281      */
282     virtual bool onNewLockPixels(LockRec*) = 0;
283 
284     /**
285      *  Balancing the previous successful call to onNewLockPixels. The locked
286      *  pixel address will no longer be referenced, so the subclass is free to
287      *  move or discard that memory.
288      *
289      *  The caller will have already acquired a mutex for thread safety, so this
290      *  method need not do that.
291      */
292     virtual void onUnlockPixels() = 0;
293 
294     /** Default impl returns true */
295     virtual bool onLockPixelsAreWritable() const;
296 
297     /**
298      *  For pixelrefs that don't have access to their raw pixels, they may be
299      *  able to make a copy of them (e.g. if the pixels are on the GPU).
300      *
301      *  The base class implementation returns false;
302      */
303     virtual bool onReadPixels(SkBitmap* dst, SkColorType colorType, const SkIRect* subsetOrNull);
304 
305     // default impl returns NULL.
306     virtual SkData* onRefEncodedData();
307 
308     // default impl does nothing.
309     virtual void onNotifyPixelsChanged();
310 
311     // default impl returns false.
312     virtual bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
313                                  SkYUVColorSpace* colorSpace);
314 
315     /**
316      *  Returns the size (in bytes) of the internally allocated memory.
317      *  This should be implemented in all serializable SkPixelRef derived classes.
318      *  SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value,
319      *  otherwise the rendering code may attempt to read memory out of bounds.
320      *
321      *  @return default impl returns 0.
322      */
323     virtual size_t getAllocatedSizeInBytes() const;
324 
325     virtual bool onRequestLock(const LockRequest&, LockResult*);
326 
onIsLazyGenerated()327     virtual bool onIsLazyGenerated() const { return false; }
328 
329     /** Return the mutex associated with this pixelref. This value is assigned
330         in the constructor, and cannot change during the lifetime of the object.
331     */
mutex()332     SkBaseMutex* mutex() const { return &fMutex; }
333 
334     // only call from constructor. Flags this to always be locked, removing
335     // the need to grab the mutex and call onLockPixels/onUnlockPixels.
336     // Performance tweak to avoid those calls (esp. in multi-thread use case).
337     void setPreLocked(void*, size_t rowBytes, SkColorTable*);
338 
339 private:
340     mutable SkMutex fMutex;
341 
342     // mostly const. fInfo.fAlpahType can be changed at runtime.
343     const SkImageInfo fInfo;
344 
345     // LockRec is only valid if we're in a locked state (isLocked())
346     LockRec         fRec;
347     int             fLockCount;
348 
349     bool lockPixelsInsideMutex();
350 
351     // Bottom bit indicates the Gen ID is unique.
genIDIsUnique()352     bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }
353     mutable SkAtomic<uint32_t> fTaggedGenID;
354 
355 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
356     const uint32_t fStableID;
357 #endif
358 
359     SkTDArray<GenIDChangeListener*> fGenIDChangeListeners;  // pointers are owned
360 
361     SkString    fURI;
362 
363     // Set true by caches when they cache content that's derived from the current pixels.
364     SkAtomic<bool> fAddedToCache;
365 
366     enum {
367         kMutable,               // PixelRefs begin mutable.
368         kTemporarilyImmutable,  // Considered immutable, but can revert to mutable.
369         kImmutable,             // Once set to this state, it never leaves.
370     } fMutability : 8;          // easily fits inside a byte
371 
372     // only ever set in constructor, const after that
373     bool fPreLocked;
374 
375     void needsNewGenID();
376     void callGenIDChangeListeners();
377 
378     void setTemporarilyImmutable();
379     void restoreMutability();
380     friend class SkSurface_Raster;   // For the two methods above.
381 
isPreLocked()382     bool isPreLocked() const { return fPreLocked; }
383     friend class SkImage_Raster;
384     friend class SkSpecialImage_Raster;
385 
386     // When copying a bitmap to another with the same shape and config, we can safely
387     // clone the pixelref generation ID too, which makes them equivalent under caching.
388     friend class SkBitmap;  // only for cloneGenID
389     void cloneGenID(const SkPixelRef&);
390 
391     void setImmutableWithID(uint32_t genID);
392     friend class SkImage_Gpu;
393     friend class SkImageCacherator;
394 
395     typedef SkRefCnt INHERITED;
396 };
397 
398 class SkPixelRefFactory : public SkRefCnt {
399 public:
400     /**
401      *  Allocate a new pixelref matching the specified ImageInfo, allocating
402      *  the memory for the pixels. If the ImageInfo requires a ColorTable,
403      *  the pixelref will ref() the colortable.
404      *  On failure return NULL.
405      */
406     virtual SkPixelRef* create(const SkImageInfo&, size_t rowBytes, SkColorTable*) = 0;
407 };
408 
409 #endif
410