aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkRemoteGlyphCache.h
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@google.com>2018-05-02 13:54:11 +0000
committerGravatar Mike Klein <mtklein@google.com>2018-05-02 13:55:08 +0000
commit8a232023e192b30a2148b0c07116e43f800d3233 (patch)
tree17a3a809cbb7e0d50efc9c758c350c1957c77e73 /src/core/SkRemoteGlyphCache.h
parentc76e26a6bb8af9ac9b0c7226851b2ded12d18687 (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.h288
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