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