Home | History | Annotate | Download | only in core
      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 
     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     */
     49     void* pixels() const { return fRec.fPixels; }
     50 
     51     /** Return the current colorTable (if any) if pixels are locked, or null.
     52     */
     53     SkColorTable* colorTable() const { return fRec.fColorTable; }
     54 
     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 {
     62         LockRec() : fPixels(NULL), fColorTable(NULL) {}
     63 
     64         void*           fPixels;
     65         SkColorTable*   fColorTable;
     66         size_t          fRowBytes;
     67 
     68         void zero() { sk_bzero(this, sizeof(*this)); }
     69 
     70         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      */
    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     */
    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     */
    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      */
    156     void setURI(const char uri[]) {
    157         fURI.set(uri);
    158     }
    159 
    160     /** Copy a URI string to this pixelref
    161      */
    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     */
    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      */
    178     SkData* refEncodedData() {
    179         return this->onRefEncodedData();
    180     }
    181 
    182     struct LockRequest {
    183         SkISize         fSize;
    184         SkFilterQuality fQuality;
    185     };
    186 
    187     struct LockResult {
    188         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 
    198         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      */
    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      */
    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      */
    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 {
    254         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.
    263     void notifyAddedToCache() {
    264         fAddedToCache.store(true);
    265     }
    266 
    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      */
    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 
    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     */
    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.
    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 
    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