blob: 12a72f4e86db082aa4d7abc5c7000526480c0a28 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2008 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
8#ifndef SkPixelRef_DEFINED
9#define SkPixelRef_DEFINED
10
herbe6e41a82015-09-28 11:24:13 -070011#include "../private/SkAtomics.h"
bungemana7e9f052016-02-18 08:53:33 -080012#include "../private/SkMutex.h"
13#include "../private/SkTDArray.h"
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000014#include "SkBitmap.h"
reed92fc2ae2015-05-22 08:06:21 -070015#include "SkFilterQuality.h"
mtklein86821b52015-02-24 14:38:12 -080016#include "SkImageInfo.h"
reed92fc2ae2015-05-22 08:06:21 -070017#include "SkPixmap.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000018#include "SkRefCnt.h"
sugoi518d83d2014-07-21 11:37:39 -070019#include "SkSize.h"
mtklein86821b52015-02-24 14:38:12 -080020#include "SkString.h"
msarett4984c3c2016-03-10 05:44:43 -080021#include "SkYUVSizeInfo.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000022
23class SkColorTable;
reed@google.com50dfa012011-04-01 19:05:36 +000024struct SkIRect;
reed@android.com8a1c16f2008-12-17 15:59:43 +000025
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +000026class GrTexture;
reed216b6432015-08-19 12:25:40 -070027class SkDiscardableMemory;
reed@android.comce4e53a2010-09-09 16:01:26 +000028
reed@android.com8a1c16f2008-12-17 15:59:43 +000029/** \class SkPixelRef
30
31 This class is the smart container for pixel memory, and is used with
32 SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
33 access the actual pixel memory by calling lockPixels/unlockPixels.
34
35 This class can be shared/accessed between multiple threads.
36*/
reeded458682014-07-14 09:21:31 -070037class SK_API SkPixelRef : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000038public:
reed@google.comf1715702013-12-06 22:07:17 +000039 explicit SkPixelRef(const SkImageInfo&);
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000040 virtual ~SkPixelRef();
reed@google.com93c5f9e2011-02-24 18:09:46 +000041
reed@google.com9230ea22013-12-09 22:01:03 +000042 const SkImageInfo& info() const {
43 return fInfo;
44 }
45
reed@android.com8a1c16f2008-12-17 15:59:43 +000046 /** Return the pixel memory returned from lockPixels, or null if the
47 lockCount is 0.
48 */
reed@google.comd0419b12014-01-06 17:08:27 +000049 void* pixels() const { return fRec.fPixels; }
reed@android.com8a1c16f2008-12-17 15:59:43 +000050
51 /** Return the current colorTable (if any) if pixels are locked, or null.
52 */
reed@google.comd0419b12014-01-06 17:08:27 +000053 SkColorTable* colorTable() const { return fRec.fColorTable; }
reed@android.com8a1c16f2008-12-17 15:59:43 +000054
reed@google.com672588b2014-01-08 15:42:01 +000055 size_t rowBytes() const { return fRec.fRowBytes; }
56
reed@google.comff0da4f2012-05-17 13:14:52 +000057 /**
reed@google.com92713892014-01-03 17:58:57 +000058 * To access the actual pixels of a pixelref, it must be "locked".
59 * Calling lockPixels returns a LockRec struct (on success).
60 */
61 struct LockRec {
reeddb74f622015-05-30 13:41:15 -070062 LockRec() : fPixels(NULL), fColorTable(NULL) {}
63
reed@google.com92713892014-01-03 17:58:57 +000064 void* fPixels;
65 SkColorTable* fColorTable;
66 size_t fRowBytes;
skia.committer@gmail.com98272d92014-01-04 07:01:40 +000067
reed@google.com92713892014-01-03 17:58:57 +000068 void zero() { sk_bzero(this, sizeof(*this)); }
69
70 bool isZero() const {
71 return NULL == fPixels && NULL == fColorTable && 0 == fRowBytes;
72 }
73 };
skia.committer@gmail.com98272d92014-01-04 07:01:40 +000074
mtklein96d68b72015-02-20 12:40:40 -080075 SkDEBUGCODE(bool isLocked() const { return fLockCount > 0; })
reed@google.comea033602012-12-14 13:13:55 +000076 SkDEBUGCODE(int getLockCount() const { return fLockCount; })
77
reed@google.comd0419b12014-01-06 17:08:27 +000078 /**
79 * Call to access the pixel memory. Return true on success. Balance this
80 * with a call to unlockPixels().
81 */
82 bool lockPixels();
83
84 /**
85 * Call to access the pixel memory. On success, return true and fill out
86 * the specified rec. On failure, return false and ignore the rec parameter.
87 * Balance this with a call to unlockPixels().
88 */
89 bool lockPixels(LockRec* rec);
90
reed@android.com8a1c16f2008-12-17 15:59:43 +000091 /** Call to balanace a previous call to lockPixels(). Returns the pixels
92 (or null) after the unlock. NOTE: lock calls can be nested, but the
93 matching number of unlock calls must be made in order to free the
94 memory (if the subclass implements caching/deferred-decoding.)
95 */
96 void unlockPixels();
reed@google.com93c5f9e2011-02-24 18:09:46 +000097
reed@google.com9c49bc32011-07-07 13:42:37 +000098 /**
99 * Some bitmaps can return a copy of their pixels for lockPixels(), but
100 * that copy, if modified, will not be pushed back. These bitmaps should
101 * not be used as targets for a raster device/canvas (since all pixels
102 * modifications will be lost when unlockPixels() is called.)
103 */
104 bool lockPixelsAreWritable() const;
105
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106 /** Returns a non-zero, unique value corresponding to the pixels in this
107 pixelref. Each time the pixels are changed (and notifyPixelsChanged is
108 called), a different generation ID will be returned.
109 */
110 uint32_t getGenerationID() const;
reed@google.com93c5f9e2011-02-24 18:09:46 +0000111
scroggof3ca41c2014-11-25 13:42:12 -0800112#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
113 /** Returns a non-zero, unique value corresponding to this SkPixelRef.
114 Unlike the generation ID, this ID remains the same even when the pixels
115 are changed. IDs are not reused (until uint32_t wraps), so it is safe
116 to consider this ID unique even after this SkPixelRef is deleted.
117
118 Can be used as a key which uniquely identifies this SkPixelRef
119 regardless of changes to its pixels or deletion of this object.
120 */
121 uint32_t getStableID() const { return fStableID; }
122#endif
123
commit-bot@chromium.org0e8d0d62014-01-27 15:41:07 +0000124 /**
125 * Call this if you have changed the contents of the pixels. This will in-
126 * turn cause a different generation ID value to be returned from
127 * getGenerationID().
commit-bot@chromium.org0e8d0d62014-01-27 15:41:07 +0000128 */
reed@google.comc1587f92014-01-28 16:05:39 +0000129 void notifyPixelsChanged();
130
131 /**
132 * Change the info's AlphaType. Note that this does not automatically
133 * invalidate the generation ID. If the pixel values themselves have
134 * changed, then you must explicitly call notifyPixelsChanged() as well.
135 */
136 void changeAlphaType(SkAlphaType at);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137
138 /** Returns true if this pixelref is marked as immutable, meaning that the
139 contents of its pixels will not change for the lifetime of the pixelref.
140 */
reed26e0e582015-07-29 11:44:52 -0700141 bool isImmutable() const { return fMutability != kMutable; }
reed@google.com93c5f9e2011-02-24 18:09:46 +0000142
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143 /** Marks this pixelref is immutable, meaning that the contents of its
144 pixels will not change for the lifetime of the pixelref. This state can
145 be set on a pixelref, but it cannot be cleared once it is set.
146 */
147 void setImmutable();
148
149 /** Return the optional URI string associated with this pixelref. May be
150 null.
151 */
152 const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
153
154 /** Copy a URI string to this pixelref, or clear the URI if the uri is null
155 */
156 void setURI(const char uri[]) {
157 fURI.set(uri);
158 }
reed@google.com93c5f9e2011-02-24 18:09:46 +0000159
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160 /** Copy a URI string to this pixelref
161 */
162 void setURI(const char uri[], size_t len) {
163 fURI.set(uri, len);
164 }
reed@google.com93c5f9e2011-02-24 18:09:46 +0000165
reed@android.com8a1c16f2008-12-17 15:59:43 +0000166 /** Assign a URI string to this pixelref.
167 */
168 void setURI(const SkString& uri) { fURI = uri; }
169
reed92fc2ae2015-05-22 08:06:21 -0700170 struct LockRequest {
171 SkISize fSize;
172 SkFilterQuality fQuality;
173 };
174
175 struct LockResult {
reeddb74f622015-05-30 13:41:15 -0700176 LockResult() : fPixels(NULL), fCTable(NULL) {}
177
reed92fc2ae2015-05-22 08:06:21 -0700178 void (*fUnlockProc)(void* ctx);
179 void* fUnlockContext;
180
reed11e833d2015-05-30 09:20:29 -0700181 const void* fPixels;
reeddb74f622015-05-30 13:41:15 -0700182 SkColorTable* fCTable; // should be NULL unless colortype is kIndex8
reed92fc2ae2015-05-22 08:06:21 -0700183 size_t fRowBytes;
184 SkISize fSize;
185
186 void unlock() {
187 if (fUnlockProc) {
188 fUnlockProc(fUnlockContext);
189 fUnlockProc = NULL; // can't unlock twice!
190 }
191 }
192 };
193
194 bool requestLock(const LockRequest&, LockResult*);
195
sugoi518d83d2014-07-21 11:37:39 -0700196 /**
msarett4984c3c2016-03-10 05:44:43 -0800197 * If this can efficiently return YUV data, this should return true.
198 * Otherwise this returns false and does not modify any of the parameters.
sugoi518d83d2014-07-21 11:37:39 -0700199 *
msarett4984c3c2016-03-10 05:44:43 -0800200 * @param sizeInfo Output parameter indicating the sizes and required
201 * allocation widths of the Y, U, and V planes.
202 * @param colorSpace Output parameter.
msarett095d31c2016-03-07 08:39:12 -0800203 */
msarett4984c3c2016-03-10 05:44:43 -0800204 bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
205 return this->onQueryYUV8(sizeInfo, colorSpace);
206 }
207
208 /**
209 * Returns true on success and false on failure.
210 * Copies YUV data into the provided YUV planes.
211 *
212 * @param sizeInfo Needs to exactly match the values returned by the
213 * query, except the WidthBytes may be larger than the
214 * recommendation (but not smaller).
215 * @param planes Memory for each of the Y, U, and V planes.
216 */
217 bool getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
218 return this->onGetYUV8Planes(sizeInfo, planes);
sugoi518d83d2014-07-21 11:37:39 -0700219 }
220
bsalomon9d22fd62016-01-11 11:14:17 -0800221 /** Populates dst with the pixels of this pixelRef, converting them to colorType. */
222 bool readPixels(SkBitmap* dst, SkColorType colorType, const SkIRect* subset = NULL);
reed@google.com50dfa012011-04-01 19:05:36 +0000223
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000224 // Register a listener that may be called the next time our generation ID changes.
225 //
226 // We'll only call the listener if we're confident that we are the only SkPixelRef with this
227 // generation ID. If our generation ID changes and we decide not to call the listener, we'll
228 // never call it: you must add a new listener for each generation ID change. We also won't call
229 // the listener when we're certain no one knows what our generation ID is.
230 //
231 // This can be used to invalidate caches keyed by SkPixelRef generation ID.
232 struct GenIDChangeListener {
233 virtual ~GenIDChangeListener() {}
234 virtual void onChange() = 0;
235 };
236
237 // Takes ownership of listener.
238 void addGenIDChangeListener(GenIDChangeListener* listener);
239
reed83787d02015-02-25 07:17:11 -0800240 // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache
241 // to know automatically those entries can be purged when this pixelref is changed or deleted.
242 void notifyAddedToCache() {
mtklein61010772015-02-25 08:27:41 -0800243 fAddedToCache.store(true);
reed83787d02015-02-25 07:17:11 -0800244 }
245
reed216b6432015-08-19 12:25:40 -0700246 virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return NULL; }
247
fmalitaddbbdda2015-08-20 08:47:26 -0700248 /**
249 * Returns true if the pixels are generated on-the-fly (when required).
250 */
251 bool isLazyGenerated() const { return this->onIsLazyGenerated(); }
252
reed@android.com8a1c16f2008-12-17 15:59:43 +0000253protected:
reed@google.comd0419b12014-01-06 17:08:27 +0000254 /**
255 * On success, returns true and fills out the LockRec for the pixels. On
256 * failure returns false and ignores the LockRec parameter.
257 *
258 * The caller will have already acquired a mutex for thread safety, so this
259 * method need not do that.
260 */
261 virtual bool onNewLockPixels(LockRec*) = 0;
skia.committer@gmail.com96f5fa02013-12-16 07:01:40 +0000262
reed@google.comc83a91f2013-12-13 13:41:14 +0000263 /**
reed@google.comd0419b12014-01-06 17:08:27 +0000264 * Balancing the previous successful call to onNewLockPixels. The locked
265 * pixel address will no longer be referenced, so the subclass is free to
266 * move or discard that memory.
reed@google.comc83a91f2013-12-13 13:41:14 +0000267 *
reed@google.comd0419b12014-01-06 17:08:27 +0000268 * The caller will have already acquired a mutex for thread safety, so this
269 * method need not do that.
reed@google.comc83a91f2013-12-13 13:41:14 +0000270 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000271 virtual void onUnlockPixels() = 0;
272
reed@google.com9c49bc32011-07-07 13:42:37 +0000273 /** Default impl returns true */
274 virtual bool onLockPixelsAreWritable() const;
275
reed@google.com50dfa012011-04-01 19:05:36 +0000276 /**
277 * For pixelrefs that don't have access to their raw pixels, they may be
278 * able to make a copy of them (e.g. if the pixels are on the GPU).
279 *
280 * The base class implementation returns false;
281 */
bsalomon9d22fd62016-01-11 11:14:17 -0800282 virtual bool onReadPixels(SkBitmap* dst, SkColorType colorType, const SkIRect* subsetOrNull);
reed@google.com50dfa012011-04-01 19:05:36 +0000283
junovda5469d2015-06-15 09:48:15 -0700284 // default impl does nothing.
285 virtual void onNotifyPixelsChanged();
286
msarett4984c3c2016-03-10 05:44:43 -0800287 virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const {
288 return false;
289 }
290 virtual bool onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) {
291 return false;
292 }
sugoi518d83d2014-07-21 11:37:39 -0700293
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000294 /**
295 * Returns the size (in bytes) of the internally allocated memory.
296 * This should be implemented in all serializable SkPixelRef derived classes.
297 * SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value,
298 * otherwise the rendering code may attempt to read memory out of bounds.
299 *
300 * @return default impl returns 0.
301 */
302 virtual size_t getAllocatedSizeInBytes() const;
303
reed92fc2ae2015-05-22 08:06:21 -0700304 virtual bool onRequestLock(const LockRequest&, LockResult*);
305
fmalitaddbbdda2015-08-20 08:47:26 -0700306 virtual bool onIsLazyGenerated() const { return false; }
307
reed@android.com8a1c16f2008-12-17 15:59:43 +0000308 /** Return the mutex associated with this pixelref. This value is assigned
309 in the constructor, and cannot change during the lifetime of the object.
310 */
sclittled9f5d202016-05-04 18:23:30 -0700311 SkBaseMutex* mutex() const { return &fMutex; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000312
reed@google.comff0da4f2012-05-17 13:14:52 +0000313 // only call from constructor. Flags this to always be locked, removing
314 // the need to grab the mutex and call onLockPixels/onUnlockPixels.
315 // Performance tweak to avoid those calls (esp. in multi-thread use case).
reed@google.comd0419b12014-01-06 17:08:27 +0000316 void setPreLocked(void*, size_t rowBytes, SkColorTable*);
reed@google.comff0da4f2012-05-17 13:14:52 +0000317
reed@android.com8a1c16f2008-12-17 15:59:43 +0000318private:
mtklein7e6d9c02015-08-13 14:02:06 -0700319 mutable SkMutex fMutex;
reed@google.com33cc9892014-01-02 18:07:46 +0000320
commit-bot@chromium.org0e8d0d62014-01-27 15:41:07 +0000321 // mostly const. fInfo.fAlpahType can be changed at runtime.
reed@google.com33cc9892014-01-02 18:07:46 +0000322 const SkImageInfo fInfo;
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +0000323
reed@google.comd0419b12014-01-06 17:08:27 +0000324 // LockRec is only valid if we're in a locked state (isLocked())
325 LockRec fRec;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326 int fLockCount;
reed@google.com93c5f9e2011-02-24 18:09:46 +0000327
reeddb74f622015-05-30 13:41:15 -0700328 bool lockPixelsInsideMutex();
reed92fc2ae2015-05-22 08:06:21 -0700329
mtklein63d00242015-02-25 09:10:57 -0800330 // Bottom bit indicates the Gen ID is unique.
331 bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }
332 mutable SkAtomic<uint32_t> fTaggedGenID;
333
scroggof3ca41c2014-11-25 13:42:12 -0800334#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
335 const uint32_t fStableID;
336#endif
reed@google.com93c5f9e2011-02-24 18:09:46 +0000337
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000338 SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned
scroggo@google.comd5764e82012-08-22 15:00:05 +0000339
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340 SkString fURI;
341
mtklein63d00242015-02-25 09:10:57 -0800342 // Set true by caches when they cache content that's derived from the current pixels.
343 SkAtomic<bool> fAddedToCache;
reed26e0e582015-07-29 11:44:52 -0700344
345 enum {
346 kMutable, // PixelRefs begin mutable.
347 kTemporarilyImmutable, // Considered immutable, but can revert to mutable.
348 kImmutable, // Once set to this state, it never leaves.
349 } fMutability : 8; // easily fits inside a byte
350
reed@google.comff0da4f2012-05-17 13:14:52 +0000351 // only ever set in constructor, const after that
mtklein63d00242015-02-25 09:10:57 -0800352 bool fPreLocked;
reed@google.comff0da4f2012-05-17 13:14:52 +0000353
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000354 void needsNewGenID();
355 void callGenIDChangeListeners();
356
reed26e0e582015-07-29 11:44:52 -0700357 void setTemporarilyImmutable();
358 void restoreMutability();
359 friend class SkSurface_Raster; // For the two methods above.
360
reed02d91d12015-07-30 20:13:43 -0700361 bool isPreLocked() const { return fPreLocked; }
362 friend class SkImage_Raster;
robertphillipsb6c65e92016-02-04 10:52:42 -0800363 friend class SkSpecialImage_Raster;
reed02d91d12015-07-30 20:13:43 -0700364
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000365 // When copying a bitmap to another with the same shape and config, we can safely
366 // clone the pixelref generation ID too, which makes them equivalent under caching.
367 friend class SkBitmap; // only for cloneGenID
368 void cloneGenID(const SkPixelRef&);
369
reed6f1216a2015-08-04 08:10:13 -0700370 void setImmutableWithID(uint32_t genID);
371 friend class SkImage_Gpu;
reed8f343722015-08-13 13:32:39 -0700372 friend class SkImageCacherator;
robertphillips64612512016-04-08 12:10:42 -0700373 friend class SkSpecialImage_Gpu;
reed6f1216a2015-08-04 08:10:13 -0700374
reeded458682014-07-14 09:21:31 -0700375 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000376};
377
reed@google.com9ebcac52014-01-24 18:53:42 +0000378class SkPixelRefFactory : public SkRefCnt {
379public:
380 /**
381 * Allocate a new pixelref matching the specified ImageInfo, allocating
382 * the memory for the pixels. If the ImageInfo requires a ColorTable,
383 * the pixelref will ref() the colortable.
384 * On failure return NULL.
385 */
reedf0aed972014-07-01 12:48:11 -0700386 virtual SkPixelRef* create(const SkImageInfo&, size_t rowBytes, SkColorTable*) = 0;
reed@google.com9ebcac52014-01-24 18:53:42 +0000387};
388
reed@android.com8a1c16f2008-12-17 15:59:43 +0000389#endif