3 * Copyright 2008 The Android Open Source Project
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
10 #ifndef SkPixelRef_DEFINED
11 #define SkPixelRef_DEFINED
16 #include "SkFlattenable.h"
17 #include "SkImageInfo.h"
18 #include "SkTDArray.h"
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.
29 * This build-flag disables that optimization, to add in debugging our
30 * call-sites, to ensure that they correctly balance their calls of
33 // #define SK_IGNORE_PIXELREF_SETPRELOCKED
45 This class is the smart container for pixel memory, and is used with
46 SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
47 access the actual pixel memory by calling lockPixels/unlockPixels.
49 This class can be shared/accessed between multiple threads.
51 class SK_API SkPixelRef : public SkFlattenable {
53 SK_DECLARE_INST_COUNT(SkPixelRef)
55 explicit SkPixelRef(const SkImageInfo&);
56 SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex);
57 virtual ~SkPixelRef();
59 const SkImageInfo& info() const {
63 /** Return the pixel memory returned from lockPixels, or null if the
66 void* pixels() const { return fRec.fPixels; }
68 /** Return the current colorTable (if any) if pixels are locked, or null.
70 SkColorTable* colorTable() const { return fRec.fColorTable; }
72 size_t rowBytes() const { return fRec.fRowBytes; }
75 * To access the actual pixels of a pixelref, it must be "locked".
76 * Calling lockPixels returns a LockRec struct (on success).
80 SkColorTable* fColorTable;
83 void zero() { sk_bzero(this, sizeof(*this)); }
86 return NULL == fPixels && NULL == fColorTable && 0 == fRowBytes;
91 * Returns true if the lockcount > 0
93 bool isLocked() const { return fLockCount > 0; }
95 SkDEBUGCODE(int getLockCount() const { return fLockCount; })
98 * Call to access the pixel memory. Return true on success. Balance this
99 * with a call to unlockPixels().
104 * Call to access the pixel memory. On success, return true and fill out
105 * the specified rec. On failure, return false and ignore the rec parameter.
106 * Balance this with a call to unlockPixels().
108 bool lockPixels(LockRec* rec);
110 /** Call to balanace a previous call to lockPixels(). Returns the pixels
111 (or null) after the unlock. NOTE: lock calls can be nested, but the
112 matching number of unlock calls must be made in order to free the
113 memory (if the subclass implements caching/deferred-decoding.)
118 * Some bitmaps can return a copy of their pixels for lockPixels(), but
119 * that copy, if modified, will not be pushed back. These bitmaps should
120 * not be used as targets for a raster device/canvas (since all pixels
121 * modifications will be lost when unlockPixels() is called.)
123 bool lockPixelsAreWritable() const;
125 /** Returns a non-zero, unique value corresponding to the pixels in this
126 pixelref. Each time the pixels are changed (and notifyPixelsChanged is
127 called), a different generation ID will be returned.
129 uint32_t getGenerationID() const;
131 /** Call this if you have changed the contents of the pixels. This will in-
132 turn cause a different generation ID value to be returned from
135 void notifyPixelsChanged();
137 /** Returns true if this pixelref is marked as immutable, meaning that the
138 contents of its pixels will not change for the lifetime of the pixelref.
140 bool isImmutable() const { return fIsImmutable; }
142 /** Marks this pixelref is immutable, meaning that the contents of its
143 pixels will not change for the lifetime of the pixelref. This state can
144 be set on a pixelref, but it cannot be cleared once it is set.
148 /** Return the optional URI string associated with this pixelref. May be
151 const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
153 /** Copy a URI string to this pixelref, or clear the URI if the uri is null
155 void setURI(const char uri[]) {
159 /** Copy a URI string to this pixelref
161 void setURI(const char uri[], size_t len) {
165 /** Assign a URI string to this pixelref.
167 void setURI(const SkString& uri) { fURI = uri; }
170 * If the pixelRef has an encoded (i.e. compressed) representation,
171 * return a ref to its data. If the pixelRef
172 * is uncompressed or otherwise does not have this form, return NULL.
174 * If non-null is returned, the caller is responsible for calling unref()
175 * on the data when it is finished.
177 SkData* refEncodedData() {
178 return this->onRefEncodedData();
182 * Experimental -- tells the caller if it is worth it to call decodeInto().
183 * Just an optimization at this point, to avoid checking the cache first.
184 * We may remove/change this call in the future.
186 bool implementsDecodeInto() {
187 return this->onImplementsDecodeInto();
191 * Return a decoded instance of this pixelRef in bitmap. If this cannot be
192 * done, return false and the bitmap parameter is ignored/unchanged.
194 * pow2 is the requeste power-of-two downscale that the caller needs. This
195 * can be ignored, and the "original" size can be returned, but if the
196 * underlying codec can efficiently return a smaller size, that should be
197 * done. Some examples:
199 * To request the "base" version (original scale), pass 0 for pow2
200 * To request 1/2 scale version (1/2 width, 1/2 height), pass 1 for pow2
201 * To request 1/4 scale version (1/4 width, 1/4 height), pass 2 for pow2
204 * If this returns true, then bitmap must be "locked" such that
205 * bitmap->getPixels() will return the correct address.
207 bool decodeInto(int pow2, SkBitmap* bitmap) {
209 return this->onDecodeInto(pow2, bitmap);
212 /** Are we really wrapping a texture instead of a bitmap?
214 virtual GrTexture* getTexture() { return NULL; }
216 bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
219 * Makes a deep copy of this PixelRef, respecting the requested config.
220 * @param config Desired config.
221 * @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
223 * @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
224 * not be created with the given config), or this PixelRef does not support deep
227 virtual SkPixelRef* deepCopy(SkBitmap::Config config, const SkIRect* subset = NULL) {
231 #ifdef SK_BUILD_FOR_ANDROID
233 * Acquire a "global" ref on this object.
234 * The default implementation just calls ref(), but subclasses can override
235 * this method to implement additional behavior.
237 virtual void globalRef(void* data=NULL);
240 * Release a "global" ref on this object.
241 * The default implementation just calls unref(), but subclasses can override
242 * this method to implement additional behavior.
244 virtual void globalUnref();
247 SK_DEFINE_FLATTENABLE_TYPE(SkPixelRef)
249 // Register a listener that may be called the next time our generation ID changes.
251 // We'll only call the listener if we're confident that we are the only SkPixelRef with this
252 // generation ID. If our generation ID changes and we decide not to call the listener, we'll
253 // never call it: you must add a new listener for each generation ID change. We also won't call
254 // the listener when we're certain no one knows what our generation ID is.
256 // This can be used to invalidate caches keyed by SkPixelRef generation ID.
257 struct GenIDChangeListener {
258 virtual ~GenIDChangeListener() {}
259 virtual void onChange() = 0;
262 // Takes ownership of listener.
263 void addGenIDChangeListener(GenIDChangeListener* listener);
266 #ifdef SK_SUPPORT_LEGACY_ONLOCKPIXELS
267 virtual void* onLockPixels(SkColorTable**);
268 virtual bool onNewLockPixels(LockRec*);
271 * On success, returns true and fills out the LockRec for the pixels. On
272 * failure returns false and ignores the LockRec parameter.
274 * The caller will have already acquired a mutex for thread safety, so this
275 * method need not do that.
277 virtual bool onNewLockPixels(LockRec*) = 0;
281 * Balancing the previous successful call to onNewLockPixels. The locked
282 * pixel address will no longer be referenced, so the subclass is free to
283 * move or discard that memory.
285 * The caller will have already acquired a mutex for thread safety, so this
286 * method need not do that.
288 virtual void onUnlockPixels() = 0;
290 /** Default impl returns true */
291 virtual bool onLockPixelsAreWritable() const;
294 virtual bool onImplementsDecodeInto();
296 virtual bool onDecodeInto(int pow2, SkBitmap* bitmap);
299 * For pixelrefs that don't have access to their raw pixels, they may be
300 * able to make a copy of them (e.g. if the pixels are on the GPU).
302 * The base class implementation returns false;
304 virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull);
306 // default impl returns NULL.
307 virtual SkData* onRefEncodedData();
310 * Returns the size (in bytes) of the internally allocated memory.
311 * This should be implemented in all serializable SkPixelRef derived classes.
312 * SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value,
313 * otherwise the rendering code may attempt to read memory out of bounds.
315 * @return default impl returns 0.
317 virtual size_t getAllocatedSizeInBytes() const;
319 /** Return the mutex associated with this pixelref. This value is assigned
320 in the constructor, and cannot change during the lifetime of the object.
322 SkBaseMutex* mutex() const { return fMutex; }
325 SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
326 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
328 // only call from constructor. Flags this to always be locked, removing
329 // the need to grab the mutex and call onLockPixels/onUnlockPixels.
330 // Performance tweak to avoid those calls (esp. in multi-thread use case).
331 void setPreLocked(void*, size_t rowBytes, SkColorTable*);
334 SkBaseMutex* fMutex; // must remain in scope for the life of this object
336 const SkImageInfo fInfo;
338 // LockRec is only valid if we're in a locked state (isLocked())
342 mutable uint32_t fGenerationID;
343 mutable bool fUniqueGenerationID;
345 SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned
349 // can go from false to true, but never from true to false
351 // only ever set in constructor, const after that
354 void needsNewGenID();
355 void callGenIDChangeListeners();
357 void setMutex(SkBaseMutex* mutex);
359 // When copying a bitmap to another with the same shape and config, we can safely
360 // clone the pixelref generation ID too, which makes them equivalent under caching.
361 friend class SkBitmap; // only for cloneGenID
362 void cloneGenID(const SkPixelRef&);
364 typedef SkFlattenable INHERITED;
367 class SkPixelRefFactory : public SkRefCnt {
370 * Allocate a new pixelref matching the specified ImageInfo, allocating
371 * the memory for the pixels. If the ImageInfo requires a ColorTable,
372 * the pixelref will ref() the colortable.
373 * On failure return NULL.
375 virtual SkPixelRef* create(const SkImageInfo&, SkColorTable*) = 0;