blob: a13b91096dbe2804b68bde093d58df0384d99866 [file] [log] [blame]
Khushal38a08432018-05-02 10:29:37 -07001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkGraphics.h"
9#include "include/core/SkSurface.h"
10#include "include/core/SkTextBlob.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040011#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/private/SkMutex.h"
13#include "src/core/SkDraw.h"
14#include "src/core/SkRemoteGlyphCache.h"
Herb Derby81e84a62020-02-14 11:47:35 -050015#include "src/core/SkScalerCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/core/SkStrikeCache.h"
Herb Derbyd249e8c2019-06-03 11:36:01 -040017#include "src/core/SkStrikeSpec.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/core/SkSurfacePriv.h"
19#include "src/core/SkTypeface_remote.h"
Adlai Hollera0693042020-10-14 11:23:11 -040020#include "src/gpu/GrDirectContextPriv.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040021#include "src/gpu/GrRecordingContextPriv.h"
22#include "src/gpu/text/GrSDFTOptions.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "tests/Test.h"
24#include "tools/Resources.h"
25#include "tools/ToolUtils.h"
26#include "tools/fonts/TestEmptyTypeface.h"
Khushal38a08432018-05-02 10:29:37 -070027
28class DiscardableManager : public SkStrikeServer::DiscardableHandleManager,
29 public SkStrikeClient::DiscardableHandleManager {
30public:
Khushald4160832018-05-23 18:16:00 -070031 DiscardableManager() { sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount)); }
Khushal38a08432018-05-02 10:29:37 -070032 ~DiscardableManager() override = default;
33
34 // Server implementation.
35 SkDiscardableHandleId createHandle() override {
Herb Derby9b869552019-05-10 12:16:17 -040036 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070037
Khushal38a08432018-05-02 10:29:37 -070038 // Handles starts as locked.
39 fLockedHandles.add(++fNextHandleId);
40 return fNextHandleId;
41 }
42 bool lockHandle(SkDiscardableHandleId id) override {
Herb Derby9b869552019-05-10 12:16:17 -040043 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070044
Khushal38a08432018-05-02 10:29:37 -070045 if (id <= fLastDeletedHandleId) return false;
46 fLockedHandles.add(id);
47 return true;
48 }
49
50 // Client implementation.
Khushal3de67bd2019-03-15 14:43:15 -070051 bool deleteHandle(SkDiscardableHandleId id) override {
Herb Derby9b869552019-05-10 12:16:17 -040052 SkAutoMutexExclusive l(fMutex);
Khushal38a08432018-05-02 10:29:37 -070053
Khushal3de67bd2019-03-15 14:43:15 -070054 return id <= fLastDeletedHandleId;
55 }
56
57 void notifyCacheMiss(SkStrikeClient::CacheMissType type) override {
Herb Derby9b869552019-05-10 12:16:17 -040058 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070059
60 fCacheMissCount[type]++;
61 }
62 bool isHandleDeleted(SkDiscardableHandleId id) override {
Herb Derby9b869552019-05-10 12:16:17 -040063 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070064
65 return id <= fLastDeletedHandleId;
66 }
67
68 void unlockAll() {
Herb Derby9b869552019-05-10 12:16:17 -040069 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070070
71 fLockedHandles.reset();
72 }
Khushal38a08432018-05-02 10:29:37 -070073 void unlockAndDeleteAll() {
Herb Derby9b869552019-05-10 12:16:17 -040074 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070075
76 fLockedHandles.reset();
Khushal38a08432018-05-02 10:29:37 -070077 fLastDeletedHandleId = fNextHandleId;
78 }
Khushal3de67bd2019-03-15 14:43:15 -070079 const SkTHashSet<SkDiscardableHandleId>& lockedHandles() const {
Herb Derby9b869552019-05-10 12:16:17 -040080 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070081
82 return fLockedHandles;
83 }
84 SkDiscardableHandleId handleCount() {
Herb Derby9b869552019-05-10 12:16:17 -040085 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070086
87 return fNextHandleId;
88 }
89 int cacheMissCount(uint32_t type) {
Herb Derby9b869552019-05-10 12:16:17 -040090 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070091
92 return fCacheMissCount[type];
93 }
Khushalfa8ff092018-06-06 17:46:38 -070094 bool hasCacheMiss() const {
Herb Derby9b869552019-05-10 12:16:17 -040095 SkAutoMutexExclusive l(fMutex);
Khushal3de67bd2019-03-15 14:43:15 -070096
Khushalfa8ff092018-06-06 17:46:38 -070097 for (uint32_t i = 0; i <= SkStrikeClient::CacheMissType::kLast; ++i) {
Hal Canarye107faa2019-10-23 12:52:33 -040098 if (fCacheMissCount[i] > 0) { return true; }
Khushalfa8ff092018-06-06 17:46:38 -070099 }
100 return false;
101 }
Herb Derbye384a1e2019-05-21 11:27:40 -0400102 void resetCacheMissCounts() {
103 SkAutoMutexExclusive l(fMutex);
104 sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount));
105 }
Khushal38a08432018-05-02 10:29:37 -0700106
107private:
Khushal3de67bd2019-03-15 14:43:15 -0700108 // The tests below run in parallel on multiple threads and use the same
109 // process global SkStrikeCache. So the implementation needs to be
110 // thread-safe.
111 mutable SkMutex fMutex;
112
Khushal38a08432018-05-02 10:29:37 -0700113 SkDiscardableHandleId fNextHandleId = 0u;
114 SkDiscardableHandleId fLastDeletedHandleId = 0u;
115 SkTHashSet<SkDiscardableHandleId> fLockedHandles;
Khushald4160832018-05-23 18:16:00 -0700116 int fCacheMissCount[SkStrikeClient::CacheMissType::kLast + 1u];
Khushal38a08432018-05-02 10:29:37 -0700117};
118
119sk_sp<SkTextBlob> buildTextBlob(sk_sp<SkTypeface> tf, int glyphCount) {
Mike Reed2ed78202018-11-21 15:10:08 -0500120 SkFont font;
Khushal38a08432018-05-02 10:29:37 -0700121 font.setTypeface(tf);
Ben Wagner5785e4a2019-05-07 16:50:29 -0400122 font.setHinting(SkFontHinting::kNormal);
Mike Reed2ed78202018-11-21 15:10:08 -0500123 font.setSize(1u);
124 font.setEdging(SkFont::Edging::kAntiAlias);
125 font.setSubpixel(true);
Khushal38a08432018-05-02 10:29:37 -0700126
127 SkTextBlobBuilder builder;
128 SkRect bounds = SkRect::MakeWH(10, 10);
129 const auto& runBuffer = builder.allocRunPosH(font, glyphCount, 0, &bounds);
130 SkASSERT(runBuffer.utf8text == nullptr);
131 SkASSERT(runBuffer.clusters == nullptr);
132
133 for (int i = 0; i < glyphCount; i++) {
134 runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
135 runBuffer.pos[i] = SkIntToScalar(i);
136 }
137 return builder.make();
138}
139
Chris Daltonf9a90a22018-08-28 14:17:55 -0600140static void compare_blobs(const SkBitmap& expected, const SkBitmap& actual,
141 skiatest::Reporter* reporter, int tolerance = 0) {
142 SkASSERT(expected.width() == actual.width());
143 SkASSERT(expected.height() == actual.height());
144 for (int i = 0; i < expected.width(); ++i) {
145 for (int j = 0; j < expected.height(); ++j) {
146 SkColor expectedColor = expected.getColor(i, j);
147 SkColor actualColor = actual.getColor(i, j);
148 if (0 == tolerance) {
149 REPORTER_ASSERT(reporter, expectedColor == actualColor);
150 } else {
151 for (int k = 0; k < 4; ++k) {
152 int expectedChannel = (expectedColor >> (k*8)) & 0xff;
153 int actualChannel = (actualColor >> (k*8)) & 0xff;
154 REPORTER_ASSERT(reporter, abs(expectedChannel - actualChannel) <= tolerance);
155 }
156 }
157 }
Khushal51371a42018-05-17 10:41:40 -0700158 }
Chris Daltonf9a90a22018-08-28 14:17:55 -0600159}
Khushal51371a42018-05-17 10:41:40 -0700160
Robert Phillipse94b4e12020-07-23 13:54:35 -0400161sk_sp<SkSurface> MakeSurface(int width, int height, GrRecordingContext* rContext) {
Herb Derbyc3415002018-11-08 16:40:26 -0500162 const SkImageInfo info =
163 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
Robert Phillipse94b4e12020-07-23 13:54:35 -0400164 return SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info);
Herb Derbyc3415002018-11-08 16:40:26 -0500165}
166
John Stilesec9b4aa2020-08-07 13:05:14 -0400167SkSurfaceProps FindSurfaceProps(GrRecordingContext* rContext) {
Robert Phillipse94b4e12020-07-23 13:54:35 -0400168 auto surface = MakeSurface(1, 1, rContext);
Herb Derbyc3415002018-11-08 16:40:26 -0500169 return surface->props();
170}
171
Ravi Mistrycd21d672018-05-29 21:45:46 +0000172SkBitmap RasterBlob(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint& paint,
Robert Phillipse94b4e12020-07-23 13:54:35 -0400173 GrRecordingContext* rContext, const SkMatrix* matrix = nullptr,
Herb Derby1a9971e2018-07-19 13:41:15 -0400174 SkScalar x = 0) {
Robert Phillipse94b4e12020-07-23 13:54:35 -0400175 auto surface = MakeSurface(width, height, rContext);
Ravi Mistrycd21d672018-05-29 21:45:46 +0000176 if (matrix) surface->getCanvas()->concat(*matrix);
Herb Derbyb1dbbc82019-03-22 17:05:14 -0400177 surface->getCanvas()->drawTextBlob(blob.get(), x, height/2, paint);
Khushal38a08432018-05-02 10:29:37 -0700178 SkBitmap bitmap;
Ravi Mistrycd21d672018-05-29 21:45:46 +0000179 bitmap.allocN32Pixels(width, height);
Khushal38a08432018-05-02 10:29:37 -0700180 surface->readPixels(bitmap, 0, 0);
181 return bitmap;
182}
183
184DEF_TEST(SkRemoteGlyphCache_TypefaceSerialization, reporter) {
185 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
186 SkStrikeServer server(discardableManager.get());
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400187 SkStrikeClient client(discardableManager, false);
Khushal38a08432018-05-02 10:29:37 -0700188
189 auto server_tf = SkTypeface::MakeDefault();
190 auto tf_data = server.serializeTypeface(server_tf.get());
191
192 auto client_tf = client.deserializeTypeface(tf_data->data(), tf_data->size());
193 REPORTER_ASSERT(reporter, client_tf);
Khushald4160832018-05-23 18:16:00 -0700194 REPORTER_ASSERT(reporter, static_cast<SkTypefaceProxy*>(client_tf.get())->remoteTypefaceID() ==
Khushal38a08432018-05-02 10:29:37 -0700195 server_tf->uniqueID());
Khushal3e7548c2018-05-23 15:45:01 -0700196
197 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
198 discardableManager->unlockAndDeleteAll();
Khushal38a08432018-05-02 10:29:37 -0700199}
200
Khushal3e7548c2018-05-23 15:45:01 -0700201DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_StrikeSerialization, reporter, ctxInfo) {
Robert Phillipse94b4e12020-07-23 13:54:35 -0400202 auto dContext = ctxInfo.directContext();
Khushal38a08432018-05-02 10:29:37 -0700203 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
204 SkStrikeServer server(discardableManager.get());
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400205 SkStrikeClient client(discardableManager, false);
Khushal51371a42018-05-17 10:41:40 -0700206 const SkPaint paint;
Khushal38a08432018-05-02 10:29:37 -0700207
208 // Server.
209 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
210 auto serverTfData = server.serializeTypeface(serverTf.get());
211
212 int glyphCount = 10;
213 auto serverBlob = buildTextBlob(serverTf, glyphCount);
Robert Phillipse94b4e12020-07-23 13:54:35 -0400214 auto props = FindSurfaceProps(dContext);
Mike Reedf922c782019-02-19 15:46:38 -0500215 SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server,
Robert Phillipse94b4e12020-07-23 13:54:35 -0400216 dContext->supportsDistanceFieldText());
Khushal38a08432018-05-02 10:29:37 -0700217 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
218
219 std::vector<uint8_t> serverStrikeData;
220 server.writeStrikeData(&serverStrikeData);
221
222 // Client.
223 auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
224 REPORTER_ASSERT(reporter,
225 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
226 auto clientBlob = buildTextBlob(clientTf, glyphCount);
227
Robert Phillipse94b4e12020-07-23 13:54:35 -0400228 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, dContext);
229 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, dContext);
Chris Daltonf9a90a22018-08-28 14:17:55 -0600230 compare_blobs(expected, actual, reporter);
Khushalfa8ff092018-06-06 17:46:38 -0700231 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
Khushal3e7548c2018-05-23 15:45:01 -0700232
233 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
234 discardableManager->unlockAndDeleteAll();
Khushal38a08432018-05-02 10:29:37 -0700235}
236
Herb Derbyaca2b9e2018-08-28 15:33:19 -0400237DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_ReleaseTypeFace, reporter, ctxInfo) {
238 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
239 SkStrikeServer server(discardableManager.get());
240 SkStrikeClient client(discardableManager, false);
241
242 // Server.
Mike Klein0cffcbf92019-03-20 11:08:46 -0500243 auto serverTf = TestEmptyTypeface::Make();
Herb Derbyaca2b9e2018-08-28 15:33:19 -0400244 auto serverTfData = server.serializeTypeface(serverTf.get());
245 REPORTER_ASSERT(reporter, serverTf->unique());
246
247 {
248 const SkPaint paint;
249 int glyphCount = 10;
250 auto serverBlob = buildTextBlob(serverTf, glyphCount);
Ben Wagnerae4bb982020-09-24 14:49:00 -0400251 const SkSurfaceProps props;
herb7022b772019-08-15 22:45:43 -0400252 SkTextBlobCacheDiffCanvas cache_diff_canvas(
Robert Phillips6d344c32020-07-06 10:56:46 -0400253 10, 10, props, &server, ctxInfo.directContext()->supportsDistanceFieldText());
Herb Derbyaca2b9e2018-08-28 15:33:19 -0400254 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
255 REPORTER_ASSERT(reporter, !serverTf->unique());
256
257 std::vector<uint8_t> serverStrikeData;
258 server.writeStrikeData(&serverStrikeData);
259 }
260 REPORTER_ASSERT(reporter, serverTf->unique());
261
262 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
263 discardableManager->unlockAndDeleteAll();
264}
265
Khushal38a08432018-05-02 10:29:37 -0700266DEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter) {
267 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
268 SkStrikeServer server(discardableManager.get());
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400269 SkStrikeClient client(discardableManager, false);
Khushal38a08432018-05-02 10:29:37 -0700270
271 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
272 server.serializeTypeface(serverTf.get());
273 int glyphCount = 10;
274 auto serverBlob = buildTextBlob(serverTf, glyphCount);
275
Ben Wagnerae4bb982020-09-24 14:49:00 -0400276 const SkSurfaceProps props;
Mike Reedf922c782019-02-19 15:46:38 -0500277 SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
Khushal38a08432018-05-02 10:29:37 -0700278 SkPaint paint;
279 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
280
281 // The strike from the blob should be locked after it has been drawn on the canvas.
282 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
283 REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u);
284
285 // Write the strike data and unlock everything. Re-analyzing the blob should lock the handle
286 // again.
287 std::vector<uint8_t> fontData;
288 server.writeStrikeData(&fontData);
289 discardableManager->unlockAll();
290 REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 0u);
291
292 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
293 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
294 REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u);
Khushal3e7548c2018-05-23 15:45:01 -0700295
296 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
297 discardableManager->unlockAndDeleteAll();
Khushal38a08432018-05-02 10:29:37 -0700298}
299
300DEF_TEST(SkRemoteGlyphCache_StrikeDeletionServer, reporter) {
301 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
302 SkStrikeServer server(discardableManager.get());
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400303 SkStrikeClient client(discardableManager, false);
Khushal38a08432018-05-02 10:29:37 -0700304
305 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
306 server.serializeTypeface(serverTf.get());
307 int glyphCount = 10;
308 auto serverBlob = buildTextBlob(serverTf, glyphCount);
309
Ben Wagnerae4bb982020-09-24 14:49:00 -0400310 const SkSurfaceProps props;
Mike Reedf922c782019-02-19 15:46:38 -0500311 SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
Khushal38a08432018-05-02 10:29:37 -0700312 SkPaint paint;
313 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
314 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
315
316 // Write the strike data and delete all the handles. Re-analyzing the blob should create new
317 // handles.
318 std::vector<uint8_t> fontData;
319 server.writeStrikeData(&fontData);
Khushal498a9b22019-09-04 16:19:22 -0700320
321 // Another analysis pass, to ensure that deleting handles after a complete cache hit still
322 // works. This is a regression test for crbug.com/999682.
323 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
324 server.writeStrikeData(&fontData);
325 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
326
Khushal38a08432018-05-02 10:29:37 -0700327 discardableManager->unlockAndDeleteAll();
328 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
Khushal38a08432018-05-02 10:29:37 -0700329 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 2u);
Khushal3e7548c2018-05-23 15:45:01 -0700330
331 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
332 discardableManager->unlockAndDeleteAll();
Khushal38a08432018-05-02 10:29:37 -0700333}
334
335DEF_TEST(SkRemoteGlyphCache_StrikePinningClient, reporter) {
336 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
337 SkStrikeServer server(discardableManager.get());
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400338 SkStrikeClient client(discardableManager, false);
Khushal38a08432018-05-02 10:29:37 -0700339
340 // Server.
341 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
342 auto serverTfData = server.serializeTypeface(serverTf.get());
343
344 int glyphCount = 10;
345 auto serverBlob = buildTextBlob(serverTf, glyphCount);
346
Ben Wagnerae4bb982020-09-24 14:49:00 -0400347 const SkSurfaceProps props;
Mike Reedf922c782019-02-19 15:46:38 -0500348 SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
Khushal38a08432018-05-02 10:29:37 -0700349 SkPaint paint;
350 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
351
352 std::vector<uint8_t> serverStrikeData;
353 server.writeStrikeData(&serverStrikeData);
354
355 // Client.
356 REPORTER_ASSERT(reporter,
357 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
358 auto* clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()).get();
359
360 // The cache remains alive until it is pinned in the discardable manager.
361 SkGraphics::PurgeFontCache();
362 REPORTER_ASSERT(reporter, !clientTf->unique());
363
364 // Once the strike is unpinned and purged, SkStrikeClient should be the only owner of the
365 // clientTf.
366 discardableManager->unlockAndDeleteAll();
367 SkGraphics::PurgeFontCache();
368 REPORTER_ASSERT(reporter, clientTf->unique());
Khushal3e7548c2018-05-23 15:45:01 -0700369
370 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
371 discardableManager->unlockAndDeleteAll();
Khushal38a08432018-05-02 10:29:37 -0700372}
Khushalb2e71272018-05-15 12:59:48 -0700373
374DEF_TEST(SkRemoteGlyphCache_ClientMemoryAccounting, reporter) {
375 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
376 SkStrikeServer server(discardableManager.get());
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400377 SkStrikeClient client(discardableManager, false);
Khushalb2e71272018-05-15 12:59:48 -0700378
379 // Server.
380 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
381 auto serverTfData = server.serializeTypeface(serverTf.get());
382
383 int glyphCount = 10;
384 auto serverBlob = buildTextBlob(serverTf, glyphCount);
385
Ben Wagnerae4bb982020-09-24 14:49:00 -0400386 const SkSurfaceProps props;
Mike Reedf922c782019-02-19 15:46:38 -0500387 SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
Khushalb2e71272018-05-15 12:59:48 -0700388 SkPaint paint;
389 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
390
391 std::vector<uint8_t> serverStrikeData;
392 server.writeStrikeData(&serverStrikeData);
393
394 // Client.
395 REPORTER_ASSERT(reporter,
396 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
Khushal3e7548c2018-05-23 15:45:01 -0700397
398 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
399 discardableManager->unlockAndDeleteAll();
Khushalb2e71272018-05-15 12:59:48 -0700400}
Khushal51371a42018-05-17 10:41:40 -0700401
Khushalcf33b1b2018-08-29 16:16:25 -0700402DEF_TEST(SkRemoteGlyphCache_PurgesServerEntries, reporter) {
403 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
404 SkStrikeServer server(discardableManager.get());
405 server.setMaxEntriesInDescriptorMapForTesting(1u);
406 SkStrikeClient client(discardableManager, false);
407
408 {
409 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
410 int glyphCount = 10;
411 auto serverBlob = buildTextBlob(serverTf, glyphCount);
412
Ben Wagnerae4bb982020-09-24 14:49:00 -0400413 const SkSurfaceProps props;
Mike Reedf922c782019-02-19 15:46:38 -0500414 SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
Khushalcf33b1b2018-08-29 16:16:25 -0700415 SkPaint paint;
Herb Derbya4c78832019-08-27 16:03:45 -0400416 REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 0u);
Khushalcf33b1b2018-08-29 16:16:25 -0700417 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
Herb Derbya4c78832019-08-27 16:03:45 -0400418 REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u);
Khushalcf33b1b2018-08-29 16:16:25 -0700419 }
420
421 // Serialize to release the lock from the strike server and delete all current
422 // handles.
423 std::vector<uint8_t> fontData;
424 server.writeStrikeData(&fontData);
425 discardableManager->unlockAndDeleteAll();
426
427 // Use a different typeface. Creating a new strike should evict the previous
428 // one.
429 {
430 auto serverTf = SkTypeface::MakeFromName("Georgia", SkFontStyle());
431 int glyphCount = 10;
432 auto serverBlob = buildTextBlob(serverTf, glyphCount);
433
Ben Wagnerae4bb982020-09-24 14:49:00 -0400434 const SkSurfaceProps props;
Mike Reedf922c782019-02-19 15:46:38 -0500435 SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
Khushalcf33b1b2018-08-29 16:16:25 -0700436 SkPaint paint;
Herb Derbya4c78832019-08-27 16:03:45 -0400437 REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u);
Khushalcf33b1b2018-08-29 16:16:25 -0700438 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
Herb Derbya4c78832019-08-27 16:03:45 -0400439 REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u);
Khushalcf33b1b2018-08-29 16:16:25 -0700440 }
441
442 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
443 discardableManager->unlockAndDeleteAll();
444}
445
Khushal3e7548c2018-05-23 15:45:01 -0700446DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsPath, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400447 auto direct = ctxInfo.directContext();
Khushal51371a42018-05-17 10:41:40 -0700448 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
449 SkStrikeServer server(discardableManager.get());
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400450 SkStrikeClient client(discardableManager, false);
Khushal51371a42018-05-17 10:41:40 -0700451 SkPaint paint;
452 paint.setStyle(SkPaint::kStroke_Style);
453 paint.setStrokeWidth(0);
Herb Derbyd249e8c2019-06-03 11:36:01 -0400454 REPORTER_ASSERT(reporter,
Herb Derby36a54c12019-06-06 10:50:56 -0400455 SkStrikeSpec::ShouldDrawAsPath(paint, SkFont(), SkMatrix::I()));
Khushal51371a42018-05-17 10:41:40 -0700456
457 // Server.
458 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
459 auto serverTfData = server.serializeTypeface(serverTf.get());
460
461 int glyphCount = 10;
462 auto serverBlob = buildTextBlob(serverTf, glyphCount);
Robert Phillips6d344c32020-07-06 10:56:46 -0400463 auto props = FindSurfaceProps(direct);
herb7022b772019-08-15 22:45:43 -0400464 SkTextBlobCacheDiffCanvas cache_diff_canvas(
Robert Phillips6d344c32020-07-06 10:56:46 -0400465 10, 10, props, &server, direct->supportsDistanceFieldText());
Khushal51371a42018-05-17 10:41:40 -0700466 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
467
468 std::vector<uint8_t> serverStrikeData;
469 server.writeStrikeData(&serverStrikeData);
470
471 // Client.
472 auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
473 REPORTER_ASSERT(reporter,
474 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
475 auto clientBlob = buildTextBlob(clientTf, glyphCount);
476
Robert Phillips6d344c32020-07-06 10:56:46 -0400477 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct);
478 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct);
Chris Daltonf9a90a22018-08-28 14:17:55 -0600479 compare_blobs(expected, actual, reporter, 1);
Khushalfa8ff092018-06-06 17:46:38 -0700480 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
Khushal3e7548c2018-05-23 15:45:01 -0700481
482 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
483 discardableManager->unlockAndDeleteAll();
Khushal51371a42018-05-17 10:41:40 -0700484}
Khushal3e7548c2018-05-23 15:45:01 -0700485
Herb Derby8e318fd2018-08-29 11:04:18 -0400486sk_sp<SkTextBlob> make_blob_causing_fallback(
487 sk_sp<SkTypeface> targetTf, const SkTypeface* glyphTf, skiatest::Reporter* reporter) {
Mike Reed70914f52018-11-23 13:08:33 -0500488 SkFont font;
489 font.setSubpixel(true);
490 font.setSize(96);
Ben Wagner5785e4a2019-05-07 16:50:29 -0400491 font.setHinting(SkFontHinting::kNormal);
Mike Reed70914f52018-11-23 13:08:33 -0500492 font.setTypeface(targetTf);
Herb Derby8e318fd2018-08-29 11:04:18 -0400493
Herb Derbyd249e8c2019-06-03 11:36:01 -0400494 REPORTER_ASSERT(reporter,
Herb Derby36a54c12019-06-06 10:50:56 -0400495 !SkStrikeSpec::ShouldDrawAsPath(SkPaint(), font, SkMatrix::I()));
Herb Derby8e318fd2018-08-29 11:04:18 -0400496
497 char s[] = "Skia";
498 int runSize = strlen(s);
499
500 SkTextBlobBuilder builder;
501 SkRect bounds = SkRect::MakeIWH(100, 100);
Mike Reed70914f52018-11-23 13:08:33 -0500502 const auto& runBuffer = builder.allocRunPosH(font, runSize, 10, &bounds);
Herb Derby8e318fd2018-08-29 11:04:18 -0400503 SkASSERT(runBuffer.utf8text == nullptr);
504 SkASSERT(runBuffer.clusters == nullptr);
505
Mike Reed64670cb2019-04-16 11:37:38 -0700506 SkFont(sk_ref_sp(glyphTf)).textToGlyphs(s, strlen(s), SkTextEncoding::kUTF8,
507 runBuffer.glyphs, runSize);
Herb Derby8e318fd2018-08-29 11:04:18 -0400508
509 SkRect glyphBounds;
Mike Reed70914f52018-11-23 13:08:33 -0500510 font.getWidths(runBuffer.glyphs, 1, nullptr, &glyphBounds);
Herb Derby8e318fd2018-08-29 11:04:18 -0400511
Herb Derby5fd955e2019-01-16 11:23:29 -0500512 REPORTER_ASSERT(reporter, glyphBounds.width() > SkStrikeCommon::kSkSideTooBigForAtlas);
Herb Derby8e318fd2018-08-29 11:04:18 -0400513
514 for (int i = 0; i < runSize; i++) {
515 runBuffer.pos[i] = i * 10;
516 }
517
518 return builder.make();
519}
520
521DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsMaskWithPathFallback,
522 reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400523 auto direct = ctxInfo.directContext();
Herb Derby8e318fd2018-08-29 11:04:18 -0400524 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
525 SkStrikeServer server(discardableManager.get());
526 SkStrikeClient client(discardableManager, false);
527
528 SkPaint paint;
529
530 auto serverTf = MakeResourceAsTypeface("fonts/HangingS.ttf");
531 // TODO: when the cq bots can handle this font remove the check.
532 if (serverTf == nullptr) {
533 return;
534 }
535 auto serverTfData = server.serializeTypeface(serverTf.get());
536
537 auto serverBlob = make_blob_causing_fallback(serverTf, serverTf.get(), reporter);
538
Robert Phillips6d344c32020-07-06 10:56:46 -0400539 auto props = FindSurfaceProps(direct);
herb7022b772019-08-15 22:45:43 -0400540 SkTextBlobCacheDiffCanvas cache_diff_canvas(
Robert Phillips6d344c32020-07-06 10:56:46 -0400541 10, 10, props, &server, direct->supportsDistanceFieldText());
Herb Derby8e318fd2018-08-29 11:04:18 -0400542 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
543
544 std::vector<uint8_t> serverStrikeData;
545 server.writeStrikeData(&serverStrikeData);
546
547 // Client.
548 auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
549 REPORTER_ASSERT(reporter,
550 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
551
552 auto clientBlob = make_blob_causing_fallback(clientTf, serverTf.get(), reporter);
553
Robert Phillips6d344c32020-07-06 10:56:46 -0400554 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct);
555 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct);
Herb Derby8e318fd2018-08-29 11:04:18 -0400556 compare_blobs(expected, actual, reporter);
557 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
Herb Derby8e318fd2018-08-29 11:04:18 -0400558
559 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
560 discardableManager->unlockAndDeleteAll();
561}
562
Herb Derbyb1dbbc82019-03-22 17:05:14 -0400563#if 0
564// TODO: turn this one when I figure out how to deal with the pixel variance from linear
565// interpolation from GPU to GPU.
566DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsSDFTWithAllARGBFallback,
567 reporter, ctxInfo) {
568 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
569 SkStrikeServer server(discardableManager.get());
570 SkStrikeClient client(discardableManager, false);
571
572 SkPaint paint;
573
574 auto serverTf = ToolUtils::planet_typeface();
575 // TODO: when the cq bots can handle this font remove the check.
576 if (serverTf == nullptr) {
577 return;
578 }
579 auto serverTfData = server.serializeTypeface(serverTf.get());
580
581 auto makeBlob = [&reporter](sk_sp<SkTypeface> typeface) {
582 SkFont font;
583 font.setSubpixel(true);
584 font.setSize(96);
Ben Wagner5785e4a2019-05-07 16:50:29 -0400585 font.setHinting(SkFontHinting::kNormal);
Herb Derbyb1dbbc82019-03-22 17:05:14 -0400586 font.setTypeface(typeface);
587
588 REPORTER_ASSERT(reporter, !SkDraw::ShouldDrawTextAsPaths(font, SkPaint(), SkMatrix::I()));
589
590 // Mercury to Uranus.
591 SkGlyphID glyphs[] = {1, 2, 3, 4, 5, 6, 7, 8};
592
593 SkTextBlobBuilder builder;
594 SkRect bounds = SkRect::MakeIWH(100, 100);
595 const auto& runBuffer = builder.allocRunPosH(font, SK_ARRAY_COUNT(glyphs), 100, &bounds);
596 SkASSERT(runBuffer.utf8text == nullptr);
597 SkASSERT(runBuffer.clusters == nullptr);
598
599 std::copy(std::begin(glyphs), std::end(glyphs), runBuffer.glyphs);
600
601 for (size_t i = 0; i < SK_ARRAY_COUNT(glyphs); i++) {
602 runBuffer.pos[i] = i * 100;
603 }
604
605 return builder.make();
606 };
607
608 auto serverBlob = makeBlob(serverTf);
609
610 auto props = FindSurfaceProps(ctxInfo.grContext());
herb7022b772019-08-15 22:45:43 -0400611 SkTextBlobCacheDiffCanvas cache_diff_canvas(
612 800, 800, props, &server, ctxInfo.grContext()->supportsDistanceFieldText());
Herb Derbyb1dbbc82019-03-22 17:05:14 -0400613 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 400, paint);
614
615 std::vector<uint8_t> serverStrikeData;
616 server.writeStrikeData(&serverStrikeData);
617
618 // Client.
619 auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
620 REPORTER_ASSERT(reporter,
621 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
622
623 auto clientBlob = makeBlob(clientTf);
624
625 SkBitmap expected = RasterBlob(serverBlob, 800, 800, paint, ctxInfo.grContext());
626 SkBitmap actual = RasterBlob(clientBlob, 800, 800, paint, ctxInfo.grContext());
627
628 // Pixel variance can be high because of the atlas placement, and large scaling in the linear
629 // interpolation.
630 compare_blobs(expected, actual, reporter, 36);
631 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
Herb Derbyb1dbbc82019-03-22 17:05:14 -0400632
633 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
634 discardableManager->unlockAndDeleteAll();
635}
636#endif
637
Herb Derby1a9971e2018-07-19 13:41:15 -0400638DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextXY, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400639 auto direct = ctxInfo.directContext();
Herb Derby1a9971e2018-07-19 13:41:15 -0400640 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
641 SkStrikeServer server(discardableManager.get());
642 SkStrikeClient client(discardableManager, false);
643 SkPaint paint;
644 paint.setAntiAlias(true);
Herb Derby1a9971e2018-07-19 13:41:15 -0400645
646 // Server.
647 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
648 auto serverTfData = server.serializeTypeface(serverTf.get());
649
650 int glyphCount = 10;
651 auto serverBlob = buildTextBlob(serverTf, glyphCount);
Robert Phillips6d344c32020-07-06 10:56:46 -0400652 auto props = FindSurfaceProps(direct);
herb7022b772019-08-15 22:45:43 -0400653 SkTextBlobCacheDiffCanvas cache_diff_canvas(
Robert Phillips6d344c32020-07-06 10:56:46 -0400654 10, 10, props, &server, direct->supportsDistanceFieldText());
Herb Derby1a9971e2018-07-19 13:41:15 -0400655 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0.5, 0, paint);
656
657 std::vector<uint8_t> serverStrikeData;
658 server.writeStrikeData(&serverStrikeData);
659
660 // Client.
661 auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
662 REPORTER_ASSERT(reporter,
663 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
664 auto clientBlob = buildTextBlob(clientTf, glyphCount);
665
Robert Phillips6d344c32020-07-06 10:56:46 -0400666 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct, nullptr, 0.5);
667 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct, nullptr, 0.5);
Chris Daltonf9a90a22018-08-28 14:17:55 -0600668 compare_blobs(expected, actual, reporter);
Herb Derby1a9971e2018-07-19 13:41:15 -0400669 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
Herb Derby1a9971e2018-07-19 13:41:15 -0400670
671 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
672 discardableManager->unlockAndDeleteAll();
673}
674
Khushal3e7548c2018-05-23 15:45:01 -0700675DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsDFT, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400676 auto direct = ctxInfo.directContext();
Khushal3e7548c2018-05-23 15:45:01 -0700677 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
678 SkStrikeServer server(discardableManager.get());
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400679 SkStrikeClient client(discardableManager, false);
Khushal3e7548c2018-05-23 15:45:01 -0700680 SkPaint paint;
Mike Reedf2b074e2018-12-03 16:52:59 -0500681 SkFont font;
Khushal3e7548c2018-05-23 15:45:01 -0700682
Jim Van Verthce3cf802019-10-10 11:06:20 -0400683 // A scale transform forces fallback to dft.
Mike Reed1f607332020-05-21 12:11:27 -0400684 SkMatrix matrix = SkMatrix::Scale(16, 16);
Ravi Mistrycd21d672018-05-29 21:45:46 +0000685 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
Robert Phillips6d344c32020-07-06 10:56:46 -0400686 GrSDFTOptions options = direct->priv().asRecordingContext()->priv().SDFTOptions();
Herb Derby45fe2e82020-06-12 14:30:05 -0400687 REPORTER_ASSERT(reporter,
688 options.canDrawAsDistanceFields(paint, font, matrix, surfaceProps, true));
Khushal3e7548c2018-05-23 15:45:01 -0700689
690 // Server.
691 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
692 auto serverTfData = server.serializeTypeface(serverTf.get());
693
694 int glyphCount = 10;
695 auto serverBlob = buildTextBlob(serverTf, glyphCount);
Ben Wagnerae4bb982020-09-24 14:49:00 -0400696 const SkSurfaceProps props;
herb7022b772019-08-15 22:45:43 -0400697 SkTextBlobCacheDiffCanvas cache_diff_canvas(
Robert Phillips6d344c32020-07-06 10:56:46 -0400698 10, 10, props, &server, direct->supportsDistanceFieldText());
Khushal3e7548c2018-05-23 15:45:01 -0700699 cache_diff_canvas.concat(matrix);
700 cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
701
702 std::vector<uint8_t> serverStrikeData;
703 server.writeStrikeData(&serverStrikeData);
704
705 // Client.
706 auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
707 REPORTER_ASSERT(reporter,
708 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
709 auto clientBlob = buildTextBlob(clientTf, glyphCount);
710
Robert Phillips6d344c32020-07-06 10:56:46 -0400711 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct, &matrix);
712 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct, &matrix);
Chris Daltonf9a90a22018-08-28 14:17:55 -0600713 compare_blobs(expected, actual, reporter);
Khushalfa8ff092018-06-06 17:46:38 -0700714 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
Khushal3e7548c2018-05-23 15:45:01 -0700715
716 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
717 discardableManager->unlockAndDeleteAll();
718}
Khushald4160832018-05-23 18:16:00 -0700719
720DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_CacheMissReporting, reporter, ctxInfo) {
721 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
722 SkStrikeServer server(discardableManager.get());
Herb Derbyfeb9fa92018-06-01 16:47:21 -0400723 SkStrikeClient client(discardableManager, false);
Khushald4160832018-05-23 18:16:00 -0700724
725 auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
726 auto tfData = server.serializeTypeface(serverTf.get());
727 auto clientTf = client.deserializeTypeface(tfData->data(), tfData->size());
728 REPORTER_ASSERT(reporter, clientTf);
729 int glyphCount = 10;
730 auto clientBlob = buildTextBlob(clientTf, glyphCount);
731
732 // Raster the client-side blob without the glyph data, we should get cache miss notifications.
Ravi Mistrycd21d672018-05-29 21:45:46 +0000733 SkPaint paint;
734 SkMatrix matrix = SkMatrix::I();
Robert Phillips6d344c32020-07-06 10:56:46 -0400735 RasterBlob(clientBlob, 10, 10, paint, ctxInfo.directContext(), &matrix);
Khushald4160832018-05-23 18:16:00 -0700736 REPORTER_ASSERT(reporter,
737 discardableManager->cacheMissCount(SkStrikeClient::kFontMetrics) == 1);
738 REPORTER_ASSERT(reporter,
739 discardableManager->cacheMissCount(SkStrikeClient::kGlyphMetrics) == 10);
740
741 // There shouldn't be any image or path requests, since we mark the glyph as empty on a cache
742 // miss.
743 REPORTER_ASSERT(reporter, discardableManager->cacheMissCount(SkStrikeClient::kGlyphImage) == 0);
744 REPORTER_ASSERT(reporter, discardableManager->cacheMissCount(SkStrikeClient::kGlyphPath) == 0);
745
746 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
747 discardableManager->unlockAndDeleteAll();
748}
Herb Derby65b7bfc2018-06-05 13:32:12 -0400749
Herb Derbye384a1e2019-05-21 11:27:40 -0400750sk_sp<SkTextBlob> MakeEmojiBlob(sk_sp<SkTypeface> serverTf, SkScalar textSize,
751 sk_sp<SkTypeface> clientTf = nullptr) {
752 SkFont font;
753 font.setTypeface(serverTf);
754 font.setSize(textSize);
755
756 const char* text = ToolUtils::emoji_sample_text();
757 SkFont serverFont = font;
758 auto blob = SkTextBlob::MakeFromText(text, strlen(text), font);
759 if (clientTf == nullptr) return blob;
760
761 SkSerialProcs s_procs;
762 s_procs.fTypefaceProc = [](SkTypeface*, void* ctx) -> sk_sp<SkData> {
763 return SkData::MakeUninitialized(1u);
764 };
765 auto serialized = blob->serialize(s_procs);
766
767 SkDeserialProcs d_procs;
768 d_procs.fTypefaceCtx = &clientTf;
769 d_procs.fTypefaceProc = [](const void* data, size_t length, void* ctx) -> sk_sp<SkTypeface> {
770 return *(static_cast<sk_sp<SkTypeface>*>(ctx));
771 };
772 return SkTextBlob::Deserialize(serialized->data(), serialized->size(), d_procs);
773}
774
775DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_TypefaceWithNoPaths, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400776 auto direct = ctxInfo.directContext();
Herb Derbye384a1e2019-05-21 11:27:40 -0400777 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
778 SkStrikeServer server(discardableManager.get());
779 SkStrikeClient client(discardableManager, false);
780
781 auto serverTf = ToolUtils::emoji_typeface();
782 auto serverTfData = server.serializeTypeface(serverTf.get());
783 auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
784
Mike Reed69aaee02019-05-30 11:40:51 +0000785 for (SkScalar textSize : { 70, 180, 270, 340}) {
Herb Derbye384a1e2019-05-21 11:27:40 -0400786 auto serverBlob = MakeEmojiBlob(serverTf, textSize);
Robert Phillips6d344c32020-07-06 10:56:46 -0400787 auto props = FindSurfaceProps(direct);
herb7022b772019-08-15 22:45:43 -0400788 SkTextBlobCacheDiffCanvas cache_diff_canvas(
Robert Phillips6d344c32020-07-06 10:56:46 -0400789 500, 500, props, &server, direct->supportsDistanceFieldText());
Herb Derbye384a1e2019-05-21 11:27:40 -0400790 SkPaint paint;
Mike Reed69aaee02019-05-30 11:40:51 +0000791 cache_diff_canvas.drawTextBlob(serverBlob.get(), 100, 100, paint);
Herb Derbye384a1e2019-05-21 11:27:40 -0400792
793 std::vector<uint8_t> serverStrikeData;
794 server.writeStrikeData(&serverStrikeData);
Herb Derbyf5e9b422019-10-22 16:06:22 -0400795 if (!serverStrikeData.empty()) {
796 REPORTER_ASSERT(reporter,
797 client.readStrikeData(serverStrikeData.data(),
798 serverStrikeData.size()));
799 }
Herb Derbye384a1e2019-05-21 11:27:40 -0400800 auto clientBlob = MakeEmojiBlob(serverTf, textSize, clientTf);
801 REPORTER_ASSERT(reporter, clientBlob);
802
Robert Phillips6d344c32020-07-06 10:56:46 -0400803 RasterBlob(clientBlob, 500, 500, paint, direct);
Herb Derbye384a1e2019-05-21 11:27:40 -0400804 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
Herb Derbye384a1e2019-05-21 11:27:40 -0400805 discardableManager->resetCacheMissCounts();
806 }
807
808 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
809 discardableManager->unlockAndDeleteAll();
810}
811