blob: d4c35323bbf3b713e22ac79d2ec7fb73026e2c9c [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2008 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkPixelRef_DEFINED
11#define SkPixelRef_DEFINED
12
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000013#include "SkBitmap.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014#include "SkRefCnt.h"
15#include "SkString.h"
djsollen@google.com5370cd92012-03-28 20:47:01 +000016#include "SkFlattenable.h"
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000017#include "SkTDArray.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000018
reed@google.com398337b2013-12-11 21:22:39 +000019#define SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR
reed@google.comf1715702013-12-06 22:07:17 +000020
reed@google.com2a3f08b2012-12-13 21:41:00 +000021#ifdef SK_DEBUG
22 /**
23 * Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref
24 * subclasses to correctly handle lock/unlock pixels. For performance
25 * reasons, simple malloc-based subclasses call setPreLocked() to skip
26 * the overhead of implementing these calls.
27 *
28 * This build-flag disables that optimization, to add in debugging our
29 * call-sites, to ensure that they correctly balance their calls of
30 * lock and unlock.
31 */
32// #define SK_IGNORE_PIXELREF_SETPRELOCKED
33#endif
34
reed@android.com8a1c16f2008-12-17 15:59:43 +000035class SkColorTable;
reed@google.comeb776122012-12-06 14:26:02 +000036class SkData;
reed@google.com50dfa012011-04-01 19:05:36 +000037struct SkIRect;
reed@android.com8a1c16f2008-12-17 15:59:43 +000038class SkMutex;
reed@android.com8a1c16f2008-12-17 15:59:43 +000039
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +000040class GrTexture;
reed@android.comce4e53a2010-09-09 16:01:26 +000041
reed@android.com8a1c16f2008-12-17 15:59:43 +000042/** \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*/
djsollen@google.com5370cd92012-03-28 20:47:01 +000050class SK_API SkPixelRef : public SkFlattenable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000051public:
robertphillips@google.com0456e0b2012-06-27 14:03:26 +000052 SK_DECLARE_INST_COUNT(SkPixelRef)
53
reed@google.comf1715702013-12-06 22:07:17 +000054#ifdef SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR
55 // DEPRECATED -- use a constructor that takes SkImageInfo
reed@google.com2ebc10d2013-12-06 21:43:05 +000056 explicit SkPixelRef(SkBaseMutex* mutex = NULL);
reed@google.comf1715702013-12-06 22:07:17 +000057#endif
58
59 explicit SkPixelRef(const SkImageInfo&);
reed@google.comb0eb1022013-12-06 22:16:10 +000060 SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex);
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000061 virtual ~SkPixelRef();
reed@google.com93c5f9e2011-02-24 18:09:46 +000062
reed@google.com9230ea22013-12-09 22:01:03 +000063 const SkImageInfo& info() const {
64 return fInfo;
65 }
66
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 /** Return the pixel memory returned from lockPixels, or null if the
68 lockCount is 0.
69 */
reed@google.com398337b2013-12-11 21:22:39 +000070 void* pixels() const { return fPixels; }
reed@android.com8a1c16f2008-12-17 15:59:43 +000071
72 /** Return the current colorTable (if any) if pixels are locked, or null.
73 */
reed@google.com398337b2013-12-11 21:22:39 +000074 SkColorTable* colorTable() const { return fColorTable; }
reed@android.com8a1c16f2008-12-17 15:59:43 +000075
reed@google.comff0da4f2012-05-17 13:14:52 +000076 /**
77 * Returns true if the lockcount > 0
78 */
79 bool isLocked() const { return fLockCount > 0; }
reed@android.com8a1c16f2008-12-17 15:59:43 +000080
reed@google.comea033602012-12-14 13:13:55 +000081 SkDEBUGCODE(int getLockCount() const { return fLockCount; })
82
reed@google.com398337b2013-12-11 21:22:39 +000083 /** Call to access the pixel memory, which is returned. Balance with a call
84 to unlockPixels().
85 */
86 void lockPixels();
reed@android.com8a1c16f2008-12-17 15:59:43 +000087 /** Call to balanace a previous call to lockPixels(). Returns the pixels
88 (or null) after the unlock. NOTE: lock calls can be nested, but the
89 matching number of unlock calls must be made in order to free the
90 memory (if the subclass implements caching/deferred-decoding.)
91 */
92 void unlockPixels();
reed@google.com93c5f9e2011-02-24 18:09:46 +000093
reed@google.com9c49bc32011-07-07 13:42:37 +000094 /**
95 * Some bitmaps can return a copy of their pixels for lockPixels(), but
96 * that copy, if modified, will not be pushed back. These bitmaps should
97 * not be used as targets for a raster device/canvas (since all pixels
98 * modifications will be lost when unlockPixels() is called.)
99 */
100 bool lockPixelsAreWritable() const;
101
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102 /** Returns a non-zero, unique value corresponding to the pixels in this
103 pixelref. Each time the pixels are changed (and notifyPixelsChanged is
104 called), a different generation ID will be returned.
105 */
106 uint32_t getGenerationID() const;
reed@google.com93c5f9e2011-02-24 18:09:46 +0000107
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108 /** Call this if you have changed the contents of the pixels. This will in-
109 turn cause a different generation ID value to be returned from
110 getGenerationID().
111 */
112 void notifyPixelsChanged();
113
114 /** Returns true if this pixelref is marked as immutable, meaning that the
115 contents of its pixels will not change for the lifetime of the pixelref.
116 */
117 bool isImmutable() const { return fIsImmutable; }
reed@google.com93c5f9e2011-02-24 18:09:46 +0000118
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119 /** Marks this pixelref is immutable, meaning that the contents of its
120 pixels will not change for the lifetime of the pixelref. This state can
121 be set on a pixelref, but it cannot be cleared once it is set.
122 */
123 void setImmutable();
124
125 /** Return the optional URI string associated with this pixelref. May be
126 null.
127 */
128 const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
129
130 /** Copy a URI string to this pixelref, or clear the URI if the uri is null
131 */
132 void setURI(const char uri[]) {
133 fURI.set(uri);
134 }
reed@google.com93c5f9e2011-02-24 18:09:46 +0000135
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136 /** Copy a URI string to this pixelref
137 */
138 void setURI(const char uri[], size_t len) {
139 fURI.set(uri, len);
140 }
reed@google.com93c5f9e2011-02-24 18:09:46 +0000141
reed@android.com8a1c16f2008-12-17 15:59:43 +0000142 /** Assign a URI string to this pixelref.
143 */
144 void setURI(const SkString& uri) { fURI = uri; }
145
reed@google.comeb776122012-12-06 14:26:02 +0000146 /**
147 * If the pixelRef has an encoded (i.e. compressed) representation,
148 * return a ref to its data. If the pixelRef
149 * is uncompressed or otherwise does not have this form, return NULL.
150 *
151 * If non-null is returned, the caller is responsible for calling unref()
152 * on the data when it is finished.
153 */
154 SkData* refEncodedData() {
155 return this->onRefEncodedData();
156 }
157
reed@google.comcee9dcb2013-09-13 16:04:49 +0000158 /**
159 * Experimental -- tells the caller if it is worth it to call decodeInto().
160 * Just an optimization at this point, to avoid checking the cache first.
161 * We may remove/change this call in the future.
162 */
163 bool implementsDecodeInto() {
164 return this->onImplementsDecodeInto();
165 }
166
167 /**
168 * Return a decoded instance of this pixelRef in bitmap. If this cannot be
169 * done, return false and the bitmap parameter is ignored/unchanged.
170 *
171 * pow2 is the requeste power-of-two downscale that the caller needs. This
172 * can be ignored, and the "original" size can be returned, but if the
173 * underlying codec can efficiently return a smaller size, that should be
174 * done. Some examples:
175 *
176 * To request the "base" version (original scale), pass 0 for pow2
177 * To request 1/2 scale version (1/2 width, 1/2 height), pass 1 for pow2
178 * To request 1/4 scale version (1/4 width, 1/4 height), pass 2 for pow2
179 * ...
180 *
181 * If this returns true, then bitmap must be "locked" such that
182 * bitmap->getPixels() will return the correct address.
183 */
184 bool decodeInto(int pow2, SkBitmap* bitmap) {
185 SkASSERT(pow2 >= 0);
186 return this->onDecodeInto(pow2, bitmap);
187 }
188
reed@android.comce4e53a2010-09-09 16:01:26 +0000189 /** Are we really wrapping a texture instead of a bitmap?
190 */
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000191 virtual GrTexture* getTexture() { return NULL; }
reed@android.comce4e53a2010-09-09 16:01:26 +0000192
reed@google.com50dfa012011-04-01 19:05:36 +0000193 bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
194
scroggo@google.coma2a31922012-12-07 19:14:45 +0000195 /**
196 * Makes a deep copy of this PixelRef, respecting the requested config.
197 * @param config Desired config.
198 * @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
199 * of this PixelRef.
200 * @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
201 * not be created with the given config), or this PixelRef does not support deep
202 * copies.
203 */
204 virtual SkPixelRef* deepCopy(SkBitmap::Config config, const SkIRect* subset = NULL) {
205 return NULL;
206 }
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000207
djsollen@google.com56c69772011-11-08 19:00:26 +0000208#ifdef SK_BUILD_FOR_ANDROID
reed@google.com93c5f9e2011-02-24 18:09:46 +0000209 /**
210 * Acquire a "global" ref on this object.
211 * The default implementation just calls ref(), but subclasses can override
212 * this method to implement additional behavior.
213 */
djsollen@google.com57f49692011-02-23 20:46:31 +0000214 virtual void globalRef(void* data=NULL);
215
reed@google.com93c5f9e2011-02-24 18:09:46 +0000216 /**
217 * Release a "global" ref on this object.
218 * The default implementation just calls unref(), but subclasses can override
219 * this method to implement additional behavior.
220 */
djsollen@google.com57f49692011-02-23 20:46:31 +0000221 virtual void globalUnref();
reed@google.com93c5f9e2011-02-24 18:09:46 +0000222#endif
djsollen@google.com57f49692011-02-23 20:46:31 +0000223
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000224 SK_DEFINE_FLATTENABLE_TYPE(SkPixelRef)
225
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000226 // Register a listener that may be called the next time our generation ID changes.
227 //
228 // We'll only call the listener if we're confident that we are the only SkPixelRef with this
229 // generation ID. If our generation ID changes and we decide not to call the listener, we'll
230 // never call it: you must add a new listener for each generation ID change. We also won't call
231 // the listener when we're certain no one knows what our generation ID is.
232 //
233 // This can be used to invalidate caches keyed by SkPixelRef generation ID.
234 struct GenIDChangeListener {
235 virtual ~GenIDChangeListener() {}
236 virtual void onChange() = 0;
237 };
238
239 // Takes ownership of listener.
240 void addGenIDChangeListener(GenIDChangeListener* listener);
241
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242protected:
reed@google.com398337b2013-12-11 21:22:39 +0000243 /** Called when the lockCount goes from 0 to 1. The caller will have already
244 acquire a mutex for thread safety, so this method need not do that.
245 */
246 virtual void* onLockPixels(SkColorTable**) = 0;
reed@google.com772d8522013-12-12 16:27:12 +0000247
248 /**
249 * Called when the lock count goes from 1 to 0. The caller will have
250 * already acquire a mutex for thread safety, so this method need not do
251 * that.
252 *
253 * If the previous call to onLockPixels failed (i.e. returned NULL), then
254 * the onUnlockPixels will NOT be called.
255 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256 virtual void onUnlockPixels() = 0;
257
reed@google.com9c49bc32011-07-07 13:42:37 +0000258 /** Default impl returns true */
259 virtual bool onLockPixelsAreWritable() const;
260
reed@google.comcee9dcb2013-09-13 16:04:49 +0000261 // returns false;
262 virtual bool onImplementsDecodeInto();
263 // returns false;
264 virtual bool onDecodeInto(int pow2, SkBitmap* bitmap);
265
reed@google.com50dfa012011-04-01 19:05:36 +0000266 /**
267 * For pixelrefs that don't have access to their raw pixels, they may be
268 * able to make a copy of them (e.g. if the pixels are on the GPU).
269 *
270 * The base class implementation returns false;
271 */
272 virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull);
273
reed@google.comeb776122012-12-06 14:26:02 +0000274 // default impl returns NULL.
275 virtual SkData* onRefEncodedData();
276
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000277 /**
278 * Returns the size (in bytes) of the internally allocated memory.
279 * This should be implemented in all serializable SkPixelRef derived classes.
280 * SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value,
281 * otherwise the rendering code may attempt to read memory out of bounds.
282 *
283 * @return default impl returns 0.
284 */
285 virtual size_t getAllocatedSizeInBytes() const;
286
reed@android.com8a1c16f2008-12-17 15:59:43 +0000287 /** Return the mutex associated with this pixelref. This value is assigned
288 in the constructor, and cannot change during the lifetime of the object.
289 */
digit@google.com1771cbf2012-01-26 21:26:40 +0000290 SkBaseMutex* mutex() const { return fMutex; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000291
djsollen@google.com54924242012-03-29 15:18:04 +0000292 // serialization
digit@google.com1771cbf2012-01-26 21:26:40 +0000293 SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
djsollen@google.com54924242012-03-29 15:18:04 +0000294 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000295
reed@google.comff0da4f2012-05-17 13:14:52 +0000296 // only call from constructor. Flags this to always be locked, removing
297 // the need to grab the mutex and call onLockPixels/onUnlockPixels.
298 // Performance tweak to avoid those calls (esp. in multi-thread use case).
reed@google.com398337b2013-12-11 21:22:39 +0000299 void setPreLocked(void* pixels, SkColorTable* ctable);
reed@google.comff0da4f2012-05-17 13:14:52 +0000300
reed@android.com8a1c16f2008-12-17 15:59:43 +0000301private:
digit@google.com1771cbf2012-01-26 21:26:40 +0000302 SkBaseMutex* fMutex; // must remain in scope for the life of this object
scroggo@google.com728f2a62013-12-12 15:19:30 +0000303 // FIXME: fInfo should be const once we remove old constructor that does
304 // not set it.
reed@google.com9230ea22013-12-09 22:01:03 +0000305 SkImageInfo fInfo;
reed@google.com398337b2013-12-11 21:22:39 +0000306
307 void* fPixels;
308 SkColorTable* fColorTable; // we do not track ownership, subclass does
reed@android.com8a1c16f2008-12-17 15:59:43 +0000309 int fLockCount;
reed@google.com93c5f9e2011-02-24 18:09:46 +0000310
reed@android.com8a1c16f2008-12-17 15:59:43 +0000311 mutable uint32_t fGenerationID;
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000312 mutable bool fUniqueGenerationID;
reed@google.com93c5f9e2011-02-24 18:09:46 +0000313
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000314 SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned
scroggo@google.comd5764e82012-08-22 15:00:05 +0000315
reed@android.com8a1c16f2008-12-17 15:59:43 +0000316 SkString fURI;
317
318 // can go from false to true, but never from true to false
319 bool fIsImmutable;
reed@google.comff0da4f2012-05-17 13:14:52 +0000320 // only ever set in constructor, const after that
321 bool fPreLocked;
322
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000323 void needsNewGenID();
324 void callGenIDChangeListeners();
325
reed@google.comff0da4f2012-05-17 13:14:52 +0000326 void setMutex(SkBaseMutex* mutex);
caryclark@google.com9d0c6ec2011-12-20 20:26:56 +0000327
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000328 // When copying a bitmap to another with the same shape and config, we can safely
329 // clone the pixelref generation ID too, which makes them equivalent under caching.
330 friend class SkBitmap; // only for cloneGenID
331 void cloneGenID(const SkPixelRef&);
332
djsollen@google.com5370cd92012-03-28 20:47:01 +0000333 typedef SkFlattenable INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000334};
335
336#endif