diff options
author | Khushal <khushalsagar@chromium.org> | 2018-05-02 10:29:37 -0700 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-02 18:39:31 +0000 |
commit | 38a08436886e82de4eb9ebdbcb2bbd5ea7b05c6d (patch) | |
tree | 3477528878c8d4b0a053fbc807efd02e60fcde14 /src/core/SkRemoteGlyphCache.h | |
parent | 81afc04b5368fc4a7cb6ae4b4d7069e67a3a51f8 (diff) |
fonts: Reland push font remoting.
This relands the following changes:
1) https://skia-review.googlesource.com/c/skia/+/120283
2) https://skia-review.googlesource.com/c/skia/+/125029
3) https://skia-review.googlesource.com/c/skia/+/125140
The original changes had to be reverted due to a memory leak in
SkBaseDevice from SkTextBlobCacheDiffCanvas. This has been addressed by
https://skia-review.googlesource.com/c/skia/+/125160
TBR=herb@google.com
Bug: skia:7515, 831354
Change-Id: I73f4fcb1c397f31bf01553ff48c71ed2d6dd0770
Reviewed-on: https://skia-review.googlesource.com/125326
Commit-Queue: Khusal Sagar <khushalsagar@chromium.org>
Reviewed-by: Khusal Sagar <khushalsagar@chromium.org>
Diffstat (limited to 'src/core/SkRemoteGlyphCache.h')
-rw-r--r-- | src/core/SkRemoteGlyphCache.h | 288 |
1 files changed, 146 insertions, 142 deletions
diff --git a/src/core/SkRemoteGlyphCache.h b/src/core/SkRemoteGlyphCache.h index ff905862fa..b210f1c6d7 100644 --- a/src/core/SkRemoteGlyphCache.h +++ b/src/core/SkRemoteGlyphCache.h @@ -5,192 +5,196 @@ * found in the LICENSE file. */ -#ifndef SkRemoteGlyphCache_DEFINED -#define SkRemoteGlyphCache_DEFINED +#ifndef SkRemoteGlyphCachePriv_DEFINED +#define SkRemoteGlyphCachePriv_DEFINED #include <memory> #include <tuple> #include <unordered_map> +#include <unordered_set> #include <vector> +#include "../private/SkTHash.h" #include "SkData.h" -#include "SkDescriptor.h" #include "SkDrawLooper.h" -#include "SkGlyphCache.h" #include "SkMakeUnique.h" #include "SkNoDrawCanvas.h" #include "SkRefCnt.h" +#include "SkRemoteGlyphCache.h" #include "SkSerialProcs.h" -#include "SkStrikeCache.h" -#include "SkTextBlobRunIterator.h" -#include "SkTHash.h" #include "SkTypeface.h" -#include "SkTypeface_remote.h" -// The client uses a SkStrikeCacheClientRPC to send and receive data. -using SkStrikeCacheClientRPC = std::function<sk_sp<SkData>(const SkData&)>; +class Serializer; +class SkDescriptor; +class SkGlyphCache; +struct SkPackedGlyphID; +class SkScalerContextRecDescriptor; +class SkTextBlobRunIterator; +class SkTypefaceProxy; +struct WireTypeface; -class SkScalerContextRecDescriptor { -public: - SkScalerContextRecDescriptor() {} - explicit SkScalerContextRecDescriptor(const SkScalerContextRec& rec) { - auto desc = reinterpret_cast<SkDescriptor*>(&fDescriptor); - desc->init(); - desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); - desc->computeChecksum(); - SkASSERT(sizeof(fDescriptor) == desc->getLength()); - } - - explicit SkScalerContextRecDescriptor(const SkDescriptor& desc) - : SkScalerContextRecDescriptor(ExtractRec(desc)) { } - - SkScalerContextRecDescriptor& operator=(const SkScalerContextRecDescriptor& rhs) { - std::memcpy(&fDescriptor, &rhs.fDescriptor, rhs.desc().getLength()); - return *this; - } - - const SkDescriptor& desc() const { - return *reinterpret_cast<const SkDescriptor*>(&fDescriptor); - } - - struct Hash { - uint32_t operator()(SkScalerContextRecDescriptor const& s) const { - return s.desc().getChecksum(); - } - }; - - friend bool operator==(const SkScalerContextRecDescriptor& lhs, - const SkScalerContextRecDescriptor& rhs ) { - return lhs.desc() == rhs.desc(); - } +class SkStrikeServer; -private: - static SkScalerContextRec ExtractRec(const SkDescriptor& desc) { - uint32_t size; - auto recPtr = desc.findEntry(kRec_SkDescriptorTag, &size); - - SkScalerContextRec result; - std::memcpy(&result, recPtr, size); - return result; - } - // The system only passes descriptors without effects. That is why it uses a fixed size - // descriptor. storageFor is needed because some of the constructors below are private. - template <typename T> - using storageFor = typename std::aligned_storage<sizeof(T), alignof(T)>::type; - struct { - storageFor<SkDescriptor> dummy1; - storageFor<SkDescriptor::Entry> dummy2; - storageFor<SkScalerContextRec> dummy3; - } fDescriptor; +struct SkDescriptorMapOperators { + size_t operator()(const SkDescriptor* key) const; + bool operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const; }; -class SkStrikeDifferences { -public: - SkStrikeDifferences(SkFontID typefaceID, std::unique_ptr<SkDescriptor> desc); - void add(uint16_t glyphID, SkIPoint pos); - SkFontID fTypefaceID; - std::unique_ptr<SkDescriptor> fDesc; - std::unique_ptr<SkTHashSet<SkPackedGlyphID>> fGlyphIDs = - skstd::make_unique<SkTHashSet<SkPackedGlyphID>>(); -}; +template <typename T> +using SkDescriptorMap = std::unordered_map<const SkDescriptor*, T, SkDescriptorMapOperators, + SkDescriptorMapOperators>; -class SkStrikeCacheDifferenceSpec { -public: - SkStrikeDifferences& findStrikeDifferences(const SkDescriptor& desc, SkFontID typefaceID); - int strikeCount() const { return fDescriptorToDifferencesMap.size(); } - size_t sizeBytes() const; - template <typename PerStrike, typename PerGlyph> - void iterateDifferences(PerStrike perStrike, PerGlyph perGlyph) const; +using SkDescriptorSet = + std::unordered_set<const SkDescriptor*, SkDescriptorMapOperators, SkDescriptorMapOperators>; -private: - SkDescriptorMap<SkStrikeDifferences> fDescriptorToDifferencesMap{16}; -}; - -class SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas { +// 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: - SkTextBlobCacheDiffCanvas(int width, int height, - const SkMatrix& deviceMatrix, - const SkSurfaceProps& props, - SkScalerContextFlags flags, - SkStrikeCacheDifferenceSpec* strikeDiffs); + SkTextBlobCacheDiffCanvas(int width, int height, const SkMatrix& deviceMatrix, + const SkSurfaceProps& props, SkStrikeServer* strikeserver); + ~SkTextBlobCacheDiffCanvas() override; protected: - SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override; + SkCanvas::SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override; - void onDrawTextBlob( - const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) override; + void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, + const SkPaint& paint) override; private: - void processLooper( - const SkPoint& position, - const SkTextBlobRunIterator& it, - const SkPaint& origPaint, - SkDrawLooper* looper); - - void processGlyphRun( - const SkPoint& position, - const SkTextBlobRunIterator& it, - const SkPaint& runPaint); + void processLooper(const SkPoint& position, + const SkTextBlobRunIterator& it, + const SkPaint& origPaint, + SkDrawLooper* looper); + void processGlyphRun(const SkPoint& position, + const SkTextBlobRunIterator& it, + const SkPaint& runPaint); const SkMatrix fDeviceMatrix; const SkSurfaceProps fSurfaceProps; - const SkScalerContextFlags fScalerContextFlags; - - SkStrikeCacheDifferenceSpec* const fStrikeCacheDiff; + SkStrikeServer* const fStrikeServer; }; -class SkStrikeServer { -public: - SkStrikeServer(); - ~SkStrikeServer(); +using SkDiscardableHandleId = uint32_t; - // embedding clients call these methods - void serve(const SkData&, std::vector<uint8_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. + }; - void prepareSerializeProcs(SkSerialProcs* procs); + SkStrikeServer(DiscardableHandleManager* discardableHandleManager); + ~SkStrikeServer(); - // mostly called internally by Skia - SkScalerContext* generateScalerContext( - const SkScalerContextRecDescriptor& desc, SkFontID typefaceId); + // 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> desc, + SkDiscardableHandleId discardableHandleId); + ~SkGlyphCacheState(); + + void addGlyph(SkTypeface*, const SkScalerContextEffects&, SkPackedGlyphID); + void writePendingGlyphs(Serializer* serializer); + bool has_pending_glyphs() const { return !fPendingGlyphs.empty(); } + SkDiscardableHandleId discardable_handle_id() const { return fDiscardableHandleId; } + + private: + // The set of glyphs cached on the remote client. + SkTHashSet<SkPackedGlyphID> fCachedGlyphs; + + // The set of glyphs which has not yet been serialized and sent to the + // remote client. + std::vector<SkPackedGlyphID> fPendingGlyphs; + + std::unique_ptr<SkDescriptor> fDesc; + const SkDiscardableHandleId fDiscardableHandleId = -1; + std::unique_ptr<SkScalerContext> fContext; + }; + SkGlyphCacheState* getOrCreateCache(SkTypeface*, std::unique_ptr<SkDescriptor>); private: - using DescriptorToContextMap = SkTHashMap<SkScalerContextRecDescriptor, - std::unique_ptr<SkScalerContext>, - SkScalerContextRecDescriptor::Hash>; - - sk_sp<SkData> encodeTypeface(SkTypeface* tf); + SkDescriptorMap<std::unique_ptr<SkGlyphCacheState>> fRemoteGlyphStateMap; + DiscardableHandleManager* const fDiscardableHandleManager; + SkTHashSet<SkFontID> fCachedTypefaces; - int fOpCount = 0; - SkTHashMap<SkFontID, sk_sp<SkTypeface>> fTypefaceMap; - DescriptorToContextMap fScalerContextMap; + // State cached until the next serialization. + SkDescriptorSet fLockedDescs; + std::vector<WireTypeface> fTypefacesToSend; }; -class SkStrikeClient { +class SK_API SkStrikeClient { public: - SkStrikeClient(SkStrikeCacheClientRPC); - - // embedding clients call these methods - void primeStrikeCache(const SkStrikeCacheDifferenceSpec&); - void prepareDeserializeProcs(SkDeserialProcs* procs); + // 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; + }; - // mostly called internally by Skia - void generateFontMetrics( - const SkTypefaceProxy&, const SkScalerContextRec&, SkPaint::FontMetrics*); - void generateMetricsAndImage( - const SkTypefaceProxy&, const SkScalerContextRec&, SkArenaAlloc*, SkGlyph*); - bool generatePath( - const SkTypefaceProxy&, const SkScalerContextRec&, SkGlyphID glyph, SkPath* path); - SkTypeface* lookupTypeface(SkFontID id); + SkStrikeClient(sk_sp<DiscardableHandleManager>); + ~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); + + // TODO: Remove these since we don't support pulling this data on-demand. + void generateFontMetrics(const SkTypefaceProxy& typefaceProxy, + const SkScalerContextRec& rec, + SkPaint::FontMetrics* metrics); + void generateMetricsAndImage(const SkTypefaceProxy& typefaceProxy, + const SkScalerContextRec& rec, + SkArenaAlloc* alloc, + SkGlyph* glyph); + void generatePath(const SkTypefaceProxy& typefaceProxy, + const SkScalerContextRec& rec, + SkGlyphID glyphID, + SkPath* path); private: - sk_sp<SkTypeface> decodeTypeface(const void* buf, size_t len); - - // TODO: Figure out how to manage the entries for the following maps. - SkTHashMap<SkFontID, sk_sp<SkTypefaceProxy>> fMapIdToTypeface; + class DiscardableStrikePinner; - SkStrikeCacheClientRPC fClientRPC; + sk_sp<SkTypeface> addTypeface(const WireTypeface& wire); - std::vector<uint8_t> fBuffer; + SkTHashMap<SkFontID, sk_sp<SkTypeface>> fRemoteFontIdToTypeface; + sk_sp<DiscardableHandleManager> fDiscardableHandleManager; }; -#endif // SkRemoteGlyphCache_DEFINED +#endif // SkRemoteGlyphCachePriv_DEFINED |