blob: bcef370f68e68c8e8ff1e76e5f5eb9e43cd02b96 [file] [log] [blame]
reed@google.combaed71f2013-09-26 19:28:27 +00001/*
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 Derby840c66c2018-04-16 16:42:08 -04008#ifndef SkStrikeCache_DEFINED
9#define SkStrikeCache_DEFINED
reed@google.combaed71f2013-09-26 19:28:27 +000010
Herb Derby1849ffd2018-04-23 12:59:05 -040011#include <unordered_map>
Khushal38a08432018-05-02 10:29:37 -070012#include <unordered_set>
Herb Derby1849ffd2018-04-23 12:59:05 -040013
Herbert Derby671e7ee2018-04-17 08:04:47 -040014#include "SkDescriptor.h"
Herb Derby5fd955e2019-01-16 11:23:29 -050015#include "SkStrike.h"
herb35475052015-07-09 11:37:35 -070016#include "SkSpinlock.h"
Herbert Derby671e7ee2018-04-17 08:04:47 -040017#include "SkTemplates.h"
Herb Derbydfeb2aa2018-02-28 18:47:27 -050018
Herb Derby5fd955e2019-01-16 11:23:29 -050019class SkStrike;
Herbert Derby671e7ee2018-04-17 08:04:47 -040020class SkTraceMemoryDump;
reed@google.combaed71f2013-09-26 19:28:27 +000021
22#ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT
reed@google.com12eb7812013-10-09 12:45:51 +000023 #define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT 2048
reed@google.combaed71f2013-09-26 19:28:27 +000024#endif
25
26#ifndef SK_DEFAULT_FONT_CACHE_LIMIT
27 #define SK_DEFAULT_FONT_CACHE_LIMIT (2 * 1024 * 1024)
28#endif
29
Mike Reedd5bee5d2017-06-01 14:45:44 -040030#ifndef SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT
31 #define SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT 256
32#endif
33
reed@google.combaed71f2013-09-26 19:28:27 +000034///////////////////////////////////////////////////////////////////////////////
35
Herb Derbye68c4fb2018-04-19 13:12:07 -040036class SkStrikePinner {
37public:
38 virtual ~SkStrikePinner() = default;
39 virtual bool canDelete() = 0;
40};
41
Herb Derby840c66c2018-04-16 16:42:08 -040042class SkStrikeCache {
Herb Derbydcdabf32018-11-13 12:26:10 -050043 class Node;
Herb Derbydce19a72018-04-18 16:02:17 -040044
reed@google.combaed71f2013-09-26 19:28:27 +000045public:
Herbert Derby671e7ee2018-04-17 08:04:47 -040046 SkStrikeCache() = default;
Herb Derby840c66c2018-04-16 16:42:08 -040047 ~SkStrikeCache();
Herb Derbydfeb2aa2018-02-28 18:47:27 -050048
Herb Derbydce19a72018-04-18 16:02:17 -040049 class ExclusiveStrikePtr {
50 public:
Herb Derbydcdabf32018-11-13 12:26:10 -050051 explicit ExclusiveStrikePtr(Node*);
Herb Derbydce19a72018-04-18 16:02:17 -040052 ExclusiveStrikePtr();
53 ExclusiveStrikePtr(const ExclusiveStrikePtr&) = delete;
54 ExclusiveStrikePtr& operator = (const ExclusiveStrikePtr&) = delete;
55 ExclusiveStrikePtr(ExclusiveStrikePtr&&);
56 ExclusiveStrikePtr& operator = (ExclusiveStrikePtr&&);
57 ~ExclusiveStrikePtr();
58
Herb Derby5fd955e2019-01-16 11:23:29 -050059 SkStrike* get() const;
60 SkStrike* operator -> () const;
61 SkStrike& operator * () const;
Herb Derbydce19a72018-04-18 16:02:17 -040062 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.combaed71f2013-09-26 19:28:27 +000070
Herb Derbyae167ed2018-06-21 11:36:44 -040071 static SkStrikeCache* GlobalStrikeCache();
Herb Derby65b7bfc2018-06-05 13:32:12 -040072
Herbert Derby671e7ee2018-04-17 08:04:47 -040073 static ExclusiveStrikePtr FindStrikeExclusive(const SkDescriptor&);
Herb Derby71cca672018-06-21 11:53:44 -040074 ExclusiveStrikePtr findStrikeExclusive(const SkDescriptor&);
Herb Derbydcdabf32018-11-13 12:26:10 -050075 Node* findAndDetachStrike(const SkDescriptor&);
Herb Derby65b7bfc2018-06-05 13:32:12 -040076
Herb Derbyf155f812018-04-17 15:00:40 -040077 static ExclusiveStrikePtr CreateStrikeExclusive(
78 const SkDescriptor& desc,
79 std::unique_ptr<SkScalerContext> scaler,
Mike Reeddca2e912018-11-09 14:31:44 -050080 SkFontMetrics* maybeMetrics = nullptr,
Herb Derbye68c4fb2018-04-19 13:12:07 -040081 std::unique_ptr<SkStrikePinner> = nullptr);
Herb Derbyf155f812018-04-17 15:00:40 -040082
Herb Derby71cca672018-06-21 11:53:44 -040083 ExclusiveStrikePtr createStrikeExclusive(
84 const SkDescriptor& desc,
85 std::unique_ptr<SkScalerContext> scaler,
Mike Reeddca2e912018-11-09 14:31:44 -050086 SkFontMetrics* maybeMetrics = nullptr,
Herb Derby71cca672018-06-21 11:53:44 -040087 std::unique_ptr<SkStrikePinner> = nullptr);
88
Herb Derbydcdabf32018-11-13 12:26:10 -050089 Node* createStrike(
90 const SkDescriptor& desc,
91 std::unique_ptr<SkScalerContext> scaler,
Mike Reed93439b72018-11-14 10:46:13 -080092 SkFontMetrics* maybeMetrics = nullptr,
Herb Derbydcdabf32018-11-13 12:26:10 -050093 std::unique_ptr<SkStrikePinner> = nullptr);
94
Herb Derbyfa996902018-04-18 11:36:12 -040095 static ExclusiveStrikePtr FindOrCreateStrikeExclusive(
96 const SkDescriptor& desc,
97 const SkScalerContextEffects& effects,
98 const SkTypeface& typeface);
99
Herb Derby71cca672018-06-21 11:53:44 -0400100 ExclusiveStrikePtr findOrCreateStrikeExclusive(
101 const SkDescriptor& desc,
102 const SkScalerContextEffects& effects,
103 const SkTypeface& typeface);
104
Herb Derbydcdabf32018-11-13 12:26:10 -0500105 Node* findOrCreateStrike(
106 const SkDescriptor& desc,
107 const SkScalerContextEffects& effects,
108 const SkTypeface& typeface);
109
Herb Derby71cca672018-06-21 11:53:44 -0400110 // Routines to find suitable data when working in a remote cache situation. These are
111 // suitable as substitutes for similar calls in SkScalerContext.
Herb Derby71cca672018-06-21 11:53:44 -0400112 bool desperationSearchForImage(const SkDescriptor& desc,
113 SkGlyph* glyph,
Herb Derby5fd955e2019-01-16 11:23:29 -0500114 SkStrike* targetCache);
Herb Derby71cca672018-06-21 11:53:44 -0400115 bool desperationSearchForPath(const SkDescriptor& desc, SkGlyphID glyphID, SkPath* path);
116
Herb Derbyfa996902018-04-18 11:36:12 -0400117 static ExclusiveStrikePtr FindOrCreateStrikeExclusive(
Mike Reed32c60662018-11-28 10:28:07 -0500118 const SkFont& font,
Herb Derbyfa996902018-04-18 11:36:12 -0400119 const SkPaint& paint,
Herb Derbyc3415002018-11-08 16:40:26 -0500120 const SkSurfaceProps& surfaceProps,
Herb Derbyfa996902018-04-18 11:36:12 -0400121 SkScalerContextFlags scalerContextFlags,
Herb Derbyc3415002018-11-08 16:40:26 -0500122 const SkMatrix& deviceMatrix);
Herb Derbyfa996902018-04-18 11:36:12 -0400123
Herb Derbydcdabf32018-11-13 12:26:10 -0500124 Node* findOrCreateStrike(
Mike Reed32c60662018-11-28 10:28:07 -0500125 const SkFont& font,
Herb Derbydcdabf32018-11-13 12:26:10 -0500126 const SkPaint& paint,
127 const SkSurfaceProps& surfaceProps,
128 SkScalerContextFlags scalerContextFlags,
129 const SkMatrix& deviceMatrix);
130
Mike Reed32c60662018-11-28 10:28:07 -0500131 // cons up a default paint, which is only needed for patheffects/maskfilter
Mike Reed5fb83f92018-11-15 13:10:07 -0500132 static ExclusiveStrikePtr FindOrCreateStrikeWithNoDeviceExclusive(const SkFont&);
133
Mike Reed54bf6842018-11-27 12:27:15 -0500134 static ExclusiveStrikePtr FindOrCreateStrikeWithNoDeviceExclusive(const SkFont& font,
135 const SkPaint& paint);
136
Herb Derbyfa996902018-04-18 11:36:12 -0400137 static std::unique_ptr<SkScalerContext> CreateScalerContext(
138 const SkDescriptor&, const SkScalerContextEffects&, const SkTypeface&);
139
Herbert Derby671e7ee2018-04-17 08:04:47 -0400140 static void PurgeAll();
Herb Derbyc113e9e2018-06-21 14:06:30 -0400141 static void ValidateGlyphCacheDataSize();
Herbert Derby671e7ee2018-04-17 08:04:47 -0400142 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 Derbydce19a72018-04-18 16:02:17 -0400149 void attachNode(Node* node);
Herbert Derby671e7ee2018-04-17 08:04:47 -0400150
151 void purgeAll(); // does not change budget
152
153 int getCacheCountLimit() const;
154 int setCacheCountLimit(int limit);
herb632d0042016-06-22 10:19:16 -0700155 int getCacheCountUsed() const;
reed@google.combaed71f2013-09-26 19:28:27 +0000156
Herbert Derby671e7ee2018-04-17 08:04:47 -0400157 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.combaed71f2013-09-26 19:28:27 +0000164#ifdef SK_DEBUG
Herb Derbyc113e9e2018-06-21 14:06:30 -0400165 // A simple accounting of what each glyph cache reports and the strike cache total.
reed@google.combaed71f2013-09-26 19:28:27 +0000166 void validate() const;
Herb Derbyc113e9e2018-06-21 14:06:30 -0400167 // Make sure that each glyph cache's memory tracking and actual memory used are in sync.
168 void validateGlyphCacheDataSize() const;
reed@google.combaed71f2013-09-26 19:28:27 +0000169#else
170 void validate() const {}
Herb Derbyc113e9e2018-06-21 14:06:30 -0400171 void validateGlyphCacheDataSize() const {}
reed@google.combaed71f2013-09-26 19:28:27 +0000172#endif
173
Herbert Derby671e7ee2018-04-17 08:04:47 -0400174private:
Herb Derby960d4212018-06-21 12:44:26 +0000175
Herbert Derby671e7ee2018-04-17 08:04:47 -0400176 // The following methods can only be called when mutex is already held.
Herb Derbydce19a72018-04-18 16:02:17 -0400177 Node* internalGetHead() const { return fHead; }
Herb Derbyd238d2f2018-04-26 12:59:08 -0400178 Node* internalGetTail() const { return fTail; }
Herb Derbydce19a72018-04-18 16:02:17 -0400179 void internalDetachCache(Node*);
180 void internalAttachToHead(Node*);
herbcd7f0352015-09-15 15:15:40 -0700181
reed@google.combaed71f2013-09-26 19:28:27 +0000182 // 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 Derby671e7ee2018-04-17 08:04:47 -0400186
Herb Derby5fd955e2019-01-16 11:23:29 -0500187 void forEachStrike(std::function<void(const SkStrike&)> visitor) const;
Herbert Derby671e7ee2018-04-17 08:04:47 -0400188
189 mutable SkSpinlock fLock;
Herb Derbydce19a72018-04-18 16:02:17 -0400190 Node* fHead{nullptr};
Herb Derbyd238d2f2018-04-26 12:59:08 -0400191 Node* fTail{nullptr};
Herbert Derby671e7ee2018-04-17 08:04:47 -0400192 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.combaed71f2013-09-26 19:28:27 +0000197};
198
Herbert Derby671e7ee2018-04-17 08:04:47 -0400199using SkExclusiveStrikePtr = SkStrikeCache::ExclusiveStrikePtr;
200
Herb Derby840c66c2018-04-16 16:42:08 -0400201#endif // SkStrikeCache_DEFINED