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 { 43 class Node; 44 45 public: 46 SkStrikeCache() = default; 47 ~SkStrikeCache(); 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 static ExclusiveStrikePtr FindOrCreateStrikeExclusive( 118 const SkFont& font, 119 const SkPaint& paint, 120 const SkSurfaceProps& surfaceProps, 121 SkScalerContextFlags scalerContextFlags, 122 const SkMatrix& deviceMatrix); 123 124 Node* findOrCreateStrike( 125 const SkFont& font, 126 const SkPaint& paint, 127 const SkSurfaceProps& surfaceProps, 128 SkScalerContextFlags scalerContextFlags, 129 const SkMatrix& deviceMatrix); 130 131 // cons up a default paint, which is only needed for patheffects/maskfilter 132 static ExclusiveStrikePtr FindOrCreateStrikeWithNoDeviceExclusive(const SkFont&); 133 134 static ExclusiveStrikePtr FindOrCreateStrikeWithNoDeviceExclusive(const SkFont& font, 135 const SkPaint& paint); 136 137 static std::unique_ptr<SkScalerContext> CreateScalerContext( 138 const SkDescriptor&, const SkScalerContextEffects&, const SkTypeface&); 139 140 static void PurgeAll(); 141 static void ValidateGlyphCacheDataSize(); 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) 149 void attachNode(Node* node); 150 151 void purgeAll(); // does not change budget 152 153 int getCacheCountLimit() const; 154 int setCacheCountLimit(int limit); 155 int getCacheCountUsed() const; 156 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 164 #ifdef SK_DEBUG 165 // A simple accounting of what each glyph cache reports and the strike cache total. 166 void validate() const; 167 // Make sure that each glyph cache's memory tracking and actual memory used are in sync. 168 void validateGlyphCacheDataSize() const; 169 #else 170 void validate() const {} 171 void validateGlyphCacheDataSize() const {} 172 #endif 173 174 private: 175 176 // The following methods can only be called when mutex is already held. 177 Node* internalGetHead() const { return fHead; } 178 Node* internalGetTail() const { return fTail; } 179 void internalDetachCache(Node*); 180 void internalAttachToHead(Node*); 181 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); 186 187 void forEachStrike(std::function<void(const SkStrike&)> visitor) const; 188 189 mutable SkSpinlock fLock; 190 Node* fHead{nullptr}; 191 Node* fTail{nullptr}; 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}; 197 }; 198 199 using SkExclusiveStrikePtr = SkStrikeCache::ExclusiveStrikePtr; 200 201 #endif // SkStrikeCache_DEFINED 202