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