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 "SkAtomics.h" 12 #include "SkBitmap.h" 13 #include "SkImageInfo.h" 14 #include "SkMutex.h" 15 #include "SkRefCnt.h" 16 #include "SkSize.h" 17 #include "SkString.h" 18 #include "SkTDArray.h" 19 20 //#define xed 21 22 #ifdef SK_DEBUG 23 /** 24 * Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref 25 * subclasses to correctly handle lock/unlock pixels. For performance 26 * reasons, simple malloc-based subclasses call setPreLocked() to skip 27 * the overhead of implementing these calls. 28 * 29 * This build-flag disables that optimization, to add in debugging our 30 * call-sites, to ensure that they correctly balance their calls of 31 * lock and unlock. 32 */ 33 // #define SK_IGNORE_PIXELREF_SETPRELOCKED 34 #endif 35 36 class SkColorTable; 37 class SkData; 38 struct SkIRect; 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 SkRefCnt { 51 public: 52 SK_DECLARE_INST_COUNT(SkPixelRef) 53 54 explicit SkPixelRef(const SkImageInfo&); 55 SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex); 56 virtual ~SkPixelRef(); 57 info()58 const SkImageInfo& info() const { 59 return fInfo; 60 } 61 62 /** Return the pixel memory returned from lockPixels, or null if the 63 lockCount is 0. 64 */ pixels()65 void* pixels() const { return fRec.fPixels; } 66 67 /** Return the current colorTable (if any) if pixels are locked, or null. 68 */ colorTable()69 SkColorTable* colorTable() const { return fRec.fColorTable; } 70 rowBytes()71 size_t rowBytes() const { return fRec.fRowBytes; } 72 73 /** 74 * To access the actual pixels of a pixelref, it must be "locked". 75 * Calling lockPixels returns a LockRec struct (on success). 76 */ 77 struct LockRec { 78 void* fPixels; 79 SkColorTable* fColorTable; 80 size_t fRowBytes; 81 zeroLockRec82 void zero() { sk_bzero(this, sizeof(*this)); } 83 isZeroLockRec84 bool isZero() const { 85 return NULL == fPixels && NULL == fColorTable && 0 == fRowBytes; 86 } 87 }; 88 89 SkDEBUGCODE(bool isLocked() const { return fLockCount > 0; }) 90 SkDEBUGCODE(int getLockCount() const { return fLockCount; }) 91 92 /** 93 * Call to access the pixel memory. Return true on success. Balance this 94 * with a call to unlockPixels(). 95 */ 96 bool lockPixels(); 97 98 /** 99 * Call to access the pixel memory. On success, return true and fill out 100 * the specified rec. On failure, return false and ignore the rec parameter. 101 * Balance this with a call to unlockPixels(). 102 */ 103 bool lockPixels(LockRec* rec); 104 105 /** Call to balanace a previous call to lockPixels(). Returns the pixels 106 (or null) after the unlock. NOTE: lock calls can be nested, but the 107 matching number of unlock calls must be made in order to free the 108 memory (if the subclass implements caching/deferred-decoding.) 109 */ 110 void unlockPixels(); 111 112 /** 113 * Some bitmaps can return a copy of their pixels for lockPixels(), but 114 * that copy, if modified, will not be pushed back. These bitmaps should 115 * not be used as targets for a raster device/canvas (since all pixels 116 * modifications will be lost when unlockPixels() is called.) 117 */ 118 bool lockPixelsAreWritable() const; 119 120 /** Returns a non-zero, unique value corresponding to the pixels in this 121 pixelref. Each time the pixels are changed (and notifyPixelsChanged is 122 called), a different generation ID will be returned. 123 */ 124 uint32_t getGenerationID() const; 125 126 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 127 /** Returns a non-zero, unique value corresponding to this SkPixelRef. 128 Unlike the generation ID, this ID remains the same even when the pixels 129 are changed. IDs are not reused (until uint32_t wraps), so it is safe 130 to consider this ID unique even after this SkPixelRef is deleted. 131 132 Can be used as a key which uniquely identifies this SkPixelRef 133 regardless of changes to its pixels or deletion of this object. 134 */ getStableID()135 uint32_t getStableID() const { return fStableID; } 136 #endif 137 138 /** 139 * Call this if you have changed the contents of the pixels. This will in- 140 * turn cause a different generation ID value to be returned from 141 * getGenerationID(). 142 */ 143 void notifyPixelsChanged(); 144 145 /** 146 * Change the info's AlphaType. Note that this does not automatically 147 * invalidate the generation ID. If the pixel values themselves have 148 * changed, then you must explicitly call notifyPixelsChanged() as well. 149 */ 150 void changeAlphaType(SkAlphaType at); 151 152 /** Returns true if this pixelref is marked as immutable, meaning that the 153 contents of its pixels will not change for the lifetime of the pixelref. 154 */ isImmutable()155 bool isImmutable() const { return fIsImmutable; } 156 157 /** Marks this pixelref is immutable, meaning that the contents of its 158 pixels will not change for the lifetime of the pixelref. This state can 159 be set on a pixelref, but it cannot be cleared once it is set. 160 */ 161 void setImmutable(); 162 163 /** Return the optional URI string associated with this pixelref. May be 164 null. 165 */ getURI()166 const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; } 167 168 /** Copy a URI string to this pixelref, or clear the URI if the uri is null 169 */ setURI(const char uri[])170 void setURI(const char uri[]) { 171 fURI.set(uri); 172 } 173 174 /** Copy a URI string to this pixelref 175 */ setURI(const char uri[],size_t len)176 void setURI(const char uri[], size_t len) { 177 fURI.set(uri, len); 178 } 179 180 /** Assign a URI string to this pixelref. 181 */ setURI(const SkString & uri)182 void setURI(const SkString& uri) { fURI = uri; } 183 184 /** 185 * If the pixelRef has an encoded (i.e. compressed) representation, 186 * return a ref to its data. If the pixelRef 187 * is uncompressed or otherwise does not have this form, return NULL. 188 * 189 * If non-null is returned, the caller is responsible for calling unref() 190 * on the data when it is finished. 191 */ refEncodedData()192 SkData* refEncodedData() { 193 return this->onRefEncodedData(); 194 } 195 196 /** Are we really wrapping a texture instead of a bitmap? 197 */ getTexture()198 virtual GrTexture* getTexture() { return NULL; } 199 200 /** 201 * If any planes or rowBytes is NULL, this should output the sizes and return true 202 * if it can efficiently return YUV planar data. If it cannot, it should return false. 203 * 204 * If all planes and rowBytes are not NULL, then it should copy the associated Y,U,V data 205 * into those planes of memory supplied by the caller. It should validate that the sizes 206 * match what it expected. If the sizes do not match, it should return false. 207 * 208 * If colorSpace is not NULL, the YUV color space of the data should be stored in the address 209 * it points at. 210 */ getYUV8Planes(SkISize sizes[3],void * planes[3],size_t rowBytes[3],SkYUVColorSpace * colorSpace)211 bool getYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], 212 SkYUVColorSpace* colorSpace) { 213 return this->onGetYUV8Planes(sizes, planes, rowBytes, colorSpace); 214 } 215 216 bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL); 217 218 /** 219 * Makes a deep copy of this PixelRef, respecting the requested config. 220 * @param colorType Desired colortype. 221 * @param profileType Desired colorprofiletype. 222 * @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of 223 * of this PixelRef. 224 * @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could 225 * not be created with the given config), or this PixelRef does not support deep 226 * copies. 227 */ deepCopy(SkColorType,SkColorProfileType,const SkIRect *)228 virtual SkPixelRef* deepCopy(SkColorType, SkColorProfileType, const SkIRect* /*subset*/) { 229 return NULL; 230 } 231 232 // Register a listener that may be called the next time our generation ID changes. 233 // 234 // We'll only call the listener if we're confident that we are the only SkPixelRef with this 235 // generation ID. If our generation ID changes and we decide not to call the listener, we'll 236 // never call it: you must add a new listener for each generation ID change. We also won't call 237 // the listener when we're certain no one knows what our generation ID is. 238 // 239 // This can be used to invalidate caches keyed by SkPixelRef generation ID. 240 struct GenIDChangeListener { ~GenIDChangeListenerGenIDChangeListener241 virtual ~GenIDChangeListener() {} 242 virtual void onChange() = 0; 243 }; 244 245 // Takes ownership of listener. 246 void addGenIDChangeListener(GenIDChangeListener* listener); 247 248 // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache 249 // to know automatically those entries can be purged when this pixelref is changed or deleted. notifyAddedToCache()250 void notifyAddedToCache() { 251 fAddedToCache.store(true); 252 } 253 254 protected: 255 /** 256 * On success, returns true and fills out the LockRec for the pixels. On 257 * failure returns false and ignores the LockRec parameter. 258 * 259 * The caller will have already acquired a mutex for thread safety, so this 260 * method need not do that. 261 */ 262 virtual bool onNewLockPixels(LockRec*) = 0; 263 264 /** 265 * Balancing the previous successful call to onNewLockPixels. The locked 266 * pixel address will no longer be referenced, so the subclass is free to 267 * move or discard that memory. 268 * 269 * The caller will have already acquired a mutex for thread safety, so this 270 * method need not do that. 271 */ 272 virtual void onUnlockPixels() = 0; 273 274 /** Default impl returns true */ 275 virtual bool onLockPixelsAreWritable() const; 276 277 /** 278 * For pixelrefs that don't have access to their raw pixels, they may be 279 * able to make a copy of them (e.g. if the pixels are on the GPU). 280 * 281 * The base class implementation returns false; 282 */ 283 virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull); 284 285 // default impl returns NULL. 286 virtual SkData* onRefEncodedData(); 287 288 // default impl returns false. 289 virtual bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], 290 SkYUVColorSpace* colorSpace); 291 292 /** 293 * Returns the size (in bytes) of the internally allocated memory. 294 * This should be implemented in all serializable SkPixelRef derived classes. 295 * SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value, 296 * otherwise the rendering code may attempt to read memory out of bounds. 297 * 298 * @return default impl returns 0. 299 */ 300 virtual size_t getAllocatedSizeInBytes() const; 301 302 /** Return the mutex associated with this pixelref. This value is assigned 303 in the constructor, and cannot change during the lifetime of the object. 304 */ mutex()305 SkBaseMutex* mutex() const { return fMutex; } 306 307 // only call from constructor. Flags this to always be locked, removing 308 // the need to grab the mutex and call onLockPixels/onUnlockPixels. 309 // Performance tweak to avoid those calls (esp. in multi-thread use case). 310 void setPreLocked(void*, size_t rowBytes, SkColorTable*); 311 312 private: 313 SkBaseMutex* fMutex; // must remain in scope for the life of this object 314 315 // mostly const. fInfo.fAlpahType can be changed at runtime. 316 const SkImageInfo fInfo; 317 318 // LockRec is only valid if we're in a locked state (isLocked()) 319 LockRec fRec; 320 int fLockCount; 321 322 // Bottom bit indicates the Gen ID is unique. genIDIsUnique()323 bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); } 324 mutable SkAtomic<uint32_t> fTaggedGenID; 325 326 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 327 const uint32_t fStableID; 328 #endif 329 330 SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned 331 332 SkString fURI; 333 334 // Set true by caches when they cache content that's derived from the current pixels. 335 SkAtomic<bool> fAddedToCache; 336 // can go from false to true, but never from true to false 337 bool fIsImmutable; 338 // only ever set in constructor, const after that 339 bool fPreLocked; 340 341 void needsNewGenID(); 342 void callGenIDChangeListeners(); 343 344 void setMutex(SkBaseMutex* mutex); 345 346 // When copying a bitmap to another with the same shape and config, we can safely 347 // clone the pixelref generation ID too, which makes them equivalent under caching. 348 friend class SkBitmap; // only for cloneGenID 349 void cloneGenID(const SkPixelRef&); 350 351 typedef SkRefCnt INHERITED; 352 }; 353 354 class SkPixelRefFactory : public SkRefCnt { 355 public: 356 /** 357 * Allocate a new pixelref matching the specified ImageInfo, allocating 358 * the memory for the pixels. If the ImageInfo requires a ColorTable, 359 * the pixelref will ref() the colortable. 360 * On failure return NULL. 361 */ 362 virtual SkPixelRef* create(const SkImageInfo&, size_t rowBytes, SkColorTable*) = 0; 363 }; 364 365 #endif 366