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