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