1 /* 2 * Copyright 2021 Google LLC. 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 SkChromeRemoteGlyphCache_DEFINED 9 #define SkChromeRemoteGlyphCache_DEFINED 10 11 #include <memory> 12 #include <vector> 13 14 #include "include/core/SkData.h" 15 #include "include/core/SkRefCnt.h" 16 #include "include/utils/SkNoDrawCanvas.h" 17 18 struct SkPackedGlyphID; 19 class SkAutoDescriptor; 20 class SkStrikeCache; 21 class SkStrikeClientImpl; 22 class SkStrikeServer; 23 class SkStrikeServerImpl; 24 class SkTypeface; 25 namespace sktext::gpu { class Slug; } 26 27 using SkDiscardableHandleId = uint32_t; 28 // This class is not thread-safe. 29 class SkStrikeServer { 30 public: 31 // An interface used by the server to create handles for pinning SkStrike 32 // entries on the remote client. 33 class DiscardableHandleManager { 34 public: 35 SK_SPI virtual ~DiscardableHandleManager() = default; 36 37 // Creates a new *locked* handle and returns a unique ID that can be used to identify 38 // it on the remote client. 39 SK_SPI virtual SkDiscardableHandleId createHandle() = 0; 40 41 // Returns true if the handle could be successfully locked. The server can 42 // assume it will remain locked until the next set of serialized entries is 43 // pulled from the SkStrikeServer. 44 // If returns false, the cache entry mapped to the handle has been deleted 45 // on the client. Any subsequent attempts to lock the same handle are not 46 // allowed. 47 SK_SPI virtual bool lockHandle(SkDiscardableHandleId) = 0; 48 49 // Returns true if a handle has been deleted on the remote client. It is 50 // invalid to use a handle id again with this manager once this returns true. 51 SK_SPI virtual bool isHandleDeleted(SkDiscardableHandleId) = 0; 52 }; 53 54 SK_SPI explicit SkStrikeServer(DiscardableHandleManager* discardableHandleManager); 55 SK_SPI ~SkStrikeServer(); 56 57 // Create an analysis SkCanvas used to populate the SkStrikeServer with ops 58 // which will be serialized and rendered using the SkStrikeClient. 59 SK_API std::unique_ptr<SkCanvas> makeAnalysisCanvas(int width, int height, 60 const SkSurfaceProps& props, 61 sk_sp<SkColorSpace> colorSpace, 62 bool DFTSupport, 63 bool DFTPerspSupport = true); 64 65 // Serializes the typeface to be transmitted using this server. 66 SK_SPI sk_sp<SkData> serializeTypeface(SkTypeface*); 67 68 // Serializes the strike data captured using a canvas returned by ::makeAnalysisCanvas. Any 69 // handles locked using the DiscardableHandleManager will be assumed to be 70 // unlocked after this call. 71 SK_SPI void writeStrikeData(std::vector<uint8_t>* memory); 72 73 // Testing helpers 74 void setMaxEntriesInDescriptorMapForTesting(size_t count); 75 size_t remoteStrikeMapSizeForTesting() const; 76 77 private: 78 SkStrikeServerImpl* impl(); 79 80 std::unique_ptr<SkStrikeServerImpl> fImpl; 81 }; 82 83 class SkStrikeClient { 84 public: 85 // This enum is used in histogram reporting in chromium. Please don't re-order the list of 86 // entries, and consider it to be append-only. 87 enum CacheMissType : uint32_t { 88 // Hard failures where no fallback could be found. 89 kFontMetrics = 0, 90 kGlyphMetrics = 1, 91 kGlyphImage = 2, 92 kGlyphPath = 3, 93 94 // (DEPRECATED) The original glyph could not be found and a fallback was used. 95 kGlyphMetricsFallback = 4, 96 kGlyphPathFallback = 5, 97 98 kGlyphDrawable = 6, 99 kLast = kGlyphDrawable 100 }; 101 102 // An interface to delete handles that may be pinned by the remote server. 103 class DiscardableHandleManager : public SkRefCnt { 104 public: 105 ~DiscardableHandleManager() override = default; 106 107 // Returns true if the handle was unlocked and can be safely deleted. Once 108 // successful, subsequent attempts to delete the same handle are invalid. 109 virtual bool deleteHandle(SkDiscardableHandleId) = 0; 110 assertHandleValid(SkDiscardableHandleId)111 virtual void assertHandleValid(SkDiscardableHandleId) {} 112 113 virtual void notifyCacheMiss(CacheMissType type, int fontSize) = 0; 114 115 struct ReadFailureData { 116 size_t memorySize; 117 size_t bytesRead; 118 uint64_t typefaceSize; 119 uint64_t strikeCount; 120 uint64_t glyphImagesCount; 121 uint64_t glyphPathsCount; 122 }; notifyReadFailure(const ReadFailureData & data)123 virtual void notifyReadFailure(const ReadFailureData& data) {} 124 }; 125 126 SK_SPI explicit SkStrikeClient(sk_sp<DiscardableHandleManager>, 127 bool isLogging = true, 128 SkStrikeCache* strikeCache = nullptr); 129 SK_SPI ~SkStrikeClient(); 130 131 // Deserializes the typeface previously serialized using the SkStrikeServer. Returns null if the 132 // data is invalid. 133 SK_SPI sk_sp<SkTypeface> deserializeTypeface(const void* data, size_t length); 134 135 // Deserializes the strike data from a SkStrikeServer. All messages generated 136 // from a server when serializing the ops must be deserialized before the op 137 // is rasterized. 138 // Returns false if the data is invalid. 139 SK_SPI bool readStrikeData(const volatile void* memory, size_t memorySize); 140 141 // Given a descriptor re-write the Rec mapping the typefaceID from the renderer to the 142 // corresponding typefaceID on the GPU. 143 SK_SPI bool translateTypefaceID(SkAutoDescriptor* descriptor) const; 144 145 // Given a buffer, unflatten into a slug making sure to do the typefaceID translation from 146 // renderer to GPU. Returns nullptr if there was a problem. 147 sk_sp<sktext::gpu::Slug> deserializeSlug(const void* data, size_t size) const; 148 149 private: 150 std::unique_ptr<SkStrikeClientImpl> fImpl; 151 }; 152 #endif // SkChromeRemoteGlyphCache_DEFINED 153