• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 SkRemoteGlyphCache_DEFINED
9 #define SkRemoteGlyphCache_DEFINED
10 
11 #include <memory>
12 #include <tuple>
13 #include <unordered_map>
14 #include <unordered_set>
15 #include <vector>
16 
17 #include "include/core/SkData.h"
18 #include "include/core/SkRefCnt.h"
19 #include "include/core/SkSerialProcs.h"
20 #include "include/core/SkTypeface.h"
21 #include "include/private/SkTHash.h"
22 #include "include/utils/SkNoDrawCanvas.h"
23 #include "src/core/SkDevice.h"
24 #include "src/core/SkMakeUnique.h"
25 #include "src/core/SkStrikeInterface.h"
26 #include "src/core/SkTLazy.h"
27 
28 class Deserializer;
29 class Serializer;
30 enum SkAxisAlignment : uint32_t;
31 class SkDescriptor;
32 class SkStrike;
33 struct SkPackedGlyphID;
34 enum SkScalerContextFlags : uint32_t;
35 class SkStrikeCache;
36 class SkTypefaceProxy;
37 struct WireTypeface;
38 
39 class SkStrikeServer;
40 
41 struct SkDescriptorMapOperators {
42     size_t operator()(const SkDescriptor* key) const;
43     bool operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const;
44 };
45 
46 template <typename T>
47 using SkDescriptorMap = std::unordered_map<const SkDescriptor*, T, SkDescriptorMapOperators,
48                                            SkDescriptorMapOperators>;
49 
50 using SkDescriptorSet =
51         std::unordered_set<const SkDescriptor*, SkDescriptorMapOperators, SkDescriptorMapOperators>;
52 
53 // A SkTextBlobCacheDiffCanvas is used to populate the SkStrikeServer with ops
54 // which will be serialized and rendered using the SkStrikeClient.
55 class SK_API SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas {
56 public:
57 
58     // DEPRECATED
59     // TODO(herb): remove uses in Chrome
60     struct SK_API Settings {
61         Settings();
62         bool fContextSupportsDistanceFieldText = true;
63 
64         // These are set by Chrome, but not used in Skia.
65         int fMaxTextureSize = 0;
66         size_t fMaxTextureBytes = 0u;
67     };
68 
69     // For testing use only
70     SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props,
71                               SkStrikeServer* strikeServer, bool DFTSupport = true);
72 
73     // DEPRECATED
74     // TODO(herb) : remove uses in Chrome.
75     SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props,
76                               SkStrikeServer* strikeServer, sk_sp<SkColorSpace> colorSpace,
77                               Settings settings = Settings());
78 
79     SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props,
80                               SkStrikeServer* strikeServer, sk_sp<SkColorSpace> colorSpace,
81                               bool DFTSupport);
82 
83     ~SkTextBlobCacheDiffCanvas() override;
84 
85 protected:
86     SkCanvas::SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override;
87     bool onDoSaveBehind(const SkRect*) override;
88     void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
89                         const SkPaint& paint) override;
90 
91 private:
92     class TrackLayerDevice;
93 };
94 
95 using SkDiscardableHandleId = uint32_t;
96 
97 // This class is not thread-safe.
98 class SK_API SkStrikeServer final : public SkStrikeCacheInterface {
99 public:
100     // An interface used by the server to create handles for pinning SkStrike
101     // entries on the remote client.
102     class SK_API DiscardableHandleManager {
103     public:
104         virtual ~DiscardableHandleManager() = default;
105 
106         // Creates a new *locked* handle and returns a unique ID that can be used to identify
107         // it on the remote client.
108         virtual SkDiscardableHandleId createHandle() = 0;
109 
110         // Returns true if the handle could be successfully locked. The server can
111         // assume it will remain locked until the next set of serialized entries is
112         // pulled from the SkStrikeServer.
113         // If returns false, the cache entry mapped to the handle has been deleted
114         // on the client. Any subsequent attempts to lock the same handle are not
115         // allowed.
116         virtual bool lockHandle(SkDiscardableHandleId) = 0;
117 
118         // Returns true if a handle has been deleted on the remote client. It is
119         // invalid to use a handle id again with this manager once this returns true.
120         // TODO(khushalsagar): Make pure virtual once chrome implementation lands.
isHandleDeleted(SkDiscardableHandleId)121         virtual bool isHandleDeleted(SkDiscardableHandleId) { return false; }
122     };
123 
124     explicit SkStrikeServer(DiscardableHandleManager* discardableHandleManager);
125     ~SkStrikeServer() override;
126 
127     // Serializes the typeface to be transmitted using this server.
128     sk_sp<SkData> serializeTypeface(SkTypeface*);
129 
130     // Serializes the strike data captured using a SkTextBlobCacheDiffCanvas. Any
131     // handles locked using the DiscardableHandleManager will be assumed to be
132     // unlocked after this call.
133     void writeStrikeData(std::vector<uint8_t>* memory);
134 
135     // Methods used internally in Skia ------------------------------------------
136     class SkGlyphCacheState;
137 
138     SkGlyphCacheState* getOrCreateCache(const SkPaint&,
139                                         const SkFont& font,
140                                         const SkSurfaceProps&,
141                                         const SkMatrix&,
142                                         SkScalerContextFlags flags,
143                                         SkScalerContextEffects* effects);
144 
145     SkScopedStrike findOrCreateScopedStrike(const SkDescriptor& desc,
146                                             const SkScalerContextEffects& effects,
147                                             const SkTypeface& typeface) override;
148 
149     static void AddGlyphForTesting(
150             SkGlyphCacheState* cache, SkPackedGlyphID glyphID, bool asPath);
151 
setMaxEntriesInDescriptorMapForTesting(size_t count)152     void setMaxEntriesInDescriptorMapForTesting(size_t count) {
153         fMaxEntriesInDescriptorMap = count;
154     }
remoteGlyphStateMapSizeForTesting()155     size_t remoteGlyphStateMapSizeForTesting() const { return fRemoteGlyphStateMap.size(); }
156 
157 private:
158     static constexpr size_t kMaxEntriesInDescriptorMap = 2000u;
159 
160     void checkForDeletedEntries();
161 
162     SkGlyphCacheState* getOrCreateCache(const SkDescriptor& desc,
163                                         const SkTypeface& typeface,
164                                         SkScalerContextEffects effects);
165 
166     SkDescriptorMap<std::unique_ptr<SkGlyphCacheState>> fRemoteGlyphStateMap;
167     DiscardableHandleManager* const fDiscardableHandleManager;
168     SkTHashSet<SkFontID> fCachedTypefaces;
169     size_t fMaxEntriesInDescriptorMap = kMaxEntriesInDescriptorMap;
170 
171     // Cached serialized typefaces.
172     SkTHashMap<SkFontID, sk_sp<SkData>> fSerializedTypefaces;
173 
174     // State cached until the next serialization.
175     SkDescriptorSet fLockedDescs;
176     std::vector<WireTypeface> fTypefacesToSend;
177 };
178 
179 class SK_API SkStrikeClient {
180 public:
181     // This enum is used in histogram reporting in chromium. Please don't re-order the list of
182     // entries, and consider it to be append-only.
183     enum CacheMissType : uint32_t {
184         // Hard failures where no fallback could be found.
185         kFontMetrics = 0,
186         kGlyphMetrics = 1,
187         kGlyphImage = 2,
188         kGlyphPath = 3,
189 
190         // The original glyph could not be found and a fallback was used.
191         kGlyphMetricsFallback = 4,
192         kGlyphPathFallback = 5,
193 
194         kLast = kGlyphPathFallback
195     };
196 
197     // An interface to delete handles that may be pinned by the remote server.
198     class DiscardableHandleManager : public SkRefCnt {
199     public:
200         ~DiscardableHandleManager() override = default;
201 
202         // Returns true if the handle was unlocked and can be safely deleted. Once
203         // successful, subsequent attempts to delete the same handle are invalid.
204         virtual bool deleteHandle(SkDiscardableHandleId) = 0;
205 
notifyCacheMiss(CacheMissType)206         virtual void notifyCacheMiss(CacheMissType) {}
207 
208         struct ReadFailureData {
209             size_t memorySize;
210             size_t bytesRead;
211             uint64_t typefaceSize;
212             uint64_t strikeCount;
213             uint64_t glyphImagesCount;
214             uint64_t glyphPathsCount;
215         };
notifyReadFailure(const ReadFailureData & data)216         virtual void notifyReadFailure(const ReadFailureData& data) {}
217     };
218 
219     explicit SkStrikeClient(sk_sp<DiscardableHandleManager>,
220                             bool isLogging = true,
221                             SkStrikeCache* strikeCache = nullptr);
222     ~SkStrikeClient();
223 
224     // Deserializes the typeface previously serialized using the SkStrikeServer. Returns null if the
225     // data is invalid.
226     sk_sp<SkTypeface> deserializeTypeface(const void* data, size_t length);
227 
228     static bool ReadGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer);
229 
230     // Deserializes the strike data from a SkStrikeServer. All messages generated
231     // from a server when serializing the ops must be deserialized before the op
232     // is rasterized.
233     // Returns false if the data is invalid.
234     bool readStrikeData(const volatile void* memory, size_t memorySize);
235 
236 private:
237     class DiscardableStrikePinner;
238 
239     sk_sp<SkTypeface> addTypeface(const WireTypeface& wire);
240 
241     SkTHashMap<SkFontID, sk_sp<SkTypeface>> fRemoteFontIdToTypeface;
242     sk_sp<DiscardableHandleManager> fDiscardableHandleManager;
243     SkStrikeCache* const fStrikeCache;
244     const bool fIsLogging;
245 };
246 
247 #endif  // SkRemoteGlyphCache_DEFINED
248