1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "include/core/SkGraphics.h"
10cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
11cb93a386Sopenharmony_ci#include "include/core/SkTextBlob.h"
12cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
13cb93a386Sopenharmony_ci#include "include/private/SkMutex.h"
14cb93a386Sopenharmony_ci#include "src/core/SkDraw.h"
15cb93a386Sopenharmony_ci#include "src/core/SkRemoteGlyphCache.h"
16cb93a386Sopenharmony_ci#include "src/core/SkScalerCache.h"
17cb93a386Sopenharmony_ci#include "src/core/SkStrikeCache.h"
18cb93a386Sopenharmony_ci#include "src/core/SkStrikeSpec.h"
19cb93a386Sopenharmony_ci#include "src/core/SkSurfacePriv.h"
20cb93a386Sopenharmony_ci#include "src/core/SkTypeface_remote.h"
21cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
22cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
23cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h"
24cb93a386Sopenharmony_ci#include "src/gpu/text/GrSDFTControl.h"
25cb93a386Sopenharmony_ci#include "tests/Test.h"
26cb93a386Sopenharmony_ci#include "tools/Resources.h"
27cb93a386Sopenharmony_ci#include "tools/ToolUtils.h"
28cb93a386Sopenharmony_ci#include "tools/fonts/TestEmptyTypeface.h"
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ciclass DiscardableManager : public SkStrikeServer::DiscardableHandleManager,
31cb93a386Sopenharmony_ci                           public SkStrikeClient::DiscardableHandleManager {
32cb93a386Sopenharmony_cipublic:
33cb93a386Sopenharmony_ci    DiscardableManager() { sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount)); }
34cb93a386Sopenharmony_ci    ~DiscardableManager() override = default;
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_ci    // Server implementation.
37cb93a386Sopenharmony_ci    SkDiscardableHandleId createHandle() override {
38cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_ci        // Handles starts as locked.
41cb93a386Sopenharmony_ci        fLockedHandles.add(++fNextHandleId);
42cb93a386Sopenharmony_ci        return fNextHandleId;
43cb93a386Sopenharmony_ci    }
44cb93a386Sopenharmony_ci    bool lockHandle(SkDiscardableHandleId id) override {
45cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci        if (id <= fLastDeletedHandleId) return false;
48cb93a386Sopenharmony_ci        fLockedHandles.add(id);
49cb93a386Sopenharmony_ci        return true;
50cb93a386Sopenharmony_ci    }
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ci    // Client implementation.
53cb93a386Sopenharmony_ci    bool deleteHandle(SkDiscardableHandleId id) override {
54cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci        return id <= fLastDeletedHandleId;
57cb93a386Sopenharmony_ci    }
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci    void notifyCacheMiss(SkStrikeClient::CacheMissType type, int fontSize) override {
60cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ci        fCacheMissCount[type]++;
63cb93a386Sopenharmony_ci    }
64cb93a386Sopenharmony_ci    bool isHandleDeleted(SkDiscardableHandleId id) override {
65cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci        return id <= fLastDeletedHandleId;
68cb93a386Sopenharmony_ci    }
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    void unlockAll() {
71cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci        fLockedHandles.reset();
74cb93a386Sopenharmony_ci    }
75cb93a386Sopenharmony_ci    void unlockAndDeleteAll() {
76cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ci        fLockedHandles.reset();
79cb93a386Sopenharmony_ci        fLastDeletedHandleId = fNextHandleId;
80cb93a386Sopenharmony_ci    }
81cb93a386Sopenharmony_ci    const SkTHashSet<SkDiscardableHandleId>& lockedHandles() const {
82cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ci        return fLockedHandles;
85cb93a386Sopenharmony_ci    }
86cb93a386Sopenharmony_ci    SkDiscardableHandleId handleCount() {
87cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci        return fNextHandleId;
90cb93a386Sopenharmony_ci    }
91cb93a386Sopenharmony_ci    int cacheMissCount(uint32_t type) {
92cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ci        return fCacheMissCount[type];
95cb93a386Sopenharmony_ci    }
96cb93a386Sopenharmony_ci    bool hasCacheMiss() const {
97cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ci        for (uint32_t i = 0; i <= SkStrikeClient::CacheMissType::kLast; ++i) {
100cb93a386Sopenharmony_ci            if (fCacheMissCount[i] > 0) { return true; }
101cb93a386Sopenharmony_ci        }
102cb93a386Sopenharmony_ci        return false;
103cb93a386Sopenharmony_ci    }
104cb93a386Sopenharmony_ci    void resetCacheMissCounts() {
105cb93a386Sopenharmony_ci        SkAutoMutexExclusive l(fMutex);
106cb93a386Sopenharmony_ci        sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount));
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ciprivate:
110cb93a386Sopenharmony_ci    // The tests below run in parallel on multiple threads and use the same
111cb93a386Sopenharmony_ci    // process global SkStrikeCache. So the implementation needs to be
112cb93a386Sopenharmony_ci    // thread-safe.
113cb93a386Sopenharmony_ci    mutable SkMutex fMutex;
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ci    SkDiscardableHandleId fNextHandleId = 0u;
116cb93a386Sopenharmony_ci    SkDiscardableHandleId fLastDeletedHandleId = 0u;
117cb93a386Sopenharmony_ci    SkTHashSet<SkDiscardableHandleId> fLockedHandles;
118cb93a386Sopenharmony_ci    int fCacheMissCount[SkStrikeClient::CacheMissType::kLast + 1u];
119cb93a386Sopenharmony_ci};
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_cisk_sp<SkTextBlob> buildTextBlob(sk_sp<SkTypeface> tf, int glyphCount) {
122cb93a386Sopenharmony_ci    SkFont font;
123cb93a386Sopenharmony_ci    font.setTypeface(tf);
124cb93a386Sopenharmony_ci    font.setHinting(SkFontHinting::kNormal);
125cb93a386Sopenharmony_ci    font.setSize(1u);
126cb93a386Sopenharmony_ci    font.setEdging(SkFont::Edging::kAntiAlias);
127cb93a386Sopenharmony_ci    font.setSubpixel(true);
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci    SkTextBlobBuilder builder;
130cb93a386Sopenharmony_ci    SkRect bounds = SkRect::MakeWH(10, 10);
131cb93a386Sopenharmony_ci    const auto& runBuffer = builder.allocRunPosH(font, glyphCount, 0, &bounds);
132cb93a386Sopenharmony_ci    SkASSERT(runBuffer.utf8text == nullptr);
133cb93a386Sopenharmony_ci    SkASSERT(runBuffer.clusters == nullptr);
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ci    for (int i = 0; i < glyphCount; i++) {
136cb93a386Sopenharmony_ci        runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
137cb93a386Sopenharmony_ci        runBuffer.pos[i] = SkIntToScalar(i);
138cb93a386Sopenharmony_ci    }
139cb93a386Sopenharmony_ci    return builder.make();
140cb93a386Sopenharmony_ci}
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_cistatic void compare_blobs(const SkBitmap& expected, const SkBitmap& actual,
143cb93a386Sopenharmony_ci                          skiatest::Reporter* reporter, int tolerance = 0) {
144cb93a386Sopenharmony_ci    SkASSERT(expected.width() == actual.width());
145cb93a386Sopenharmony_ci    SkASSERT(expected.height() == actual.height());
146cb93a386Sopenharmony_ci    for (int i = 0; i < expected.width(); ++i) {
147cb93a386Sopenharmony_ci        for (int j = 0; j < expected.height(); ++j) {
148cb93a386Sopenharmony_ci            SkColor expectedColor = expected.getColor(i, j);
149cb93a386Sopenharmony_ci            SkColor actualColor = actual.getColor(i, j);
150cb93a386Sopenharmony_ci            if (0 == tolerance) {
151cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, expectedColor == actualColor);
152cb93a386Sopenharmony_ci            } else {
153cb93a386Sopenharmony_ci                for (int k = 0; k < 4; ++k) {
154cb93a386Sopenharmony_ci                    int expectedChannel = (expectedColor >> (k*8)) & 0xff;
155cb93a386Sopenharmony_ci                    int actualChannel = (actualColor >> (k*8)) & 0xff;
156cb93a386Sopenharmony_ci                    REPORTER_ASSERT(reporter, abs(expectedChannel - actualChannel) <= tolerance);
157cb93a386Sopenharmony_ci                }
158cb93a386Sopenharmony_ci            }
159cb93a386Sopenharmony_ci        }
160cb93a386Sopenharmony_ci    }
161cb93a386Sopenharmony_ci}
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_cisk_sp<SkSurface> MakeSurface(int width, int height, GrRecordingContext* rContext) {
164cb93a386Sopenharmony_ci    const SkImageInfo info =
165cb93a386Sopenharmony_ci            SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
166cb93a386Sopenharmony_ci    return SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info);
167cb93a386Sopenharmony_ci}
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ciSkSurfaceProps FindSurfaceProps(GrRecordingContext* rContext) {
170cb93a386Sopenharmony_ci    auto surface = MakeSurface(1, 1, rContext);
171cb93a386Sopenharmony_ci    return surface->props();
172cb93a386Sopenharmony_ci}
173cb93a386Sopenharmony_ci
174cb93a386Sopenharmony_ciSkBitmap RasterBlob(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint& paint,
175cb93a386Sopenharmony_ci                    GrRecordingContext* rContext, const SkMatrix* matrix = nullptr,
176cb93a386Sopenharmony_ci                    SkScalar x = 0) {
177cb93a386Sopenharmony_ci    auto surface = MakeSurface(width, height, rContext);
178cb93a386Sopenharmony_ci    if (matrix) surface->getCanvas()->concat(*matrix);
179cb93a386Sopenharmony_ci    surface->getCanvas()->drawTextBlob(blob.get(), x, height/2, paint);
180cb93a386Sopenharmony_ci    SkBitmap bitmap;
181cb93a386Sopenharmony_ci    bitmap.allocN32Pixels(width, height);
182cb93a386Sopenharmony_ci    surface->readPixels(bitmap, 0, 0);
183cb93a386Sopenharmony_ci    return bitmap;
184cb93a386Sopenharmony_ci}
185cb93a386Sopenharmony_ci
186cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_TypefaceSerialization, reporter) {
187cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
188cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
189cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_ci    auto server_tf = SkTypeface::MakeDefault();
192cb93a386Sopenharmony_ci    auto tf_data = server.serializeTypeface(server_tf.get());
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci    auto client_tf = client.deserializeTypeface(tf_data->data(), tf_data->size());
195cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, client_tf);
196cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, static_cast<SkTypefaceProxy*>(client_tf.get())->remoteTypefaceID() ==
197cb93a386Sopenharmony_ci                                      server_tf->uniqueID());
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
200cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
201cb93a386Sopenharmony_ci}
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_StrikeSerialization, reporter, ctxInfo) {
204cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
205cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
206cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
207cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
208cb93a386Sopenharmony_ci    const SkPaint paint;
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_ci    // Server.
211cb93a386Sopenharmony_ci    auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
212cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_ci    int glyphCount = 10;
215cb93a386Sopenharmony_ci    auto serverBlob = buildTextBlob(serverTf, glyphCount);
216cb93a386Sopenharmony_ci    auto props = FindSurfaceProps(dContext);
217cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
218cb93a386Sopenharmony_ci            10, 10, props, nullptr, dContext->supportsDistanceFieldText());
219cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
220cb93a386Sopenharmony_ci
221cb93a386Sopenharmony_ci    std::vector<uint8_t> serverStrikeData;
222cb93a386Sopenharmony_ci    server.writeStrikeData(&serverStrikeData);
223cb93a386Sopenharmony_ci
224cb93a386Sopenharmony_ci    // Client.
225cb93a386Sopenharmony_ci    auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
226cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
227cb93a386Sopenharmony_ci                    client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
228cb93a386Sopenharmony_ci    auto clientBlob = buildTextBlob(clientTf, glyphCount);
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_ci    SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, dContext);
231cb93a386Sopenharmony_ci    SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, dContext);
232cb93a386Sopenharmony_ci    compare_blobs(expected, actual, reporter);
233cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
236cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
237cb93a386Sopenharmony_ci}
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_ReleaseTypeFace, reporter, ctxInfo) {
240cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
241cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
242cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
243cb93a386Sopenharmony_ci
244cb93a386Sopenharmony_ci    // Server.
245cb93a386Sopenharmony_ci    auto serverTf     = TestEmptyTypeface::Make();
246cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
247cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, serverTf->unique());
248cb93a386Sopenharmony_ci
249cb93a386Sopenharmony_ci    {
250cb93a386Sopenharmony_ci        const SkPaint paint;
251cb93a386Sopenharmony_ci        int glyphCount = 10;
252cb93a386Sopenharmony_ci        auto serverBlob = buildTextBlob(serverTf, glyphCount);
253cb93a386Sopenharmony_ci        const SkSurfaceProps props;
254cb93a386Sopenharmony_ci        std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
255cb93a386Sopenharmony_ci            10, 10, props, nullptr, ctxInfo.directContext()->supportsDistanceFieldText());
256cb93a386Sopenharmony_ci        cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
257cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !serverTf->unique());
258cb93a386Sopenharmony_ci
259cb93a386Sopenharmony_ci        std::vector<uint8_t> serverStrikeData;
260cb93a386Sopenharmony_ci        server.writeStrikeData(&serverStrikeData);
261cb93a386Sopenharmony_ci    }
262cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, serverTf->unique());
263cb93a386Sopenharmony_ci
264cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
265cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
266cb93a386Sopenharmony_ci}
267cb93a386Sopenharmony_ci
268cb93a386Sopenharmony_ci#ifdef SKIA_COMPILE_DM_ALL
269cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter) {
270cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
271cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
272cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
273cb93a386Sopenharmony_ci
274cb93a386Sopenharmony_ci    auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
275cb93a386Sopenharmony_ci    server.serializeTypeface(serverTf.get());
276cb93a386Sopenharmony_ci    int glyphCount = 10;
277cb93a386Sopenharmony_ci    auto serverBlob = buildTextBlob(serverTf, glyphCount);
278cb93a386Sopenharmony_ci
279cb93a386Sopenharmony_ci    const SkSurfaceProps props;
280cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas =
281cb93a386Sopenharmony_ci            server.makeAnalysisCanvas(10, 10, props, nullptr, true);
282cb93a386Sopenharmony_ci    SkPaint paint;
283cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci    // The strike from the blob should be locked after it has been drawn on the canvas.
286cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
287cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u);
288cb93a386Sopenharmony_ci
289cb93a386Sopenharmony_ci    // Write the strike data and unlock everything. Re-analyzing the blob should lock the handle
290cb93a386Sopenharmony_ci    // again.
291cb93a386Sopenharmony_ci    std::vector<uint8_t> fontData;
292cb93a386Sopenharmony_ci    server.writeStrikeData(&fontData);
293cb93a386Sopenharmony_ci    discardableManager->unlockAll();
294cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 0u);
295cb93a386Sopenharmony_ci
296cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
297cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
298cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u);
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
301cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
302cb93a386Sopenharmony_ci}
303cb93a386Sopenharmony_ci#endif
304cb93a386Sopenharmony_ci
305cb93a386Sopenharmony_ci#ifdef SKIA_COMPILE_DM_ALL
306cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_StrikeDeletionServer, reporter) {
307cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
308cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
309cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
310cb93a386Sopenharmony_ci
311cb93a386Sopenharmony_ci    auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
312cb93a386Sopenharmony_ci    server.serializeTypeface(serverTf.get());
313cb93a386Sopenharmony_ci    int glyphCount = 10;
314cb93a386Sopenharmony_ci    auto serverBlob = buildTextBlob(serverTf, glyphCount);
315cb93a386Sopenharmony_ci
316cb93a386Sopenharmony_ci    const SkSurfaceProps props;
317cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas =
318cb93a386Sopenharmony_ci            server.makeAnalysisCanvas(10, 10, props, nullptr, true);
319cb93a386Sopenharmony_ci    SkPaint paint;
320cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
321cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
322cb93a386Sopenharmony_ci
323cb93a386Sopenharmony_ci    // Write the strike data and delete all the handles. Re-analyzing the blob should create new
324cb93a386Sopenharmony_ci    // handles.
325cb93a386Sopenharmony_ci    std::vector<uint8_t> fontData;
326cb93a386Sopenharmony_ci    server.writeStrikeData(&fontData);
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ci    // Another analysis pass, to ensure that deleting handles after a complete cache hit still
329cb93a386Sopenharmony_ci    // works. This is a regression test for crbug.com/999682.
330cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
331cb93a386Sopenharmony_ci    server.writeStrikeData(&fontData);
332cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
333cb93a386Sopenharmony_ci
334cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
335cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
336cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->handleCount() == 2u);
337cb93a386Sopenharmony_ci
338cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
339cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
340cb93a386Sopenharmony_ci}
341cb93a386Sopenharmony_ci#endif
342cb93a386Sopenharmony_ci
343cb93a386Sopenharmony_ci#ifdef SKIA_COMPILE_DM_ALL
344cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_StrikePinningClient, reporter) {
345cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
346cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
347cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
348cb93a386Sopenharmony_ci
349cb93a386Sopenharmony_ci    // Server.
350cb93a386Sopenharmony_ci    auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
351cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
352cb93a386Sopenharmony_ci
353cb93a386Sopenharmony_ci    int glyphCount = 10;
354cb93a386Sopenharmony_ci    auto serverBlob = buildTextBlob(serverTf, glyphCount);
355cb93a386Sopenharmony_ci
356cb93a386Sopenharmony_ci    const SkSurfaceProps props;
357cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas =
358cb93a386Sopenharmony_ci            server.makeAnalysisCanvas(10, 10, props, nullptr, true);
359cb93a386Sopenharmony_ci    SkPaint paint;
360cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ci    std::vector<uint8_t> serverStrikeData;
363cb93a386Sopenharmony_ci    server.writeStrikeData(&serverStrikeData);
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_ci    // Client.
366cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
367cb93a386Sopenharmony_ci                    client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
368cb93a386Sopenharmony_ci    auto* clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()).get();
369cb93a386Sopenharmony_ci
370cb93a386Sopenharmony_ci    // The cache remains alive until it is pinned in the discardable manager.
371cb93a386Sopenharmony_ci    SkGraphics::PurgeFontCache();
372cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !clientTf->unique());
373cb93a386Sopenharmony_ci
374cb93a386Sopenharmony_ci    // Once the strike is unpinned and purged, SkStrikeClient should be the only owner of the
375cb93a386Sopenharmony_ci    // clientTf.
376cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
377cb93a386Sopenharmony_ci    SkGraphics::PurgeFontCache();
378cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, clientTf->unique());
379cb93a386Sopenharmony_ci
380cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
381cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
382cb93a386Sopenharmony_ci}
383cb93a386Sopenharmony_ci#endif
384cb93a386Sopenharmony_ci
385cb93a386Sopenharmony_ci#ifdef SKIA_COMPILE_DM_ALL
386cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_ClientMemoryAccounting, reporter) {
387cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
388cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
389cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
390cb93a386Sopenharmony_ci
391cb93a386Sopenharmony_ci    // Server.
392cb93a386Sopenharmony_ci    auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
393cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
394cb93a386Sopenharmony_ci
395cb93a386Sopenharmony_ci    int glyphCount = 10;
396cb93a386Sopenharmony_ci    auto serverBlob = buildTextBlob(serverTf, glyphCount);
397cb93a386Sopenharmony_ci
398cb93a386Sopenharmony_ci    const SkSurfaceProps props;
399cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas =
400cb93a386Sopenharmony_ci            server.makeAnalysisCanvas(10, 10, props, nullptr, true);
401cb93a386Sopenharmony_ci    SkPaint paint;
402cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
403cb93a386Sopenharmony_ci
404cb93a386Sopenharmony_ci    std::vector<uint8_t> serverStrikeData;
405cb93a386Sopenharmony_ci    server.writeStrikeData(&serverStrikeData);
406cb93a386Sopenharmony_ci
407cb93a386Sopenharmony_ci    // Client.
408cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
409cb93a386Sopenharmony_ci                    client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
410cb93a386Sopenharmony_ci
411cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
412cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
413cb93a386Sopenharmony_ci}
414cb93a386Sopenharmony_ci#endif
415cb93a386Sopenharmony_ci
416cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_PurgesServerEntries, reporter) {
417cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
418cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
419cb93a386Sopenharmony_ci    server.setMaxEntriesInDescriptorMapForTesting(1u);
420cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_ci    {
423cb93a386Sopenharmony_ci        auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
424cb93a386Sopenharmony_ci        int glyphCount = 10;
425cb93a386Sopenharmony_ci        auto serverBlob = buildTextBlob(serverTf, glyphCount);
426cb93a386Sopenharmony_ci
427cb93a386Sopenharmony_ci        const SkSurfaceProps props;
428cb93a386Sopenharmony_ci        std::unique_ptr<SkCanvas> cache_diff_canvas =
429cb93a386Sopenharmony_ci            server.makeAnalysisCanvas(10, 10, props, nullptr, true);
430cb93a386Sopenharmony_ci        SkPaint paint;
431cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 0u);
432cb93a386Sopenharmony_ci        cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
433cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u);
434cb93a386Sopenharmony_ci    }
435cb93a386Sopenharmony_ci
436cb93a386Sopenharmony_ci    // Serialize to release the lock from the strike server and delete all current
437cb93a386Sopenharmony_ci    // handles.
438cb93a386Sopenharmony_ci    std::vector<uint8_t> fontData;
439cb93a386Sopenharmony_ci    server.writeStrikeData(&fontData);
440cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
441cb93a386Sopenharmony_ci
442cb93a386Sopenharmony_ci    // Use a different typeface. Creating a new strike should evict the previous
443cb93a386Sopenharmony_ci    // one.
444cb93a386Sopenharmony_ci    {
445cb93a386Sopenharmony_ci        auto serverTf = SkTypeface::MakeFromName("Georgia", SkFontStyle());
446cb93a386Sopenharmony_ci        int glyphCount = 10;
447cb93a386Sopenharmony_ci        auto serverBlob = buildTextBlob(serverTf, glyphCount);
448cb93a386Sopenharmony_ci
449cb93a386Sopenharmony_ci        const SkSurfaceProps props;
450cb93a386Sopenharmony_ci        std::unique_ptr<SkCanvas> cache_diff_canvas =
451cb93a386Sopenharmony_ci            server.makeAnalysisCanvas(10, 10, props, nullptr, true);
452cb93a386Sopenharmony_ci        SkPaint paint;
453cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u);
454cb93a386Sopenharmony_ci        cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
455cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u);
456cb93a386Sopenharmony_ci    }
457cb93a386Sopenharmony_ci
458cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
459cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
460cb93a386Sopenharmony_ci}
461cb93a386Sopenharmony_ci
462cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsPath, reporter, ctxInfo) {
463cb93a386Sopenharmony_ci    auto direct = ctxInfo.directContext();
464cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
465cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
466cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
467cb93a386Sopenharmony_ci    SkPaint paint;
468cb93a386Sopenharmony_ci    paint.setStyle(SkPaint::kStroke_Style);
469cb93a386Sopenharmony_ci    paint.setStrokeWidth(0);
470cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
471cb93a386Sopenharmony_ci            SkStrikeSpec::ShouldDrawAsPath(paint, SkFont(), SkMatrix::I()));
472cb93a386Sopenharmony_ci
473cb93a386Sopenharmony_ci    // Server.
474cb93a386Sopenharmony_ci    auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
475cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
476cb93a386Sopenharmony_ci
477cb93a386Sopenharmony_ci    int glyphCount = 10;
478cb93a386Sopenharmony_ci    auto serverBlob = buildTextBlob(serverTf, glyphCount);
479cb93a386Sopenharmony_ci    auto props = FindSurfaceProps(direct);
480cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
481cb93a386Sopenharmony_ci            10, 10, props, nullptr, direct->supportsDistanceFieldText());
482cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
483cb93a386Sopenharmony_ci
484cb93a386Sopenharmony_ci    std::vector<uint8_t> serverStrikeData;
485cb93a386Sopenharmony_ci    server.writeStrikeData(&serverStrikeData);
486cb93a386Sopenharmony_ci
487cb93a386Sopenharmony_ci    // Client.
488cb93a386Sopenharmony_ci    auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
489cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
490cb93a386Sopenharmony_ci                    client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
491cb93a386Sopenharmony_ci    auto clientBlob = buildTextBlob(clientTf, glyphCount);
492cb93a386Sopenharmony_ci
493cb93a386Sopenharmony_ci    SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct);
494cb93a386Sopenharmony_ci    SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct);
495cb93a386Sopenharmony_ci    compare_blobs(expected, actual, reporter, 1);
496cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
497cb93a386Sopenharmony_ci
498cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
499cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
500cb93a386Sopenharmony_ci}
501cb93a386Sopenharmony_ci
502cb93a386Sopenharmony_cisk_sp<SkTextBlob> make_blob_causing_fallback(
503cb93a386Sopenharmony_ci        sk_sp<SkTypeface> targetTf, const SkTypeface* glyphTf, skiatest::Reporter* reporter) {
504cb93a386Sopenharmony_ci    SkFont font;
505cb93a386Sopenharmony_ci    font.setSubpixel(true);
506cb93a386Sopenharmony_ci    font.setSize(96);
507cb93a386Sopenharmony_ci    font.setHinting(SkFontHinting::kNormal);
508cb93a386Sopenharmony_ci    font.setTypeface(targetTf);
509cb93a386Sopenharmony_ci
510cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
511cb93a386Sopenharmony_ci            !SkStrikeSpec::ShouldDrawAsPath(SkPaint(), font, SkMatrix::I()));
512cb93a386Sopenharmony_ci
513cb93a386Sopenharmony_ci    char s[] = "Skia";
514cb93a386Sopenharmony_ci    int runSize = strlen(s);
515cb93a386Sopenharmony_ci
516cb93a386Sopenharmony_ci    SkTextBlobBuilder builder;
517cb93a386Sopenharmony_ci    SkRect bounds = SkRect::MakeIWH(100, 100);
518cb93a386Sopenharmony_ci    const auto& runBuffer = builder.allocRunPosH(font, runSize, 10, &bounds);
519cb93a386Sopenharmony_ci    SkASSERT(runBuffer.utf8text == nullptr);
520cb93a386Sopenharmony_ci    SkASSERT(runBuffer.clusters == nullptr);
521cb93a386Sopenharmony_ci
522cb93a386Sopenharmony_ci    SkFont(sk_ref_sp(glyphTf)).textToGlyphs(s, strlen(s), SkTextEncoding::kUTF8,
523cb93a386Sopenharmony_ci                                            runBuffer.glyphs, runSize);
524cb93a386Sopenharmony_ci
525cb93a386Sopenharmony_ci    SkRect glyphBounds;
526cb93a386Sopenharmony_ci    font.getWidths(runBuffer.glyphs, 1, nullptr, &glyphBounds);
527cb93a386Sopenharmony_ci
528cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, glyphBounds.width() > SkStrikeCommon::kSkSideTooBigForAtlas);
529cb93a386Sopenharmony_ci
530cb93a386Sopenharmony_ci    for (int i = 0; i < runSize; i++) {
531cb93a386Sopenharmony_ci        runBuffer.pos[i] = i * 10;
532cb93a386Sopenharmony_ci    }
533cb93a386Sopenharmony_ci
534cb93a386Sopenharmony_ci    return builder.make();
535cb93a386Sopenharmony_ci}
536cb93a386Sopenharmony_ci
537cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsMaskWithPathFallback,
538cb93a386Sopenharmony_ci        reporter, ctxInfo) {
539cb93a386Sopenharmony_ci    auto direct = ctxInfo.directContext();
540cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
541cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
542cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
543cb93a386Sopenharmony_ci
544cb93a386Sopenharmony_ci    SkPaint paint;
545cb93a386Sopenharmony_ci
546cb93a386Sopenharmony_ci    auto serverTf = MakeResourceAsTypeface("fonts/HangingS.ttf");
547cb93a386Sopenharmony_ci    // TODO: when the cq bots can handle this font remove the check.
548cb93a386Sopenharmony_ci    if (serverTf == nullptr) {
549cb93a386Sopenharmony_ci        return;
550cb93a386Sopenharmony_ci    }
551cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
552cb93a386Sopenharmony_ci
553cb93a386Sopenharmony_ci    auto serverBlob = make_blob_causing_fallback(serverTf, serverTf.get(), reporter);
554cb93a386Sopenharmony_ci
555cb93a386Sopenharmony_ci    auto props = FindSurfaceProps(direct);
556cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
557cb93a386Sopenharmony_ci            10, 10, props, nullptr, direct->supportsDistanceFieldText());
558cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
559cb93a386Sopenharmony_ci
560cb93a386Sopenharmony_ci    std::vector<uint8_t> serverStrikeData;
561cb93a386Sopenharmony_ci    server.writeStrikeData(&serverStrikeData);
562cb93a386Sopenharmony_ci
563cb93a386Sopenharmony_ci    // Client.
564cb93a386Sopenharmony_ci    auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
565cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
566cb93a386Sopenharmony_ci                    client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
567cb93a386Sopenharmony_ci
568cb93a386Sopenharmony_ci    auto clientBlob = make_blob_causing_fallback(clientTf, serverTf.get(), reporter);
569cb93a386Sopenharmony_ci
570cb93a386Sopenharmony_ci    SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct);
571cb93a386Sopenharmony_ci    SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct);
572cb93a386Sopenharmony_ci    compare_blobs(expected, actual, reporter);
573cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
574cb93a386Sopenharmony_ci
575cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
576cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
577cb93a386Sopenharmony_ci}
578cb93a386Sopenharmony_ci
579cb93a386Sopenharmony_ci#if 0
580cb93a386Sopenharmony_ci// TODO: turn this one when I figure out how to deal with the pixel variance from linear
581cb93a386Sopenharmony_ci//  interpolation from GPU to GPU.
582cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsSDFTWithAllARGBFallback,
583cb93a386Sopenharmony_ci                                   reporter, ctxInfo) {
584cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
585cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
586cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
587cb93a386Sopenharmony_ci
588cb93a386Sopenharmony_ci    SkPaint paint;
589cb93a386Sopenharmony_ci
590cb93a386Sopenharmony_ci    auto serverTf = ToolUtils::planet_typeface();
591cb93a386Sopenharmony_ci    // TODO: when the cq bots can handle this font remove the check.
592cb93a386Sopenharmony_ci    if (serverTf == nullptr) {
593cb93a386Sopenharmony_ci        return;
594cb93a386Sopenharmony_ci    }
595cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
596cb93a386Sopenharmony_ci
597cb93a386Sopenharmony_ci    auto makeBlob = [&reporter](sk_sp<SkTypeface> typeface) {
598cb93a386Sopenharmony_ci        SkFont font;
599cb93a386Sopenharmony_ci        font.setSubpixel(true);
600cb93a386Sopenharmony_ci        font.setSize(96);
601cb93a386Sopenharmony_ci        font.setHinting(SkFontHinting::kNormal);
602cb93a386Sopenharmony_ci        font.setTypeface(typeface);
603cb93a386Sopenharmony_ci
604cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !SkDraw::ShouldDrawTextAsPaths(font, SkPaint(), SkMatrix::I()));
605cb93a386Sopenharmony_ci
606cb93a386Sopenharmony_ci        // Mercury to Uranus.
607cb93a386Sopenharmony_ci        SkGlyphID glyphs[] = {1, 2, 3, 4, 5, 6, 7, 8};
608cb93a386Sopenharmony_ci
609cb93a386Sopenharmony_ci        SkTextBlobBuilder builder;
610cb93a386Sopenharmony_ci        SkRect bounds = SkRect::MakeIWH(100, 100);
611cb93a386Sopenharmony_ci        const auto& runBuffer = builder.allocRunPosH(font, SK_ARRAY_COUNT(glyphs), 100, &bounds);
612cb93a386Sopenharmony_ci        SkASSERT(runBuffer.utf8text == nullptr);
613cb93a386Sopenharmony_ci        SkASSERT(runBuffer.clusters == nullptr);
614cb93a386Sopenharmony_ci
615cb93a386Sopenharmony_ci        std::copy(std::begin(glyphs), std::end(glyphs), runBuffer.glyphs);
616cb93a386Sopenharmony_ci
617cb93a386Sopenharmony_ci        for (size_t i = 0; i < SK_ARRAY_COUNT(glyphs); i++) {
618cb93a386Sopenharmony_ci            runBuffer.pos[i] = i * 100;
619cb93a386Sopenharmony_ci        }
620cb93a386Sopenharmony_ci
621cb93a386Sopenharmony_ci        return builder.make();
622cb93a386Sopenharmony_ci    };
623cb93a386Sopenharmony_ci
624cb93a386Sopenharmony_ci    auto serverBlob = makeBlob(serverTf);
625cb93a386Sopenharmony_ci
626cb93a386Sopenharmony_ci    auto props = FindSurfaceProps(ctxInfo.grContext());
627cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
628cb93a386Sopenharmony_ci            10, 10, props, nullptr, ctxInfo.directContext()->supportsDistanceFieldText());
629cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 400, paint);
630cb93a386Sopenharmony_ci
631cb93a386Sopenharmony_ci    std::vector<uint8_t> serverStrikeData;
632cb93a386Sopenharmony_ci    server.writeStrikeData(&serverStrikeData);
633cb93a386Sopenharmony_ci
634cb93a386Sopenharmony_ci    // Client.
635cb93a386Sopenharmony_ci    auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
636cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
637cb93a386Sopenharmony_ci                    client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
638cb93a386Sopenharmony_ci
639cb93a386Sopenharmony_ci    auto clientBlob = makeBlob(clientTf);
640cb93a386Sopenharmony_ci
641cb93a386Sopenharmony_ci    SkBitmap expected = RasterBlob(serverBlob, 800, 800, paint, ctxInfo.grContext());
642cb93a386Sopenharmony_ci    SkBitmap actual = RasterBlob(clientBlob, 800, 800, paint, ctxInfo.grContext());
643cb93a386Sopenharmony_ci
644cb93a386Sopenharmony_ci    // Pixel variance can be high because of the atlas placement, and large scaling in the linear
645cb93a386Sopenharmony_ci    // interpolation.
646cb93a386Sopenharmony_ci    compare_blobs(expected, actual, reporter, 36);
647cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
648cb93a386Sopenharmony_ci
649cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
650cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
651cb93a386Sopenharmony_ci}
652cb93a386Sopenharmony_ci#endif
653cb93a386Sopenharmony_ci
654cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextXY, reporter, ctxInfo) {
655cb93a386Sopenharmony_ci    auto direct = ctxInfo.directContext();
656cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
657cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
658cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
659cb93a386Sopenharmony_ci    SkPaint paint;
660cb93a386Sopenharmony_ci    paint.setAntiAlias(true);
661cb93a386Sopenharmony_ci
662cb93a386Sopenharmony_ci    // Server.
663cb93a386Sopenharmony_ci    auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
664cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
665cb93a386Sopenharmony_ci
666cb93a386Sopenharmony_ci    int glyphCount = 10;
667cb93a386Sopenharmony_ci    auto serverBlob = buildTextBlob(serverTf, glyphCount);
668cb93a386Sopenharmony_ci    auto props = FindSurfaceProps(direct);
669cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
670cb93a386Sopenharmony_ci            10, 10, props, nullptr, direct->supportsDistanceFieldText());
671cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0.5, 0, paint);
672cb93a386Sopenharmony_ci
673cb93a386Sopenharmony_ci    std::vector<uint8_t> serverStrikeData;
674cb93a386Sopenharmony_ci    server.writeStrikeData(&serverStrikeData);
675cb93a386Sopenharmony_ci
676cb93a386Sopenharmony_ci    // Client.
677cb93a386Sopenharmony_ci    auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
678cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
679cb93a386Sopenharmony_ci                    client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
680cb93a386Sopenharmony_ci    auto clientBlob = buildTextBlob(clientTf, glyphCount);
681cb93a386Sopenharmony_ci
682cb93a386Sopenharmony_ci    SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct, nullptr, 0.5);
683cb93a386Sopenharmony_ci    SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct, nullptr, 0.5);
684cb93a386Sopenharmony_ci    compare_blobs(expected, actual, reporter);
685cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
686cb93a386Sopenharmony_ci
687cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
688cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
689cb93a386Sopenharmony_ci}
690cb93a386Sopenharmony_ci
691cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsDFT, reporter, ctxInfo) {
692cb93a386Sopenharmony_ci    auto direct = ctxInfo.directContext();
693cb93a386Sopenharmony_ci    if (!direct->priv().caps()->shaderCaps()->supportsDistanceFieldText()) {
694cb93a386Sopenharmony_ci        return;
695cb93a386Sopenharmony_ci    }
696cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
697cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
698cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
699cb93a386Sopenharmony_ci    SkPaint paint;
700cb93a386Sopenharmony_ci    SkFont font;
701cb93a386Sopenharmony_ci
702cb93a386Sopenharmony_ci    // A scale transform forces fallback to dft.
703cb93a386Sopenharmony_ci    SkMatrix matrix = SkMatrix::Scale(16, 16);
704cb93a386Sopenharmony_ci    GrSDFTControl control = direct->priv().asRecordingContext()->priv().getSDFTControl(true);
705cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, control.drawingType(font, paint, matrix) == GrSDFTControl::kSDFT);
706cb93a386Sopenharmony_ci
707cb93a386Sopenharmony_ci    // Server.
708cb93a386Sopenharmony_ci    auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
709cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
710cb93a386Sopenharmony_ci
711cb93a386Sopenharmony_ci    int glyphCount = 10;
712cb93a386Sopenharmony_ci    auto serverBlob = buildTextBlob(serverTf, glyphCount);
713cb93a386Sopenharmony_ci    const SkSurfaceProps props;
714cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
715cb93a386Sopenharmony_ci            10, 10, props, nullptr, direct->supportsDistanceFieldText());
716cb93a386Sopenharmony_ci    cache_diff_canvas->concat(matrix);
717cb93a386Sopenharmony_ci    cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
718cb93a386Sopenharmony_ci
719cb93a386Sopenharmony_ci    std::vector<uint8_t> serverStrikeData;
720cb93a386Sopenharmony_ci    server.writeStrikeData(&serverStrikeData);
721cb93a386Sopenharmony_ci
722cb93a386Sopenharmony_ci    // Client.
723cb93a386Sopenharmony_ci    auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
724cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
725cb93a386Sopenharmony_ci                    client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
726cb93a386Sopenharmony_ci    auto clientBlob = buildTextBlob(clientTf, glyphCount);
727cb93a386Sopenharmony_ci
728cb93a386Sopenharmony_ci    SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct, &matrix);
729cb93a386Sopenharmony_ci    SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct, &matrix);
730cb93a386Sopenharmony_ci    compare_blobs(expected, actual, reporter);
731cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
732cb93a386Sopenharmony_ci
733cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
734cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
735cb93a386Sopenharmony_ci}
736cb93a386Sopenharmony_ci
737cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_CacheMissReporting, reporter, ctxInfo) {
738cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
739cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
740cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
741cb93a386Sopenharmony_ci
742cb93a386Sopenharmony_ci    auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
743cb93a386Sopenharmony_ci    auto tfData = server.serializeTypeface(serverTf.get());
744cb93a386Sopenharmony_ci    auto clientTf = client.deserializeTypeface(tfData->data(), tfData->size());
745cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, clientTf);
746cb93a386Sopenharmony_ci    int glyphCount = 10;
747cb93a386Sopenharmony_ci    auto clientBlob = buildTextBlob(clientTf, glyphCount);
748cb93a386Sopenharmony_ci
749cb93a386Sopenharmony_ci    // Raster the client-side blob without the glyph data, we should get cache miss notifications.
750cb93a386Sopenharmony_ci    SkPaint paint;
751cb93a386Sopenharmony_ci    SkMatrix matrix = SkMatrix::I();
752cb93a386Sopenharmony_ci    RasterBlob(clientBlob, 10, 10, paint, ctxInfo.directContext(), &matrix);
753cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
754cb93a386Sopenharmony_ci                    discardableManager->cacheMissCount(SkStrikeClient::kFontMetrics) == 1);
755cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
756cb93a386Sopenharmony_ci                    discardableManager->cacheMissCount(SkStrikeClient::kGlyphMetrics) == 10);
757cb93a386Sopenharmony_ci
758cb93a386Sopenharmony_ci    // There shouldn't be any image or path requests, since we mark the glyph as empty on a cache
759cb93a386Sopenharmony_ci    // miss.
760cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->cacheMissCount(SkStrikeClient::kGlyphImage) == 0);
761cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, discardableManager->cacheMissCount(SkStrikeClient::kGlyphPath) == 0);
762cb93a386Sopenharmony_ci
763cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
764cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
765cb93a386Sopenharmony_ci}
766cb93a386Sopenharmony_ci
767cb93a386Sopenharmony_cisk_sp<SkTextBlob> MakeEmojiBlob(sk_sp<SkTypeface> serverTf, SkScalar textSize,
768cb93a386Sopenharmony_ci                                sk_sp<SkTypeface> clientTf = nullptr) {
769cb93a386Sopenharmony_ci    SkFont font;
770cb93a386Sopenharmony_ci    font.setTypeface(serverTf);
771cb93a386Sopenharmony_ci    font.setSize(textSize);
772cb93a386Sopenharmony_ci
773cb93a386Sopenharmony_ci    const char* text = ToolUtils::emoji_sample_text();
774cb93a386Sopenharmony_ci    SkFont serverFont = font;
775cb93a386Sopenharmony_ci    auto blob = SkTextBlob::MakeFromText(text, strlen(text), font);
776cb93a386Sopenharmony_ci    if (clientTf == nullptr) return blob;
777cb93a386Sopenharmony_ci
778cb93a386Sopenharmony_ci    SkSerialProcs s_procs;
779cb93a386Sopenharmony_ci    s_procs.fTypefaceProc = [](SkTypeface*, void* ctx) -> sk_sp<SkData> {
780cb93a386Sopenharmony_ci        return SkData::MakeUninitialized(1u);
781cb93a386Sopenharmony_ci    };
782cb93a386Sopenharmony_ci    auto serialized = blob->serialize(s_procs);
783cb93a386Sopenharmony_ci
784cb93a386Sopenharmony_ci    SkDeserialProcs d_procs;
785cb93a386Sopenharmony_ci    d_procs.fTypefaceCtx = &clientTf;
786cb93a386Sopenharmony_ci    d_procs.fTypefaceProc = [](const void* data, size_t length, void* ctx) -> sk_sp<SkTypeface> {
787cb93a386Sopenharmony_ci        return *(static_cast<sk_sp<SkTypeface>*>(ctx));
788cb93a386Sopenharmony_ci    };
789cb93a386Sopenharmony_ci    return SkTextBlob::Deserialize(serialized->data(), serialized->size(), d_procs);
790cb93a386Sopenharmony_ci}
791cb93a386Sopenharmony_ci
792cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_TypefaceWithNoPaths, reporter, ctxInfo) {
793cb93a386Sopenharmony_ci    auto direct = ctxInfo.directContext();
794cb93a386Sopenharmony_ci    sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
795cb93a386Sopenharmony_ci    SkStrikeServer server(discardableManager.get());
796cb93a386Sopenharmony_ci    SkStrikeClient client(discardableManager, false);
797cb93a386Sopenharmony_ci
798cb93a386Sopenharmony_ci    auto serverTf = ToolUtils::emoji_typeface();
799cb93a386Sopenharmony_ci    auto serverTfData = server.serializeTypeface(serverTf.get());
800cb93a386Sopenharmony_ci    auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
801cb93a386Sopenharmony_ci
802cb93a386Sopenharmony_ci    auto props = FindSurfaceProps(direct);
803cb93a386Sopenharmony_ci    std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
804cb93a386Sopenharmony_ci            500, 500, props, nullptr, direct->supportsDistanceFieldText());
805cb93a386Sopenharmony_ci    for (SkScalar textSize : { 70, 180, 270, 340}) {
806cb93a386Sopenharmony_ci        auto serverBlob = MakeEmojiBlob(serverTf, textSize);
807cb93a386Sopenharmony_ci
808cb93a386Sopenharmony_ci        SkPaint paint;
809cb93a386Sopenharmony_ci        cache_diff_canvas->drawTextBlob(serverBlob.get(), 100, 100, paint);
810cb93a386Sopenharmony_ci
811cb93a386Sopenharmony_ci        std::vector<uint8_t> serverStrikeData;
812cb93a386Sopenharmony_ci        server.writeStrikeData(&serverStrikeData);
813cb93a386Sopenharmony_ci        if (!serverStrikeData.empty()) {
814cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter,
815cb93a386Sopenharmony_ci                            client.readStrikeData(serverStrikeData.data(),
816cb93a386Sopenharmony_ci                                                  serverStrikeData.size()));
817cb93a386Sopenharmony_ci        }
818cb93a386Sopenharmony_ci        auto clientBlob = MakeEmojiBlob(serverTf, textSize, clientTf);
819cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, clientBlob);
820cb93a386Sopenharmony_ci
821cb93a386Sopenharmony_ci        RasterBlob(clientBlob, 500, 500, paint, direct);
822cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
823cb93a386Sopenharmony_ci        discardableManager->resetCacheMissCounts();
824cb93a386Sopenharmony_ci    }
825cb93a386Sopenharmony_ci
826cb93a386Sopenharmony_ci    // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
827cb93a386Sopenharmony_ci    discardableManager->unlockAndDeleteAll();
828cb93a386Sopenharmony_ci}
829