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 struct SkIRect;
23 
24 class GrTexture;
25 class SkDiscardableMemory;
26 
27 /** \class SkPixelRef
28 
29     This class is the smart container for pixel memory, and is used with SkBitmap.
30     This class can be shared/accessed between multiple threads.
31 */
32 class SK_API SkPixelRef : public SkRefCnt {
33 public:
34     SkPixelRef(int width, int height, void* addr, size_t rowBytes);
35     ~SkPixelRef() override;
36 
width()37     int width() const { return fWidth; }
height()38     int height() const { return fHeight; }
pixels()39     void* pixels() const { return fPixels; }
rowBytes()40     size_t rowBytes() const { return fRowBytes; }
41 
42     /** Returns a non-zero, unique value corresponding to the pixels in this
43         pixelref. Each time the pixels are changed (and notifyPixelsChanged is
44         called), a different generation ID will be returned.
45     */
46     uint32_t getGenerationID() const;
47 
48 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
49     /** Returns a non-zero, unique value corresponding to this SkPixelRef.
50         Unlike the generation ID, this ID remains the same even when the pixels
51         are changed. IDs are not reused (until uint32_t wraps), so it is safe
52         to consider this ID unique even after this SkPixelRef is deleted.
53 
54         Can be used as a key which uniquely identifies this SkPixelRef
55         regardless of changes to its pixels or deletion of this object.
56      */
getStableID()57     uint32_t getStableID() const { return fStableID; }
58 #endif
59 
60     /**
61      *  Call this if you have changed the contents of the pixels. This will in-
62      *  turn cause a different generation ID value to be returned from
63      *  getGenerationID().
64      */
65     void notifyPixelsChanged();
66 
67     /** Returns true if this pixelref is marked as immutable, meaning that the
68         contents of its pixels will not change for the lifetime of the pixelref.
69     */
isImmutable()70     bool isImmutable() const { return fMutability != kMutable; }
71 
72     /** Marks this pixelref is immutable, meaning that the contents of its
73         pixels will not change for the lifetime of the pixelref. This state can
74         be set on a pixelref, but it cannot be cleared once it is set.
75     */
76     void setImmutable();
77 
78     // Register a listener that may be called the next time our generation ID changes.
79     //
80     // We'll only call the listener if we're confident that we are the only SkPixelRef with this
81     // generation ID.  If our generation ID changes and we decide not to call the listener, we'll
82     // never call it: you must add a new listener for each generation ID change.  We also won't call
83     // the listener when we're certain no one knows what our generation ID is.
84     //
85     // This can be used to invalidate caches keyed by SkPixelRef generation ID.
86     struct GenIDChangeListener {
~GenIDChangeListenerGenIDChangeListener87         virtual ~GenIDChangeListener() {}
88         virtual void onChange() = 0;
89     };
90 
91     // Takes ownership of listener.
92     void addGenIDChangeListener(GenIDChangeListener* listener);
93 
94     // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache
95     // to know automatically those entries can be purged when this pixelref is changed or deleted.
notifyAddedToCache()96     void notifyAddedToCache() {
97         fAddedToCache.store(true);
98     }
99 
diagnostic_only_getDiscardable()100     virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return nullptr; }
101 
102 protected:
103     // default impl does nothing.
104     virtual void onNotifyPixelsChanged();
105 
106     void android_only_reset(int width, int height, size_t rowBytes);
107 
108 private:
109     int                 fWidth;
110     int                 fHeight;
111     void*               fPixels;
112     size_t              fRowBytes;
113 
114     // Bottom bit indicates the Gen ID is unique.
genIDIsUnique()115     bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }
116     mutable SkAtomic<uint32_t> fTaggedGenID;
117 
118 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
119     const uint32_t fStableID;
120 #endif
121 
122     SkTDArray<GenIDChangeListener*> fGenIDChangeListeners;  // pointers are owned
123 
124     // Set true by caches when they cache content that's derived from the current pixels.
125     SkAtomic<bool> fAddedToCache;
126 
127     enum {
128         kMutable,               // PixelRefs begin mutable.
129         kTemporarilyImmutable,  // Considered immutable, but can revert to mutable.
130         kImmutable,             // Once set to this state, it never leaves.
131     } fMutability : 8;          // easily fits inside a byte
132 
133     void needsNewGenID();
134     void callGenIDChangeListeners();
135 
136     void setTemporarilyImmutable();
137     void restoreMutability();
138     friend class SkSurface_Raster;   // For the two methods above.
139 
140     friend class SkImage_Raster;
141     friend class SkSpecialImage_Raster;
142 
143     void setImmutableWithID(uint32_t genID);
144     friend class SkImage_Gpu;
145     friend class SkImage_Lazy;
146     friend class SkSpecialImage_Gpu;
147     friend void SkBitmapCache_setImmutableWithID(SkPixelRef*, uint32_t);
148 
149     typedef SkRefCnt INHERITED;
150 };
151 
152 #endif
153