diff options
author | Mike Klein <mtklein@google.com> | 2018-05-02 13:54:11 +0000 |
---|---|---|
committer | Mike Klein <mtklein@google.com> | 2018-05-02 13:55:08 +0000 |
commit | 8a232023e192b30a2148b0c07116e43f800d3233 (patch) | |
tree | 17a3a809cbb7e0d50efc9c758c350c1957c77e73 /src/core/SkRemoteGlyphCache.h | |
parent | c76e26a6bb8af9ac9b0c7226851b2ded12d18687 (diff) |
Revert "fonts: Set up remote glyph caching to push fonts."
This reverts commit 101d56359a5a5dc3b8a2a4149ac171e25eb0bec0.
Reason for revert: 5 of 5
Original change's description:
> fonts: Set up remote glyph caching to push fonts.
>
> Currently the SkStrikeClient is designed to pull fonts from the server
> on demand, and to pre-fetch a batched request by analyzing the ops using
> a SkTextBlobCacheDiffCanvas. This change modifies the design to support
> a push based model, where the server pushes fonts required by the client
> and sets up the requisite SkGlyphCaches on the client prior to
> rasterizing the ops.
>
> This model still relies on the SkTextBlobCacheDiffCanvas for analyzing
> the glyphs required for rasterizing an op. The glyph caches required for
> raster are locked and missing glyphs to be sent to the client are tracked
> by the SkStrikeServer. The embedder can serialize this font data at any
> point, but must ensure that this data is deserialized by the
> SkStrikeClient at the remote end, before rasterizing any ops analyzed
> prior to serialization. Any refs on the caches are released once the
> font data is serialized by the server.
>
> The locking of glyph caches relies on the embedder providing discardable
> handles. These handles can be created on the server and serialized to be
> sent to the client, and map to an instance of SkGlyphCache. This allows
> the server to control the lifetime of the caches on the client.
>
> Bug: skia:7515
> Change-Id: Id39f346b47b60899778404bbd0429ee811d0e53b
> Reviewed-on: https://skia-review.googlesource.com/120283
> Commit-Queue: Khusal Sagar <khushalsagar@chromium.org>
> Reviewed-by: Herb Derby <herb@google.com>
TBR=mtklein@google.com,herb@google.com,khushalsagar@chromium.org
Change-Id: If72caf968ddcbf70b8b9d71782a2339a118ed202
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:7515
Reviewed-on: https://skia-review.googlesource.com/125264
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
Diffstat (limited to 'src/core/SkRemoteGlyphCache.h')
-rw-r--r-- | src/core/SkRemoteGlyphCache.h | 288 |
1 files changed, 142 insertions, 146 deletions
diff --git a/src/core/SkRemoteGlyphCache.h b/src/core/SkRemoteGlyphCache.h index b210f1c6d7..ff905862fa 100644 --- a/src/core/SkRemoteGlyphCache.h +++ b/src/core/SkRemoteGlyphCache.h @@ -5,196 +5,192 @@ * found in the LICENSE file. */ -#ifndef SkRemoteGlyphCachePriv_DEFINED -#define SkRemoteGlyphCachePriv_DEFINED +#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 "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" -class Serializer; -class SkDescriptor; -class SkGlyphCache; -struct SkPackedGlyphID; -class SkScalerContextRecDescriptor; -class SkTextBlobRunIterator; -class SkTypefaceProxy; -struct WireTypeface; +// The client uses a SkStrikeCacheClientRPC to send and receive data. +using SkStrikeCacheClientRPC = std::function<sk_sp<SkData>(const SkData&)>; -class SkStrikeServer; +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(); + } -struct SkDescriptorMapOperators { - size_t operator()(const SkDescriptor* key) const; - bool operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const; +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; }; -template <typename T> -using SkDescriptorMap = std::unordered_map<const SkDescriptor*, T, SkDescriptorMapOperators, - SkDescriptorMapOperators>; +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>>(); +}; -using SkDescriptorSet = - std::unordered_set<const SkDescriptor*, 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; -// 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 { +private: + SkDescriptorMap<SkStrikeDifferences> fDescriptorToDifferencesMap{16}; +}; + +class SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas { public: - SkTextBlobCacheDiffCanvas(int width, int height, const SkMatrix& deviceMatrix, - const SkSurfaceProps& props, SkStrikeServer* strikeserver); - ~SkTextBlobCacheDiffCanvas() override; + SkTextBlobCacheDiffCanvas(int width, int height, + const SkMatrix& deviceMatrix, + const SkSurfaceProps& props, + SkScalerContextFlags flags, + SkStrikeCacheDifferenceSpec* strikeDiffs); protected: - SkCanvas::SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override; + 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; - SkStrikeServer* const fStrikeServer; -}; + const SkScalerContextFlags fScalerContextFlags; -using SkDiscardableHandleId = uint32_t; + SkStrikeCacheDifferenceSpec* const fStrikeCacheDiff; +}; -// This class is not thread-safe. -class SK_API SkStrikeServer { +class 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(); ~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> 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>); + // embedding clients call these methods + void serve(const SkData&, std::vector<uint8_t>*); + + void prepareSerializeProcs(SkSerialProcs* procs); + + // mostly called internally by Skia + SkScalerContext* generateScalerContext( + const SkScalerContextRecDescriptor& desc, SkFontID typefaceId); private: - SkDescriptorMap<std::unique_ptr<SkGlyphCacheState>> fRemoteGlyphStateMap; - DiscardableHandleManager* const fDiscardableHandleManager; - SkTHashSet<SkFontID> fCachedTypefaces; + using DescriptorToContextMap = SkTHashMap<SkScalerContextRecDescriptor, + std::unique_ptr<SkScalerContext>, + SkScalerContextRecDescriptor::Hash>; + + sk_sp<SkData> encodeTypeface(SkTypeface* tf); - // State cached until the next serialization. - SkDescriptorSet fLockedDescs; - std::vector<WireTypeface> fTypefacesToSend; + int fOpCount = 0; + SkTHashMap<SkFontID, sk_sp<SkTypeface>> fTypefaceMap; + DescriptorToContextMap fScalerContextMap; }; -class SK_API SkStrikeClient { +class SkStrikeClient { public: - // 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; - }; + SkStrikeClient(SkStrikeCacheClientRPC); - 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); + // embedding clients call these methods + void primeStrikeCache(const SkStrikeCacheDifferenceSpec&); + void prepareDeserializeProcs(SkDeserialProcs* procs); + + // 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); private: - class DiscardableStrikePinner; + 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; - sk_sp<SkTypeface> addTypeface(const WireTypeface& wire); + SkStrikeCacheClientRPC fClientRPC; - SkTHashMap<SkFontID, sk_sp<SkTypeface>> fRemoteFontIdToTypeface; - sk_sp<DiscardableHandleManager> fDiscardableHandleManager; + std::vector<uint8_t> fBuffer; }; -#endif // SkRemoteGlyphCachePriv_DEFINED +#endif // SkRemoteGlyphCache_DEFINED |