blob: a332b76a5dab84f4c2c0e8df5adb50ad2ed0414f [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"
reed@google.com92713892014-01-03 17:58:57 +000017#include "SkImageInfo.h"
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000018#include "SkTDArray.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000019
reed@google.com92713892014-01-03 17:58:57 +000020//#define SK_SUPPORT_LEGACY_ONLOCKPIXELS
21
reed@google.com2a3f08b2012-12-13 21:41:00 +000022#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
reed@android.com8a1c16f2008-12-17 15:59:43 +000036class SkColorTable;
reed@google.comeb776122012-12-06 14:26:02 +000037class SkData;
reed@google.com50dfa012011-04-01 19:05:36 +000038struct SkIRect;
reed@android.com8a1c16f2008-12-17 15:59:43 +000039class SkMutex;
reed@android.com8a1c16f2008-12-17 15:59:43 +000040
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +000041class GrTexture;
reed@android.comce4e53a2010-09-09 16:01:26 +000042
reed@android.com8a1c16f2008-12-17 15:59:43 +000043/** \class SkPixelRef
44
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.
48
49 This class can be shared/accessed between multiple threads.
50*/
djsollen@google.com5370cd92012-03-28 20:47:01 +000051class SK_API SkPixelRef : public SkFlattenable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000052public:
robertphillips@google.com0456e0b2012-06-27 14:03:26 +000053 SK_DECLARE_INST_COUNT(SkPixelRef)
54
reed@google.comf1715702013-12-06 22:07:17 +000055 explicit SkPixelRef(const SkImageInfo&);
reed@google.comb0eb1022013-12-06 22:16:10 +000056 SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex);
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000057 virtual ~SkPixelRef();
reed@google.com93c5f9e2011-02-24 18:09:46 +000058
reed@google.com9230ea22013-12-09 22:01:03 +000059 const SkImageInfo& info() const {
60 return fInfo;
61 }
62
reed@android.com8a1c16f2008-12-17 15:59:43 +000063 /** Return the pixel memory returned from lockPixels, or null if the
64 lockCount is 0.
65 */
reed@google.com92713892014-01-03 17:58:57 +000066 void* pixels() const { return fRec.fPixels; }
reed@android.com8a1c16f2008-12-17 15:59:43 +000067
68 /** Return the current colorTable (if any) if pixels are locked, or null.
69 */
reed@google.com92713892014-01-03 17:58:57 +000070 SkColorTable* colorTable() const { return fRec.fColorTable; }
reed@android.com8a1c16f2008-12-17 15:59:43 +000071
reed@google.comff0da4f2012-05-17 13:14:52 +000072 /**
reed@google.com92713892014-01-03 17:58:57 +000073 * To access the actual pixels of a pixelref, it must be "locked".
74 * Calling lockPixels returns a LockRec struct (on success).
75 */
76 struct LockRec {
77 void* fPixels;
78 SkColorTable* fColorTable;
79 size_t fRowBytes;
80
81 void zero() { sk_bzero(this, sizeof(*this)); }
82
83 bool isZero() const {
84 return NULL == fPixels && NULL == fColorTable && 0 == fRowBytes;
85 }
86 };
87
88 /**
reed@google.comff0da4f2012-05-17 13:14:52 +000089 * Returns true if the lockcount > 0
90 */
91 bool isLocked() const { return fLockCount > 0; }
reed@android.com8a1c16f2008-12-17 15:59:43 +000092
reed@google.comea033602012-12-14 13:13:55 +000093 SkDEBUGCODE(int getLockCount() const { return fLockCount; })
94
reed@google.com92713892014-01-03 17:58:57 +000095 /**
96 * Call to access the pixel memory. Return true on success. Balance this
97 * with a call to unlockPixels().
98 */
99 bool lockPixels();
100
101 /**
102 * Call to access the pixel memory. On success, return true and fill out
103 * the specified rec. On failure, return false and ignore the rec parameter.
104 * Balance this with a call to unlockPixels().
105 */
106 bool lockPixels(LockRec* rec);
107
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108 /** Call to balanace a previous call to lockPixels(). Returns the pixels
109 (or null) after the unlock. NOTE: lock calls can be nested, but the
110 matching number of unlock calls must be made in order to free the
111 memory (if the subclass implements caching/deferred-decoding.)
112 */
113 void unlockPixels();
reed@google.com93c5f9e2011-02-24 18:09:46 +0000114
reed@google.com9c49bc32011-07-07 13:42:37 +0000115 /**
116 * Some bitmaps can return a copy of their pixels for lockPixels(), but
117 * that copy, if modified, will not be pushed back. These bitmaps should
118 * not be used as targets for a raster device/canvas (since all pixels
119 * modifications will be lost when unlockPixels() is called.)
120 */
121 bool lockPixelsAreWritable() const;
122
reed@android.com8a1c16f2008-12-17 15:59:43 +0000123 /** Returns a non-zero, unique value corresponding to the pixels in this
124 pixelref. Each time the pixels are changed (and notifyPixelsChanged is
125 called), a different generation ID will be returned.
126 */
127 uint32_t getGenerationID() const;
reed@google.com93c5f9e2011-02-24 18:09:46 +0000128
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129 /** Call this if you have changed the contents of the pixels. This will in-
130 turn cause a different generation ID value to be returned from
131 getGenerationID().
132 */
133 void notifyPixelsChanged();
134
135 /** Returns true if this pixelref is marked as immutable, meaning that the
136 contents of its pixels will not change for the lifetime of the pixelref.
137 */
138 bool isImmutable() const { return fIsImmutable; }
reed@google.com93c5f9e2011-02-24 18:09:46 +0000139
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140 /** Marks this pixelref is immutable, meaning that the contents of its
141 pixels will not change for the lifetime of the pixelref. This state can
142 be set on a pixelref, but it cannot be cleared once it is set.
143 */
144 void setImmutable();
145
146 /** Return the optional URI string associated with this pixelref. May be
147 null.
148 */
149 const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
150
151 /** Copy a URI string to this pixelref, or clear the URI if the uri is null
152 */
153 void setURI(const char uri[]) {
154 fURI.set(uri);
155 }
reed@google.com93c5f9e2011-02-24 18:09:46 +0000156
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157 /** Copy a URI string to this pixelref
158 */
159 void setURI(const char uri[], size_t len) {
160 fURI.set(uri, len);
161 }
reed@google.com93c5f9e2011-02-24 18:09:46 +0000162
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163 /** Assign a URI string to this pixelref.
164 */
165 void setURI(const SkString& uri) { fURI = uri; }
166
reed@google.comeb776122012-12-06 14:26:02 +0000167 /**
168 * If the pixelRef has an encoded (i.e. compressed) representation,
169 * return a ref to its data. If the pixelRef
170 * is uncompressed or otherwise does not have this form, return NULL.
171 *
172 * If non-null is returned, the caller is responsible for calling unref()
173 * on the data when it is finished.
174 */
175 SkData* refEncodedData() {
176 return this->onRefEncodedData();
177 }
178
reed@google.comcee9dcb2013-09-13 16:04:49 +0000179 /**
180 * Experimental -- tells the caller if it is worth it to call decodeInto().
181 * Just an optimization at this point, to avoid checking the cache first.
182 * We may remove/change this call in the future.
183 */
184 bool implementsDecodeInto() {
185 return this->onImplementsDecodeInto();
186 }
187
188 /**
189 * Return a decoded instance of this pixelRef in bitmap. If this cannot be
190 * done, return false and the bitmap parameter is ignored/unchanged.
191 *
192 * pow2 is the requeste power-of-two downscale that the caller needs. This
193 * can be ignored, and the "original" size can be returned, but if the
194 * underlying codec can efficiently return a smaller size, that should be
195 * done. Some examples:
196 *
197 * To request the "base" version (original scale), pass 0 for pow2
198 * To request 1/2 scale version (1/2 width, 1/2 height), pass 1 for pow2
199 * To request 1/4 scale version (1/4 width, 1/4 height), pass 2 for pow2
200 * ...
201 *
202 * If this returns true, then bitmap must be "locked" such that
203 * bitmap->getPixels() will return the correct address.
204 */
205 bool decodeInto(int pow2, SkBitmap* bitmap) {
206 SkASSERT(pow2 >= 0);
207 return this->onDecodeInto(pow2, bitmap);
208 }
209
reed@android.comce4e53a2010-09-09 16:01:26 +0000210 /** Are we really wrapping a texture instead of a bitmap?
211 */
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000212 virtual GrTexture* getTexture() { return NULL; }
reed@android.comce4e53a2010-09-09 16:01:26 +0000213
reed@google.com50dfa012011-04-01 19:05:36 +0000214 bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
215
scroggo@google.coma2a31922012-12-07 19:14:45 +0000216 /**
217 * Makes a deep copy of this PixelRef, respecting the requested config.
218 * @param config Desired config.
219 * @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
220 * of this PixelRef.
221 * @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
222 * not be created with the given config), or this PixelRef does not support deep
223 * copies.
224 */
225 virtual SkPixelRef* deepCopy(SkBitmap::Config config, const SkIRect* subset = NULL) {
226 return NULL;
227 }
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000228
djsollen@google.com56c69772011-11-08 19:00:26 +0000229#ifdef SK_BUILD_FOR_ANDROID
reed@google.com93c5f9e2011-02-24 18:09:46 +0000230 /**
231 * Acquire a "global" ref on this object.
232 * The default implementation just calls ref(), but subclasses can override
233 * this method to implement additional behavior.
234 */
djsollen@google.com57f49692011-02-23 20:46:31 +0000235 virtual void globalRef(void* data=NULL);
236
reed@google.com93c5f9e2011-02-24 18:09:46 +0000237 /**
238 * Release a "global" ref on this object.
239 * The default implementation just calls unref(), but subclasses can override
240 * this method to implement additional behavior.
241 */
djsollen@google.com57f49692011-02-23 20:46:31 +0000242 virtual void globalUnref();
reed@google.com93c5f9e2011-02-24 18:09:46 +0000243#endif
djsollen@google.com57f49692011-02-23 20:46:31 +0000244
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000245 SK_DEFINE_FLATTENABLE_TYPE(SkPixelRef)
246
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000247 // Register a listener that may be called the next time our generation ID changes.
248 //
249 // We'll only call the listener if we're confident that we are the only SkPixelRef with this
250 // generation ID. If our generation ID changes and we decide not to call the listener, we'll
251 // never call it: you must add a new listener for each generation ID change. We also won't call
252 // the listener when we're certain no one knows what our generation ID is.
253 //
254 // This can be used to invalidate caches keyed by SkPixelRef generation ID.
255 struct GenIDChangeListener {
256 virtual ~GenIDChangeListener() {}
257 virtual void onChange() = 0;
258 };
259
260 // Takes ownership of listener.
261 void addGenIDChangeListener(GenIDChangeListener* listener);
262
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263protected:
reed@google.com92713892014-01-03 17:58:57 +0000264#ifdef SK_SUPPORT_LEGACY_ONLOCKPIXELS
265 virtual void* onLockPixels(SkColorTable**);
266 virtual bool onNewLockPixels(LockRec*);
267#else
268 /**
269 * On success, returns true and fills out the LockRec for the pixels. On
270 * failure returns false and ignores the LockRec parameter.
271 *
272 * The caller will have already acquired a mutex for thread safety, so this
273 * method need not do that.
274 */
275 virtual bool onNewLockPixels(LockRec*) = 0;
276#endif
skia.committer@gmail.com96f5fa02013-12-16 07:01:40 +0000277
reed@google.comc83a91f2013-12-13 13:41:14 +0000278 /**
reed@google.com92713892014-01-03 17:58:57 +0000279 * Balancing the previous successful call to onNewLockPixels. The locked
280 * pixel address will no longer be referenced, so the subclass is free to
281 * move or discard that memory.
reed@google.comc83a91f2013-12-13 13:41:14 +0000282 *
reed@google.com92713892014-01-03 17:58:57 +0000283 * The caller will have already acquired a mutex for thread safety, so this
284 * method need not do that.
reed@google.comc83a91f2013-12-13 13:41:14 +0000285 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000286 virtual void onUnlockPixels() = 0;
287
reed@google.com9c49bc32011-07-07 13:42:37 +0000288 /** Default impl returns true */
289 virtual bool onLockPixelsAreWritable() const;
290
reed@google.comcee9dcb2013-09-13 16:04:49 +0000291 // returns false;
292 virtual bool onImplementsDecodeInto();
293 // returns false;
294 virtual bool onDecodeInto(int pow2, SkBitmap* bitmap);
295
reed@google.com50dfa012011-04-01 19:05:36 +0000296 /**
297 * For pixelrefs that don't have access to their raw pixels, they may be
298 * able to make a copy of them (e.g. if the pixels are on the GPU).
299 *
300 * The base class implementation returns false;
301 */
302 virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull);
303
reed@google.comeb776122012-12-06 14:26:02 +0000304 // default impl returns NULL.
305 virtual SkData* onRefEncodedData();
306
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000307 /**
308 * Returns the size (in bytes) of the internally allocated memory.
309 * This should be implemented in all serializable SkPixelRef derived classes.
310 * SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value,
311 * otherwise the rendering code may attempt to read memory out of bounds.
312 *
313 * @return default impl returns 0.
314 */
315 virtual size_t getAllocatedSizeInBytes() const;
316
reed@android.com8a1c16f2008-12-17 15:59:43 +0000317 /** Return the mutex associated with this pixelref. This value is assigned
318 in the constructor, and cannot change during the lifetime of the object.
319 */
digit@google.com1771cbf2012-01-26 21:26:40 +0000320 SkBaseMutex* mutex() const { return fMutex; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000321
djsollen@google.com54924242012-03-29 15:18:04 +0000322 // serialization
digit@google.com1771cbf2012-01-26 21:26:40 +0000323 SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
djsollen@google.com54924242012-03-29 15:18:04 +0000324 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000325
reed@google.comff0da4f2012-05-17 13:14:52 +0000326 // only call from constructor. Flags this to always be locked, removing
327 // the need to grab the mutex and call onLockPixels/onUnlockPixels.
328 // Performance tweak to avoid those calls (esp. in multi-thread use case).
reed@google.com92713892014-01-03 17:58:57 +0000329 void setPreLocked(void*, size_t rowBytes, SkColorTable*);
reed@google.comff0da4f2012-05-17 13:14:52 +0000330
reed@android.com8a1c16f2008-12-17 15:59:43 +0000331private:
digit@google.com1771cbf2012-01-26 21:26:40 +0000332 SkBaseMutex* fMutex; // must remain in scope for the life of this object
reed@google.com33cc9892014-01-02 18:07:46 +0000333
334 const SkImageInfo fInfo;
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +0000335
reed@google.com92713892014-01-03 17:58:57 +0000336 // LockRec is only valid if we're in a locked state (isLocked())
337 LockRec fRec;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000338 int fLockCount;
reed@google.com93c5f9e2011-02-24 18:09:46 +0000339
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340 mutable uint32_t fGenerationID;
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000341 mutable bool fUniqueGenerationID;
reed@google.com93c5f9e2011-02-24 18:09:46 +0000342
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000343 SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned
scroggo@google.comd5764e82012-08-22 15:00:05 +0000344
reed@android.com8a1c16f2008-12-17 15:59:43 +0000345 SkString fURI;
346
347 // can go from false to true, but never from true to false
348 bool fIsImmutable;
reed@google.comff0da4f2012-05-17 13:14:52 +0000349 // only ever set in constructor, const after that
350 bool fPreLocked;
351
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000352 void needsNewGenID();
353 void callGenIDChangeListeners();
354
reed@google.comff0da4f2012-05-17 13:14:52 +0000355 void setMutex(SkBaseMutex* mutex);
caryclark@google.com9d0c6ec2011-12-20 20:26:56 +0000356
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000357 // When copying a bitmap to another with the same shape and config, we can safely
358 // clone the pixelref generation ID too, which makes them equivalent under caching.
359 friend class SkBitmap; // only for cloneGenID
360 void cloneGenID(const SkPixelRef&);
361
djsollen@google.com5370cd92012-03-28 20:47:01 +0000362 typedef SkFlattenable INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000363};
364
365#endif