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