Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2008 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkPixelRef_DEFINED
     11 #define SkPixelRef_DEFINED
     12 
     13 #include "SkBitmap.h"
     14 #include "SkRefCnt.h"
     15 #include "SkString.h"
     16 #include "SkFlattenable.h"
     17 #include "SkTDArray.h"
     18 
     19 //#define SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR
     20 
     21 #ifdef SK_DEBUG
     22     /**
     23      *  Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref
     24      *  subclasses to correctly handle lock/unlock pixels. For performance
     25      *  reasons, simple malloc-based subclasses call setPreLocked() to skip
     26      *  the overhead of implementing these calls.
     27      *
     28      *  This build-flag disables that optimization, to add in debugging our
     29      *  call-sites, to ensure that they correctly balance their calls of
     30      *  lock and unlock.
     31      */
     32 //    #define SK_IGNORE_PIXELREF_SETPRELOCKED
     33 #endif
     34 
     35 class SkColorTable;
     36 class SkData;
     37 struct SkIRect;
     38 class SkMutex;
     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 SkFlattenable {
     51 public:
     52     SK_DECLARE_INST_COUNT(SkPixelRef)
     53 
     54 #ifdef SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR
     55     // DEPRECATED -- use a constructor that takes SkImageInfo
     56     explicit SkPixelRef(SkBaseMutex* mutex = NULL);
     57 #endif
     58 
     59     explicit SkPixelRef(const SkImageInfo&);
     60     SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex);
     61     virtual ~SkPixelRef();
     62 
     63     const SkImageInfo& info() const {
     64         return fInfo;
     65     }
     66 
     67     /** Return the pixel memory returned from lockPixels, or null if the
     68         lockCount is 0.
     69     */
     70     void* pixels() const { return fPixels; }
     71 
     72     /** Return the current colorTable (if any) if pixels are locked, or null.
     73     */
     74     SkColorTable* colorTable() const { return fColorTable; }
     75 
     76     /**
     77      *  Returns true if the lockcount > 0
     78      */
     79     bool isLocked() const { return fLockCount > 0; }
     80 
     81     SkDEBUGCODE(int getLockCount() const { return fLockCount; })
     82 
     83     /** Call to access the pixel memory, which is returned. Balance with a call
     84         to unlockPixels().
     85     */
     86     void lockPixels();
     87     /** Call to balanace a previous call to lockPixels(). Returns the pixels
     88         (or null) after the unlock. NOTE: lock calls can be nested, but the
     89         matching number of unlock calls must be made in order to free the
     90         memory (if the subclass implements caching/deferred-decoding.)
     91     */
     92     void unlockPixels();
     93 
     94     /**
     95      *  Some bitmaps can return a copy of their pixels for lockPixels(), but
     96      *  that copy, if modified, will not be pushed back. These bitmaps should
     97      *  not be used as targets for a raster device/canvas (since all pixels
     98      *  modifications will be lost when unlockPixels() is called.)
     99      */
    100     bool lockPixelsAreWritable() const;
    101 
    102     /** Returns a non-zero, unique value corresponding to the pixels in this
    103         pixelref. Each time the pixels are changed (and notifyPixelsChanged is
    104         called), a different generation ID will be returned.
    105     */
    106     uint32_t getGenerationID() const;
    107 
    108     /** Call this if you have changed the contents of the pixels. This will in-
    109         turn cause a different generation ID value to be returned from
    110         getGenerationID().
    111     */
    112     void notifyPixelsChanged();
    113 
    114     /** Returns true if this pixelref is marked as immutable, meaning that the
    115         contents of its pixels will not change for the lifetime of the pixelref.
    116     */
    117     bool isImmutable() const { return fIsImmutable; }
    118 
    119     /** Marks this pixelref is immutable, meaning that the contents of its
    120         pixels will not change for the lifetime of the pixelref. This state can
    121         be set on a pixelref, but it cannot be cleared once it is set.
    122     */
    123     void setImmutable();
    124 
    125     /** Return the optional URI string associated with this pixelref. May be
    126         null.
    127     */
    128     const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
    129 
    130     /** Copy a URI string to this pixelref, or clear the URI if the uri is null
    131      */
    132     void setURI(const char uri[]) {
    133         fURI.set(uri);
    134     }
    135 
    136     /** Copy a URI string to this pixelref
    137      */
    138     void setURI(const char uri[], size_t len) {
    139         fURI.set(uri, len);
    140     }
    141 
    142     /** Assign a URI string to this pixelref.
    143     */
    144     void setURI(const SkString& uri) { fURI = uri; }
    145 
    146     /**
    147      *  If the pixelRef has an encoded (i.e. compressed) representation,
    148      *  return a ref to its data. If the pixelRef
    149      *  is uncompressed or otherwise does not have this form, return NULL.
    150      *
    151      *  If non-null is returned, the caller is responsible for calling unref()
    152      *  on the data when it is finished.
    153      */
    154     SkData* refEncodedData() {
    155         return this->onRefEncodedData();
    156     }
    157 
    158     /**
    159      *  Experimental -- tells the caller if it is worth it to call decodeInto().
    160      *  Just an optimization at this point, to avoid checking the cache first.
    161      *  We may remove/change this call in the future.
    162      */
    163     bool implementsDecodeInto() {
    164         return this->onImplementsDecodeInto();
    165     }
    166 
    167     /**
    168      *  Return a decoded instance of this pixelRef in bitmap. If this cannot be
    169      *  done, return false and the bitmap parameter is ignored/unchanged.
    170      *
    171      *  pow2 is the requeste power-of-two downscale that the caller needs. This
    172      *  can be ignored, and the "original" size can be returned, but if the
    173      *  underlying codec can efficiently return a smaller size, that should be
    174      *  done. Some examples:
    175      *
    176      *  To request the "base" version (original scale), pass 0 for pow2
    177      *  To request 1/2 scale version (1/2 width, 1/2 height), pass 1 for pow2
    178      *  To request 1/4 scale version (1/4 width, 1/4 height), pass 2 for pow2
    179      *  ...
    180      *
    181      *  If this returns true, then bitmap must be "locked" such that
    182      *  bitmap->getPixels() will return the correct address.
    183      */
    184     bool decodeInto(int pow2, SkBitmap* bitmap) {
    185         SkASSERT(pow2 >= 0);
    186         return this->onDecodeInto(pow2, bitmap);
    187     }
    188 
    189     /** Are we really wrapping a texture instead of a bitmap?
    190      */
    191     virtual GrTexture* getTexture() { return NULL; }
    192 
    193     bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
    194 
    195     /**
    196      *  Makes a deep copy of this PixelRef, respecting the requested config.
    197      *  @param config Desired config.
    198      *  @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
    199      *         of this PixelRef.
    200      *  @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
    201      *          not be created with the given config), or this PixelRef does not support deep
    202      *          copies.
    203      */
    204     virtual SkPixelRef* deepCopy(SkBitmap::Config config, const SkIRect* subset = NULL) {
    205         return NULL;
    206     }
    207 
    208 #ifdef SK_BUILD_FOR_ANDROID
    209     /**
    210      *  Acquire a "global" ref on this object.
    211      *  The default implementation just calls ref(), but subclasses can override
    212      *  this method to implement additional behavior.
    213      */
    214     virtual void globalRef(void* data=NULL);
    215 
    216     /**
    217      *  Release a "global" ref on this object.
    218      *  The default implementation just calls unref(), but subclasses can override
    219      *  this method to implement additional behavior.
    220      */
    221     virtual void globalUnref();
    222 #endif
    223 
    224     SK_DEFINE_FLATTENABLE_TYPE(SkPixelRef)
    225 
    226     // Register a listener that may be called the next time our generation ID changes.
    227     //
    228     // We'll only call the listener if we're confident that we are the only SkPixelRef with this
    229     // generation ID.  If our generation ID changes and we decide not to call the listener, we'll
    230     // never call it: you must add a new listener for each generation ID change.  We also won't call
    231     // the listener when we're certain no one knows what our generation ID is.
    232     //
    233     // This can be used to invalidate caches keyed by SkPixelRef generation ID.
    234     struct GenIDChangeListener {
    235         virtual ~GenIDChangeListener() {}
    236         virtual void onChange() = 0;
    237     };
    238 
    239     // Takes ownership of listener.
    240     void addGenIDChangeListener(GenIDChangeListener* listener);
    241 
    242 protected:
    243     /** Called when the lockCount goes from 0 to 1. The caller will have already
    244         acquire a mutex for thread safety, so this method need not do that.
    245     */
    246     virtual void* onLockPixels(SkColorTable**) = 0;
    247 
    248     /**
    249      *  Called when the lock count goes from 1 to 0. The caller will have
    250      *  already acquire a mutex for thread safety, so this method need not do
    251      *  that.
    252      *
    253      *  If the previous call to onLockPixels failed (i.e. returned NULL), then
    254      *  the onUnlockPixels will NOT be called.
    255      */
    256     virtual void onUnlockPixels() = 0;
    257 
    258     /** Default impl returns true */
    259     virtual bool onLockPixelsAreWritable() const;
    260 
    261     // returns false;
    262     virtual bool onImplementsDecodeInto();
    263     // returns false;
    264     virtual bool onDecodeInto(int pow2, SkBitmap* bitmap);
    265 
    266     /**
    267      *  For pixelrefs that don't have access to their raw pixels, they may be
    268      *  able to make a copy of them (e.g. if the pixels are on the GPU).
    269      *
    270      *  The base class implementation returns false;
    271      */
    272     virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull);
    273 
    274     // default impl returns NULL.
    275     virtual SkData* onRefEncodedData();
    276 
    277     /**
    278      *  Returns the size (in bytes) of the internally allocated memory.
    279      *  This should be implemented in all serializable SkPixelRef derived classes.
    280      *  SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value,
    281      *  otherwise the rendering code may attempt to read memory out of bounds.
    282      *
    283      *  @return default impl returns 0.
    284      */
    285     virtual size_t getAllocatedSizeInBytes() const;
    286 
    287     /** Return the mutex associated with this pixelref. This value is assigned
    288         in the constructor, and cannot change during the lifetime of the object.
    289     */
    290     SkBaseMutex* mutex() const { return fMutex; }
    291 
    292     // serialization
    293     SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
    294     virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
    295 
    296     // only call from constructor. Flags this to always be locked, removing
    297     // the need to grab the mutex and call onLockPixels/onUnlockPixels.
    298     // Performance tweak to avoid those calls (esp. in multi-thread use case).
    299     void setPreLocked(void* pixels, SkColorTable* ctable);
    300 
    301 private:
    302     SkBaseMutex*    fMutex; // must remain in scope for the life of this object
    303     // FIXME: fInfo should be const once we remove old constructor that does
    304     // not set it.
    305     SkImageInfo     fInfo;
    306 
    307     void*           fPixels;
    308     SkColorTable*   fColorTable;    // we do not track ownership, subclass does
    309     int             fLockCount;
    310 
    311     mutable uint32_t fGenerationID;
    312     mutable bool     fUniqueGenerationID;
    313 
    314     SkTDArray<GenIDChangeListener*> fGenIDChangeListeners;  // pointers are owned
    315 
    316     SkString    fURI;
    317 
    318     // can go from false to true, but never from true to false
    319     bool    fIsImmutable;
    320     // only ever set in constructor, const after that
    321     bool    fPreLocked;
    322 
    323     void needsNewGenID();
    324     void callGenIDChangeListeners();
    325 
    326     void setMutex(SkBaseMutex* mutex);
    327 
    328     // When copying a bitmap to another with the same shape and config, we can safely
    329     // clone the pixelref generation ID too, which makes them equivalent under caching.
    330     friend class SkBitmap;  // only for cloneGenID
    331     void cloneGenID(const SkPixelRef&);
    332 
    333     typedef SkFlattenable INHERITED;
    334 };
    335 
    336 #endif
    337