1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/include/core/SkPixelRef.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,380 @@ 1.4 +/* 1.5 + * Copyright 2008 The Android Open Source Project 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#ifndef SkPixelRef_DEFINED 1.12 +#define SkPixelRef_DEFINED 1.13 + 1.14 +#include "SkBitmap.h" 1.15 +#include "SkRefCnt.h" 1.16 +#include "SkString.h" 1.17 +#include "SkFlattenable.h" 1.18 +#include "SkImageInfo.h" 1.19 +#include "SkTDArray.h" 1.20 + 1.21 +//#define xed 1.22 + 1.23 +#ifdef SK_DEBUG 1.24 + /** 1.25 + * Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref 1.26 + * subclasses to correctly handle lock/unlock pixels. For performance 1.27 + * reasons, simple malloc-based subclasses call setPreLocked() to skip 1.28 + * the overhead of implementing these calls. 1.29 + * 1.30 + * This build-flag disables that optimization, to add in debugging our 1.31 + * call-sites, to ensure that they correctly balance their calls of 1.32 + * lock and unlock. 1.33 + */ 1.34 +// #define SK_IGNORE_PIXELREF_SETPRELOCKED 1.35 +#endif 1.36 + 1.37 +class SkColorTable; 1.38 +class SkData; 1.39 +struct SkIRect; 1.40 +class SkMutex; 1.41 + 1.42 +class GrTexture; 1.43 + 1.44 +/** \class SkPixelRef 1.45 + 1.46 + This class is the smart container for pixel memory, and is used with 1.47 + SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can 1.48 + access the actual pixel memory by calling lockPixels/unlockPixels. 1.49 + 1.50 + This class can be shared/accessed between multiple threads. 1.51 +*/ 1.52 +class SK_API SkPixelRef : public SkFlattenable { 1.53 +public: 1.54 + SK_DECLARE_INST_COUNT(SkPixelRef) 1.55 + 1.56 + explicit SkPixelRef(const SkImageInfo&); 1.57 + SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex); 1.58 + virtual ~SkPixelRef(); 1.59 + 1.60 + const SkImageInfo& info() const { 1.61 + return fInfo; 1.62 + } 1.63 + 1.64 + /** Return the pixel memory returned from lockPixels, or null if the 1.65 + lockCount is 0. 1.66 + */ 1.67 + void* pixels() const { return fRec.fPixels; } 1.68 + 1.69 + /** Return the current colorTable (if any) if pixels are locked, or null. 1.70 + */ 1.71 + SkColorTable* colorTable() const { return fRec.fColorTable; } 1.72 + 1.73 + size_t rowBytes() const { return fRec.fRowBytes; } 1.74 + 1.75 + /** 1.76 + * To access the actual pixels of a pixelref, it must be "locked". 1.77 + * Calling lockPixels returns a LockRec struct (on success). 1.78 + */ 1.79 + struct LockRec { 1.80 + void* fPixels; 1.81 + SkColorTable* fColorTable; 1.82 + size_t fRowBytes; 1.83 + 1.84 + void zero() { sk_bzero(this, sizeof(*this)); } 1.85 + 1.86 + bool isZero() const { 1.87 + return NULL == fPixels && NULL == fColorTable && 0 == fRowBytes; 1.88 + } 1.89 + }; 1.90 + 1.91 + /** 1.92 + * Returns true if the lockcount > 0 1.93 + */ 1.94 + bool isLocked() const { return fLockCount > 0; } 1.95 + 1.96 + SkDEBUGCODE(int getLockCount() const { return fLockCount; }) 1.97 + 1.98 + /** 1.99 + * Call to access the pixel memory. Return true on success. Balance this 1.100 + * with a call to unlockPixels(). 1.101 + */ 1.102 + bool lockPixels(); 1.103 + 1.104 + /** 1.105 + * Call to access the pixel memory. On success, return true and fill out 1.106 + * the specified rec. On failure, return false and ignore the rec parameter. 1.107 + * Balance this with a call to unlockPixels(). 1.108 + */ 1.109 + bool lockPixels(LockRec* rec); 1.110 + 1.111 + /** Call to balanace a previous call to lockPixels(). Returns the pixels 1.112 + (or null) after the unlock. NOTE: lock calls can be nested, but the 1.113 + matching number of unlock calls must be made in order to free the 1.114 + memory (if the subclass implements caching/deferred-decoding.) 1.115 + */ 1.116 + void unlockPixels(); 1.117 + 1.118 + /** 1.119 + * Some bitmaps can return a copy of their pixels for lockPixels(), but 1.120 + * that copy, if modified, will not be pushed back. These bitmaps should 1.121 + * not be used as targets for a raster device/canvas (since all pixels 1.122 + * modifications will be lost when unlockPixels() is called.) 1.123 + */ 1.124 + bool lockPixelsAreWritable() const; 1.125 + 1.126 + /** Returns a non-zero, unique value corresponding to the pixels in this 1.127 + pixelref. Each time the pixels are changed (and notifyPixelsChanged is 1.128 + called), a different generation ID will be returned. 1.129 + */ 1.130 + uint32_t getGenerationID() const; 1.131 + 1.132 + /** 1.133 + * Call this if you have changed the contents of the pixels. This will in- 1.134 + * turn cause a different generation ID value to be returned from 1.135 + * getGenerationID(). 1.136 + */ 1.137 + void notifyPixelsChanged(); 1.138 + 1.139 + /** 1.140 + * Change the info's AlphaType. Note that this does not automatically 1.141 + * invalidate the generation ID. If the pixel values themselves have 1.142 + * changed, then you must explicitly call notifyPixelsChanged() as well. 1.143 + */ 1.144 + void changeAlphaType(SkAlphaType at); 1.145 + 1.146 + /** Returns true if this pixelref is marked as immutable, meaning that the 1.147 + contents of its pixels will not change for the lifetime of the pixelref. 1.148 + */ 1.149 + bool isImmutable() const { return fIsImmutable; } 1.150 + 1.151 + /** Marks this pixelref is immutable, meaning that the contents of its 1.152 + pixels will not change for the lifetime of the pixelref. This state can 1.153 + be set on a pixelref, but it cannot be cleared once it is set. 1.154 + */ 1.155 + void setImmutable(); 1.156 + 1.157 + /** Return the optional URI string associated with this pixelref. May be 1.158 + null. 1.159 + */ 1.160 + const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; } 1.161 + 1.162 + /** Copy a URI string to this pixelref, or clear the URI if the uri is null 1.163 + */ 1.164 + void setURI(const char uri[]) { 1.165 + fURI.set(uri); 1.166 + } 1.167 + 1.168 + /** Copy a URI string to this pixelref 1.169 + */ 1.170 + void setURI(const char uri[], size_t len) { 1.171 + fURI.set(uri, len); 1.172 + } 1.173 + 1.174 + /** Assign a URI string to this pixelref. 1.175 + */ 1.176 + void setURI(const SkString& uri) { fURI = uri; } 1.177 + 1.178 + /** 1.179 + * If the pixelRef has an encoded (i.e. compressed) representation, 1.180 + * return a ref to its data. If the pixelRef 1.181 + * is uncompressed or otherwise does not have this form, return NULL. 1.182 + * 1.183 + * If non-null is returned, the caller is responsible for calling unref() 1.184 + * on the data when it is finished. 1.185 + */ 1.186 + SkData* refEncodedData() { 1.187 + return this->onRefEncodedData(); 1.188 + } 1.189 + 1.190 + /** 1.191 + * Experimental -- tells the caller if it is worth it to call decodeInto(). 1.192 + * Just an optimization at this point, to avoid checking the cache first. 1.193 + * We may remove/change this call in the future. 1.194 + */ 1.195 + bool implementsDecodeInto() { 1.196 + return this->onImplementsDecodeInto(); 1.197 + } 1.198 + 1.199 + /** 1.200 + * Return a decoded instance of this pixelRef in bitmap. If this cannot be 1.201 + * done, return false and the bitmap parameter is ignored/unchanged. 1.202 + * 1.203 + * pow2 is the requeste power-of-two downscale that the caller needs. This 1.204 + * can be ignored, and the "original" size can be returned, but if the 1.205 + * underlying codec can efficiently return a smaller size, that should be 1.206 + * done. Some examples: 1.207 + * 1.208 + * To request the "base" version (original scale), pass 0 for pow2 1.209 + * To request 1/2 scale version (1/2 width, 1/2 height), pass 1 for pow2 1.210 + * To request 1/4 scale version (1/4 width, 1/4 height), pass 2 for pow2 1.211 + * ... 1.212 + * 1.213 + * If this returns true, then bitmap must be "locked" such that 1.214 + * bitmap->getPixels() will return the correct address. 1.215 + */ 1.216 + bool decodeInto(int pow2, SkBitmap* bitmap) { 1.217 + SkASSERT(pow2 >= 0); 1.218 + return this->onDecodeInto(pow2, bitmap); 1.219 + } 1.220 + 1.221 + /** Are we really wrapping a texture instead of a bitmap? 1.222 + */ 1.223 + virtual GrTexture* getTexture() { return NULL; } 1.224 + 1.225 + bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL); 1.226 + 1.227 + /** 1.228 + * Makes a deep copy of this PixelRef, respecting the requested config. 1.229 + * @param config Desired config. 1.230 + * @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of 1.231 + * of this PixelRef. 1.232 + * @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could 1.233 + * not be created with the given config), or this PixelRef does not support deep 1.234 + * copies. 1.235 + */ 1.236 + virtual SkPixelRef* deepCopy(SkBitmap::Config config, const SkIRect* subset = NULL) { 1.237 + return NULL; 1.238 + } 1.239 + 1.240 +#ifdef SK_BUILD_FOR_ANDROID 1.241 + /** 1.242 + * Acquire a "global" ref on this object. 1.243 + * The default implementation just calls ref(), but subclasses can override 1.244 + * this method to implement additional behavior. 1.245 + */ 1.246 + virtual void globalRef(void* data=NULL); 1.247 + 1.248 + /** 1.249 + * Release a "global" ref on this object. 1.250 + * The default implementation just calls unref(), but subclasses can override 1.251 + * this method to implement additional behavior. 1.252 + */ 1.253 + virtual void globalUnref(); 1.254 +#endif 1.255 + 1.256 + SK_DEFINE_FLATTENABLE_TYPE(SkPixelRef) 1.257 + 1.258 + // Register a listener that may be called the next time our generation ID changes. 1.259 + // 1.260 + // We'll only call the listener if we're confident that we are the only SkPixelRef with this 1.261 + // generation ID. If our generation ID changes and we decide not to call the listener, we'll 1.262 + // never call it: you must add a new listener for each generation ID change. We also won't call 1.263 + // the listener when we're certain no one knows what our generation ID is. 1.264 + // 1.265 + // This can be used to invalidate caches keyed by SkPixelRef generation ID. 1.266 + struct GenIDChangeListener { 1.267 + virtual ~GenIDChangeListener() {} 1.268 + virtual void onChange() = 0; 1.269 + }; 1.270 + 1.271 + // Takes ownership of listener. 1.272 + void addGenIDChangeListener(GenIDChangeListener* listener); 1.273 + 1.274 +protected: 1.275 + /** 1.276 + * On success, returns true and fills out the LockRec for the pixels. On 1.277 + * failure returns false and ignores the LockRec parameter. 1.278 + * 1.279 + * The caller will have already acquired a mutex for thread safety, so this 1.280 + * method need not do that. 1.281 + */ 1.282 + virtual bool onNewLockPixels(LockRec*) = 0; 1.283 + 1.284 + /** 1.285 + * Balancing the previous successful call to onNewLockPixels. The locked 1.286 + * pixel address will no longer be referenced, so the subclass is free to 1.287 + * move or discard that memory. 1.288 + * 1.289 + * The caller will have already acquired a mutex for thread safety, so this 1.290 + * method need not do that. 1.291 + */ 1.292 + virtual void onUnlockPixels() = 0; 1.293 + 1.294 + /** Default impl returns true */ 1.295 + virtual bool onLockPixelsAreWritable() const; 1.296 + 1.297 + // returns false; 1.298 + virtual bool onImplementsDecodeInto(); 1.299 + // returns false; 1.300 + virtual bool onDecodeInto(int pow2, SkBitmap* bitmap); 1.301 + 1.302 + /** 1.303 + * For pixelrefs that don't have access to their raw pixels, they may be 1.304 + * able to make a copy of them (e.g. if the pixels are on the GPU). 1.305 + * 1.306 + * The base class implementation returns false; 1.307 + */ 1.308 + virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull); 1.309 + 1.310 + // default impl returns NULL. 1.311 + virtual SkData* onRefEncodedData(); 1.312 + 1.313 + /** 1.314 + * Returns the size (in bytes) of the internally allocated memory. 1.315 + * This should be implemented in all serializable SkPixelRef derived classes. 1.316 + * SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value, 1.317 + * otherwise the rendering code may attempt to read memory out of bounds. 1.318 + * 1.319 + * @return default impl returns 0. 1.320 + */ 1.321 + virtual size_t getAllocatedSizeInBytes() const; 1.322 + 1.323 + /** Return the mutex associated with this pixelref. This value is assigned 1.324 + in the constructor, and cannot change during the lifetime of the object. 1.325 + */ 1.326 + SkBaseMutex* mutex() const { return fMutex; } 1.327 + 1.328 + // serialization 1.329 + SkPixelRef(SkReadBuffer&, SkBaseMutex*); 1.330 + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; 1.331 + 1.332 + // only call from constructor. Flags this to always be locked, removing 1.333 + // the need to grab the mutex and call onLockPixels/onUnlockPixels. 1.334 + // Performance tweak to avoid those calls (esp. in multi-thread use case). 1.335 + void setPreLocked(void*, size_t rowBytes, SkColorTable*); 1.336 + 1.337 +private: 1.338 + SkBaseMutex* fMutex; // must remain in scope for the life of this object 1.339 + 1.340 + // mostly const. fInfo.fAlpahType can be changed at runtime. 1.341 + const SkImageInfo fInfo; 1.342 + 1.343 + // LockRec is only valid if we're in a locked state (isLocked()) 1.344 + LockRec fRec; 1.345 + int fLockCount; 1.346 + 1.347 + mutable uint32_t fGenerationID; 1.348 + mutable bool fUniqueGenerationID; 1.349 + 1.350 + SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned 1.351 + 1.352 + SkString fURI; 1.353 + 1.354 + // can go from false to true, but never from true to false 1.355 + bool fIsImmutable; 1.356 + // only ever set in constructor, const after that 1.357 + bool fPreLocked; 1.358 + 1.359 + void needsNewGenID(); 1.360 + void callGenIDChangeListeners(); 1.361 + 1.362 + void setMutex(SkBaseMutex* mutex); 1.363 + 1.364 + // When copying a bitmap to another with the same shape and config, we can safely 1.365 + // clone the pixelref generation ID too, which makes them equivalent under caching. 1.366 + friend class SkBitmap; // only for cloneGenID 1.367 + void cloneGenID(const SkPixelRef&); 1.368 + 1.369 + typedef SkFlattenable INHERITED; 1.370 +}; 1.371 + 1.372 +class SkPixelRefFactory : public SkRefCnt { 1.373 +public: 1.374 + /** 1.375 + * Allocate a new pixelref matching the specified ImageInfo, allocating 1.376 + * the memory for the pixels. If the ImageInfo requires a ColorTable, 1.377 + * the pixelref will ref() the colortable. 1.378 + * On failure return NULL. 1.379 + */ 1.380 + virtual SkPixelRef* create(const SkImageInfo&, SkColorTable*) = 0; 1.381 +}; 1.382 + 1.383 +#endif