xref: /aosp_15_r20/external/skia/src/text/gpu/SkChromeRemoteGlyphCache.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/SkChromeRemoteGlyphCache.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkDrawable.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMetrics.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPicture.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurfaceProps.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkPoint_impl.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTFitsIn.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/Slug.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkDescriptor.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkDevice.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkFontMetricsPriv.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkGlyph.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkReadBuffer.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkScalerContext.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStrike.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStrikeCache.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStrikeSpec.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTHash.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTypeface_remote.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkWriteBuffer.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "src/text/GlyphRun.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "src/text/StrikeForGPU.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "src/text/gpu/SubRunAllocator.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "src/text/gpu/SubRunContainer.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "src/text/gpu/SubRunControl.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "src/text/gpu/TextBlob.h"
49*c8dee2aaSAndroid Build Coastguard Worker 
50*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
51*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
52*c8dee2aaSAndroid Build Coastguard Worker #include <optional>
53*c8dee2aaSAndroid Build Coastguard Worker #include <unordered_map>
54*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
55*c8dee2aaSAndroid Build Coastguard Worker 
56*c8dee2aaSAndroid Build Coastguard Worker class SkPaint;
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
59*c8dee2aaSAndroid Build Coastguard Worker using namespace sktext;
60*c8dee2aaSAndroid Build Coastguard Worker using namespace sktext::gpu;
61*c8dee2aaSAndroid Build Coastguard Worker using namespace skglyph;
62*c8dee2aaSAndroid Build Coastguard Worker 
63*c8dee2aaSAndroid Build Coastguard Worker namespace {
64*c8dee2aaSAndroid Build Coastguard Worker 
65*c8dee2aaSAndroid Build Coastguard Worker // -- StrikeSpec -----------------------------------------------------------------------------------
66*c8dee2aaSAndroid Build Coastguard Worker struct StrikeSpec {
67*c8dee2aaSAndroid Build Coastguard Worker     StrikeSpec() = default;
StrikeSpec__anond12534150111::StrikeSpec68*c8dee2aaSAndroid Build Coastguard Worker     StrikeSpec(SkTypefaceID typefaceID, SkDiscardableHandleId discardableHandleId)
69*c8dee2aaSAndroid Build Coastguard Worker             : fTypefaceID{typefaceID}, fDiscardableHandleId(discardableHandleId) {}
70*c8dee2aaSAndroid Build Coastguard Worker     SkTypefaceID fTypefaceID = 0u;
71*c8dee2aaSAndroid Build Coastguard Worker     SkDiscardableHandleId fDiscardableHandleId = 0u;
72*c8dee2aaSAndroid Build Coastguard Worker };
73*c8dee2aaSAndroid Build Coastguard Worker 
74*c8dee2aaSAndroid Build Coastguard Worker // -- RemoteStrike ----------------------------------------------------------------------------
75*c8dee2aaSAndroid Build Coastguard Worker class RemoteStrike final : public sktext::StrikeForGPU {
76*c8dee2aaSAndroid Build Coastguard Worker public:
77*c8dee2aaSAndroid Build Coastguard Worker     // N.B. RemoteStrike is not valid until ensureScalerContext is called.
78*c8dee2aaSAndroid Build Coastguard Worker     RemoteStrike(const SkStrikeSpec& strikeSpec,
79*c8dee2aaSAndroid Build Coastguard Worker                  std::unique_ptr<SkScalerContext> context,
80*c8dee2aaSAndroid Build Coastguard Worker                  SkDiscardableHandleId discardableHandleId);
81*c8dee2aaSAndroid Build Coastguard Worker     ~RemoteStrike() override = default;
82*c8dee2aaSAndroid Build Coastguard Worker 
lock()83*c8dee2aaSAndroid Build Coastguard Worker     void lock() override {}
unlock()84*c8dee2aaSAndroid Build Coastguard Worker     void unlock() override {}
85*c8dee2aaSAndroid Build Coastguard Worker     SkGlyphDigest digestFor(skglyph::ActionType, SkPackedGlyphID) override;
prepareForImage(SkGlyph * glyph)86*c8dee2aaSAndroid Build Coastguard Worker     bool prepareForImage(SkGlyph* glyph) override {
87*c8dee2aaSAndroid Build Coastguard Worker         this->ensureScalerContext();
88*c8dee2aaSAndroid Build Coastguard Worker         glyph->setImage(&fAlloc, fContext.get());
89*c8dee2aaSAndroid Build Coastguard Worker         return glyph->image() != nullptr;
90*c8dee2aaSAndroid Build Coastguard Worker     }
prepareForPath(SkGlyph * glyph)91*c8dee2aaSAndroid Build Coastguard Worker     bool prepareForPath(SkGlyph* glyph) override {
92*c8dee2aaSAndroid Build Coastguard Worker         this->ensureScalerContext();
93*c8dee2aaSAndroid Build Coastguard Worker         glyph->setPath(&fAlloc, fContext.get());
94*c8dee2aaSAndroid Build Coastguard Worker         return glyph->path() != nullptr;
95*c8dee2aaSAndroid Build Coastguard Worker     }
prepareForDrawable(SkGlyph * glyph)96*c8dee2aaSAndroid Build Coastguard Worker     bool prepareForDrawable(SkGlyph* glyph) override {
97*c8dee2aaSAndroid Build Coastguard Worker         this->ensureScalerContext();
98*c8dee2aaSAndroid Build Coastguard Worker         glyph->setDrawable(&fAlloc, fContext.get());
99*c8dee2aaSAndroid Build Coastguard Worker         return glyph->drawable() != nullptr;
100*c8dee2aaSAndroid Build Coastguard Worker     }
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker     void writePendingGlyphs(SkWriteBuffer& buffer);
103*c8dee2aaSAndroid Build Coastguard Worker 
discardableHandleId() const104*c8dee2aaSAndroid Build Coastguard Worker     SkDiscardableHandleId discardableHandleId() const { return fDiscardableHandleId; }
105*c8dee2aaSAndroid Build Coastguard Worker 
getDescriptor() const106*c8dee2aaSAndroid Build Coastguard Worker     const SkDescriptor& getDescriptor() const override {
107*c8dee2aaSAndroid Build Coastguard Worker         return *fDescriptor.getDesc();
108*c8dee2aaSAndroid Build Coastguard Worker     }
109*c8dee2aaSAndroid Build Coastguard Worker 
110*c8dee2aaSAndroid Build Coastguard Worker     void setStrikeSpec(const SkStrikeSpec& strikeSpec);
111*c8dee2aaSAndroid Build Coastguard Worker 
roundingSpec() const112*c8dee2aaSAndroid Build Coastguard Worker     const SkGlyphPositionRoundingSpec& roundingSpec() const override {
113*c8dee2aaSAndroid Build Coastguard Worker         return fRoundingSpec;
114*c8dee2aaSAndroid Build Coastguard Worker     }
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker     sktext::SkStrikePromise strikePromise() override;
117*c8dee2aaSAndroid Build Coastguard Worker 
hasPendingGlyphs() const118*c8dee2aaSAndroid Build Coastguard Worker     bool hasPendingGlyphs() const {
119*c8dee2aaSAndroid Build Coastguard Worker         return !fMasksToSend.empty() || !fPathsToSend.empty() || !fDrawablesToSend.empty();
120*c8dee2aaSAndroid Build Coastguard Worker     }
121*c8dee2aaSAndroid Build Coastguard Worker 
122*c8dee2aaSAndroid Build Coastguard Worker     void resetScalerContext();
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker private:
125*c8dee2aaSAndroid Build Coastguard Worker     void ensureScalerContext();
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker     const SkAutoDescriptor fDescriptor;
128*c8dee2aaSAndroid Build Coastguard Worker     const SkDiscardableHandleId fDiscardableHandleId;
129*c8dee2aaSAndroid Build Coastguard Worker 
130*c8dee2aaSAndroid Build Coastguard Worker     const SkGlyphPositionRoundingSpec fRoundingSpec;
131*c8dee2aaSAndroid Build Coastguard Worker 
132*c8dee2aaSAndroid Build Coastguard Worker     // The context built using fDescriptor
133*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkScalerContext> fContext;
134*c8dee2aaSAndroid Build Coastguard Worker     SkTypefaceID fStrikeSpecTypefaceId;
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker     // fStrikeSpec is set every time getOrCreateCache is called. This allows the code to maintain
137*c8dee2aaSAndroid Build Coastguard Worker     // the fContext as lazy as possible.
138*c8dee2aaSAndroid Build Coastguard Worker     const SkStrikeSpec* fStrikeSpec;
139*c8dee2aaSAndroid Build Coastguard Worker 
140*c8dee2aaSAndroid Build Coastguard Worker     // Have the metrics been sent for this strike. Only send them once.
141*c8dee2aaSAndroid Build Coastguard Worker     bool fHaveSentFontMetrics{false};
142*c8dee2aaSAndroid Build Coastguard Worker 
143*c8dee2aaSAndroid Build Coastguard Worker     // The masks and paths that currently reside in the GPU process.
144*c8dee2aaSAndroid Build Coastguard Worker     THashTable<SkGlyphDigest, SkPackedGlyphID, SkGlyphDigest> fSentGlyphs;
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker     // The Masks, SDFT Mask, and Paths that need to be sent to the GPU task for the processed
147*c8dee2aaSAndroid Build Coastguard Worker     // TextBlobs. Cleared after diffs are serialized.
148*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkGlyph> fMasksToSend;
149*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkGlyph> fPathsToSend;
150*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkGlyph> fDrawablesToSend;
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker     // Alloc for storing bits and pieces of paths and drawables, Cleared after diffs are serialized.
153*c8dee2aaSAndroid Build Coastguard Worker     SkArenaAllocWithReset fAlloc{256};
154*c8dee2aaSAndroid Build Coastguard Worker };
155*c8dee2aaSAndroid Build Coastguard Worker 
RemoteStrike(const SkStrikeSpec & strikeSpec,std::unique_ptr<SkScalerContext> context,uint32_t discardableHandleId)156*c8dee2aaSAndroid Build Coastguard Worker RemoteStrike::RemoteStrike(
157*c8dee2aaSAndroid Build Coastguard Worker         const SkStrikeSpec& strikeSpec,
158*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<SkScalerContext> context,
159*c8dee2aaSAndroid Build Coastguard Worker         uint32_t discardableHandleId)
160*c8dee2aaSAndroid Build Coastguard Worker         : fDescriptor{strikeSpec.descriptor()}
161*c8dee2aaSAndroid Build Coastguard Worker         , fDiscardableHandleId(discardableHandleId)
162*c8dee2aaSAndroid Build Coastguard Worker         , fRoundingSpec{context->isSubpixel(), context->computeAxisAlignmentForHText()}
163*c8dee2aaSAndroid Build Coastguard Worker         // N.B. context must come last because it is used above.
164*c8dee2aaSAndroid Build Coastguard Worker         , fContext{std::move(context)}
165*c8dee2aaSAndroid Build Coastguard Worker         , fStrikeSpecTypefaceId(strikeSpec.typeface().uniqueID()) {
166*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fDescriptor.getDesc() != nullptr);
167*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fContext != nullptr);
168*c8dee2aaSAndroid Build Coastguard Worker }
169*c8dee2aaSAndroid Build Coastguard Worker 
writePendingGlyphs(SkWriteBuffer & buffer)170*c8dee2aaSAndroid Build Coastguard Worker void RemoteStrike::writePendingGlyphs(SkWriteBuffer& buffer) {
171*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->hasPendingGlyphs());
172*c8dee2aaSAndroid Build Coastguard Worker 
173*c8dee2aaSAndroid Build Coastguard Worker     // ScalerContext should not hold to the typeface, so we should not use its ID.
174*c8dee2aaSAndroid Build Coastguard Worker     // We should use StrikeSpec typeface and its ID instead.
175*c8dee2aaSAndroid Build Coastguard Worker     buffer.writeUInt(fStrikeSpecTypefaceId);
176*c8dee2aaSAndroid Build Coastguard Worker     buffer.writeUInt(fDiscardableHandleId);
177*c8dee2aaSAndroid Build Coastguard Worker     fDescriptor.getDesc()->flatten(buffer);
178*c8dee2aaSAndroid Build Coastguard Worker 
179*c8dee2aaSAndroid Build Coastguard Worker     buffer.writeBool(fHaveSentFontMetrics);
180*c8dee2aaSAndroid Build Coastguard Worker     if (!fHaveSentFontMetrics) {
181*c8dee2aaSAndroid Build Coastguard Worker         // Write FontMetrics if not sent before.
182*c8dee2aaSAndroid Build Coastguard Worker         SkFontMetrics fontMetrics;
183*c8dee2aaSAndroid Build Coastguard Worker         fContext->getFontMetrics(&fontMetrics);
184*c8dee2aaSAndroid Build Coastguard Worker         SkFontMetricsPriv::Flatten(buffer, fontMetrics);
185*c8dee2aaSAndroid Build Coastguard Worker         fHaveSentFontMetrics = true;
186*c8dee2aaSAndroid Build Coastguard Worker     }
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker     // Make sure to install all the mask data into the glyphs before sending.
189*c8dee2aaSAndroid Build Coastguard Worker     for (SkGlyph& glyph: fMasksToSend) {
190*c8dee2aaSAndroid Build Coastguard Worker         this->prepareForImage(&glyph);
191*c8dee2aaSAndroid Build Coastguard Worker     }
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker     // Make sure to install all the path data into the glyphs before sending.
194*c8dee2aaSAndroid Build Coastguard Worker     for (SkGlyph& glyph: fPathsToSend) {
195*c8dee2aaSAndroid Build Coastguard Worker         this->prepareForPath(&glyph);
196*c8dee2aaSAndroid Build Coastguard Worker     }
197*c8dee2aaSAndroid Build Coastguard Worker 
198*c8dee2aaSAndroid Build Coastguard Worker     // Make sure to install all the drawable data into the glyphs before sending.
199*c8dee2aaSAndroid Build Coastguard Worker     for (SkGlyph& glyph: fDrawablesToSend) {
200*c8dee2aaSAndroid Build Coastguard Worker         this->prepareForDrawable(&glyph);
201*c8dee2aaSAndroid Build Coastguard Worker     }
202*c8dee2aaSAndroid Build Coastguard Worker 
203*c8dee2aaSAndroid Build Coastguard Worker     // Send all the pending glyph information.
204*c8dee2aaSAndroid Build Coastguard Worker     SkStrike::FlattenGlyphsByType(buffer, fMasksToSend, fPathsToSend, fDrawablesToSend);
205*c8dee2aaSAndroid Build Coastguard Worker 
206*c8dee2aaSAndroid Build Coastguard Worker     // Reset all the sending data.
207*c8dee2aaSAndroid Build Coastguard Worker     fMasksToSend.clear();
208*c8dee2aaSAndroid Build Coastguard Worker     fPathsToSend.clear();
209*c8dee2aaSAndroid Build Coastguard Worker     fDrawablesToSend.clear();
210*c8dee2aaSAndroid Build Coastguard Worker     fAlloc.reset();
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker 
ensureScalerContext()213*c8dee2aaSAndroid Build Coastguard Worker void RemoteStrike::ensureScalerContext() {
214*c8dee2aaSAndroid Build Coastguard Worker     if (fContext == nullptr) {
215*c8dee2aaSAndroid Build Coastguard Worker         fContext = fStrikeSpec->createScalerContext();
216*c8dee2aaSAndroid Build Coastguard Worker     }
217*c8dee2aaSAndroid Build Coastguard Worker }
218*c8dee2aaSAndroid Build Coastguard Worker 
resetScalerContext()219*c8dee2aaSAndroid Build Coastguard Worker void RemoteStrike::resetScalerContext() {
220*c8dee2aaSAndroid Build Coastguard Worker     fContext = nullptr;
221*c8dee2aaSAndroid Build Coastguard Worker     fStrikeSpec = nullptr;
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker 
setStrikeSpec(const SkStrikeSpec & strikeSpec)224*c8dee2aaSAndroid Build Coastguard Worker void RemoteStrike::setStrikeSpec(const SkStrikeSpec& strikeSpec) {
225*c8dee2aaSAndroid Build Coastguard Worker     fStrikeSpec = &strikeSpec;
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker 
digestFor(ActionType actionType,SkPackedGlyphID packedGlyphID)228*c8dee2aaSAndroid Build Coastguard Worker SkGlyphDigest RemoteStrike::digestFor(ActionType actionType, SkPackedGlyphID packedGlyphID) {
229*c8dee2aaSAndroid Build Coastguard Worker     SkGlyphDigest* digestPtr = fSentGlyphs.find(packedGlyphID);
230*c8dee2aaSAndroid Build Coastguard Worker     if (digestPtr != nullptr && digestPtr->actionFor(actionType) != GlyphAction::kUnset) {
231*c8dee2aaSAndroid Build Coastguard Worker         return *digestPtr;
232*c8dee2aaSAndroid Build Coastguard Worker     }
233*c8dee2aaSAndroid Build Coastguard Worker 
234*c8dee2aaSAndroid Build Coastguard Worker     SkGlyph* glyph;
235*c8dee2aaSAndroid Build Coastguard Worker     this->ensureScalerContext();
236*c8dee2aaSAndroid Build Coastguard Worker     switch (actionType) {
237*c8dee2aaSAndroid Build Coastguard Worker         case skglyph::kPath: {
238*c8dee2aaSAndroid Build Coastguard Worker             fPathsToSend.emplace_back(fContext->makeGlyph(packedGlyphID, &fAlloc));
239*c8dee2aaSAndroid Build Coastguard Worker             glyph = &fPathsToSend.back();
240*c8dee2aaSAndroid Build Coastguard Worker             break;
241*c8dee2aaSAndroid Build Coastguard Worker         }
242*c8dee2aaSAndroid Build Coastguard Worker         case skglyph::kDrawable: {
243*c8dee2aaSAndroid Build Coastguard Worker             fDrawablesToSend.emplace_back(fContext->makeGlyph(packedGlyphID, &fAlloc));
244*c8dee2aaSAndroid Build Coastguard Worker             glyph = &fDrawablesToSend.back();
245*c8dee2aaSAndroid Build Coastguard Worker             break;
246*c8dee2aaSAndroid Build Coastguard Worker         }
247*c8dee2aaSAndroid Build Coastguard Worker         default: {
248*c8dee2aaSAndroid Build Coastguard Worker             fMasksToSend.emplace_back(fContext->makeGlyph(packedGlyphID, &fAlloc));
249*c8dee2aaSAndroid Build Coastguard Worker             glyph = &fMasksToSend.back();
250*c8dee2aaSAndroid Build Coastguard Worker             break;
251*c8dee2aaSAndroid Build Coastguard Worker         }
252*c8dee2aaSAndroid Build Coastguard Worker     }
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker     if (digestPtr == nullptr) {
255*c8dee2aaSAndroid Build Coastguard Worker         digestPtr = fSentGlyphs.set(SkGlyphDigest{0, *glyph});
256*c8dee2aaSAndroid Build Coastguard Worker     }
257*c8dee2aaSAndroid Build Coastguard Worker 
258*c8dee2aaSAndroid Build Coastguard Worker     digestPtr->setActionFor(actionType, glyph, this);
259*c8dee2aaSAndroid Build Coastguard Worker 
260*c8dee2aaSAndroid Build Coastguard Worker     return *digestPtr;
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker 
strikePromise()263*c8dee2aaSAndroid Build Coastguard Worker sktext::SkStrikePromise RemoteStrike::strikePromise() {
264*c8dee2aaSAndroid Build Coastguard Worker     return sktext::SkStrikePromise{*this->fStrikeSpec};
265*c8dee2aaSAndroid Build Coastguard Worker }
266*c8dee2aaSAndroid Build Coastguard Worker }  // namespace
267*c8dee2aaSAndroid Build Coastguard Worker 
268*c8dee2aaSAndroid Build Coastguard Worker // -- SkStrikeServerImpl ---------------------------------------------------------------------------
269*c8dee2aaSAndroid Build Coastguard Worker class SkStrikeServerImpl final : public sktext::StrikeForGPUCacheInterface {
270*c8dee2aaSAndroid Build Coastguard Worker public:
271*c8dee2aaSAndroid Build Coastguard Worker     explicit SkStrikeServerImpl(
272*c8dee2aaSAndroid Build Coastguard Worker             SkStrikeServer::DiscardableHandleManager* discardableHandleManager);
273*c8dee2aaSAndroid Build Coastguard Worker 
274*c8dee2aaSAndroid Build Coastguard Worker     // SkStrikeServer API methods
275*c8dee2aaSAndroid Build Coastguard Worker     void writeStrikeData(std::vector<uint8_t>* memory);
276*c8dee2aaSAndroid Build Coastguard Worker 
277*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<sktext::StrikeForGPU> findOrCreateScopedStrike(const SkStrikeSpec& strikeSpec) override;
278*c8dee2aaSAndroid Build Coastguard Worker 
279*c8dee2aaSAndroid Build Coastguard Worker     // Methods for testing
280*c8dee2aaSAndroid Build Coastguard Worker     void setMaxEntriesInDescriptorMapForTesting(size_t count);
281*c8dee2aaSAndroid Build Coastguard Worker     size_t remoteStrikeMapSizeForTesting() const;
282*c8dee2aaSAndroid Build Coastguard Worker 
283*c8dee2aaSAndroid Build Coastguard Worker private:
284*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr size_t kMaxEntriesInDescriptorMap = 2000u;
285*c8dee2aaSAndroid Build Coastguard Worker 
286*c8dee2aaSAndroid Build Coastguard Worker     void checkForDeletedEntries();
287*c8dee2aaSAndroid Build Coastguard Worker 
288*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<RemoteStrike> getOrCreateCache(const SkStrikeSpec& strikeSpec);
289*c8dee2aaSAndroid Build Coastguard Worker 
290*c8dee2aaSAndroid Build Coastguard Worker     struct MapOps {
operator ()SkStrikeServerImpl::MapOps291*c8dee2aaSAndroid Build Coastguard Worker         size_t operator()(const SkDescriptor* key) const {
292*c8dee2aaSAndroid Build Coastguard Worker             return key->getChecksum();
293*c8dee2aaSAndroid Build Coastguard Worker         }
operator ()SkStrikeServerImpl::MapOps294*c8dee2aaSAndroid Build Coastguard Worker         bool operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const {
295*c8dee2aaSAndroid Build Coastguard Worker             return *lhs == *rhs;
296*c8dee2aaSAndroid Build Coastguard Worker         }
297*c8dee2aaSAndroid Build Coastguard Worker     };
298*c8dee2aaSAndroid Build Coastguard Worker 
299*c8dee2aaSAndroid Build Coastguard Worker     using DescToRemoteStrike =
300*c8dee2aaSAndroid Build Coastguard Worker         std::unordered_map<const SkDescriptor*, sk_sp<RemoteStrike>, MapOps, MapOps>;
301*c8dee2aaSAndroid Build Coastguard Worker     DescToRemoteStrike fDescToRemoteStrike;
302*c8dee2aaSAndroid Build Coastguard Worker 
303*c8dee2aaSAndroid Build Coastguard Worker     SkStrikeServer::DiscardableHandleManager* const fDiscardableHandleManager;
304*c8dee2aaSAndroid Build Coastguard Worker     THashSet<SkTypefaceID> fCachedTypefaces;
305*c8dee2aaSAndroid Build Coastguard Worker     size_t fMaxEntriesInDescriptorMap = kMaxEntriesInDescriptorMap;
306*c8dee2aaSAndroid Build Coastguard Worker 
307*c8dee2aaSAndroid Build Coastguard Worker     // State cached until the next serialization.
308*c8dee2aaSAndroid Build Coastguard Worker     THashSet<RemoteStrike*> fRemoteStrikesToSend;
309*c8dee2aaSAndroid Build Coastguard Worker     std::vector<SkTypefaceProxyPrototype> fTypefacesToSend;
310*c8dee2aaSAndroid Build Coastguard Worker };
311*c8dee2aaSAndroid Build Coastguard Worker 
SkStrikeServerImpl(SkStrikeServer::DiscardableHandleManager * dhm)312*c8dee2aaSAndroid Build Coastguard Worker SkStrikeServerImpl::SkStrikeServerImpl(SkStrikeServer::DiscardableHandleManager* dhm)
313*c8dee2aaSAndroid Build Coastguard Worker         : fDiscardableHandleManager(dhm) {
314*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fDiscardableHandleManager);
315*c8dee2aaSAndroid Build Coastguard Worker }
316*c8dee2aaSAndroid Build Coastguard Worker 
setMaxEntriesInDescriptorMapForTesting(size_t count)317*c8dee2aaSAndroid Build Coastguard Worker void SkStrikeServerImpl::setMaxEntriesInDescriptorMapForTesting(size_t count) {
318*c8dee2aaSAndroid Build Coastguard Worker     fMaxEntriesInDescriptorMap = count;
319*c8dee2aaSAndroid Build Coastguard Worker }
remoteStrikeMapSizeForTesting() const320*c8dee2aaSAndroid Build Coastguard Worker size_t SkStrikeServerImpl::remoteStrikeMapSizeForTesting() const {
321*c8dee2aaSAndroid Build Coastguard Worker     return fDescToRemoteStrike.size();
322*c8dee2aaSAndroid Build Coastguard Worker }
323*c8dee2aaSAndroid Build Coastguard Worker 
writeStrikeData(std::vector<uint8_t> * memory)324*c8dee2aaSAndroid Build Coastguard Worker void SkStrikeServerImpl::writeStrikeData(std::vector<uint8_t>* memory) {
325*c8dee2aaSAndroid Build Coastguard Worker     // We can use the default SkSerialProcs because we do not currently need to encode any SkImages.
326*c8dee2aaSAndroid Build Coastguard Worker     SkBinaryWriteBuffer buffer{nullptr, 0, {}};
327*c8dee2aaSAndroid Build Coastguard Worker 
328*c8dee2aaSAndroid Build Coastguard Worker     // Gather statistics about what needs to be sent.
329*c8dee2aaSAndroid Build Coastguard Worker     size_t strikesToSend = 0;
330*c8dee2aaSAndroid Build Coastguard Worker     fRemoteStrikesToSend.foreach([&](RemoteStrike* strike) {
331*c8dee2aaSAndroid Build Coastguard Worker         if (strike->hasPendingGlyphs()) {
332*c8dee2aaSAndroid Build Coastguard Worker             strikesToSend++;
333*c8dee2aaSAndroid Build Coastguard Worker         } else {
334*c8dee2aaSAndroid Build Coastguard Worker             // This strike has nothing to send, so drop its scaler context to reduce memory.
335*c8dee2aaSAndroid Build Coastguard Worker             strike->resetScalerContext();
336*c8dee2aaSAndroid Build Coastguard Worker         }
337*c8dee2aaSAndroid Build Coastguard Worker     });
338*c8dee2aaSAndroid Build Coastguard Worker 
339*c8dee2aaSAndroid Build Coastguard Worker     // If there are no strikes or typefaces to send, then cleanup and return.
340*c8dee2aaSAndroid Build Coastguard Worker     if (strikesToSend == 0 && fTypefacesToSend.empty()) {
341*c8dee2aaSAndroid Build Coastguard Worker         fRemoteStrikesToSend.reset();
342*c8dee2aaSAndroid Build Coastguard Worker         return;
343*c8dee2aaSAndroid Build Coastguard Worker     }
344*c8dee2aaSAndroid Build Coastguard Worker 
345*c8dee2aaSAndroid Build Coastguard Worker     // Send newly seen typefaces.
346*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT_RELEASE(SkTFitsIn<int>(fTypefacesToSend.size()));
347*c8dee2aaSAndroid Build Coastguard Worker     buffer.writeInt(fTypefacesToSend.size());
348*c8dee2aaSAndroid Build Coastguard Worker     for (const auto& typeface: fTypefacesToSend) {
349*c8dee2aaSAndroid Build Coastguard Worker         SkTypefaceProxyPrototype proto{typeface};
350*c8dee2aaSAndroid Build Coastguard Worker         proto.flatten(buffer);
351*c8dee2aaSAndroid Build Coastguard Worker     }
352*c8dee2aaSAndroid Build Coastguard Worker     fTypefacesToSend.clear();
353*c8dee2aaSAndroid Build Coastguard Worker 
354*c8dee2aaSAndroid Build Coastguard Worker     buffer.writeInt(strikesToSend);
355*c8dee2aaSAndroid Build Coastguard Worker     fRemoteStrikesToSend.foreach(
356*c8dee2aaSAndroid Build Coastguard Worker             [&](RemoteStrike* strike) {
357*c8dee2aaSAndroid Build Coastguard Worker                 if (strike->hasPendingGlyphs()) {
358*c8dee2aaSAndroid Build Coastguard Worker                     strike->writePendingGlyphs(buffer);
359*c8dee2aaSAndroid Build Coastguard Worker                     strike->resetScalerContext();
360*c8dee2aaSAndroid Build Coastguard Worker                 }
361*c8dee2aaSAndroid Build Coastguard Worker             }
362*c8dee2aaSAndroid Build Coastguard Worker     );
363*c8dee2aaSAndroid Build Coastguard Worker     fRemoteStrikesToSend.reset();
364*c8dee2aaSAndroid Build Coastguard Worker 
365*c8dee2aaSAndroid Build Coastguard Worker     // Copy data into the vector.
366*c8dee2aaSAndroid Build Coastguard Worker     auto data = buffer.snapshotAsData();
367*c8dee2aaSAndroid Build Coastguard Worker     memory->assign(data->bytes(), data->bytes() + data->size());
368*c8dee2aaSAndroid Build Coastguard Worker }
369*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateScopedStrike(const SkStrikeSpec & strikeSpec)370*c8dee2aaSAndroid Build Coastguard Worker sk_sp<StrikeForGPU> SkStrikeServerImpl::findOrCreateScopedStrike(
371*c8dee2aaSAndroid Build Coastguard Worker         const SkStrikeSpec& strikeSpec) {
372*c8dee2aaSAndroid Build Coastguard Worker     return this->getOrCreateCache(strikeSpec);
373*c8dee2aaSAndroid Build Coastguard Worker }
374*c8dee2aaSAndroid Build Coastguard Worker 
checkForDeletedEntries()375*c8dee2aaSAndroid Build Coastguard Worker void SkStrikeServerImpl::checkForDeletedEntries() {
376*c8dee2aaSAndroid Build Coastguard Worker     auto it = fDescToRemoteStrike.begin();
377*c8dee2aaSAndroid Build Coastguard Worker     while (fDescToRemoteStrike.size() > fMaxEntriesInDescriptorMap &&
378*c8dee2aaSAndroid Build Coastguard Worker            it != fDescToRemoteStrike.end()) {
379*c8dee2aaSAndroid Build Coastguard Worker         RemoteStrike* strike = it->second.get();
380*c8dee2aaSAndroid Build Coastguard Worker         if (fDiscardableHandleManager->isHandleDeleted(strike->discardableHandleId())) {
381*c8dee2aaSAndroid Build Coastguard Worker             // If we are trying to send the strike, then do not erase it.
382*c8dee2aaSAndroid Build Coastguard Worker             if (!fRemoteStrikesToSend.contains(strike)) {
383*c8dee2aaSAndroid Build Coastguard Worker                 // Erase returns the iterator following the removed element.
384*c8dee2aaSAndroid Build Coastguard Worker                 it = fDescToRemoteStrike.erase(it);
385*c8dee2aaSAndroid Build Coastguard Worker                 continue;
386*c8dee2aaSAndroid Build Coastguard Worker             }
387*c8dee2aaSAndroid Build Coastguard Worker         }
388*c8dee2aaSAndroid Build Coastguard Worker         ++it;
389*c8dee2aaSAndroid Build Coastguard Worker     }
390*c8dee2aaSAndroid Build Coastguard Worker }
391*c8dee2aaSAndroid Build Coastguard Worker 
getOrCreateCache(const SkStrikeSpec & strikeSpec)392*c8dee2aaSAndroid Build Coastguard Worker sk_sp<RemoteStrike> SkStrikeServerImpl::getOrCreateCache(const SkStrikeSpec& strikeSpec) {
393*c8dee2aaSAndroid Build Coastguard Worker     // In cases where tracing is turned off, make sure not to get an unused function warning.
394*c8dee2aaSAndroid Build Coastguard Worker     // Lambdaize the function.
395*c8dee2aaSAndroid Build Coastguard Worker     TRACE_EVENT1("skia", "RecForDesc", "rec",
396*c8dee2aaSAndroid Build Coastguard Worker                  TRACE_STR_COPY(
397*c8dee2aaSAndroid Build Coastguard Worker                          [&strikeSpec](){
398*c8dee2aaSAndroid Build Coastguard Worker                              auto ptr =
399*c8dee2aaSAndroid Build Coastguard Worker                                  strikeSpec.descriptor().findEntry(kRec_SkDescriptorTag, nullptr);
400*c8dee2aaSAndroid Build Coastguard Worker                              SkScalerContextRec rec;
401*c8dee2aaSAndroid Build Coastguard Worker                              std::memcpy((void*)&rec, ptr, sizeof(rec));
402*c8dee2aaSAndroid Build Coastguard Worker                              return rec.dump();
403*c8dee2aaSAndroid Build Coastguard Worker                          }().c_str()
404*c8dee2aaSAndroid Build Coastguard Worker                  )
405*c8dee2aaSAndroid Build Coastguard Worker     );
406*c8dee2aaSAndroid Build Coastguard Worker 
407*c8dee2aaSAndroid Build Coastguard Worker     if (auto it = fDescToRemoteStrike.find(&strikeSpec.descriptor());
408*c8dee2aaSAndroid Build Coastguard Worker         it != fDescToRemoteStrike.end())
409*c8dee2aaSAndroid Build Coastguard Worker     {
410*c8dee2aaSAndroid Build Coastguard Worker         // We have processed the RemoteStrike before. Reuse it.
411*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<RemoteStrike> strike = it->second;
412*c8dee2aaSAndroid Build Coastguard Worker         strike->setStrikeSpec(strikeSpec);
413*c8dee2aaSAndroid Build Coastguard Worker         if (fRemoteStrikesToSend.contains(strike.get())) {
414*c8dee2aaSAndroid Build Coastguard Worker             // Already tracking
415*c8dee2aaSAndroid Build Coastguard Worker             return strike;
416*c8dee2aaSAndroid Build Coastguard Worker         }
417*c8dee2aaSAndroid Build Coastguard Worker 
418*c8dee2aaSAndroid Build Coastguard Worker         // Strike is in unknown state on GPU. Start tracking strike on GPU by locking it.
419*c8dee2aaSAndroid Build Coastguard Worker         bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId());
420*c8dee2aaSAndroid Build Coastguard Worker         if (locked) {
421*c8dee2aaSAndroid Build Coastguard Worker             fRemoteStrikesToSend.add(strike.get());
422*c8dee2aaSAndroid Build Coastguard Worker             return strike;
423*c8dee2aaSAndroid Build Coastguard Worker         }
424*c8dee2aaSAndroid Build Coastguard Worker 
425*c8dee2aaSAndroid Build Coastguard Worker         // If it wasn't locked, then forget this strike, and build it anew below.
426*c8dee2aaSAndroid Build Coastguard Worker         fDescToRemoteStrike.erase(it);
427*c8dee2aaSAndroid Build Coastguard Worker     }
428*c8dee2aaSAndroid Build Coastguard Worker 
429*c8dee2aaSAndroid Build Coastguard Worker     const SkTypeface& typeface = strikeSpec.typeface();
430*c8dee2aaSAndroid Build Coastguard Worker     // Create a new RemoteStrike. Start by processing the typeface.
431*c8dee2aaSAndroid Build Coastguard Worker     const SkTypefaceID typefaceId = typeface.uniqueID();
432*c8dee2aaSAndroid Build Coastguard Worker     if (!fCachedTypefaces.contains(typefaceId)) {
433*c8dee2aaSAndroid Build Coastguard Worker         fCachedTypefaces.add(typefaceId);
434*c8dee2aaSAndroid Build Coastguard Worker         fTypefacesToSend.emplace_back(typeface);
435*c8dee2aaSAndroid Build Coastguard Worker     }
436*c8dee2aaSAndroid Build Coastguard Worker 
437*c8dee2aaSAndroid Build Coastguard Worker     auto context = strikeSpec.createScalerContext();
438*c8dee2aaSAndroid Build Coastguard Worker     auto newHandle = fDiscardableHandleManager->createHandle();  // Locked on creation
439*c8dee2aaSAndroid Build Coastguard Worker     auto remoteStrike = sk_make_sp<RemoteStrike>(strikeSpec, std::move(context), newHandle);
440*c8dee2aaSAndroid Build Coastguard Worker     remoteStrike->setStrikeSpec(strikeSpec);
441*c8dee2aaSAndroid Build Coastguard Worker     fRemoteStrikesToSend.add(remoteStrike.get());
442*c8dee2aaSAndroid Build Coastguard Worker     auto d = &remoteStrike->getDescriptor();
443*c8dee2aaSAndroid Build Coastguard Worker     fDescToRemoteStrike[d] = remoteStrike;
444*c8dee2aaSAndroid Build Coastguard Worker 
445*c8dee2aaSAndroid Build Coastguard Worker     checkForDeletedEntries();
446*c8dee2aaSAndroid Build Coastguard Worker 
447*c8dee2aaSAndroid Build Coastguard Worker     return remoteStrike;
448*c8dee2aaSAndroid Build Coastguard Worker }
449*c8dee2aaSAndroid Build Coastguard Worker 
450*c8dee2aaSAndroid Build Coastguard Worker // -- GlyphTrackingDevice --------------------------------------------------------------------------
451*c8dee2aaSAndroid Build Coastguard Worker class GlyphTrackingDevice final : public SkNoPixelsDevice {
452*c8dee2aaSAndroid Build Coastguard Worker public:
GlyphTrackingDevice(const SkISize & dimensions,const SkSurfaceProps & props,SkStrikeServerImpl * server,sk_sp<SkColorSpace> colorSpace,sktext::gpu::SubRunControl SubRunControl)453*c8dee2aaSAndroid Build Coastguard Worker     GlyphTrackingDevice(
454*c8dee2aaSAndroid Build Coastguard Worker             const SkISize& dimensions, const SkSurfaceProps& props, SkStrikeServerImpl* server,
455*c8dee2aaSAndroid Build Coastguard Worker             sk_sp<SkColorSpace> colorSpace, sktext::gpu::SubRunControl SubRunControl)
456*c8dee2aaSAndroid Build Coastguard Worker             : SkNoPixelsDevice(SkIRect::MakeSize(dimensions), props, std::move(colorSpace))
457*c8dee2aaSAndroid Build Coastguard Worker             , fStrikeServerImpl(server)
458*c8dee2aaSAndroid Build Coastguard Worker             , fSubRunControl(SubRunControl) {
459*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fStrikeServerImpl != nullptr);
460*c8dee2aaSAndroid Build Coastguard Worker     }
461*c8dee2aaSAndroid Build Coastguard Worker 
createDevice(const CreateInfo & cinfo,const SkPaint *)462*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkDevice> createDevice(const CreateInfo& cinfo, const SkPaint*) override {
463*c8dee2aaSAndroid Build Coastguard Worker         const SkSurfaceProps surfaceProps =
464*c8dee2aaSAndroid Build Coastguard Worker             this->surfaceProps().cloneWithPixelGeometry(cinfo.fPixelGeometry);
465*c8dee2aaSAndroid Build Coastguard Worker 
466*c8dee2aaSAndroid Build Coastguard Worker         return sk_make_sp<GlyphTrackingDevice>(cinfo.fInfo.dimensions(),
467*c8dee2aaSAndroid Build Coastguard Worker                                                surfaceProps,
468*c8dee2aaSAndroid Build Coastguard Worker                                                fStrikeServerImpl,
469*c8dee2aaSAndroid Build Coastguard Worker                                                cinfo.fInfo.refColorSpace(),
470*c8dee2aaSAndroid Build Coastguard Worker                                                fSubRunControl);
471*c8dee2aaSAndroid Build Coastguard Worker     }
472*c8dee2aaSAndroid Build Coastguard Worker 
strikeDeviceInfo() const473*c8dee2aaSAndroid Build Coastguard Worker     SkStrikeDeviceInfo strikeDeviceInfo() const override {
474*c8dee2aaSAndroid Build Coastguard Worker         return {this->surfaceProps(), this->scalerContextFlags(), &fSubRunControl};
475*c8dee2aaSAndroid Build Coastguard Worker     }
476*c8dee2aaSAndroid Build Coastguard Worker 
477*c8dee2aaSAndroid Build Coastguard Worker protected:
onDrawGlyphRunList(SkCanvas *,const sktext::GlyphRunList & glyphRunList,const SkPaint & paint)478*c8dee2aaSAndroid Build Coastguard Worker     void onDrawGlyphRunList(SkCanvas*,
479*c8dee2aaSAndroid Build Coastguard Worker                             const sktext::GlyphRunList& glyphRunList,
480*c8dee2aaSAndroid Build Coastguard Worker                             const SkPaint& paint) override {
481*c8dee2aaSAndroid Build Coastguard Worker         SkMatrix drawMatrix = this->localToDevice();
482*c8dee2aaSAndroid Build Coastguard Worker         drawMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());
483*c8dee2aaSAndroid Build Coastguard Worker 
484*c8dee2aaSAndroid Build Coastguard Worker         // Just ignore the resulting SubRunContainer. Since we're passing in a null SubRunAllocator
485*c8dee2aaSAndroid Build Coastguard Worker         // no SubRuns will be produced.
486*c8dee2aaSAndroid Build Coastguard Worker         STSubRunAllocator<sizeof(SubRunContainer), alignof(SubRunContainer)> tempAlloc;
487*c8dee2aaSAndroid Build Coastguard Worker         auto container = SubRunContainer::MakeInAlloc(glyphRunList,
488*c8dee2aaSAndroid Build Coastguard Worker                                                       drawMatrix,
489*c8dee2aaSAndroid Build Coastguard Worker                                                       paint,
490*c8dee2aaSAndroid Build Coastguard Worker                                                       this->strikeDeviceInfo(),
491*c8dee2aaSAndroid Build Coastguard Worker                                                       fStrikeServerImpl,
492*c8dee2aaSAndroid Build Coastguard Worker                                                       &tempAlloc,
493*c8dee2aaSAndroid Build Coastguard Worker                                                       SubRunContainer::kStrikeCalculationsOnly,
494*c8dee2aaSAndroid Build Coastguard Worker                                                       "Cache Diff");
495*c8dee2aaSAndroid Build Coastguard Worker         // Calculations only. No SubRuns.
496*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(container->isEmpty());
497*c8dee2aaSAndroid Build Coastguard Worker     }
498*c8dee2aaSAndroid Build Coastguard Worker 
convertGlyphRunListToSlug(const sktext::GlyphRunList & glyphRunList,const SkPaint & paint)499*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<sktext::gpu::Slug> convertGlyphRunListToSlug(const sktext::GlyphRunList& glyphRunList,
500*c8dee2aaSAndroid Build Coastguard Worker                                                        const SkPaint& paint) override {
501*c8dee2aaSAndroid Build Coastguard Worker         // Full matrix for placing glyphs.
502*c8dee2aaSAndroid Build Coastguard Worker         SkMatrix positionMatrix = this->localToDevice();
503*c8dee2aaSAndroid Build Coastguard Worker         positionMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());
504*c8dee2aaSAndroid Build Coastguard Worker 
505*c8dee2aaSAndroid Build Coastguard Worker         // Use the SkStrikeServer's strike cache to generate the Slug.
506*c8dee2aaSAndroid Build Coastguard Worker         return sktext::gpu::MakeSlug(this->localToDevice(),
507*c8dee2aaSAndroid Build Coastguard Worker                                      glyphRunList,
508*c8dee2aaSAndroid Build Coastguard Worker                                      paint,
509*c8dee2aaSAndroid Build Coastguard Worker                                      this->strikeDeviceInfo(),
510*c8dee2aaSAndroid Build Coastguard Worker                                      fStrikeServerImpl);
511*c8dee2aaSAndroid Build Coastguard Worker     }
512*c8dee2aaSAndroid Build Coastguard Worker 
513*c8dee2aaSAndroid Build Coastguard Worker private:
514*c8dee2aaSAndroid Build Coastguard Worker     SkStrikeServerImpl* const fStrikeServerImpl;
515*c8dee2aaSAndroid Build Coastguard Worker     const sktext::gpu::SubRunControl fSubRunControl;
516*c8dee2aaSAndroid Build Coastguard Worker };
517*c8dee2aaSAndroid Build Coastguard Worker 
518*c8dee2aaSAndroid Build Coastguard Worker // -- SkStrikeServer -------------------------------------------------------------------------------
SkStrikeServer(DiscardableHandleManager * dhm)519*c8dee2aaSAndroid Build Coastguard Worker SkStrikeServer::SkStrikeServer(DiscardableHandleManager* dhm)
520*c8dee2aaSAndroid Build Coastguard Worker         : fImpl(new SkStrikeServerImpl{dhm}) { }
521*c8dee2aaSAndroid Build Coastguard Worker 
522*c8dee2aaSAndroid Build Coastguard Worker SkStrikeServer::~SkStrikeServer() = default;
523*c8dee2aaSAndroid Build Coastguard Worker 
makeAnalysisCanvas(int width,int height,const SkSurfaceProps & props,sk_sp<SkColorSpace> colorSpace,bool DFTSupport,bool DFTPerspSupport)524*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCanvas> SkStrikeServer::makeAnalysisCanvas(int width, int height,
525*c8dee2aaSAndroid Build Coastguard Worker                                                              const SkSurfaceProps& props,
526*c8dee2aaSAndroid Build Coastguard Worker                                                              sk_sp<SkColorSpace> colorSpace,
527*c8dee2aaSAndroid Build Coastguard Worker                                                              bool DFTSupport,
528*c8dee2aaSAndroid Build Coastguard Worker                                                              bool DFTPerspSupport) {
529*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_DISABLE_SDF_TEXT)
530*c8dee2aaSAndroid Build Coastguard Worker     // These are copied from the defaults in GrContextOptions for historical reasons.
531*c8dee2aaSAndroid Build Coastguard Worker     // TODO(herb, jvanverth) pipe in parameters that can be used for both Ganesh and Graphite
532*c8dee2aaSAndroid Build Coastguard Worker     // backends instead of just using the defaults.
533*c8dee2aaSAndroid Build Coastguard Worker     constexpr float kMinDistanceFieldFontSize = 18.f;
534*c8dee2aaSAndroid Build Coastguard Worker 
535*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_ANDROID)
536*c8dee2aaSAndroid Build Coastguard Worker     constexpr float kGlyphsAsPathsFontSize = 384.f;
537*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_BUILD_FOR_MAC)
538*c8dee2aaSAndroid Build Coastguard Worker     constexpr float kGlyphsAsPathsFontSize = 256.f;
539*c8dee2aaSAndroid Build Coastguard Worker #else
540*c8dee2aaSAndroid Build Coastguard Worker     constexpr float kGlyphsAsPathsFontSize = 324.f;
541*c8dee2aaSAndroid Build Coastguard Worker #endif
542*c8dee2aaSAndroid Build Coastguard Worker     // There is no need to set forcePathAA for the remote glyph cache as that control impacts
543*c8dee2aaSAndroid Build Coastguard Worker     // *how* the glyphs are rendered as paths, not *when* they are rendered as paths.
544*c8dee2aaSAndroid Build Coastguard Worker     auto control = sktext::gpu::SubRunControl{DFTSupport,
545*c8dee2aaSAndroid Build Coastguard Worker                                             props.isUseDeviceIndependentFonts(),
546*c8dee2aaSAndroid Build Coastguard Worker                                             DFTPerspSupport,
547*c8dee2aaSAndroid Build Coastguard Worker                                             kMinDistanceFieldFontSize,
548*c8dee2aaSAndroid Build Coastguard Worker                                             kGlyphsAsPathsFontSize};
549*c8dee2aaSAndroid Build Coastguard Worker #else
550*c8dee2aaSAndroid Build Coastguard Worker     auto control = sktext::gpu::SubRunControl{};
551*c8dee2aaSAndroid Build Coastguard Worker #endif
552*c8dee2aaSAndroid Build Coastguard Worker 
553*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkDevice> trackingDevice = sk_make_sp<GlyphTrackingDevice>(
554*c8dee2aaSAndroid Build Coastguard Worker             SkISize::Make(width, height),
555*c8dee2aaSAndroid Build Coastguard Worker             props, this->impl(),
556*c8dee2aaSAndroid Build Coastguard Worker             std::move(colorSpace),
557*c8dee2aaSAndroid Build Coastguard Worker             control);
558*c8dee2aaSAndroid Build Coastguard Worker     return std::make_unique<SkCanvas>(std::move(trackingDevice));
559*c8dee2aaSAndroid Build Coastguard Worker }
560*c8dee2aaSAndroid Build Coastguard Worker 
writeStrikeData(std::vector<uint8_t> * memory)561*c8dee2aaSAndroid Build Coastguard Worker void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
562*c8dee2aaSAndroid Build Coastguard Worker     fImpl->writeStrikeData(memory);
563*c8dee2aaSAndroid Build Coastguard Worker }
564*c8dee2aaSAndroid Build Coastguard Worker 
impl()565*c8dee2aaSAndroid Build Coastguard Worker SkStrikeServerImpl* SkStrikeServer::impl() { return fImpl.get(); }
566*c8dee2aaSAndroid Build Coastguard Worker 
setMaxEntriesInDescriptorMapForTesting(size_t count)567*c8dee2aaSAndroid Build Coastguard Worker void SkStrikeServer::setMaxEntriesInDescriptorMapForTesting(size_t count) {
568*c8dee2aaSAndroid Build Coastguard Worker     fImpl->setMaxEntriesInDescriptorMapForTesting(count);
569*c8dee2aaSAndroid Build Coastguard Worker }
remoteStrikeMapSizeForTesting() const570*c8dee2aaSAndroid Build Coastguard Worker size_t SkStrikeServer::remoteStrikeMapSizeForTesting() const {
571*c8dee2aaSAndroid Build Coastguard Worker     return fImpl->remoteStrikeMapSizeForTesting();
572*c8dee2aaSAndroid Build Coastguard Worker }
573*c8dee2aaSAndroid Build Coastguard Worker 
574*c8dee2aaSAndroid Build Coastguard Worker // -- DiscardableStrikePinner ----------------------------------------------------------------------
575*c8dee2aaSAndroid Build Coastguard Worker class DiscardableStrikePinner : public SkStrikePinner {
576*c8dee2aaSAndroid Build Coastguard Worker public:
DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,sk_sp<SkStrikeClient::DiscardableHandleManager> manager)577*c8dee2aaSAndroid Build Coastguard Worker     DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,
578*c8dee2aaSAndroid Build Coastguard Worker                             sk_sp<SkStrikeClient::DiscardableHandleManager> manager)
579*c8dee2aaSAndroid Build Coastguard Worker             : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {}
580*c8dee2aaSAndroid Build Coastguard Worker 
581*c8dee2aaSAndroid Build Coastguard Worker     ~DiscardableStrikePinner() override = default;
canDelete()582*c8dee2aaSAndroid Build Coastguard Worker     bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); }
assertValid()583*c8dee2aaSAndroid Build Coastguard Worker     void assertValid() override { fManager->assertHandleValid(fDiscardableHandleId); }
584*c8dee2aaSAndroid Build Coastguard Worker 
585*c8dee2aaSAndroid Build Coastguard Worker private:
586*c8dee2aaSAndroid Build Coastguard Worker     const SkDiscardableHandleId fDiscardableHandleId;
587*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkStrikeClient::DiscardableHandleManager> fManager;
588*c8dee2aaSAndroid Build Coastguard Worker };
589*c8dee2aaSAndroid Build Coastguard Worker 
590*c8dee2aaSAndroid Build Coastguard Worker // -- SkStrikeClientImpl ---------------------------------------------------------------------------
591*c8dee2aaSAndroid Build Coastguard Worker class SkStrikeClientImpl {
592*c8dee2aaSAndroid Build Coastguard Worker public:
593*c8dee2aaSAndroid Build Coastguard Worker     explicit SkStrikeClientImpl(sk_sp<SkStrikeClient::DiscardableHandleManager>,
594*c8dee2aaSAndroid Build Coastguard Worker                                 bool isLogging = true,
595*c8dee2aaSAndroid Build Coastguard Worker                                 SkStrikeCache* strikeCache = nullptr);
596*c8dee2aaSAndroid Build Coastguard Worker 
597*c8dee2aaSAndroid Build Coastguard Worker     bool readStrikeData(const volatile void* memory, size_t memorySize);
598*c8dee2aaSAndroid Build Coastguard Worker     bool translateTypefaceID(SkAutoDescriptor* descriptor) const;
599*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkTypeface> retrieveTypefaceUsingServerID(SkTypefaceID) const;
600*c8dee2aaSAndroid Build Coastguard Worker 
601*c8dee2aaSAndroid Build Coastguard Worker private:
602*c8dee2aaSAndroid Build Coastguard Worker     class PictureBackedGlyphDrawable final : public SkDrawable {
603*c8dee2aaSAndroid Build Coastguard Worker     public:
PictureBackedGlyphDrawable(sk_sp<SkPicture> self)604*c8dee2aaSAndroid Build Coastguard Worker         PictureBackedGlyphDrawable(sk_sp<SkPicture> self) : fSelf(std::move(self)) {}
605*c8dee2aaSAndroid Build Coastguard Worker     private:
606*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkPicture> fSelf;
onGetBounds()607*c8dee2aaSAndroid Build Coastguard Worker         SkRect onGetBounds() override { return fSelf->cullRect();  }
onApproximateBytesUsed()608*c8dee2aaSAndroid Build Coastguard Worker         size_t onApproximateBytesUsed() override {
609*c8dee2aaSAndroid Build Coastguard Worker             return sizeof(PictureBackedGlyphDrawable) + fSelf->approximateBytesUsed();
610*c8dee2aaSAndroid Build Coastguard Worker         }
onDraw(SkCanvas * canvas)611*c8dee2aaSAndroid Build Coastguard Worker         void onDraw(SkCanvas* canvas) override { canvas->drawPicture(fSelf); }
612*c8dee2aaSAndroid Build Coastguard Worker     };
613*c8dee2aaSAndroid Build Coastguard Worker 
614*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkTypeface> addTypeface(const SkTypefaceProxyPrototype& typefaceProto);
615*c8dee2aaSAndroid Build Coastguard Worker 
616*c8dee2aaSAndroid Build Coastguard Worker     THashMap<SkTypefaceID, sk_sp<SkTypeface>> fServerTypefaceIdToTypeface;
617*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkStrikeClient::DiscardableHandleManager> fDiscardableHandleManager;
618*c8dee2aaSAndroid Build Coastguard Worker     SkStrikeCache* const fStrikeCache;
619*c8dee2aaSAndroid Build Coastguard Worker     const bool fIsLogging;
620*c8dee2aaSAndroid Build Coastguard Worker };
621*c8dee2aaSAndroid Build Coastguard Worker 
SkStrikeClientImpl(sk_sp<SkStrikeClient::DiscardableHandleManager> discardableManager,bool isLogging,SkStrikeCache * strikeCache)622*c8dee2aaSAndroid Build Coastguard Worker SkStrikeClientImpl::SkStrikeClientImpl(
623*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkStrikeClient::DiscardableHandleManager>
624*c8dee2aaSAndroid Build Coastguard Worker         discardableManager,
625*c8dee2aaSAndroid Build Coastguard Worker         bool isLogging,
626*c8dee2aaSAndroid Build Coastguard Worker         SkStrikeCache* strikeCache)
627*c8dee2aaSAndroid Build Coastguard Worker     : fDiscardableHandleManager(std::move(discardableManager)),
628*c8dee2aaSAndroid Build Coastguard Worker       fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()},
629*c8dee2aaSAndroid Build Coastguard Worker       fIsLogging{isLogging} {}
630*c8dee2aaSAndroid Build Coastguard Worker 
631*c8dee2aaSAndroid Build Coastguard Worker // Change the path count to track the line number of the failing read.
632*c8dee2aaSAndroid Build Coastguard Worker // TODO: change __LINE__ back to glyphPathsCount when bug chromium:1287356 is closed.
633*c8dee2aaSAndroid Build Coastguard Worker #define READ_FAILURE                                                        \
634*c8dee2aaSAndroid Build Coastguard Worker     {                                                                       \
635*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Bad font data serialization line: %d", __LINE__);         \
636*c8dee2aaSAndroid Build Coastguard Worker         SkStrikeClient::DiscardableHandleManager::ReadFailureData data = {  \
637*c8dee2aaSAndroid Build Coastguard Worker                 memorySize,  deserializer.bytesRead(), typefaceSize,        \
638*c8dee2aaSAndroid Build Coastguard Worker                 strikeCount, glyphImagesCount, __LINE__};                   \
639*c8dee2aaSAndroid Build Coastguard Worker         fDiscardableHandleManager->notifyReadFailure(data);                 \
640*c8dee2aaSAndroid Build Coastguard Worker         return false;                                                       \
641*c8dee2aaSAndroid Build Coastguard Worker     }
642*c8dee2aaSAndroid Build Coastguard Worker 
readStrikeData(const volatile void * memory,size_t memorySize)643*c8dee2aaSAndroid Build Coastguard Worker bool SkStrikeClientImpl::readStrikeData(const volatile void* memory, size_t memorySize) {
644*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(memorySize != 0);
645*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(memory != nullptr);
646*c8dee2aaSAndroid Build Coastguard Worker 
647*c8dee2aaSAndroid Build Coastguard Worker     // We do not need to set any SkDeserialProcs here because SkStrikeServerImpl::writeStrikeData
648*c8dee2aaSAndroid Build Coastguard Worker     // did not encode any SkImages.
649*c8dee2aaSAndroid Build Coastguard Worker     SkReadBuffer buffer{const_cast<const void*>(memory), memorySize};
650*c8dee2aaSAndroid Build Coastguard Worker     // Limit the kinds of effects that appear in a glyph's drawable (crbug.com/1442140):
651*c8dee2aaSAndroid Build Coastguard Worker     buffer.setAllowSkSL(false);
652*c8dee2aaSAndroid Build Coastguard Worker 
653*c8dee2aaSAndroid Build Coastguard Worker     int curTypeface = 0,
654*c8dee2aaSAndroid Build Coastguard Worker         curStrike = 0;
655*c8dee2aaSAndroid Build Coastguard Worker 
656*c8dee2aaSAndroid Build Coastguard Worker     auto postError = [&](int line) {
657*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Read Error Posted %s : %d", __FILE__, line);
658*c8dee2aaSAndroid Build Coastguard Worker         SkStrikeClient::DiscardableHandleManager::ReadFailureData data{
659*c8dee2aaSAndroid Build Coastguard Worker                 memorySize,
660*c8dee2aaSAndroid Build Coastguard Worker                 buffer.offset(),
661*c8dee2aaSAndroid Build Coastguard Worker                 SkTo<uint64_t>(curTypeface),
662*c8dee2aaSAndroid Build Coastguard Worker                 SkTo<uint64_t>(curStrike),
663*c8dee2aaSAndroid Build Coastguard Worker                 SkTo<uint64_t>(0),
664*c8dee2aaSAndroid Build Coastguard Worker                 SkTo<uint64_t>(0)};
665*c8dee2aaSAndroid Build Coastguard Worker         fDiscardableHandleManager->notifyReadFailure(data);
666*c8dee2aaSAndroid Build Coastguard Worker     };
667*c8dee2aaSAndroid Build Coastguard Worker 
668*c8dee2aaSAndroid Build Coastguard Worker     // Read the number of typefaces sent.
669*c8dee2aaSAndroid Build Coastguard Worker     const int typefaceCount = buffer.readInt();
670*c8dee2aaSAndroid Build Coastguard Worker     for (curTypeface = 0; curTypeface < typefaceCount; ++curTypeface) {
671*c8dee2aaSAndroid Build Coastguard Worker         auto proto = SkTypefaceProxyPrototype::MakeFromBuffer(buffer);
672*c8dee2aaSAndroid Build Coastguard Worker         if (proto) {
673*c8dee2aaSAndroid Build Coastguard Worker             this->addTypeface(proto.value());
674*c8dee2aaSAndroid Build Coastguard Worker         } else {
675*c8dee2aaSAndroid Build Coastguard Worker             postError(__LINE__);
676*c8dee2aaSAndroid Build Coastguard Worker             return false;
677*c8dee2aaSAndroid Build Coastguard Worker         }
678*c8dee2aaSAndroid Build Coastguard Worker     }
679*c8dee2aaSAndroid Build Coastguard Worker 
680*c8dee2aaSAndroid Build Coastguard Worker     // Read the number of strikes sent.
681*c8dee2aaSAndroid Build Coastguard Worker     const int stirkeCount = buffer.readInt();
682*c8dee2aaSAndroid Build Coastguard Worker     for (curStrike = 0; curStrike < stirkeCount; ++curStrike) {
683*c8dee2aaSAndroid Build Coastguard Worker 
684*c8dee2aaSAndroid Build Coastguard Worker         const SkTypefaceID serverTypefaceID = buffer.readUInt();
685*c8dee2aaSAndroid Build Coastguard Worker         if (serverTypefaceID == 0 && !buffer.isValid()) {
686*c8dee2aaSAndroid Build Coastguard Worker             postError(__LINE__);
687*c8dee2aaSAndroid Build Coastguard Worker             return false;
688*c8dee2aaSAndroid Build Coastguard Worker         }
689*c8dee2aaSAndroid Build Coastguard Worker 
690*c8dee2aaSAndroid Build Coastguard Worker         const SkDiscardableHandleId discardableHandleID = buffer.readUInt();
691*c8dee2aaSAndroid Build Coastguard Worker         if (discardableHandleID == 0 && !buffer.isValid()) {
692*c8dee2aaSAndroid Build Coastguard Worker             postError(__LINE__);
693*c8dee2aaSAndroid Build Coastguard Worker             return false;
694*c8dee2aaSAndroid Build Coastguard Worker         }
695*c8dee2aaSAndroid Build Coastguard Worker 
696*c8dee2aaSAndroid Build Coastguard Worker         std::optional<SkAutoDescriptor> serverDescriptor = SkAutoDescriptor::MakeFromBuffer(buffer);
697*c8dee2aaSAndroid Build Coastguard Worker         if (!buffer.validate(serverDescriptor.has_value())) {
698*c8dee2aaSAndroid Build Coastguard Worker             postError(__LINE__);
699*c8dee2aaSAndroid Build Coastguard Worker             return false;
700*c8dee2aaSAndroid Build Coastguard Worker         }
701*c8dee2aaSAndroid Build Coastguard Worker 
702*c8dee2aaSAndroid Build Coastguard Worker         const bool fontMetricsInitialized = buffer.readBool();
703*c8dee2aaSAndroid Build Coastguard Worker         if (!fontMetricsInitialized && !buffer.isValid()) {
704*c8dee2aaSAndroid Build Coastguard Worker             postError(__LINE__);
705*c8dee2aaSAndroid Build Coastguard Worker             return false;
706*c8dee2aaSAndroid Build Coastguard Worker         }
707*c8dee2aaSAndroid Build Coastguard Worker 
708*c8dee2aaSAndroid Build Coastguard Worker         std::optional<SkFontMetrics> fontMetrics;
709*c8dee2aaSAndroid Build Coastguard Worker         if (!fontMetricsInitialized) {
710*c8dee2aaSAndroid Build Coastguard Worker             fontMetrics = SkFontMetricsPriv::MakeFromBuffer(buffer);
711*c8dee2aaSAndroid Build Coastguard Worker             if (!fontMetrics || !buffer.isValid()) {
712*c8dee2aaSAndroid Build Coastguard Worker                 postError(__LINE__);
713*c8dee2aaSAndroid Build Coastguard Worker                 return false;
714*c8dee2aaSAndroid Build Coastguard Worker             }
715*c8dee2aaSAndroid Build Coastguard Worker         }
716*c8dee2aaSAndroid Build Coastguard Worker 
717*c8dee2aaSAndroid Build Coastguard Worker         auto* clientTypeface = fServerTypefaceIdToTypeface.find(serverTypefaceID);
718*c8dee2aaSAndroid Build Coastguard Worker         if (clientTypeface == nullptr) {
719*c8dee2aaSAndroid Build Coastguard Worker             postError(__LINE__);
720*c8dee2aaSAndroid Build Coastguard Worker             return false;
721*c8dee2aaSAndroid Build Coastguard Worker         }
722*c8dee2aaSAndroid Build Coastguard Worker 
723*c8dee2aaSAndroid Build Coastguard Worker         if (!this->translateTypefaceID(&serverDescriptor.value())) {
724*c8dee2aaSAndroid Build Coastguard Worker             postError(__LINE__);
725*c8dee2aaSAndroid Build Coastguard Worker             return false;
726*c8dee2aaSAndroid Build Coastguard Worker         }
727*c8dee2aaSAndroid Build Coastguard Worker 
728*c8dee2aaSAndroid Build Coastguard Worker         SkDescriptor* clientDescriptor = serverDescriptor->getDesc();
729*c8dee2aaSAndroid Build Coastguard Worker         auto strike = fStrikeCache->findStrike(*clientDescriptor);
730*c8dee2aaSAndroid Build Coastguard Worker 
731*c8dee2aaSAndroid Build Coastguard Worker         if (strike == nullptr) {
732*c8dee2aaSAndroid Build Coastguard Worker             // Metrics are only sent the first time. If creating a new strike, then the metrics
733*c8dee2aaSAndroid Build Coastguard Worker             // are not initialized.
734*c8dee2aaSAndroid Build Coastguard Worker             if (fontMetricsInitialized) {
735*c8dee2aaSAndroid Build Coastguard Worker                 postError(__LINE__);
736*c8dee2aaSAndroid Build Coastguard Worker                 return false;
737*c8dee2aaSAndroid Build Coastguard Worker             }
738*c8dee2aaSAndroid Build Coastguard Worker             SkStrikeSpec strikeSpec{*clientDescriptor, *clientTypeface};
739*c8dee2aaSAndroid Build Coastguard Worker             strike = fStrikeCache->createStrike(
740*c8dee2aaSAndroid Build Coastguard Worker                     strikeSpec, &fontMetrics.value(),
741*c8dee2aaSAndroid Build Coastguard Worker                     std::make_unique<DiscardableStrikePinner>(
742*c8dee2aaSAndroid Build Coastguard Worker                             discardableHandleID, fDiscardableHandleManager));
743*c8dee2aaSAndroid Build Coastguard Worker         }
744*c8dee2aaSAndroid Build Coastguard Worker 
745*c8dee2aaSAndroid Build Coastguard Worker         // Make sure this strike is pinned on the GPU side.
746*c8dee2aaSAndroid Build Coastguard Worker         strike->verifyPinnedStrike();
747*c8dee2aaSAndroid Build Coastguard Worker 
748*c8dee2aaSAndroid Build Coastguard Worker         if (!strike->mergeFromBuffer(buffer)) {
749*c8dee2aaSAndroid Build Coastguard Worker             postError(__LINE__);
750*c8dee2aaSAndroid Build Coastguard Worker             return false;
751*c8dee2aaSAndroid Build Coastguard Worker         }
752*c8dee2aaSAndroid Build Coastguard Worker     }
753*c8dee2aaSAndroid Build Coastguard Worker 
754*c8dee2aaSAndroid Build Coastguard Worker     return true;
755*c8dee2aaSAndroid Build Coastguard Worker }
756*c8dee2aaSAndroid Build Coastguard Worker 
translateTypefaceID(SkAutoDescriptor * toChange) const757*c8dee2aaSAndroid Build Coastguard Worker bool SkStrikeClientImpl::translateTypefaceID(SkAutoDescriptor* toChange) const {
758*c8dee2aaSAndroid Build Coastguard Worker     SkDescriptor& descriptor = *toChange->getDesc();
759*c8dee2aaSAndroid Build Coastguard Worker 
760*c8dee2aaSAndroid Build Coastguard Worker     // Rewrite the typefaceID in the rec.
761*c8dee2aaSAndroid Build Coastguard Worker     {
762*c8dee2aaSAndroid Build Coastguard Worker         uint32_t size;
763*c8dee2aaSAndroid Build Coastguard Worker         // findEntry returns a const void*, remove the const in order to update in place.
764*c8dee2aaSAndroid Build Coastguard Worker         void* ptr = const_cast<void *>(descriptor.findEntry(kRec_SkDescriptorTag, &size));
765*c8dee2aaSAndroid Build Coastguard Worker         SkScalerContextRec rec;
766*c8dee2aaSAndroid Build Coastguard Worker         if (!ptr || size != sizeof(rec)) { return false; }
767*c8dee2aaSAndroid Build Coastguard Worker         std::memcpy((void*)&rec, ptr, size);
768*c8dee2aaSAndroid Build Coastguard Worker         // Get the local typeface from remote typefaceID.
769*c8dee2aaSAndroid Build Coastguard Worker         auto* tfPtr = fServerTypefaceIdToTypeface.find(rec.fTypefaceID);
770*c8dee2aaSAndroid Build Coastguard Worker         // Received a strike for a typeface which doesn't exist.
771*c8dee2aaSAndroid Build Coastguard Worker         if (!tfPtr) { return false; }
772*c8dee2aaSAndroid Build Coastguard Worker         // Update the typeface id to work with the client side.
773*c8dee2aaSAndroid Build Coastguard Worker         rec.fTypefaceID = tfPtr->get()->uniqueID();
774*c8dee2aaSAndroid Build Coastguard Worker         std::memcpy(ptr, &rec, size);
775*c8dee2aaSAndroid Build Coastguard Worker     }
776*c8dee2aaSAndroid Build Coastguard Worker 
777*c8dee2aaSAndroid Build Coastguard Worker     descriptor.computeChecksum();
778*c8dee2aaSAndroid Build Coastguard Worker 
779*c8dee2aaSAndroid Build Coastguard Worker     return true;
780*c8dee2aaSAndroid Build Coastguard Worker }
781*c8dee2aaSAndroid Build Coastguard Worker 
retrieveTypefaceUsingServerID(SkTypefaceID typefaceID) const782*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> SkStrikeClientImpl::retrieveTypefaceUsingServerID(SkTypefaceID typefaceID) const {
783*c8dee2aaSAndroid Build Coastguard Worker     auto* tfPtr = fServerTypefaceIdToTypeface.find(typefaceID);
784*c8dee2aaSAndroid Build Coastguard Worker     return tfPtr != nullptr ? *tfPtr : nullptr;
785*c8dee2aaSAndroid Build Coastguard Worker }
786*c8dee2aaSAndroid Build Coastguard Worker 
addTypeface(const SkTypefaceProxyPrototype & typefaceProto)787*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> SkStrikeClientImpl::addTypeface(const SkTypefaceProxyPrototype& typefaceProto) {
788*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkTypeface>* typeface =
789*c8dee2aaSAndroid Build Coastguard Worker             fServerTypefaceIdToTypeface.find(typefaceProto.serverTypefaceID());
790*c8dee2aaSAndroid Build Coastguard Worker 
791*c8dee2aaSAndroid Build Coastguard Worker     // We already have the typeface.
792*c8dee2aaSAndroid Build Coastguard Worker     if (typeface != nullptr)  {
793*c8dee2aaSAndroid Build Coastguard Worker         return *typeface;
794*c8dee2aaSAndroid Build Coastguard Worker     }
795*c8dee2aaSAndroid Build Coastguard Worker 
796*c8dee2aaSAndroid Build Coastguard Worker     auto newTypeface = sk_make_sp<SkTypefaceProxy>(
797*c8dee2aaSAndroid Build Coastguard Worker             typefaceProto, fDiscardableHandleManager, fIsLogging);
798*c8dee2aaSAndroid Build Coastguard Worker     fServerTypefaceIdToTypeface.set(typefaceProto.serverTypefaceID(), newTypeface);
799*c8dee2aaSAndroid Build Coastguard Worker     return newTypeface;
800*c8dee2aaSAndroid Build Coastguard Worker }
801*c8dee2aaSAndroid Build Coastguard Worker 
802*c8dee2aaSAndroid Build Coastguard Worker // SkStrikeClient ----------------------------------------------------------------------------------
SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,bool isLogging,SkStrikeCache * strikeCache)803*c8dee2aaSAndroid Build Coastguard Worker SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,
804*c8dee2aaSAndroid Build Coastguard Worker                                bool isLogging,
805*c8dee2aaSAndroid Build Coastguard Worker                                SkStrikeCache* strikeCache)
806*c8dee2aaSAndroid Build Coastguard Worker        : fImpl{new SkStrikeClientImpl{std::move(discardableManager), isLogging, strikeCache}} {}
807*c8dee2aaSAndroid Build Coastguard Worker 
808*c8dee2aaSAndroid Build Coastguard Worker SkStrikeClient::~SkStrikeClient() = default;
809*c8dee2aaSAndroid Build Coastguard Worker 
readStrikeData(const volatile void * memory,size_t memorySize)810*c8dee2aaSAndroid Build Coastguard Worker bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) {
811*c8dee2aaSAndroid Build Coastguard Worker     return fImpl->readStrikeData(memory, memorySize);
812*c8dee2aaSAndroid Build Coastguard Worker }
813*c8dee2aaSAndroid Build Coastguard Worker 
retrieveTypefaceUsingServerIDForTest(SkTypefaceID typefaceID) const814*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> SkStrikeClient::retrieveTypefaceUsingServerIDForTest(
815*c8dee2aaSAndroid Build Coastguard Worker         SkTypefaceID typefaceID) const {
816*c8dee2aaSAndroid Build Coastguard Worker     return fImpl->retrieveTypefaceUsingServerID(typefaceID);
817*c8dee2aaSAndroid Build Coastguard Worker }
818*c8dee2aaSAndroid Build Coastguard Worker 
translateTypefaceID(SkAutoDescriptor * descriptor) const819*c8dee2aaSAndroid Build Coastguard Worker bool SkStrikeClient::translateTypefaceID(SkAutoDescriptor* descriptor) const {
820*c8dee2aaSAndroid Build Coastguard Worker     return fImpl->translateTypefaceID(descriptor);
821*c8dee2aaSAndroid Build Coastguard Worker }
822*c8dee2aaSAndroid Build Coastguard Worker 
deserializeSlugForTest(const void * data,size_t size) const823*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sktext::gpu::Slug> SkStrikeClient::deserializeSlugForTest(const void* data,
824*c8dee2aaSAndroid Build Coastguard Worker                                                                 size_t size) const {
825*c8dee2aaSAndroid Build Coastguard Worker     return sktext::gpu::Slug::Deserialize(data, size, this);
826*c8dee2aaSAndroid Build Coastguard Worker }
827