Home | History | Annotate | Download | only in core
      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