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 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 
     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     */
     48     void* pixels() const { return fRec.fPixels; }
     49 
     50     /** Return the current colorTable (if any) if pixels are locked, or null.
     51     */
     52     SkColorTable* colorTable() const { return fRec.fColorTable; }
     53 
     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 {
     61         LockRec() : fPixels(NULL), fColorTable(NULL) {}
     62 
     63         void*           fPixels;
     64         SkColorTable*   fColorTable;
     65         size_t          fRowBytes;
     66 
     67         void zero() { sk_bzero(this, sizeof(*this)); }
     68 
     69         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      */
    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     */
    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     */
    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      */
    155     void setURI(const char uri[]) {
    156         fURI.set(uri);
    157     }
    158 
    159     /** Copy a URI string to this pixelref
    160      */
    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     */
    167     void setURI(const SkString& uri) { fURI = uri; }
    168 
    169     struct LockRequest {
    170         SkISize         fSize;
    171         SkFilterQuality fQuality;
    172     };
    173 
    174     struct LockResult {
    175         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 
    185         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 {
    204         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.
    213     void notifyAddedToCache() {
    214         fAddedToCache.store(true);
    215     }
    216 
    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      */
    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 
    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     */
    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.
    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 
    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