1 /* 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 10 #include <iterator> 11 #include <memory> 12 #include <new> 13 #include <string> 14 #include <tuple> 15 16 #include "SkDevice.h" 17 #include "SkDraw.h" 18 #include "SkGlyphRun.h" 19 #include "SkRemoteGlyphCacheImpl.h" 20 #include "SkStrike.h" 21 #include "SkStrikeCache.h" 22 #include "SkTLazy.h" 23 #include "SkTraceEvent.h" 24 #include "SkTypeface_remote.h" 25 26 #if SK_SUPPORT_GPU 27 #include "GrDrawOpAtlas.h" 28 #include "text/GrTextContext.h" 29 #endif 30 31 static 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 48 // Effects. 49 { 50 uint32_t size; 51 auto ptr = source_desc->findEntry(kEffects_SkDescriptorTag, &size); 52 if (ptr) { desc->addEntry(kEffects_SkDescriptorTag, size, ptr); } 53 } 54 55 desc->computeChecksum(); 56 return desc; 57 } 58 59 static const SkDescriptor* create_descriptor( 60 const SkPaint& paint, const SkFont& font, const SkMatrix& m, 61 const SkSurfaceProps& props, SkScalerContextFlags flags, 62 SkAutoDescriptor* ad, SkScalerContextEffects* effects) { 63 SkScalerContextRec rec; 64 SkScalerContext::MakeRecAndEffects(font, paint, props, flags, m, &rec, effects); 65 return SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, *effects, ad); 66 } 67 68 // -- Serializer ---------------------------------------------------------------------------------- 69 70 size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); } 71 72 class Serializer { 73 public: 74 Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} { } 75 76 template <typename T, typename... Args> 77 T* emplace(Args&&... args) { 78 auto result = allocate(sizeof(T), alignof(T)); 79 return new (result) T{std::forward<Args>(args)...}; 80 } 81 82 template <typename T> 83 void write(const T& data) { 84 T* result = (T*)allocate(sizeof(T), alignof(T)); 85 memcpy(result, &data, sizeof(T)); 86 } 87 88 template <typename T> 89 T* allocate() { 90 T* result = (T*)allocate(sizeof(T), alignof(T)); 91 return result; 92 } 93 94 void writeDescriptor(const SkDescriptor& desc) { 95 write(desc.getLength()); 96 auto result = allocate(desc.getLength(), alignof(SkDescriptor)); 97 memcpy(result, &desc, desc.getLength()); 98 } 99 100 void* allocate(size_t size, size_t alignment) { 101 size_t aligned = pad(fBuffer->size(), alignment); 102 fBuffer->resize(aligned + size); 103 return &(*fBuffer)[aligned]; 104 } 105 106 private: 107 std::vector<uint8_t>* fBuffer; 108 }; 109 110 // -- Deserializer ------------------------------------------------------------------------------- 111 // Note that the Deserializer is reading untrusted data, we need to guard against invalid data. 112 class Deserializer { 113 public: 114 Deserializer(const volatile char* memory, size_t memorySize) 115 : fMemory(memory), fMemorySize(memorySize) {} 116 117 template <typename T> 118 bool read(T* val) { 119 auto* result = this->ensureAtLeast(sizeof(T), alignof(T)); 120 if (!result) return false; 121 122 memcpy(val, const_cast<const char*>(result), sizeof(T)); 123 return true; 124 } 125 126 bool readDescriptor(SkAutoDescriptor* ad) { 127 uint32_t desc_length = 0u; 128 if (!read<uint32_t>(&desc_length)) return false; 129 130 auto* result = this->ensureAtLeast(desc_length, alignof(SkDescriptor)); 131 if (!result) return false; 132 133 ad->reset(desc_length); 134 memcpy(ad->getDesc(), const_cast<const char*>(result), desc_length); 135 return true; 136 } 137 138 const volatile void* read(size_t size, size_t alignment) { 139 return this->ensureAtLeast(size, alignment); 140 } 141 142 private: 143 const volatile char* ensureAtLeast(size_t size, size_t alignment) { 144 size_t padded = pad(fBytesRead, alignment); 145 146 // Not enough data 147 if (padded + size > fMemorySize) return nullptr; 148 149 auto* result = fMemory + padded; 150 fBytesRead = padded + size; 151 return result; 152 } 153 154 // Note that we read each piece of memory only once to guard against TOCTOU violations. 155 const volatile char* fMemory; 156 size_t fMemorySize; 157 size_t fBytesRead = 0u; 158 }; 159 160 // Paths use a SkWriter32 which requires 4 byte alignment. 161 static const size_t kPathAlignment = 4u; 162 163 bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkStrike* cache) { 164 uint64_t pathSize = 0u; 165 if (!deserializer->read<uint64_t>(&pathSize)) return false; 166 167 if (pathSize == 0u) return true; 168 169 auto* path = deserializer->read(pathSize, kPathAlignment); 170 if (!path) return false; 171 172 return cache->initializePath(glyph, path, pathSize); 173 } 174 175 size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const { 176 return key->getChecksum(); 177 } 178 179 bool SkDescriptorMapOperators::operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const { 180 return *lhs == *rhs; 181 } 182 183 struct StrikeSpec { 184 StrikeSpec() {} 185 StrikeSpec(SkFontID typefaceID_, SkDiscardableHandleId discardableHandleId_) 186 : typefaceID{typefaceID_}, discardableHandleId(discardableHandleId_) {} 187 SkFontID typefaceID = 0u; 188 SkDiscardableHandleId discardableHandleId = 0u; 189 /* desc */ 190 /* n X (glyphs ids) */ 191 }; 192 193 // -- TrackLayerDevice ----------------------------------------------------------------------------- 194 SkTextBlobCacheDiffCanvas::TrackLayerDevice::TrackLayerDevice( 195 const SkIRect& bounds, const SkSurfaceProps& props, SkStrikeServer* server, 196 sk_sp<SkColorSpace> colorSpace, const SkTextBlobCacheDiffCanvas::Settings& settings) 197 : SkNoPixelsDevice(bounds, props, std::move(colorSpace)) 198 , fStrikeServer(server) 199 , fSettings(settings) 200 , fPainter{props, kUnknown_SkColorType, imageInfo().colorSpace(), fStrikeServer} { 201 SkASSERT(fStrikeServer); 202 } 203 204 SkBaseDevice* SkTextBlobCacheDiffCanvas::TrackLayerDevice::onCreateDevice( 205 const CreateInfo& cinfo, const SkPaint*) { 206 const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry); 207 return new TrackLayerDevice(this->getGlobalBounds(), surfaceProps, fStrikeServer, 208 cinfo.fInfo.refColorSpace(), fSettings); 209 } 210 211 void SkTextBlobCacheDiffCanvas::TrackLayerDevice::drawGlyphRunList( 212 const SkGlyphRunList& glyphRunList) { 213 214 #if SK_SUPPORT_GPU 215 GrTextContext::Options options; 216 options.fMinDistanceFieldFontSize = fSettings.fMinDistanceFieldFontSize; 217 options.fMaxDistanceFieldFontSize = fSettings.fMaxDistanceFieldFontSize; 218 GrTextContext::SanitizeOptions(&options); 219 220 fPainter.processGlyphRunList(glyphRunList, 221 this->ctm(), 222 this->surfaceProps(), 223 fSettings.fContextSupportsDistanceFieldText, 224 options, 225 nullptr); 226 #endif // SK_SUPPORT_GPU 227 228 } 229 230 // -- SkTextBlobCacheDiffCanvas ------------------------------------------------------------------- 231 SkTextBlobCacheDiffCanvas::Settings::Settings() = default; 232 233 SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas( 234 int width, int height, const SkSurfaceProps& props, 235 SkStrikeServer* strikeServer, Settings settings) 236 : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>( 237 SkIRect::MakeWH(width, height), props, strikeServer, nullptr, settings)} {} 238 239 SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height, 240 const SkSurfaceProps& props, 241 SkStrikeServer* strikeServer, 242 sk_sp<SkColorSpace> colorSpace, 243 Settings settings) 244 : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkIRect::MakeWH(width, height), props, 245 strikeServer, std::move(colorSpace), settings)} {} 246 247 SkTextBlobCacheDiffCanvas::~SkTextBlobCacheDiffCanvas() = default; 248 249 SkCanvas::SaveLayerStrategy SkTextBlobCacheDiffCanvas::getSaveLayerStrategy( 250 const SaveLayerRec& rec) { 251 return kFullLayer_SaveLayerStrategy; 252 } 253 254 bool SkTextBlobCacheDiffCanvas::onDoSaveBehind(const SkRect*) { 255 return false; 256 } 257 258 void SkTextBlobCacheDiffCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 259 const SkPaint& paint) { 260 /// 261 SkCanvas::onDrawTextBlob(blob, x, y, paint); 262 } 263 264 struct WireTypeface { 265 WireTypeface() = default; 266 WireTypeface(SkFontID typeface_id, int glyph_count, SkFontStyle style, bool is_fixed) 267 : typefaceID(typeface_id), glyphCount(glyph_count), style(style), isFixed(is_fixed) {} 268 269 SkFontID typefaceID; 270 int glyphCount; 271 SkFontStyle style; 272 bool isFixed; 273 }; 274 275 // SkStrikeServer ----------------------------------------- 276 277 SkStrikeServer::SkStrikeServer(DiscardableHandleManager* discardableHandleManager) 278 : fDiscardableHandleManager(discardableHandleManager) { 279 SkASSERT(fDiscardableHandleManager); 280 } 281 282 SkStrikeServer::~SkStrikeServer() = default; 283 284 sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) { 285 auto* data = fSerializedTypefaces.find(SkTypeface::UniqueID(tf)); 286 if (data) { 287 return *data; 288 } 289 290 WireTypeface wire(SkTypeface::UniqueID(tf), tf->countGlyphs(), tf->fontStyle(), 291 tf->isFixedPitch()); 292 data = fSerializedTypefaces.set(SkTypeface::UniqueID(tf), 293 SkData::MakeWithCopy(&wire, sizeof(wire))); 294 return *data; 295 } 296 297 void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) { 298 if (fLockedDescs.empty() && fTypefacesToSend.empty()) { 299 return; 300 } 301 302 Serializer serializer(memory); 303 serializer.emplace<uint64_t>(fTypefacesToSend.size()); 304 for (const auto& tf : fTypefacesToSend) serializer.write<WireTypeface>(tf); 305 fTypefacesToSend.clear(); 306 307 serializer.emplace<uint64_t>(fLockedDescs.size()); 308 for (const auto* desc : fLockedDescs) { 309 auto it = fRemoteGlyphStateMap.find(desc); 310 SkASSERT(it != fRemoteGlyphStateMap.end()); 311 it->second->writePendingGlyphs(&serializer); 312 } 313 fLockedDescs.clear(); 314 } 315 316 SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache( 317 const SkPaint& paint, 318 const SkFont& font, 319 const SkSurfaceProps& props, 320 const SkMatrix& matrix, 321 SkScalerContextFlags flags, 322 SkScalerContextEffects* effects) { 323 SkAutoDescriptor descStorage; 324 auto desc = create_descriptor(paint, font, matrix, props, flags, &descStorage, effects); 325 326 return this->getOrCreateCache(*desc, *font.getTypefaceOrDefault(), *effects); 327 328 } 329 330 SkScopedStrike SkStrikeServer::findOrCreateScopedStrike(const SkDescriptor& desc, 331 const SkScalerContextEffects& effects, 332 const SkTypeface& typeface) { 333 return SkScopedStrike{this->getOrCreateCache(desc, typeface, effects)}; 334 } 335 336 void SkStrikeServer::checkForDeletedEntries() { 337 auto it = fRemoteGlyphStateMap.begin(); 338 while (fRemoteGlyphStateMap.size() > fMaxEntriesInDescriptorMap && 339 it != fRemoteGlyphStateMap.end()) { 340 if (fDiscardableHandleManager->isHandleDeleted(it->second->discardableHandleId())) { 341 it = fRemoteGlyphStateMap.erase(it); 342 } else { 343 ++it; 344 } 345 } 346 } 347 348 SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache( 349 const SkDescriptor& desc, const SkTypeface& typeface, SkScalerContextEffects effects) { 350 351 // In cases where tracing is turned off, make sure not to get an unused function warning. 352 // Lambdaize the function. 353 TRACE_EVENT1("skia", "RecForDesc", "rec", 354 TRACE_STR_COPY( 355 [&desc](){ 356 auto ptr = desc.findEntry(kRec_SkDescriptorTag, nullptr); 357 SkScalerContextRec rec; 358 std::memcpy(&rec, ptr, sizeof(rec)); 359 return rec.dump(); 360 }().c_str() 361 ) 362 ); 363 364 // Already locked. 365 if (fLockedDescs.find(&desc) != fLockedDescs.end()) { 366 auto it = fRemoteGlyphStateMap.find(&desc); 367 SkASSERT(it != fRemoteGlyphStateMap.end()); 368 SkGlyphCacheState* cache = it->second.get(); 369 cache->setTypefaceAndEffects(&typeface, effects); 370 return cache; 371 } 372 373 // Try to lock. 374 auto it = fRemoteGlyphStateMap.find(&desc); 375 if (it != fRemoteGlyphStateMap.end()) { 376 SkGlyphCacheState* cache = it->second.get(); 377 bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId()); 378 if (locked) { 379 fLockedDescs.insert(it->first); 380 cache->setTypefaceAndEffects(&typeface, effects); 381 return cache; 382 } 383 384 // If the lock failed, the entry was deleted on the client. Remove our 385 // tracking. 386 fRemoteGlyphStateMap.erase(it); 387 } 388 389 const SkFontID typefaceId = typeface.uniqueID(); 390 if (!fCachedTypefaces.contains(typefaceId)) { 391 fCachedTypefaces.add(typefaceId); 392 fTypefacesToSend.emplace_back(typefaceId, typeface.countGlyphs(), 393 typeface.fontStyle(), 394 typeface.isFixedPitch()); 395 } 396 397 auto context = typeface.createScalerContext(effects, &desc); 398 399 // Create a new cache state and insert it into the map. 400 auto newHandle = fDiscardableHandleManager->createHandle(); 401 auto cacheState = skstd::make_unique<SkGlyphCacheState>(desc, std::move(context), newHandle); 402 403 auto* cacheStatePtr = cacheState.get(); 404 405 fLockedDescs.insert(&cacheStatePtr->getDescriptor()); 406 fRemoteGlyphStateMap[&cacheStatePtr->getDescriptor()] = std::move(cacheState); 407 408 checkForDeletedEntries(); 409 410 cacheStatePtr->setTypefaceAndEffects(&typeface, effects); 411 return cacheStatePtr; 412 } 413 414 // -- SkGlyphCacheState ---------------------------------------------------------------------------- 415 SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState( 416 const SkDescriptor& descriptor, 417 std::unique_ptr<SkScalerContext> context, 418 uint32_t discardableHandleId) 419 : fDescriptor{descriptor} 420 , fDiscardableHandleId(discardableHandleId) 421 , fIsSubpixel{context->isSubpixel()} 422 , fAxisAlignmentForHText{context->computeAxisAlignmentForHText()} 423 // N.B. context must come last because it is used above. 424 , fContext{std::move(context)} { 425 SkASSERT(fDescriptor.getDesc() != nullptr); 426 SkASSERT(fContext != nullptr); 427 } 428 429 SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState() = default; 430 431 void SkStrikeServer::SkGlyphCacheState::addGlyph(SkPackedGlyphID glyph, bool asPath) { 432 auto* cache = asPath ? &fCachedGlyphPaths : &fCachedGlyphImages; 433 auto* pending = asPath ? &fPendingGlyphPaths : &fPendingGlyphImages; 434 435 // Already cached. 436 if (cache->contains(glyph)) { 437 return; 438 } 439 440 // A glyph is going to be sent. Make sure we have a scaler context to send it. 441 this->ensureScalerContext(); 442 443 // Serialize and cache. Also create the scalar context to use when serializing 444 // this glyph. 445 cache->add(glyph); 446 pending->push_back(glyph); 447 } 448 449 static void writeGlyph(SkGlyph* glyph, Serializer* serializer) { 450 serializer->write<SkPackedGlyphID>(glyph->getPackedID()); 451 serializer->write<float>(glyph->fAdvanceX); 452 serializer->write<float>(glyph->fAdvanceY); 453 serializer->write<uint16_t>(glyph->fWidth); 454 serializer->write<uint16_t>(glyph->fHeight); 455 serializer->write<int16_t>(glyph->fTop); 456 serializer->write<int16_t>(glyph->fLeft); 457 serializer->write<int8_t>(glyph->fForceBW); 458 serializer->write<uint8_t>(glyph->fMaskFormat); 459 } 460 461 void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serializer) { 462 // TODO(khushalsagar): Write a strike only if it has any pending glyphs. 463 serializer->emplace<bool>(this->hasPendingGlyphs()); 464 if (!this->hasPendingGlyphs()) { 465 this->resetScalerContext(); 466 return; 467 } 468 469 // Write the desc. 470 serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId); 471 serializer->writeDescriptor(*fDescriptor.getDesc()); 472 473 // Write FontMetrics. 474 // TODO(khushalsagar): Do we need to re-send each time? 475 SkFontMetrics fontMetrics; 476 fContext->getFontMetrics(&fontMetrics); 477 serializer->write<SkFontMetrics>(fontMetrics); 478 479 // Write glyphs images. 480 serializer->emplace<uint64_t>(fPendingGlyphImages.size()); 481 for (const auto& glyphID : fPendingGlyphImages) { 482 SkGlyph glyph{glyphID}; 483 fContext->getMetrics(&glyph); 484 writeGlyph(&glyph, serializer); 485 486 auto imageSize = glyph.computeImageSize(); 487 if (imageSize == 0u) continue; 488 489 glyph.fImage = serializer->allocate(imageSize, glyph.formatAlignment()); 490 fContext->getImage(glyph); 491 // TODO: Generating the image can change the mask format, do we need to update it in the 492 // serialized glyph? 493 } 494 fPendingGlyphImages.clear(); 495 496 // Write glyphs paths. 497 serializer->emplace<uint64_t>(fPendingGlyphPaths.size()); 498 for (const auto& glyphID : fPendingGlyphPaths) { 499 SkGlyph glyph{glyphID}; 500 fContext->getMetrics(&glyph); 501 writeGlyph(&glyph, serializer); 502 writeGlyphPath(glyphID, serializer); 503 } 504 fPendingGlyphPaths.clear(); 505 this->resetScalerContext(); 506 } 507 508 void SkStrikeServer::SkGlyphCacheState::ensureScalerContext() { 509 if (fContext == nullptr) { 510 fContext = fTypeface->createScalerContext(fEffects, fDescriptor.getDesc()); 511 } 512 } 513 514 void SkStrikeServer::SkGlyphCacheState::resetScalerContext() { 515 fContext.reset(); 516 fTypeface = nullptr; 517 } 518 519 void SkStrikeServer::SkGlyphCacheState::setTypefaceAndEffects( 520 const SkTypeface* typeface, SkScalerContextEffects effects) { 521 fTypeface = typeface; 522 fEffects = effects; 523 } 524 525 SkVector SkStrikeServer::SkGlyphCacheState::rounding() const { 526 return SkStrikeCommon::PixelRounding(fIsSubpixel, fAxisAlignmentForHText); 527 } 528 529 // Note: In the split Renderer/GPU architecture, if getGlyphMetrics is called in the Renderer 530 // process, then it will be called on the GPU process because they share the rendering code. Any 531 // data that is created in the Renderer process needs to be found in the GPU process. By 532 // implication, any cache-miss/glyph-creation data needs to be sent to the GPU. 533 const SkGlyph& SkStrikeServer::SkGlyphCacheState::getGlyphMetrics( 534 SkGlyphID glyphID, SkPoint position) { 535 SkIPoint lookupPoint = SkStrikeCommon::SubpixelLookup(fAxisAlignmentForHText, position); 536 SkPackedGlyphID packedGlyphID = fIsSubpixel ? SkPackedGlyphID{glyphID, lookupPoint} 537 : SkPackedGlyphID{glyphID}; 538 539 // Check the cache for the glyph. 540 SkGlyph* glyphPtr = fGlyphMap.findOrNull(packedGlyphID); 541 542 // Has this glyph ever been seen before? 543 if (glyphPtr == nullptr) { 544 545 // Never seen before. Make a new glyph. 546 glyphPtr = fAlloc.make<SkGlyph>(packedGlyphID); 547 fGlyphMap.set(glyphPtr); 548 this->ensureScalerContext(); 549 fContext->getMetrics(glyphPtr); 550 551 // Make sure to send the glyph to the GPU because we always send the image for a glyph. 552 fCachedGlyphImages.add(packedGlyphID); 553 fPendingGlyphImages.push_back(packedGlyphID); 554 } 555 556 return *glyphPtr; 557 } 558 559 // Because the strike calls between the Renderer and the GPU are mirror images of each other, the 560 // information needed to make the call in the Renderer needs to be sent to the GPU so it can also 561 // make the call. If there is a path then it should be sent, and the path is queued to be sent and 562 // true returned. Otherwise, false is returned signaling an empty glyph. 563 // 564 // A key reason for no path is the fact that the glyph is a color image or is a bitmap only 565 // font. 566 bool SkStrikeServer::SkGlyphCacheState::decideCouldDrawFromPath(const SkGlyph& glyph) { 567 568 // Check to see if we have processed this glyph for a path before. 569 if (glyph.fPathData == nullptr) { 570 571 // Never checked for a path before. Add the path now. 572 auto path = const_cast<SkGlyph&>(glyph).addPath(fContext.get(), &fAlloc); 573 if (path != nullptr) { 574 575 // A path was added make sure to send it to the GPU. 576 fCachedGlyphPaths.add(glyph.getPackedID()); 577 fPendingGlyphPaths.push_back(glyph.getPackedID()); 578 return true; 579 } 580 } 581 582 return glyph.path() != nullptr; 583 } 584 585 void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID, 586 Serializer* serializer) const { 587 SkPath path; 588 if (!fContext->getPath(glyphID, &path)) { 589 serializer->write<uint64_t>(0u); 590 return; 591 } 592 593 size_t pathSize = path.writeToMemory(nullptr); 594 serializer->write<uint64_t>(pathSize); 595 path.writeToMemory(serializer->allocate(pathSize, kPathAlignment)); 596 } 597 598 599 // This version of glyphMetrics only adds entries to result if their data need to be sent to the 600 // GPU process. 601 int SkStrikeServer::SkGlyphCacheState::glyphMetrics( 602 const SkGlyphID glyphIDs[], const SkPoint positions[], int n, SkGlyphPos result[]) { 603 604 int glyphsToSendCount = 0; 605 const SkPoint* posCursor = positions; 606 for (int i = 0; i < n; i++) { 607 SkPoint glyphPos = *posCursor++; 608 SkGlyphID glyphID = glyphIDs[i]; 609 SkIPoint lookupPoint = SkStrikeCommon::SubpixelLookup(fAxisAlignmentForHText, glyphPos); 610 SkPackedGlyphID packedGlyphID = fIsSubpixel ? SkPackedGlyphID{glyphID, lookupPoint} 611 : SkPackedGlyphID{glyphID}; 612 613 // Check the cache for the glyph. 614 SkGlyph* glyphPtr = fGlyphMap.findOrNull(packedGlyphID); 615 616 // Has this glyph ever been seen before? 617 if (glyphPtr == nullptr) { 618 619 // Never seen before. Make a new glyph. 620 glyphPtr = fAlloc.make<SkGlyph>(packedGlyphID); 621 fGlyphMap.set(glyphPtr); 622 this->ensureScalerContext(); 623 fContext->getMetrics(glyphPtr); 624 625 result[glyphsToSendCount++] = {glyphPtr, glyphPos}; 626 627 // Make sure to send the glyph to the GPU because we always send the image for a glyph. 628 fCachedGlyphImages.add(packedGlyphID); 629 fPendingGlyphImages.push_back(packedGlyphID); 630 } 631 } 632 633 return glyphsToSendCount; 634 } 635 636 // SkStrikeClient ----------------------------------------- 637 class SkStrikeClient::DiscardableStrikePinner : public SkStrikePinner { 638 public: 639 DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId, 640 sk_sp<DiscardableHandleManager> manager) 641 : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {} 642 643 ~DiscardableStrikePinner() override = default; 644 bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); } 645 646 private: 647 const SkDiscardableHandleId fDiscardableHandleId; 648 sk_sp<DiscardableHandleManager> fManager; 649 }; 650 651 SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager, 652 bool isLogging, 653 SkStrikeCache* strikeCache) 654 : fDiscardableHandleManager(std::move(discardableManager)) 655 , fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()} 656 , fIsLogging{isLogging} {} 657 658 SkStrikeClient::~SkStrikeClient() = default; 659 660 #define READ_FAILURE \ 661 { \ 662 SkDEBUGFAIL("Bad serialization"); \ 663 return false; \ 664 } 665 666 static bool readGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer) { 667 SkPackedGlyphID glyphID; 668 if (!deserializer->read<SkPackedGlyphID>(&glyphID)) return false; 669 glyph.init(glyphID); 670 if (!deserializer->read<float>(&glyph->fAdvanceX)) return false; 671 if (!deserializer->read<float>(&glyph->fAdvanceY)) return false; 672 if (!deserializer->read<uint16_t>(&glyph->fWidth)) return false; 673 if (!deserializer->read<uint16_t>(&glyph->fHeight)) return false; 674 if (!deserializer->read<int16_t>(&glyph->fTop)) return false; 675 if (!deserializer->read<int16_t>(&glyph->fLeft)) return false; 676 if (!deserializer->read<int8_t>(&glyph->fForceBW)) return false; 677 if (!deserializer->read<uint8_t>(&glyph->fMaskFormat)) return false; 678 return true; 679 } 680 681 bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) { 682 SkASSERT(memorySize != 0u); 683 Deserializer deserializer(static_cast<const volatile char*>(memory), memorySize); 684 685 uint64_t typefaceSize = 0u; 686 if (!deserializer.read<uint64_t>(&typefaceSize)) READ_FAILURE 687 688 for (size_t i = 0; i < typefaceSize; ++i) { 689 WireTypeface wire; 690 if (!deserializer.read<WireTypeface>(&wire)) READ_FAILURE 691 692 // TODO(khushalsagar): The typeface no longer needs a reference to the 693 // SkStrikeClient, since all needed glyphs must have been pushed before 694 // raster. 695 addTypeface(wire); 696 } 697 698 uint64_t strikeCount = 0u; 699 if (!deserializer.read<uint64_t>(&strikeCount)) READ_FAILURE 700 701 for (size_t i = 0; i < strikeCount; ++i) { 702 bool has_glyphs = false; 703 if (!deserializer.read<bool>(&has_glyphs)) READ_FAILURE 704 705 if (!has_glyphs) continue; 706 707 StrikeSpec spec; 708 if (!deserializer.read<StrikeSpec>(&spec)) READ_FAILURE 709 710 SkAutoDescriptor sourceAd; 711 if (!deserializer.readDescriptor(&sourceAd)) READ_FAILURE 712 713 SkFontMetrics fontMetrics; 714 if (!deserializer.read<SkFontMetrics>(&fontMetrics)) READ_FAILURE 715 716 // Get the local typeface from remote fontID. 717 auto* tf = fRemoteFontIdToTypeface.find(spec.typefaceID)->get(); 718 // Received strikes for a typeface which doesn't exist. 719 if (!tf) READ_FAILURE 720 721 // Replace the ContextRec in the desc from the server to create the client 722 // side descriptor. 723 // TODO: Can we do this in-place and re-compute checksum? Instead of a complete copy. 724 SkAutoDescriptor ad; 725 auto* client_desc = auto_descriptor_from_desc(sourceAd.getDesc(), tf->uniqueID(), &ad); 726 727 auto strike = fStrikeCache->findStrikeExclusive(*client_desc); 728 if (strike == nullptr) { 729 // Note that we don't need to deserialize the effects since we won't be generating any 730 // glyphs here anyway, and the desc is still correct since it includes the serialized 731 // effects. 732 SkScalerContextEffects effects; 733 auto scaler = SkStrikeCache::CreateScalerContext(*client_desc, effects, *tf); 734 strike = fStrikeCache->createStrikeExclusive( 735 *client_desc, std::move(scaler), &fontMetrics, 736 skstd::make_unique<DiscardableStrikePinner>(spec.discardableHandleId, 737 fDiscardableHandleManager)); 738 auto proxyContext = static_cast<SkScalerContextProxy*>(strike->getScalerContext()); 739 proxyContext->initCache(strike.get(), fStrikeCache); 740 } 741 742 uint64_t glyphImagesCount = 0u; 743 if (!deserializer.read<uint64_t>(&glyphImagesCount)) READ_FAILURE 744 for (size_t j = 0; j < glyphImagesCount; j++) { 745 SkTLazy<SkGlyph> glyph; 746 if (!readGlyph(glyph, &deserializer)) READ_FAILURE 747 748 SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID()); 749 750 // Update the glyph unless it's already got an image (from fallback), 751 // preserving any path that might be present. 752 if (allocatedGlyph->fImage == nullptr) { 753 auto* glyphPath = allocatedGlyph->fPathData; 754 *allocatedGlyph = *glyph; 755 allocatedGlyph->fPathData = glyphPath; 756 } 757 758 auto imageSize = glyph->computeImageSize(); 759 if (imageSize == 0u) continue; 760 761 auto* image = deserializer.read(imageSize, allocatedGlyph->formatAlignment()); 762 if (!image) READ_FAILURE 763 strike->initializeImage(image, imageSize, allocatedGlyph); 764 } 765 766 uint64_t glyphPathsCount = 0u; 767 if (!deserializer.read<uint64_t>(&glyphPathsCount)) READ_FAILURE 768 for (size_t j = 0; j < glyphPathsCount; j++) { 769 SkTLazy<SkGlyph> glyph; 770 if (!readGlyph(glyph, &deserializer)) READ_FAILURE 771 772 SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID()); 773 774 // Update the glyph unless it's already got a path (from fallback), 775 // preserving any image that might be present. 776 if (allocatedGlyph->fPathData == nullptr) { 777 auto* glyphImage = allocatedGlyph->fImage; 778 *allocatedGlyph = *glyph; 779 allocatedGlyph->fImage = glyphImage; 780 } 781 782 if (!read_path(&deserializer, allocatedGlyph, strike.get())) READ_FAILURE 783 } 784 } 785 786 return true; 787 } 788 789 sk_sp<SkTypeface> SkStrikeClient::deserializeTypeface(const void* buf, size_t len) { 790 WireTypeface wire; 791 if (len != sizeof(wire)) return nullptr; 792 memcpy(&wire, buf, sizeof(wire)); 793 return this->addTypeface(wire); 794 } 795 796 sk_sp<SkTypeface> SkStrikeClient::addTypeface(const WireTypeface& wire) { 797 auto* typeface = fRemoteFontIdToTypeface.find(wire.typefaceID); 798 if (typeface) return *typeface; 799 800 auto newTypeface = sk_make_sp<SkTypefaceProxy>( 801 wire.typefaceID, wire.glyphCount, wire.style, wire.isFixed, 802 fDiscardableHandleManager, fIsLogging); 803 fRemoteFontIdToTypeface.set(wire.typefaceID, newTypeface); 804 return std::move(newTypeface); 805 } 806