blob: 7aaebde2e0cff0dbd7d800f0fabdc501aee27d65 [file] [log] [blame]
Herb Derbyb2922f62018-01-26 16:47:54 -05001/*
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#include "SkRemoteGlyphCache.h"
9
Herb Derby97be88f2018-03-21 16:23:49 -040010#include <iterator>
11#include <memory>
Mike Klein79aea6a2018-06-11 10:45:26 -040012#include <new>
Khushal38a08432018-05-02 10:29:37 -070013#include <string>
Herb Derby97be88f2018-03-21 16:23:49 -040014#include <tuple>
15
16#include "SkDevice.h"
Khushal51371a42018-05-17 10:41:40 -070017#include "SkDraw.h"
Herb Derby1a9971e2018-07-19 13:41:15 -040018#include "SkGlyphRun.h"
Mike Reed6be47152018-10-05 10:54:15 -040019#include "SkGlyphCache.h"
Herb Derbyd2fec232018-08-23 18:44:45 -040020#include "SkRemoteGlyphCacheImpl.h"
Herb Derbydce19a72018-04-18 16:02:17 -040021#include "SkStrikeCache.h"
Herb Derby811a6722019-01-10 13:58:05 -050022#include "SkTLazy.h"
Khushal38a08432018-05-02 10:29:37 -070023#include "SkTraceEvent.h"
Herb Derby97be88f2018-03-21 16:23:49 -040024#include "SkTypeface_remote.h"
25
Khushal51371a42018-05-17 10:41:40 -070026#if SK_SUPPORT_GPU
27#include "GrDrawOpAtlas.h"
Herb Derby26cbe512018-05-24 14:39:01 -040028#include "text/GrTextContext.h"
Khushal51371a42018-05-17 10:41:40 -070029#endif
30
Khushal38a08432018-05-02 10:29:37 -070031static SkDescriptor* auto_descriptor_from_desc(const SkDescriptor* source_desc,
32 SkFontID font_id,
33 SkAutoDescriptor* ad) {
34 ad->reset(source_desc->getLength());
35 auto* desc = ad->getDesc();
36 desc->init();
37
38 // Rec.
39 {
40 uint32_t size;
41 auto ptr = source_desc->findEntry(kRec_SkDescriptorTag, &size);
42 SkScalerContextRec rec;
43 std::memcpy(&rec, ptr, size);
44 rec.fFontID = font_id;
45 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
46 }
47
Mike Klein48fb8d82018-10-10 13:10:24 -040048 // Effects.
Khushal38a08432018-05-02 10:29:37 -070049 {
50 uint32_t size;
Mike Klein48fb8d82018-10-10 13:10:24 -040051 auto ptr = source_desc->findEntry(kEffects_SkDescriptorTag, &size);
52 if (ptr) { desc->addEntry(kEffects_SkDescriptorTag, size, ptr); }
Khushal38a08432018-05-02 10:29:37 -070053 }
54
55 desc->computeChecksum();
56 return desc;
57}
58
Herb Derby48415e92018-09-11 17:29:53 -040059enum DescriptorType : bool { kKey = false, kDevice = true };
60static const SkDescriptor* create_descriptor(
Herb Derbye7f662b2018-12-17 12:12:56 -050061 DescriptorType type, const SkPaint& paint, const SkFont& font, const SkMatrix& m,
Herb Derby48415e92018-09-11 17:29:53 -040062 const SkSurfaceProps& props, SkScalerContextFlags flags,
63 SkAutoDescriptor* ad, SkScalerContextEffects* effects) {
64 SkScalerContextRec deviceRec;
65 bool enableTypefaceFiltering = (type == kDevice);
66 SkScalerContext::MakeRecAndEffects(
Herb Derbyc3415002018-11-08 16:40:26 -050067 font, paint, props, flags, m, &deviceRec, effects, enableTypefaceFiltering);
Herb Derby48415e92018-09-11 17:29:53 -040068 return SkScalerContext::AutoDescriptorGivenRecAndEffects(deviceRec, *effects, ad);
69}
70
Herb Derby97be88f2018-03-21 16:23:49 -040071// -- Serializer ----------------------------------------------------------------------------------
72
Khushal38a08432018-05-02 10:29:37 -070073size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); }
Herb Derby46117c82018-04-03 18:44:34 -040074
Herb Derby97be88f2018-03-21 16:23:49 -040075class Serializer {
76public:
Herb Derby46117c82018-04-03 18:44:34 -040077 Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} { }
Herb Derby97be88f2018-03-21 16:23:49 -040078
Herb Derby97be88f2018-03-21 16:23:49 -040079 template <typename T, typename... Args>
Khushal38a08432018-05-02 10:29:37 -070080 T* emplace(Args&&... args) {
Herb Derby46117c82018-04-03 18:44:34 -040081 auto result = allocate(sizeof(T), alignof(T));
82 return new (result) T{std::forward<Args>(args)...};
Herb Derby97be88f2018-03-21 16:23:49 -040083 }
84
Khushal38a08432018-05-02 10:29:37 -070085 template <typename T>
86 void write(const T& data) {
87 T* result = (T*)allocate(sizeof(T), alignof(T));
88 memcpy(result, &data, sizeof(T));
89 }
90
91 template <typename T>
92 T* allocate() {
93 T* result = (T*)allocate(sizeof(T), alignof(T));
94 return result;
95 }
96
Herb Derby97be88f2018-03-21 16:23:49 -040097 void writeDescriptor(const SkDescriptor& desc) {
Khushal38a08432018-05-02 10:29:37 -070098 write(desc.getLength());
Herb Derby46117c82018-04-03 18:44:34 -040099 auto result = allocate(desc.getLength(), alignof(SkDescriptor));
100 memcpy(result, &desc, desc.getLength());
Herb Derby97be88f2018-03-21 16:23:49 -0400101 }
102
Herb Derby46117c82018-04-03 18:44:34 -0400103 void* allocate(size_t size, size_t alignment) {
104 size_t aligned = pad(fBuffer->size(), alignment);
105 fBuffer->resize(aligned + size);
106 return &(*fBuffer)[aligned];
107 }
108
Khushal51371a42018-05-17 10:41:40 -0700109private:
Herb Derby46117c82018-04-03 18:44:34 -0400110 std::vector<uint8_t>* fBuffer;
Herb Derby97be88f2018-03-21 16:23:49 -0400111};
112
113// -- Deserializer -------------------------------------------------------------------------------
Khushal38a08432018-05-02 10:29:37 -0700114// Note that the Deserializer is reading untrusted data, we need to guard against invalid data.
Herb Derby97be88f2018-03-21 16:23:49 -0400115class Deserializer {
116public:
Khushal38a08432018-05-02 10:29:37 -0700117 Deserializer(const volatile char* memory, size_t memorySize)
118 : fMemory(memory), fMemorySize(memorySize) {}
Herb Derby97be88f2018-03-21 16:23:49 -0400119
120 template <typename T>
Khushal38a08432018-05-02 10:29:37 -0700121 bool read(T* val) {
122 auto* result = this->ensureAtLeast(sizeof(T), alignof(T));
123 if (!result) return false;
124
125 memcpy(val, const_cast<const char*>(result), sizeof(T));
126 return true;
Herb Derby97be88f2018-03-21 16:23:49 -0400127 }
128
Khushal38a08432018-05-02 10:29:37 -0700129 bool readDescriptor(SkAutoDescriptor* ad) {
130 uint32_t desc_length = 0u;
131 if (!read<uint32_t>(&desc_length)) return false;
132
133 auto* result = this->ensureAtLeast(desc_length, alignof(SkDescriptor));
134 if (!result) return false;
135
136 ad->reset(desc_length);
137 memcpy(ad->getDesc(), const_cast<const char*>(result), desc_length);
138 return true;
Herb Derby97be88f2018-03-21 16:23:49 -0400139 }
140
Khushal51371a42018-05-17 10:41:40 -0700141 const volatile void* read(size_t size, size_t alignment) {
142 return this->ensureAtLeast(size, alignment);
Herb Derby97be88f2018-03-21 16:23:49 -0400143 }
144
Herb Derby97be88f2018-03-21 16:23:49 -0400145private:
Khushal38a08432018-05-02 10:29:37 -0700146 const volatile char* ensureAtLeast(size_t size, size_t alignment) {
147 size_t padded = pad(fBytesRead, alignment);
148
149 // Not enough data
150 if (padded + size > fMemorySize) return nullptr;
151
152 auto* result = fMemory + padded;
153 fBytesRead = padded + size;
154 return result;
155 }
156
157 // Note that we read each piece of memory only once to guard against TOCTOU violations.
158 const volatile char* fMemory;
159 size_t fMemorySize;
160 size_t fBytesRead = 0u;
Herb Derby97be88f2018-03-21 16:23:49 -0400161};
162
Khushal51371a42018-05-17 10:41:40 -0700163// Paths use a SkWriter32 which requires 4 byte alignment.
164static const size_t kPathAlignment = 4u;
165
166bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkGlyphCache* cache) {
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700167 uint64_t pathSize = 0u;
168 if (!deserializer->read<uint64_t>(&pathSize)) return false;
Khushal51371a42018-05-17 10:41:40 -0700169
170 if (pathSize == 0u) return true;
171
172 auto* path = deserializer->read(pathSize, kPathAlignment);
173 if (!path) return false;
174
175 return cache->initializePath(glyph, path, pathSize);
176}
177
Khushal38a08432018-05-02 10:29:37 -0700178size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const {
179 return key->getChecksum();
Khushala05a31a2018-06-08 13:00:40 -0700180}
Herb Derby97be88f2018-03-21 16:23:49 -0400181
Khushala05a31a2018-06-08 13:00:40 -0700182bool SkDescriptorMapOperators::operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const {
183 return *lhs == *rhs;
184}
Herb Derby97be88f2018-03-21 16:23:49 -0400185
Herb Derbyd2fec232018-08-23 18:44:45 -0400186struct StrikeSpec {
187 StrikeSpec() {}
188 StrikeSpec(SkFontID typefaceID_, SkDiscardableHandleId discardableHandleId_)
189 : typefaceID{typefaceID_}, discardableHandleId(discardableHandleId_) {}
190 SkFontID typefaceID = 0u;
191 SkDiscardableHandleId discardableHandleId = 0u;
192 /* desc */
193 /* n X (glyphs ids) */
194};
195
Herb Derby30a9d262018-04-06 16:49:57 -0400196// -- TrackLayerDevice -----------------------------------------------------------------------------
Herb Derby447b1982018-08-23 18:19:03 -0400197SkTextBlobCacheDiffCanvas::TrackLayerDevice::TrackLayerDevice(
198 const SkIRect& bounds, const SkSurfaceProps& props, SkStrikeServer* server,
199 const SkTextBlobCacheDiffCanvas::Settings& settings)
Herb Derbyd2fec232018-08-23 18:44:45 -0400200 : SkNoPixelsDevice(bounds, props)
201 , fStrikeServer(server)
202 , fSettings(settings)
203 , fPainter{props, kUnknown_SkColorType, SkScalerContextFlags::kFakeGammaAndBoostContrast} {
Herb Derby447b1982018-08-23 18:19:03 -0400204 SkASSERT(fStrikeServer);
205}
Khushala05a31a2018-06-08 13:00:40 -0700206
Herb Derby447b1982018-08-23 18:19:03 -0400207SkBaseDevice* SkTextBlobCacheDiffCanvas::TrackLayerDevice::onCreateDevice(
208 const CreateInfo& cinfo, const SkPaint*) {
209 const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
210 return new TrackLayerDevice(this->getGlobalBounds(), surfaceProps, fStrikeServer, fSettings);
211}
212
213void SkTextBlobCacheDiffCanvas::TrackLayerDevice::drawGlyphRunList(
214 const SkGlyphRunList& glyphRunList) {
215 for (auto& glyphRun : glyphRunList) {
Herb Derby95e17602018-12-06 17:11:43 -0500216 this->processGlyphRun(glyphRunList.origin(), glyphRun, glyphRunList.paint());
Khushala05a31a2018-06-08 13:00:40 -0700217 }
Herb Derby447b1982018-08-23 18:19:03 -0400218}
219
Herb Derby97be88f2018-03-21 16:23:49 -0400220// -- SkTextBlobCacheDiffCanvas -------------------------------------------------------------------
Khushal3e7548c2018-05-23 15:45:01 -0700221SkTextBlobCacheDiffCanvas::Settings::Settings() = default;
Khushal3e7548c2018-05-23 15:45:01 -0700222
Khushal38a08432018-05-02 10:29:37 -0700223SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height,
224 const SkMatrix& deviceMatrix,
225 const SkSurfaceProps& props,
Khushala05a31a2018-06-08 13:00:40 -0700226 SkStrikeServer* strikeServer,
227 Settings settings)
228 : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkIRect::MakeWH(width, height), props,
229 strikeServer, settings)} {}
Khushal38a08432018-05-02 10:29:37 -0700230
Herb Derby90c7d9b2018-09-07 17:00:36 -0400231SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(
232 int width, int height, const SkSurfaceProps& props,
233 SkStrikeServer* strikeServer, Settings settings)
234 : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(
235 SkIRect::MakeWH(width, height), props, strikeServer, settings)} {}
236
Khushal38a08432018-05-02 10:29:37 -0700237SkTextBlobCacheDiffCanvas::~SkTextBlobCacheDiffCanvas() = default;
Herb Derby97be88f2018-03-21 16:23:49 -0400238
239SkCanvas::SaveLayerStrategy SkTextBlobCacheDiffCanvas::getSaveLayerStrategy(
Khushala05a31a2018-06-08 13:00:40 -0700240 const SaveLayerRec& rec) {
Herb Derby97be88f2018-03-21 16:23:49 -0400241 return kFullLayer_SaveLayerStrategy;
242}
243
Mike Reed148b7fd2018-12-18 17:38:18 -0500244bool SkTextBlobCacheDiffCanvas::onDoSaveBehind(const SkRect*) {
245 return false;
246}
247
Khushala05a31a2018-06-08 13:00:40 -0700248void SkTextBlobCacheDiffCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
249 const SkPaint& paint) {
250 SkCanvas::onDrawTextBlob(blob, x, y, paint);
Khushale70c5fb2018-05-31 13:38:57 -0700251}
252
Herb Derby97be88f2018-03-21 16:23:49 -0400253struct WireTypeface {
Khushal38a08432018-05-02 10:29:37 -0700254 WireTypeface() = default;
255 WireTypeface(SkFontID typeface_id, int glyph_count, SkFontStyle style, bool is_fixed)
256 : typefaceID(typeface_id), glyphCount(glyph_count), style(style), isFixed(is_fixed) {}
257
Herb Derby97be88f2018-03-21 16:23:49 -0400258 SkFontID typefaceID;
259 int glyphCount;
260 SkFontStyle style;
261 bool isFixed;
262};
263
Khushal38a08432018-05-02 10:29:37 -0700264// SkStrikeServer -----------------------------------------
Herb Derbyb2922f62018-01-26 16:47:54 -0500265
Khushal38a08432018-05-02 10:29:37 -0700266SkStrikeServer::SkStrikeServer(DiscardableHandleManager* discardableHandleManager)
267 : fDiscardableHandleManager(discardableHandleManager) {
268 SkASSERT(fDiscardableHandleManager);
Mike Klein8a232022018-05-02 13:54:11 +0000269}
Herb Derby46117c82018-04-03 18:44:34 -0400270
Khushal38a08432018-05-02 10:29:37 -0700271SkStrikeServer::~SkStrikeServer() = default;
Herb Derby46117c82018-04-03 18:44:34 -0400272
Khushal38a08432018-05-02 10:29:37 -0700273sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) {
Khushal38c7a2e2018-10-16 13:50:34 -0700274 auto* data = fSerializedTypefaces.find(SkTypeface::UniqueID(tf));
275 if (data) {
276 return *data;
277 }
278
Khushal38a08432018-05-02 10:29:37 -0700279 WireTypeface wire(SkTypeface::UniqueID(tf), tf->countGlyphs(), tf->fontStyle(),
280 tf->isFixedPitch());
Khushal38c7a2e2018-10-16 13:50:34 -0700281 data = fSerializedTypefaces.set(SkTypeface::UniqueID(tf),
282 SkData::MakeWithCopy(&wire, sizeof(wire)));
283 return *data;
Mike Klein8a232022018-05-02 13:54:11 +0000284}
285
Khushal38a08432018-05-02 10:29:37 -0700286void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
Herb Derbyaca2b9e2018-08-28 15:33:19 -0400287 if (fLockedDescs.empty() && fTypefacesToSend.empty()) {
288 return;
289 }
Mike Klein8a232022018-05-02 13:54:11 +0000290
Khushal38a08432018-05-02 10:29:37 -0700291 Serializer serializer(memory);
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700292 serializer.emplace<uint64_t>(fTypefacesToSend.size());
Khushal38a08432018-05-02 10:29:37 -0700293 for (const auto& tf : fTypefacesToSend) serializer.write<WireTypeface>(tf);
294 fTypefacesToSend.clear();
Mike Klein8a232022018-05-02 13:54:11 +0000295
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700296 serializer.emplace<uint64_t>(fLockedDescs.size());
Khushal38a08432018-05-02 10:29:37 -0700297 for (const auto* desc : fLockedDescs) {
298 auto it = fRemoteGlyphStateMap.find(desc);
299 SkASSERT(it != fRemoteGlyphStateMap.end());
Khushal38a08432018-05-02 10:29:37 -0700300 it->second->writePendingGlyphs(&serializer);
301 }
302 fLockedDescs.clear();
Mike Klein8a232022018-05-02 13:54:11 +0000303}
304
Khushal38a08432018-05-02 10:29:37 -0700305SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
Khushal51371a42018-05-17 10:41:40 -0700306 const SkPaint& paint,
Herb Derbye7f662b2018-12-17 12:12:56 -0500307 const SkFont& font,
Herb Derbyc03716d2018-09-17 11:39:51 -0400308 const SkSurfaceProps& props,
309 const SkMatrix& matrix,
Khushal3e7548c2018-05-23 15:45:01 -0700310 SkScalerContextFlags flags,
Khushal51371a42018-05-17 10:41:40 -0700311 SkScalerContextEffects* effects) {
Herb Derby48415e92018-09-11 17:29:53 -0400312 SkAutoDescriptor keyAutoDesc;
Herb Derbye7f662b2018-12-17 12:12:56 -0500313 auto keyDesc = create_descriptor(
314 kKey, paint, font, matrix, props, flags, &keyAutoDesc, effects);
Herb Derby48415e92018-09-11 17:29:53 -0400315
316 // In cases where tracing is turned off, make sure not to get an unused function warning.
317 // Lambdaize the function.
318 TRACE_EVENT1("skia", "RecForDesc", "rec",
319 TRACE_STR_COPY(
320 [keyDesc](){
321 auto ptr = keyDesc->findEntry(kRec_SkDescriptorTag, nullptr);
322 SkScalerContextRec rec;
323 std::memcpy(&rec, ptr, sizeof(rec));
324 return rec.dump();
325 }().c_str()
326 )
327 );
Mike Klein8a232022018-05-02 13:54:11 +0000328
Khushal38a08432018-05-02 10:29:37 -0700329 // Already locked.
Herb Derby48415e92018-09-11 17:29:53 -0400330 if (fLockedDescs.find(keyDesc) != fLockedDescs.end()) {
331 auto it = fRemoteGlyphStateMap.find(keyDesc);
Khushal38a08432018-05-02 10:29:37 -0700332 SkASSERT(it != fRemoteGlyphStateMap.end());
Herb Derbyee2a3f32018-08-24 11:43:58 -0400333 SkGlyphCacheState* cache = it->second.get();
Herb Derbyfc1cb222018-12-17 13:50:00 -0500334 cache->setFontAndEffects(font, SkScalerContextEffects{paint});
Herb Derbyee2a3f32018-08-24 11:43:58 -0400335 return cache;
Mike Klein8a232022018-05-02 13:54:11 +0000336 }
Khushal38a08432018-05-02 10:29:37 -0700337
338 // Try to lock.
Herb Derby48415e92018-09-11 17:29:53 -0400339 auto it = fRemoteGlyphStateMap.find(keyDesc);
Khushal38a08432018-05-02 10:29:37 -0700340 if (it != fRemoteGlyphStateMap.end()) {
Herb Derbyee2a3f32018-08-24 11:43:58 -0400341 SkGlyphCacheState* cache = it->second.get();
Khushal1c94a8f2018-07-23 13:40:37 -0700342#ifdef SK_DEBUG
Herb Derby48415e92018-09-11 17:29:53 -0400343 SkScalerContextEffects deviceEffects;
344 SkAutoDescriptor deviceAutoDesc;
345 auto deviceDesc = create_descriptor(
Herb Derbye7f662b2018-12-17 12:12:56 -0500346 kDevice, paint, font, matrix, props, flags, &deviceAutoDesc, &deviceEffects);
Herb Derbyee2a3f32018-08-24 11:43:58 -0400347 SkASSERT(cache->getDeviceDescriptor() == *deviceDesc);
Khushal1c94a8f2018-07-23 13:40:37 -0700348#endif
Khushalfa8ff092018-06-06 17:46:38 -0700349 bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId());
Khushal38a08432018-05-02 10:29:37 -0700350 if (locked) {
351 fLockedDescs.insert(it->first);
Herb Derbyfc1cb222018-12-17 13:50:00 -0500352 cache->setFontAndEffects(font, SkScalerContextEffects{paint});
Herb Derbyee2a3f32018-08-24 11:43:58 -0400353 return cache;
Khushal38a08432018-05-02 10:29:37 -0700354 }
355
356 // If the lock failed, the entry was deleted on the client. Remove our
357 // tracking.
358 fRemoteGlyphStateMap.erase(it);
359 }
360
Herb Derbye7f662b2018-12-17 12:12:56 -0500361 auto* tf = font.getTypeface();
Herb Derbye1f566f2018-05-03 17:05:30 -0400362 const SkFontID typefaceId = tf->uniqueID();
363 if (!fCachedTypefaces.contains(typefaceId)) {
364 fCachedTypefaces.add(typefaceId);
365 fTypefacesToSend.emplace_back(typefaceId, tf->countGlyphs(), tf->fontStyle(),
Khushal38a08432018-05-02 10:29:37 -0700366 tf->isFixedPitch());
367 }
368
Herb Derby48415e92018-09-11 17:29:53 -0400369 SkScalerContextEffects deviceEffects;
370 SkAutoDescriptor deviceAutoDesc;
371 auto deviceDesc = create_descriptor(
Herb Derbye7f662b2018-12-17 12:12:56 -0500372 kDevice, paint, font, matrix, props, flags, &deviceAutoDesc, &deviceEffects);
Herb Derby48415e92018-09-11 17:29:53 -0400373
374 auto context = tf->createScalerContext(deviceEffects, deviceDesc);
375
Herb Derbyee2a3f32018-08-24 11:43:58 -0400376 // Create a new cache state and insert it into the map.
Herb Derbye1f566f2018-05-03 17:05:30 -0400377 auto newHandle = fDiscardableHandleManager->createHandle();
Herb Derby48415e92018-09-11 17:29:53 -0400378 auto cacheState = skstd::make_unique<SkGlyphCacheState>(
379 *keyDesc, *deviceDesc, std::move(context), newHandle);
380
Herb Derbye1f566f2018-05-03 17:05:30 -0400381 auto* cacheStatePtr = cacheState.get();
Khushal38a08432018-05-02 10:29:37 -0700382
Herb Derby48415e92018-09-11 17:29:53 -0400383 fLockedDescs.insert(&cacheStatePtr->getKeyDescriptor());
384 fRemoteGlyphStateMap[&cacheStatePtr->getKeyDescriptor()] = std::move(cacheState);
Khushalcf33b1b2018-08-29 16:16:25 -0700385
386 checkForDeletedEntries();
Herb Derbyfc1cb222018-12-17 13:50:00 -0500387
Herb Derbyfc1cb222018-12-17 13:50:00 -0500388 cacheStatePtr->setFontAndEffects(font, SkScalerContextEffects{paint});
Herb Derbye1f566f2018-05-03 17:05:30 -0400389 return cacheStatePtr;
Mike Klein8a232022018-05-02 13:54:11 +0000390}
391
Khushalcf33b1b2018-08-29 16:16:25 -0700392void SkStrikeServer::checkForDeletedEntries() {
393 auto it = fRemoteGlyphStateMap.begin();
394 while (fRemoteGlyphStateMap.size() > fMaxEntriesInDescriptorMap &&
395 it != fRemoteGlyphStateMap.end()) {
396 if (fDiscardableHandleManager->isHandleDeleted(it->second->discardableHandleId())) {
397 it = fRemoteGlyphStateMap.erase(it);
398 } else {
399 ++it;
400 }
401 }
402}
403
Herb Derbyd2fec232018-08-23 18:44:45 -0400404// -- SkGlyphCacheState ----------------------------------------------------------------------------
405SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState(
Herb Derby48415e92018-09-11 17:29:53 -0400406 const SkDescriptor& keyDescriptor,
407 const SkDescriptor& deviceDescriptor,
408 std::unique_ptr<SkScalerContext> context,
409 uint32_t discardableHandleId)
410 : fKeyDescriptor{keyDescriptor}
411 , fDeviceDescriptor{deviceDescriptor}
412 , fDiscardableHandleId(discardableHandleId)
413 , fIsSubpixel{context->isSubpixel()}
414 , fAxisAlignmentForHText{context->computeAxisAlignmentForHText()}
415 // N.B. context must come last because it is used above.
416 , fContext{std::move(context)} {
417 SkASSERT(fKeyDescriptor.getDesc() != nullptr);
418 SkASSERT(fDeviceDescriptor.getDesc() != nullptr);
419 SkASSERT(fContext != nullptr);
Herb Derbyd2fec232018-08-23 18:44:45 -0400420}
421
422SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState() = default;
423
Herb Derbyb2c72162018-08-23 16:16:31 -0400424void SkStrikeServer::SkGlyphCacheState::addGlyph(SkPackedGlyphID glyph, bool asPath) {
Khushal51371a42018-05-17 10:41:40 -0700425 auto* cache = asPath ? &fCachedGlyphPaths : &fCachedGlyphImages;
426 auto* pending = asPath ? &fPendingGlyphPaths : &fPendingGlyphImages;
427
Khushal38a08432018-05-02 10:29:37 -0700428 // Already cached.
Herb Derbyaca2b9e2018-08-28 15:33:19 -0400429 if (cache->contains(glyph)) {
430 return;
431 }
Khushal38a08432018-05-02 10:29:37 -0700432
Herb Derby48415e92018-09-11 17:29:53 -0400433 // A glyph is going to be sent. Make sure we have a scaler context to send it.
434 this->ensureScalerContext();
435
Khushal38a08432018-05-02 10:29:37 -0700436 // Serialize and cache. Also create the scalar context to use when serializing
437 // this glyph.
Khushal51371a42018-05-17 10:41:40 -0700438 cache->add(glyph);
439 pending->push_back(glyph);
Khushal38a08432018-05-02 10:29:37 -0700440}
441
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700442static void writeGlyph(SkGlyph* glyph, Serializer* serializer) {
443 serializer->write<SkPackedGlyphID>(glyph->getPackedID());
444 serializer->write<float>(glyph->fAdvanceX);
445 serializer->write<float>(glyph->fAdvanceY);
446 serializer->write<uint16_t>(glyph->fWidth);
447 serializer->write<uint16_t>(glyph->fHeight);
448 serializer->write<int16_t>(glyph->fTop);
449 serializer->write<int16_t>(glyph->fLeft);
450 serializer->write<int8_t>(glyph->fForceBW);
451 serializer->write<uint8_t>(glyph->fMaskFormat);
452}
453
Khushal38a08432018-05-02 10:29:37 -0700454void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serializer) {
Khushalfa8ff092018-06-06 17:46:38 -0700455 // TODO(khushalsagar): Write a strike only if it has any pending glyphs.
456 serializer->emplace<bool>(this->hasPendingGlyphs());
457 if (!this->hasPendingGlyphs()) {
Herb Derbyfc1cb222018-12-17 13:50:00 -0500458 this->resetScalerContext();
Khushalfa8ff092018-06-06 17:46:38 -0700459 return;
460 }
461
Khushal38a08432018-05-02 10:29:37 -0700462 // Write the desc.
Khushal51371a42018-05-17 10:41:40 -0700463 serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId);
Herb Derby48415e92018-09-11 17:29:53 -0400464 serializer->writeDescriptor(*fKeyDescriptor.getDesc());
Khushal38a08432018-05-02 10:29:37 -0700465
466 // Write FontMetrics.
Khushal51371a42018-05-17 10:41:40 -0700467 // TODO(khushalsagar): Do we need to re-send each time?
Mike Reedb5784ac2018-11-12 09:35:15 -0500468 SkFontMetrics fontMetrics;
Khushal38a08432018-05-02 10:29:37 -0700469 fContext->getFontMetrics(&fontMetrics);
Mike Reedb5784ac2018-11-12 09:35:15 -0500470 serializer->write<SkFontMetrics>(fontMetrics);
Khushal38a08432018-05-02 10:29:37 -0700471
Khushal51371a42018-05-17 10:41:40 -0700472 // Write glyphs images.
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700473 serializer->emplace<uint64_t>(fPendingGlyphImages.size());
Khushal51371a42018-05-17 10:41:40 -0700474 for (const auto& glyphID : fPendingGlyphImages) {
Herb Derbyf6fca262019-01-09 15:13:54 -0500475 SkGlyph glyph{glyphID};
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700476 fContext->getMetrics(&glyph);
477 writeGlyph(&glyph, serializer);
Khushal40adb3c2018-08-16 17:10:11 -0700478
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700479 auto imageSize = glyph.computeImageSize();
Khushal51371a42018-05-17 10:41:40 -0700480 if (imageSize == 0u) continue;
481
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700482 glyph.fImage = serializer->allocate(imageSize, glyph.formatAlignment());
483 fContext->getImage(glyph);
Khushal4010c792018-06-13 09:44:23 -0700484 // TODO: Generating the image can change the mask format, do we need to update it in the
485 // serialized glyph?
Mike Klein8a232022018-05-02 13:54:11 +0000486 }
Khushal51371a42018-05-17 10:41:40 -0700487 fPendingGlyphImages.clear();
488
489 // Write glyphs paths.
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700490 serializer->emplace<uint64_t>(fPendingGlyphPaths.size());
Khushal51371a42018-05-17 10:41:40 -0700491 for (const auto& glyphID : fPendingGlyphPaths) {
Herb Derbyf6fca262019-01-09 15:13:54 -0500492 SkGlyph glyph{glyphID};
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700493 fContext->getMetrics(&glyph);
494 writeGlyph(&glyph, serializer);
Khushal51371a42018-05-17 10:41:40 -0700495 writeGlyphPath(glyphID, serializer);
496 }
497 fPendingGlyphPaths.clear();
Herb Derbyfc1cb222018-12-17 13:50:00 -0500498 this->resetScalerContext();
Khushal38a08432018-05-02 10:29:37 -0700499}
500
Herb Derbyb2c72162018-08-23 16:16:31 -0400501const SkGlyph& SkStrikeServer::SkGlyphCacheState::findGlyph(SkPackedGlyphID glyphID) {
Herb Derby46275232019-01-10 14:01:22 -0500502 SkGlyph* glyphPtr = fGlyphMap.findOrNull(glyphID);
503 if (glyphPtr == nullptr) {
504 glyphPtr = fAlloc.make<SkGlyph>(glyphID);
505 fGlyphMap.set(glyphPtr);
Herb Derby48415e92018-09-11 17:29:53 -0400506 this->ensureScalerContext();
Herb Derby46275232019-01-10 14:01:22 -0500507 fContext->getMetrics(glyphPtr);
Khushalfa8ff092018-06-06 17:46:38 -0700508 }
Herb Derbyb2c72162018-08-23 16:16:31 -0400509
Herb Derby46275232019-01-10 14:01:22 -0500510 return *glyphPtr;
Khushalfa8ff092018-06-06 17:46:38 -0700511}
512
Herb Derby48415e92018-09-11 17:29:53 -0400513void SkStrikeServer::SkGlyphCacheState::ensureScalerContext() {
514 if (fContext == nullptr) {
Herb Derbyfc1cb222018-12-17 13:50:00 -0500515 auto tf = fFont->getTypeface();
516 fContext = tf->createScalerContext(fEffects, fDeviceDescriptor.getDesc());
Herb Derbyd2fec232018-08-23 18:44:45 -0400517 }
518}
519
Herb Derbyfc1cb222018-12-17 13:50:00 -0500520void SkStrikeServer::SkGlyphCacheState::resetScalerContext() {
521 fContext.reset();
522 fFont = nullptr;
523}
524
525void SkStrikeServer::SkGlyphCacheState::setFontAndEffects(
526 const SkFont& font, SkScalerContextEffects effects) {
527 fFont = &font;
528 fEffects = effects;
Herb Derby48415e92018-09-11 17:29:53 -0400529}
530
Herb Derbyd2fec232018-08-23 18:44:45 -0400531SkVector SkStrikeServer::SkGlyphCacheState::rounding() const {
532 return SkGlyphCacheCommon::PixelRounding(fIsSubpixel, fAxisAlignmentForHText);
533}
534
535const SkGlyph& SkStrikeServer::SkGlyphCacheState::getGlyphMetrics(
536 SkGlyphID glyphID, SkPoint position) {
537 SkIPoint lookupPoint = SkGlyphCacheCommon::SubpixelLookup(fAxisAlignmentForHText, position);
538 SkPackedGlyphID packedGlyphID = fIsSubpixel ? SkPackedGlyphID{glyphID, lookupPoint}
539 : SkPackedGlyphID{glyphID};
540
541 return this->findGlyph(packedGlyphID);
542}
543
Herb Derby2d4f7cb2018-11-27 12:37:50 -0500544bool SkStrikeServer::SkGlyphCacheState::hasImage(const SkGlyph& glyph) {
545 // If a glyph has width and height, it must have an image available to it.
546 return !glyph.isEmpty();
547}
548
549bool SkStrikeServer::SkGlyphCacheState::hasPath(const SkGlyph& glyph) {
550 return const_cast<SkGlyph&>(glyph).addPath(fContext.get(), &fAlloc) != nullptr;
551}
552
Khushal51371a42018-05-17 10:41:40 -0700553void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID,
554 Serializer* serializer) const {
555 SkPath path;
556 if (!fContext->getPath(glyphID, &path)) {
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700557 serializer->write<uint64_t>(0u);
Khushal51371a42018-05-17 10:41:40 -0700558 return;
559 }
560
561 size_t pathSize = path.writeToMemory(nullptr);
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700562 serializer->write<uint64_t>(pathSize);
Khushal51371a42018-05-17 10:41:40 -0700563 path.writeToMemory(serializer->allocate(pathSize, kPathAlignment));
564}
565
Khushal38a08432018-05-02 10:29:37 -0700566// SkStrikeClient -----------------------------------------
Khushal38a08432018-05-02 10:29:37 -0700567class SkStrikeClient::DiscardableStrikePinner : public SkStrikePinner {
568public:
569 DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,
570 sk_sp<DiscardableHandleManager> manager)
571 : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {}
572
573 ~DiscardableStrikePinner() override = default;
574 bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); }
575
576private:
577 const SkDiscardableHandleId fDiscardableHandleId;
578 sk_sp<DiscardableHandleManager> fManager;
579};
580
Herb Derby5c0c7982018-06-21 15:15:50 -0400581SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,
582 bool isLogging,
583 SkStrikeCache* strikeCache)
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400584 : fDiscardableHandleManager(std::move(discardableManager))
Herb Derby5c0c7982018-06-21 15:15:50 -0400585 , fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()}
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400586 , fIsLogging{isLogging} {}
Khushal38a08432018-05-02 10:29:37 -0700587
588SkStrikeClient::~SkStrikeClient() = default;
589
590#define READ_FAILURE \
591 { \
592 SkDEBUGFAIL("Bad serialization"); \
593 return false; \
594 }
595
Herb Derby811a6722019-01-10 13:58:05 -0500596static bool readGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer) {
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700597 SkPackedGlyphID glyphID;
598 if (!deserializer->read<SkPackedGlyphID>(&glyphID)) return false;
Herb Derby811a6722019-01-10 13:58:05 -0500599 glyph.init(glyphID);
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700600 if (!deserializer->read<float>(&glyph->fAdvanceX)) return false;
601 if (!deserializer->read<float>(&glyph->fAdvanceY)) return false;
602 if (!deserializer->read<uint16_t>(&glyph->fWidth)) return false;
603 if (!deserializer->read<uint16_t>(&glyph->fHeight)) return false;
604 if (!deserializer->read<int16_t>(&glyph->fTop)) return false;
605 if (!deserializer->read<int16_t>(&glyph->fLeft)) return false;
606 if (!deserializer->read<int8_t>(&glyph->fForceBW)) return false;
607 if (!deserializer->read<uint8_t>(&glyph->fMaskFormat)) return false;
608 return true;
609}
610
Khushal38a08432018-05-02 10:29:37 -0700611bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) {
612 SkASSERT(memorySize != 0u);
613 Deserializer deserializer(static_cast<const volatile char*>(memory), memorySize);
614
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700615 uint64_t typefaceSize = 0u;
616 if (!deserializer.read<uint64_t>(&typefaceSize)) READ_FAILURE
Khushal38a08432018-05-02 10:29:37 -0700617
618 for (size_t i = 0; i < typefaceSize; ++i) {
619 WireTypeface wire;
620 if (!deserializer.read<WireTypeface>(&wire)) READ_FAILURE
621
622 // TODO(khushalsagar): The typeface no longer needs a reference to the
623 // SkStrikeClient, since all needed glyphs must have been pushed before
624 // raster.
625 addTypeface(wire);
626 }
627
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700628 uint64_t strikeCount = 0u;
629 if (!deserializer.read<uint64_t>(&strikeCount)) READ_FAILURE
Khushal38a08432018-05-02 10:29:37 -0700630
631 for (size_t i = 0; i < strikeCount; ++i) {
632 bool has_glyphs = false;
633 if (!deserializer.read<bool>(&has_glyphs)) READ_FAILURE
634
635 if (!has_glyphs) continue;
636
637 StrikeSpec spec;
638 if (!deserializer.read<StrikeSpec>(&spec)) READ_FAILURE
639
640 SkAutoDescriptor sourceAd;
641 if (!deserializer.readDescriptor(&sourceAd)) READ_FAILURE
642
Mike Reedb5784ac2018-11-12 09:35:15 -0500643 SkFontMetrics fontMetrics;
644 if (!deserializer.read<SkFontMetrics>(&fontMetrics)) READ_FAILURE
Khushal38a08432018-05-02 10:29:37 -0700645
646 // Get the local typeface from remote fontID.
647 auto* tf = fRemoteFontIdToTypeface.find(spec.typefaceID)->get();
648 // Received strikes for a typeface which doesn't exist.
649 if (!tf) READ_FAILURE
650
651 // Replace the ContextRec in the desc from the server to create the client
652 // side descriptor.
653 // TODO: Can we do this in-place and re-compute checksum? Instead of a complete copy.
654 SkAutoDescriptor ad;
655 auto* client_desc = auto_descriptor_from_desc(sourceAd.getDesc(), tf->uniqueID(), &ad);
656
Herb Derby5c0c7982018-06-21 15:15:50 -0400657 auto strike = fStrikeCache->findStrikeExclusive(*client_desc);
Khushal38a08432018-05-02 10:29:37 -0700658 if (strike == nullptr) {
659 // Note that we don't need to deserialize the effects since we won't be generating any
660 // glyphs here anyway, and the desc is still correct since it includes the serialized
661 // effects.
662 SkScalerContextEffects effects;
663 auto scaler = SkStrikeCache::CreateScalerContext(*client_desc, effects, *tf);
Herb Derby5c0c7982018-06-21 15:15:50 -0400664 strike = fStrikeCache->createStrikeExclusive(
Khushal38a08432018-05-02 10:29:37 -0700665 *client_desc, std::move(scaler), &fontMetrics,
666 skstd::make_unique<DiscardableStrikePinner>(spec.discardableHandleId,
667 fDiscardableHandleManager));
Herb Derby5c0c7982018-06-21 15:15:50 -0400668 auto proxyContext = static_cast<SkScalerContextProxy*>(strike->getScalerContext());
669 proxyContext->initCache(strike.get(), fStrikeCache);
Khushal38a08432018-05-02 10:29:37 -0700670 }
671
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700672 uint64_t glyphImagesCount = 0u;
673 if (!deserializer.read<uint64_t>(&glyphImagesCount)) READ_FAILURE
Khushal51371a42018-05-17 10:41:40 -0700674 for (size_t j = 0; j < glyphImagesCount; j++) {
Herb Derby811a6722019-01-10 13:58:05 -0500675 SkTLazy<SkGlyph> glyph;
676 if (!readGlyph(glyph, &deserializer)) READ_FAILURE
Khushal38a08432018-05-02 10:29:37 -0700677
Herb Derby811a6722019-01-10 13:58:05 -0500678 SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID());
Khushal4010c792018-06-13 09:44:23 -0700679
680 // Update the glyph unless it's already got an image (from fallback),
681 // preserving any path that might be present.
682 if (allocatedGlyph->fImage == nullptr) {
683 auto* glyphPath = allocatedGlyph->fPathData;
Herb Derby811a6722019-01-10 13:58:05 -0500684 *allocatedGlyph = *glyph;
Khushal4010c792018-06-13 09:44:23 -0700685 allocatedGlyph->fPathData = glyphPath;
686 }
Khushal38a08432018-05-02 10:29:37 -0700687
Herb Derby811a6722019-01-10 13:58:05 -0500688 auto imageSize = glyph->computeImageSize();
Khushal51371a42018-05-17 10:41:40 -0700689 if (imageSize == 0u) continue;
690
691 auto* image = deserializer.read(imageSize, allocatedGlyph->formatAlignment());
Khushal4010c792018-06-13 09:44:23 -0700692 if (!image) READ_FAILURE
693 strike->initializeImage(image, imageSize, allocatedGlyph);
Khushal51371a42018-05-17 10:41:40 -0700694 }
695
Peter Collingbourne77b02f62018-07-16 16:41:47 -0700696 uint64_t glyphPathsCount = 0u;
697 if (!deserializer.read<uint64_t>(&glyphPathsCount)) READ_FAILURE
Khushal51371a42018-05-17 10:41:40 -0700698 for (size_t j = 0; j < glyphPathsCount; j++) {
Herb Derby811a6722019-01-10 13:58:05 -0500699 SkTLazy<SkGlyph> glyph;
700 if (!readGlyph(glyph, &deserializer)) READ_FAILURE
Khushal51371a42018-05-17 10:41:40 -0700701
Herb Derby811a6722019-01-10 13:58:05 -0500702 SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID());
Khushal4010c792018-06-13 09:44:23 -0700703
704 // Update the glyph unless it's already got a path (from fallback),
705 // preserving any image that might be present.
706 if (allocatedGlyph->fPathData == nullptr) {
707 auto* glyphImage = allocatedGlyph->fImage;
Herb Derby811a6722019-01-10 13:58:05 -0500708 *allocatedGlyph = *glyph;
Khushal4010c792018-06-13 09:44:23 -0700709 allocatedGlyph->fImage = glyphImage;
710 }
Khushal51371a42018-05-17 10:41:40 -0700711
712 if (!read_path(&deserializer, allocatedGlyph, strike.get())) READ_FAILURE
Khushal38a08432018-05-02 10:29:37 -0700713 }
714 }
715
Ben Wagner5ddb3082018-03-29 11:18:06 -0400716 return true;
Herb Derby97be88f2018-03-21 16:23:49 -0400717}
718
Khushal38a08432018-05-02 10:29:37 -0700719sk_sp<SkTypeface> SkStrikeClient::deserializeTypeface(const void* buf, size_t len) {
Herb Derbyb2922f62018-01-26 16:47:54 -0500720 WireTypeface wire;
Khushal38a08432018-05-02 10:29:37 -0700721 if (len != sizeof(wire)) return nullptr;
Herb Derbyb2922f62018-01-26 16:47:54 -0500722 memcpy(&wire, buf, sizeof(wire));
Herb Derby5c0c7982018-06-21 15:15:50 -0400723 return this->addTypeface(wire);
Khushal38a08432018-05-02 10:29:37 -0700724}
Herb Derby9d021822018-02-02 12:54:55 -0500725
Khushal38a08432018-05-02 10:29:37 -0700726sk_sp<SkTypeface> SkStrikeClient::addTypeface(const WireTypeface& wire) {
727 auto* typeface = fRemoteFontIdToTypeface.find(wire.typefaceID);
728 if (typeface) return *typeface;
Herb Derbyb2922f62018-01-26 16:47:54 -0500729
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400730 auto newTypeface = sk_make_sp<SkTypefaceProxy>(
731 wire.typefaceID, wire.glyphCount, wire.style, wire.isFixed,
732 fDiscardableHandleManager, fIsLogging);
Khushal38a08432018-05-02 10:29:37 -0700733 fRemoteFontIdToTypeface.set(wire.typefaceID, newTypeface);
Herb Derby16d45642018-05-03 10:52:02 -0400734 return std::move(newTypeface);
Khushal38a08432018-05-02 10:29:37 -0700735}