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