aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkRemoteGlyphCache.h
blob: 157e05833162b14dbca4d7666b311a3be21ce825 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkRemoteGlyphCache_DEFINED
#define SkRemoteGlyphCache_DEFINED

#include <memory>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "../private/SkTHash.h"
#include "SkData.h"
#include "SkDrawLooper.h"
#include "SkMakeUnique.h"
#include "SkNoDrawCanvas.h"
#include "SkRefCnt.h"
#include "SkSerialProcs.h"
#include "SkTypeface.h"

class Serializer;
class SkDescriptor;
class SkGlyphCache;
struct SkPackedGlyphID;
enum SkScalerContextFlags : uint32_t;
class SkScalerContextRecDescriptor;
class SkStrikeCache;
class SkTextBlobRunIterator;
class SkTypefaceProxy;
struct WireTypeface;

class SkStrikeServer;

struct SkDescriptorMapOperators {
    size_t operator()(const SkDescriptor* key) const;
    bool operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const;
};

template <typename T>
using SkDescriptorMap = std::unordered_map<const SkDescriptor*, T, SkDescriptorMapOperators,
                                           SkDescriptorMapOperators>;

using SkDescriptorSet =
        std::unordered_set<const SkDescriptor*, SkDescriptorMapOperators, SkDescriptorMapOperators>;

// A SkTextBlobCacheDiffCanvas is used to populate the SkStrikeServer with ops
// which will be serialized and renderered using the SkStrikeClient.
class SK_API SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas {
public:
    struct SK_API Settings {
        Settings();
        ~Settings();

        bool fContextSupportsDistanceFieldText = true;
        SkScalar fMinDistanceFieldFontSize = -1.f;
        SkScalar fMaxDistanceFieldFontSize = -1.f;
        int fMaxTextureSize = 0;
        size_t fMaxTextureBytes = 0u;
    };
    SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props,
                              SkStrikeServer* strikeserver, Settings settings = Settings());

    // TODO(khushalsagar): Remove once removed from chromium.
    SkTextBlobCacheDiffCanvas(int width, int height, const SkMatrix& deviceMatrix,
                              const SkSurfaceProps& props, SkStrikeServer* strikeserver,
                              Settings settings = Settings());
    ~SkTextBlobCacheDiffCanvas() override;

protected:
    SkCanvas::SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override;
    void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
                        const SkPaint& paint) override;

private:
    class TrackLayerDevice;
};

using SkDiscardableHandleId = uint32_t;

// This class is not thread-safe.
class SK_API SkStrikeServer {
public:
    // An interface used by the server to create handles for pinning SkGlyphCache
    // entries on the remote client.
    class SK_API DiscardableHandleManager {
    public:
        virtual ~DiscardableHandleManager() {}

        // Creates a new *locked* handle and returns a unique ID that can be used to identify
        // it on the remote client.
        virtual SkDiscardableHandleId createHandle() = 0;

        // Returns true if the handle could be successfully locked. The server can
        // assume it will remain locked until the next set of serialized entries is
        // pulled from the SkStrikeServer.
        // If returns false, the cache entry mapped to the handle has been deleted
        // on the client. Any subsequent attempts to lock the same handle are not
        // allowed.
        virtual bool lockHandle(SkDiscardableHandleId) = 0;

        // TODO(khushalsagar): Add an API which checks whether a handle is still
        // valid without locking, so we can avoid tracking stale handles once they
        // have been purged on the remote side.
    };

    SkStrikeServer(DiscardableHandleManager* discardableHandleManager);
    ~SkStrikeServer();

    // Serializes the typeface to be remoted using this server.
    sk_sp<SkData> serializeTypeface(SkTypeface*);

    // Serializes the strike data captured using a SkTextBlobCacheDiffCanvas. Any
    // handles locked using the DiscardableHandleManager will be assumed to be
    // unlocked after this call.
    void writeStrikeData(std::vector<uint8_t>* memory);

    // Methods used internally in skia ------------------------------------------
    class SkGlyphCacheState {
    public:
        SkGlyphCacheState(std::unique_ptr<SkDescriptor> deviceDescriptor,
                          std::unique_ptr<SkDescriptor> keyDescriptor,
                          SkDiscardableHandleId discardableHandleId);
        ~SkGlyphCacheState();

        void addGlyph(SkTypeface*, const SkScalerContextEffects&, SkPackedGlyphID, bool pathOnly);
        void writePendingGlyphs(Serializer* serializer);
        SkDiscardableHandleId discardableHandleId() const { return fDiscardableHandleId; }
        const SkDescriptor& getDeviceDescriptor() {
            return *fDeviceDescriptor;
        }

