aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkPixelRef.h
blob: 6c9ff0c36312ef1683fbcf76fb487da30fa6e95c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 * Copyright 2008 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkPixelRef_DEFINED
#define SkPixelRef_DEFINED

#include "../private/SkAtomics.h"
#include "../private/SkMutex.h"
#include "../private/SkTDArray.h"
#include "SkBitmap.h"
#include "SkFilterQuality.h"
#include "SkImageInfo.h"
#include "SkPixmap.h"
#include "SkRefCnt.h"
#include "SkSize.h"
#include "SkString.h"

struct SkIRect;

class GrTexture;
class SkDiscardableMemory;

/** \class SkPixelRef

    This class is the smart container for pixel memory, and is used with SkBitmap.
    This class can be shared/accessed between multiple threads.
*/
class SK_API SkPixelRef : public SkRefCnt {
public:
    SkPixelRef(int width, int height, void* addr, size_t rowBytes);
    ~SkPixelRef() override;

    int width() const { return fWidth; }
    int height() const { return fHeight; }
    void* pixels() const { return fPixels; }
    size_t rowBytes() const { return fRowBytes; }

    /** Returns a non-zero, unique value corresponding to the pixels in this
        pixelref. Each time the pixels are changed (and notifyPixelsChanged is
        called), a different generation ID will be returned.
    */
    uint32_t getGenerationID() const;

#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    /** Returns a non-zero, unique value corresponding to this SkPixelRef.
        Unlike the generation ID, this ID remains the same even when the pixels
        are changed. IDs are not reused (until uint32_t wraps), so it is safe
        to consider this ID unique even after this SkPixelRef is deleted.

        Can be used as a key which uniquely identifies this SkPixelRef
        regardless of changes to its pixels or deletion of this object.
     */
    uint32_t getStableID() const { return fStableID; }
#endif

    /**
     *  Call this if you have changed the contents of the pixels. This will in-
     *  turn cause a different generation ID value to be returned from
     *  getGenerationID().
     */
    void notifyPixelsChanged();

    /** Returns true if this pixelref is marked as immutable, meaning that the
        contents of its pixels will not change for the lifetime of the pixelref.
    */
    bool isImmutable() const { return fMutability != kMutable; }

    /** Marks this pixelref is immutable, meaning that the contents of its
        pixels will not change for the lifetime of the pixelref. This state can
        be set on a pixelref, but it cannot be cleared once it is set.
    */
    void setImmutable();

    // Register a listener that may be called the next time our generation ID changes.
    //
    // We'll only call the listener if we're confident that we are the only SkPixelRef with this
    // generation ID.  If our generation ID changes and we decide not to call the listener, we'll
    // never call it: you must add a new listener for each generation ID change.  We also won't call
    // the listener when we're certain no one knows what our generation ID is.
    //
    // This can be used to invalidate caches keyed by SkPixelRef generation ID.
    struct GenIDChangeListener {
        virtual ~GenIDChangeListener() {}
        virtual void onChange() = 0;
    };

    // Takes ownership of listener.
    void addGenIDChangeListener(GenIDChangeListener* listener);

    // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache
    // to know automatically those entries can be purged when this pixelref is changed or deleted.
    void notifyAddedToCache() {
        fAddedToCache.store(true);
    }

    virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return nullptr; }

protected:
    void android_only_reset(int width, int height, size_t rowBytes);

private:
    int                 fWidth;
    int                 fHeight;
    void*               fPixels;
    size_t              fRowBytes;

    // Bottom bit indicates the Gen ID is unique.
    bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }
    mutable SkAtomic<uint32_t> fTaggedGenID;

#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    const uint32_t fStableID;
#endif

    SkTDArray<GenIDChangeListener*> fGenIDChangeListeners;  // pointers are owned

    // Set true by caches when they cache content that's derived from the current pixels.
    SkAtomic<bool> fAddedToCache;

    enum Mutability {
        kMutable,               // PixelRefs begin mutable.
        kTemporarilyImmutable,  // Considered immutable, but can revert to mutable.
        kImmutable,             // Once set to this state, it never leaves.
    } fMutability : 8;          // easily fits inside a byte

    void needsNewGenID();
    void callGenIDChangeListeners();

    void setTemporarilyImmutable();
    void restoreMutability();
    friend class SkSurface_Raster;   // For the two methods above.

    friend class SkImage_Raster;
    friend class SkSpecialImage_Raster;

    void setImmutableWithID(uint32_t genID);
    friend class SkImage_Gpu;
    friend class SkImage_Lazy;
    friend class SkSpecialImage_Gpu;
    friend void SkBitmapCache_setImmutableWithID(SkPixelRef*, uint32_t);

    typedef SkRefCnt INHERITED;
};

#endif