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