        const SkDescriptor& getKeyDescriptor() {
            return *fKeyDescriptor;
        }
        const SkGlyph& findGlyph(SkTypeface*, const SkScalerContextEffects&, SkPackedGlyphID);

    private:
        bool hasPendingGlyphs() const {
            return !fPendingGlyphImages.empty() || !fPendingGlyphPaths.empty();
        }
        void writeGlyphPath(const SkPackedGlyphID& glyphID, Serializer* serializer) const;

        // The set of glyphs cached on the remote client.
        SkTHashSet<SkPackedGlyphID> fCachedGlyphImages;
        SkTHashSet<SkPackedGlyphID> fCachedGlyphPaths;

        // The set of glyphs which has not yet been serialized and sent to the
        // remote client.
        std::vector<SkPackedGlyphID> fPendingGlyphImages;
        std::vector<SkPackedGlyphID> fPendingGlyphPaths;

        // The device descriptor is used to create the scaler context. The glyphs to have the
        // correct device rendering. The key descriptor is used for communication. The GPU side will
        // create descriptors with out the device filtering, thus matching the key descriptor.
        std::unique_ptr<SkDescriptor> fDeviceDescriptor;
        std::unique_ptr<SkDescriptor> fKeyDescriptor;
        const SkDiscardableHandleId fDiscardableHandleId = static_cast<SkDiscardableHandleId>(-1);

        // The context built using fDeviceDescriptor
        std::unique_ptr<SkScalerContext> fContext;
        // FallbackTextHelper cases require glyph metrics when analyzing a glyph run, in which case
        // we cache them here.
        SkTHashMap<SkPackedGlyphID, SkGlyph> fGlyphMap;
    };

    SkGlyphCacheState* getOrCreateCache(const SkPaint&, const SkSurfaceProps*, const SkMatrix*,
                                        SkScalerContextFlags flags, SkScalerContextRec* deviceRec,
                                        SkScalerContextEffects* effects);

private:
    SkDescriptorMap<std::unique_ptr<SkGlyphCacheState>> fRemoteGlyphStateMap;
    DiscardableHandleManager* const fDiscardableHandleManager;
    SkTHashSet<SkFontID> fCachedTypefaces;

    // State cached until the next serialization.
    SkDescriptorSet fLockedDescs;
    std::vector<WireTypeface> fTypefacesToSend;
};

class SK_API SkStrikeClient {
public:
    // This enum is used in histogram reporting in chromium. Please don't re-order the list of
    // entries, and consider it to be append-only.
    enum CacheMissType : uint32_t {
        // Hard failures where no fallback could be found.
        kFontMetrics = 0,
        kGlyphMetrics = 1,
        kGlyphImage = 2,
        kGlyphPath = 3,

        // The original glyph could not be found and a fallback was used.
        kGlyphMetricsFallback = 4,
        kGlyphPathFallback = 5,

        kLast = kGlyphPathFallback
    };

    // An interface to delete handles that may be pinned by the remote server.
    class DiscardableHandleManager : public SkRefCnt {
    public:
        virtual ~DiscardableHandleManager() {}

        // Returns true if the handle was unlocked and can be safely deleted. Once
        // successful, subsequent attempts to delete the same handle are invalid.
        virtual bool deleteHandle(SkDiscardableHandleId) = 0;

        virtual void notifyCacheMiss(CacheMissType) {}
    };

    SkStrikeClient(sk_sp<DiscardableHandleManager>,
                   bool isLogging = true,
                   SkStrikeCache* strikeCache = nullptr);
    ~SkStrikeClient();

    // Deserializes the typeface previously serialized using the SkStrikeServer. Returns null if the
    // data is invalid.
    sk_sp<SkTypeface> deserializeTypeface(const void* data, size_t length);

    // Deserializes the strike data from a SkStrikeServer. All messages generated
    // from a server when serializing the ops must be deserialized before the op
    // is rasterized.
    // Returns false if the data is invalid.
    bool readStrikeData(const volatile void* memory, size_t memorySize);

private:
    class DiscardableStrikePinner;

    sk_sp<SkTypeface> addTypeface(const WireTypeface& wire);

    SkTHashMap<SkFontID, sk_sp<SkTypeface>> fRemoteFontIdToTypeface;
    sk_sp<DiscardableHandleManager> fDiscardableHandleManager;
    SkStrikeCache* const fStrikeCache;
    const bool fIsLogging;
};

#endif  // SkRemoteGlyphCache_DEFINED