reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2010 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 | |
Herb Derby | 840c66c | 2018-04-16 16:42:08 -0400 | [diff] [blame] | 8 | #ifndef SkStrikeCache_DEFINED |
| 9 | #define SkStrikeCache_DEFINED |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 10 | |
Herb Derby | 1849ffd | 2018-04-23 12:59:05 -0400 | [diff] [blame] | 11 | #include <unordered_map> |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 12 | #include <unordered_set> |
Herb Derby | 1849ffd | 2018-04-23 12:59:05 -0400 | [diff] [blame] | 13 | |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 14 | #include "SkDescriptor.h" |
Herb Derby | 5fd955e | 2019-01-16 11:23:29 -0500 | [diff] [blame] | 15 | #include "SkStrike.h" |
herb | 3547505 | 2015-07-09 11:37:35 -0700 | [diff] [blame] | 16 | #include "SkSpinlock.h" |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 17 | #include "SkTemplates.h" |
Herb Derby | dfeb2aa | 2018-02-28 18:47:27 -0500 | [diff] [blame] | 18 | |
Herb Derby | 5fd955e | 2019-01-16 11:23:29 -0500 | [diff] [blame] | 19 | class SkStrike; |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 20 | class SkTraceMemoryDump; |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 21 | |
| 22 | #ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT |
reed@google.com | 12eb781 | 2013-10-09 12:45:51 +0000 | [diff] [blame] | 23 | #define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT 2048 |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 24 | #endif |
| 25 | |
| 26 | #ifndef SK_DEFAULT_FONT_CACHE_LIMIT |
| 27 | #define SK_DEFAULT_FONT_CACHE_LIMIT (2 * 1024 * 1024) |
| 28 | #endif |
| 29 | |
Mike Reed | d5bee5d | 2017-06-01 14:45:44 -0400 | [diff] [blame] | 30 | #ifndef SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT |
| 31 | #define SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT 256 |
| 32 | #endif |
| 33 | |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 34 | /////////////////////////////////////////////////////////////////////////////// |
| 35 | |
Herb Derby | e68c4fb | 2018-04-19 13:12:07 -0400 | [diff] [blame] | 36 | class SkStrikePinner { |
| 37 | public: |
| 38 | virtual ~SkStrikePinner() = default; |
| 39 | virtual bool canDelete() = 0; |
| 40 | }; |
| 41 | |
Herb Derby | 840c66c | 2018-04-16 16:42:08 -0400 | [diff] [blame] | 42 | class SkStrikeCache { |
Herb Derby | dcdabf3 | 2018-11-13 12:26:10 -0500 | [diff] [blame] | 43 | class Node; |
Herb Derby | dce19a7 | 2018-04-18 16:02:17 -0400 | [diff] [blame] | 44 | |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 45 | public: |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 46 | SkStrikeCache() = default; |
Herb Derby | 840c66c | 2018-04-16 16:42:08 -0400 | [diff] [blame] | 47 | ~SkStrikeCache(); |
Herb Derby | dfeb2aa | 2018-02-28 18:47:27 -0500 | [diff] [blame] | 48 | |
Herb Derby | dce19a7 | 2018-04-18 16:02:17 -0400 | [diff] [blame] | 49 | class ExclusiveStrikePtr { |
| 50 | public: |
Herb Derby | dcdabf3 | 2018-11-13 12:26:10 -0500 | [diff] [blame] | 51 | explicit ExclusiveStrikePtr(Node*); |
Herb Derby | dce19a7 | 2018-04-18 16:02:17 -0400 | [diff] [blame] | 52 | ExclusiveStrikePtr(); |
| 53 | ExclusiveStrikePtr(const ExclusiveStrikePtr&) = delete; |
| 54 | ExclusiveStrikePtr& operator = (const ExclusiveStrikePtr&) = delete; |
| 55 | ExclusiveStrikePtr(ExclusiveStrikePtr&&); |
| 56 | ExclusiveStrikePtr& operator = (ExclusiveStrikePtr&&); |
| 57 | ~ExclusiveStrikePtr(); |
| 58 | |
Herb Derby | 5fd955e | 2019-01-16 11:23:29 -0500 | [diff] [blame] | 59 | SkStrike* get() const; |
| 60 | SkStrike* operator -> () const; |
| 61 | SkStrike& operator * () const; |
Herb Derby | dce19a7 | 2018-04-18 16:02:17 -0400 | [diff] [blame] | 62 | explicit operator bool () const; |
| 63 | friend bool operator == (const ExclusiveStrikePtr&, const ExclusiveStrikePtr&); |
| 64 | friend bool operator == (const ExclusiveStrikePtr&, decltype(nullptr)); |
| 65 | friend bool operator == (decltype(nullptr), const ExclusiveStrikePtr&); |
| 66 | |
| 67 | private: |
| 68 | Node* fNode; |
| 69 | }; |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 70 | |
Herb Derby | ae167ed | 2018-06-21 11:36:44 -0400 | [diff] [blame] | 71 | static SkStrikeCache* GlobalStrikeCache(); |
Herb Derby | 65b7bfc | 2018-06-05 13:32:12 -0400 | [diff] [blame] | 72 | |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 73 | static ExclusiveStrikePtr FindStrikeExclusive(const SkDescriptor&); |
Herb Derby | 71cca67 | 2018-06-21 11:53:44 -0400 | [diff] [blame] | 74 | ExclusiveStrikePtr findStrikeExclusive(const SkDescriptor&); |
Herb Derby | dcdabf3 | 2018-11-13 12:26:10 -0500 | [diff] [blame] | 75 | Node* findAndDetachStrike(const SkDescriptor&); |
Herb Derby | 65b7bfc | 2018-06-05 13:32:12 -0400 | [diff] [blame] | 76 | |
Herb Derby | f155f81 | 2018-04-17 15:00:40 -0400 | [diff] [blame] | 77 | static ExclusiveStrikePtr CreateStrikeExclusive( |
| 78 | const SkDescriptor& desc, |
| 79 | std::unique_ptr<SkScalerContext> scaler, |
Mike Reed | dca2e91 | 2018-11-09 14:31:44 -0500 | [diff] [blame] | 80 | SkFontMetrics* maybeMetrics = nullptr, |
Herb Derby | e68c4fb | 2018-04-19 13:12:07 -0400 | [diff] [blame] | 81 | std::unique_ptr<SkStrikePinner> = nullptr); |
Herb Derby | f155f81 | 2018-04-17 15:00:40 -0400 | [diff] [blame] | 82 | |
Herb Derby | 71cca67 | 2018-06-21 11:53:44 -0400 | [diff] [blame] | 83 | ExclusiveStrikePtr createStrikeExclusive( |
| 84 | const SkDescriptor& desc, |
| 85 | std::unique_ptr<SkScalerContext> scaler, |
Mike Reed | dca2e91 | 2018-11-09 14:31:44 -0500 | [diff] [blame] | 86 | SkFontMetrics* maybeMetrics = nullptr, |
Herb Derby | 71cca67 | 2018-06-21 11:53:44 -0400 | [diff] [blame] | 87 | std::unique_ptr<SkStrikePinner> = nullptr); |
| 88 | |
Herb Derby | dcdabf3 | 2018-11-13 12:26:10 -0500 | [diff] [blame] | 89 | Node* createStrike( |
| 90 | const SkDescriptor& desc, |
| 91 | std::unique_ptr<SkScalerContext> scaler, |
Mike Reed | 93439b7 | 2018-11-14 10:46:13 -0800 | [diff] [blame] | 92 | SkFontMetrics* maybeMetrics = nullptr, |
Herb Derby | dcdabf3 | 2018-11-13 12:26:10 -0500 | [diff] [blame] | 93 | std::unique_ptr<SkStrikePinner> = nullptr); |
| 94 | |
Herb Derby | fa99690 | 2018-04-18 11:36:12 -0400 | [diff] [blame] | 95 | static ExclusiveStrikePtr FindOrCreateStrikeExclusive( |
| 96 | const SkDescriptor& desc, |
| 97 | const SkScalerContextEffects& effects, |
| 98 | const SkTypeface& typeface); |
| 99 | |
Herb Derby | 71cca67 | 2018-06-21 11:53:44 -0400 | [diff] [blame] | 100 | ExclusiveStrikePtr findOrCreateStrikeExclusive( |
| 101 | const SkDescriptor& desc, |
| 102 | const SkScalerContextEffects& effects, |
| 103 | const SkTypeface& typeface); |
| 104 | |
Herb Derby | dcdabf3 | 2018-11-13 12:26:10 -0500 | [diff] [blame] | 105 | Node* findOrCreateStrike( |
| 106 | const SkDescriptor& desc, |
| 107 | const SkScalerContextEffects& effects, |
| 108 | const SkTypeface& typeface); |
| 109 | |
Herb Derby | 71cca67 | 2018-06-21 11:53:44 -0400 | [diff] [blame] | 110 | // Routines to find suitable data when working in a remote cache situation. These are |
| 111 | // suitable as substitutes for similar calls in SkScalerContext. |
Herb Derby | 71cca67 | 2018-06-21 11:53:44 -0400 | [diff] [blame] | 112 | bool desperationSearchForImage(const SkDescriptor& desc, |
| 113 | SkGlyph* glyph, |
Herb Derby | 5fd955e | 2019-01-16 11:23:29 -0500 | [diff] [blame] | 114 | SkStrike* targetCache); |
Herb Derby | 71cca67 | 2018-06-21 11:53:44 -0400 | [diff] [blame] | 115 | bool desperationSearchForPath(const SkDescriptor& desc, SkGlyphID glyphID, SkPath* path); |
| 116 | |
Herb Derby | fa99690 | 2018-04-18 11:36:12 -0400 | [diff] [blame] | 117 | static ExclusiveStrikePtr FindOrCreateStrikeExclusive( |
Mike Reed | 32c6066 | 2018-11-28 10:28:07 -0500 | [diff] [blame] | 118 | const SkFont& font, |
Herb Derby | fa99690 | 2018-04-18 11:36:12 -0400 | [diff] [blame] | 119 | const SkPaint& paint, |
Herb Derby | c341500 | 2018-11-08 16:40:26 -0500 | [diff] [blame] | 120 | const SkSurfaceProps& surfaceProps, |
Herb Derby | fa99690 | 2018-04-18 11:36:12 -0400 | [diff] [blame] | 121 | SkScalerContextFlags scalerContextFlags, |
Herb Derby | c341500 | 2018-11-08 16:40:26 -0500 | [diff] [blame] | 122 | const SkMatrix& deviceMatrix); |
Herb Derby | fa99690 | 2018-04-18 11:36:12 -0400 | [diff] [blame] | 123 | |
Herb Derby | dcdabf3 | 2018-11-13 12:26:10 -0500 | [diff] [blame] | 124 | Node* findOrCreateStrike( |
Mike Reed | 32c6066 | 2018-11-28 10:28:07 -0500 | [diff] [blame] | 125 | const SkFont& font, |
Herb Derby | dcdabf3 | 2018-11-13 12:26:10 -0500 | [diff] [blame] | 126 | const SkPaint& paint, |
| 127 | const SkSurfaceProps& surfaceProps, |
| 128 | SkScalerContextFlags scalerContextFlags, |
| 129 | const SkMatrix& deviceMatrix); |
| 130 | |
Mike Reed | 32c6066 | 2018-11-28 10:28:07 -0500 | [diff] [blame] | 131 | // cons up a default paint, which is only needed for patheffects/maskfilter |
Mike Reed | 5fb83f9 | 2018-11-15 13:10:07 -0500 | [diff] [blame] | 132 | static ExclusiveStrikePtr FindOrCreateStrikeWithNoDeviceExclusive(const SkFont&); |
| 133 | |
Mike Reed | 54bf684 | 2018-11-27 12:27:15 -0500 | [diff] [blame] | 134 | static ExclusiveStrikePtr FindOrCreateStrikeWithNoDeviceExclusive(const SkFont& font, |
| 135 | const SkPaint& paint); |
| 136 | |
Herb Derby | fa99690 | 2018-04-18 11:36:12 -0400 | [diff] [blame] | 137 | static std::unique_ptr<SkScalerContext> CreateScalerContext( |
| 138 | const SkDescriptor&, const SkScalerContextEffects&, const SkTypeface&); |
| 139 | |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 140 | static void PurgeAll(); |
Herb Derby | c113e9e | 2018-06-21 14:06:30 -0400 | [diff] [blame] | 141 | static void ValidateGlyphCacheDataSize(); |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 142 | static void Dump(); |
| 143 | |
| 144 | // Dump memory usage statistics of all the attaches caches in the process using the |
| 145 | // SkTraceMemoryDump interface. |
| 146 | static void DumpMemoryStatistics(SkTraceMemoryDump* dump); |
| 147 | |
| 148 | // call when a glyphcache is available for caching (i.e. not in use) |
Herb Derby | dce19a7 | 2018-04-18 16:02:17 -0400 | [diff] [blame] | 149 | void attachNode(Node* node); |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 150 | |
| 151 | void purgeAll(); // does not change budget |
| 152 | |
| 153 | int getCacheCountLimit() const; |
| 154 | int setCacheCountLimit(int limit); |
herb | 632d004 | 2016-06-22 10:19:16 -0700 | [diff] [blame] | 155 | int getCacheCountUsed() const; |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 156 | |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 157 | size_t getCacheSizeLimit() const; |
| 158 | size_t setCacheSizeLimit(size_t limit); |
| 159 | size_t getTotalMemoryUsed() const; |
| 160 | |
| 161 | int getCachePointSizeLimit() const; |
| 162 | int setCachePointSizeLimit(int limit); |
| 163 | |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 164 | #ifdef SK_DEBUG |
Herb Derby | c113e9e | 2018-06-21 14:06:30 -0400 | [diff] [blame] | 165 | // A simple accounting of what each glyph cache reports and the strike cache total. |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 166 | void validate() const; |
Herb Derby | c113e9e | 2018-06-21 14:06:30 -0400 | [diff] [blame] | 167 | // Make sure that each glyph cache's memory tracking and actual memory used are in sync. |
| 168 | void validateGlyphCacheDataSize() const; |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 169 | #else |
| 170 | void validate() const {} |
Herb Derby | c113e9e | 2018-06-21 14:06:30 -0400 | [diff] [blame] | 171 | void validateGlyphCacheDataSize() const {} |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 172 | #endif |
| 173 | |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 174 | private: |
Herb Derby | 960d421 | 2018-06-21 12:44:26 +0000 | [diff] [blame] | 175 | |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 176 | // The following methods can only be called when mutex is already held. |
Herb Derby | dce19a7 | 2018-04-18 16:02:17 -0400 | [diff] [blame] | 177 | Node* internalGetHead() const { return fHead; } |
Herb Derby | d238d2f | 2018-04-26 12:59:08 -0400 | [diff] [blame] | 178 | Node* internalGetTail() const { return fTail; } |
Herb Derby | dce19a7 | 2018-04-18 16:02:17 -0400 | [diff] [blame] | 179 | void internalDetachCache(Node*); |
| 180 | void internalAttachToHead(Node*); |
herb | cd7f035 | 2015-09-15 15:15:40 -0700 | [diff] [blame] | 181 | |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 182 | // Checkout budgets, modulated by the specified min-bytes-needed-to-purge, |
| 183 | // and attempt to purge caches to match. |
| 184 | // Returns number of bytes freed. |
| 185 | size_t internalPurge(size_t minBytesNeeded = 0); |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 186 | |
Herb Derby | 5fd955e | 2019-01-16 11:23:29 -0500 | [diff] [blame] | 187 | void forEachStrike(std::function<void(const SkStrike&)> visitor) const; |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 188 | |
| 189 | mutable SkSpinlock fLock; |
Herb Derby | dce19a7 | 2018-04-18 16:02:17 -0400 | [diff] [blame] | 190 | Node* fHead{nullptr}; |
Herb Derby | d238d2f | 2018-04-26 12:59:08 -0400 | [diff] [blame] | 191 | Node* fTail{nullptr}; |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 192 | size_t fTotalMemoryUsed{0}; |
| 193 | size_t fCacheSizeLimit{SK_DEFAULT_FONT_CACHE_LIMIT}; |
| 194 | int32_t fCacheCountLimit{SK_DEFAULT_FONT_CACHE_COUNT_LIMIT}; |
| 195 | int32_t fCacheCount{0}; |
| 196 | int32_t fPointSizeLimit{SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT}; |
reed@google.com | baed71f | 2013-09-26 19:28:27 +0000 | [diff] [blame] | 197 | }; |
| 198 | |
Herbert Derby | 671e7ee | 2018-04-17 08:04:47 -0400 | [diff] [blame] | 199 | using SkExclusiveStrikePtr = SkStrikeCache::ExclusiveStrikePtr; |
| 200 | |
Herb Derby | 840c66c | 2018-04-16 16:42:08 -0400 | [diff] [blame] | 201 | #endif // SkStrikeCache_DEFINED |