1 /*
2  * Copyright 2016 Google Inc.
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 SkImageFilterCache_DEFINED
9 #define SkImageFilterCache_DEFINED
10 
11 #include "include/core/SkMatrix.h"
12 #include "include/core/SkRefCnt.h"
13 #include "src/core/SkImageFilterTypes.h"
14 
15 struct SkIPoint;
16 class SkImageFilter;
17 
18 struct SkImageFilterCacheKey {
SkImageFilterCacheKeySkImageFilterCacheKey19     SkImageFilterCacheKey(const uint32_t uniqueID, const SkMatrix& matrix,
20         const SkIRect& clipBounds, uint32_t srcGenID, const SkIRect& srcSubset)
21         : fUniqueID(uniqueID)
22         , fMatrix(matrix)
23         , fClipBounds(clipBounds)
24         , fSrcGenID(srcGenID)
25         , fSrcSubset(srcSubset) {
26         // Assert that Key is tightly-packed, since it is hashed.
27         static_assert(sizeof(SkImageFilterCacheKey) == sizeof(uint32_t) + sizeof(SkMatrix) +
28                                      sizeof(SkIRect) + sizeof(uint32_t) + 4 * sizeof(int32_t),
29                                      "image_filter_key_tight_packing");
30         fMatrix.getType();  // force initialization of type, so hashes match
31         SkASSERT(fMatrix.isFinite());   // otherwise we can't rely on == self when comparing keys
32     }
33 
34     uint32_t fUniqueID;
35     SkMatrix fMatrix;
36     SkIRect fClipBounds;
37     uint32_t fSrcGenID;
38     SkIRect fSrcSubset;
39 
40     bool operator==(const SkImageFilterCacheKey& other) const {
41         return fUniqueID == other.fUniqueID &&
42                fMatrix == other.fMatrix &&
43                fClipBounds == other.fClipBounds &&
44                fSrcGenID == other.fSrcGenID &&
45                fSrcSubset == other.fSrcSubset;
46     }
47 };
48 
49 // This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to result
50 // NOTE: this is the _specific_ unique ID of the image filter, so refiltering the same image with a
51 // copy of the image filter (with exactly the same parameters) will not yield a cache hit.
52 class SkImageFilterCache : public SkRefCnt {
53 public:
54     SK_USE_FLUENT_IMAGE_FILTER_TYPES_IN_CLASS
55 
56     enum { kDefaultTransientSize = 32 * 1024 * 1024 };
57 
~SkImageFilterCache()58     virtual ~SkImageFilterCache() {}
59     static SkImageFilterCache* Create(size_t maxBytes);
60     static SkImageFilterCache* Get();
61 
62     // Returns true on cache hit and updates 'result' to be the cached result. Returns false when
63     // not in the cache, in which case 'result' is not modified.
64     virtual bool get(const SkImageFilterCacheKey& key,
65                      skif::FilterResult<For::kOutput>* result) const = 0;
66     // 'filter' is included in the caching to allow the purging of all of an image filter's cached
67     // results when it is destroyed.
68     virtual void set(const SkImageFilterCacheKey& key, const SkImageFilter* filter,
69                      const skif::FilterResult<For::kOutput>& result) = 0;
70     virtual void purge() = 0;
71     virtual void purgeByImageFilter(const SkImageFilter*) = 0;
72     SkDEBUGCODE(virtual int count() const = 0;)
73 };
74 
75 #endif
76