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