Line data Source code
1 : /*
2 : * Copyright 2008 The Android Open Source Project
3 : *
4 : * Use of this source code is governed by a BSD-style license that can be
5 : * found in the LICENSE file.
6 : */
7 :
8 : #ifndef SkPixelRef_DEFINED
9 : #define SkPixelRef_DEFINED
10 :
11 : #include "../private/SkAtomics.h"
12 : #include "../private/SkMutex.h"
13 : #include "../private/SkTDArray.h"
14 : #include "SkBitmap.h"
15 : #include "SkFilterQuality.h"
16 : #include "SkImageInfo.h"
17 : #include "SkPixmap.h"
18 : #include "SkRefCnt.h"
19 : #include "SkSize.h"
20 : #include "SkString.h"
21 :
22 : class SkColorTable;
23 : struct SkIRect;
24 :
25 : class GrTexture;
26 : class SkDiscardableMemory;
27 :
28 : /** \class SkPixelRef
29 :
30 : This class is the smart container for pixel memory, and is used with
31 : SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
32 : access the actual pixel memory by calling lockPixels/unlockPixels.
33 :
34 : This class can be shared/accessed between multiple threads.
35 : */
36 : class SK_API SkPixelRef : public SkRefCnt {
37 : public:
38 : #ifdef SK_SUPPORT_LEGACY_NO_ADDR_PIXELREF
39 : explicit SkPixelRef(const SkImageInfo&);
40 : #endif
41 : explicit SkPixelRef(const SkImageInfo&, void* addr, size_t rowBytes,
42 : sk_sp<SkColorTable> = nullptr);
43 : virtual ~SkPixelRef();
44 :
45 3840 : const SkImageInfo& info() const {
46 3840 : return fInfo;
47 : }
48 :
49 : /** Return the pixel memory returned from lockPixels, or null if the
50 : lockCount is 0.
51 : */
52 708 : void* pixels() const { return fRec.fPixels; }
53 :
54 : /** Return the current colorTable (if any) if pixels are locked, or null.
55 : */
56 499 : SkColorTable* colorTable() const { return fRec.fColorTable; }
57 :
58 2860 : size_t rowBytes() const { return fRec.fRowBytes; }
59 :
60 : /**
61 : * To access the actual pixels of a pixelref, it must be "locked".
62 : * Calling lockPixels returns a LockRec struct (on success).
63 : */
64 : struct LockRec {
65 270 : LockRec() : fPixels(NULL), fColorTable(NULL) {}
66 :
67 : void* fPixels;
68 : SkColorTable* fColorTable;
69 : size_t fRowBytes;
70 :
71 0 : void zero() { sk_bzero(this, sizeof(*this)); }
72 :
73 0 : bool isZero() const {
74 0 : return NULL == fPixels && NULL == fColorTable && 0 == fRowBytes;
75 : }
76 : };
77 :
78 1890 : SkDEBUGCODE(bool isLocked() const { return fLockCount > 0; })
79 : SkDEBUGCODE(int getLockCount() const { return fLockCount; })
80 :
81 : /**
82 : * Call to access the pixel memory. Return true on success. Balance this
83 : * with a call to unlockPixels().
84 : */
85 : bool lockPixels();
86 :
87 : /**
88 : * Call to access the pixel memory. On success, return true and fill out
89 : * the specified rec. On failure, return false and ignore the rec parameter.
90 : * Balance this with a call to unlockPixels().
91 : */
92 : bool lockPixels(LockRec* rec);
93 :
94 : /** Call to balanace a previous call to lockPixels(). Returns the pixels
95 : (or null) after the unlock. NOTE: lock calls can be nested, but the
96 : matching number of unlock calls must be made in order to free the
97 : memory (if the subclass implements caching/deferred-decoding.)
98 : */
99 : void unlockPixels();
100 :
101 : /** Returns a non-zero, unique value corresponding to the pixels in this
102 : pixelref. Each time the pixels are changed (and notifyPixelsChanged is
103 : called), a different generation ID will be returned.
104 : */
105 : uint32_t getGenerationID() const;
106 :
107 : #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
108 : /** Returns a non-zero, unique value corresponding to this SkPixelRef.
109 : Unlike the generation ID, this ID remains the same even when the pixels
110 : are changed. IDs are not reused (until uint32_t wraps), so it is safe
111 : to consider this ID unique even after this SkPixelRef is deleted.
112 :
113 : Can be used as a key which uniquely identifies this SkPixelRef
114 : regardless of changes to its pixels or deletion of this object.
115 : */
116 : uint32_t getStableID() const { return fStableID; }
117 : #endif
118 :
119 : /**
120 : * Call this if you have changed the contents of the pixels. This will in-
121 : * turn cause a different generation ID value to be returned from
122 : * getGenerationID().
123 : */
124 : void notifyPixelsChanged();
125 :
126 : /**
127 : * Change the info's AlphaType. Note that this does not automatically
128 : * invalidate the generation ID. If the pixel values themselves have
129 : * changed, then you must explicitly call notifyPixelsChanged() as well.
130 : */
131 : void changeAlphaType(SkAlphaType at);
132 :
133 : /** Returns true if this pixelref is marked as immutable, meaning that the
134 : contents of its pixels will not change for the lifetime of the pixelref.
135 : */
136 990 : bool isImmutable() const { return fMutability != kMutable; }
137 :
138 : /** Marks this pixelref is immutable, meaning that the contents of its
139 : pixels will not change for the lifetime of the pixelref. This state can
140 : be set on a pixelref, but it cannot be cleared once it is set.
141 : */
142 : void setImmutable();
143 :
144 : struct LockRequest {
145 : SkISize fSize;
146 : SkFilterQuality fQuality;
147 : };
148 :
149 : struct LockResult {
150 152 : LockResult() : fPixels(NULL), fCTable(NULL) {}
151 :
152 : void (*fUnlockProc)(void* ctx);
153 : void* fUnlockContext;
154 :
155 : const void* fPixels;
156 : SkColorTable* fCTable; // should be NULL unless colortype is kIndex8
157 : size_t fRowBytes;
158 : SkISize fSize;
159 :
160 : void unlock() {
161 : if (fUnlockProc) {
162 : fUnlockProc(fUnlockContext);
163 : fUnlockProc = NULL; // can't unlock twice!
164 : }
165 : }
166 : };
167 :
168 : bool requestLock(const LockRequest&, LockResult*);
169 :
170 : // Register a listener that may be called the next time our generation ID changes.
171 : //
172 : // We'll only call the listener if we're confident that we are the only SkPixelRef with this
173 : // generation ID. If our generation ID changes and we decide not to call the listener, we'll
174 : // never call it: you must add a new listener for each generation ID change. We also won't call
175 : // the listener when we're certain no one knows what our generation ID is.
176 : //
177 : // This can be used to invalidate caches keyed by SkPixelRef generation ID.
178 0 : struct GenIDChangeListener {
179 0 : virtual ~GenIDChangeListener() {}
180 : virtual void onChange() = 0;
181 : };
182 :
183 : // Takes ownership of listener.
184 : void addGenIDChangeListener(GenIDChangeListener* listener);
185 :
186 : // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache
187 : // to know automatically those entries can be purged when this pixelref is changed or deleted.
188 0 : void notifyAddedToCache() {
189 0 : fAddedToCache.store(true);
190 0 : }
191 :
192 0 : virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return NULL; }
193 :
194 : protected:
195 : #ifdef SK_SUPPORT_LEGACY_NO_ADDR_PIXELREF
196 : virtual
197 : #endif
198 : /**
199 : * On success, returns true and fills out the LockRec for the pixels. On
200 : * failure returns false and ignores the LockRec parameter.
201 : *
202 : * The caller will have already acquired a mutex for thread safety, so this
203 : * method need not do that.
204 : */
205 0 : bool onNewLockPixels(LockRec*) {
206 0 : SkASSERT(false); // should never be called
207 0 : return true;
208 : }
209 :
210 : #ifdef SK_SUPPORT_LEGACY_NO_ADDR_PIXELREF
211 : virtual
212 : #endif
213 : /**
214 : * Balancing the previous successful call to onNewLockPixels. The locked
215 : * pixel address will no longer be referenced, so the subclass is free to
216 : * move or discard that memory.
217 : *
218 : * The caller will have already acquired a mutex for thread safety, so this
219 : * method need not do that.
220 : */
221 0 : void onUnlockPixels() {
222 0 : SkASSERT(false); // should never be called
223 0 : }
224 :
225 : // default impl does nothing.
226 : virtual void onNotifyPixelsChanged();
227 :
228 : /**
229 : * Returns the size (in bytes) of the internally allocated memory.
230 : * This should be implemented in all serializable SkPixelRef derived classes.
231 : * SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value,
232 : * otherwise the rendering code may attempt to read memory out of bounds.
233 : *
234 : * @return default impl returns 0.
235 : */
236 : virtual size_t getAllocatedSizeInBytes() const;
237 :
238 : #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
239 : // This is undefined if there are clients in-flight trying to use us
240 : void android_only_reset(const SkImageInfo&, size_t rowBytes, sk_sp<SkColorTable>);
241 : #endif
242 :
243 : /** Return the mutex associated with this pixelref. This value is assigned
244 : in the constructor, and cannot change during the lifetime of the object.
245 : */
246 : SkBaseMutex* mutex() const { return &fMutex; }
247 :
248 : #ifdef SK_SUPPORT_LEGACY_NO_ADDR_PIXELREF
249 : // only call from constructor. Flags this to always be locked, removing
250 : // the need to grab the mutex and call onLockPixels/onUnlockPixels.
251 : // Performance tweak to avoid those calls (esp. in multi-thread use case).
252 : void setPreLocked(void*, size_t rowBytes, SkColorTable*);
253 : #endif
254 :
255 : private:
256 : mutable SkMutex fMutex;
257 :
258 : // mostly const. fInfo.fAlpahType can be changed at runtime.
259 : const SkImageInfo fInfo;
260 : sk_sp<SkColorTable> fCTable; // duplicated in LockRec, will unify later
261 :
262 : // LockRec is only valid if we're in a locked state (isLocked())
263 : LockRec fRec;
264 : int fLockCount;
265 :
266 : bool lockPixelsInsideMutex();
267 : bool internalRequestLock(const LockRequest&, LockResult*);
268 :
269 : // Bottom bit indicates the Gen ID is unique.
270 1441 : bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }
271 : mutable SkAtomic<uint32_t> fTaggedGenID;
272 :
273 : #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
274 : const uint32_t fStableID;
275 : #endif
276 :
277 : SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned
278 :
279 : // Set true by caches when they cache content that's derived from the current pixels.
280 : SkAtomic<bool> fAddedToCache;
281 :
282 : enum {
283 : kMutable, // PixelRefs begin mutable.
284 : kTemporarilyImmutable, // Considered immutable, but can revert to mutable.
285 : kImmutable, // Once set to this state, it never leaves.
286 : } fMutability : 8; // easily fits inside a byte
287 :
288 : // only ever set in constructor, const after that
289 : bool fPreLocked;
290 :
291 : void needsNewGenID();
292 : void callGenIDChangeListeners();
293 :
294 : void setTemporarilyImmutable();
295 : void restoreMutability();
296 : friend class SkSurface_Raster; // For the two methods above.
297 :
298 44 : bool isPreLocked() const { return fPreLocked; }
299 : friend class SkImage_Raster;
300 : friend class SkSpecialImage_Raster;
301 :
302 : // When copying a bitmap to another with the same shape and config, we can safely
303 : // clone the pixelref generation ID too, which makes them equivalent under caching.
304 : friend class SkBitmap; // only for cloneGenID
305 : void cloneGenID(const SkPixelRef&);
306 :
307 : void setImmutableWithID(uint32_t genID);
308 : friend class SkImage_Gpu;
309 : friend class SkImageCacherator;
310 : friend class SkSpecialImage_Gpu;
311 : friend void SkBitmapCache_setImmutableWithID(SkPixelRef*, uint32_t);
312 :
313 : typedef SkRefCnt INHERITED;
314 : };
315 :
316 : #endif
|