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 
     18 #ifdef SK_DEBUG
     19     /**
     20      *  Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref
     21      *  subclasses to correctly handle lock/unlock pixels. For performance
     22      *  reasons, simple malloc-based subclasses call setPreLocked() to skip
     23      *  the overhead of implementing these calls.
     24      *
     25      *  This build-flag disables that optimization, to add in debugging our
     26      *  call-sites, to ensure that they correctly balance their calls of
     27      *  lock and unlock.
     28      */
     29 //    #define SK_IGNORE_PIXELREF_SETPRELOCKED
     30 #endif
     31 
     32 class SkColorTable;
     33 class SkData;
     34 struct SkIRect;
     35 class SkMutex;
     36 
     37 // this is an opaque class, not interpreted by skia
     38 class SkGpuTexture;
     39 
     40 /** \class SkPixelRef
     41 
     42     This class is the smart container for pixel memory, and is used with
     43     SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
     44     access the actual pixel memory by calling lockPixels/unlockPixels.
     45 
     46     This class can be shared/accessed between multiple threads.
     47 */
     48 class SK_API SkPixelRef : public SkFlattenable {
     49 public:
     50     SK_DECLARE_INST_COUNT(SkPixelRef)
     51 
     52     explicit SkPixelRef(SkBaseMutex* mutex = NULL);
     53 
     54     /** Return the pixel memory returned from lockPixels, or null if the
     55         lockCount is 0.
     56     */
     57     void* pixels() const { return fPixels; }
     58 
     59     /** Return the current colorTable (if any) if pixels are locked, or null.
     60     */
     61     SkColorTable* colorTable() const { return fColorTable; }
     62 
     63     /**
     64      *  Returns true if the lockcount > 0
     65      */
     66     bool isLocked() const { return fLockCount > 0; }
     67 
     68     SkDEBUGCODE(int getLockCount() const { return fLockCount; })
     69 
     70     /** Call to access the pixel memory, which is returned. Balance with a call
     71         to unlockPixels().
     72     */
     73     void lockPixels();
     74     /** Call to balanace a previous call to lockPixels(). Returns the pixels
     75         (or null) after the unlock. NOTE: lock calls can be nested, but the
     76         matching number of unlock calls must be made in order to free the
     77         memory (if the subclass implements caching/deferred-decoding.)
     78     */
     79     void unlockPixels();
     80 
     81     /**
     82      *  Some bitmaps can return a copy of their pixels for lockPixels(), but
     83      *  that copy, if modified, will not be pushed back. These bitmaps should
     84      *  not be used as targets for a raster device/canvas (since all pixels
     85      *  modifications will be lost when unlockPixels() is called.)
     86      */
     87     bool lockPixelsAreWritable() const;
     88 
     89     /** Returns a non-zero, unique value corresponding to the pixels in this
     90         pixelref. Each time the pixels are changed (and notifyPixelsChanged is
     91         called), a different generation ID will be returned.
     92     */
     93     uint32_t getGenerationID() const;
     94 
     95     /** Call this if you have changed the contents of the pixels. This will in-
     96         turn cause a different generation ID value to be returned from
     97         getGenerationID().
     98     */
     99     void notifyPixelsChanged();
    100 
    101     /** Returns true if this pixelref is marked as immutable, meaning that the
    102         contents of its pixels will not change for the lifetime of the pixelref.
    103     */
    104     bool isImmutable() const { return fIsImmutable; }
    105 
    106     /** Marks this pixelref is immutable, meaning that the contents of its
    107         pixels will not change for the lifetime of the pixelref. This state can
    108         be set on a pixelref, but it cannot be cleared once it is set.
    109     */
    110     void setImmutable();
    111 
    112     /** Return the optional URI string associated with this pixelref. May be
    113         null.
    114     */
    115     const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
    116 
    117     /** Copy a URI string to this pixelref, or clear the URI if the uri is null
    118      */
    119     void setURI(const char uri[]) {
    120         fURI.set(uri);
    121     }
    122 
    123     /** Copy a URI string to this pixelref
    124      */
    125     void setURI(const char uri[], size_t len) {
    126         fURI.set(uri, len);
    127     }
    128 
    129     /** Assign a URI string to this pixelref.
    130     */
    131     void setURI(const SkString& uri) { fURI = uri; }
    132 
    133     /**
    134      *  If the pixelRef has an encoded (i.e. compressed) representation,
    135      *  return a ref to its data. If the pixelRef
    136      *  is uncompressed or otherwise does not have this form, return NULL.
    137      *
    138      *  If non-null is returned, the caller is responsible for calling unref()
    139      *  on the data when it is finished.
    140      */
    141     SkData* refEncodedData() {
    142         return this->onRefEncodedData();
    143     }
    144 
    145     /** Are we really wrapping a texture instead of a bitmap?
    146      */
    147     virtual SkGpuTexture* getTexture() { return NULL; }
    148 
    149     bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
    150 
    151     /**
    152      *  Makes a deep copy of this PixelRef, respecting the requested config.
    153      *  @param config Desired config.
    154      *  @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
    155      *         of this PixelRef.
    156      *  @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
    157      *          not be created with the given config), or this PixelRef does not support deep
    158      *          copies.
    159      */
    160     virtual SkPixelRef* deepCopy(SkBitmap::Config config, const SkIRect* subset = NULL) {
    161         return NULL;
    162     }
    163 
    164 #ifdef SK_BUILD_FOR_ANDROID
    165     /**
    166      *  Acquire a "global" ref on this object.
    167      *  The default implementation just calls ref(), but subclasses can override
    168      *  this method to implement additional behavior.
    169      */
    170     virtual void globalRef(void* data=NULL);
    171 
    172     /**
    173      *  Release a "global" ref on this object.
    174      *  The default implementation just calls unref(), but subclasses can override
    175      *  this method to implement additional behavior.
    176      */
    177     virtual void globalUnref();
    178 #endif
    179 
    180 protected:
    181     /** Called when the lockCount goes from 0 to 1. The caller will have already
    182         acquire a mutex for thread safety, so this method need not do that.
    183     */
    184     virtual void* onLockPixels(SkColorTable**) = 0;
    185     /** Called when the lock count goes from 1 to 0. The caller will have
    186         already acquire a mutex for thread safety, so this method need not do
    187         that.
    188     */
    189     virtual void onUnlockPixels() = 0;
    190 
    191     /** Default impl returns true */
    192     virtual bool onLockPixelsAreWritable() const;
    193 
    194     /**
    195      *  For pixelrefs that don't have access to their raw pixels, they may be
    196      *  able to make a copy of them (e.g. if the pixels are on the GPU).
    197      *
    198      *  The base class implementation returns false;
    199      */
    200     virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull);
    201 
    202     // default impl returns NULL.
    203     virtual SkData* onRefEncodedData();
    204 
    205     /** Return the mutex associated with this pixelref. This value is assigned
    206         in the constructor, and cannot change during the lifetime of the object.
    207     */
    208     SkBaseMutex* mutex() const { return fMutex; }
    209 
    210     // serialization
    211     SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
    212     virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
    213 
    214     // only call from constructor. Flags this to always be locked, removing
    215     // the need to grab the mutex and call onLockPixels/onUnlockPixels.
    216     // Performance tweak to avoid those calls (esp. in multi-thread use case).
    217     void setPreLocked(void* pixels, SkColorTable* ctable);
    218 
    219 private:
    220 
    221     SkBaseMutex*    fMutex; // must remain in scope for the life of this object
    222     void*           fPixels;
    223     SkColorTable*   fColorTable;    // we do not track ownership, subclass does
    224     int             fLockCount;
    225 
    226     mutable uint32_t fGenerationID;
    227 
    228     // SkBitmap is only a friend so that when copying, it can modify the new SkPixelRef to have the
    229     // same fGenerationID as the original.
    230     friend class SkBitmap;
    231 
    232     SkString    fURI;
    233 
    234     // can go from false to true, but never from true to false
    235     bool    fIsImmutable;
    236     // only ever set in constructor, const after that
    237     bool    fPreLocked;
    238 
    239     void setMutex(SkBaseMutex* mutex);
    240 
    241     typedef SkFlattenable INHERITED;
    242 };
    243 
    244 #endif
    245